x86_64: Per-cpu IDT
authorSepherosa Ziehau <sephe@dragonflybsd.org>
Sun, 18 Dec 2011 05:05:07 +0000 (13:05 +0800)
committerSepherosa Ziehau <sephe@dragonflybsd.org>
Sun, 18 Dec 2011 05:05:07 +0000 (13:05 +0800)
sys/cpu/x86_64/include/segments.h
sys/platform/pc64/apic/ioapic_abi.c
sys/platform/pc64/apic/lapic.c
sys/platform/pc64/icu/icu_abi.c
sys/platform/pc64/include/md_var.h
sys/platform/pc64/x86_64/machdep.c
sys/platform/pc64/x86_64/mp_machdep.c

index 0038930..a5d66a8 100644 (file)
@@ -260,7 +260,8 @@ struct region_descriptor {
 #ifdef _KERNEL
 extern struct user_segment_descriptor gdt[];
 extern struct soft_segment_descriptor gdt_segs[];
-extern struct gate_descriptor *idt;
+extern struct gate_descriptor idt_arr[MAXCPU][NIDT];
+extern struct region_descriptor r_idt_arr[];
 extern struct mtx dt_lock;
 
 void   lgdt(struct region_descriptor *rdp);
index c5239a9..49422cb 100644 (file)
@@ -715,8 +715,8 @@ ioapic_abi_setdefault(void)
        for (intr = 0; intr < IOAPIC_HWI_VECTORS; ++intr) {
                if (intr == IOAPIC_HWI_SYSCALL)
                        continue;
-               setidt(IDT_OFFSET + intr, ioapic_intr[intr], SDT_SYSIGT,
-                      SEL_KPL, 0);
+               setidt_global(IDT_OFFSET + intr, ioapic_intr[intr],
+                   SDT_SYSIGT, SEL_KPL, 0);
        }
 }
 
index 93b89dd..4ed8a6d 100644 (file)
@@ -112,24 +112,24 @@ lapic_init(boolean_t bsp)
         */
        if (bsp) {
                /* Install a 'Spurious INTerrupt' vector */
-               setidt(XSPURIOUSINT_OFFSET, Xspuriousint,
+               setidt_global(XSPURIOUSINT_OFFSET, Xspuriousint,
                    SDT_SYSIGT, SEL_KPL, 0);
 
                /* Install a timer vector */
-               setidt(XTIMER_OFFSET, Xtimer,
+               setidt_global(XTIMER_OFFSET, Xtimer,
                    SDT_SYSIGT, SEL_KPL, 0);
 
 #ifdef SMP
                /* Install an inter-CPU IPI for TLB invalidation */
-               setidt(XINVLTLB_OFFSET, Xinvltlb,
+               setidt_global(XINVLTLB_OFFSET, Xinvltlb,
                    SDT_SYSIGT, SEL_KPL, 0);
 
                /* Install an inter-CPU IPI for IPIQ messaging */
-               setidt(XIPIQ_OFFSET, Xipiq,
+               setidt_global(XIPIQ_OFFSET, Xipiq,
                    SDT_SYSIGT, SEL_KPL, 0);
 
                /* Install an inter-CPU IPI for CPU stop/restart */
-               setidt(XCPUSTOP_OFFSET, Xcpustop,
+               setidt_global(XCPUSTOP_OFFSET, Xcpustop,
                    SDT_SYSIGT, SEL_KPL, 0);
 #endif
        }
index cdf327e..7d9ff0c 100644 (file)
@@ -287,8 +287,8 @@ icu_abi_setdefault(void)
        for (intr = 0; intr < ICU_HWI_VECTORS; ++intr) {
                if (intr == ICU_IRQ_SLAVE)
                        continue;
-               setidt(IDT_OFFSET + intr, icu_intr[intr], SDT_SYSIGT,
-                      SEL_KPL, 0);
+               setidt_global(IDT_OFFSET + intr, icu_intr[intr],
+                   SDT_SYSIGT, SEL_KPL, 0);
        }
 }
 
index 3c76da4..7bc3747 100644 (file)
@@ -81,7 +81,8 @@ void  enable_sse(void);
 void   fillw(int /*u_short*/ pat, void *base, size_t cnt);
 void   pagezero(void *addr);
 void   pagecopy(void *from, void *to);
-void   setidt(int idx, alias_for_inthand_t *func, int typ, int dpl, int ist);
+void   setidt_global(int idx, alias_for_inthand_t *func,
+           int typ, int dpl, int ist);
 int    user_dbreg_trap(void);
 void   fpstate_drop(struct thread *td);
 
index 8adeaf6..e8e046d 100644 (file)
@@ -1174,14 +1174,14 @@ SYSCTL_ULONG(_machdep, OID_AUTO, guessed_bootdev,
 
 int _default_ldt;
 struct user_segment_descriptor gdt[NGDT * MAXCPU];     /* global descriptor table */
-static struct gate_descriptor idt0[NIDT];
-struct gate_descriptor *idt = &idt0[0];        /* interrupt descriptor table */
+struct gate_descriptor idt_arr[MAXCPU][NIDT];
 #if JG
 union descriptor ldt[NLDT];            /* local descriptor table */
 #endif
 
 /* table descriptors - used to load tables by cpu */
-struct region_descriptor r_gdt, r_idt;
+struct region_descriptor r_gdt;
+struct region_descriptor r_idt_arr[MAXCPU];
 
 /* JG proc0paddr is a virtual address */
 void *proc0paddr;
@@ -1276,19 +1276,22 @@ struct soft_segment_descriptor gdt_segs[] = {
 };
 
 void
-setidt(int idx, inthand_t *func, int typ, int dpl, int ist)
+setidt_global(int idx, inthand_t *func, int typ, int dpl, int ist)
 {
-       struct gate_descriptor *ip;
-
-       ip = idt + idx;
-       ip->gd_looffset = (uintptr_t)func;
-       ip->gd_selector = GSEL(GCODE_SEL, SEL_KPL);
-       ip->gd_ist = ist;
-       ip->gd_xx = 0;
-       ip->gd_type = typ;
-       ip->gd_dpl = dpl;
-       ip->gd_p = 1;
-       ip->gd_hioffset = ((uintptr_t)func)>>16 ;
+       int cpu;
+
+       for (cpu = 0; cpu < MAXCPU; ++cpu) {
+               struct gate_descriptor *ip = &idt_arr[cpu][idx];
+
+               ip->gd_looffset = (uintptr_t)func;
+               ip->gd_selector = GSEL(GCODE_SEL, SEL_KPL);
+               ip->gd_ist = ist;
+               ip->gd_xx = 0;
+               ip->gd_type = typ;
+               ip->gd_dpl = dpl;
+               ip->gd_p = 1;
+               ip->gd_hioffset = ((uintptr_t)func)>>16 ;
+       }
 }
 
 #define        IDTVEC(name)    __CONCAT(X,name)
@@ -1718,7 +1721,7 @@ u_int64_t
 hammer_time(u_int64_t modulep, u_int64_t physfree)
 {
        caddr_t kmdp;
-       int gsel_tss, x;
+       int gsel_tss, x, cpu;
 #if JG
        int metadata_missing, off;
 #endif
@@ -1822,30 +1825,33 @@ hammer_time(u_int64_t modulep, u_int64_t physfree)
 
        /* exceptions */
        for (x = 0; x < NIDT; x++)
-               setidt(x, &IDTVEC(rsvd), SDT_SYSIGT, SEL_KPL, 0);
-       setidt(IDT_DE, &IDTVEC(div),  SDT_SYSIGT, SEL_KPL, 0);
-       setidt(IDT_DB, &IDTVEC(dbg),  SDT_SYSIGT, SEL_KPL, 0);
-       setidt(IDT_NMI, &IDTVEC(nmi),  SDT_SYSIGT, SEL_KPL, 1);
-       setidt(IDT_BP, &IDTVEC(bpt),  SDT_SYSIGT, SEL_UPL, 0);
-       setidt(IDT_OF, &IDTVEC(ofl),  SDT_SYSIGT, SEL_KPL, 0);
-       setidt(IDT_BR, &IDTVEC(bnd),  SDT_SYSIGT, SEL_KPL, 0);
-       setidt(IDT_UD, &IDTVEC(ill),  SDT_SYSIGT, SEL_KPL, 0);
-       setidt(IDT_NM, &IDTVEC(dna),  SDT_SYSIGT, SEL_KPL, 0);
-       setidt(IDT_DF, &IDTVEC(dblfault), SDT_SYSIGT, SEL_KPL, 1);
-       setidt(IDT_FPUGP, &IDTVEC(fpusegm),  SDT_SYSIGT, SEL_KPL, 0);
-       setidt(IDT_TS, &IDTVEC(tss),  SDT_SYSIGT, SEL_KPL, 0);
-       setidt(IDT_NP, &IDTVEC(missing),  SDT_SYSIGT, SEL_KPL, 0);
-       setidt(IDT_SS, &IDTVEC(stk),  SDT_SYSIGT, SEL_KPL, 0);
-       setidt(IDT_GP, &IDTVEC(prot),  SDT_SYSIGT, SEL_KPL, 0);
-       setidt(IDT_PF, &IDTVEC(page),  SDT_SYSIGT, SEL_KPL, 0);
-       setidt(IDT_MF, &IDTVEC(fpu),  SDT_SYSIGT, SEL_KPL, 0);
-       setidt(IDT_AC, &IDTVEC(align), SDT_SYSIGT, SEL_KPL, 0);
-       setidt(IDT_MC, &IDTVEC(mchk),  SDT_SYSIGT, SEL_KPL, 0);
-       setidt(IDT_XF, &IDTVEC(xmm), SDT_SYSIGT, SEL_KPL, 0);
-
-       r_idt.rd_limit = sizeof(idt0) - 1;
-       r_idt.rd_base = (long) idt;
-       lidt(&r_idt);
+               setidt_global(x, &IDTVEC(rsvd), SDT_SYSIGT, SEL_KPL, 0);
+       setidt_global(IDT_DE, &IDTVEC(div),  SDT_SYSIGT, SEL_KPL, 0);
+       setidt_global(IDT_DB, &IDTVEC(dbg),  SDT_SYSIGT, SEL_KPL, 0);
+       setidt_global(IDT_NMI, &IDTVEC(nmi),  SDT_SYSIGT, SEL_KPL, 1);
+       setidt_global(IDT_BP, &IDTVEC(bpt),  SDT_SYSIGT, SEL_UPL, 0);
+       setidt_global(IDT_OF, &IDTVEC(ofl),  SDT_SYSIGT, SEL_KPL, 0);
+       setidt_global(IDT_BR, &IDTVEC(bnd),  SDT_SYSIGT, SEL_KPL, 0);
+       setidt_global(IDT_UD, &IDTVEC(ill),  SDT_SYSIGT, SEL_KPL, 0);
+       setidt_global(IDT_NM, &IDTVEC(dna),  SDT_SYSIGT, SEL_KPL, 0);
+       setidt_global(IDT_DF, &IDTVEC(dblfault), SDT_SYSIGT, SEL_KPL, 1);
+       setidt_global(IDT_FPUGP, &IDTVEC(fpusegm),  SDT_SYSIGT, SEL_KPL, 0);
+       setidt_global(IDT_TS, &IDTVEC(tss),  SDT_SYSIGT, SEL_KPL, 0);
+       setidt_global(IDT_NP, &IDTVEC(missing),  SDT_SYSIGT, SEL_KPL, 0);
+       setidt_global(IDT_SS, &IDTVEC(stk),  SDT_SYSIGT, SEL_KPL, 0);
+       setidt_global(IDT_GP, &IDTVEC(prot),  SDT_SYSIGT, SEL_KPL, 0);
+       setidt_global(IDT_PF, &IDTVEC(page),  SDT_SYSIGT, SEL_KPL, 0);
+       setidt_global(IDT_MF, &IDTVEC(fpu),  SDT_SYSIGT, SEL_KPL, 0);
+       setidt_global(IDT_AC, &IDTVEC(align), SDT_SYSIGT, SEL_KPL, 0);
+       setidt_global(IDT_MC, &IDTVEC(mchk),  SDT_SYSIGT, SEL_KPL, 0);
+       setidt_global(IDT_XF, &IDTVEC(xmm), SDT_SYSIGT, SEL_KPL, 0);
+
+       for (cpu = 0; cpu < MAXCPU; ++cpu) {
+               r_idt_arr[cpu].rd_limit = sizeof(idt_arr[cpu]) - 1;
+               r_idt_arr[cpu].rd_base = (long) &idt_arr[cpu][0];
+       }
+
+       lidt(&r_idt_arr[0]);
 
        /*
         * Initialize the console before we print anything out.
index e36fa99..74e21d8 100644 (file)
 int    current_postcode;
 
 /** XXX FIXME: what system files declare these??? */
-extern struct region_descriptor r_gdt, r_idt;
+extern struct region_descriptor r_gdt;
 
 extern int nkpt;
 extern int naps;
@@ -247,7 +247,7 @@ init_secondary(void)
        wrmsr(MSR_GSBASE, (u_int64_t)ps);
        wrmsr(MSR_KGSBASE, 0);          /* XXX User value while we're in the kernel */
 
-       lidt(&r_idt);
+       lidt(&r_idt_arr[mdcpu->mi.gd_cpuid]);
 
 #if 0
        lldt(_default_ldt);