summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authorpeter <peter@FreeBSD.org>2004-05-16 22:43:57 +0000
committerpeter <peter@FreeBSD.org>2004-05-16 22:43:57 +0000
commit8b77ed77bd073cb3767a57552844fed3125fcfa3 (patch)
treebefcd9f4b2350e266f7fe945e786539e307d0ba3 /sys
parent42f5ddc2f4e7e2251c8969f6e4873c73f48a8b12 (diff)
downloadFreeBSD-src-8b77ed77bd073cb3767a57552844fed3125fcfa3.zip
FreeBSD-src-8b77ed77bd073cb3767a57552844fed3125fcfa3.tar.gz
Checkpoint some of what I was starting to tinker with for having some
different context support for 32 vs 64 bit processes. This simply omits the save/restore of the segment selector registers for non 32 bit processes. This avoids the rdmsr/rwmsr juggling when restoring %gs clobbers the kernel msr that holds the gsbase. However, I suspect it might be better to conditionally do this at user<->kernel transition where we wouldn't need to do the juggling in the first place. Or have per-thread extended context save/restore hooks.
Diffstat (limited to 'sys')
-rw-r--r--sys/amd64/amd64/cpu_switch.S25
-rw-r--r--sys/amd64/amd64/genassym.c1
-rw-r--r--sys/amd64/include/pcb.h1
3 files changed, 20 insertions, 7 deletions
diff --git a/sys/amd64/amd64/cpu_switch.S b/sys/amd64/amd64/cpu_switch.S
index 2bbd904..ae13f58 100644
--- a/sys/amd64/amd64/cpu_switch.S
+++ b/sys/amd64/amd64/cpu_switch.S
@@ -103,6 +103,17 @@ ENTRY(cpu_switch)
pushfq /* PSL */
popq PCB_RFLAGS(%r8)
+ testl $PCB_32BIT,PCB_FLAGS(%r8)
+ jz 1f /* no, skip over */
+
+ /* Save segment selector numbers */
+ movl %ds,PCB_DS(%r8)
+ movl %es,PCB_ES(%r8)
+ movl %fs,PCB_FS(%r8)
+ movl %gs,PCB_GS(%r8)
+ jmp 2f
+1:
+
/* Save userland %fs */
movl $MSR_FSBASE,%ecx
rdmsr
@@ -114,12 +125,7 @@ ENTRY(cpu_switch)
rdmsr
movl %eax,PCB_GSBASE(%r8)
movl %edx,PCB_GSBASE+4(%r8)
-
- /* Save segment selector numbers */
- movl %ds,PCB_DS(%r8)
- movl %es,PCB_ES(%r8)
- movl %fs,PCB_FS(%r8)
- movl %gs,PCB_GS(%r8)
+2:
/* Test if debug registers should be saved. */
testl $PCB_DBREGS,PCB_FLAGS(%r8)
@@ -181,6 +187,9 @@ sw1:
*/
movq TD_PCB(%rsi),%r8
+ testl $PCB_32BIT,PCB_FLAGS(%r8)
+ jz 1f /* no, skip over */
+
/* Restore segment selector numbers */
movl PCB_DS(%r8),%ds
movl PCB_ES(%r8),%es
@@ -191,6 +200,8 @@ sw1:
rdmsr
movl PCB_GS(%r8),%gs
wrmsr
+ jmp 2f
+1:
/* Restore userland %fs */
movl $MSR_FSBASE,%ecx
@@ -203,6 +214,7 @@ sw1:
movl PCB_GSBASE(%r8),%eax
movl PCB_GSBASE+4(%r8),%edx
wrmsr
+2:
/* Update the TSS_RSP0 pointer for the next interrupt */
movq PCPU(TSSP), %rax
@@ -248,7 +260,6 @@ sw1:
orq %rcx,%rax
movq %rax,%dr7
1:
-
ret
/*
diff --git a/sys/amd64/amd64/genassym.c b/sys/amd64/amd64/genassym.c
index 933c7be..5152be5 100644
--- a/sys/amd64/amd64/genassym.c
+++ b/sys/amd64/amd64/genassym.c
@@ -138,6 +138,7 @@ ASSYM(PCB_DR3, offsetof(struct pcb, pcb_dr3));
ASSYM(PCB_DR6, offsetof(struct pcb, pcb_dr6));
ASSYM(PCB_DR7, offsetof(struct pcb, pcb_dr7));
ASSYM(PCB_DBREGS, PCB_DBREGS);
+ASSYM(PCB_32BIT, PCB_32BIT);
ASSYM(PCB_FLAGS, offsetof(struct pcb, pcb_flags));
ASSYM(PCB_FULLCTX, PCB_FULLCTX);
diff --git a/sys/amd64/include/pcb.h b/sys/amd64/include/pcb.h
index de9bad8..73d8aa5 100644
--- a/sys/amd64/include/pcb.h
+++ b/sys/amd64/include/pcb.h
@@ -71,6 +71,7 @@ struct pcb {
u_long pcb_flags;
#define PCB_DBREGS 0x02 /* process using debug registers */
#define PCB_FPUINITDONE 0x08 /* fpu state is initialized */
+#define PCB_32BIT 0x40 /* process has 32 bit context (segs etc) */
#define PCB_FULLCTX 0x80 /* full context restore on sysret */
caddr_t pcb_onfault; /* copyin/out fault recovery */
OpenPOWER on IntegriCloud