PERFORCE change 30986 for review
Peter Wemm
peter at FreeBSD.org
Sun May 11 19:03:27 PDT 2003
http://perforce.freebsd.org/chv.cgi?CH=30986
Change 30986 by peter at 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_ */
More information about the p4-projects
mailing list