Skip site navigation (1)Skip section navigation (2)
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>