Bring back the save/restore of the %ds, %es, %fs and %gs registers for
the 32bit images on amd64. Change the semantic of the PCB_32BIT pcb flag to request the context switch code to operate on the segment registers. Its previous meaning of saving or restoring the %gs base offset is assigned to the new PCB_GS32BIT flag. FreeBSD 32bit image activator sets the PCB_32BIT flag, while Linux 32bit emulation sets PCB_32BIT | PCB_GS32BIT. Reviewed by: peter MFC after: 2 weeks
This commit is contained in:
parent
13b6ce6962
commit
19bf5e2807
sys/amd64
@ -113,8 +113,8 @@ ENTRY(cpu_switch)
|
||||
movq PCB_GSBASE(%r8),%r10
|
||||
|
||||
testl $PCB_32BIT,PCB_FLAGS(%r8)
|
||||
jnz store_gs /* static predict not taken */
|
||||
done_store_gs:
|
||||
jnz store_seg
|
||||
done_store_seg:
|
||||
|
||||
testl $PCB_DBREGS,PCB_FLAGS(%r8)
|
||||
jnz store_dr /* static predict not taken */
|
||||
@ -176,6 +176,10 @@ sw1:
|
||||
testl $TDP_KTHREAD,TD_PFLAGS(%rsi)
|
||||
jnz do_kthread
|
||||
|
||||
testl $PCB_32BIT,PCB_FLAGS(%r8)
|
||||
jnz load_seg
|
||||
done_load_seg:
|
||||
|
||||
cmpq PCB_FSBASE(%r8),%r9
|
||||
jz 1f
|
||||
/* Restore userland %fs */
|
||||
@ -184,7 +188,6 @@ sw1:
|
||||
movl PCB_FSBASE+4(%r8),%edx
|
||||
wrmsr
|
||||
1:
|
||||
|
||||
cmpq PCB_GSBASE(%r8),%r10
|
||||
jz 2f
|
||||
/* Restore userland %gs */
|
||||
@ -193,8 +196,8 @@ sw1:
|
||||
movl PCB_GSBASE+4(%r8),%edx
|
||||
wrmsr
|
||||
2:
|
||||
do_tss:
|
||||
|
||||
do_tss:
|
||||
/* Update the TSS_RSP0 pointer for the next interrupt */
|
||||
movq PCPU(TSSP), %rax
|
||||
movq %r8, PCPU(RSP0)
|
||||
@ -208,10 +211,6 @@ do_tss:
|
||||
jnz load_dr /* static predict not taken */
|
||||
done_load_dr:
|
||||
|
||||
testl $PCB_32BIT,PCB_FLAGS(%r8)
|
||||
jnz load_gs /* static predict not taken */
|
||||
done_load_gs:
|
||||
|
||||
/* Restore context. */
|
||||
movq PCB_R15(%r8),%r15
|
||||
movq PCB_R14(%r8),%r14
|
||||
@ -243,23 +242,35 @@ do_kthread:
|
||||
movq %r10,PCB_GSBASE(%r8)
|
||||
jmp do_tss
|
||||
|
||||
store_gs:
|
||||
store_seg:
|
||||
movl %gs,PCB_GS(%r8)
|
||||
movq PCB_GS32P(%r8),%rax
|
||||
testl $PCB_GS32BIT,PCB_FLAGS(%r8)
|
||||
jnz 2f
|
||||
1: movl %ds,PCB_DS(%r8)
|
||||
movl %es,PCB_ES(%r8)
|
||||
movl %fs,PCB_FS(%r8)
|
||||
jmp done_store_seg
|
||||
2: movq PCB_GS32P(%r8),%rax
|
||||
movq (%rax),%rax
|
||||
movq %rax,PCB_GS32SD(%r8)
|
||||
jmp done_store_gs
|
||||
jmp 1b
|
||||
|
||||
load_gs:
|
||||
/* Restore userland %gs while preserving kernel gsbase */
|
||||
movq PCB_GS32P(%r8),%rax
|
||||
movq PCB_GS32SD(%r8),%rcx
|
||||
movq %rcx,(%rax)
|
||||
movl $MSR_GSBASE,%ecx
|
||||
load_seg:
|
||||
testl $PCB_GS32BIT,PCB_FLAGS(%r8)
|
||||
jnz 2f
|
||||
1: movl $MSR_GSBASE,%ecx
|
||||
rdmsr
|
||||
movl PCB_GS(%r8),%gs
|
||||
wrmsr
|
||||
jmp done_load_gs
|
||||
movl PCB_DS(%r8),%ds
|
||||
movl PCB_ES(%r8),%es
|
||||
movl PCB_FS(%r8),%fs
|
||||
jmp done_load_seg
|
||||
/* Restore userland %gs while preserving kernel gsbase */
|
||||
2: movq PCB_GS32P(%r8),%rax
|
||||
movq PCB_GS32SD(%r8),%rcx
|
||||
movq %rcx,(%rax)
|
||||
jmp 1b
|
||||
|
||||
store_dr:
|
||||
movq %dr7,%rax /* yes, do the save */
|
||||
|
@ -140,6 +140,7 @@ 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_GS32BIT, PCB_GS32BIT);
|
||||
ASSYM(PCB_FULLCTX, PCB_FULLCTX);
|
||||
|
||||
ASSYM(PCB_FLAGS, offsetof(struct pcb, pcb_flags));
|
||||
|
@ -741,6 +741,6 @@ ia32_setregs(td, entry, stack, ps_strings)
|
||||
fpstate_drop(td);
|
||||
|
||||
/* Return via doreti so that we can change to a different %cs */
|
||||
pcb->pcb_flags |= PCB_FULLCTX;
|
||||
pcb->pcb_flags |= PCB_FULLCTX | PCB_32BIT;
|
||||
td->td_retval[1] = 0;
|
||||
}
|
||||
|
@ -70,6 +70,7 @@ struct pcb {
|
||||
struct savefpu pcb_save;
|
||||
#define PCB_DBREGS 0x02 /* process using debug registers */
|
||||
#define PCB_FPUINITDONE 0x08 /* fpu state is initialized */
|
||||
#define PCB_GS32BIT 0x20 /* linux gs switch */
|
||||
#define PCB_32BIT 0x40 /* process has 32 bit context (segs etc) */
|
||||
#define PCB_FULLCTX 0x80 /* full context restore on sysret */
|
||||
|
||||
|
@ -696,7 +696,7 @@ linux_clone(struct thread *td, struct linux_clone_args *args)
|
||||
td2->td_pcb->pcb_gs32sd = sd;
|
||||
td2->td_pcb->pcb_gs32p = &gdt[GUGS32_SEL];
|
||||
td2->td_pcb->pcb_gs = GSEL(GUGS32_SEL, SEL_UPL);
|
||||
td2->td_pcb->pcb_flags |= PCB_32BIT;
|
||||
td2->td_pcb->pcb_flags |= PCB_GS32BIT | PCB_32BIT;
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user