Date: Mon, 19 Feb 2007 22:56:20 GMT From: Jung-uk Kim <jkim@FreeBSD.org> To: Perforce Change Reviews <perforce@freebsd.org> Subject: PERFORCE change 114732 for review Message-ID: <200702192256.l1JMuKHH029284@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=114732 Change 114732 by jkim@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;
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200702192256.l1JMuKHH029284>