X86: initializes the 64 bit IDT and TSS
authorBarret Rhoden <brho@cs.berkeley.edu>
Fri, 21 Jun 2013 00:37:53 +0000 (17:37 -0700)
committerBarret Rhoden <brho@cs.berkeley.edu>
Sat, 22 Jun 2013 17:29:31 +0000 (10:29 -0700)
The IRQ handlers aren't fixed yet.

kern/arch/x86/ros/mmu32.h
kern/arch/x86/ros/mmu64.h
kern/arch/x86/smp_boot.c
kern/arch/x86/trap.c
kern/arch/x86/trap32.h
kern/arch/x86/trap64.h
kern/include/trap.h
kern/src/init.c

index fb457a7..443ae85 100644 (file)
@@ -256,6 +256,8 @@ typedef struct Segdesc {
        unsigned sd_g : 1;          // Granularity: limit scaled by 4K when set
        unsigned sd_base_31_24 : 8; // High bits of segment base address
 } segdesc_t;
+typedef struct Segdesc syssegdesc_t;
+
 // Null segment
 #define SEG_NULL       { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
 // Segment that is loadable but faults when used
@@ -265,36 +267,28 @@ typedef struct Segdesc {
 { ((lim) >> 12) & 0xffff, (base) & 0xffff, ((base) >> 16) & 0xff,      \
     type, 1, dpl, 1, (unsigned) (lim) >> 28, 0, 0, 1, 1,                       \
     (unsigned) (base) >> 24 }
+
+#define SEG16(type, base, lim, dpl)                                                            \
+{ (lim) & 0xffff, (base) & 0xffff, ((base) >> 16) & 0xff,                      \
+    type, 1, dpl, 1, (unsigned) (lim) >> 16, 0, 0, 1, 0,                       \
+    (unsigned) (base) >> 24 }
+
 // System segment (LDT)
-#define SEG_SYS(type, base, lim, dpl)                                                                  \
+#define SEG_SYS(type, base, lim, dpl)                                                          \
 { ((lim) >> 12) & 0xffff, (base) & 0xffff, ((base) >> 16) & 0xff,      \
     type, 0, dpl, 1, (unsigned) (lim) >> 28, 0, 0, 1, 1,                       \
     (unsigned) (base) >> 24 }
 
-#define SEG16(type, base, lim, dpl)                                                            \
+#define SEG16_SYS(type, base, lim, dpl)                                                        \
 { (lim) & 0xffff, (base) & 0xffff, ((base) >> 16) & 0xff,                      \
-    type, 1, dpl, 1, (unsigned) (lim) >> 16, 0, 0, 1, 0,                       \
+    type, 0, dpl, 1, (unsigned) (lim) >> 16, 0, 0, 1, 0,                       \
     (unsigned) (base) >> 24 }
 
-#define SEG16ROINIT(seg,type,base,lim,dpl) \
-       {\
-               (seg).sd_lim_15_0 = SINIT((lim) & 0xffff);\
-               (seg).sd_base_15_0 = SINIT((uint32_t)(base)&0xffff);\
-               (seg).sd_base_23_16 = SINIT(((uint32_t)(base)>>16)&0xff);\
-               (seg).sd_type = SINIT(type);\
-               (seg).sd_s = SINIT(1);\
-               (seg).sd_dpl = SINIT(dpl);\
-               (seg).sd_p = SINIT(1);\
-               (seg).sd_lim_19_16 = SINIT((unsigned)(lim)>>16);\
-               (seg).sd_avl = SINIT(0);\
-               (seg).sd_rsv1 = SINIT(0);\
-               (seg).sd_db = SINIT(1);\
-               (seg).sd_g = SINIT(0);\
-               (seg).sd_base_31_24 = SINIT((uint32_t)(base)>> 24);\
-       }
+#define SEG_SYS_SMALL(type, base, lim, dpl) \
+        SEG16_SYS(type, base, lim, dpl)
 
 // Task state segment format (as described by the Pentium architecture book)
-typedef struct Taskstate {
+typedef struct taskstate {
        uint32_t ts_link;       // Old ts selector
        uintptr_t ts_esp0;      // Stack pointers and segment selectors
        uint16_t ts_ss0;        //   after an increase in privilege level
index 6e545c9..c10fdcc 100644 (file)
@@ -300,16 +300,21 @@ typedef unsigned long pde_t;
 
 /* **************************************** */
 /* Segmentation */
-// XXX 64b: these all need redone
 
-// Global descriptor numbers
-#define GD_NULL   0x00     // NULL descriptor
-#define GD_KT     0x08     // kernel text
+/* Global descriptor numbers */
+#define GD_NULL                        0x00    /* NULL descriptor */
+#define GD_KT                  0x08    /* kernel text */
+#define GD_UT                  0x10    /* user text */
+#define GD_TSS                 0x18    /* Task segment selector */
+#define GD_TSS2                        0x20    /* Placeholder, TSS is 2-descriptors wide */
+/* These two aren't in the GDT yet (might never be) */
+#define GD_LDT                 0x28    /* Local descriptor table */
+#define GD_LDT2                        0x30    /* Placeholder */
+
+/* Kept around to help compile, will remove */
 #define GD_KD     0x10     // kernel data
-#define GD_UT     0x18     // user text
 #define GD_UD     0x20     // user data
-#define GD_TSS    0x28     // Task segment selector
-#define GD_LDT    0x30     // local descriptor table
+
 
 #ifdef __ASSEMBLER__
 
@@ -357,8 +362,7 @@ typedef unsigned long pde_t;
 
 #else  // not __ASSEMBLER__
 
-/* TODO: consider removing this, if we're just using one asm GDT */
-// Segment Descriptors
+/* Legacy Segment Descriptor (used for 64 bit data and code) */
 typedef struct Segdesc {
        unsigned sd_lim_15_0 : 16;  // Low bits of segment limit
        unsigned sd_base_15_0 : 16; // Low bits of segment base address
@@ -374,144 +378,106 @@ typedef struct Segdesc {
        unsigned sd_g : 1;          // Granularity: limit scaled by 4K when set
        unsigned sd_base_31_24 : 8; // High bits of segment base address
 } segdesc_t;
-// Null segment
-#define SEG_NULL       { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
-// Segment that is loadable but faults when used
-#define SEG_FAULT      { 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0 }
-// Normal segment
-#define SEG(type, base, lim, dpl)                                                                      \
-{ ((lim) >> 12) & 0xffff, (base) & 0xffff, ((base) >> 16) & 0xff,      \
-    type, 1, dpl, 1, (unsigned) (lim) >> 28, 0, 0, 1, 1,                       \
-    (unsigned) (base) >> 24 }
-// System segment (LDT)
-#define SEG_SYS(type, base, lim, dpl)                                                                  \
-{ ((lim) >> 12) & 0xffff, (base) & 0xffff, ((base) >> 16) & 0xff,      \
-    type, 0, dpl, 1, (unsigned) (lim) >> 28, 0, 0, 1, 1,                       \
-    (unsigned) (base) >> 24 }
-
-#define SEG16(type, base, lim, dpl)                                                            \
-{ (lim) & 0xffff, (base) & 0xffff, ((base) >> 16) & 0xff,                      \
-    type, 1, dpl, 1, (unsigned) (lim) >> 16, 0, 0, 1, 0,                       \
-    (unsigned) (base) >> 24 }
-
-#define SEG16ROINIT(seg,type,base,lim,dpl) \
-       {\
-               (seg).sd_lim_15_0 = SINIT((lim) & 0xffff);\
-               (seg).sd_base_15_0 = SINIT((uintptr_t)(base)&0xffff);\
-               (seg).sd_base_23_16 = SINIT(((uintptr_t)(base)>>16)&0xff);\
-               (seg).sd_type = SINIT(type);\
-               (seg).sd_s = SINIT(1);\
-               (seg).sd_dpl = SINIT(dpl);\
-               (seg).sd_p = SINIT(1);\
-               (seg).sd_lim_19_16 = SINIT((unsigned)(lim)>>16);\
-               (seg).sd_avl = SINIT(0);\
-               (seg).sd_rsv1 = SINIT(0);\
-               (seg).sd_db = SINIT(1);\
-               (seg).sd_g = SINIT(0);\
-               (seg).sd_base_31_24 = SINIT((uintptr_t)(base)>> 24);\
-       }
-
-// Task state segment format (as described by the Pentium architecture book)
-typedef struct Taskstate {
-       uintptr_t ts_link;      // Old ts selector
-       uintptr_t ts_esp0;      // Stack pointers and segment selectors
-       uint16_t ts_ss0;        //   after an increase in privilege level
-       uint16_t ts_padding1;
-       uintptr_t ts_esp1;
-       uint16_t ts_ss1;
-       uint16_t ts_padding2;
-       uintptr_t ts_esp2;
-       uint16_t ts_ss2;
-       uint16_t ts_padding3;
-       physaddr_t ts_cr3;      // Page directory base
-       uintptr_t ts_eip;       // Saved state from last task switch
-       uintptr_t ts_eflags;
-       uintptr_t ts_eax;       // More saved state (registers)
-       uintptr_t ts_ecx;
-       uintptr_t ts_edx;
-       uintptr_t ts_ebx;
-       uintptr_t ts_esp;
-       uintptr_t ts_ebp;
-       uintptr_t ts_esi;
-       uintptr_t ts_edi;
-       uint16_t ts_es;         // Even more saved state (segment selectors)
-       uint16_t ts_padding4;
-       uint16_t ts_cs;
-       uint16_t ts_padding5;
-       uint16_t ts_ss;
-       uint16_t ts_padding6;
-       uint16_t ts_ds;
-       uint16_t ts_padding7;
-       uint16_t ts_fs;
-       uint16_t ts_padding8;
-       uint16_t ts_gs;
-       uint16_t ts_padding9;
-       uint16_t ts_ldt;
-       uint16_t ts_padding10;
-       uint16_t ts_t;          // Trap on task switch
-       uint16_t ts_iomb;       // I/O map base address
+
+/* Lower half is similar (more ignored, etc)  to a legacy system descriptor */
+struct x86_sysseg64 {
+       unsigned sd_lim_15_0 : 16;      /* Low bits of segment limit */
+       unsigned sd_base_15_0 : 16;     /* Low bits of segment base address */
+       unsigned sd_base_23_16 : 8;     /* Middle bits of segment base address */
+       unsigned sd_type : 4;           /* Segment type (see STS_ constants) */
+       unsigned sd_s : 1;                      /* 0 = system, 1 = application */
+       unsigned sd_dpl : 2;            /* Descriptor Privilege Level */
+       unsigned sd_p : 1;                      /* Present */
+       unsigned sd_lim_19_16 : 4;      /* High bits of segment limit */
+       unsigned sd_avl : 1;            /* Unused (available for software use) */
+       unsigned sd_rsv2 : 2;           /* Reserved */
+       unsigned sd_g : 1;                      /* Granularity: limit scaled by 4K when set */
+       unsigned sd_base_31_24 : 8;     /* 24-31 bits of segment base address */
+       unsigned sd_base_63_32;         /* top 32 bits of the base */
+       unsigned sd_reserved;           /* some parts must be zero, just zero it all */
+};
+typedef struct x86_sysseg64 syssegdesc_t;
+
+/* G(ranularity) determines if the limit is shifted */
+#define __SEG_SYS64(type, base, lim, dpl, g)                                   \
+{ ((lim) >> ((g) * 12)) & 0xffff, (base) & 0xffff, ((base) >> 16) & 0xff,      \
+    type, 0, dpl, 1, (unsigned) (lim) >> 28, 0, 0, (g),                        \
+    ((unsigned) (base) >> 24) & 0xff,                                          \
+    ((unsigned long) (base) >> 32), 0 }
+
+/* Normal system segment descriptor (LDT or TSS). (limit is scaled by 4k) */
+#define SEG_SYS64(type, base, lim, dpl)                                        \
+        __SEG_SYS64(type, base, lim, dpl, 1)
+
+/* Smaller system segment descriptor (LDT or TSS). */
+#define SEG_SYS64_SMALL(type, base, lim, dpl)                                  \
+        __SEG_SYS64(type, base, lim, dpl, 0)
+
+#define SEG_SYS_SMALL(type, base, lim, dpl) \
+        SEG_SYS64_SMALL(type, base, lim, dpl)
+
+/* 64 bit task state segment (AMD 2:12.2.5) */
+typedef struct taskstate {
+       uint32_t                                        ts_rsv1;        /* reserved / ignored */
+       uint64_t                                        ts_rsp0;        /* stack ptr in ring 0 */
+       uint64_t                                        ts_rsp1;        /* stack ptr in ring 1 */
+       uint64_t                                        ts_rsp2;        /* stack ptr in ring 2 */
+       uint64_t                                        ts_rsv2;        /* reserved / ignored */
+       uint64_t                                        ts_ist1;        /* IST stacks: unconditional rsp */
+       uint64_t                                        ts_ist2;        /* check AMD 2:8.9.4 for info */
+       uint64_t                                        ts_ist3;
+       uint64_t                                        ts_ist4;
+       uint64_t                                        ts_ist5;
+       uint64_t                                        ts_ist6;
+       uint64_t                                        ts_ist7;
+       uint64_t                                        ts_rsv3;        /* reserved / ignored */
+       uint16_t                                        ts_rsv4;        /* reserved / ignored */
+       uint16_t                                        ts_iobm;        /* IO base map (offset) */
 } taskstate_t;
 
-// Gate descriptors for interrupts and traps
+/* 64 bit gate descriptors for interrupts and traps */
 typedef struct Gatedesc {
-       unsigned gd_off_15_0 : 16;   // low 16 bits of offset in segment
-       unsigned gd_ss : 16;         // segment selector
-       unsigned gd_args : 5;        // # args, 0 for interrupt/trap gates
-       unsigned gd_rsv1 : 3;        // reserved(should be zero I guess)
-       unsigned gd_type : 4;        // type(STS_{TG,IG32,TG32})
-       unsigned gd_s : 1;           // must be 0 (system)
-       unsigned gd_dpl : 2;         // DPL - highest ring allowed to use this
-       unsigned gd_p : 1;           // Present
-       unsigned gd_off_31_16 : 16;  // high bits of offset in segment
+       unsigned gd_off_15_0 : 16;      /* low 16 bits of offset in segment */
+       unsigned gd_ss : 16;            /* segment selector */
+       unsigned gd_ist : 3;            /* interrupt stack table selector (0 = none) */
+       unsigned gd_rsv1 : 5;           /* ignored */
+       unsigned gd_type : 4;           /* type(STS_{TG,IG32,TG32}) */
+       unsigned gd_s : 1;                      /* must be 0 (system) */
+       unsigned gd_dpl : 2;            /* DPL - highest ring allowed to use this */
+       unsigned gd_p : 1;                      /* Present */
+       unsigned gd_off_31_16 : 16;     /* 16-31 bits of offset in segment */
+       unsigned gd_off_63_32;          /* top 32 bits of offset */
+       unsigned gd_rsv2;                       /* reserved / unsused */
 } gatedesc_t;
 
-// Set up a normal interrupt/trap gate descriptor.
-// - istrap: 1 for a trap (= exception) gate, 0 for an interrupt gate.
-//   - interrupt gates automatically disable interrupts (cli)
-// - sel: Code segment selector for interrupt/trap handler
-// - off: Offset in code segment for interrupt/trap handler
-// - dpl: Descriptor Privilege Level -
-//       the privilege level required for software to invoke
-//       this interrupt/trap gate explicitly using an int instruction.
-#define SETGATE(gate, istrap, sel, off, dpl)                   \
-{                                                              \
-       (gate).gd_off_15_0 = (uintptr_t) (off) & 0xffff;                \
-       (gate).gd_ss = (sel);                                   \
-       (gate).gd_args = 0;                                     \
-       (gate).gd_rsv1 = 0;                                     \
-       (gate).gd_type = (istrap) ? STS_TG32 : STS_IG32;        \
-       (gate).gd_s = 0;                                        \
-       (gate).gd_dpl = (dpl);                                  \
-       (gate).gd_p = 1;                                        \
-       (gate).gd_off_31_16 = (uintptr_t) (off) >> 16;          \
+/* Set up an IST-capable 64 bit interrupt/trap gate descriptor.  IST selects a
+ * stack pointer from the interrupt-stack table (in TSS) that will be loaded
+ * unconditionally when we hit this gate  - regardless of privelege change. */
+#define SETGATE64(gate, istrap, sel, off, dpl, ist)                            \
+{                                                                              \
+       (gate).gd_off_15_0 = (uintptr_t) (off) & 0xffff;                           \
+       (gate).gd_ss = (sel);                                                      \
+       (gate).gd_ist = (ist);                                                     \
+       (gate).gd_rsv1 = 0;                                                        \
+       (gate).gd_type = (istrap) ? STS_TG32 : STS_IG32;                           \
+       (gate).gd_s = 0;                                                           \
+       (gate).gd_dpl = (dpl);                                                     \
+       (gate).gd_p = 1;                                                           \
+       (gate).gd_off_31_16 = (uintptr_t) (off) >> 16;                             \
+       (gate).gd_off_63_32 = (uintptr_t) (off) >> 32;                             \
+       (gate).gd_rsv2 = 0;                                                        \
 }
 
-#define ROSETGATE(gate, istrap, sel, off, dpl)                 \
-{                                                              \
-       (gate).gd_off_15_0 = SINIT((uintptr_t) (off) & 0xffff);         \
-       (gate).gd_ss = SINIT(sel);                                      \
-       (gate).gd_args = SINIT(0);                                      \
-       (gate).gd_rsv1 = SINIT(0);                                      \
-       (gate).gd_type = SINIT((istrap) ? STS_TG32 : STS_IG32); \
-       (gate).gd_s = SINIT(0);                                 \
-       (gate).gd_dpl = SINIT(dpl);                                     \
-       (gate).gd_p = SINIT(1);                                 \
-       (gate).gd_off_31_16 = SINIT((uintptr_t) (off) >> 16);           \
-}
-
-// Set up a call gate descriptor.
-#define SETCALLGATE(gate, ss, off, dpl)                        \
-{                                                              \
-       (gate).gd_off_15_0 = (uintptr_t) (off) & 0xffff;                \
-       (gate).gd_ss = (ss);                                    \
-       (gate).gd_args = 0;                                     \
-       (gate).gd_rsv1 = 0;                                     \
-       (gate).gd_type = STS_CG32;                              \
-       (gate).gd_s = 0;                                        \
-       (gate).gd_dpl = (dpl);                                  \
-       (gate).gd_p = 1;                                        \
-       (gate).gd_off_31_16 = (uintptr_t) (off) >> 16;          \
-}
+/* Set up a normal, 64 bit interrupt/trap gate descriptor.
+ * - istrap: 1 for a trap (= exception) gate, 0 for an interrupt gate.
+ *   - interrupt gates automatically disable interrupts (cli)
+ * - sel: Code segment selector for interrupt/trap handler
+ * - off: Offset in code segment for interrupt/trap handler (address)
+ * - dpl: Descriptor Privilege Level -
+ *       the privilege level required for software to invoke
+ *       this interrupt/trap gate explicitly using an int instruction. */
+#define SETGATE(gate, istrap, sel, off, dpl)                                   \
+        SETGATE64(gate, istrap, sel, off, dpl, 0)
 
 // Pseudo-descriptors used for LGDT, LLDT and LIDT instructions.
 typedef struct Pseudodesc {
@@ -529,21 +495,17 @@ typedef struct Pseudodesc {
 #define STA_R          0x2         // Readable (executable segments)
 #define STA_A          0x1         // Accessed
 
-// System segment type bits
-#define STS_T16A       0x1         // Available 16-bit TSS
-#define STS_LDT                0x2         // Local Descriptor Table
-#define STS_T16B       0x3         // Busy 16-bit TSS
-#define STS_CG16       0x4         // 16-bit Call Gate
-#define STS_TG         0x5         // Task Gate / Coum Transmitions
-#define STS_IG16       0x6         // 16-bit Interrupt Gate
-#define STS_TG16       0x7         // 16-bit Trap Gate
-#define STS_T32A       0x9         // Available 32-bit TSS
-#define STS_T32B       0xB         // Busy 32-bit TSS
-#define STS_CG32       0xC         // 32-bit Call Gate
-#define STS_IG32       0xE         // 32-bit Interrupt Gate
-#define STS_TG32       0xF         // 32-bit Trap Gate
-
-#define SEG_COUNT      7               // Number of segments in the steady state
+/* System segment type bits.  All other types are reserved/illegal.  The '32' is
+ * mostly a legacy naming - the bits work for both 64 and 32. */
+#define STS_LDT                0x2             /* 64-bit Local Descriptor Table  */
+#define STS_T32A       0x9             /* Available 64-bit TSS */
+#define STS_T32B       0xB             /* Busy 64-bit TSS */
+#define STS_CG32       0xC             /* 64-bit Call Gate */
+#define STS_IG32       0xE             /* 64-bit Interrupt Gate */
+#define STS_TG32       0xF             /* 64-bit Trap Gate */
+
+#define SEG_COUNT      5               /* Number of GDT segments */
+/* TODO: Probably won't use this */
 #define LDT_SIZE       (8192 * sizeof(segdesc_t))
 
 #endif /* ROS_INC_ARCH_MMU64_H */
index 49579c1..eb94bdb 100644 (file)
@@ -245,12 +245,11 @@ uint32_t smp_main(void)
        asm volatile("lgdt %0" : : "m"(*my_gdt_pd));
 
        // Need to set the TSS so we know where to trap on this core
-       my_ts->ts_esp0 = my_stack_top;
-       my_ts->ts_ss0 = GD_KD;
+       x86_set_stacktop_tss(my_ts, my_stack_top);
        // Initialize the TSS field of my_gdt.
-       my_gdt[GD_TSS >> 3] = (segdesc_t)SEG16(STS_T32A, (uintptr_t)my_ts,
-                             sizeof(taskstate_t), 0);
-       my_gdt[GD_TSS >> 3].sd_s = 0;
+       syssegdesc_t *ts_slot = (syssegdesc_t*)&my_gdt[GD_TSS >> 3];
+       *ts_slot = (syssegdesc_t)SEG_SYS_SMALL(STS_T32A, (uintptr_t)my_ts,
+                                              sizeof(taskstate_t), 0);
        // Load the TSS
        ltr(GD_TSS);
 
index 7ae55e5..1c3430d 100644 (file)
 
 taskstate_t RO ts;
 
-/* Interrupt descriptor table.  (Must be built at run time because
- * shifted function addresses can't be represented in relocation records.)
- */
-// Aligned on an 8 byte boundary (SDM V3A 5-13)
-gatedesc_t __attribute__ ((aligned (8))) (RO idt)[256] = { { 0 } };
+/* Interrupt descriptor table.  64 bit needs 16 byte alignment (i think). */
+gatedesc_t __attribute__((aligned (16))) idt[256] = { { 0 } };
 pseudodesc_t idt_pd;
 
 /* global handler table, used by core0 (for now).  allows the registration
  * of functions to be called when servicing an interrupt.  other cores
- * can set up their own later.
- */
-#ifdef __IVY__
-#pragma cilnoremove("iht_lock")
-#endif
-spinlock_t iht_lock;
-handler_t TP(TV(t)) LCKD(&iht_lock) (RO interrupt_handlers)[NUM_INTERRUPT_HANDLERS];
+ * can set up their own later. */
+handler_t interrupt_handlers[NUM_INTERRUPT_HANDLERS];
 
 const char *x86_trapname(int trapno)
 {
@@ -80,9 +72,9 @@ const char *x86_trapname(int trapno)
  * and then the GDT.  Still, it's a pain. */
 void set_stack_top(uintptr_t stacktop)
 {
-       struct per_cpu_info *pcpu = &per_cpu_info[core_id()];
+       struct per_cpu_info *pcpui = &per_cpu_info[core_id()];
        /* No need to reload the task register, this takes effect immediately */
-       pcpu->tss->ts_esp0 = stacktop;
+       x86_set_stacktop_tss(pcpui->tss, stacktop);
        /* Also need to make sure sysenters come in correctly */
        x86_set_sysenter_stacktop(stacktop);
 }
@@ -95,7 +87,7 @@ uintptr_t get_stack_top(void)
        /* so we can check this in interrupt handlers (before smp_boot()) */
        if (!pcpui->tss)
                return ROUNDUP(read_sp(), PGSIZE);
-       stacktop = pcpui->tss->ts_esp0;
+       stacktop = x86_get_stacktop_tss(pcpui->tss);
        if (stacktop != ROUNDUP(read_sp(), PGSIZE))
                panic("Bad stacktop: %p esp one is %p\n", stacktop,
                      ROUNDUP(read_sp(), PGSIZE));
@@ -112,50 +104,49 @@ void send_nmi(uint32_t os_coreid)
 
 void idt_init(void)
 {
-       // This table is made in trapentry.S by each macro in that file.
-       // It is layed out such that the ith entry is the ith's traphandler's
-       // (uint32_t) trap addr, then (uint32_t) trap number
-       struct trapinfo { uintptr_t trapaddr; uint32_t trapnumber; };
-       extern struct trapinfo (BND(__this,trap_tbl_end) RO trap_tbl)[];
-       extern struct trapinfo (SNT RO trap_tbl_end)[];
+       /* This table is made in trapentry$BITS.S by each macro in that file.
+        * It is layed out such that the ith entry is the ith's traphandler's
+        * (uintptr_t) trap addr, then (uint32_t) trap number. */
+       struct trapinfo { uintptr_t trapaddr; uint32_t trapnumber; }
+              __attribute__((packed));
+       extern struct trapinfo trap_tbl[];
+       extern struct trapinfo trap_tbl_end[];
        int i, trap_tbl_size = trap_tbl_end - trap_tbl;
        extern void ISR_default(void);
 
-       // set all to default, to catch everything
-       for(i = 0; i < 256; i++)
-               ROSETGATE(idt[i], 0, GD_KT, &ISR_default, 0);
-
-       // set all entries that have real trap handlers
-       // we need to stop short of the last one, since the last is the default
-       // handler with a fake interrupt number (500) that is out of bounds of
-       // the idt[]
-       // if we set these to trap gates, be sure to handle the IRQs separately
-       // and we might need to break our pretty tables
-       for(i = 0; i < trap_tbl_size - 1; i++)
-               ROSETGATE(idt[trap_tbl[i].trapnumber], 0, GD_KT, trap_tbl[i].trapaddr, 0);
-
-       // turn on syscall handling and other user-accessible ints
-       // DPL 3 means this can be triggered by the int instruction
-       // STS_TG32 sets the IDT type to a Interrupt Gate (interrupts disabled)
+       /* set all to default, to catch everything */
+       for (i = 0; i < 256; i++)
+               SETGATE(idt[i], 0, GD_KT, &ISR_default, 0);
+
+       /* set all entries that have real trap handlers
+        * we need to stop short of the last one, since the last is the default
+        * handler with a fake interrupt number (500) that is out of bounds of
+        * the idt[] */
+       for (i = 0; i < trap_tbl_size - 1; i++)
+               SETGATE(idt[trap_tbl[i].trapnumber], 0, GD_KT, trap_tbl[i].trapaddr, 0);
+
+       /* turn on trap-based syscall handling and other user-accessible ints
+        * DPL 3 means this can be triggered by the int instruction
+        * STS_TG32 sets the IDT type to a Interrupt Gate (interrupts disabled) */
        idt[T_SYSCALL].gd_dpl = SINIT(3);
        idt[T_SYSCALL].gd_type = SINIT(STS_IG32);
        idt[T_BRKPT].gd_dpl = SINIT(3);
 
        /* Setup a TSS so that we get the right stack when we trap to the kernel. */
-       ts.ts_esp0 = (uintptr_t)bootstacktop;
-       ts.ts_ss0 = SINIT(GD_KD);
+       /* Note: we want 16 byte aligned kernel stack frames (AMD 2:8.9.3) */
+       x86_set_stacktop_tss(&ts, (uintptr_t)bootstacktop);
+
 #ifdef CONFIG_KTHREAD_POISON
        /* TODO: KTHR-STACK */
        uintptr_t *poison = (uintptr_t*)ROUNDDOWN(bootstacktop - 1, PGSIZE);
        *poison = 0xdeadbeef;
 #endif /* CONFIG_KTHREAD_POISON */
 
-       // Initialize the TSS field of the gdt.
-       SEG16ROINIT(gdt[GD_TSS >> 3], STS_T32A, &ts,
-                   sizeof(taskstate_t), 0);
-       //gdt[GD_TSS >> 3] = (segdesc_t)SEG16(STS_T32A, (uint32_t) (&ts),
-       //                                 sizeof(taskstate_t), 0);
-       gdt[GD_TSS >> 3].sd_s = SINIT(0);
+       /* Initialize the TSS field of the gdt.  The size of the TSS desc differs
+        * between 64 and 32 bit, hence the pointer acrobatics */
+       syssegdesc_t *ts_slot = (syssegdesc_t*)&gdt[GD_TSS >> 3];
+       *ts_slot = (syssegdesc_t)SEG_SYS_SMALL(STS_T32A, (uintptr_t)&ts,
+                                              sizeof(taskstate_t), 0);
 
        /* Init the IDT PD.  Need to do this before ltr for some reason.  (Doing
         * this between ltr and lidt causes the machine to reboot... */
@@ -477,7 +468,7 @@ void irq_handler(struct hw_trapframe *hw_tf)
 
        extern handler_wrapper_t (RO handler_wrappers)[NUM_HANDLER_WRAPPERS];
        // determine the interrupt handler table to use.  for now, pick the global
-       handler_t TP(TV(t)) LCKD(&iht_lock) * handler_tbl = interrupt_handlers;
+       handler_t *handler_tbl = interrupt_handlers;
        if (handler_tbl[hw_tf->tf_trapno].isr != 0)
                handler_tbl[hw_tf->tf_trapno].isr(hw_tf,
                                                  handler_tbl[hw_tf->tf_trapno].data);
index b3a840d..0d87fd9 100644 (file)
@@ -73,4 +73,15 @@ static inline long x86_get_sysenter_arg1(struct hw_trapframe *hw_tf)
        return hw_tf->tf_regs.reg_esi;
 }
 
+static inline uintptr_t x86_get_stacktop_tss(struct taskstate *tss)
+{
+       return tss->ts_esp0;
+}
+
+static inline void x86_set_stacktop_tss(struct taskstate *tss, uintptr_t top)
+{
+       tss->ts_esp0 = top;
+       tss->ts_ss0 = GD_KD;
+}
+
 #endif /* ROS_KERN_ARCH_TRAP32_H */
index 223455b..88e3476 100644 (file)
@@ -75,4 +75,14 @@ static inline long x86_get_sysenter_arg1(struct hw_trapframe *hw_tf)
        return hw_tf->tf_regs.reg_esi;
 }
 
+static inline uintptr_t x86_get_stacktop_tss(struct taskstate *tss)
+{
+       return tss->ts_rsp0;
+}
+
+static inline void x86_set_stacktop_tss(struct taskstate *tss, uintptr_t top)
+{
+       tss->ts_rsp0 = top;
+}
+
 #endif /* ROS_KERN_ARCH_TRAP64_H */
index b7847b2..bd32897 100644 (file)
@@ -29,11 +29,7 @@ typedef struct InterruptHandler {
        TV(t) data;
 } handler_t;
 
-#ifdef __IVY__
-#pragma cilnoremove("iht_lock")
-extern spinlock_t iht_lock;
-#endif
-extern handler_t LCKD(&iht_lock) (CT(NUM_INTERRUPT_HANDLERS) RO interrupt_handlers)[];
+extern handler_t interrupt_handlers[];
 
 void idt_init(void);
 void
index 8064e1a..e61eb10 100644 (file)
@@ -78,6 +78,7 @@ void kernel_init(multiboot_info_t *mboot_info)
        page_check();
        vfs_init();
        devfs_init();
+       idt_init();
 
 #ifdef CONFIG_X86_64
 monitor(0);
@@ -86,7 +87,6 @@ while (1)
        asm volatile("hlt");
 #endif
 
-       idt_init();
        kernel_msg_init();
        sysenter_init();
        timer_init();