1/* 2 * Copyright (c) 2000-2009 Apple Inc. All rights reserved. 3 * 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. The rights granted to you under the License 10 * may not be used to create, or enable the creation or redistribution of, 11 * unlawful or unlicensed copies of an Apple operating system, or to 12 * circumvent, violate, or enable the circumvention or violation of, any 13 * terms of an Apple operating system software license agreement. 14 * 15 * Please obtain a copy of the License at 16 * http://www.opensource.apple.com/apsl/ and read it before using this file. 17 * 18 * The Original Code and all software distributed under the License are 19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 23 * Please see the License for the specific language governing rights and 24 * limitations under the License. 25 * 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 27 */ 28 29#include <mach/vm_types.h> 30#include <i386/acpi.h> /* install_real_mode_bootstrap */ 31#include <i386/mp.h> 32#include <i386/lapic.h> /* lapic_* functions */ 33#include <i386/machine_routines.h> 34#include <i386/cpu_data.h> 35#include <i386/pmap.h> 36 37/* PAL-related routines */ 38void i386_cpu_IPI(int cpu); 39boolean_t i386_smp_init(int nmi_vector, i386_intr_func_t nmi_handler, 40 int ipi_vector, i386_intr_func_t ipi_handler); 41void i386_start_cpu(int lapic_id, int cpu_num); 42void i386_send_NMI(int cpu); 43void handle_pending_TLB_flushes(void); 44 45extern void slave_pstart(void); 46 47#ifdef MP_DEBUG 48int trappedalready = 0; /* (BRINGUP) */ 49#endif /* MP_DEBUG */ 50 51boolean_t 52i386_smp_init(int nmi_vector, i386_intr_func_t nmi_handler, int ipi_vector, i386_intr_func_t ipi_handler) 53{ 54 /* Local APIC? */ 55 if (!lapic_probe()) 56 return FALSE; 57 58 lapic_init(); 59 lapic_configure(); 60 lapic_set_intr_func(nmi_vector, nmi_handler); 61 lapic_set_intr_func(ipi_vector, ipi_handler); 62 63 install_real_mode_bootstrap(slave_pstart); 64 65 return TRUE; 66} 67 68void 69i386_start_cpu(int lapic_id, __unused int cpu_num ) 70{ 71 LAPIC_WRITE_ICR(lapic_id, LAPIC_ICR_DM_INIT); 72 delay(100); 73 LAPIC_WRITE_ICR(lapic_id, 74 LAPIC_ICR_DM_STARTUP|(REAL_MODE_BOOTSTRAP_OFFSET>>12)); 75} 76 77void 78i386_send_NMI(int cpu) 79{ 80 boolean_t state = ml_set_interrupts_enabled(FALSE); 81 /* Program the interrupt command register */ 82 /* The vector is ignored in this case--the target CPU will enter on the 83 * NMI vector. 84 */ 85 LAPIC_WRITE_ICR(cpu_to_lapic[cpu], 86 LAPIC_VECTOR(INTERPROCESSOR)|LAPIC_ICR_DM_NMI); 87 (void) ml_set_interrupts_enabled(state); 88} 89 90void 91handle_pending_TLB_flushes(void) 92{ 93 volatile int *my_word = ¤t_cpu_datap()->cpu_signals; 94 95 if (i_bit(MP_TLB_FLUSH, my_word) && (pmap_tlb_flush_timeout == FALSE)) { 96 DBGLOG(cpu_handle, cpu_number(), MP_TLB_FLUSH); 97 i_bit_clear(MP_TLB_FLUSH, my_word); 98 pmap_update_interrupt(); 99 } 100} 101 102void 103i386_cpu_IPI(int cpu) 104{ 105#ifdef MP_DEBUG 106 if(cpu_datap(cpu)->cpu_signals & 6) { /* (BRINGUP) */ 107 kprintf("i386_cpu_IPI: sending enter debugger signal (%08X) to cpu %d\n", cpu_datap(cpu)->cpu_signals, cpu); 108 } 109#endif /* MP_DEBUG */ 110 111 lapic_send_ipi(cpu, LAPIC_VECTOR(INTERPROCESSOR)); 112} 113