diff options
author | peter <peter@FreeBSD.org> | 2004-05-16 22:43:57 +0000 |
---|---|---|
committer | peter <peter@FreeBSD.org> | 2004-05-16 22:43:57 +0000 |
commit | 8b77ed77bd073cb3767a57552844fed3125fcfa3 (patch) | |
tree | befcd9f4b2350e266f7fe945e786539e307d0ba3 /sys | |
parent | 42f5ddc2f4e7e2251c8969f6e4873c73f48a8b12 (diff) | |
download | FreeBSD-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.S | 25 | ||||
-rw-r--r-- | sys/amd64/amd64/genassym.c | 1 | ||||
-rw-r--r-- | sys/amd64/include/pcb.h | 1 |
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 */ |