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#include <i386/bit_routines.h> 37 38/* PAL-related routines */ 39void i386_cpu_IPI(int cpu); 40boolean_t i386_smp_init(int nmi_vector, i386_intr_func_t nmi_handler, 41 int ipi_vector, i386_intr_func_t ipi_handler); 42void i386_start_cpu(int lapic_id, int cpu_num); 43void i386_send_NMI(int cpu); 44void handle_pending_TLB_flushes(void); 45 46extern void slave_pstart(void); 47 48#ifdef MP_DEBUG 49int trappedalready = 0; /* (BRINGUP) */ 50#endif /* MP_DEBUG */ 51 52boolean_t 53i386_smp_init(int nmi_vector, i386_intr_func_t nmi_handler, int ipi_vector, i386_intr_func_t ipi_handler) 54{ 55 /* Local APIC? */ 56 if (!lapic_probe()) 57 return FALSE; 58 59 lapic_init(); 60 lapic_configure(); 61 lapic_set_intr_func(nmi_vector, nmi_handler); 62 lapic_set_intr_func(ipi_vector, ipi_handler); 63 64 install_real_mode_bootstrap(slave_pstart); 65 66 return TRUE; 67} 68 69void 70i386_start_cpu(int lapic_id, __unused int cpu_num ) 71{ 72 LAPIC_WRITE_ICR(lapic_id, LAPIC_ICR_DM_INIT); 73 delay(100); 74 LAPIC_WRITE_ICR(lapic_id, 75 LAPIC_ICR_DM_STARTUP|(REAL_MODE_BOOTSTRAP_OFFSET>>12)); 76} 77 78void 79i386_send_NMI(int cpu) 80{ 81 boolean_t state = ml_set_interrupts_enabled(FALSE); 82 /* Program the interrupt command register */ 83 /* The vector is ignored in this case--the target CPU will enter on the 84 * NMI vector. 85 */ 86 LAPIC_WRITE_ICR(cpu_to_lapic[cpu], 87 LAPIC_VECTOR(INTERPROCESSOR)|LAPIC_ICR_DM_NMI); 88 (void) ml_set_interrupts_enabled(state); 89} 90 91void 92handle_pending_TLB_flushes(void) 93{ 94 volatile int *my_word = ¤t_cpu_datap()->cpu_signals; 95 96 if (i_bit(MP_TLB_FLUSH, my_word) && (pmap_tlb_flush_timeout == FALSE)) { 97 DBGLOG(cpu_handle, cpu_number(), MP_TLB_FLUSH); 98 i_bit_clear(MP_TLB_FLUSH, my_word); 99 pmap_update_interrupt(); 100 } 101} 102 103void 104i386_cpu_IPI(int cpu) 105{ 106#ifdef MP_DEBUG 107 if(cpu_datap(cpu)->cpu_signals & 6) { /* (BRINGUP) */ 108 kprintf("i386_cpu_IPI: sending enter debugger signal (%08X) to cpu %d\n", cpu_datap(cpu)->cpu_signals, cpu); 109 } 110#endif /* MP_DEBUG */ 111 112 lapic_send_ipi(cpu, LAPIC_VECTOR(INTERPROCESSOR)); 113} 114