PERFORCE change 114732 for review
Jung-uk Kim
jkim at FreeBSD.org
Mon Feb 19 22:56:22 UTC 2007
http://perforce.freebsd.org/chv.cgi?CH=114732
Change 114732 by jkim at jkim_hammer on 2007/02/19 22:56:14
Finish TLS on amd64 support.
It may have rough edges but it seems usable.
Tested on a real UP machine and QEMU SMP.
<rant>
PCB_32BIT flag was half-baked and never used from the day one.
Unfortunately it was confusing me from the beginning. :-(
</rant>
Affected files ...
.. //depot/projects/linuxolator/src/sys/amd64/amd64/cpu_switch.S#5 edit
.. //depot/projects/linuxolator/src/sys/amd64/amd64/genassym.c#6 edit
.. //depot/projects/linuxolator/src/sys/amd64/ia32/ia32_signal.c#4 edit
.. //depot/projects/linuxolator/src/sys/amd64/include/pcb.h#3 edit
.. //depot/projects/linuxolator/src/sys/amd64/linux32/linux32_locore.s#3 edit
.. //depot/projects/linuxolator/src/sys/amd64/linux32/linux32_machdep.c#37 edit
.. //depot/projects/linuxolator/src/sys/amd64/linux32/linux32_sysvec.c#11 edit
Differences ...
==== //depot/projects/linuxolator/src/sys/amd64/amd64/cpu_switch.S#5 (text+ko) ====
@@ -104,11 +104,11 @@
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)
+ /* Save userland %gs */
movl %gs,PCB_GS(%r8)
+ movq PCB_GS32P(%r8),%rax
+ movq (%rax),%rax
+ movq %rax,PCB_GS32SD(%r8)
1:
/* Test if debug registers should be saved. */
@@ -171,30 +171,6 @@
*/
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
- movl PCB_FS(%r8),%fs
-
- /* Restore userland %gs while preserving kernel gsbase */
- movl $MSR_GSBASE,%ecx
- rdmsr
- movl PCB_GS(%r8),%gs
- wrmsr
-
- /* Restore userland 32 bit GS descriptor for Linuxulator */
- movq PCB_GS32P(%r8),%rax
- testq %rax,%rax
- jz 2f /* no, skip over */
-
- movq PCB_GS32SD(%r8),%rcx
- movq %rcx,(%rax)
- jmp 2f
-
-1:
/* Restore userland %fs */
movl $MSR_FSBASE,%ecx
movl PCB_FSBASE(%r8),%eax
@@ -207,7 +183,6 @@
movl PCB_GSBASE+4(%r8),%edx
wrmsr
-2:
/* Update the TSS_RSP0 pointer for the next interrupt */
movq PCPU(TSSP), %rax
addq $COMMON_TSS_RSP0, %rax
@@ -220,6 +195,19 @@
movl %eax, PCPU(CURTID)
movq %rsi, PCPU(CURTHREAD) /* into next thread */
+ testl $PCB_32BIT,PCB_FLAGS(%r8)
+ jz 1f /* no, skip over */
+
+ /* Restore userland %gs while preserving kernel gsbase */
+ movq PCB_GS32P(%r8),%rax
+ movq PCB_GS32SD(%r8),%rbx
+ movq %rbx,(%rax)
+ movl $MSR_GSBASE,%ecx
+ rdmsr
+ movl PCB_GS(%r8),%gs
+ wrmsr
+
+1:
/* Restore context. */
movq PCB_RBX(%r8),%rbx
movq PCB_RSP(%r8),%rsp
==== //depot/projects/linuxolator/src/sys/amd64/amd64/genassym.c#6 (text+ko) ====
@@ -136,20 +136,19 @@
ASSYM(PCB_DR7, offsetof(struct pcb, pcb_dr7));
ASSYM(PCB_DBREGS, PCB_DBREGS);
ASSYM(PCB_32BIT, PCB_32BIT);
+ASSYM(PCB_FULLCTX, PCB_FULLCTX);
ASSYM(PCB_FLAGS, offsetof(struct pcb, pcb_flags));
-ASSYM(PCB_FULLCTX, PCB_FULLCTX);
ASSYM(PCB_SAVEFPU, offsetof(struct pcb, pcb_save));
ASSYM(PCB_SAVEFPU_SIZE, sizeof(struct savefpu));
ASSYM(PCB_ONFAULT, offsetof(struct pcb, pcb_onfault));
+ASSYM(PCB_GS32P, offsetof(struct pcb, pcb_gs32p));
+ASSYM(PCB_GS32SD, offsetof(struct pcb, pcb_gs32sd));
ASSYM(PCB_SIZE, sizeof(struct pcb));
ASSYM(COMMON_TSS_RSP0, offsetof(struct amd64tss, tss_rsp0));
-ASSYM(PCB_GS32P, offsetof(struct pcb, pcb_gs32p));
-ASSYM(PCB_GS32SD, offsetof(struct pcb, pcb_gs32sd));
-
ASSYM(TF_R15, offsetof(struct trapframe, tf_r15));
ASSYM(TF_R14, offsetof(struct trapframe, tf_r14));
ASSYM(TF_R13, offsetof(struct trapframe, tf_r13));
==== //depot/projects/linuxolator/src/sys/amd64/ia32/ia32_signal.c#4 (text+ko) ====
@@ -727,7 +727,6 @@
pcb->pcb_es = _udatasel;
pcb->pcb_fs = _udatasel;
pcb->pcb_gs = _udatasel;
- pcb->pcb_gs32p = NULL;
bzero((char *)regs, sizeof(struct trapframe));
regs->tf_rip = entry;
==== //depot/projects/linuxolator/src/sys/amd64/include/pcb.h#3 (text+ko) ====
@@ -41,6 +41,7 @@
* AMD64 process control block
*/
#include <machine/fpu.h>
+#include <machine/segments.h>
struct pcb {
register_t pcb_cr3;
@@ -74,8 +75,9 @@
caddr_t pcb_onfault; /* copyin/out fault recovery */
- caddr_t pcb_gs32p; /* XXX pointer to gdt[GUGS32_SEL] */
- u_int64_t pcb_gs32sd; /* 32 bit GS segment descriptor */
+ /* 32-bit segment descriptor */
+ struct user_segment_descriptor *pcb_gs32p;
+ struct user_segment_descriptor pcb_gs32sd;
};
#ifdef _KERNEL
==== //depot/projects/linuxolator/src/sys/amd64/linux32/linux32_locore.s#3 (text+ko) ====
@@ -11,10 +11,6 @@
NON_GPROF_ENTRY(linux_sigcode)
call *LINUX_SIGF_HANDLER(%esp)
leal LINUX_SIGF_SC(%esp),%ebx /* linux scp */
-#if 0
- movl LINUX_SC_GS(%ebx),%gs
-#endif
- movl LINUX_SC_FS(%ebx),%fs
movl LINUX_SC_ES(%ebx),%es
movl LINUX_SC_DS(%ebx),%ds
movl %esp, %ebx /* pass sigframe */
@@ -27,10 +23,6 @@
linux_rt_sigcode:
call *LINUX_RT_SIGF_HANDLER(%esp)
leal LINUX_RT_SIGF_UC(%esp),%ebx /* linux ucp */
-#if 0
- movl LINUX_SC_GS(%ebx),%gs
-#endif
- movl LINUX_SC_FS(%ebx),%fs
movl LINUX_SC_ES(%ebx),%es
movl LINUX_SC_DS(%ebx),%ds
push %eax /* fake ret addr */
==== //depot/projects/linuxolator/src/sys/amd64/linux32/linux32_machdep.c#37 (text+ko) ====
@@ -724,8 +724,9 @@
sd.sd_gran);
#endif
td2->td_pcb->pcb_gsbase = (register_t)info.base_addr;
- td2->td_pcb->pcb_gs32p = (caddr_t)&gdt[GUGS32_SEL];
- memcpy(&td2->td_pcb->pcb_gs32sd, &sd, sizeof(sd));
+ td2->td_pcb->pcb_gs32sd = sd;
+ td2->td_pcb->pcb_gs32p = &gdt[GUGS32_SEL];
+ td2->td_pcb->pcb_flags |= PCB_32BIT;
}
}
@@ -1350,11 +1351,11 @@
critical_enter();
td->td_pcb->pcb_gsbase = (register_t)info.base_addr;
- td->td_pcb->pcb_gs32p = (caddr_t)&gdt[GUGS32_SEL];
- memcpy(&td->td_pcb->pcb_gs32sd, &sd, sizeof(sd));
+ td->td_pcb->pcb_gs32sd = gdt[GUGS32_SEL] = sd;
+ td->td_pcb->pcb_gs32p = &gdt[GUGS32_SEL];
+ td->td_pcb->pcb_flags |= PCB_32BIT;
wrmsr(MSR_KGSBASE, td->td_pcb->pcb_gsbase);
- gdt[GUGS32_SEL] = sd;
critical_exit();
-
+
return (0);
}
==== //depot/projects/linuxolator/src/sys/amd64/linux32/linux32_sysvec.c#11 (text+ko) ====
@@ -408,6 +408,7 @@
td->td_pcb->pcb_ds = _udatasel;
load_es(_udatasel);
td->td_pcb->pcb_es = _udatasel;
+ /* leave user %fs and %gs untouched */
PROC_LOCK(p);
mtx_lock(&psp->ps_mtx);
}
@@ -528,6 +529,7 @@
td->td_pcb->pcb_ds = _udatasel;
load_es(_udatasel);
td->td_pcb->pcb_es = _udatasel;
+ /* leave user %fs and %gs untouched */
PROC_LOCK(p);
mtx_lock(&psp->ps_mtx);
}
@@ -813,10 +815,12 @@
struct trapframe *regs = td->td_frame;
struct pcb *pcb = td->td_pcb;
+ critical_enter();
wrmsr(MSR_FSBASE, 0);
wrmsr(MSR_KGSBASE, 0); /* User value while we're in the kernel */
pcb->pcb_fsbase = 0;
pcb->pcb_gsbase = 0;
+ critical_exit();
load_ds(_udatasel);
load_es(_udatasel);
load_fs(_udatasel);
@@ -825,7 +829,6 @@
pcb->pcb_es = _udatasel;
pcb->pcb_fs = _udatasel;
pcb->pcb_gs = _udatasel;
- pcb->pcb_gs32p = NULL;
bzero((char *)regs, sizeof(struct trapframe));
regs->tf_rip = entry;
More information about the p4-projects
mailing list