[email protected]
[Top] [All Lists]

PERFORCE change 114732 for review

Subject: PERFORCE change 114732 for review
From: Jung-uk Kim
Date: Mon, 19 Feb 2007 22:56:20 GMT
http://perforce.freebsd.org/chv.cgi?CH=114732

Change 114732 by [email protected]_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;
_______________________________________________
[email protected] mailing list
http://lists.freebsd.org/mailman/listinfo/p4-projects
To unsubscribe, send any mail to "[email protected]"

<Prev in Thread] Current Thread [Next in Thread>