]> git.saurik.com Git - apple/xnu.git/blobdiff - osfmk/i386/lapic.c
xnu-1456.1.26.tar.gz
[apple/xnu.git] / osfmk / i386 / lapic.c
index ef37b72fa7dd7e9f3bc4f757c56d97383bc6c56a..0206d098697420782370ee646559ea0b8a894281 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2008-2009 Apple Inc. All rights reserved.
  *
  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
  * 
 #include <i386/mtrr.h>
 #include <i386/postcode.h>
 #include <i386/cpu_threads.h>
-#include <i386/trap.h>
 #include <i386/machine_routines.h>
+#if CONFIG_MCA
 #include <i386/machine_check.h>
+#endif
+
+#if CONFIG_COUNTERS
+#include <pmc/pmc.h>
+#endif
 
 #if MACH_KDB
 #include <machine/db_machdep.h>
@@ -129,6 +134,18 @@ ml_get_apicid(uint32_t cpu)
 
 }
 
+uint32_t
+ml_get_cpuid(uint32_t lapic_index)
+{
+       if(lapic_index >= (uint32_t)MAX_CPUS)
+               return 0xFFFFFFFF;      /* Return -1 if cpu too big */
+       
+       /* Return the cpu ID (or -1 if not configured) */
+       return (uint32_t)lapic_to_cpu[lapic_index];
+
+}
+
+
 #ifdef MP_DEBUG
 static void
 lapic_cpu_map_dump(void)
@@ -166,14 +183,14 @@ lapic_init(void)
        is_boot_processor = (lo & MSR_IA32_APIC_BASE_BSP) != 0;
        is_lapic_enabled  = (lo & MSR_IA32_APIC_BASE_ENABLE) != 0;
        lapic_base = (lo &  MSR_IA32_APIC_BASE_BASE);
