x86: set pcpui->{ts,gdt} early
authorBarret Rhoden <brho@cs.berkeley.edu>
Wed, 26 Oct 2016 22:17:32 +0000 (18:17 -0400)
committerBarret Rhoden <brho@cs.berkeley.edu>
Tue, 29 Nov 2016 16:27:40 +0000 (11:27 -0500)
This allows us to set/get the stacktop with the usual, arch-independent
helper early.  I'll need this during init, before smp_boot.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
kern/arch/x86/smp_boot.c
kern/arch/x86/trap.c
kern/arch/x86/trap64.h

index 0a18695..41d15a1 100644 (file)
@@ -323,11 +323,8 @@ void __arch_pcpu_init(uint32_t coreid)
        // Initialize fpu and extended state by restoring our default XSAVE area.
        init_fp_state();
 
-       /* core 0 sets up via the global gdt symbol */
-       if (!coreid) {
-               pcpui->tss = &ts;
-               pcpui->gdt = gdt;
-       } else {
+       /* core 0 set up earlier in idt_init() */
+       if (coreid) {
                my_stack_bot = kstack_bottom_addr(ROUNDUP(read_sp() - 1, PGSIZE));
                pcpui->tss = (taskstate_t*)(*my_stack_bot);
                pcpui->gdt = (segdesc_t*)(*my_stack_bot +
@@ -336,7 +333,8 @@ void __arch_pcpu_init(uint32_t coreid)
        assert(read_gsbase() == (uintptr_t)pcpui);
        assert(read_msr(MSR_KERN_GS_BASE) == (uint64_t)pcpui);
        /* Don't try setting up til after setting GS */
-       x86_sysenter_init(x86_get_stacktop_tss(pcpui->tss));
+       x86_sysenter_init();
+       x86_set_sysenter_stacktop(x86_get_stacktop_tss(pcpui->tss));
        pcpu_init_nmi(pcpui);
        /* need to init perfctr before potentially using it in timer handler */
        perfmon_pcpu_init();
index 83ad353..e9b92b0 100644 (file)
@@ -85,9 +85,7 @@ const char *x86_trapname(int trapno)
 }
 
 /* Set stacktop for the current core to be the stack the kernel will start on
- * when trapping/interrupting from userspace.  Don't use this til after
- * smp_percpu_init().  We can probably get the TSS by reading the task register
- * and then the GDT.  Still, it's a pain. */
+ * when trapping/interrupting from userspace. */
 void set_stack_top(uintptr_t stacktop)
 {
        struct per_cpu_info *pcpui = &per_cpu_info[core_id()];
@@ -102,11 +100,7 @@ uintptr_t get_stack_top(void)
 {
        struct per_cpu_info *pcpui = &per_cpu_info[core_id()];
        uintptr_t stacktop;
-       /* so we can check this in interrupt handlers (before smp_boot()) */
-       /* TODO: These are dangerous - it assumes we're on a one-page stack.  If we
-        * change it to KSTKSIZE, then we assume stacks are KSTKSIZE-aligned */
-       if (!pcpui->tss)
-               return ROUNDUP(read_sp(), PGSIZE);
+
        stacktop = x86_get_stacktop_tss(pcpui->tss);
        if (stacktop != ROUNDUP(read_sp(), PGSIZE))
                panic("Bad stacktop: %p esp one is %p\n", stacktop,
@@ -157,10 +151,14 @@ void idt_init(void)
        /* Send NMIs to their own stack (IST1 in every core's TSS) */
        idt[T_NMI].gd_ist = 1;
 
+       /* The sooner we set this, the sooner we can use set/get_stack_top. */
+       per_cpu_info[0].tss = &ts;
+       per_cpu_info[0].gdt = gdt;
+
        /* Set up our kernel stack when changing rings */
        /* Note: we want 16 byte aligned kernel stack frames (AMD 2:8.9.3) */
-       x86_set_stacktop_tss(&ts, (uintptr_t)bootstacktop);
-       x86_sysenter_init((uintptr_t)bootstacktop);
+       x86_sysenter_init();
+       set_stack_top((uintptr_t)bootstacktop);
 
 #ifdef CONFIG_KTHREAD_POISON
        *kstack_bottom_addr((uintptr_t)bootstacktop) = 0xdeadbeef;
index c6977eb..07bcf08 100644 (file)
@@ -34,7 +34,7 @@ static inline void x86_fake_rdtscp(struct hw_trapframe *hw_tf)
        hw_tf->tf_rcx = core_id();
 }
 
-static inline void x86_sysenter_init(uintptr_t stacktop)
+static inline void x86_sysenter_init(void)
 {
        /* check amd 2:6.1.1 for details.  they have some expectations about the GDT
         * layout. */
@@ -44,7 +44,6 @@ static inline void x86_sysenter_init(uintptr_t stacktop)
        /* Masking all flags.  when we syscall, we'll get rflags = 0 */
        write_msr(MSR_SFMASK, 0xffffffff);
        write_msr(IA32_EFER_MSR, read_msr(IA32_EFER_MSR) | IA32_EFER_SYSCALL);
-       asm volatile ("movq %0, %%gs:0" : : "r"(stacktop));
 }
 
 /* these are used for both sysenter and traps on 32 bit */