From owner-p4-projects@FreeBSD.ORG Mon Feb 19 22:56:21 2007 Return-Path: X-Original-To: p4-projects@freebsd.org Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id 8FA4816EE05; Mon, 19 Feb 2007 22:56:21 +0000 (UTC) X-Original-To: perforce@freebsd.org Delivered-To: perforce@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [69.147.83.52]) by hub.freebsd.org (Postfix) with ESMTP id 195BE16EE00 for ; Mon, 19 Feb 2007 22:56:21 +0000 (UTC) (envelope-from jkim@freebsd.org) Received: from repoman.freebsd.org (repoman.freebsd.org [69.147.83.41]) by mx1.freebsd.org (Postfix) with ESMTP id 06B9213C4A3 for ; Mon, 19 Feb 2007 22:56:21 +0000 (UTC) (envelope-from jkim@freebsd.org) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.13.6/8.13.6) with ESMTP id l1JMuKtO029287 for ; Mon, 19 Feb 2007 22:56:20 GMT (envelope-from jkim@freebsd.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.13.6/8.13.4/Submit) id l1JMuKHH029284 for perforce@freebsd.org; Mon, 19 Feb 2007 22:56:20 GMT (envelope-from jkim@freebsd.org) Date: Mon, 19 Feb 2007 22:56:20 GMT Message-Id: <200702192256.l1JMuKHH029284@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to jkim@freebsd.org using -f From: Jung-uk Kim To: Perforce Change Reviews Cc: Subject: PERFORCE change 114732 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 19 Feb 2007 22:56:22 -0000 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. PCB_32BIT flag was half-baked and never used from the day one. Unfortunately it was confusing me from the beginning. :-( 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 +#include 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;