-       kprintf("MSR_IA32_APIC_BASE 0x%x %s %s\n", lapic_base,
+       kprintf("MSR_IA32_APIC_BASE %p %s %s\n", (void *) lapic_base,
                is_lapic_enabled ? "enabled" : "disabled",
                is_boot_processor ? "BSP" : "AP");
        if (!is_boot_processor || !is_lapic_enabled)
                panic("Unexpected local APIC state\n");
 
        /* Establish a map to the local apic */
-       lapic_start = vm_map_min(kernel_map);
+       lapic_start = (vm_offset_t)vm_map_min(kernel_map);
        result = vm_map_find_space(kernel_map,
                                   (vm_map_address_t *) &lapic_start,
                                   round_page(LAPIC_SIZE), 0,
@@ -194,7 +211,7 @@ lapic_init(void)
        lapic_id = (unsigned long)(lapic_start + LAPIC_ID);
 
        if ((LAPIC_READ(VERSION)&LAPIC_VERSION_MASK) < 0x14) {
-               printf("Local APIC version 0x%x, 0x14 or greater expected\n",
+               panic("Local APIC version 0x%x, 0x14 or more expected\n",
                        (LAPIC_READ(VERSION)&LAPIC_VERSION_MASK));
        }
 
@@ -249,9 +266,9 @@ lapic_dump(void)
 #define IP(lvt) \
        (LAPIC_READ(lvt)&LAPIC_LVT_IP_PLRITY_LOW)? "Low " : "High"
 
-       kprintf("LAPIC %d at 0x%x version 0x%x\n", 
+       kprintf("LAPIC %d at %p version 0x%x\n", 
                (LAPIC_READ(ID)>>LAPIC_ID_SHIFT)&LAPIC_ID_MASK,
-               lapic_start,
+               (void *) lapic_start,
                LAPIC_READ(VERSION)&LAPIC_VERSION_MASK);
        kprintf("Priorities: Task 0x%x  Arbitration 0x%x  Processor 0x%x\n",
                LAPIC_READ(TPR)&LAPIC_TPR_MASK,
@@ -264,12 +281,14 @@ lapic_dump(void)
                BOOL(LAPIC_READ(SVR)&LAPIC_SVR_ENABLE),
                BOOL(!(LAPIC_READ(SVR)&LAPIC_SVR_FOCUS_OFF)),
                LAPIC_READ(SVR) & LAPIC_SVR_MASK);
+#if CONFIG_MCA
        if (mca_is_cmci_present())
                kprintf("LVT_CMCI:    Vector 0x%02x [%s] %s %cmasked\n",
                        VEC(LVT_CMCI),
                        DM(LVT_CMCI),
                        DS(LVT_CMCI),
                        MASK(LVT_CMCI));
+#endif
        kprintf("LVT_TIMER:   Vector 0x%02x %s %cmasked %s\n",
                VEC(LVT_TIMER),
                DS(LVT_TIMER),
@@ -460,9 +479,11 @@ lapic_configure(void)
        /* Thermal: unmasked */
        LAPIC_WRITE(LVT_THERMAL, LAPIC_VECTOR(THERMAL));
 
+#if CONFIG_MCA
        /* CMCI, if available */
        if (mca_is_cmci_present())
                LAPIC_WRITE(LVT_CMCI, LAPIC_VECTOR(CMCI));
+#endif
 
        if (((cpu_number() == master_cpu) && lapic_errors_masked == FALSE) ||
                (cpu_number() != master_cpu)) {
@@ -473,7 +494,7 @@ lapic_configure(void)
 
 void
 lapic_set_timer(
-       boolean_t               interrupt,
+       boolean_t               interrupt_unmasked,
        lapic_timer_mode_t      mode,
        lapic_timer_divide_t    divisor,
        lapic_timer_count_t     initial_count)
@@ -484,7 +505,7 @@ lapic_set_timer(
        state = ml_set_interrupts_enabled(FALSE);
        timer_vector = LAPIC_READ(LVT_TIMER);
        timer_vector &= ~(LAPIC_LVT_MASKED|LAPIC_LVT_PERIODIC);;
-       timer_vector |= interrupt ? 0 : LAPIC_LVT_MASKED;
+       timer_vector |= interrupt_unmasked ? 0 : LAPIC_LVT_MASKED;
        timer_vector |= (mode == periodic) ? LAPIC_LVT_PERIODIC : 0;
        LAPIC_WRITE(LVT_TIMER, timer_vector);
        LAPIC_WRITE(TIMER_DIVIDE_CONFIG, divisor);
@@ -526,6 +547,10 @@ lapic_end_of_interrupt(void)
        _lapic_end_of_interrupt();
 }
 
+void lapic_unmask_perfcnt_interrupt(void) {
+       LAPIC_WRITE(LVT_PERFCNT, LAPIC_VECTOR(PERFCNT));
+}
+
 void
 lapic_set_intr_func(int vector, i386_intr_func_t func)
 {
@@ -539,6 +564,7 @@ lapic_set_intr_func(int vector, i386_intr_func_t func)
        case LAPIC_THERMAL_INTERRUPT:
        case LAPIC_PERFCNT_INTERRUPT:
        case LAPIC_CMCI_INTERRUPT:
+       case LAPIC_PM_INTERRUPT:
                lapic_intr_func[vector] = func;
                break;
        default:
@@ -548,14 +574,14 @@ lapic_set_intr_func(int vector, i386_intr_func_t func)
 }
 
 int
-lapic_interrupt(int interrupt, x86_saved_state_t *state)
+lapic_interrupt(int interrupt_num, x86_saved_state_t *state)
 {
        int     retval = 0;
        int     esr = -1;
 
-       interrupt -= lapic_interrupt_base;
-       if (interrupt < 0) {
-               if (interrupt == (LAPIC_NMI_INTERRUPT - lapic_interrupt_base) &&
+       interrupt_num -= lapic_interrupt_base;
+       if (interrupt_num < 0) {
+               if (interrupt_num == (LAPIC_NMI_INTERRUPT - lapic_interrupt_base) &&
                    lapic_intr_func[LAPIC_NMI_INTERRUPT] != NULL) {
                        retval = (*lapic_intr_func[LAPIC_NMI_INTERRUPT])(state);
                        _lapic_end_of_interrupt();
@@ -565,22 +591,33 @@ lapic_interrupt(int interrupt, x86_saved_state_t *state)
                        return 0;
        }
 
-       switch(interrupt) {
+       switch(interrupt_num) {
        case LAPIC_TIMER_INTERRUPT:
        case LAPIC_THERMAL_INTERRUPT:
-       case LAPIC_PERFCNT_INTERRUPT:
        case LAPIC_INTERPROCESSOR_INTERRUPT:
-               if (lapic_intr_func[interrupt] != NULL)
-                       (void) (*lapic_intr_func[interrupt])(state);
-               if (interrupt == LAPIC_PERFCNT_INTERRUPT)
-                       /* Clear interrupt masked */
-                       LAPIC_WRITE(LVT_PERFCNT, LAPIC_VECTOR(PERFCNT));
+       case LAPIC_PM_INTERRUPT:
+               if (lapic_intr_func[interrupt_num] != NULL)
+                       (void) (*lapic_intr_func[interrupt_num])(state);
                _lapic_end_of_interrupt();
                retval = 1;
                break;
+       case LAPIC_PERFCNT_INTERRUPT:
+               /* If a function has been registered, invoke it.  Otherwise,
+                * pass up to IOKit.
+                */
+               if (lapic_intr_func[interrupt_num] != NULL) {
+                       (void) (*lapic_intr_func[interrupt_num])(state);
+                       /* Unmask the interrupt since we don't expect legacy users
+                        * to be responsible for it.
+                        */
+                       lapic_unmask_perfcnt_interrupt();
+                       _lapic_end_of_interrupt();
+                       retval = 1;
+               }
+               break;
        case LAPIC_CMCI_INTERRUPT:
-               if (lapic_intr_func[interrupt] != NULL)
-                       (void) (*lapic_intr_func[interrupt])(state);
+               if (lapic_intr_func[interrupt_num] != NULL)
+                       (void) (*lapic_intr_func[interrupt_num])(state);
                /* return 0 for plaform expert to handle */
                break;
        case LAPIC_ERROR_INTERRUPT:
@@ -634,6 +671,19 @@ lapic_interrupt(int interrupt, x86_saved_state_t *state)
                /* No EOI required here */
                retval = 1;
                break;
+       case LAPIC_PMC_SW_INTERRUPT: 
+               {
+#if CONFIG_COUNTERS
+                       thread_t old, new;
+                       ml_get_csw_threads(&old, &new);
+
+                       if (pmc_context_switch(old, new) == TRUE) {
+                               retval = 1;
+                               /* No EOI required for SWI */
+                       }
+#endif /* CONFIG_COUNTERS */
+               }
+               break;
        }
 
        return retval;
@@ -672,3 +722,23 @@ lapic_smm_restore(void)
        ml_set_interrupts_enabled(state);
 }
 
+void
+lapic_send_ipi(int cpu, int vector)
+{
+       boolean_t       state;
+
+       if (vector < lapic_interrupt_base)
+               vector += lapic_interrupt_base;
+
+       state = ml_set_interrupts_enabled(FALSE);
+
+       /* Wait for pending outgoing send to complete */
+       while (LAPIC_READ(ICR) & LAPIC_ICR_DS_PENDING) {
+               cpu_pause();
+       }
+
+       LAPIC_WRITE(ICRD, cpu_to_lapic[cpu] << LAPIC_ICRD_DEST_SHIFT);
+       LAPIC_WRITE(ICR, vector | LAPIC_ICR_DM_FIXED);
+
+       (void) ml_set_interrupts_enabled(state);
+}