From owner-p4-projects@FreeBSD.ORG Sun May 11 19:03:26 2003 Return-Path: Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id 2D3F737B404; Sun, 11 May 2003 19:03:26 -0700 (PDT) Delivered-To: perforce@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id BC5B637B401 for ; Sun, 11 May 2003 19:03:25 -0700 (PDT) Received: from repoman.freebsd.org (repoman.freebsd.org [216.136.204.115]) by mx1.FreeBSD.org (Postfix) with ESMTP id 48DB243F93 for ; Sun, 11 May 2003 19:03:25 -0700 (PDT) (envelope-from peter@freebsd.org) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.12.6/8.12.6) with ESMTP id h4C23P0U038905 for ; Sun, 11 May 2003 19:03:25 -0700 (PDT) (envelope-from peter@freebsd.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.12.6/8.12.6/Submit) id h4C23OtD038902 for perforce@freebsd.org; Sun, 11 May 2003 19:03:24 -0700 (PDT) Date: Sun, 11 May 2003 19:03:24 -0700 (PDT) Message-Id: <200305120203.h4C23OtD038902@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to peter@freebsd.org using -f From: Peter Wemm To: Perforce Change Reviews Subject: PERFORCE change 30986 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.1 Precedence: list List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 12 May 2003 02:03:27 -0000 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 #include #include +#include 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 #include #include +#include +#include +#include #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 + +__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_ */