7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases/*
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * CDDL HEADER START
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases *
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * The contents of this file are subject to the terms of the
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * Common Development and Distribution License (the "License").
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * You may not use this file except in compliance with the License.
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases *
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * or http://www.opensolaris.org/os/licensing.
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * See the License for the specific language governing permissions
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * and limitations under the License.
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases *
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * When distributing Covered Code, include this CDDL HEADER in each
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * If applicable, add the following below this CDDL HEADER, with the
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * fields enclosed by brackets "[]" replaced with your own identifying
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * information: Portions Copyright [yyyy] [name of copyright owner]
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases *
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * CDDL HEADER END
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases/*
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases */
a288e5a9793fdffe5e842d7e61ab45263e75eacaJoshua M. Clulow/*
a288e5a9793fdffe5e842d7e61ab45263e75eacaJoshua M. Clulow * Copyright (c) 2013, Joyent, Inc. All rights reserved.
970db7b7a5b4656c659fc7c5226da7be313dc336Dan Kimmel * Copyright (c) 2016 by Delphix. All rights reserved.
a288e5a9793fdffe5e842d7e61ab45263e75eacaJoshua M. Clulow */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases/*
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * PSMI 1.1 extensions are supported only in 2.6 and later versions.
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * PSMI 1.2 extensions are supported only in 2.7 and later versions.
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * PSMI 1.3 and 1.4 extensions are supported in Solaris 10.
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * PSMI 1.5 extensions are supported in Solaris Nevada.
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * PSMI 1.6 extensions are supported in Solaris Nevada.
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * PSMI 1.7 extensions are supported in Solaris Nevada.
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases#define PSMI_1_7
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases#include <sys/processor.h>
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases#include <sys/time.h>
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases#include <sys/psm.h>
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases#include <sys/smp_impldefs.h>
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases#include <sys/cram.h>
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases#include <sys/acpi/acpi.h>
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases#include <sys/acpica.h>
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases#include <sys/psm_common.h>
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases#include <sys/apic.h>
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases#include <sys/pit.h>
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases#include <sys/ddi.h>
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases#include <sys/sunddi.h>
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases#include <sys/ddi_impldefs.h>
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases#include <sys/pci.h>
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases#include <sys/promif.h>
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases#include <sys/x86_archext.h>
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases#include <sys/cpc_impl.h>
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases#include <sys/uadmin.h>
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases#include <sys/panic.h>
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases#include <sys/debug.h>
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases#include <sys/archsystm.h>
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases#include <sys/trap.h>
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases#include <sys/machsystm.h>
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases#include <sys/sysmacros.h>
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases#include <sys/cpuvar.h>
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases#include <sys/rm_platter.h>
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases#include <sys/privregs.h>
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases#include <sys/note.h>
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases#include <sys/pci_intr_lib.h>
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases#include <sys/spl.h>
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases#include <sys/clock.h>
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases#include <sys/dditypes.h>
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases#include <sys/sunddi.h>
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases#include <sys/x_call.h>
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases#include <sys/reboot.h>
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases#include <sys/hpet.h>
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases#include <sys/apic_common.h>
41afdfa77f9af46beb3aaab2eccc0d9afe660d31Krishnendu Sadhukhan - Sun Microsystems#include <sys/apic_timer.h>
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesstatic void apic_record_ioapic_rdt(void *intrmap_private,
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases ioapic_rdt_t *irdt);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesstatic void apic_record_msi(void *intrmap_private, msi_regs_t *mregs);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases/*
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * Common routines between pcplusmp & apix (taken from apic.c).
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesint apic_clkinit(int);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayaseshrtime_t apic_gethrtime(void);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesvoid apic_send_ipi(int, int);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesvoid apic_set_idlecpu(processorid_t);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesvoid apic_unset_idlecpu(processorid_t);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesvoid apic_shutdown(int, int);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesvoid apic_preshutdown(int, int);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesprocessorid_t apic_get_next_processorid(processorid_t);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayaseshrtime_t apic_gettime();
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesenum apic_ioapic_method_type apix_mul_ioapic_method = APIC_MUL_IOAPIC_PCPLUSMP;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases/* Now the ones for Dynamic Interrupt distribution */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesint apic_enable_dynamic_migration = 0;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases/* maximum loop count when sending Start IPIs. */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesint apic_sipi_max_loop_count = 0x1000;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases/*
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * These variables are frequently accessed in apic_intr_enter(),
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * apic_intr_exit and apic_setspl, so group them together
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesvolatile uint32_t *apicadr = NULL; /* virtual addr of local APIC */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesint apic_setspl_delay = 1; /* apic_setspl - delay enable */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesint apic_clkvect;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases/* vector at which error interrupts come in */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesint apic_errvect;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesint apic_enable_error_intr = 1;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesint apic_error_display_delay = 100;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases/* vector at which performance counter overflow interrupts come in */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesint apic_cpcovf_vect;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesint apic_enable_cpcovf_intr = 1;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases/* vector at which CMCI interrupts come in */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesint apic_cmci_vect;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesextern int cmi_enable_cmci;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesextern void cmi_cmci_trap(void);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayaseskmutex_t cmci_cpu_setup_lock; /* protects cmci_cpu_setup_registered */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesint cmci_cpu_setup_registered;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases/* number of CPUs in power-on transition state */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesstatic int apic_poweron_cnt = 0;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayaseslock_t apic_mode_switch_lock;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases/*
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * Patchable global variables.
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesint apic_forceload = 0;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesint apic_coarse_hrtime = 1; /* 0 - use accurate slow gethrtime() */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesint apic_flat_model = 0; /* 0 - clustered. 1 - flat */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesint apic_panic_on_nmi = 0;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesint apic_panic_on_apic_error = 0;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesint apic_verbose = 0; /* 0x1ff */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases#ifdef DEBUG
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesint apic_debug = 0;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesint apic_restrict_vector = 0;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesint apic_debug_msgbuf[APIC_DEBUG_MSGBUFSIZE];
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesint apic_debug_msgbufindex = 0;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases#endif /* DEBUG */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesuint_t apic_nticks = 0;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesuint_t apic_skipped_redistribute = 0;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesuint_t last_count_read = 0;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayaseslock_t apic_gethrtime_lock;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesvolatile int apic_hrtime_stamp = 0;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesvolatile hrtime_t apic_nsec_since_boot = 0;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesstatic hrtime_t apic_last_hrtime = 0;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesint apic_hrtime_error = 0;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesint apic_remote_hrterr = 0;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesint apic_num_nmis = 0;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesint apic_apic_error = 0;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesint apic_num_apic_errors = 0;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesint apic_num_cksum_errors = 0;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesint apic_error = 0;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesstatic int apic_cmos_ssb_set = 0;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases/* use to make sure only one cpu handles the nmi */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayaseslock_t apic_nmi_lock;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases/* use to make sure only one cpu handles the error interrupt */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayaseslock_t apic_error_lock;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesstatic struct {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases uchar_t cntl;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases uchar_t data;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases} aspen_bmc[] = {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases { CC_SMS_WR_START, 0x18 }, /* NetFn/LUN */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases { CC_SMS_WR_NEXT, 0x24 }, /* Cmd SET_WATCHDOG_TIMER */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases { CC_SMS_WR_NEXT, 0x84 }, /* DataByte 1: SMS/OS no log */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases { CC_SMS_WR_NEXT, 0x2 }, /* DataByte 2: Power Down */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases { CC_SMS_WR_NEXT, 0x0 }, /* DataByte 3: no pre-timeout */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases { CC_SMS_WR_NEXT, 0x0 }, /* DataByte 4: timer expir. */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases { CC_SMS_WR_NEXT, 0xa }, /* DataByte 5: init countdown */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases { CC_SMS_WR_END, 0x0 }, /* DataByte 6: init countdown */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases { CC_SMS_WR_START, 0x18 }, /* NetFn/LUN */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases { CC_SMS_WR_END, 0x22 } /* Cmd RESET_WATCHDOG_TIMER */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases};
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesstatic struct {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases int port;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases uchar_t data;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases} sitka_bmc[] = {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases { SMS_COMMAND_REGISTER, SMS_WRITE_START },
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases { SMS_DATA_REGISTER, 0x18 }, /* NetFn/LUN */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases { SMS_DATA_REGISTER, 0x24 }, /* Cmd SET_WATCHDOG_TIMER */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases { SMS_DATA_REGISTER, 0x84 }, /* DataByte 1: SMS/OS no log */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases { SMS_DATA_REGISTER, 0x2 }, /* DataByte 2: Power Down */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases { SMS_DATA_REGISTER, 0x0 }, /* DataByte 3: no pre-timeout */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases { SMS_DATA_REGISTER, 0x0 }, /* DataByte 4: timer expir. */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases { SMS_DATA_REGISTER, 0xa }, /* DataByte 5: init countdown */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases { SMS_COMMAND_REGISTER, SMS_WRITE_END },
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases { SMS_DATA_REGISTER, 0x0 }, /* DataByte 6: init countdown */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases { SMS_COMMAND_REGISTER, SMS_WRITE_START },
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases { SMS_DATA_REGISTER, 0x18 }, /* NetFn/LUN */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases { SMS_COMMAND_REGISTER, SMS_WRITE_END },
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases { SMS_DATA_REGISTER, 0x22 } /* Cmd RESET_WATCHDOG_TIMER */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases};
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases/* Patchable global variables. */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesint apic_kmdb_on_nmi = 0; /* 0 - no, 1 - yes enter kmdb */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesuint32_t apic_divide_reg_init = 0; /* 0 - divide by 2 */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases/* default apic ops without interrupt remapping */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesstatic apic_intrmap_ops_t apic_nointrmap_ops = {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases (int (*)(int))return_instr,
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases (void (*)(int))return_instr,
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases (void (*)(void **, dev_info_t *, uint16_t, int, uchar_t))return_instr,
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases (void (*)(void *, void *, uint16_t, int))return_instr,
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases (void (*)(void **))return_instr,
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases apic_record_ioapic_rdt,
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases apic_record_msi,
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases};
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesapic_intrmap_ops_t *apic_vt_ops = &apic_nointrmap_ops;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesapic_cpus_info_t *apic_cpus = NULL;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasescpuset_t apic_cpumask;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesuint_t apic_picinit_called;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases/* Flag to indicate that we need to shut down all processors */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesstatic uint_t apic_shutdown_processors;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases/*
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * Probe the ioapic method for apix module. Called in apic_probe_common()
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesint
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesapic_ioapic_method_probe()
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases{
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (apix_enable == 0)
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases return (PSM_SUCCESS);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /*
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * Set IOAPIC EOI handling method. The priority from low to high is:
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * 1. IOxAPIC: with EOI register
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * 2. IOMMU interrupt mapping
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * 3. Mask-Before-EOI method for systems without boot
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * interrupt routing, such as systems with only one IOAPIC;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * NVIDIA CK8-04/MCP55 systems; systems with bridge solution
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * which disables the boot interrupt routing already.
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * 4. Directed EOI
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (apic_io_ver[0] >= 0x20)
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases apix_mul_ioapic_method = APIC_MUL_IOAPIC_IOXAPIC;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if ((apic_io_max == 1) || (apic_nvidia_io_max == apic_io_max))
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases apix_mul_ioapic_method = APIC_MUL_IOAPIC_MASK;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (apic_directed_EOI_supported())
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases apix_mul_ioapic_method = APIC_MUL_IOAPIC_DEOI;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /* fall back to pcplusmp */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (apix_mul_ioapic_method == APIC_MUL_IOAPIC_PCPLUSMP) {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /* make sure apix is after pcplusmp in /etc/mach */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases apix_enable = 0; /* go ahead with pcplusmp install next */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases return (PSM_FAILURE);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases }
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases return (PSM_SUCCESS);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases}
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases/*
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * handler for APIC Error interrupt. Just print a warning and continue
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesint
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesapic_error_intr()
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases{
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases uint_t error0, error1, error;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases uint_t i;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /*
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * We need to write before read as per 7.4.17 of system prog manual.
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * We do both and or the results to be safe
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases error0 = apic_reg_ops->apic_read(APIC_ERROR_STATUS);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases apic_reg_ops->apic_write(APIC_ERROR_STATUS, 0);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases error1 = apic_reg_ops->apic_read(APIC_ERROR_STATUS);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases error = error0 | error1;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /*
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * Clear the APIC error status (do this on all cpus that enter here)
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * (two writes are required due to the semantics of accessing the
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * error status register.)
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases apic_reg_ops->apic_write(APIC_ERROR_STATUS, 0);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases apic_reg_ops->apic_write(APIC_ERROR_STATUS, 0);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /*
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * Prevent more than 1 CPU from handling error interrupt causing
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * double printing (interleave of characters from multiple
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * CPU's when using prom_printf)
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (lock_try(&apic_error_lock) == 0)
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases return (error ? DDI_INTR_CLAIMED : DDI_INTR_UNCLAIMED);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (error) {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases#if DEBUG
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (apic_debug)
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases debug_enter("pcplusmp: APIC Error interrupt received");
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases#endif /* DEBUG */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (apic_panic_on_apic_error)
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases cmn_err(CE_PANIC,
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases "APIC Error interrupt on CPU %d. Status = %x",
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases psm_get_cpu_id(), error);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases else {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if ((error & ~APIC_CS_ERRORS) == 0) {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /* cksum error only */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases apic_error |= APIC_ERR_APIC_ERROR;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases apic_apic_error |= error;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases apic_num_apic_errors++;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases apic_num_cksum_errors++;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases } else {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /*
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * prom_printf is the best shot we have of
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * something which is problem free from
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * high level/NMI type of interrupts
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases prom_printf("APIC Error interrupt on CPU %d. "
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases "Status 0 = %x, Status 1 = %x\n",
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases psm_get_cpu_id(), error0, error1);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases apic_error |= APIC_ERR_APIC_ERROR;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases apic_apic_error |= error;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases apic_num_apic_errors++;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases for (i = 0; i < apic_error_display_delay; i++) {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases tenmicrosec();
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases }
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /*
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * provide more delay next time limited to
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * roughly 1 clock tick time
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (apic_error_display_delay < 500)
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases apic_error_display_delay *= 2;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases }
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases }
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases lock_clear(&apic_error_lock);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases return (DDI_INTR_CLAIMED);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases } else {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases lock_clear(&apic_error_lock);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases return (DDI_INTR_UNCLAIMED);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases }
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases}
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases/*
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * Turn off the mask bit in the performance counter Local Vector Table entry.
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesvoid
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesapic_cpcovf_mask_clear(void)
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases{
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases apic_reg_ops->apic_write(APIC_PCINT_VECT,
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases (apic_reg_ops->apic_read(APIC_PCINT_VECT) & ~APIC_LVT_MASK));
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases}
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases/*ARGSUSED*/
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesstatic int
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesapic_cmci_enable(xc_arg_t arg1, xc_arg_t arg2, xc_arg_t arg3)
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases{
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases apic_reg_ops->apic_write(APIC_CMCI_VECT, apic_cmci_vect);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases return (0);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases}
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases/*ARGSUSED*/
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesstatic int
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesapic_cmci_disable(xc_arg_t arg1, xc_arg_t arg2, xc_arg_t arg3)
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases{
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases apic_reg_ops->apic_write(APIC_CMCI_VECT, apic_cmci_vect | AV_MASK);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases return (0);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases}
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases/*ARGSUSED*/
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesint
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasescmci_cpu_setup(cpu_setup_t what, int cpuid, void *arg)
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases{
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases cpuset_t cpu_set;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases CPUSET_ONLY(cpu_set, cpuid);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases switch (what) {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases case CPU_ON:
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases xc_call(NULL, NULL, NULL, CPUSET2BV(cpu_set),
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases (xc_func_t)apic_cmci_enable);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases break;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases case CPU_OFF:
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases xc_call(NULL, NULL, NULL, CPUSET2BV(cpu_set),
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases (xc_func_t)apic_cmci_disable);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases break;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases default:
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases break;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases }
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases return (0);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases}
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesstatic void
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesapic_disable_local_apic(void)
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases{
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases apic_reg_ops->apic_write_task_reg(APIC_MASK_ALL);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases apic_reg_ops->apic_write(APIC_LOCAL_TIMER, AV_MASK);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /* local intr reg 0 */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases apic_reg_ops->apic_write(APIC_INT_VECT0, AV_MASK);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /* disable NMI */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases apic_reg_ops->apic_write(APIC_INT_VECT1, AV_MASK);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /* and error interrupt */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases apic_reg_ops->apic_write(APIC_ERR_VECT, AV_MASK);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /* and perf counter intr */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases apic_reg_ops->apic_write(APIC_PCINT_VECT, AV_MASK);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases apic_reg_ops->apic_write(APIC_SPUR_INT_REG, APIC_SPUR_INTR);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases}
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesstatic void
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesapic_cpu_send_SIPI(processorid_t cpun, boolean_t start)
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases{
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases int loop_count;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases uint32_t vector;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases uint_t apicid;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases ulong_t iflag;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases apicid = apic_cpus[cpun].aci_local_id;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /*
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * Interrupts on current CPU will be disabled during the
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * steps in order to avoid unwanted side effects from
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * executing interrupt handlers on a problematic BIOS.
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases iflag = intr_clear();
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (start) {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases outb(CMOS_ADDR, SSB);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases outb(CMOS_DATA, BIOS_SHUTDOWN);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases }
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /*
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * According to X2APIC specification in section '2.3.5.1' of
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * Interrupt Command Register Semantics, the semantics of
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * programming the Interrupt Command Register to dispatch an interrupt
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * is simplified. A single MSR write to the 64-bit ICR is required
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * for dispatching an interrupt. Specifically, with the 64-bit MSR
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * interface to ICR, system software is not required to check the
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * status of the delivery status bit prior to writing to the ICR
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * to send an IPI. With the removal of the Delivery Status bit,
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * system software no longer has a reason to read the ICR. It remains
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * readable only to aid in debugging.
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases#ifdef DEBUG
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases APIC_AV_PENDING_SET();
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases#else
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (apic_mode == LOCAL_APIC) {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases APIC_AV_PENDING_SET();
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases }
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases#endif /* DEBUG */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /* for integrated - make sure there is one INIT IPI in buffer */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /* for external - it will wake up the cpu */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases apic_reg_ops->apic_write_int_cmd(apicid, AV_ASSERT | AV_RESET);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /* If only 1 CPU is installed, PENDING bit will not go low */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases for (loop_count = apic_sipi_max_loop_count; loop_count; loop_count--) {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (apic_mode == LOCAL_APIC &&
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases apic_reg_ops->apic_read(APIC_INT_CMD1) & AV_PENDING)
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases apic_ret();
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases else
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases break;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases }
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases apic_reg_ops->apic_write_int_cmd(apicid, AV_DEASSERT | AV_RESET);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases drv_usecwait(20000); /* 20 milli sec */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (apic_cpus[cpun].aci_local_ver >= APIC_INTEGRATED_VERS) {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /* integrated apic */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases vector = (rm_platter_pa >> MMU_PAGESHIFT) &
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases (APIC_VECTOR_MASK | APIC_IPL_MASK);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /* to offset the INIT IPI queue up in the buffer */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases apic_reg_ops->apic_write_int_cmd(apicid, vector | AV_STARTUP);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases drv_usecwait(200); /* 20 micro sec */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /*
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * send the second SIPI (Startup IPI) as recommended by Intel
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * software development manual.
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases apic_reg_ops->apic_write_int_cmd(apicid, vector | AV_STARTUP);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases drv_usecwait(200); /* 20 micro sec */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases }
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases intr_restore(iflag);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases}
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases/*ARGSUSED1*/
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesint
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesapic_cpu_start(processorid_t cpun, caddr_t arg)
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases{
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases ASSERT(MUTEX_HELD(&cpu_lock));
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (!apic_cpu_in_range(cpun)) {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases return (EINVAL);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases }
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /*
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * Switch to apic_common_send_ipi for safety during starting other CPUs.
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (apic_mode == LOCAL_X2APIC) {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases apic_switch_ipi_callback(B_TRUE);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases }
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases apic_cmos_ssb_set = 1;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases apic_cpu_send_SIPI(cpun, B_TRUE);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases return (0);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases}
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases/*
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * Put CPU into halted state with interrupts disabled.
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases/*ARGSUSED1*/
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesint
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesapic_cpu_stop(processorid_t cpun, caddr_t arg)
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases{
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases int rc;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases cpu_t *cp;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases extern cpuset_t cpu_ready_set;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases extern void cpu_idle_intercept_cpu(cpu_t *cp);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases ASSERT(MUTEX_HELD(&cpu_lock));
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (!apic_cpu_in_range(cpun)) {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases return (EINVAL);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases }
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (apic_cpus[cpun].aci_local_ver < APIC_INTEGRATED_VERS) {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases return (ENOTSUP);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases }
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases cp = cpu_get(cpun);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases ASSERT(cp != NULL);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases ASSERT((cp->cpu_flags & CPU_OFFLINE) != 0);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases ASSERT((cp->cpu_flags & CPU_QUIESCED) != 0);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases ASSERT((cp->cpu_flags & CPU_ENABLE) == 0);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /* Clear CPU_READY flag to disable cross calls. */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases cp->cpu_flags &= ~CPU_READY;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases CPUSET_ATOMIC_DEL(cpu_ready_set, cpun);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases rc = xc_flush_cpu(cp);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (rc != 0) {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases CPUSET_ATOMIC_ADD(cpu_ready_set, cpun);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases cp->cpu_flags |= CPU_READY;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases return (rc);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases }
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /* Intercept target CPU at a safe point before powering it off. */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases cpu_idle_intercept_cpu(cp);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases apic_cpu_send_SIPI(cpun, B_FALSE);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases cp->cpu_flags &= ~CPU_RUNNING;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases return (0);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases}
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesint
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesapic_cpu_ops(psm_cpu_request_t *reqp)
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases{
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (reqp == NULL) {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases return (EINVAL);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases }
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases switch (reqp->pcr_cmd) {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases case PSM_CPU_ADD:
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases return (apic_cpu_add(reqp));
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases case PSM_CPU_REMOVE:
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases return (apic_cpu_remove(reqp));
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases case PSM_CPU_STOP:
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases return (apic_cpu_stop(reqp->req.cpu_stop.cpuid,
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases reqp->req.cpu_stop.ctx));
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases default:
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases return (ENOTSUP);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases }
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases}
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases#ifdef DEBUG
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesint apic_break_on_cpu = 9;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesint apic_stretch_interrupts = 0;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesint apic_stretch_ISR = 1 << 3; /* IPL of 3 matches nothing now */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases#endif /* DEBUG */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases/*
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * generates an interprocessor interrupt to another CPU. Any changes made to
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * this routine must be accompanied by similar changes to
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * apic_common_send_ipi().
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesvoid
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesapic_send_ipi(int cpun, int ipl)
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases{
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases int vector;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases ulong_t flag;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases vector = apic_resv_vector[ipl];
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases ASSERT((vector >= APIC_BASE_VECT) && (vector <= APIC_SPUR_INTR));
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases flag = intr_clear();
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases APIC_AV_PENDING_SET();
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases apic_reg_ops->apic_write_int_cmd(apic_cpus[cpun].aci_local_id,
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases vector);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases intr_restore(flag);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases}
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases/*ARGSUSED*/
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesvoid
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesapic_set_idlecpu(processorid_t cpun)
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases{
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases}
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases/*ARGSUSED*/
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesvoid
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesapic_unset_idlecpu(processorid_t cpun)
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases{
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases}
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesvoid
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesapic_ret()
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases{
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases}
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases/*
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * If apic_coarse_time == 1, then apic_gettime() is used instead of
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * apic_gethrtime(). This is used for performance instead of accuracy.
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayaseshrtime_t
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesapic_gettime()
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases{
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases int old_hrtime_stamp;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases hrtime_t temp;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /*
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * In one-shot mode, we do not keep time, so if anyone
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * calls psm_gettime() directly, we vector over to
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * gethrtime().
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * one-shot mode MUST NOT be enabled if this psm is the source of
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * hrtime.
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (apic_oneshot)
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases return (gethrtime());
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesgettime_again:
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases while ((old_hrtime_stamp = apic_hrtime_stamp) & 1)
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases apic_ret();
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases temp = apic_nsec_since_boot;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (apic_hrtime_stamp != old_hrtime_stamp) { /* got an interrupt */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases goto gettime_again;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases }
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases return (temp);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases}
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases/*
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * Here we return the number of nanoseconds since booting. Note every
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * clock interrupt increments apic_nsec_since_boot by the appropriate
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * amount.
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayaseshrtime_t
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesapic_gethrtime(void)
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases{
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases int curr_timeval, countval, elapsed_ticks;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases int old_hrtime_stamp, status;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases hrtime_t temp;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases uint32_t cpun;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases ulong_t oflags;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /*
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * In one-shot mode, we do not keep time, so if anyone
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * calls psm_gethrtime() directly, we vector over to
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * gethrtime().
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * one-shot mode MUST NOT be enabled if this psm is the source of
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * hrtime.
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (apic_oneshot)
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases return (gethrtime());
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases oflags = intr_clear(); /* prevent migration */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases cpun = apic_reg_ops->apic_read(APIC_LID_REG);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (apic_mode == LOCAL_APIC)
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases cpun >>= APIC_ID_BIT_OFFSET;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases lock_set(&apic_gethrtime_lock);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesgethrtime_again:
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases while ((old_hrtime_stamp = apic_hrtime_stamp) & 1)
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases apic_ret();
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /*
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * Check to see which CPU we are on. Note the time is kept on
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * the local APIC of CPU 0. If on CPU 0, simply read the current
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * counter. If on another CPU, issue a remote read command to CPU 0.
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (cpun == apic_cpus[0].aci_local_id) {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases countval = apic_reg_ops->apic_read(APIC_CURR_COUNT);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases } else {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases#ifdef DEBUG
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases APIC_AV_PENDING_SET();
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases#else
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (apic_mode == LOCAL_APIC)
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases APIC_AV_PENDING_SET();
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases#endif /* DEBUG */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases apic_reg_ops->apic_write_int_cmd(
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases apic_cpus[0].aci_local_id, APIC_CURR_ADD | AV_REMOTE);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases while ((status = apic_reg_ops->apic_read(APIC_INT_CMD1))
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases & AV_READ_PENDING) {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases apic_ret();
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases }
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (status & AV_REMOTE_STATUS) /* 1 = valid */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases countval = apic_reg_ops->apic_read(APIC_REMOTE_READ);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases else { /* 0 = invalid */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases apic_remote_hrterr++;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /*
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * return last hrtime right now, will need more
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * testing if change to retry
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases temp = apic_last_hrtime;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases lock_clear(&apic_gethrtime_lock);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases intr_restore(oflags);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases return (temp);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases }
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases }
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (countval > last_count_read)
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases countval = 0;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases else
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases last_count_read = countval;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases elapsed_ticks = apic_hertz_count - countval;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases curr_timeval = APIC_TICKS_TO_NSECS(elapsed_ticks);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases temp = apic_nsec_since_boot + curr_timeval;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (apic_hrtime_stamp != old_hrtime_stamp) { /* got an interrupt */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /* we might have clobbered last_count_read. Restore it */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases last_count_read = apic_hertz_count;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases goto gethrtime_again;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases }
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (temp < apic_last_hrtime) {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /* return last hrtime if error occurs */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases apic_hrtime_error++;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases temp = apic_last_hrtime;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases }
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases else
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases apic_last_hrtime = temp;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases lock_clear(&apic_gethrtime_lock);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases intr_restore(oflags);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases return (temp);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases}
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases/* apic NMI handler */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases/*ARGSUSED*/
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesvoid
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesapic_nmi_intr(caddr_t arg, struct regs *rp)
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases{
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (apic_shutdown_processors) {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases apic_disable_local_apic();
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases return;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases }
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases apic_error |= APIC_ERR_NMI;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (!lock_try(&apic_nmi_lock))
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases return;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases apic_num_nmis++;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (apic_kmdb_on_nmi && psm_debugger()) {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases debug_enter("NMI received: entering kmdb\n");
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases } else if (apic_panic_on_nmi) {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /* Keep panic from entering kmdb. */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases nopanicdebug = 1;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases panic("NMI received\n");
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases } else {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /*
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * prom_printf is the best shot we have of something which is
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * problem free from high level/NMI type of interrupts
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases prom_printf("NMI received\n");
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases }
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases lock_clear(&apic_nmi_lock);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases}
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesprocessorid_t
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesapic_get_next_processorid(processorid_t cpu_id)
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases{
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases int i;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (cpu_id == -1)
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases return ((processorid_t)0);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases for (i = cpu_id + 1; i < NCPU; i++) {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (apic_cpu_in_range(i))
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases return (i);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases }
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases return ((processorid_t)-1);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases}
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesint
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesapic_cpu_add(psm_cpu_request_t *reqp)
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases{
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases int i, rv = 0;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases ulong_t iflag;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases boolean_t first = B_TRUE;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases uchar_t localver;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases uint32_t localid, procid;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases processorid_t cpuid = (processorid_t)-1;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases mach_cpu_add_arg_t *ap;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases ASSERT(reqp != NULL);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases reqp->req.cpu_add.cpuid = (processorid_t)-1;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /* Check whether CPU hotplug is supported. */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (!plat_dr_support_cpu() || apic_max_nproc == -1) {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases return (ENOTSUP);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases }
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases ap = (mach_cpu_add_arg_t *)reqp->req.cpu_add.argp;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases switch (ap->type) {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases case MACH_CPU_ARG_LOCAL_APIC:
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases localid = ap->arg.apic.apic_id;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases procid = ap->arg.apic.proc_id;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (localid >= 255 || procid > 255) {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases cmn_err(CE_WARN,
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases "!apic: apicid(%u) or procid(%u) is invalid.",
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases localid, procid);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases return (EINVAL);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases }
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases break;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases case MACH_CPU_ARG_LOCAL_X2APIC:
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases localid = ap->arg.apic.apic_id;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases procid = ap->arg.apic.proc_id;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (localid >= UINT32_MAX) {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases cmn_err(CE_WARN,
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases "!apic: x2apicid(%u) is invalid.", localid);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases return (EINVAL);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases } else if (localid >= 255 && apic_mode == LOCAL_APIC) {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases cmn_err(CE_WARN, "!apic: system is in APIC mode, "
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases "can't support x2APIC processor.");
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases return (ENOTSUP);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases }
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases break;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases default:
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases cmn_err(CE_WARN,
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases "!apic: unknown argument type %d to apic_cpu_add().",
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases ap->type);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases return (EINVAL);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases }
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /* Use apic_ioapic_lock to sync with apic_get_next_bind_cpu. */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases iflag = intr_clear();
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases lock_set(&apic_ioapic_lock);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /* Check whether local APIC id already exists. */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases for (i = 0; i < apic_nproc; i++) {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (!CPU_IN_SET(apic_cpumask, i))
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases continue;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (apic_cpus[i].aci_local_id == localid) {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases lock_clear(&apic_ioapic_lock);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases intr_restore(iflag);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases cmn_err(CE_WARN,
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases "!apic: local apic id %u already exists.",
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases localid);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases return (EEXIST);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases } else if (apic_cpus[i].aci_processor_id == procid) {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases lock_clear(&apic_ioapic_lock);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases intr_restore(iflag);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases cmn_err(CE_WARN,
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases "!apic: processor id %u already exists.",
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases (int)procid);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases return (EEXIST);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases }
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /*
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * There's no local APIC version number available in MADT table,
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * so assume that all CPUs are homogeneous and use local APIC
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * version number of the first existing CPU.
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (first) {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases first = B_FALSE;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases localver = apic_cpus[i].aci_local_ver;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases }
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases }
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases ASSERT(first == B_FALSE);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /*
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * Try to assign the same cpuid if APIC id exists in the dirty cache.
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases for (i = 0; i < apic_max_nproc; i++) {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (CPU_IN_SET(apic_cpumask, i)) {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases ASSERT((apic_cpus[i].aci_status & APIC_CPU_FREE) == 0);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases continue;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases }
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases ASSERT(apic_cpus[i].aci_status & APIC_CPU_FREE);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if ((apic_cpus[i].aci_status & APIC_CPU_DIRTY) &&
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases apic_cpus[i].aci_local_id == localid &&
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases apic_cpus[i].aci_processor_id == procid) {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases cpuid = i;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases break;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases }
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases }
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /* Avoid the dirty cache and allocate fresh slot if possible. */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (cpuid == (processorid_t)-1) {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases for (i = 0; i < apic_max_nproc; i++) {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if ((apic_cpus[i].aci_status & APIC_CPU_FREE) &&
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases (apic_cpus[i].aci_status & APIC_CPU_DIRTY) == 0) {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases cpuid = i;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases break;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases }
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases }
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases }
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /* Try to find any free slot as last resort. */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (cpuid == (processorid_t)-1) {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases for (i = 0; i < apic_max_nproc; i++) {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (apic_cpus[i].aci_status & APIC_CPU_FREE) {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases cpuid = i;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases break;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases }
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases }
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases }
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (cpuid == (processorid_t)-1) {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases lock_clear(&apic_ioapic_lock);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases intr_restore(iflag);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases cmn_err(CE_NOTE,
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases "!apic: failed to allocate cpu id for processor %u.",
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases procid);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases rv = EAGAIN;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases } else if (ACPI_FAILURE(acpica_map_cpu(cpuid, procid))) {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases lock_clear(&apic_ioapic_lock);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases intr_restore(iflag);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases cmn_err(CE_NOTE,
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases "!apic: failed to build mapping for processor %u.",
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases procid);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases rv = EBUSY;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases } else {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases ASSERT(cpuid >= 0 && cpuid < NCPU);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases ASSERT(cpuid < apic_max_nproc && cpuid < max_ncpus);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases bzero(&apic_cpus[cpuid], sizeof (apic_cpus[0]));
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases apic_cpus[cpuid].aci_processor_id = procid;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases apic_cpus[cpuid].aci_local_id = localid;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases apic_cpus[cpuid].aci_local_ver = localver;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases CPUSET_ATOMIC_ADD(apic_cpumask, cpuid);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (cpuid >= apic_nproc) {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases apic_nproc = cpuid + 1;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases }
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases lock_clear(&apic_ioapic_lock);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases intr_restore(iflag);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases reqp->req.cpu_add.cpuid = cpuid;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases }
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases return (rv);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases}
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesint
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesapic_cpu_remove(psm_cpu_request_t *reqp)
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases{
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases int i;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases ulong_t iflag;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases processorid_t cpuid;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /* Check whether CPU hotplug is supported. */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (!plat_dr_support_cpu() || apic_max_nproc == -1) {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases return (ENOTSUP);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases }
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases cpuid = reqp->req.cpu_remove.cpuid;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /* Use apic_ioapic_lock to sync with apic_get_next_bind_cpu. */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases iflag = intr_clear();
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases lock_set(&apic_ioapic_lock);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (!apic_cpu_in_range(cpuid)) {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases lock_clear(&apic_ioapic_lock);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases intr_restore(iflag);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases cmn_err(CE_WARN,
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases "!apic: cpuid %d doesn't exist in apic_cpus array.",
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases cpuid);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases return (ENODEV);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases }
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases ASSERT((apic_cpus[cpuid].aci_status & APIC_CPU_FREE) == 0);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (ACPI_FAILURE(acpica_unmap_cpu(cpuid))) {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases lock_clear(&apic_ioapic_lock);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases intr_restore(iflag);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases return (ENOENT);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases }
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (cpuid == apic_nproc - 1) {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /*
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * We are removing the highest numbered cpuid so we need to
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * find the next highest cpuid as the new value for apic_nproc.
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases for (i = apic_nproc; i > 0; i--) {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (CPU_IN_SET(apic_cpumask, i - 1)) {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases apic_nproc = i;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases break;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases }
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases }
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /* at least one CPU left */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases ASSERT(i > 0);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases }
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases CPUSET_ATOMIC_DEL(apic_cpumask, cpuid);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /* mark slot as free and keep it in the dirty cache */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases apic_cpus[cpuid].aci_status = APIC_CPU_FREE | APIC_CPU_DIRTY;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases lock_clear(&apic_ioapic_lock);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases intr_restore(iflag);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases return (0);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases}
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases/*
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * Return the number of APIC clock ticks elapsed for 8245 to decrement
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * (APIC_TIME_COUNT + pit_ticks_adj) ticks.
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases */
41afdfa77f9af46beb3aaab2eccc0d9afe660d31Krishnendu Sadhukhan - Sun Microsystemsuint_t
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesapic_calibrate(volatile uint32_t *addr, uint16_t *pit_ticks_adj)
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases{
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases uint8_t pit_tick_lo;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases uint16_t pit_tick, target_pit_tick;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases uint32_t start_apic_tick, end_apic_tick;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases ulong_t iflag;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases uint32_t reg;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases reg = addr + APIC_CURR_COUNT - apicadr;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases iflag = intr_clear();
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases do {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases pit_tick_lo = inb(PITCTR0_PORT);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases pit_tick = (inb(PITCTR0_PORT) << 8) | pit_tick_lo;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases } while (pit_tick < APIC_TIME_MIN ||
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases pit_tick_lo <= APIC_LB_MIN || pit_tick_lo >= APIC_LB_MAX);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /*
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * Wait for the 8254 to decrement by 5 ticks to ensure
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * we didn't start in the middle of a tick.
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * Compare with 0x10 for the wrap around case.
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases target_pit_tick = pit_tick - 5;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases do {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases pit_tick_lo = inb(PITCTR0_PORT);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases pit_tick = (inb(PITCTR0_PORT) << 8) | pit_tick_lo;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases } while (pit_tick > target_pit_tick || pit_tick_lo < 0x10);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases start_apic_tick = apic_reg_ops->apic_read(reg);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /*
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * Wait for the 8254 to decrement by
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * (APIC_TIME_COUNT + pit_ticks_adj) ticks
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases target_pit_tick = pit_tick - APIC_TIME_COUNT;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases do {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases pit_tick_lo = inb(PITCTR0_PORT);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases pit_tick = (inb(PITCTR0_PORT) << 8) | pit_tick_lo;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases } while (pit_tick > target_pit_tick || pit_tick_lo < 0x10);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases end_apic_tick = apic_reg_ops->apic_read(reg);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases *pit_ticks_adj = target_pit_tick - pit_tick;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases intr_restore(iflag);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases return (start_apic_tick - end_apic_tick);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases}
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases/*
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * Initialise the APIC timer on the local APIC of CPU 0 to the desired
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * frequency. Note at this stage in the boot sequence, the boot processor
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * is the only active processor.
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * hertz value of 0 indicates a one-shot mode request. In this case
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * the function returns the resolution (in nanoseconds) for the hardware
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * timer interrupt. If one-shot mode capability is not available,
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * the return value will be 0. apic_enable_oneshot is a global switch
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * for disabling the functionality.
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * A non-zero positive value for hertz indicates a periodic mode request.
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * In this case the hardware will be programmed to generate clock interrupts
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * at hertz frequency and returns the resolution of interrupts in
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * nanosecond.
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesint
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesapic_clkinit(int hertz)
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases{
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases int ret;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases apic_int_busy_mark = (apic_int_busy_mark *
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases apic_sample_factor_redistribution) / 100;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases apic_int_free_mark = (apic_int_free_mark *
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases apic_sample_factor_redistribution) / 100;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases apic_diff_for_redistribution = (apic_diff_for_redistribution *
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases apic_sample_factor_redistribution) / 100;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
41afdfa77f9af46beb3aaab2eccc0d9afe660d31Krishnendu Sadhukhan - Sun Microsystems ret = apic_timer_init(hertz);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases return (ret);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases}
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases/*
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * apic_preshutdown:
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * Called early in shutdown whilst we can still access filesystems to do
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * things like loading modules which will be required to complete shutdown
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * after filesystems are all unmounted.
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesvoid
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesapic_preshutdown(int cmd, int fcn)
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases{
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases APIC_VERBOSE_POWEROFF(("apic_preshutdown(%d,%d); m=%d a=%d\n",
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases cmd, fcn, apic_poweroff_method, apic_enable_acpi));
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases}
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesvoid
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesapic_shutdown(int cmd, int fcn)
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases{
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases int restarts, attempts;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases int i;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases uchar_t byte;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases ulong_t iflag;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases hpet_acpi_fini();
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /* Send NMI to all CPUs except self to do per processor shutdown */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases iflag = intr_clear();
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases#ifdef DEBUG
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases APIC_AV_PENDING_SET();
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases#else
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (apic_mode == LOCAL_APIC)
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases APIC_AV_PENDING_SET();
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases#endif /* DEBUG */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases apic_shutdown_processors = 1;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases apic_reg_ops->apic_write(APIC_INT_CMD1,
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases AV_NMI | AV_LEVEL | AV_SH_ALL_EXCSELF);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /* restore cmos shutdown byte before reboot */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (apic_cmos_ssb_set) {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases outb(CMOS_ADDR, SSB);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases outb(CMOS_DATA, 0);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases }
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases ioapic_disable_redirection();
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /* disable apic mode if imcr present */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (apic_imcrp) {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases outb(APIC_IMCR_P1, (uchar_t)APIC_IMCR_SELECT);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases outb(APIC_IMCR_P2, (uchar_t)APIC_IMCR_PIC);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases }
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases apic_disable_local_apic();
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases intr_restore(iflag);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /* remainder of function is for shutdown cases only */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (cmd != A_SHUTDOWN)
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases return;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /*
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * Switch system back into Legacy-Mode if using ACPI and
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * not powering-off. Some BIOSes need to remain in ACPI-mode
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * for power-off to succeed (Dell Dimension 4600)
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * Do not disable ACPI while doing fastreboot
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (apic_enable_acpi && fcn != AD_POWEROFF && fcn != AD_FASTREBOOT)
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases (void) AcpiDisable();
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (fcn == AD_FASTREBOOT) {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases apic_reg_ops->apic_write(APIC_INT_CMD1,
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases AV_ASSERT | AV_RESET | AV_SH_ALL_EXCSELF);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases }
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /* remainder of function is for shutdown+poweroff case only */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (fcn != AD_POWEROFF)
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases return;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases switch (apic_poweroff_method) {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases case APIC_POWEROFF_VIA_RTC:
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /* select the extended NVRAM bank in the RTC */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases outb(CMOS_ADDR, RTC_REGA);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases byte = inb(CMOS_DATA);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases outb(CMOS_DATA, (byte | EXT_BANK));
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases outb(CMOS_ADDR, PFR_REG);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /* for Predator must toggle the PAB bit */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases byte = inb(CMOS_DATA);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /*
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * clear power active bar, wakeup alarm and
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * kickstart
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases byte &= ~(PAB_CBIT | WF_FLAG | KS_FLAG);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases outb(CMOS_DATA, byte);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /* delay before next write */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases drv_usecwait(1000);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /* for S40 the following would suffice */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases byte = inb(CMOS_DATA);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /* power active bar control bit */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases byte |= PAB_CBIT;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases outb(CMOS_DATA, byte);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases break;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases case APIC_POWEROFF_VIA_ASPEN_BMC:
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases restarts = 0;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesrestart_aspen_bmc:
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (++restarts == 3)
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases break;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases attempts = 0;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases do {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases byte = inb(MISMIC_FLAG_REGISTER);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases byte &= MISMIC_BUSY_MASK;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (byte != 0) {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases drv_usecwait(1000);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (attempts >= 3)
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases goto restart_aspen_bmc;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases ++attempts;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases }
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases } while (byte != 0);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases outb(MISMIC_CNTL_REGISTER, CC_SMS_GET_STATUS);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases byte = inb(MISMIC_FLAG_REGISTER);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases byte |= 0x1;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases outb(MISMIC_FLAG_REGISTER, byte);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases i = 0;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases for (; i < (sizeof (aspen_bmc)/sizeof (aspen_bmc[0]));
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases i++) {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases attempts = 0;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases do {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases byte = inb(MISMIC_FLAG_REGISTER);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases byte &= MISMIC_BUSY_MASK;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (byte != 0) {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases drv_usecwait(1000);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (attempts >= 3)
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases goto restart_aspen_bmc;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases ++attempts;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases }
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases } while (byte != 0);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases outb(MISMIC_CNTL_REGISTER, aspen_bmc[i].cntl);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases outb(MISMIC_DATA_REGISTER, aspen_bmc[i].data);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases byte = inb(MISMIC_FLAG_REGISTER);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases byte |= 0x1;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases outb(MISMIC_FLAG_REGISTER, byte);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases }
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases break;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases case APIC_POWEROFF_VIA_SITKA_BMC:
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases restarts = 0;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesrestart_sitka_bmc:
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (++restarts == 3)
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases break;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases attempts = 0;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases do {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases byte = inb(SMS_STATUS_REGISTER);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases byte &= SMS_STATE_MASK;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if ((byte == SMS_READ_STATE) ||
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases (byte == SMS_WRITE_STATE)) {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases drv_usecwait(1000);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (attempts >= 3)
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases goto restart_sitka_bmc;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases ++attempts;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases }
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases } while ((byte == SMS_READ_STATE) ||
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases (byte == SMS_WRITE_STATE));
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases outb(SMS_COMMAND_REGISTER, SMS_GET_STATUS);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases i = 0;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases for (; i < (sizeof (sitka_bmc)/sizeof (sitka_bmc[0]));
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases i++) {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases attempts = 0;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases do {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases byte = inb(SMS_STATUS_REGISTER);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases byte &= SMS_IBF_MASK;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (byte != 0) {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases drv_usecwait(1000);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (attempts >= 3)
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases goto restart_sitka_bmc;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases ++attempts;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases }
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases } while (byte != 0);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases outb(sitka_bmc[i].port, sitka_bmc[i].data);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases }
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases break;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases case APIC_POWEROFF_NONE:
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /* If no APIC direct method, we will try using ACPI */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (apic_enable_acpi) {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (acpi_poweroff() == 1)
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases return;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases } else
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases return;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases break;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases }
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /*
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * Wait a limited time here for power to go off.
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * If the power does not go off, then there was a
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * problem and we should continue to the halt which
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * prints a message for the user to press a key to
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * reboot.
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases drv_usecwait(7000000); /* wait seven seconds */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases}
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
a288e5a9793fdffe5e842d7e61ab45263e75eacaJoshua M. Clulowcyclic_id_t apic_cyclic_id;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases/*
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * The following functions are in the platform specific file so that they
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * can be different functions depending on whether we are running on
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * bare metal or a hypervisor.
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases/*
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * map an apic for memory-mapped access
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesuint32_t *
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesmapin_apic(uint32_t addr, size_t len, int flags)
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases{
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases return ((void *)psm_map_phys(addr, len, flags));
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases}
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesuint32_t *
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesmapin_ioapic(uint32_t addr, size_t len, int flags)
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases{
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases return (mapin_apic(addr, len, flags));
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases}
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases/*
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * unmap an apic
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesvoid
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesmapout_apic(caddr_t addr, size_t len)
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases{
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases psm_unmap_phys(addr, len);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases}
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesvoid
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesmapout_ioapic(caddr_t addr, size_t len)
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases{
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases mapout_apic(addr, len);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases}
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesuint32_t
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesioapic_read(int ioapic_ix, uint32_t reg)
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases{
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases volatile uint32_t *ioapic;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases ioapic = apicioadr[ioapic_ix];
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases ioapic[APIC_IO_REG] = reg;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases return (ioapic[APIC_IO_DATA]);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases}
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesvoid
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesioapic_write(int ioapic_ix, uint32_t reg, uint32_t value)
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases{
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases volatile uint32_t *ioapic;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases ioapic = apicioadr[ioapic_ix];
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases ioapic[APIC_IO_REG] = reg;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases ioapic[APIC_IO_DATA] = value;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases}
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesvoid
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesioapic_write_eoi(int ioapic_ix, uint32_t value)
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases{
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases volatile uint32_t *ioapic;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases ioapic = apicioadr[ioapic_ix];
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases ioapic[APIC_IO_EOI] = value;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases}
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases/*
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * Round-robin algorithm to find the next CPU with interrupts enabled.
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * It can't share the same static variable apic_next_bind_cpu with
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * apic_get_next_bind_cpu(), since that will cause all interrupts to be
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * bound to CPU1 at boot time. During boot, only CPU0 is online with
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * interrupts enabled when apic_get_next_bind_cpu() and apic_find_cpu()
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * are called. However, the pcplusmp driver assumes that there will be
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * boot_ncpus CPUs configured eventually so it tries to distribute all
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * interrupts among CPU0 - CPU[boot_ncpus - 1]. Thus to prevent all
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * interrupts being targetted at CPU1, we need to use a dedicated static
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * variable for find_next_cpu() instead of sharing apic_next_bind_cpu.
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesprocessorid_t
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesapic_find_cpu(int flag)
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases{
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases int i;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases static processorid_t acid = 0;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /* Find the first CPU with the passed-in flag set */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases for (i = 0; i < apic_nproc; i++) {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (++acid >= apic_nproc) {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases acid = 0;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases }
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (apic_cpu_in_range(acid) &&
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases (apic_cpus[acid].aci_status & flag)) {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases break;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases }
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases }
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases ASSERT((apic_cpus[acid].aci_status & flag) != 0);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases return (acid);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases}
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases/*
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * Switch between safe and x2APIC IPI sending method.
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * CPU may power on in xapic mode or x2apic mode. If CPU needs to send IPI to
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * other CPUs before entering x2APIC mode, it still needs to xAPIC method.
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * Before sending StartIPI to target CPU, psm_send_ipi will be changed to
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * apic_common_send_ipi, which detects current local APIC mode and use right
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * method to send IPI. If some CPUs fail to start up, apic_poweron_cnt
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * won't return to zero, so apic_common_send_ipi will always be used.
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * psm_send_ipi can't be simply changed back to x2apic_send_ipi if some CPUs
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * failed to start up because those failed CPUs may recover itself later at
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * unpredictable time.
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesvoid
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesapic_switch_ipi_callback(boolean_t enter)
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases{
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases ulong_t iflag;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases struct psm_ops *pops = psmops;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases iflag = intr_clear();
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases lock_set(&apic_mode_switch_lock);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (enter) {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases ASSERT(apic_poweron_cnt >= 0);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (apic_poweron_cnt == 0) {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases pops->psm_send_ipi = apic_common_send_ipi;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases send_dirintf = pops->psm_send_ipi;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases }
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases apic_poweron_cnt++;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases } else {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases ASSERT(apic_poweron_cnt > 0);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases apic_poweron_cnt--;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (apic_poweron_cnt == 0) {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases pops->psm_send_ipi = x2apic_send_ipi;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases send_dirintf = pops->psm_send_ipi;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases }
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases }
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases lock_clear(&apic_mode_switch_lock);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases intr_restore(iflag);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases}
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesvoid
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesapic_intrmap_init(int apic_mode)
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases{
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases int suppress_brdcst_eoi = 0;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
1a9079eeb6a460980656d5e022ec89bbbfb84732Josef 'Jeff' Sipek /*
1a9079eeb6a460980656d5e022ec89bbbfb84732Josef 'Jeff' Sipek * Intel Software Developer's Manual 3A, 10.12.7:
1a9079eeb6a460980656d5e022ec89bbbfb84732Josef 'Jeff' Sipek *
1a9079eeb6a460980656d5e022ec89bbbfb84732Josef 'Jeff' Sipek * Routing of device interrupts to local APIC units operating in
1a9079eeb6a460980656d5e022ec89bbbfb84732Josef 'Jeff' Sipek * x2APIC mode requires use of the interrupt-remapping architecture
1a9079eeb6a460980656d5e022ec89bbbfb84732Josef 'Jeff' Sipek * specified in the Intel Virtualization Technology for Directed
1a9079eeb6a460980656d5e022ec89bbbfb84732Josef 'Jeff' Sipek * I/O, Revision 1.3. Because of this, BIOS must enumerate support
1a9079eeb6a460980656d5e022ec89bbbfb84732Josef 'Jeff' Sipek * for and software must enable this interrupt remapping with
1a9079eeb6a460980656d5e022ec89bbbfb84732Josef 'Jeff' Sipek * Extended Interrupt Mode Enabled before it enabling x2APIC mode in
1a9079eeb6a460980656d5e022ec89bbbfb84732Josef 'Jeff' Sipek * the local APIC units.
1a9079eeb6a460980656d5e022ec89bbbfb84732Josef 'Jeff' Sipek *
1a9079eeb6a460980656d5e022ec89bbbfb84732Josef 'Jeff' Sipek *
1a9079eeb6a460980656d5e022ec89bbbfb84732Josef 'Jeff' Sipek * In other words, to use the APIC in x2APIC mode, we need interrupt
1a9079eeb6a460980656d5e022ec89bbbfb84732Josef 'Jeff' Sipek * remapping. Since we don't start up the IOMMU by default, we
1a9079eeb6a460980656d5e022ec89bbbfb84732Josef 'Jeff' Sipek * won't be able to do any interrupt remapping and therefore have to
1a9079eeb6a460980656d5e022ec89bbbfb84732Josef 'Jeff' Sipek * use the APIC in traditional 'local APIC' mode with memory mapped
1a9079eeb6a460980656d5e022ec89bbbfb84732Josef 'Jeff' Sipek * I/O.
1a9079eeb6a460980656d5e022ec89bbbfb84732Josef 'Jeff' Sipek */
1a9079eeb6a460980656d5e022ec89bbbfb84732Josef 'Jeff' Sipek
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (psm_vt_ops != NULL) {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (((apic_intrmap_ops_t *)psm_vt_ops)->
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases apic_intrmap_init(apic_mode) == DDI_SUCCESS) {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases apic_vt_ops = psm_vt_ops;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /*
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * We leverage the interrupt remapping engine to
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * suppress broadcast EOI; thus we must send the
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * directed EOI with the directed-EOI handler.
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (apic_directed_EOI_supported() == 0) {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases suppress_brdcst_eoi = 1;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases }
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases apic_vt_ops->apic_intrmap_enable(suppress_brdcst_eoi);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (apic_detect_x2apic()) {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases apic_enable_x2apic();
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases }
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (apic_directed_EOI_supported() == 0) {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases apic_set_directed_EOI_handler();
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases }
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases }
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases }
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases}
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases/*ARGSUSED*/
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesstatic void
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesapic_record_ioapic_rdt(void *intrmap_private, ioapic_rdt_t *irdt)
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases{
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases irdt->ir_hi <<= APIC_ID_BIT_OFFSET;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases}
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases/*ARGSUSED*/
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesstatic void
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesapic_record_msi(void *intrmap_private, msi_regs_t *mregs)
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases{
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases mregs->mr_addr = MSI_ADDR_HDR |
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases (MSI_ADDR_RH_FIXED << MSI_ADDR_RH_SHIFT) |
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases (MSI_ADDR_DM_PHYSICAL << MSI_ADDR_DM_SHIFT) |
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases (mregs->mr_addr << MSI_ADDR_DEST_SHIFT);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases mregs->mr_data = (MSI_DATA_TM_EDGE << MSI_DATA_TM_SHIFT) |
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases mregs->mr_data;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases}
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases/*
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * Functions from apic_introp.c
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases *
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * Those functions are used by apic_intr_ops().
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases/*
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * MSI support flag:
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * reflects whether MSI is supported at APIC level
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * it can also be patched through /etc/system
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases *
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * 0 = default value - don't know and need to call apic_check_msi_support()
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * to find out then set it accordingly
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * 1 = supported
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * -1 = not supported
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesint apic_support_msi = 0;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases/* Multiple vector support for MSI-X */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesint apic_msix_enable = 1;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases/* Multiple vector support for MSI */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesint apic_multi_msi_enable = 1;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases/*
970db7b7a5b4656c659fc7c5226da7be313dc336Dan Kimmel * Check whether the system supports MSI.
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases *
970db7b7a5b4656c659fc7c5226da7be313dc336Dan Kimmel * MSI is required for PCI-E and for PCI versions later than 2.2, so if we find
970db7b7a5b4656c659fc7c5226da7be313dc336Dan Kimmel * a PCI-E bus or we find a PCI bus whose version we know is >= 2.2, then we
970db7b7a5b4656c659fc7c5226da7be313dc336Dan Kimmel * return PSM_SUCCESS to indicate this system supports MSI.
970db7b7a5b4656c659fc7c5226da7be313dc336Dan Kimmel *
970db7b7a5b4656c659fc7c5226da7be313dc336Dan Kimmel * (Currently the only way we check whether a given PCI bus supports >= 2.2 is
970db7b7a5b4656c659fc7c5226da7be313dc336Dan Kimmel * by detecting if we are running inside the KVM hypervisor, which guarantees
970db7b7a5b4656c659fc7c5226da7be313dc336Dan Kimmel * this version number.)
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesint
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesapic_check_msi_support()
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases{
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases dev_info_t *cdip;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases char dev_type[16];
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases int dev_len;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases DDI_INTR_IMPLDBG((CE_CONT, "apic_check_msi_support:\n"));
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /*
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * check whether the first level children of root_node have
970db7b7a5b4656c659fc7c5226da7be313dc336Dan Kimmel * PCI-E or PCI capability.
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases for (cdip = ddi_get_child(ddi_root_node()); cdip != NULL;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases cdip = ddi_get_next_sibling(cdip)) {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases DDI_INTR_IMPLDBG((CE_CONT, "apic_check_msi_support: cdip: 0x%p,"
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases " driver: %s, binding: %s, nodename: %s\n", (void *)cdip,
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases ddi_driver_name(cdip), ddi_binding_name(cdip),
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases ddi_node_name(cdip)));
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases dev_len = sizeof (dev_type);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (ddi_getlongprop_buf(DDI_DEV_T_ANY, cdip, DDI_PROP_DONTPASS,
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases "device_type", (caddr_t)dev_type, &dev_len)
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases != DDI_PROP_SUCCESS)
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases continue;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (strcmp(dev_type, "pciex") == 0)
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases return (PSM_SUCCESS);
970db7b7a5b4656c659fc7c5226da7be313dc336Dan Kimmel if (strcmp(dev_type, "pci") == 0 && get_hwenv() == HW_KVM)
970db7b7a5b4656c659fc7c5226da7be313dc336Dan Kimmel return (PSM_SUCCESS);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases }
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /* MSI is not supported on this system */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases DDI_INTR_IMPLDBG((CE_CONT, "apic_check_msi_support: no 'pciex' "
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases "device_type found\n"));
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases return (PSM_FAILURE);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases}
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases/*
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * apic_pci_msi_unconfigure:
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases *
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * This and next two interfaces are copied from pci_intr_lib.c
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * Do ensure that these two files stay in sync.
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * These needed to be copied over here to avoid a deadlock situation on
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * certain mp systems that use MSI interrupts.
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases *
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * IMPORTANT regards next three interfaces:
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * i) are called only for MSI/X interrupts.
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * ii) called with interrupts disabled, and must not block
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesvoid
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesapic_pci_msi_unconfigure(dev_info_t *rdip, int type, int inum)
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases{
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases ushort_t msi_ctrl;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases int cap_ptr = i_ddi_get_msi_msix_cap_ptr(rdip);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases ddi_acc_handle_t handle = i_ddi_get_pci_config_handle(rdip);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases ASSERT((handle != NULL) && (cap_ptr != 0));
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (type == DDI_INTR_TYPE_MSI) {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases msi_ctrl = pci_config_get16(handle, cap_ptr + PCI_MSI_CTRL);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases msi_ctrl &= (~PCI_MSI_MME_MASK);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases pci_config_put16(handle, cap_ptr + PCI_MSI_CTRL, msi_ctrl);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases pci_config_put32(handle, cap_ptr + PCI_MSI_ADDR_OFFSET, 0);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (msi_ctrl & PCI_MSI_64BIT_MASK) {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases pci_config_put16(handle,
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases cap_ptr + PCI_MSI_64BIT_DATA, 0);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases pci_config_put32(handle,
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases cap_ptr + PCI_MSI_ADDR_OFFSET + 4, 0);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases } else {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases pci_config_put16(handle,
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases cap_ptr + PCI_MSI_32BIT_DATA, 0);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases }
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases } else if (type == DDI_INTR_TYPE_MSIX) {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases uintptr_t off;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases uint32_t mask;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases ddi_intr_msix_t *msix_p = i_ddi_get_msix(rdip);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases ASSERT(msix_p != NULL);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /* Offset into "inum"th entry in the MSI-X table & mask it */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases off = (uintptr_t)msix_p->msix_tbl_addr + (inum *
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases PCI_MSIX_VECTOR_SIZE) + PCI_MSIX_VECTOR_CTRL_OFFSET;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases mask = ddi_get32(msix_p->msix_tbl_hdl, (uint32_t *)off);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases ddi_put32(msix_p->msix_tbl_hdl, (uint32_t *)off, (mask | 1));
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /* Offset into the "inum"th entry in the MSI-X table */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases off = (uintptr_t)msix_p->msix_tbl_addr +
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases (inum * PCI_MSIX_VECTOR_SIZE);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /* Reset the "data" and "addr" bits */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases ddi_put32(msix_p->msix_tbl_hdl,
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases (uint32_t *)(off + PCI_MSIX_DATA_OFFSET), 0);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases ddi_put64(msix_p->msix_tbl_hdl, (uint64_t *)off, 0);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases }
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases}
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases/*
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * apic_pci_msi_disable_mode:
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesvoid
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesapic_pci_msi_disable_mode(dev_info_t *rdip, int type)
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases{
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases ushort_t msi_ctrl;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases int cap_ptr = i_ddi_get_msi_msix_cap_ptr(rdip);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases ddi_acc_handle_t handle = i_ddi_get_pci_config_handle(rdip);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases ASSERT((handle != NULL) && (cap_ptr != 0));
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (type == DDI_INTR_TYPE_MSI) {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases msi_ctrl = pci_config_get16(handle, cap_ptr + PCI_MSI_CTRL);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (!(msi_ctrl & PCI_MSI_ENABLE_BIT))
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases return;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases msi_ctrl &= ~PCI_MSI_ENABLE_BIT; /* MSI disable */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases pci_config_put16(handle, cap_ptr + PCI_MSI_CTRL, msi_ctrl);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases } else if (type == DDI_INTR_TYPE_MSIX) {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases msi_ctrl = pci_config_get16(handle, cap_ptr + PCI_MSIX_CTRL);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (msi_ctrl & PCI_MSIX_ENABLE_BIT) {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases msi_ctrl &= ~PCI_MSIX_ENABLE_BIT;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases pci_config_put16(handle, cap_ptr + PCI_MSIX_CTRL,
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases msi_ctrl);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases }
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases }
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases}
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesuint32_t
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesapic_get_localapicid(uint32_t cpuid)
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases{
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases ASSERT(cpuid < apic_nproc && apic_cpus != NULL);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases return (apic_cpus[cpuid].aci_local_id);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases}
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesuchar_t
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesapic_get_ioapicid(uchar_t ioapicindex)
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases{
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases ASSERT(ioapicindex < MAX_IO_APIC);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases return (apic_io_id[ioapicindex]);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases}