Enabling X2APIC
authorGanShun <ganshun@gmail.com>
Thu, 17 Dec 2015 01:36:39 +0000 (17:36 -0800)
committerBarret Rhoden <brho@cs.berkeley.edu>
Fri, 26 Feb 2016 21:09:59 +0000 (16:09 -0500)
Changing all offsets from the old XAPIC mode to the newer X2APIC mode and
removing lapic_wait_to_send. All interaction with the X2APIC is done with
apicrput, apicrget or apicsendipi. Removed memory allocation in pmap64.c
and value check in check_sym_val

Signed-off-by: GanShun <ganshun@gmail.com>
[ removed some debugging comments, fixed pb_ktest ]
Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
kern/arch/x86/apic.c
kern/arch/x86/apic.h
kern/arch/x86/apic9.c
kern/arch/x86/perfmon.c
kern/arch/x86/pmap64.c
kern/arch/x86/ros/mmu64.h
kern/arch/x86/ros/msr-index.h
kern/arch/x86/smp.c
kern/arch/x86/time.c
kern/arch/x86/trapentry64.S
kern/src/ktest/pb_ktests.c

index b0550e7..e212843 100644 (file)
@@ -25,7 +25,7 @@ bool lapic_check_spurious(int trap_nr)
         * or IOAPIC RTE), since the handlers don't send an EOI.  However, our check
         * here allows us to use the vector since we can tell the diff btw a
         * spurious and a real IRQ. */
-       assert(IdtLAPIC_SPURIOUS == (read_mmreg32(LAPIC_SPURIOUS) & 0xff));
+       assert(IdtLAPIC_SPURIOUS == (apicrget(MSR_LAPIC_SPURIOUS) & 0xff));
        /* Note the lapic's vectors are not shifted by an offset. */
        if ((trap_nr == IdtLAPIC_SPURIOUS) &&
             !lapic_get_isr_bit(IdtLAPIC_SPURIOUS)) {
@@ -45,11 +45,11 @@ void lapic_print_isr(void)
        printk("LAPIC ISR on core %d\n--------------\n", core_id());
        for (int i = 7; i >= 0; i--)
                printk("%3d-%3d: %p\n", (i + 1) * 32 - 1, i * 32,
-                      *(uint32_t*)(LAPIC_ISR + i * 0x10));
+                       apicrget(MSR_LAPIC_ISR_START + i));
        printk("LAPIC IRR on core %d\n--------------\n", core_id());
        for (int i = 7; i >= 0; i--)
                printk("%3d-%3d: %p\n", (i + 1) * 32 - 1, i * 32,
-                      *(uint32_t*)(LAPIC_IRR + i * 0x10));
+                       apicrget(MSR_LAPIC_IRR_START + i));
 }
 
 /* Returns TRUE if the bit 'vector' is set in the LAPIC ISR or IRR (whatever you
@@ -58,18 +58,19 @@ void lapic_print_isr(void)
 static bool __lapic_get_isrr_bit(unsigned long base, uint8_t vector)
 {
        int which_reg = vector >> 5;    /* 32 bits per reg */
-       uintptr_t lapic_reg = base + which_reg * 0x10;  /* offset 16 */
-       return (read_mmreg32(lapic_reg) & (1 << (vector % 32)) ? 1 : 0);
+       uintptr_t lapic_reg = base + which_reg;
+
+       return (apicrget(lapic_reg) & (1 << (vector % 32)) ? 1 : 0);
 }
 
 bool lapic_get_isr_bit(uint8_t vector)
 {
-       return __lapic_get_isrr_bit(LAPIC_ISR, vector);
+       return __lapic_get_isrr_bit(MSR_LAPIC_ISR_START, vector);
 }
 
 bool lapic_get_irr_bit(uint8_t vector)
 {
-       return __lapic_get_isrr_bit(LAPIC_IRR, vector);
+       return __lapic_get_isrr_bit(MSR_LAPIC_IRR_START, vector);
 }
 
 void lapic_mask_irq(struct irq_handler *unused, int apic_vector)
@@ -79,8 +80,8 @@ void lapic_mask_irq(struct irq_handler *unused, int apic_vector)
                warn("Bad apic vector %d\n", apic_vector);
                return;
        }
-       mm_reg = LAPIC_BASE + (apic_vector - IdtLAPIC) * 0x10;
-       write_mmreg32(mm_reg, read_mmreg32(mm_reg) | LAPIC_LVT_MASK);
+       mm_reg = MSR_LAPIC_LVT_TIMER + (apic_vector - IdtLAPIC);
+       apicrput(mm_reg, apicrget(mm_reg) | LAPIC_LVT_MASK);
 }
 
 void lapic_unmask_irq(struct irq_handler *unused, int apic_vector)
@@ -90,8 +91,8 @@ void lapic_unmask_irq(struct irq_handler *unused, int apic_vector)
                warn("Bad apic vector %d\n", apic_vector);
                return;
        }
-       mm_reg = LAPIC_BASE + 0x320 + (apic_vector - IdtLAPIC) * 0x10;
-       write_mmreg32(mm_reg, read_mmreg32(mm_reg) & ~LAPIC_LVT_MASK);
+       mm_reg = MSR_LAPIC_LVT_TIMER + (apic_vector - IdtLAPIC);
+       apicrput(mm_reg, apicrget(mm_reg) & ~LAPIC_LVT_MASK);
 }
 
 /* This works for any interrupt that goes through the LAPIC, but not things like
@@ -119,15 +120,16 @@ void __lapic_set_timer(uint32_t ticks, uint8_t vec, bool periodic, uint8_t div)
        periodic = TRUE;
 #endif
        // clears bottom bit and then set divider
-       write_mmreg32(LAPIC_TIMER_DIVIDE, (read_mmreg32(LAPIC_TIMER_DIVIDE) &~0xf) |
-                     (div & 0xf));
+       apicrput(MSR_LAPIC_DIVIDE_CONFIG_REG,
+                (apicrget(MSR_LAPIC_DIVIDE_CONFIG_REG) & ~0xf) | (div & 0xf));
        // set LVT with interrupt handling information.  also unmasks.
-       write_mmreg32(LAPIC_LVT_TIMER, vec | (periodic << 17));
-       write_mmreg32(LAPIC_TIMER_INIT, ticks);
+       apicrput(MSR_LAPIC_LVT_TIMER, vec | (periodic << 17));
+       apicrput(MSR_LAPIC_INITIAL_COUNT, ticks);
        // For debugging when we expand this
-       //cprintf("LAPIC LVT Timer: 0x%08x\n", read_mmreg32(LAPIC_LVT_TIMER));
-       //cprintf("LAPIC Init Count: 0x%08x\n", read_mmreg32(LAPIC_TIMER_INIT));
-       //cprintf("LAPIC Current Count: 0x%08x\n", read_mmreg32(LAPIC_TIMER_CURRENT));
+       //cprintf("LAPIC LVT Timer: 0x%08x\n", apicrget(MSR_LAPIC_LVT_TIMER));
+       //cprintf("LAPIC Init Count: 0x%08x\n", apicrget(MSR_LAPIC_INITIAL_COUNT));
+       //cprintf("LAPIC Current Count: 0x%08x\n",
+       //        apicrget(MSR_LAPIC_CURRENT_COUNT));
 }
 
 void lapic_set_timer(uint32_t usec, bool periodic)
index 813a373..fc0fd97 100644 (file)
@@ -6,7 +6,7 @@
 
 #pragma once
 
-/* 
+/*
  * Functions and definitions for dealing with the APIC and PIC, specific to
  * Intel.  Does not handle an x2APIC.
  */
@@ -15,6 +15,7 @@
 #include <ros/trapframe.h>
 #include <atomic.h>
 #include <endian.h>
+#include <arch/ros/msr-index.h>
 
 // Local APIC
 /* PBASE is the physical address.  It is mapped in at the VADDR LAPIC_BASE.
  * memory.  We can move the PBASE, but we're limited to 32 bit (physical)
  * addresses. */
 #define LAPIC_PBASE                                    0xfee00000      /* default *physical* address */
-#define LAPIC_EOI                                      (LAPIC_BASE + 0x0b0)
-#define LAPIC_SPURIOUS                         (LAPIC_BASE + 0x0f0)
-#define LAPIC_VERSION                          (LAPIC_BASE + 0x030)
-#define LAPIC_ERROR                                    (LAPIC_BASE + 0x280)
-#define LAPIC_ID                                       (LAPIC_BASE + 0x020)
-#define LAPIC_LOGICAL_ID                       (LAPIC_BASE + 0x0d0)
-// LAPIC Local Vector Table
-#define LAPIC_LVT_TIMER                                (LAPIC_BASE + 0x320)
-#define LAPIC_LVT_THERMAL                      (LAPIC_BASE + 0x330)
-#define LAPIC_LVT_PERFMON                      (LAPIC_BASE + 0x340)
-#define LAPIC_LVT_LINT0                                (LAPIC_BASE + 0x350)
-#define LAPIC_LVT_LINT1                                (LAPIC_BASE + 0x360)
-#define LAPIC_LVT_ERROR                                (LAPIC_BASE + 0x370)
-#define LAPIC_LVT_MASK                         0x00010000
-// LAPIC Timer
-#define LAPIC_TIMER_INIT                       (LAPIC_BASE + 0x380)
-#define LAPIC_TIMER_CURRENT                    (LAPIC_BASE + 0x390)
-#define LAPIC_TIMER_DIVIDE                     (LAPIC_BASE + 0x3e0)
+#define LAPIC_LVT_MASK                                 0x00010000
+
 /* Quick note on the divisor.  The LAPIC timer ticks once per divisor-bus ticks
  * (system bus or APIC bus, depending on the model).  Ex: A divisor of 128 means
  * 128 bus ticks results in 1 timer tick.  The divisor increases the time range
 #define LAPIC_TIMER_DIVISOR_BITS       0x8     /* Div = 32 */
 
 // IPI Interrupt Command Register
-#define LAPIC_IPI_ICR_LOWER                    (LAPIC_BASE + 0x300)
-#define LAPIC_IPI_ICR_UPPER                    (LAPIC_BASE + 0x310)
+#define LAPIC_IPI_ICR_LOWER                            0x30
+#define LAPIC_IPI_ICR_UPPER                            0x31
 /* Interrupts being serviced (in-service) and pending (interrupt request reg).
  * Note these registers are not normal bitmaps, but instead are 8 separate
  * 32-bit registers, spaced/aligned on 16 byte boundaries in the LAPIC address
  * space. */
-#define LAPIC_ISR                                      (LAPIC_BASE + 0x100)
-#define LAPIC_IRR                                      (LAPIC_BASE + 0x200)
+#define LAPIC_ISR                                      0x10
+#define LAPIC_IRR                                      0x20
+#define LAPIC_DFR                                      0x0e
 
 struct irq_handler;    /* include loops */
 
@@ -77,6 +63,11 @@ void lapic_set_timer(uint32_t usec, bool periodic);
 uint32_t lapic_get_default_id(void);
 int apiconline(void);
 void handle_lapic_error(struct hw_trapframe *hw_tf, void *data);
+uint32_t apicrget(uint64_t r);
+void apicrput(uint64_t r, uint32_t data);
+void apicsendipi(uint64_t data);
+void apic_isr_dump(void);
+void apic_irr_dump(void);
 
 static inline void lapic_send_eoi(int unused);
 static inline uint32_t lapic_get_version(void);
@@ -86,7 +77,6 @@ static inline uint8_t lapic_get_logid(void);
 static inline void lapic_disable_timer(void);
 static inline void lapic_disable(void);
 static inline void lapic_enable(void);
-static inline void lapic_wait_to_send(void);
 static inline void send_init_ipi(void);
 static inline void send_startup_ipi(uint8_t vector);
 static inline void send_self_ipi(uint8_t vector);
@@ -98,39 +88,39 @@ static inline void __send_nmi(uint8_t hw_coreid);
 
 /* XXX: remove these */
 #define mask_lapic_lvt(entry) \
-       write_mmreg32(entry, read_mmreg32(entry) | LAPIC_LVT_MASK)
+       apicrput(entry, apicrget(entry) | LAPIC_LVT_MASK)
 #define unmask_lapic_lvt(entry) \
-       write_mmreg32(entry, read_mmreg32(entry) & ~LAPIC_LVT_MASK)
+       apicrput(entry, apicrget(entry) & ~LAPIC_LVT_MASK)
 
 static inline void lapic_send_eoi(int unused)
 {
-       write_mmreg32(LAPIC_EOI, 0);
+       apicrput(MSR_LAPIC_EOI, 0);
 }
 
 static inline uint32_t lapic_get_version(void)
 {
-       return read_mmreg32(LAPIC_VERSION);
+       return apicrget(MSR_LAPIC_VERSION);
 }
 
 static inline uint32_t lapic_get_error(void)
 {
-       write_mmreg32(LAPIC_ERROR, 0xdeadbeef);
-       return read_mmreg32(LAPIC_ERROR);
+       apicrput(MSR_LAPIC_ESR, 0xdeadbeef);
+       return apicrget(MSR_LAPIC_ESR);
 }
 
 static inline uint32_t lapic_get_id(void)
 {
-       return read_mmreg32(LAPIC_ID) >> 24;
+       return apicrget(MSR_LAPIC_ID);
 }
 
 static inline uint8_t lapic_get_logid(void)
 {
-       return read_mmreg32(LAPIC_LOGICAL_ID) >> 24;
+       return apicrget(MSR_LAPIC_LDR);
 }
 
 static inline void lapic_disable_timer(void)
 {
-       write_mmreg32(LAPIC_LVT_TIMER, 0);
+       apicrput(MSR_LAPIC_LVT_TIMER, 0);
 }
 
 /* There are a couple ways to do it.  The MSR route doesn't seem to work
@@ -138,75 +128,55 @@ static inline void lapic_disable_timer(void)
  */
 static inline void lapic_disable(void)
 {
-       write_mmreg32(LAPIC_SPURIOUS, read_mmreg32(LAPIC_SPURIOUS) & 0xffffefff);
+       apicrput(MSR_LAPIC_SPURIOUS, apicrget(MSR_LAPIC_SPURIOUS) & 0xffffefff);
        //write_msr(IA32_APIC_BASE, read_msr(IA32_APIC_BASE) & ~MSR_APIC_ENABLE);
 }
 
-/* Spins until previous IPIs are delivered.  Not sure if we want it inlined
- * Also not sure when we really need to do this. 
- */
-static inline void lapic_wait_to_send(void)
-{
-       while (read_mmreg32(LAPIC_IPI_ICR_LOWER) & 0x1000)
-               __cpu_relax();
-}
-
 static inline void lapic_enable(void)
 {
-       write_mmreg32(LAPIC_SPURIOUS, read_mmreg32(LAPIC_SPURIOUS) | 0x00000100);
+       apicrput(MSR_LAPIC_SPURIOUS, apicrget(MSR_LAPIC_SPURIOUS) | 0x00000100);
 }
 
 static inline void send_init_ipi(void)
 {
-       write_mmreg32(LAPIC_IPI_ICR_LOWER, 0x000c4500);
-       lapic_wait_to_send();
+       apicsendipi(0xFFFFFFFF000c4500);
 }
 
 static inline void send_startup_ipi(uint8_t vector)
 {
-       write_mmreg32(LAPIC_IPI_ICR_LOWER, 0x000c4600 | vector);
-       lapic_wait_to_send();
+       apicsendipi(0xFFFFFFFF000c4600ULL | vector);
 }
 
 static inline void send_self_ipi(uint8_t vector)
 {
-       write_mmreg32(LAPIC_IPI_ICR_LOWER, 0x00044000 | vector);
-       lapic_wait_to_send();
+       apicrput(MSR_LAPIC_SELF_IPI, 0x00000000 | vector);
 }
 
 static inline void send_broadcast_ipi(uint8_t vector)
 {
-       write_mmreg32(LAPIC_IPI_ICR_LOWER, 0x00084000 | vector);
-       lapic_wait_to_send();
+       apicsendipi(0xFFFFFFFF00084000ULL | vector);
 }
 
 static inline void send_all_others_ipi(uint8_t vector)
 {
-       write_mmreg32(LAPIC_IPI_ICR_LOWER, 0x000c4000 | vector);
-       lapic_wait_to_send();
+       apicsendipi(0xFFFFFFFF000c4000ULL | vector);
 }
 
 static inline void __send_ipi(uint8_t hw_coreid, uint8_t vector)
 {
-       write_mmreg32(LAPIC_IPI_ICR_UPPER, hw_coreid << 24);
-       write_mmreg32(LAPIC_IPI_ICR_LOWER, 0x00004000 | vector);
-       lapic_wait_to_send();
+       apicsendipi(((uint64_t)hw_coreid << 32) | 0x00004000 | vector);
 }
 
 static inline void send_group_ipi(uint8_t hw_groupid, uint8_t vector)
 {
-       write_mmreg32(LAPIC_IPI_ICR_UPPER, hw_groupid << 24);
-       write_mmreg32(LAPIC_IPI_ICR_LOWER, 0x00004800 | vector);
-       lapic_wait_to_send();
+       apicsendipi(((uint64_t)hw_groupid << 32) | 0x00004800 | vector);
 }
 
 static inline void __send_nmi(uint8_t hw_coreid)
 {
        if (hw_coreid == 255)
                return;
-       write_mmreg32(LAPIC_IPI_ICR_UPPER, hw_coreid << 24);
-       write_mmreg32(LAPIC_IPI_ICR_LOWER, 0x00004400);
-       lapic_wait_to_send();
+       apicsendipi(((uint64_t)hw_coreid << 32) | 0x00004400);
 }
 
 /* To change the LAPIC Base (not recommended):
@@ -215,7 +185,7 @@ static inline void __send_nmi(uint8_t hw_coreid)
        write_msr(IA32_APIC_BASE, msr_val);
 */
 
-/* 
+/*
  * This file is part of the UCB release of Plan 9. It is subject to the license
  * terms in the LICENSE file found in the top-level directory of this
  * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
index d03d0d6..658576f 100644 (file)
 #include <arch/io.h>
 #include <trap.h>
 
-enum {                                                 /* Local APIC registers */
-       Id = 0x0020,                            /* Identification */
-       Ver = 0x0030,   /* Version */
-       Tp = 0x0080,    /* Task Priority */
-       Ap = 0x0090,    /* Arbitration Priority */
-       Pp = 0x00a0,    /* Processor Priority */
-       Eoi = 0x00b0,   /* EOI */
-       Ld = 0x00d0,    /* Logical Destination */
-       Df = 0x00e0,    /* Destination Format */
-       Siv = 0x00f0,   /* Spurious Interrupt Vector */
-       Is = 0x0100,    /* Interrupt Status (8) */
-       Tm = 0x0180,    /* Trigger Mode (8) */
-       Ir = 0x0200,    /* Interrupt Request (8) */
-       Es = 0x0280,    /* Error Status */
-       Iclo = 0x0300,  /* Interrupt Command */
-       Ichi = 0x0310,  /* Interrupt Command [63:32] */
-       Lvt0 = 0x0320,  /* Local Vector Table 0 */
-       Lvt5 = 0x0330,  /* Local Vector Table 5 */
-       Lvt4 = 0x0340,  /* Local Vector Table 4 */
-       Lvt1 = 0x0350,  /* Local Vector Table 1 */
-       Lvt2 = 0x0360,  /* Local Vector Table 2 */
-       Lvt3 = 0x0370,  /* Local Vector Table 3 */
-       Tic = 0x0380,   /* Timer Initial Count */
-       Tcc = 0x0390,   /* Timer Current Count */
-       Tdc = 0x03e0,   /* Timer Divide Configuration */
-
-       Tlvt = Lvt0,    /* Timer */
-       Lint0 = Lvt1,   /* Local Interrupt 0 */
-       Lint1 = Lvt2,   /* Local Interrupt 1 */
-       Elvt = Lvt3,    /* Error */
-       Pclvt = Lvt4,   /* Performance Counter */
-       Tslvt = Lvt5,   /* Thermal Sensor */
-};
-
 static char *apicregnames[] = {
-       [Id] "Identification",
-       [Ver] "Version",
-       [Tp] "Task Priority",
-       [Ap] "Arbitration Priority",
-       [Pp] "Processor Priority",
-       [Eoi] "EOI",
-       [Ld] "Logical Destination",
-       [Df] "Destination Format",
-       [Siv] "Spurious Interrupt Vector",
-       [Is] "Interrupt Status (8)",
-       [Tm] "Trigger Mode (8)",
-       [Ir] "Interrupt Request (8)",
-       [Es] "Error Status",
-       [Iclo] "Interrupt Command",
-       [Ichi] "Interrupt Command [63:32]",
-       [Lvt0] "Local Vector Table 0",
-       [Lvt5] "Local Vector Table 5",
-       [Lvt4] "Local Vector Table 4",
-       [Lvt1] "Local Vector Table 1",
-       [Lvt2] "Local Vector Table 2",
-       [Lvt3] "Local Vector Table 3",
-       [Tic] "Timer Initial Count",
-       [Tcc] "Timer Current Count",
-       [Tdc] "Timer Divide Configuration",
-
-       [Tlvt] "Timer",
-       [Lint0] "Local Interrupt 0",
-       [Lint1] "Local Interrupt 1",
-       [Elvt] "Error",
-       [Pclvt] "Performance Counter",
-       [Tslvt] "Thermal Sensor",
+       [MSR_LAPIC_ID] "Identification",
+       [MSR_LAPIC_VERSION] "Version",
+       [MSR_LAPIC_TPR] "Task Priority",
+//     [Ap] "Arbitration Priority",
+       [MSR_LAPIC_PPR] "Processor Priority",
+       [MSR_LAPIC_EOI] "EOI",
+       [MSR_LAPIC_LDR] "Logical Destination",
+       [MSR_LAPIC_SPURIOUS] "Spurious Interrupt Vector",
+       [MSR_LAPIC_ISR_START] "Interrupt Status (8)",
+       [MSR_LAPIC_TMR_START] "Trigger Mode (8)",
+       [MSR_LAPIC_IRR_START] "Interrupt Request (8)",
+       [MSR_LAPIC_ESR] "Error Status",
+       [MSR_LAPIC_ICR] "Interrupt Command",
+       [MSR_LAPIC_INITIAL_COUNT] "Timer Initial Count",
+       [MSR_LAPIC_CURRENT_COUNT] "Timer Current Count",
+       [MSR_LAPIC_DIVIDE_CONFIG_REG] "Timer Divide Configuration",
+
+       [MSR_LAPIC_LVT_TIMER] "Timer",
+       [MSR_LAPIC_LVT_LINT0] "Local Interrupt 0",
+       [MSR_LAPIC_LVT_LINT1] "Local Interrupt 1",
+       [MSR_LAPIC_LVT_ERROR_REG] "Error",
+       [MSR_LAPIC_LVT_PERFMON] "Performance Counter",
+       [MSR_LAPIC_LVT_THERMAL] "Thermal Sensor",
 };
 
 enum {                                                 /* Siv */
@@ -113,31 +71,89 @@ enum {                                                     /* Tdc */
 
 static uintptr_t apicbase;
 static int apmachno = 1;
+static uint32_t apicr310;
 
 struct apic xlapic[Napic];
 
-static uint32_t apicrget(int r)
+static void __apic_ir_dump(uint64_t r);
+
+static void __apic_ir_dump(uint64_t r)
 {
+       int i;
        uint32_t val;
-       if (!apicbase)
-               panic("apicrget: no apic");
-       val = read_mmreg32(apicbase + r);
+
+       if (r != MSR_LAPIC_ISR_START && r != MSR_LAPIC_IRR_START &&
+           r != MSR_LAPIC_TMR_START)
+               panic("Invalid register dump offset!");
+
+       for (i = 7; i >= 0; i--) {
+               val = apicrget(r+i);
+               if (val) {
+                       printk("Register at range (%d,%d]: 0x%08x\n", ((i+1)*32),
+                              i*32, val);
+               }
+       }
+}
+void apic_isr_dump(void)
+{
+       printk("ISR DUMP\n");
+       __apic_ir_dump(MSR_LAPIC_ISR_START);
+}
+void apic_irr_dump(void)
+{
+       printk("IRR DUMP\n");
+       __apic_ir_dump(MSR_LAPIC_IRR_START);
+}
+
+uint32_t apicrget(uint64_t r)
+{
+       uint32_t val;
+
+       if (r >= MSR_LAPIC_END)
+               panic("%s: OUT OF BOUNDS: register 0x%x\n", __func__, r);
+       if (r != MSR_LAPIC_SPURIOUS && r != MSR_LAPIC_DIVIDE_CONFIG_REG)
+               printd("%s: Reading from register 0x%llx\n",
+                      __func__, r);
+
+       val = read_msr(r);
        printd("apicrget: %s returns %p\n", apicregnames[r], val);
+       if (r == MSR_LAPIC_ID) {
+               printd("APIC ID: 0x%lx\n", val);
+               printd("APIC LOGICAL ID: 0x%lx\n",
+                      apicrget(MSR_LAPIC_LDR));
+       }
        return val;
 }
 
-static void apicrput(int r, uint32_t data)
+void apicrput(uint64_t r, uint32_t data)
 {
-       if (!apicbase)
-               panic("apicrput: no apic");
+       uint64_t temp_data = 0;
+
+       if (r >= MSR_LAPIC_END)
+               panic("%s: OUT OF BOUNDS: register 0x%x\n", __func__, r);
+       if (r != MSR_LAPIC_INITIAL_COUNT && r != MSR_LAPIC_LVT_TIMER &&
+           r != MSR_LAPIC_DIVIDE_CONFIG_REG && r != MSR_LAPIC_EOI)
+               printd("%s: Writing to register 0x%llx, value 0x%lx\n",
+                      __func__, r, data);
+       if (r == MSR_LAPIC_ID)
+               panic("ILLEGAL WRITE TO ID");
        printd("apicrput: %s = %p\n", apicregnames[r], data);
-       write_mmreg32(apicbase + r, data);
+
+       temp_data |= data;
+
+       write_msr(r, temp_data);
+}
+
+void apicsendipi(uint64_t data)
+{
+       printd("SENDING IPI: 0x%016lx\n", data);
+       write_msr(MSR_LAPIC_ICR, data);
 }
 
 void apicinit(int apicno, uintptr_t pa, int isbp)
 {
        struct apic *apic;
-
+       uint64_t msr_val;
        /*
         * Mark the APIC useable if it has a good ID
         * and the registers can be mapped.
@@ -156,30 +172,35 @@ void apicinit(int apicno, uintptr_t pa, int isbp)
                return;
        }
        assert(pa == LAPIC_PBASE);
-       apicbase = LAPIC_BASE;  /* was the plan to just clobber the global? */
        apic->useable = 1;
 
        /* plan 9 used to set up a mapping btw apic and pcpui like so:
                pcpui->apicno = apicno; // acpino is the hw_coreid
                apic->machno = apmachno++; // machno is the os_coreid
         * akaros does its own remapping of hw <-> os coreid during smp_boot */
+
+       //X2APIC INIT
+       msr_val = read_msr(IA32_APIC_BASE);
+       write_msr(IA32_APIC_BASE, msr_val | (3<<10));
 }
 
 static char *apicdump0(char *start, char *end, struct apic *apic, int i)
 {
        if (!apic->useable || apic->addr != 0)
                return start;
-       start =
-               seprintf(start, end, "apic%d: oscore %d lint0 %#8.8p lint1 %#8.8p\n", i,
-                                get_os_coreid(i), apic->lvt[0], apic->lvt[1]);
-       start =
-               seprintf(start, end, " tslvt %#8.8p pclvt %#8.8p elvt %#8.8p\n",
-                                apicrget(Tslvt), apicrget(Pclvt), apicrget(Elvt));
-       start =
-               seprintf(start, end,
-                                " tlvt %#8.8p lint0 %#8.8p lint1 %#8.8p siv %#8.8p\n",
-                                apicrget(Tlvt), apicrget(Lint0), apicrget(Lint1),
-                                apicrget(Siv));
+       start = seprintf(start, end,
+                        "apic%d: oscore %d lint0 %#8.8p lint1 %#8.8p\n", i,
+                        get_os_coreid(i), apic->lvt[0], apic->lvt[1]);
+       start = seprintf(start, end, " tslvt %#8.8p pclvt %#8.8p elvt %#8.8p\n",
+                        apicrget(MSR_LAPIC_LVT_THERMAL),
+                        apicrget(MSR_LAPIC_LVT_PERFMON),
+                        apicrget(MSR_LAPIC_LVT_ERROR_REG));
+       start = seprintf(start, end,
+                        " tlvt %#8.8p lint0 %#8.8p lint1 %#8.8p siv %#8.8p\n",
+                        apicrget(MSR_LAPIC_LVT_TIMER),
+                        apicrget(MSR_LAPIC_LVT_LINT0),
+                        apicrget(MSR_LAPIC_LVT_LINT1),
+                        apicrget(MSR_LAPIC_SPURIOUS));
        return start;
 }
 
@@ -202,8 +223,8 @@ char *apicdump(char *start, char *end)
 void handle_lapic_error(struct hw_trapframe *hw_tf, void *data)
 {
        uint32_t err;
-       apicrput(Es, 0);
-       err = apicrget(Es);
+       apicrput(MSR_LAPIC_ESR, 0);
+       err = apicrget(MSR_LAPIC_ESR);
        /* i get a shitload of these on my nehalem, many with err == 0 */
        printd("LAPIC error vector, got 0x%08x\n", err);
 }
@@ -214,12 +235,14 @@ int apiconline(void)
        uint64_t tsc;
        uint32_t dfr, ver;
        int apicno, nlvt;
+       uint64_t msr_val;
 
-       if (!apicbase) {
-               printk("No apicbase on HW core %d!!\n", hw_core_id());
-               return 0;
-       }
-       if ((apicno = ((apicrget(Id) >> 24) & 0xff)) >= Napic) {
+       //X2APIC INIT
+       msr_val = read_msr(IA32_APIC_BASE);
+       write_msr(IA32_APIC_BASE, msr_val | (3<<10));
+
+       apicno = lapic_get_id();
+       if (apicno >= Napic) {
                printk("Bad apicno %d on HW core %d!!\n", apicno, hw_core_id());
                return 0;
        }
@@ -231,7 +254,7 @@ int apiconline(void)
        }
        /* Things that can only be done when on the processor owning the APIC,
         * apicinit above runs on the bootstrap processor. */
-       ver = apicrget(Ver);
+       ver = apicrget(MSR_LAPIC_VERSION);
        nlvt = ((ver >> 16) & 0xff) + 1;
        if (nlvt > ARRAY_SIZE(apic->lvt)) {
                printk("apiconline%d: nlvt %d > max (%d)\n",
@@ -246,22 +269,22 @@ int apiconline(void)
        //if (memcmp(m->cpuinfo, "AuthenticAMD", 12) == 0)
        //      dfr = 0xf0000000;
        //else
-               dfr = 0xffffffff;
-       apicrput(Df, dfr);
-       apicrput(Ld, 0x00000000);
+       //      dfr = 0xffffffff;
+       //apicrput(Df, dfr);
+       //apicrput(MSR_LAPIC_LDR, 0x00000000);
 
        /* Disable interrupts until ready by setting the Task Priority register to
         * 0xff. */
-       apicrput(Tp, 0xff);
+       apicrput(MSR_LAPIC_TPR, 0xff);
 
        /* Software-enable the APIC in the Spurious Interrupt Vector register and
         * set the vector number. The vector number must have bits 3-0 0x0f unless
         * the Extended Spurious Vector Enable bit is set in the HyperTransport
         * Transaction Control register. */
-       apicrput(Siv, Swen | IdtLAPIC_SPURIOUS);
+       apicrput(MSR_LAPIC_SPURIOUS, Swen | IdtLAPIC_SPURIOUS);
 
        /* Acknowledge any outstanding interrupts. */
-       apicrput(Eoi, 0);
+       apicrput(MSR_LAPIC_EOI, 0);
 
        /* Mask interrupts on Performance Counter overflow and Thermal Sensor if
         * implemented, and on Lintr0 (Legacy INTR), Lintr1 (Legacy NMI), and the
@@ -269,22 +292,22 @@ int apiconline(void)
         * Error interrupt. */
        switch (apic->nlvt) {
                case 6:
-                       apicrput(Tslvt, Im);
+                       apicrput(MSR_LAPIC_LVT_THERMAL, Im);
                        /* fall-through */
                case 5:
-                       apicrput(Pclvt, Im);
+                       apicrput(MSR_LAPIC_LVT_PERFMON, Im);
                        /* fall-through */
                default:
                        break;
        }
        /* lvt[0] and [1] were set to 0 in the BSS */
-       apicrput(Lint1, apic->lvt[1] | Im | IdtLAPIC_LINT1);
-       apicrput(Lint0, apic->lvt[0] | Im | IdtLAPIC_LINT0);
-       apicrput(Tlvt, Im);
+       apicrput(MSR_LAPIC_LVT_LINT1, apic->lvt[1] | Im | IdtLAPIC_LINT1);
+       apicrput(MSR_LAPIC_LVT_LINT0, apic->lvt[0] | Im | IdtLAPIC_LINT0);
+       apicrput(MSR_LAPIC_LVT_TIMER, Im);
 
-       apicrput(Es, 0);
-       apicrget(Es);
-       apicrput(Elvt, IdtLAPIC_ERROR | Im);
+       apicrput(MSR_LAPIC_ESR, 0);
+       apicrget(MSR_LAPIC_ESR);
+       apicrput(MSR_LAPIC_LVT_ERROR_REG, IdtLAPIC_ERROR | Im);
 
        /* Not sure we need this from plan 9, Akaros never did:
         *
@@ -299,6 +322,6 @@ int apiconline(void)
        /* this is to enable the APIC interrupts.  we did a SW lapic_enable()
         * earlier.  if we ever have issues where the lapic seems offline, check
         * here. */
-       apicrput(Tp, 0);
+       apicrput(MSR_LAPIC_TPR, 0);
        return 1;
 }
index 3655d79..eaa984a 100644 (file)
@@ -287,7 +287,7 @@ static struct perfmon_status *perfmon_alloc_status(void)
 
 static void perfmon_arm_irq(void)
 {
-       write_mmreg32(LAPIC_LVT_PERFMON, IdtLAPIC_PCINT);
+       apicrput(MSR_LAPIC_LVT_PERFMON, IdtLAPIC_PCINT);
 }
 
 bool perfmon_supported(void)
index f609b86..2b9fb8f 100644 (file)
@@ -427,8 +427,7 @@ static void check_syms_va(void)
 {
        /* Make sure our symbols are up to date (see arch/ros/mmu64.h) */
        check_sym_va(KERN_LOAD_ADDR, 0xffffffffc0000000);
-       check_sym_va(LAPIC_BASE,     0xffffffffbff00000);
-       check_sym_va(IOAPIC_BASE,    0xffffffffbfe00000);
+       check_sym_va(IOAPIC_BASE,    0xffffffffbff00000);
        check_sym_va(VPT_TOP,        0xffffff0000000000);
        check_sym_va(VPT,            0xfffffe8000000000);
        check_sym_va(KERN_VMAP_TOP,  0xfffffe8000000000);
@@ -468,8 +467,6 @@ void vm_init(void)
        }
        /* For the LAPIC and IOAPIC, we use PAT (but not *the* PAT flag) to make
         * these type UC */
-       map_segment(boot_pgdir, LAPIC_BASE, APIC_SIZE, LAPIC_PBASE,
-                   PTE_PCD | PTE_PWT | PTE_KERN_RW | PTE_G, max_jumbo_shift);
        map_segment(boot_pgdir, IOAPIC_BASE, APIC_SIZE, IOAPIC_PBASE,
                    PTE_PCD | PTE_PWT | PTE_KERN_RW | PTE_G, max_jumbo_shift);
        /* VPT mapping: recursive PTE inserted at the VPT spot */
index 84a4941..3ebd79e 100644 (file)
@@ -31,14 +31,14 @@ typedef struct x86_pgdir {
  *                     |                              |                     |
  * KERN_LOAD_ADDR -->  +------------------------------+ 0xffffffffc0000000 -+
  *                     |                              |
- *                     |          Local APIC          | RW/--  APIC_SIZE (1MB)
+ *                     |            IOAPIC            | RW/--  APIC_SIZE (1MB)
  *                     |                              |
- *    LAPIC_BASE  -->  +------------------------------+ 0xffffffffbff00000
+ *   IOAPIC_BASE  -->  +------------------------------+ 0xffffffffbff00000
  *                     |                              |
- *                     |            IOAPIC            | RW/--  APIC_SIZE (1MB)
+ *                     |                              | RW/--  APIC_SIZE (1MB)
  *                     |                              |
- *  IOAPIC_BASE,  -->  +------------------------------+ 0xffffffffbfe00000
- *  KERN_DYN_TOP       |   Kernel Dynamic Mappings    |
+ *   KERN_DYN_TOP -->  +------------------------------+ 0xffffffffbfe00000
+ *                     |   Kernel Dynamic Mappings    |
  *                     |              .               |
  *                     :              .               :
  *                     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ RW/--
@@ -152,8 +152,7 @@ typedef struct x86_pgdir {
 #define KERN_LOAD_ADDR  0xffffffffc0000000
 /* Static kernel mappings */
 #define APIC_SIZE              0x100000
-#define LAPIC_BASE             (KERN_LOAD_ADDR - APIC_SIZE)
-#define IOAPIC_BASE            (LAPIC_BASE - APIC_SIZE)
+#define IOAPIC_BASE            (KERN_LOAD_ADDR - APIC_SIZE)
 /* All arches must define this, which is the lower limit of their static
  * mappings, and where the dynamic mappings will start. */
 #define KERN_DYN_TOP   IOAPIC_BASE
index d7be860..5ae4835 100644 (file)
 #define MSR_IA32_LASTINTFROMIP         0x000001dd
 #define MSR_IA32_LASTINTTOIP           0x000001de
 
+/* X86 X2APIC registers */
+#define MSR_LAPIC_ID                                   0x00000802
+#define MSR_LAPIC_VERSION                              0x00000803
+#define MSR_LAPIC_TPR                                  0x00000808
+#define MSR_LAPIC_PPR                                  0x0000080a
+#define MSR_LAPIC_EOI                                  0x0000080b
+#define MSR_LAPIC_LDR                                  0x0000080d
+#define MSR_LAPIC_SPURIOUS                             0x0000080f
+
+#define MSR_LAPIC_ISR_31_0                             0x00000810
+#define MSR_LAPIC_ISR_63_32                            0x00000811
+#define MSR_LAPIC_ISR_95_64                            0x00000812
+#define MSR_LAPIC_ISR_127_96                   0x00000813
+#define MSR_LAPIC_ISR_159_128                  0x00000814
+#define MSR_LAPIC_ISR_191_160                  0x00000815
+#define MSR_LAPIC_ISR_223_192                  0x00000816
+#define MSR_LAPIC_ISR_255_224                  0x00000817
+// For easier looping
+#define MSR_LAPIC_ISR_START                            MSR_LAPIC_ISR_31_0
+#define MSR_LAPIC_ISR_END                              (MSR_LAPIC_ISR_255_224 + 1)
+
+#define MSR_LAPIC_TMR_31_0                             0x00000818
+#define MSR_LAPIC_TMR_63_32                            0x00000819
+#define MSR_LAPIC_TMR_95_64                            0x0000081a
+#define MSR_LAPIC_TMR_127_96                   0x0000081b
+#define MSR_LAPIC_TMR_159_128                  0x0000081c
+#define MSR_LAPIC_TMR_191_160                  0x0000081d
+#define MSR_LAPIC_TMR_223_192                  0x0000081e
+#define MSR_LAPIC_TMR_255_224                  0x0000081f
+// For easier looping
+#define MSR_LAPIC_TMR_START                            MSR_LAPIC_TMR_31_0
+#define MSR_LAPIC_TMR_END                              (MSR_LAPIC_TMR_255_224 + 1)
+
+#define MSR_LAPIC_IRR_31_0                             0x00000820
+#define MSR_LAPIC_IRR_63_32                            0x00000821
+#define MSR_LAPIC_IRR_95_64                            0x00000822
+#define MSR_LAPIC_IRR_127_96                   0x00000823
+#define MSR_LAPIC_IRR_159_128                  0x00000824
+#define MSR_LAPIC_IRR_191_160                  0x00000825
+#define MSR_LAPIC_IRR_223_192                  0x00000826
+#define MSR_LAPIC_IRR_255_224                  0x00000827
+// For easier looping
+#define MSR_LAPIC_IRR_START                            MSR_LAPIC_IRR_31_0
+#define MSR_LAPIC_IRR_END                              (MSR_LAPIC_IRR_255_224 + 1)
+
+#define MSR_LAPIC_ESR                                  0x00000828
+#define MSR_LAPIC_LVT_CMCI                             0x0000082f
+#define MSR_LAPIC_ICR                                  0x00000830
+#define MSR_LAPIC_LVT_TIMER                            0x00000832
+#define MSR_LAPIC_LVT_THERMAL                  0x00000833
+#define MSR_LAPIC_LVT_PERFMON                  0x00000834
+#define MSR_LAPIC_LVT_LINT0                            0x00000835
+#define MSR_LAPIC_LVT_LINT1                            0x00000836
+#define MSR_LAPIC_LVT_ERROR_REG                        0x00000837
+#define MSR_LAPIC_INITIAL_COUNT                        0x00000838
+#define MSR_LAPIC_CURRENT_COUNT                        0x00000839
+#define MSR_LAPIC_DIVIDE_CONFIG_REG            0x0000083e
+#define MSR_LAPIC_SELF_IPI                             0x0000083f
+
+#define MSR_LAPIC_END                                  (MSR_LAPIC_SELF_IPI + 1)
+
 /* DEBUGCTLMSR bits (others vary by model): */
 #define DEBUGCTLMSR_LBR                        (1UL <<  0)     /* last branch recording */
 #define DEBUGCTLMSR_BTF                        (1UL <<  1)     /* single-step on branches */
index d576bb0..cba0cf4 100644 (file)
@@ -144,7 +144,6 @@ static int smp_call_function(uint8_t type, uint32_t dest, isr_t handler,
                        panic("Invalid type for cross-core function call!");
        }
        // wait long enough to receive our own broadcast (PROBABLY WORKS) TODO
-       lapic_wait_to_send();
        disable_irqsave(&state);
        return 0;
 }
index ddea6c6..547251c 100644 (file)
@@ -31,10 +31,10 @@ void timer_init(void){
        __lapic_set_timer(0xffffffff, IdtLAPIC_TIMER, FALSE,
                          LAPIC_TIMER_DIVISOR_BITS);
        // Mask the LAPIC Timer, so we never receive this interrupt (minor race)
-       mask_lapic_lvt(LAPIC_LVT_TIMER);
-       timercount[0] = read_mmreg32(LAPIC_TIMER_CURRENT);
+       mask_lapic_lvt(MSR_LAPIC_LVT_TIMER);
+       timercount[0] = apicrget(MSR_LAPIC_CURRENT_COUNT);
        udelay_pit(1000000);
-       timercount[1] = read_mmreg32(LAPIC_TIMER_CURRENT);
+       timercount[1] = apicrget(MSR_LAPIC_CURRENT_COUNT);
        system_timing.bus_freq = (timercount[0] - timercount[1])
                                 * LAPIC_TIMER_DIVISOR_VAL;
        /* The time base for the timer is derived from the processor's bus clock,
@@ -49,7 +49,7 @@ void pit_set_timer(uint32_t divisor, uint32_t mode)
        if (divisor & 0xffff0000)
                warn("Divisor too large!");
        mode = TIMER_SEL0|TIMER_16BIT|mode;
-       outb(TIMER_MODE, mode); 
+       outb(TIMER_MODE, mode);
        outb(TIMER_CNTR0, divisor & 0xff);
        outb(TIMER_CNTR0, (divisor >> 8) );
        system_timing.pit_mode = mode;
@@ -64,7 +64,7 @@ static int getpit()
 
     /* Select counter 0 and latch counter value. */
     outb(TIMER_MODE, TIMER_SEL0 | TIMER_LATCH);
-    
+
     low = inb(TIMER_CNTR0);
     high = inb(TIMER_CNTR0);
 
@@ -119,14 +119,14 @@ void udelay_pit(uint64_t usec)
        else
                // round up the ticks left
                ticks_left = ((uint64_t)usec * (long long)PIT_FREQ+ 999999)
-                            / 1000000; 
+                            / 1000000;
        while (ticks_left > 0) {
                tick = getpit();
                delta = prev_tick - tick;
                prev_tick = tick;
                if (delta < 0) {
                        // counter looped around during the delta time period
-                       delta += system_timing.pit_divisor; // maximum count 
+                       delta += system_timing.pit_divisor; // maximum count
                        if (delta < 0)
                                delta = 0;
                }
@@ -136,7 +136,7 @@ void udelay_pit(uint64_t usec)
 
 uint64_t gettimer(void)
 {
-       return read_tsc();      
+       return read_tsc();
 }
 
 uint64_t getfreq(void)
index 5cda655..132f656 100644 (file)
        .type name, @function;                          \
        .align 2;                                                       \
        name:;                                                          \
-       movl $0, (LAPIC_BASE + 0x0b0);      \
+       pushq %rax;                     \
+       pushq %rcx;                     \
+       pushq %rdx;                     \
+       movq $0, %rax;                  \
+       movq $0, %rdx;                  \
+       movq $(MSR_LAPIC_EOI), %rcx;    \
+       wrmsr;                          \
+       popq %rdx;                      \
+       popq %rcx;                      \
+       popq %rax;                      \
        iretq;                                                          \
        .data;                                                          \
        .quad name;                                                     \
index b7fd96f..8ad25fc 100644 (file)
@@ -110,8 +110,9 @@ bool test_pic_reception(void)
        pic_unmask_irq(0, 0);
        cprintf("PIC1 Mask = 0x%04x\n", inb(PIC1_DATA));
        cprintf("PIC2 Mask = 0x%04x\n", inb(PIC2_DATA));
-       unmask_lapic_lvt(LAPIC_LVT_LINT0);
-       cprintf("Core %d's LINT0: 0x%08x\n", core_id(), read_mmreg32(LAPIC_LVT_LINT0));
+       unmask_lapic_lvt(MSR_LAPIC_LVT_LINT0);
+       printk("Core %d's LINT0: 0x%08x\n", core_id(),
+              apicrget(MSR_LAPIC_LVT_TIMER));
        enable_irq();
        while(1);
 
@@ -571,7 +572,6 @@ bool test_lapic_status_bit(void)
        // KT_ASSERT_M("IPIs received should be 0", (0 == a));
        for(int i = 0; i < NUM_IPI; i++) {
                send_ipi(7, I_TESTING);
-               lapic_wait_to_send();
        }
        // need to wait a bit to let those IPIs get there
        udelay(5000000);