Date: Sun, 11 May 2003 19:03:24 -0700 (PDT) From: Peter Wemm <peter@FreeBSD.org> To: Perforce Change Reviews <perforce@freebsd.org> Subject: PERFORCE change 30986 for review Message-ID: <200305120203.h4C23OtD038902@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=30986 Change 30986 by peter@peter_hammer on 2003/05/11 19:02:49 Implement userland %fs and %gs. It uses a sysarch() to get and set the 64 bit base addresses. Unfortunately, setting the %fs and %gs selectors directly in userland gives you a truncated 32 bit base value which isn't entirely useful. But that is unpriviliged, while the wrmsr() calls *are* priviliged. Hence the sysarch syscall. Presumably these could also be maintained via get/setcontext. Affected files ... .. //depot/projects/hammer/sys/amd64/amd64/cpu_switch.S#2 edit .. //depot/projects/hammer/sys/amd64/amd64/genassym.c#8 edit .. //depot/projects/hammer/sys/amd64/amd64/machdep.c#23 edit .. //depot/projects/hammer/sys/amd64/amd64/sys_machdep.c#6 edit .. //depot/projects/hammer/sys/amd64/include/pcb.h#6 edit .. //depot/projects/hammer/sys/amd64/include/sysarch.h#6 edit Differences ... ==== //depot/projects/hammer/sys/amd64/amd64/cpu_switch.S#2 (text+ko) ==== @@ -92,27 +92,39 @@ jz badsw2 /* no, panic */ #endif - movq TD_PCB(%rdi),%rdx + movq TD_PCB(%rdi),%r8 movq (%rsp),%rax /* Hardware registers */ - movq %rax,PCB_RIP(%rdx) - movq %rbx,PCB_RBX(%rdx) - movq %rsp,PCB_RSP(%rdx) - movq %rbp,PCB_RBP(%rdx) - movq %r12,PCB_R12(%rdx) - movq %r13,PCB_R13(%rdx) - movq %r14,PCB_R14(%rdx) - movq %r15,PCB_R15(%rdx) + movq %rax,PCB_RIP(%r8) + movq %rbx,PCB_RBX(%r8) + movq %rsp,PCB_RSP(%r8) + movq %rbp,PCB_RBP(%r8) + movq %r12,PCB_R12(%r8) + movq %r13,PCB_R13(%r8) + movq %r14,PCB_R14(%r8) + movq %r15,PCB_R15(%r8) pushfq /* PSL */ - popq PCB_RFLAGS(%rdx) + popq PCB_RFLAGS(%r8) + + /* Save userland %fs */ + movl $MSR_FSBASE,%ecx + rdmsr + movl %eax,PCB_FSBASE(%r8) + movl %edx,PCB_FSBASE+4(%r8) + + /* Save userland %gs */ + movl $MSR_KGSBASE,%ecx + rdmsr + movl %eax,PCB_GSBASE(%r8) + movl %edx,PCB_GSBASE+4(%r8) /* have we used fp, and need a save? */ cmpq %rdi,PCPU(FPCURTHREAD) jne 1f pushq %rdi pushq %rsi - addq $PCB_SAVEFPU,%rdx /* h/w bugs make saving complicated */ - movq %rdx, %rdi + addq $PCB_SAVEFPU,%r8 /* h/w bugs make saving complicated */ + movq %r8, %rdi call npxsave /* do it in a big C function */ popq %rsi popq %rdi @@ -123,12 +135,12 @@ testq %rsi,%rsi /* no thread? */ jz badsw3 /* no, panic */ #endif - movq TD_PCB(%rsi),%rdx + movq TD_PCB(%rsi),%r8 xorq %rax, %rax movl PCPU(CPUID), %eax /* switch address space */ - movq PCB_CR3(%rdx),%rdx + movq PCB_CR3(%r8),%rdx movq %rdx,%cr3 /* new address space */ /* Release bit from old pmap->pm_active */ @@ -146,26 +158,38 @@ * At this point, we've switched address spaces and are ready * to load up the rest of the next context. */ - movq TD_PCB(%rsi),%rdx + movq TD_PCB(%rsi),%r8 + + /* Restore userland %fs */ + movl $MSR_FSBASE,%ecx + movl PCB_FSBASE(%r8),%eax + movl PCB_FSBASE+4(%r8),%edx + wrmsr + + /* Restore userland %gs */ + movl $MSR_KGSBASE,%ecx + movl PCB_GSBASE(%r8),%eax + movl PCB_GSBASE+4(%r8),%edx + wrmsr /* Update the TSS_RSP0 pointer for the next interrupt */ - leaq -16(%rdx), %rbx + leaq -16(%r8), %rbx movq %rbx, common_tss + COMMON_TSS_RSP0 /* Restore context. */ - movq PCB_RBX(%rdx),%rbx - movq PCB_RSP(%rdx),%rsp - movq PCB_RBP(%rdx),%rbp - movq PCB_R12(%rdx),%r12 - movq PCB_R13(%rdx),%r13 - movq PCB_R14(%rdx),%r14 - movq PCB_R15(%rdx),%r15 - movq PCB_RIP(%rdx),%rax + movq PCB_RBX(%r8),%rbx + movq PCB_RSP(%r8),%rsp + movq PCB_RBP(%r8),%rbp + movq PCB_R12(%r8),%r12 + movq PCB_R13(%r8),%r13 + movq PCB_R14(%r8),%r14 + movq PCB_R15(%r8),%r15 + movq PCB_RIP(%r8),%rax movq %rax,(%rsp) - pushq PCB_RFLAGS(%rdx) + pushq PCB_RFLAGS(%r8) popfq - movq %rdx, PCPU(CURPCB) + movq %r8, PCPU(CURPCB) movq %rsi, PCPU(CURTHREAD) /* into next thread */ ret ==== //depot/projects/hammer/sys/amd64/amd64/genassym.c#8 (text+ko) ==== @@ -70,6 +70,7 @@ #include <machine/cpu.h> #include <machine/sigframe.h> #include <machine/proc.h> +#include <machine/specialreg.h> ASSYM(P_VMSPACE, offsetof(struct proc, p_vmspace)); ASSYM(VM_PMAP, offsetof(struct vmspace, vm_pmap)); @@ -122,6 +123,8 @@ ASSYM(PCB_RBX, offsetof(struct pcb, pcb_rbx)); ASSYM(PCB_RIP, offsetof(struct pcb, pcb_rip)); ASSYM(PCB_RFLAGS, offsetof(struct pcb, pcb_rflags)); +ASSYM(PCB_FSBASE, offsetof(struct pcb, pcb_fsbase)); +ASSYM(PCB_GSBASE, offsetof(struct pcb, pcb_gsbase)); ASSYM(PCB_FLAGS, offsetof(struct pcb, pcb_flags)); ASSYM(PCB_FULLCTX, PCB_FULLCTX); @@ -178,6 +181,8 @@ ASSYM(KUCSEL, GSEL(GUCODE_SEL, SEL_UPL)); ASSYM(KUDSEL, GSEL(GUDATA_SEL, SEL_UPL)); +ASSYM(MSR_FSBASE, MSR_FSBASE); +ASSYM(MSR_KGSBASE, MSR_KGSBASE); ASSYM(GPROC0_SEL, GPROC0_SEL); ASSYM(MTX_LOCK, offsetof(struct mtx, mtx_lock)); ==== //depot/projects/hammer/sys/amd64/amd64/machdep.c#23 (text+ko) ==== @@ -465,6 +465,12 @@ u_long ps_strings; { struct trapframe *regs = td->td_frame; + struct pcb *pcb = td->td_pcb; + + pcb->pcb_fsbase = 0; + pcb->pcb_gsbase = 0; + wrmsr(MSR_FSBASE, 0); + wrmsr(MSR_KGSBASE, 0); /* User value while we're in the kernel */ bzero((char *)regs, sizeof(struct trapframe)); regs->tf_rip = entry; ==== //depot/projects/hammer/sys/amd64/amd64/sys_machdep.c#6 (text+ko) ==== @@ -40,6 +40,9 @@ #include <sys/lock.h> #include <sys/proc.h> #include <sys/sysproto.h> +#include <machine/specialreg.h> +#include <machine/sysarch.h> +#include <machine/pcb.h> #ifndef _SYS_SYSPROTO_H_ struct sysarch_args { @@ -53,9 +56,30 @@ struct thread *td; register struct sysarch_args *uap; { - int error; + int error = 0; + struct pcb *pcb = curthread->td_pcb; switch(uap->op) { + case AMD64_GET_FSBASE: + error = copyout(&pcb->pcb_fsbase, uap->parms, sizeof(pcb->pcb_fsbase)); + break; + + case AMD64_SET_FSBASE: + error = copyin(uap->parms, &pcb->pcb_fsbase, sizeof(pcb->pcb_fsbase)); + if (!error) + wrmsr(MSR_FSBASE, pcb->pcb_fsbase); + break; + + case AMD64_GET_GSBASE: + error = copyout(&pcb->pcb_gsbase, uap->parms, sizeof(pcb->pcb_gsbase)); + break; + + case AMD64_SET_GSBASE: + error = copyin(uap->parms, &pcb->pcb_gsbase, sizeof(pcb->pcb_gsbase)); + if (!error) + wrmsr(MSR_KGSBASE, pcb->pcb_fsbase); + break; + default: error = EINVAL; break; ==== //depot/projects/hammer/sys/amd64/include/pcb.h#6 (text+ko) ==== @@ -57,6 +57,8 @@ register_t pcb_rbx; register_t pcb_rip; register_t pcb_rflags; + register_t pcb_fsbase; + register_t pcb_gsbase; struct savefpu pcb_save; u_long pcb_flags; ==== //depot/projects/hammer/sys/amd64/include/sysarch.h#6 (text+ko) ==== @@ -34,9 +34,27 @@ */ /* - * Architecture specific syscalls (i386) + * Architecture specific syscalls (AMD64) */ #ifndef _MACHINE_SYSARCH_H_ #define _MACHINE_SYSARCH_H_ +#define AMD64_GET_FSBASE 0 +#define AMD64_SET_FSBASE 1 +#define AMD64_GET_GSBASE 2 +#define AMD64_SET_GSBASE 3 + +#if 0 /* these wrappers need to be implemented in libc first */ +#ifndef _KERNEL +#include <sys/cdefs.h> + +__BEGIN_DECLS +unsigned long amd64_get_fsbase(void); +unsigned long amd64_set_fsbase(unsigned long); +unsigned long amd64_get_gsbase(void); +unsigned long amd64_set_gsbase(unsigned long); +__END_DECLS +#endif +#endif + #endif /* !_MACHINE_SYSARCH_H_ */
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200305120203.h4C23OtD038902>