OpenGrok

Cross Reference: mp_platform_common.c
xref: /onnv/onnv-gate/usr/src/uts/i86pc/io/mp_platform_common.c
Home | History | Annotate | Line # | Download | only in io
      1 /*
      2  * CDDL HEADER START
      3  *
      4  * The contents of this file are subject to the terms of the
      5  * Common Development and Distribution License (the "License").
      6  * You may not use this file except in compliance with the License.
      7  *
      8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9  * or http://www.opensolaris.org/os/licensing.
     10  * See the License for the specific language governing permissions
     11  * and limitations under the License.
     12  *
     13  * When distributing Covered Code, include this CDDL HEADER in each
     14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15  * If applicable, add the following below this CDDL HEADER, with the
     16  * fields enclosed by brackets "[]" replaced with your own identifying
     17  * information: Portions Copyright [yyyy] [name of copyright owner]
     18  *
     19  * CDDL HEADER END
     20  */
     21 /*
     22  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
     23  */
     24 /*
     25  * Copyright (c) 2010, Intel Corporation.
     26  * All rights reserved.
     27  */
     28 
     29 /*
     30  * PSMI 1.1 extensions are supported only in 2.6 and later versions.
     31  * PSMI 1.2 extensions are supported only in 2.7 and later versions.
     32  * PSMI 1.3 and 1.4 extensions are supported in Solaris 10.
     33  * PSMI 1.5 extensions are supported in Solaris Nevada.
     34  * PSMI 1.6 extensions are supported in Solaris Nevada.
     35  * PSMI 1.7 extensions are supported in Solaris Nevada.
     36  */
     37 #define	PSMI_1_7
     38 
     39 #include <sys/processor.h>
     40 #include <sys/time.h>
     41 #include <sys/psm.h>
     42 #include <sys/smp_impldefs.h>
     43 #include <sys/cram.h>
     44 #include <sys/acpi/acpi.h>
     45 #include <sys/acpica.h>
     46 #include <sys/psm_common.h>
     47 #include <sys/apic.h>
     48 #include <sys/apic_timer.h>
     49 #include <sys/pit.h>
     50 #include <sys/ddi.h>
     51 #include <sys/sunddi.h>
     52 #include <sys/ddi_impldefs.h>
     53 #include <sys/pci.h>
     54 #include <sys/promif.h>
     55 #include <sys/x86_archext.h>
     56 #include <sys/cpc_impl.h>
     57 #include <sys/uadmin.h>
     58 #include <sys/panic.h>
     59 #include <sys/debug.h>
     60 #include <sys/archsystm.h>
     61 #include <sys/trap.h>
     62 #include <sys/machsystm.h>
     63 #include <sys/cpuvar.h>
     64 #include <sys/rm_platter.h>
     65 #include <sys/privregs.h>
     66 #include <sys/cyclic.h>
     67 #include <sys/note.h>
     68 #include <sys/pci_intr_lib.h>
     69 #include <sys/sunndi.h>
     70 #if !defined(__xpv)
     71 #include <sys/hpet.h>
     72 #include <sys/clock.h>
     73 #endif
     74 
     75 /*
     76  *	Local Function Prototypes
     77  */
     78 static int apic_handle_defconf();
     79 static int apic_parse_mpct(caddr_t mpct, int bypass);
     80 static struct apic_mpfps_hdr *apic_find_fps_sig(caddr_t fptr, int size);
     81 static int apic_checksum(caddr_t bptr, int len);
     82 static int apic_find_bus_type(char *bus);
     83 static int apic_find_bus(int busid);
     84 static struct apic_io_intr *apic_find_io_intr(int irqno);
     85 static int apic_find_free_irq(int start, int end);
     86 struct apic_io_intr *apic_find_io_intr_w_busid(int irqno, int busid);
     87 static void apic_set_pwroff_method_from_mpcnfhdr(struct apic_mp_cnf_hdr *hdrp);
     88 static void apic_free_apic_cpus(void);
     89 static boolean_t apic_is_ioapic_AMD_813x(uint32_t physaddr);
     90 static int apic_acpi_enter_apicmode(void);
     91 
     92 int apic_handle_pci_pci_bridge(dev_info_t *idip, int child_devno,
     93     int child_ipin, struct apic_io_intr **intrp);
     94 int apic_find_bus_id(int bustype);
     95 int apic_find_intin(uchar_t ioapic, uchar_t intin);
     96 void apic_record_rdt_entry(apic_irq_t *irqptr, int irq);
     97 
     98 int apic_debug_mps_id = 0;	/* 1 - print MPS ID strings */
     99 
    100 /* ACPI SCI interrupt configuration; -1 if SCI not used */
    101 int apic_sci_vect = -1;
    102 iflag_t apic_sci_flags;
    103 
    104 #if !defined(__xpv)
    105 /* ACPI HPET interrupt configuration; -1 if HPET not used */
    106 int apic_hpet_vect = -1;
    107 iflag_t apic_hpet_flags;
    108 #endif
    109 
    110 /*
    111  * psm name pointer
    112  */
    113 char *psm_name;
    114 
    115 /* ACPI support routines */
    116 static int acpi_probe(char *);
    117 static int apic_acpi_irq_configure(acpi_psm_lnk_t *acpipsmlnkp, dev_info_t *dip,
    118     int *pci_irqp, iflag_t *intr_flagp);
    119 
    120 int apic_acpi_translate_pci_irq(dev_info_t *dip, int busid, int devid,
    121     int ipin, int *pci_irqp, iflag_t *intr_flagp);
    122 uchar_t acpi_find_ioapic(int irq);
    123 static int acpi_intr_compatible(iflag_t iflag1, iflag_t iflag2);
    124 
    125 /* Max wait time (in repetitions) for flags to clear in an RDT entry. */
    126 int apic_max_reps_clear_pending = 1000;
    127 
    128 int	apic_intr_policy = INTR_ROUND_ROBIN;
    129 
    130 int	apic_next_bind_cpu = 1; /* For round robin assignment */
    131 				/* start with cpu 1 */
    132 
    133 /*
    134  * If enabled, the distribution works as follows:
    135  * On every interrupt entry, the current ipl for the CPU is set in cpu_info
    136  * and the irq corresponding to the ipl is also set in the aci_current array.
    137  * interrupt exit and setspl (due to soft interrupts) will cause the current
    138  * ipl to be be changed. This is cache friendly as these frequently used
    139  * paths write into a per cpu structure.
    140  *
    141  * Sampling is done by checking the structures for all CPUs and incrementing
    142  * the busy field of the irq (if any) executing on each CPU and the busy field
    143  * of the corresponding CPU.
    144  * In periodic mode this is done on every clock interrupt.
    145  * In one-shot mode, this is done thru a cyclic with an interval of
    146  * apic_redistribute_sample_interval (default 10 milli sec).
    147  *
    148  * Every apic_sample_factor_redistribution times we sample, we do computations
    149  * to decide which interrupt needs to be migrated (see comments
    150  * before apic_intr_redistribute().
    151  */
    152 
    153 /*
    154  * Following 3 variables start as % and can be patched or set using an
    155  * API to be defined in future. They will be scaled to
    156  * sample_factor_redistribution which is in turn set to hertz+1 (in periodic
    157  * mode), or 101 in one-shot mode to stagger it away from one sec processing
    158  */
    159 
    160 int	apic_int_busy_mark = 60;
    161 int	apic_int_free_mark = 20;
    162 int	apic_diff_for_redistribution = 10;
    163 
    164 /* sampling interval for interrupt redistribution for dynamic migration */
    165 int	apic_redistribute_sample_interval = NANOSEC / 100; /* 10 millisec */
    166 
    167 /*
    168  * number of times we sample before deciding to redistribute interrupts
    169  * for dynamic migration
    170  */
    171 int	apic_sample_factor_redistribution = 101;
    172 
    173 int	apic_redist_cpu_skip = 0;
    174 int	apic_num_imbalance = 0;
    175 int	apic_num_rebind = 0;
    176 
    177 /*
    178  * Maximum number of APIC CPUs in the system, -1 indicates that dynamic
    179  * allocation of CPU ids is disabled.
    180  */
    181 int 	apic_max_nproc = -1;
    182 int	apic_nproc = 0;
    183 size_t	apic_cpus_size = 0;
    184 int	apic_defconf = 0;
    185 int	apic_irq_translate = 0;
    186 int	apic_spec_rev = 0;
    187 int	apic_imcrp = 0;
    188 
    189 int	apic_use_acpi = 1;	/* 1 = use ACPI, 0 = don't use ACPI */
    190 int	apic_use_acpi_madt_only = 0;	/* 1=ONLY use MADT from ACPI */
    191 
    192 /*
    193  * For interrupt link devices, if apic_unconditional_srs is set, an irq resource
    194  * will be assigned (via _SRS). If it is not set, use the current
    195  * irq setting (via _CRS), but only if that irq is in the set of possible
    196  * irqs (returned by _PRS) for the device.
    197  */
    198 int	apic_unconditional_srs = 1;
    199 
    200 /*
    201  * For interrupt link devices, if apic_prefer_crs is set when we are
    202  * assigning an IRQ resource to a device, prefer the current IRQ setting
    203  * over other possible irq settings under same conditions.
    204  */
    205 
    206 int	apic_prefer_crs = 1;
    207 
    208 uchar_t apic_io_id[MAX_IO_APIC];
    209 volatile uint32_t *apicioadr[MAX_IO_APIC];
    210 uchar_t	apic_io_ver[MAX_IO_APIC];
    211 uchar_t	apic_io_vectbase[MAX_IO_APIC];
    212 uchar_t	apic_io_vectend[MAX_IO_APIC];
    213 uchar_t apic_reserved_irqlist[MAX_ISA_IRQ + 1];
    214 uint32_t apic_physaddr[MAX_IO_APIC];
    215 
    216 boolean_t ioapic_mask_workaround[MAX_IO_APIC];
    217 
    218 /*
    219  * First available slot to be used as IRQ index into the apic_irq_table
    220  * for those interrupts (like MSI/X) that don't have a physical IRQ.
    221  */
    222 int apic_first_avail_irq  = APIC_FIRST_FREE_IRQ;
    223 
    224 /*
    225  * apic_ioapic_lock protects the ioapics (reg select), the status, temp_bound
    226  * and bound elements of cpus_info and the temp_cpu element of irq_struct
    227  */
    228 lock_t	apic_ioapic_lock;
    229 
    230 int	apic_io_max = 0;	/* no. of i/o apics enabled */
    231 
    232 struct apic_io_intr *apic_io_intrp = NULL;
    233 static	struct apic_bus	*apic_busp;
    234 
    235 uchar_t	apic_resv_vector[MAXIPL+1];
    236 
    237 char	apic_level_intr[APIC_MAX_VECTOR+1];
    238 
    239 uint32_t	eisa_level_intr_mask = 0;
    240 	/* At least MSB will be set if EISA bus */
    241 
    242 int	apic_pci_bus_total = 0;
    243 uchar_t	apic_single_pci_busid = 0;
    244 
    245 /*
    246  * airq_mutex protects additions to the apic_irq_table - the first
    247  * pointer and any airq_nexts off of that one. It also protects
    248  * apic_max_device_irq & apic_min_device_irq. It also guarantees
    249  * that share_id is unique as new ids are generated only when new
    250  * irq_t structs are linked in. Once linked in the structs are never
    251  * deleted. temp_cpu & mps_intr_index field indicate if it is programmed
    252  * or allocated. Note that there is a slight gap between allocating in
    253  * apic_introp_xlate and programming in addspl.
    254  */
    255 kmutex_t	airq_mutex;
    256 apic_irq_t	*apic_irq_table[APIC_MAX_VECTOR+1];
    257 int		apic_max_device_irq = 0;
    258 int		apic_min_device_irq = APIC_MAX_VECTOR;
    259 
    260 typedef struct prs_irq_list_ent {
    261 	int			list_prio;
    262 	int32_t			irq;
    263 	iflag_t			intrflags;
    264 	acpi_prs_private_t	prsprv;
    265 	struct prs_irq_list_ent	*next;
    266 } prs_irq_list_t;
    267 
    268 
    269 /*
    270  * ACPI variables
    271  */
    272 /* 1 = acpi is enabled & working, 0 = acpi is not enabled or not there */
    273 int apic_enable_acpi = 0;
    274 
    275 /* ACPI Multiple APIC Description Table ptr */
    276 static	ACPI_TABLE_MADT *acpi_mapic_dtp = NULL;
    277 
    278 /* ACPI Interrupt Source Override Structure ptr */
    279 ACPI_MADT_INTERRUPT_OVERRIDE *acpi_isop = NULL;
    280 int acpi_iso_cnt = 0;
    281 
    282 /* ACPI Non-maskable Interrupt Sources ptr */
    283 static	ACPI_MADT_NMI_SOURCE *acpi_nmi_sp = NULL;
    284 static	int acpi_nmi_scnt = 0;
    285 static	ACPI_MADT_LOCAL_APIC_NMI *acpi_nmi_cp = NULL;
    286 static	int acpi_nmi_ccnt = 0;
    287 
    288 /*
    289  * The following added to identify a software poweroff method if available.
    290  */
    291 
    292 static struct {
    293 	int	poweroff_method;
    294 	char	oem_id[APIC_MPS_OEM_ID_LEN + 1];	/* MAX + 1 for NULL */
    295 	char	prod_id[APIC_MPS_PROD_ID_LEN + 1];	/* MAX + 1 for NULL */
    296 } apic_mps_ids[] = {
    297 	{ APIC_POWEROFF_VIA_RTC,	"INTEL",	"ALDER" },   /* 4300 */
    298 	{ APIC_POWEROFF_VIA_RTC,	"NCR",		"AMC" },    /* 4300 */
    299 	{ APIC_POWEROFF_VIA_ASPEN_BMC,	"INTEL",	"A450NX" },  /* 4400? */
    300 	{ APIC_POWEROFF_VIA_ASPEN_BMC,	"INTEL",	"AD450NX" }, /* 4400 */
    301 	{ APIC_POWEROFF_VIA_ASPEN_BMC,	"INTEL",	"AC450NX" }, /* 4400R */
    302 	{ APIC_POWEROFF_VIA_SITKA_BMC,	"INTEL",	"S450NX" },  /* S50  */
    303 	{ APIC_POWEROFF_VIA_SITKA_BMC,	"INTEL",	"SC450NX" }  /* S50? */
    304 };
    305 
    306 int	apic_poweroff_method = APIC_POWEROFF_NONE;
    307 
    308 /*
    309  * Auto-configuration routines
    310  */
    311 
    312 /*
    313  * Look at MPSpec 1.4 (Intel Order # 242016-005) for details of what we do here
    314  * May work with 1.1 - but not guaranteed.
    315  * According to the MP Spec, the MP floating pointer structure
    316  * will be searched in the order described below:
    317  * 1. In the first kilobyte of Extended BIOS Data Area (EBDA)
    318  * 2. Within the last kilobyte of system base memory
    319  * 3. In the BIOS ROM address space between 0F0000h and 0FFFFh
    320  * Once we find the right signature with proper checksum, we call
    321  * either handle_defconf or parse_mpct to get all info necessary for
    322  * subsequent operations.
    323  */
    324 int
    325 apic_probe_common(char *modname)
    326 {
    327 	uint32_t mpct_addr, ebda_start = 0, base_mem_end;
    328 	caddr_t	biosdatap;
    329 	caddr_t	mpct = 0;
    330 	caddr_t	fptr;
    331 	int	i, mpct_size, mapsize, retval = PSM_FAILURE;
    332 	ushort_t	ebda_seg, base_mem_size;
    333 	struct	apic_mpfps_hdr	*fpsp;
    334 	struct	apic_mp_cnf_hdr	*hdrp;
    335 	int bypass_cpu_and_ioapics_in_mptables;
    336 	int acpi_user_options;
    337 
    338 	if (apic_forceload < 0)
    339 		return (retval);
    340 
    341 	/*
    342 	 * Remember who we are
    343 	 */
    344 	psm_name = modname;
    345 
    346 	/* Allow override for MADT-only mode */
    347 	acpi_user_options = ddi_prop_get_int(DDI_DEV_T_ANY, ddi_root_node(), 0,
    348 	    "acpi-user-options", 0);
    349 	apic_use_acpi_madt_only = ((acpi_user_options & ACPI_OUSER_MADT) != 0);
    350 
    351 	/* Allow apic_use_acpi to override MADT-only mode */
    352 	if (!apic_use_acpi)
    353 		apic_use_acpi_madt_only = 0;
    354 
    355 	retval = acpi_probe(modname);
    356 
    357 	/*
    358 	 * mapin the bios data area 40:0
    359 	 * 40:13h - two-byte location reports the base memory size
    360 	 * 40:0Eh - two-byte location for the exact starting address of
    361 	 *	    the EBDA segment for EISA
    362 	 */
    363 	biosdatap = psm_map_phys(0x400, 0x20, PROT_READ);
    364 	if (!biosdatap)
    365 		goto apic_ret;
    366 	fpsp = (struct apic_mpfps_hdr *)NULL;
    367 	mapsize = MPFPS_RAM_WIN_LEN;
    368 	/*LINTED: pointer cast may result in improper alignment */
    369 	ebda_seg = *((ushort_t *)(biosdatap+0xe));
    370 	/* check the 1k of EBDA */
    371 	if (ebda_seg) {
    372 		ebda_start = ((uint32_t)ebda_seg) << 4;
    373 		fptr = psm_map_phys(ebda_start, MPFPS_RAM_WIN_LEN, PROT_READ);
    374 		if (fptr) {
    375 			if (!(fpsp =
    376 			    apic_find_fps_sig(fptr, MPFPS_RAM_WIN_LEN)))
    377 				psm_unmap_phys(fptr, MPFPS_RAM_WIN_LEN);
    378 		}
    379 	}
    380 	/* If not in EBDA, check the last k of system base memory */
    381 	if (!fpsp) {
    382 		/*LINTED: pointer cast may result in improper alignment */
    383 		base_mem_size = *((ushort_t *)(biosdatap + 0x13));
    384 
    385 		if (base_mem_size > 512)
    386 			base_mem_end = 639 * 1024;
    387 		else
    388 			base_mem_end = 511 * 1024;
    389 		/* if ebda == last k of base mem, skip to check BIOS ROM */
    390 		if (base_mem_end != ebda_start) {
    391 
    392 			fptr = psm_map_phys(base_mem_end, MPFPS_RAM_WIN_LEN,
    393 			    PROT_READ);
    394 
    395 			if (fptr) {
    396 				if (!(fpsp = apic_find_fps_sig(fptr,
    397 				    MPFPS_RAM_WIN_LEN)))
    398 					psm_unmap_phys(fptr, MPFPS_RAM_WIN_LEN);
    399 			}
    400 		}
    401 	}
    402 	psm_unmap_phys(biosdatap, 0x20);
    403 
    404 	/* If still cannot find it, check the BIOS ROM space */
    405 	if (!fpsp) {
    406 		mapsize = MPFPS_ROM_WIN_LEN;
    407 		fptr = psm_map_phys(MPFPS_ROM_WIN_START,
    408 		    MPFPS_ROM_WIN_LEN, PROT_READ);
    409 		if (fptr) {
    410 			if (!(fpsp =
    411 			    apic_find_fps_sig(fptr, MPFPS_ROM_WIN_LEN))) {
    412 				psm_unmap_phys(fptr, MPFPS_ROM_WIN_LEN);
    413 				goto apic_ret;
    414 			}
    415 		}
    416 	}
    417 
    418 	if (apic_checksum((caddr_t)fpsp, fpsp->mpfps_length * 16) != 0) {
    419 		psm_unmap_phys(fptr, MPFPS_ROM_WIN_LEN);
    420 		goto apic_ret;
    421 	}
    422 
    423 	apic_spec_rev = fpsp->mpfps_spec_rev;
    424 	if ((apic_spec_rev != 04) && (apic_spec_rev != 01)) {
    425 		psm_unmap_phys(fptr, MPFPS_ROM_WIN_LEN);
    426 		goto apic_ret;
    427 	}
    428 
    429 	/* check IMCR is present or not */
    430 	apic_imcrp = fpsp->mpfps_featinfo2 & MPFPS_FEATINFO2_IMCRP;
    431 
    432 	/* check default configuration (dual CPUs) */
    433 	if ((apic_defconf = fpsp->mpfps_featinfo1) != 0) {
    434 		psm_unmap_phys(fptr, mapsize);
    435 		if ((retval = apic_handle_defconf()) != PSM_SUCCESS)
    436 			return (retval);
    437 
    438 		goto apic_ret;
    439 	}
    440 
    441 	/* MP Configuration Table */
    442 	mpct_addr = (uint32_t)(fpsp->mpfps_mpct_paddr);
    443 
    444 	psm_unmap_phys(fptr, mapsize); /* unmap floating ptr struct */
    445 
    446 	/*
    447 	 * Map in enough memory for the MP Configuration Table Header.
    448 	 * Use this table to read the total length of the BIOS data and
    449 	 * map in all the info
    450 	 */
    451 	/*LINTED: pointer cast may result in improper alignment */
    452 	hdrp = (struct apic_mp_cnf_hdr *)psm_map_phys(mpct_addr,
    453 	    sizeof (struct apic_mp_cnf_hdr), PROT_READ);
    454 	if (!hdrp)
    455 		goto apic_ret;
    456 
    457 	/* check mp configuration table signature PCMP */
    458 	if (hdrp->mpcnf_sig != 0x504d4350) {
    459 		psm_unmap_phys((caddr_t)hdrp, sizeof (struct apic_mp_cnf_hdr));
    460 		goto apic_ret;
    461 	}
    462 	mpct_size = (int)hdrp->mpcnf_tbl_length;
    463 
    464 	apic_set_pwroff_method_from_mpcnfhdr(hdrp);
    465 
    466 	psm_unmap_phys((caddr_t)hdrp, sizeof (struct apic_mp_cnf_hdr));
    467 
    468 	if ((retval == PSM_SUCCESS) && !apic_use_acpi_madt_only) {
    469 		/* This is an ACPI machine No need for further checks */
    470 		goto apic_ret;
    471 	}
    472 
    473 	/*
    474 	 * Map in the entries for this machine, ie. Processor
    475 	 * Entry Tables, Bus Entry Tables, etc.
    476 	 * They are in fixed order following one another
    477 	 */
    478 	mpct = psm_map_phys(mpct_addr, mpct_size, PROT_READ);
    479 	if (!mpct)
    480 		goto apic_ret;
    481 
    482 	if (apic_checksum(mpct, mpct_size) != 0)
    483 		goto apic_fail1;
    484 
    485 	/*LINTED: pointer cast may result in improper alignment */
    486 	hdrp = (struct apic_mp_cnf_hdr *)mpct;
    487 	apicadr = (uint32_t *)mapin_apic((uint32_t)hdrp->mpcnf_local_apic,
    488 	    APIC_LOCAL_MEMLEN, PROT_READ | PROT_WRITE);
    489 	if (!apicadr)
    490 		goto apic_fail1;
    491 
    492 	/* Parse all information in the tables */
    493 	bypass_cpu_and_ioapics_in_mptables = (retval == PSM_SUCCESS);
    494 	if (apic_parse_mpct(mpct, bypass_cpu_and_ioapics_in_mptables) ==
    495 	    PSM_SUCCESS) {
    496 		retval = PSM_SUCCESS;
    497 		goto apic_ret;
    498 	}
    499 
    500 apic_fail1:
    501 	psm_unmap_phys(mpct, mpct_size);
    502 	mpct = NULL;
    503 
    504 apic_ret:
    505 	if (retval == PSM_SUCCESS) {
    506 		extern int apic_ioapic_method_probe();
    507 
    508 		if ((retval = apic_ioapic_method_probe()) == PSM_SUCCESS)
    509 			return (PSM_SUCCESS);
    510 	}
    511 
    512 	for (i = 0; i < apic_io_max; i++)
    513 		mapout_ioapic((caddr_t)apicioadr[i], APIC_IO_MEMLEN);
    514 	if (apic_cpus) {
    515 		kmem_free(apic_cpus, apic_cpus_size);
    516 		apic_cpus = NULL;
    517 	}
    518 	if (apicadr) {
    519 		mapout_apic((caddr_t)apicadr, APIC_LOCAL_MEMLEN);
    520 		apicadr = NULL;
    521 	}
    522 	if (mpct)
    523 		psm_unmap_phys(mpct, mpct_size);
    524 
    525 	return (retval);
    526 }
    527 
    528 static void
    529 apic_set_pwroff_method_from_mpcnfhdr(struct apic_mp_cnf_hdr *hdrp)
    530 {
    531 	int	i;
    532 
    533 	for (i = 0; i < (sizeof (apic_mps_ids) / sizeof (apic_mps_ids[0]));
    534 	    i++) {
    535 		if ((strncmp(hdrp->mpcnf_oem_str, apic_mps_ids[i].oem_id,
    536 		    strlen(apic_mps_ids[i].oem_id)) == 0) &&
    537 		    (strncmp(hdrp->mpcnf_prod_str, apic_mps_ids[i].prod_id,
    538 		    strlen(apic_mps_ids[i].prod_id)) == 0)) {
    539 
    540 			apic_poweroff_method = apic_mps_ids[i].poweroff_method;
    541 			break;
    542 		}
    543 	}
    544 
    545 	if (apic_debug_mps_id != 0) {
    546 		cmn_err(CE_CONT, "%s: MPS OEM ID = '%c%c%c%c%c%c%c%c'"
    547 		    "Product ID = '%c%c%c%c%c%c%c%c%c%c%c%c'\n",
    548 		    psm_name,
    549 		    hdrp->mpcnf_oem_str[0],
    550 		    hdrp->mpcnf_oem_str[1],
    551 		    hdrp->mpcnf_oem_str[2],
    552 		    hdrp->mpcnf_oem_str[3],
    553 		    hdrp->mpcnf_oem_str[4],
    554 		    hdrp->mpcnf_oem_str[5],
    555 		    hdrp->mpcnf_oem_str[6],
    556 		    hdrp->mpcnf_oem_str[7],
    557 		    hdrp->mpcnf_prod_str[0],
    558 		    hdrp->mpcnf_prod_str[1],
    559 		    hdrp->mpcnf_prod_str[2],
    560 		    hdrp->mpcnf_prod_str[3],
    561 		    hdrp->mpcnf_prod_str[4],
    562 		    hdrp->mpcnf_prod_str[5],
    563 		    hdrp->mpcnf_prod_str[6],
    564 		    hdrp->mpcnf_prod_str[7],
    565 		    hdrp->mpcnf_prod_str[8],
    566 		    hdrp->mpcnf_prod_str[9],
    567 		    hdrp->mpcnf_prod_str[10],
    568 		    hdrp->mpcnf_prod_str[11]);
    569 	}
    570 }
    571 
    572 static void
    573 apic_free_apic_cpus(void)
    574 {
    575 	if (apic_cpus != NULL) {
    576 		kmem_free(apic_cpus, apic_cpus_size);
    577 		apic_cpus = NULL;
    578 		apic_cpus_size = 0;
    579 	}
    580 }
    581 
    582 static int
    583 acpi_probe(char *modname)
    584 {
    585 	int			i, intmax, index;
    586 	uint32_t		id, ver;
    587 	int			acpi_verboseflags = 0;
    588 	int			madt_seen, madt_size;
    589 	ACPI_SUBTABLE_HEADER		*ap;
    590 	ACPI_MADT_LOCAL_APIC	*mpa;
    591 	ACPI_MADT_LOCAL_X2APIC	*mpx2a;
    592 	ACPI_MADT_IO_APIC		*mia;
    593 	ACPI_MADT_IO_SAPIC		*misa;
    594 	ACPI_MADT_INTERRUPT_OVERRIDE	*mio;
    595 	ACPI_MADT_NMI_SOURCE		*mns;
    596 	ACPI_MADT_INTERRUPT_SOURCE	*mis;
    597 	ACPI_MADT_LOCAL_APIC_NMI	*mlan;
    598 	ACPI_MADT_LOCAL_X2APIC_NMI	*mx2alan;
    599 	ACPI_MADT_LOCAL_APIC_OVERRIDE	*mao;
    600 	int			sci;
    601 	iflag_t			sci_flags;
    602 	volatile uint32_t	*ioapic;
    603 	int			ioapic_ix;
    604 	uint32_t		*local_ids;
    605 	uint32_t		*proc_ids;
    606 	uchar_t			hid;
    607 	int			warned = 0;
    608 
    609 	if (!apic_use_acpi)
    610 		return (PSM_FAILURE);
    611 
    612 	if (AcpiGetTable(ACPI_SIG_MADT, 1,
    613 	    (ACPI_TABLE_HEADER **) &acpi_mapic_dtp) != AE_OK)
    614 		return (PSM_FAILURE);
    615 
    616 	apicadr = mapin_apic((uint32_t)acpi_mapic_dtp->Address,
    617 	    APIC_LOCAL_MEMLEN, PROT_READ | PROT_WRITE);
    618 	if (!apicadr)
    619 		return (PSM_FAILURE);
    620 
    621 	if ((local_ids = (uint32_t *)kmem_zalloc(NCPU * sizeof (uint32_t),
    622 	    KM_NOSLEEP)) == NULL)
    623 		return (PSM_FAILURE);
    624 
    625 	if ((proc_ids = (uint32_t *)kmem_zalloc(NCPU * sizeof (uint32_t),
    626 	    KM_NOSLEEP)) == NULL) {
    627 		kmem_free(local_ids, NCPU * sizeof (uint32_t));
    628 		return (PSM_FAILURE);
    629 	}
    630 
    631 	id = apic_reg_ops->apic_read(APIC_LID_REG);
    632 	local_ids[0] = (uchar_t)(id >> 24);
    633 	apic_nproc = index = 1;
    634 	apic_io_max = 0;
    635 
    636 	ap = (ACPI_SUBTABLE_HEADER *) (acpi_mapic_dtp + 1);
    637 	madt_size = acpi_mapic_dtp->Header.Length;
    638 	madt_seen = sizeof (*acpi_mapic_dtp);
    639 
    640 	while (madt_seen < madt_size) {
    641 		switch (ap->Type) {
    642 		case ACPI_MADT_TYPE_LOCAL_APIC:
    643 			mpa = (ACPI_MADT_LOCAL_APIC *) ap;
    644 			if (mpa->LapicFlags & ACPI_MADT_ENABLED) {
    645 				if (mpa->Id == local_ids[0]) {
    646 					ASSERT(index == 1);
    647 					proc_ids[0] = mpa->ProcessorId;
    648 				} else if (apic_nproc < NCPU && use_mp &&
    649 				    apic_nproc < boot_ncpus) {
    650 					local_ids[index] = mpa->Id;
    651 					proc_ids[index] = mpa->ProcessorId;
    652 					index++;
    653 					apic_nproc++;
    654 				} else if (apic_nproc == NCPU && !warned) {
    655 					cmn_err(CE_WARN, "%s: CPU limit "
    656 					    "exceeded"
    657 #if !defined(__amd64)
    658 					    " for 32-bit mode"
    659 #endif
    660 					    "; Solaris will use %d CPUs.",
    661 					    psm_name,  NCPU);
    662 					warned = 1;
    663 				}
    664 			}
    665 			break;
    666 
    667 		case ACPI_MADT_TYPE_IO_APIC:
    668 			mia = (ACPI_MADT_IO_APIC *) ap;
    669 			if (apic_io_max < MAX_IO_APIC) {
    670 				ioapic_ix = apic_io_max;
    671 				apic_io_id[apic_io_max] = mia->Id;
    672 				apic_io_vectbase[apic_io_max] =
    673 				    mia->GlobalIrqBase;
    674 				apic_physaddr[apic_io_max] =
    675 				    (uint32_t)mia->Address;
    676 				ioapic = apicioadr[apic_io_max] =
    677 				    mapin_ioapic((uint32_t)mia->Address,
    678 				    APIC_IO_MEMLEN, PROT_READ | PROT_WRITE);
    679 				if (!ioapic)
    680 					goto cleanup;
    681 				ioapic_mask_workaround[apic_io_max] =
    682 				    apic_is_ioapic_AMD_813x(mia->Address);
    683 				apic_io_max++;
    684 			}
    685 			break;
    686 
    687 		case ACPI_MADT_TYPE_INTERRUPT_OVERRIDE:
    688 			mio = (ACPI_MADT_INTERRUPT_OVERRIDE *) ap;
    689 			if (acpi_isop == NULL)
    690 				acpi_isop = mio;
    691 			acpi_iso_cnt++;
    692 			break;
    693 
    694 		case ACPI_MADT_TYPE_NMI_SOURCE:
    695 			/* UNIMPLEMENTED */
    696 			mns = (ACPI_MADT_NMI_SOURCE *) ap;
    697 			if (acpi_nmi_sp == NULL)
    698 				acpi_nmi_sp = mns;
    699 			acpi_nmi_scnt++;
    700 
    701 			cmn_err(CE_NOTE, "!apic: nmi source: %d 0x%x\n",
    702 			    mns->GlobalIrq, mns->IntiFlags);
    703 			break;
    704 
    705 		case ACPI_MADT_TYPE_LOCAL_APIC_NMI:
    706 			/* UNIMPLEMENTED */
    707 			mlan = (ACPI_MADT_LOCAL_APIC_NMI *) ap;
    708 			if (acpi_nmi_cp == NULL)
    709 				acpi_nmi_cp = mlan;
    710 			acpi_nmi_ccnt++;
    711 
    712 			cmn_err(CE_NOTE, "!apic: local nmi: %d 0x%x %d\n",
    713 			    mlan->ProcessorId, mlan->IntiFlags,
    714 			    mlan->Lint);
    715 			break;
    716 
    717 		case ACPI_MADT_TYPE_LOCAL_APIC_OVERRIDE:
    718 			/* UNIMPLEMENTED */
    719 			mao = (ACPI_MADT_LOCAL_APIC_OVERRIDE *) ap;
    720 			cmn_err(CE_NOTE, "!apic: address override: %lx\n",
    721 			    (long)mao->Address);
    722 			break;
    723 
    724 		case ACPI_MADT_TYPE_IO_SAPIC:
    725 			/* UNIMPLEMENTED */
    726 			misa = (ACPI_MADT_IO_SAPIC *) ap;
    727 
    728 			cmn_err(CE_NOTE, "!apic: io sapic: %d %d %lx\n",
    729 			    misa->Id, misa->GlobalIrqBase,
    730 			    (long)misa->Address);
    731 			break;
    732 
    733 		case ACPI_MADT_TYPE_INTERRUPT_SOURCE:
    734 			/* UNIMPLEMENTED */
    735 			mis = (ACPI_MADT_INTERRUPT_SOURCE *) ap;
    736 
    737 			cmn_err(CE_NOTE,
    738 			    "!apic: irq source: %d %d %d 0x%x %d %d\n",
    739 			    mis->Id, mis->Eid, mis->GlobalIrq,
    740 			    mis->IntiFlags, mis->Type,
    741 			    mis->IoSapicVector);
    742 			break;
    743 
    744 		case ACPI_MADT_TYPE_LOCAL_X2APIC:
    745 			mpx2a = (ACPI_MADT_LOCAL_X2APIC *) ap;
    746 
    747 			/*
    748 			 * All logical processors with APIC ID values
    749 			 * of 255 and greater will have their APIC
    750 			 * reported through Processor X2APIC structure.
    751 			 * All logical processors with APIC ID less than
    752 			 * 255 will have their APIC reported through
    753 			 * Processor Local APIC.
    754 			 */
    755 			if ((mpx2a->LapicFlags & ACPI_MADT_ENABLED) &&
    756 			    (mpx2a->LocalApicId >> 8)) {
    757 				if (apic_nproc < NCPU && use_mp &&
    758 				    apic_nproc < boot_ncpus) {
    759 					local_ids[index] = mpx2a->LocalApicId;
    760 					proc_ids[index] = mpa->ProcessorId;
    761 					index++;
    762 					apic_nproc++;
    763 				} else if (apic_nproc == NCPU && !warned) {
    764 					cmn_err(CE_WARN, "%s: CPU limit "
    765 					    "exceeded"
    766 #if !defined(__amd64)
    767 					    " for 32-bit mode"
    768 #endif
    769 					    "; Solaris will use %d CPUs.",
    770 					    psm_name,  NCPU);
    771 					warned = 1;
    772 				}
    773 			}
    774 
    775 			break;
    776 
    777 		case ACPI_MADT_TYPE_LOCAL_X2APIC_NMI:
    778 			/* UNIMPLEMENTED */
    779 			mx2alan = (ACPI_MADT_LOCAL_X2APIC_NMI *) ap;
    780 			if (mx2alan->Uid >> 8)
    781 				acpi_nmi_ccnt++;
    782 
    783 #ifdef	DEBUG
    784 			cmn_err(CE_NOTE,
    785 			    "!apic: local x2apic nmi: %d 0x%x %d\n",
    786 			    mx2alan->Uid, mx2alan->IntiFlags, mx2alan->Lint);
    787 #endif
    788 
    789 			break;
    790 
    791 		case ACPI_MADT_TYPE_RESERVED:
    792 		default:
    793 			break;
    794 		}
    795 
    796 		/* advance to next entry */
    797 		madt_seen += ap->Length;
    798 		ap = (ACPI_SUBTABLE_HEADER *)(((char *)ap) + ap->Length);
    799 	}
    800 
    801 	/*
    802 	 * allocate enough space for possible hot-adding of CPUs.
    803 	 * max_ncpus may be less than apic_nproc if it's set by user.
    804 	 */
    805 	if (plat_dr_support_cpu()) {
    806 		apic_max_nproc = max_ncpus;
    807 	}
    808 	apic_cpus_size = max(apic_nproc, max_ncpus) * sizeof (*apic_cpus);
    809 	if ((apic_cpus = kmem_zalloc(apic_cpus_size, KM_NOSLEEP)) == NULL)
    810 		goto cleanup;
    811 
    812 	/*
    813 	 * ACPI doesn't provide the local apic ver, get it directly from the
    814 	 * local apic
    815 	 */
    816 	ver = apic_reg_ops->apic_read(APIC_VERS_REG);
    817 	for (i = 0; i < apic_nproc; i++) {
    818 		apic_cpus[i].aci_local_id = local_ids[i];
    819 		apic_cpus[i].aci_local_ver = (uchar_t)(ver & 0xFF);
    820 		apic_cpus[i].aci_processor_id = proc_ids[i];
    821 		/* Only build mapping info for CPUs present at boot. */
    822 		if (i < boot_ncpus)
    823 			(void) acpica_map_cpu(i, proc_ids[i]);
    824 	}
    825 
    826 	/*
    827 	 * To support CPU dynamic reconfiguration, the apic CPU info structure
    828 	 * for each possible CPU will be pre-allocated at boot time.
    829 	 * The state for each apic CPU info structure will be assigned according
    830 	 * to the following rules:
    831 	 * Rule 1:
    832 	 * 	Slot index range: [0, min(apic_nproc, boot_ncpus))
    833 	 *	State flags: 0
    834 	 *	Note: cpu exists and will be configured/enabled at boot time
    835 	 * Rule 2:
    836 	 * 	Slot index range: [boot_ncpus, apic_nproc)
    837 	 *	State flags: APIC_CPU_FREE | APIC_CPU_DIRTY
    838 	 *	Note: cpu exists but won't be configured/enabled at boot time
    839 	 * Rule 3:
    840 	 * 	Slot index range: [apic_nproc, boot_ncpus)
    841 	 *	State flags: APIC_CPU_FREE
    842 	 *	Note: cpu doesn't exist at boot time
    843 	 * Rule 4:
    844 	 * 	Slot index range: [max(apic_nproc, boot_ncpus), max_ncpus)
    845 	 *	State flags: APIC_CPU_FREE
    846 	 *	Note: cpu doesn't exist at boot time
    847 	 */
    848 	CPUSET_ZERO(apic_cpumask);
    849 	for (i = 0; i < min(boot_ncpus, apic_nproc); i++) {
    850 		CPUSET_ADD(apic_cpumask, i);
    851 		apic_cpus[i].aci_status = 0;
    852 	}
    853 	for (i = boot_ncpus; i < apic_nproc; i++) {
    854 		apic_cpus[i].aci_status = APIC_CPU_FREE | APIC_CPU_DIRTY;
    855 	}
    856 	for (i = apic_nproc; i < boot_ncpus; i++) {
    857 		apic_cpus[i].aci_status = APIC_CPU_FREE;
    858 	}
    859 	for (i = max(boot_ncpus, apic_nproc); i < max_ncpus; i++) {
    860 		apic_cpus[i].aci_status = APIC_CPU_FREE;
    861 	}
    862 
    863 	for (i = 0; i < apic_io_max; i++) {
    864 		ioapic_ix = i;
    865 
    866 		/*
    867 		 * need to check Sitka on the following acpi problem
    868 		 * On the Sitka, the ioapic's apic_id field isn't reporting
    869 		 * the actual io apic id. We have reported this problem
    870 		 * to Intel. Until they fix the problem, we will get the
    871 		 * actual id directly from the ioapic.
    872 		 */
    873 		id = ioapic_read(ioapic_ix, APIC_ID_CMD);
    874 		hid = (uchar_t)(id >> 24);
    875 
    876 		if (hid != apic_io_id[i]) {
    877 			if (apic_io_id[i] == 0)
    878 				apic_io_id[i] = hid;
    879 			else { /* set ioapic id to whatever reported by ACPI */
    880 				id = ((uint32_t)apic_io_id[i]) << 24;
    881 				ioapic_write(ioapic_ix, APIC_ID_CMD, id);
    882 			}
    883 		}
    884 		ver = ioapic_read(ioapic_ix, APIC_VERS_CMD);
    885 		apic_io_ver[i] = (uchar_t)(ver & 0xff);
    886 		intmax = (ver >> 16) & 0xff;
    887 		apic_io_vectend[i] = apic_io_vectbase[i] + intmax;
    888 		if (apic_first_avail_irq <= apic_io_vectend[i])
    889 			apic_first_avail_irq = apic_io_vectend[i] + 1;
    890 	}
    891 
    892 
    893 	/*
    894 	 * Process SCI configuration here
    895 	 * An error may be returned here if
    896 	 * acpi-user-options specifies legacy mode
    897 	 * (no SCI, no ACPI mode)
    898 	 */
    899 	if (acpica_get_sci(&sci, &sci_flags) != AE_OK)
    900 		sci = -1;
    901 
    902 	/*
    903 	 * Now call acpi_init() to generate namespaces
    904 	 * If this fails, we don't attempt to use ACPI
    905 	 * even if we were able to get a MADT above
    906 	 */
    907 	if (acpica_init() != AE_OK)
    908 		goto cleanup;
    909 
    910 	/*
    911 	 * Call acpica_build_processor_map() now that we have
    912 	 * ACPI namesspace access
    913 	 */
    914 	(void) acpica_build_processor_map();
    915 
    916 	/*
    917 	 * Squirrel away the SCI and flags for later on
    918 	 * in apic_picinit() when we're ready
    919 	 */
    920 	apic_sci_vect = sci;
    921 	apic_sci_flags = sci_flags;
    922 
    923 	if (apic_verbose & APIC_VERBOSE_IRQ_FLAG)
    924 		acpi_verboseflags |= PSM_VERBOSE_IRQ_FLAG;
    925 
    926 	if (apic_verbose & APIC_VERBOSE_POWEROFF_FLAG)
    927 		acpi_verboseflags |= PSM_VERBOSE_POWEROFF_FLAG;
    928 
    929 	if (apic_verbose & APIC_VERBOSE_POWEROFF_PAUSE_FLAG)
    930 		acpi_verboseflags |= PSM_VERBOSE_POWEROFF_PAUSE_FLAG;
    931 
    932 	if (acpi_psm_init(modname, acpi_verboseflags) == ACPI_PSM_FAILURE)
    933 		goto cleanup;
    934 
    935 	/* Enable ACPI APIC interrupt routing */
    936 	if (apic_acpi_enter_apicmode() != PSM_FAILURE) {
    937 		build_reserved_irqlist((uchar_t *)apic_reserved_irqlist);
    938 		apic_enable_acpi = 1;
    939 		if (apic_sci_vect > 0) {
    940 			acpica_set_core_feature(ACPI_FEATURE_SCI_EVENT);
    941 		}
    942 		if (apic_use_acpi_madt_only) {
    943 			cmn_err(CE_CONT,
    944 			    "?Using ACPI for CPU/IOAPIC information ONLY\n");
    945 		}
    946 
    947 #if !defined(__xpv)
    948 		/*
    949 		 * probe ACPI for hpet information here which is used later
    950 		 * in apic_picinit().
    951 		 */
    952 		if (hpet_acpi_init(&apic_hpet_vect, &apic_hpet_flags) < 0) {
    953 			cmn_err(CE_NOTE, "!ACPI HPET table query failed\n");
    954 		}
    955 #endif
    956 
    957 		kmem_free(local_ids, NCPU * sizeof (uint32_t));
    958 		kmem_free(proc_ids, NCPU * sizeof (uint32_t));
    959 		return (PSM_SUCCESS);
    960 	}
    961 	/* if setting APIC mode failed above, we fall through to cleanup */
    962 
    963 cleanup:
    964 	apic_free_apic_cpus();
    965 	if (apicadr != NULL) {
    966 		mapout_apic((caddr_t)apicadr, APIC_LOCAL_MEMLEN);
    967 		apicadr = NULL;
    968 	}
    969 	apic_max_nproc = -1;
    970 	apic_nproc = 0;
    971 	for (i = 0; i < apic_io_max; i++) {
    972 		mapout_ioapic((caddr_t)apicioadr[i], APIC_IO_MEMLEN);
    973 		apicioadr[i] = NULL;
    974 	}
    975 	apic_io_max = 0;
    976 	acpi_isop = NULL;
    977 	acpi_iso_cnt = 0;
    978 	acpi_nmi_sp = NULL;
    979 	acpi_nmi_scnt = 0;
    980 	acpi_nmi_cp = NULL;
    981 	acpi_nmi_ccnt = 0;
    982 	kmem_free(local_ids, NCPU * sizeof (uint32_t));
    983 	kmem_free(proc_ids, NCPU * sizeof (uint32_t));
    984 	return (PSM_FAILURE);
    985 }
    986 
    987 /*
    988  * Handle default configuration. Fill in reqd global variables & tables
    989  * Fill all details as MP table does not give any more info
    990  */
    991 static int
    992 apic_handle_defconf()
    993 {
    994 	uint_t	lid;
    995 
    996 	/* Failed to probe ACPI MADT tables, disable CPU DR. */
    997 	apic_max_nproc = -1;
    998 	apic_free_apic_cpus();
    999 	plat_dr_disable_cpu();
   1000 
   1001 	apicioadr[0] = (void *)mapin_ioapic(APIC_IO_ADDR,
   1002 	    APIC_IO_MEMLEN, PROT_READ | PROT_WRITE);
   1003 	apicadr = (void *)psm_map_phys(APIC_LOCAL_ADDR,
   1004 	    APIC_LOCAL_MEMLEN, PROT_READ);
   1005 	apic_cpus_size = 2 * sizeof (*apic_cpus);
   1006 	apic_cpus = (apic_cpus_info_t *)
   1007 	    kmem_zalloc(apic_cpus_size, KM_NOSLEEP);
   1008 	if ((!apicadr) || (!apicioadr[0]) || (!apic_cpus))
   1009 		goto apic_handle_defconf_fail;
   1010 	CPUSET_ONLY(apic_cpumask, 0);
   1011 	CPUSET_ADD(apic_cpumask, 1);
   1012 	apic_nproc = 2;
   1013 	lid = apic_reg_ops->apic_read(APIC_LID_REG);
   1014 	apic_cpus[0].aci_local_id = (uchar_t)(lid >> APIC_ID_BIT_OFFSET);
   1015 	/*
   1016 	 * According to the PC+MP spec 1.1, the local ids
   1017 	 * for the default configuration has to be 0 or 1
   1018 	 */
   1019 	if (apic_cpus[0].aci_local_id == 1)
   1020 		apic_cpus[1].aci_local_id = 0;
   1021 	else if (apic_cpus[0].aci_local_id == 0)
   1022 		apic_cpus[1].aci_local_id = 1;
   1023 	else
   1024 		goto apic_handle_defconf_fail;
   1025 
   1026 	apic_io_id[0] = 2;
   1027 	apic_io_max = 1;
   1028 	if (apic_defconf >= 5) {
   1029 		apic_cpus[0].aci_local_ver = APIC_INTEGRATED_VERS;
   1030 		apic_cpus[1].aci_local_ver = APIC_INTEGRATED_VERS;
   1031 		apic_io_ver[0] = APIC_INTEGRATED_VERS;
   1032 	} else {
   1033 		apic_cpus[0].aci_local_ver = 0;		/* 82489 DX */
   1034 		apic_cpus[1].aci_local_ver = 0;
   1035 		apic_io_ver[0] = 0;
   1036 	}
   1037 	if (apic_defconf == 2 || apic_defconf == 3 || apic_defconf == 6)
   1038 		eisa_level_intr_mask = (inb(EISA_LEVEL_CNTL + 1) << 8) |
   1039 		    inb(EISA_LEVEL_CNTL) | ((uint_t)INT32_MAX + 1);
   1040 	return (PSM_SUCCESS);
   1041 
   1042 apic_handle_defconf_fail:
   1043 	if (apicadr)
   1044 		mapout_apic((caddr_t)apicadr, APIC_LOCAL_MEMLEN);
   1045 	if (apicioadr[0])
   1046 		mapout_ioapic((caddr_t)apicioadr[0], APIC_IO_MEMLEN);
   1047 	return (PSM_FAILURE);
   1048 }
   1049 
   1050 /* Parse the entries in MP configuration table and collect info that we need */
   1051 static int
   1052 apic_parse_mpct(caddr_t mpct, int bypass_cpus_and_ioapics)
   1053 {
   1054 	struct	apic_procent	*procp;
   1055 	struct	apic_bus	*busp;
   1056 	struct	apic_io_entry	*ioapicp;
   1057 	struct	apic_io_intr	*intrp;
   1058 	int			ioapic_ix;
   1059 	uint_t	lid;
   1060 	uint32_t	id;
   1061 	uchar_t hid;
   1062 	int	warned = 0;
   1063 
   1064 	/*LINTED: pointer cast may result in improper alignment */
   1065 	procp = (struct apic_procent *)(mpct + sizeof (struct apic_mp_cnf_hdr));
   1066 
   1067 	/* No need to count cpu entries if we won't use them */
   1068 	if (!bypass_cpus_and_ioapics) {
   1069 
   1070 		/* Find max # of CPUS and allocate structure accordingly */
   1071 		apic_nproc = 0;
   1072 		CPUSET_ZERO(apic_cpumask);
   1073 		while (procp->proc_entry == APIC_CPU_ENTRY) {
   1074 			if (procp->proc_cpuflags & CPUFLAGS_EN) {
   1075 				if (apic_nproc < NCPU && use_mp &&
   1076 				    apic_nproc < boot_ncpus) {
   1077 					CPUSET_ADD(apic_cpumask, apic_nproc);
   1078 					apic_nproc++;
   1079 				} else if (apic_nproc == NCPU && !warned) {
   1080 					cmn_err(CE_WARN, "%s: CPU limit "
   1081 					    "exceeded"
   1082 #if !defined(__amd64)
   1083 					    " for 32-bit mode"
   1084 #endif
   1085 					    "; Solaris will use %d CPUs.",
   1086 					    psm_name,  NCPU);
   1087 					warned = 1;
   1088 				}
   1089 
   1090 			}
   1091 			procp++;
   1092 		}
   1093 		apic_cpus_size = apic_nproc * sizeof (*apic_cpus);
   1094 		if (!apic_nproc || !(apic_cpus = (apic_cpus_info_t *)
   1095 		    kmem_zalloc(apic_cpus_size, KM_NOSLEEP)))
   1096 			return (PSM_FAILURE);
   1097 	}
   1098 
   1099 	/*LINTED: pointer cast may result in improper alignment */
   1100 	procp = (struct apic_procent *)(mpct + sizeof (struct apic_mp_cnf_hdr));
   1101 
   1102 	/*
   1103 	 * start with index 1 as 0 needs to be filled in with Boot CPU, but
   1104 	 * if we're bypassing this information, it has already been filled
   1105 	 * in by acpi_probe(), so don't overwrite it.
   1106 	 */
   1107 	if (!bypass_cpus_and_ioapics)
   1108 		apic_nproc = 1;
   1109 
   1110 	while (procp->proc_entry == APIC_CPU_ENTRY) {
   1111 		/* check whether the cpu exists or not */
   1112 		if (!bypass_cpus_and_ioapics &&
   1113 		    procp->proc_cpuflags & CPUFLAGS_EN) {
   1114 			if (procp->proc_cpuflags & CPUFLAGS_BP) { /* Boot CPU */
   1115 				lid = apic_reg_ops->apic_read(APIC_LID_REG);
   1116 				apic_cpus[0].aci_local_id = procp->proc_apicid;
   1117 				if (apic_cpus[0].aci_local_id !=
   1118 				    (uchar_t)(lid >> APIC_ID_BIT_OFFSET)) {
   1119 					return (PSM_FAILURE);
   1120 				}
   1121 				apic_cpus[0].aci_local_ver =
   1122 				    procp->proc_version;
   1123 			} else if (apic_nproc < NCPU && use_mp &&
   1124 			    apic_nproc < boot_ncpus) {
   1125 				apic_cpus[apic_nproc].aci_local_id =
   1126 				    procp->proc_apicid;
   1127 
   1128 				apic_cpus[apic_nproc].aci_local_ver =
   1129 				    procp->proc_version;
   1130 				apic_nproc++;
   1131 
   1132 			}
   1133 		}
   1134 		procp++;
   1135 	}
   1136 
   1137 	/*
   1138 	 * Save start of bus entries for later use.
   1139 	 * Get EISA level cntrl if EISA bus is present.
   1140 	 * Also get the CPI bus id for single CPI bus case
   1141 	 */
   1142 	apic_busp = busp = (struct apic_bus *)procp;
   1143 	while (busp->bus_entry == APIC_BUS_ENTRY) {
   1144 		lid = apic_find_bus_type((char *)&busp->bus_str1);
   1145 		if (lid	== BUS_EISA) {
   1146 			eisa_level_intr_mask = (inb(EISA_LEVEL_CNTL + 1) << 8) |
   1147 			    inb(EISA_LEVEL_CNTL) | ((uint_t)INT32_MAX + 1);
   1148 		} else if (lid == BUS_PCI) {
   1149 			/*
   1150 			 * apic_single_pci_busid will be used only if
   1151 			 * apic_pic_bus_total is equal to 1
   1152 			 */
   1153 			apic_pci_bus_total++;
   1154 			apic_single_pci_busid = busp->bus_id;
   1155 		}
   1156 		busp++;
   1157 	}
   1158 
   1159 	ioapicp = (struct apic_io_entry *)busp;
   1160 
   1161 	if (!bypass_cpus_and_ioapics)
   1162 		apic_io_max = 0;
   1163 	do {
   1164 		if (!bypass_cpus_and_ioapics && apic_io_max < MAX_IO_APIC) {
   1165 			if (ioapicp->io_flags & IOAPIC_FLAGS_EN) {
   1166 				apic_io_id[apic_io_max] = ioapicp->io_apicid;
   1167 				apic_io_ver[apic_io_max] = ioapicp->io_version;
   1168 				apicioadr[apic_io_max] =
   1169 				    (void *)mapin_ioapic(
   1170 				    (uint32_t)ioapicp->io_apic_addr,
   1171 				    APIC_IO_MEMLEN, PROT_READ | PROT_WRITE);
   1172 
   1173 				if (!apicioadr[apic_io_max])
   1174 					return (PSM_FAILURE);
   1175 
   1176 				ioapic_mask_workaround[apic_io_max] =
   1177 				    apic_is_ioapic_AMD_813x(
   1178 				    ioapicp->io_apic_addr);
   1179 
   1180 				ioapic_ix = apic_io_max;
   1181 				id = ioapic_read(ioapic_ix, APIC_ID_CMD);
   1182 				hid = (uchar_t)(id >> 24);
   1183 
   1184 				if (hid != apic_io_id[apic_io_max]) {
   1185 					if (apic_io_id[apic_io_max] == 0)
   1186 						apic_io_id[apic_io_max] = hid;
   1187 					else {
   1188 						/*
   1189 						 * set ioapic id to whatever
   1190 						 * reported by MPS
   1191 						 *
   1192 						 * may not need to set index
   1193 						 * again ???
   1194 						 * take it out and try
   1195 						 */
   1196 
   1197 						id = ((uint32_t)
   1198 						    apic_io_id[apic_io_max]) <<
   1199 						    24;
   1200 
   1201 						ioapic_write(ioapic_ix,
   1202 						    APIC_ID_CMD, id);
   1203 					}
   1204 				}
   1205 				apic_io_max++;
   1206 			}
   1207 		}
   1208 		ioapicp++;
   1209 	} while (ioapicp->io_entry == APIC_IO_ENTRY);
   1210 
   1211 	apic_io_intrp = (struct apic_io_intr *)ioapicp;
   1212 
   1213 	intrp = apic_io_intrp;
   1214 	while (intrp->intr_entry == APIC_IO_INTR_ENTRY) {
   1215 		if ((intrp->intr_irq > APIC_MAX_ISA_IRQ) ||
   1216 		    (apic_find_bus(intrp->intr_busid) == BUS_PCI)) {
   1217 			apic_irq_translate = 1;
   1218 			break;
   1219 		}
   1220 		intrp++;
   1221 	}
   1222 
   1223 	return (PSM_SUCCESS);
   1224 }
   1225 
   1226 boolean_t
   1227 apic_cpu_in_range(int cpu)
   1228 {
   1229 	cpu &= ~IRQ_USER_BOUND;
   1230 	/* Check whether cpu id is in valid range. */
   1231 	if (cpu < 0 || cpu >= apic_nproc) {
   1232 		return (B_FALSE);
   1233 	} else if (apic_max_nproc != -1 && cpu >= apic_max_nproc) {
   1234 		/*
   1235 		 * Check whether cpuid is in valid range if CPU DR is enabled.
   1236 		 */
   1237 		return (B_FALSE);
   1238 	} else if (!CPU_IN_SET(apic_cpumask, cpu)) {
   1239 		return (B_FALSE);
   1240 	}
   1241 
   1242 	return (B_TRUE);
   1243 }
   1244 
   1245 processorid_t
   1246 apic_get_next_bind_cpu(void)
   1247 {
   1248 	int i, count;
   1249 	processorid_t cpuid = 0;
   1250 
   1251 	for (count = 0; count < apic_nproc; count++) {
   1252 		if (apic_next_bind_cpu >= apic_nproc) {
   1253 			apic_next_bind_cpu = 0;
   1254 		}
   1255 		i = apic_next_bind_cpu++;
   1256 		if (apic_cpu_in_range(i)) {
   1257 			cpuid = i;
   1258 			break;
   1259 		}
   1260 	}
   1261 
   1262 	return (cpuid);
   1263 }
   1264 
   1265 uint16_t
   1266 apic_get_apic_version()
   1267 {
   1268 	int i;
   1269 	uchar_t min_io_apic_ver = 0;
   1270 	static uint16_t version;		/* Cache as value is constant */
   1271 	static boolean_t found = B_FALSE;	/* Accomodate zero version */
   1272 
   1273 	if (found == B_FALSE) {
   1274 		found = B_TRUE;
   1275 
   1276 		/*
   1277 		 * Don't assume all IO APICs in the system are the same.
   1278 		 *
   1279 		 * Set to the minimum version.
   1280 		 */
   1281 		for (i = 0; i < apic_io_max; i++) {
   1282 			if ((apic_io_ver[i] != 0) &&
   1283 			    ((min_io_apic_ver == 0) ||
   1284 			    (min_io_apic_ver >= apic_io_ver[i])))
   1285 				min_io_apic_ver = apic_io_ver[i];
   1286 		}
   1287 
   1288 		/* Assume all local APICs are of the same version. */
   1289 		version = (min_io_apic_ver << 8) | apic_cpus[0].aci_local_ver;
   1290 	}
   1291 	return (version);
   1292 }
   1293 
   1294 static struct apic_mpfps_hdr *
   1295 apic_find_fps_sig(caddr_t cptr, int len)
   1296 {
   1297 	int	i;
   1298 
   1299 	/* Look for the pattern "_MP_" */
   1300 	for (i = 0; i < len; i += 16) {
   1301 		if ((*(cptr+i) == '_') &&
   1302 		    (*(cptr+i+1) == 'M') &&
   1303 		    (*(cptr+i+2) == 'P') &&
   1304 		    (*(cptr+i+3) == '_'))
   1305 		    /*LINTED: pointer cast may result in improper alignment */
   1306 			return ((struct apic_mpfps_hdr *)(cptr + i));
   1307 	}
   1308 	return (NULL);
   1309 }
   1310 
   1311 static int
   1312 apic_checksum(caddr_t bptr, int len)
   1313 {
   1314 	int	i;
   1315 	uchar_t	cksum;
   1316 
   1317 	cksum = 0;
   1318 	for (i = 0; i < len; i++)
   1319 		cksum += *bptr++;
   1320 	return ((int)cksum);
   1321 }
   1322 
   1323 /*
   1324  * On machines with PCI-PCI bridges, a device behind a PCI-PCI bridge
   1325  * needs special handling.  We may need to chase up the device tree,
   1326  * using the PCI-PCI Bridge specification's "rotating IPIN assumptions",
   1327  * to find the IPIN at the root bus that relates to the IPIN on the
   1328  * subsidiary bus (for ACPI or MP).  We may, however, have an entry
   1329  * in the MP table or the ACPI namespace for this device itself.
   1330  * We handle both cases in the search below.
   1331  */
   1332 /* this is the non-acpi version */
   1333 int
   1334 apic_handle_pci_pci_bridge(dev_info_t *idip, int child_devno, int child_ipin,
   1335 			struct apic_io_intr **intrp)
   1336 {
   1337 	dev_info_t *dipp, *dip;
   1338 	int pci_irq;
   1339 	ddi_acc_handle_t cfg_handle;
   1340 	int bridge_devno, bridge_bus;
   1341 	int ipin;
   1342 
   1343 	dip = idip;
   1344 
   1345 	/*CONSTCOND*/
   1346 	while (1) {
   1347 		if (((dipp = ddi_get_parent(dip)) == (dev_info_t *)NULL) ||
   1348 		    (pci_config_setup(dipp, &cfg_handle) != DDI_SUCCESS))
   1349 			return (-1);
   1350 		if ((pci_config_get8(cfg_handle, PCI_CONF_BASCLASS) ==
   1351 		    PCI_CLASS_BRIDGE) && (pci_config_get8(cfg_handle,
   1352 		    PCI_CONF_SUBCLASS) == PCI_BRIDGE_PCI)) {
   1353 			pci_config_teardown(&cfg_handle);
   1354 			if (acpica_get_bdf(dipp, &bridge_bus, &bridge_devno,
   1355 			    NULL) != 0)
   1356 				return (-1);
   1357 			/*
   1358 			 * This is the rotating scheme documented in the
   1359 			 * PCI-to-PCI spec.  If the PCI-to-PCI bridge is
   1360 			 * behind another PCI-to-PCI bridge, then it needs
   1361 			 * to keep ascending until an interrupt entry is
   1362 			 * found or the root is reached.
   1363 			 */
   1364 			ipin = (child_devno + child_ipin) % PCI_INTD;
   1365 				if (bridge_bus == 0 && apic_pci_bus_total == 1)
   1366 					bridge_bus = (int)apic_single_pci_busid;
   1367 				pci_irq = ((bridge_devno & 0x1f) << 2) |
   1368 				    (ipin & 0x3);
   1369 				if ((*intrp = apic_find_io_intr_w_busid(pci_irq,
   1370 				    bridge_bus)) != NULL) {
   1371 					return (pci_irq);
   1372 				}
   1373 			dip = dipp;
   1374 			child_devno = bridge_devno;
   1375 			child_ipin = ipin;
   1376 		} else {
   1377 			pci_config_teardown(&cfg_handle);
   1378 			return (-1);
   1379 		}
   1380 	}
   1381 	/*LINTED: function will not fall off the bottom */
   1382 }
   1383 
   1384 uchar_t
   1385 acpi_find_ioapic(int irq)
   1386 {
   1387 	int i;
   1388 
   1389 	for (i = 0; i < apic_io_max; i++) {
   1390 		if (irq >= apic_io_vectbase[i] && irq <= apic_io_vectend[i])
   1391 			return ((uchar_t)i);
   1392 	}
   1393 	return (0xFF);	/* shouldn't happen */
   1394 }
   1395 
   1396 /*
   1397  * See if two irqs are compatible for sharing a vector.
   1398  * Currently we only support sharing of PCI devices.
   1399  */
   1400 static int
   1401 acpi_intr_compatible(iflag_t iflag1, iflag_t iflag2)
   1402 {
   1403 	uint_t	level1, po1;
   1404 	uint_t	level2, po2;
   1405 
   1406 	/* Assume active high by default */
   1407 	po1 = 0;
   1408 	po2 = 0;
   1409 
   1410 	if (iflag1.bustype != iflag2.bustype || iflag1.bustype != BUS_PCI)
   1411 		return (0);
   1412 
   1413 	if (iflag1.intr_el == INTR_EL_CONFORM)
   1414 		level1 = AV_LEVEL;
   1415 	else
   1416 		level1 = (iflag1.intr_el == INTR_EL_LEVEL) ? AV_LEVEL : 0;
   1417 
   1418 	if (level1 && ((iflag1.intr_po == INTR_PO_ACTIVE_LOW) ||
   1419 	    (iflag1.intr_po == INTR_PO_CONFORM)))
   1420 		po1 = AV_ACTIVE_LOW;
   1421 
   1422 	if (iflag2.intr_el == INTR_EL_CONFORM)
   1423 		level2 = AV_LEVEL;
   1424 	else
   1425 		level2 = (iflag2.intr_el == INTR_EL_LEVEL) ? AV_LEVEL : 0;
   1426 
   1427 	if (level2 && ((iflag2.intr_po == INTR_PO_ACTIVE_LOW) ||
   1428 	    (iflag2.intr_po == INTR_PO_CONFORM)))
   1429 		po2 = AV_ACTIVE_LOW;
   1430 
   1431 	if ((level1 == level2) && (po1 == po2))
   1432 		return (1);
   1433 
   1434 	return (0);
   1435 }
   1436 
   1437 struct apic_io_intr *
   1438 apic_find_io_intr_w_busid(int irqno, int busid)
   1439 {
   1440 	struct	apic_io_intr	*intrp;
   1441 
   1442 	/*
   1443 	 * It can have more than 1 entry with same source bus IRQ,
   1444 	 * but unique with the source bus id
   1445 	 */
   1446 	intrp = apic_io_intrp;
   1447 	if (intrp != NULL) {
   1448 		while (intrp->intr_entry == APIC_IO_INTR_ENTRY) {
   1449 			if (intrp->intr_irq == irqno &&
   1450 			    intrp->intr_busid == busid &&
   1451 			    intrp->intr_type == IO_INTR_INT)
   1452 				return (intrp);
   1453 			intrp++;
   1454 		}
   1455 	}
   1456 	APIC_VERBOSE_IOAPIC((CE_NOTE, "Did not find io intr for irqno:"
   1457 	    "busid %x:%x\n", irqno, busid));
   1458 	return ((struct apic_io_intr *)NULL);
   1459 }
   1460 
   1461 
   1462 struct mps_bus_info {
   1463 	char	*bus_name;
   1464 	int	bus_id;
   1465 } bus_info_array[] = {
   1466 	"ISA ", BUS_ISA,
   1467 	"PCI ", BUS_PCI,
   1468 	"EISA ", BUS_EISA,
   1469 	"XPRESS", BUS_XPRESS,
   1470 	"PCMCIA", BUS_PCMCIA,
   1471 	"VL ", BUS_VL,
   1472 	"CBUS ", BUS_CBUS,
   1473 	"CBUSII", BUS_CBUSII,
   1474 	"FUTURE", BUS_FUTURE,
   1475 	"INTERN", BUS_INTERN,
   1476 	"MBI ", BUS_MBI,
   1477 	"MBII ", BUS_MBII,
   1478 	"MPI ", BUS_MPI,
   1479 	"MPSA ", BUS_MPSA,
   1480 	"NUBUS ", BUS_NUBUS,
   1481 	"TC ", BUS_TC,
   1482 	"VME ", BUS_VME,
   1483 	"PCI-E ", BUS_PCIE
   1484 };
   1485 
   1486 static int
   1487 apic_find_bus_type(char *bus)
   1488 {
   1489 	int	i = 0;
   1490 
   1491 	for (; i < sizeof (bus_info_array)/sizeof (struct mps_bus_info); i++)
   1492 		if (strncmp(bus, bus_info_array[i].bus_name,
   1493 		    strlen(bus_info_array[i].bus_name)) == 0)
   1494 			return (bus_info_array[i].bus_id);
   1495 	APIC_VERBOSE_IOAPIC((CE_WARN, "Did not find bus type for bus %s", bus));
   1496 	return (0);
   1497 }
   1498 
   1499 static int
   1500 apic_find_bus(int busid)
   1501 {
   1502 	struct	apic_bus	*busp;
   1503 
   1504 	busp = apic_busp;
   1505 	while (busp->bus_entry == APIC_BUS_ENTRY) {
   1506 		if (busp->bus_id == busid)
   1507 			return (apic_find_bus_type((char *)&busp->bus_str1));
   1508 		busp++;
   1509 	}
   1510 	APIC_VERBOSE_IOAPIC((CE_WARN, "Did not find bus for bus id %x", busid));
   1511 	return (0);
   1512 }
   1513 
   1514 int
   1515 apic_find_bus_id(int bustype)
   1516 {
   1517 	struct	apic_bus	*busp;
   1518 
   1519 	busp = apic_busp;
   1520 	while (busp->bus_entry == APIC_BUS_ENTRY) {
   1521 		if (apic_find_bus_type((char *)&busp->bus_str1) == bustype)
   1522 			return (busp->bus_id);
   1523 		busp++;
   1524 	}
   1525 	APIC_VERBOSE_IOAPIC((CE_WARN, "Did not find bus id for bustype %x",
   1526 	    bustype));
   1527 	return (-1);
   1528 }
   1529 
   1530 /*
   1531  * Check if a particular irq need to be reserved for any io_intr
   1532  */
   1533 static struct apic_io_intr *
   1534 apic_find_io_intr(int irqno)
   1535 {
   1536 	struct	apic_io_intr	*intrp;
   1537 
   1538 	intrp = apic_io_intrp;
   1539 	if (intrp != NULL) {
   1540 		while (intrp->intr_entry == APIC_IO_INTR_ENTRY) {
   1541 			if (intrp->intr_irq == irqno &&
   1542 			    intrp->intr_type == IO_INTR_INT)
   1543 				return (intrp);
   1544 			intrp++;
   1545 		}
   1546 	}
   1547 	return ((struct apic_io_intr *)NULL);
   1548 }
   1549 
   1550 /*
   1551  * Check if the given ioapicindex intin combination has already been assigned
   1552  * an irq. If so return irqno. Else -1
   1553  */
   1554 int
   1555 apic_find_intin(uchar_t ioapic, uchar_t intin)
   1556 {
   1557 	apic_irq_t *irqptr;
   1558 	int	i;
   1559 
   1560 	/* find ioapic and intin in the apic_irq_table[] and return the index */
   1561 	for (i = apic_min_device_irq; i <= apic_max_device_irq; i++) {
   1562 		irqptr = apic_irq_table[i];
   1563 		while (irqptr) {
   1564 			if ((irqptr->airq_mps_intr_index >= 0) &&
   1565 			    (irqptr->airq_intin_no == intin) &&
   1566 			    (irqptr->airq_ioapicindex == ioapic)) {
   1567 				APIC_VERBOSE_IOAPIC((CE_NOTE, "!Found irq "
   1568 				    "entry for ioapic:intin %x:%x "
   1569 				    "shared interrupts ?", ioapic, intin));
   1570 				return (i);
   1571 			}
   1572 			irqptr = irqptr->airq_next;
   1573 		}
   1574 	}
   1575 	return (-1);
   1576 }
   1577 
   1578 int
   1579 apic_allocate_irq(int irq)
   1580 {
   1581 	int	freeirq, i;
   1582 
   1583 	if ((freeirq = apic_find_free_irq(irq, (APIC_RESV_IRQ - 1))) == -1)
   1584 		if ((freeirq = apic_find_free_irq(APIC_FIRST_FREE_IRQ,
   1585 		    (irq - 1))) == -1) {
   1586 			/*
   1587 			 * if BIOS really defines every single irq in the mps
   1588 			 * table, then don't worry about conflicting with
   1589 			 * them, just use any free slot in apic_irq_table
   1590 			 */
   1591 			for (i = APIC_FIRST_FREE_IRQ; i < APIC_RESV_IRQ; i++) {
   1592 				if ((apic_irq_table[i] == NULL) ||
   1593 				    apic_irq_table[i]->airq_mps_intr_index ==
   1594 				    FREE_INDEX) {
   1595 				freeirq = i;
   1596 				break;
   1597 			}
   1598 		}
   1599 		if (freeirq == -1) {
   1600 			/* This shouldn't happen, but just in case */
   1601 			cmn_err(CE_WARN, "%s: NO available IRQ", psm_name);
   1602 			return (-1);
   1603 		}
   1604 	}
   1605 	if (apic_irq_table[freeirq] == NULL) {
   1606 		apic_irq_table[freeirq] =
   1607 		    kmem_zalloc(sizeof (apic_irq_t), KM_NOSLEEP);
   1608 		if (apic_irq_table[freeirq] == NULL) {
   1609 			cmn_err(CE_WARN, "%s: NO memory to allocate IRQ",
   1610 			    psm_name);
   1611 			return (-1);
   1612 		}
   1613 		apic_irq_table[freeirq]->airq_temp_cpu = IRQ_UNINIT;
   1614 		apic_irq_table[freeirq]->airq_mps_intr_index = FREE_INDEX;
   1615 	}
   1616 	return (freeirq);
   1617 }
   1618 
   1619 static int
   1620 apic_find_free_irq(int start, int end)
   1621 {
   1622 	int	i;
   1623 
   1624 	for (i = start; i <= end; i++)
   1625 		/* Check if any I/O entry needs this IRQ */
   1626 		if (apic_find_io_intr(i) == NULL) {
   1627 			/* Then see if it is free */
   1628 			if ((apic_irq_table[i] == NULL) ||
   1629 			    (apic_irq_table[i]->airq_mps_intr_index ==
   1630 			    FREE_INDEX)) {
   1631 				return (i);
   1632 			}
   1633 		}
   1634 	return (-1);
   1635 }
   1636 
   1637 /*
   1638  * compute the polarity, trigger mode and vector for programming into
   1639  * the I/O apic and record in airq_rdt_entry.
   1640  */
   1641 void
   1642 apic_record_rdt_entry(apic_irq_t *irqptr, int irq)
   1643 {
   1644 	int	ioapicindex, bus_type, vector;
   1645 	short	intr_index;
   1646 	uint_t	level, po, io_po;
   1647 	struct apic_io_intr *iointrp;
   1648 
   1649 	intr_index = irqptr->airq_mps_intr_index;
   1650 	DDI_INTR_IMPLDBG((CE_CONT, "apic_record_rdt_entry: intr_index=%d "
   1651 	    "irq = 0x%x dip = 0x%p vector = 0x%x\n", intr_index, irq,
   1652 	    (void *)irqptr->airq_dip, irqptr->airq_vector));
   1653 
   1654 	if (intr_index == RESERVE_INDEX) {
   1655 		apic_error |= APIC_ERR_INVALID_INDEX;
   1656 		return;
   1657 	} else if (APIC_IS_MSI_OR_MSIX_INDEX(intr_index)) {
   1658 		return;
   1659 	}
   1660 
   1661 	vector = irqptr->airq_vector;
   1662 	ioapicindex = irqptr->airq_ioapicindex;
   1663 	/* Assume edge triggered by default */
   1664 	level = 0;
   1665 	/* Assume active high by default */
   1666 	po = 0;
   1667 
   1668 	if (intr_index == DEFAULT_INDEX || intr_index == FREE_INDEX) {
   1669 		ASSERT(irq < 16);
   1670 		if (eisa_level_intr_mask & (1 << irq))
   1671 			level = AV_LEVEL;
   1672 		if (intr_index == FREE_INDEX && apic_defconf == 0)
   1673 			apic_error |= APIC_ERR_INVALID_INDEX;
   1674 	} else if (intr_index == ACPI_INDEX) {
   1675 		bus_type = irqptr->airq_iflag.bustype;
   1676 		if (irqptr->airq_iflag.intr_el == INTR_EL_CONFORM) {
   1677 			if (bus_type == BUS_PCI)
   1678 				level = AV_LEVEL;
   1679 		} else
   1680 			level = (irqptr->airq_iflag.intr_el == INTR_EL_LEVEL) ?
   1681 			    AV_LEVEL : 0;
   1682 		if (level &&
   1683 		    ((irqptr->airq_iflag.intr_po == INTR_PO_ACTIVE_LOW) ||
   1684 		    (irqptr->airq_iflag.intr_po == INTR_PO_CONFORM &&
   1685 		    bus_type == BUS_PCI)))
   1686 			po = AV_ACTIVE_LOW;
   1687 	} else {
   1688 		iointrp = apic_io_intrp + intr_index;
   1689 		bus_type = apic_find_bus(iointrp->intr_busid);
   1690 		if (iointrp->intr_el == INTR_EL_CONFORM) {
   1691 			if ((irq < 16) && (eisa_level_intr_mask & (1 << irq)))
   1692 				level = AV_LEVEL;
   1693 			else if (bus_type == BUS_PCI)
   1694 				level = AV_LEVEL;
   1695 		} else
   1696 			level = (iointrp->intr_el == INTR_EL_LEVEL) ?
   1697 			    AV_LEVEL : 0;
   1698 		if (level && ((iointrp->intr_po == INTR_PO_ACTIVE_LOW) ||
   1699 		    (iointrp->intr_po == INTR_PO_CONFORM &&
   1700 		    bus_type == BUS_PCI)))
   1701 			po = AV_ACTIVE_LOW;
   1702 	}
   1703 	if (level)
   1704 		apic_level_intr[irq] = 1;
   1705 	/*
   1706 	 * The 82489DX External APIC cannot do active low polarity interrupts.
   1707 	 */
   1708 	if (po && (apic_io_ver[ioapicindex] != IOAPIC_VER_82489DX))
   1709 		io_po = po;
   1710 	else
   1711 		io_po = 0;
   1712 
   1713 	if (apic_verbose & APIC_VERBOSE_IOAPIC_FLAG)
   1714 		prom_printf("setio: ioapic=0x%x intin=0x%x level=0x%x po=0x%x "
   1715 		    "vector=0x%x cpu=0x%x\n\n", ioapicindex,
   1716 		    irqptr->airq_intin_no, level, io_po, vector,
   1717 		    irqptr->airq_cpu);
   1718 
   1719 	irqptr->airq_rdt_entry = level|io_po|vector;
   1720 }
   1721 
   1722 int
   1723 apic_acpi_translate_pci_irq(dev_info_t *dip, int busid, int devid,
   1724     int ipin, int *pci_irqp, iflag_t *intr_flagp)
   1725 {
   1726 
   1727 	int status;
   1728 	acpi_psm_lnk_t acpipsmlnk;
   1729 
   1730 	if ((status = acpi_get_irq_cache_ent(busid, devid, ipin, pci_irqp,
   1731 	    intr_flagp)) == ACPI_PSM_SUCCESS) {
   1732 		APIC_VERBOSE_IRQ((CE_CONT, "!%s: Found irqno %d "
   1733 		    "from cache for device %s, instance #%d\n", psm_name,
   1734 		    *pci_irqp, ddi_get_name(dip), ddi_get_instance(dip)));
   1735 		return (status);
   1736 	}
   1737 
   1738 	bzero(&acpipsmlnk, sizeof (acpi_psm_lnk_t));
   1739 
   1740 	if ((status = acpi_translate_pci_irq(dip, ipin, pci_irqp, intr_flagp,
   1741 	    &acpipsmlnk)) == ACPI_PSM_FAILURE) {
   1742 		APIC_VERBOSE_IRQ((CE_WARN, "%s: "
   1743 		    " acpi_translate_pci_irq failed for device %s, instance"
   1744 		    " #%d", psm_name, ddi_get_name(dip),
   1745 		    ddi_get_instance(dip)));
   1746 		return (status);
   1747 	}
   1748 
   1749 	if (status == ACPI_PSM_PARTIAL && acpipsmlnk.lnkobj != NULL) {
   1750 		status = apic_acpi_irq_configure(&acpipsmlnk, dip, pci_irqp,
   1751 		    intr_flagp);
   1752 		if (status != ACPI_PSM_SUCCESS) {
   1753 			status = acpi_get_current_irq_resource(&acpipsmlnk,
   1754 			    pci_irqp, intr_flagp);
   1755 		}
   1756 	}
   1757 
   1758 	if (status == ACPI_PSM_SUCCESS) {
   1759 		acpi_new_irq_cache_ent(busid, devid, ipin, *pci_irqp,
   1760 		    intr_flagp, &acpipsmlnk);
   1761 
   1762 		APIC_VERBOSE_IRQ((CE_CONT, "%s: [ACPI] "
   1763 		    "new irq %d for device %s, instance #%d\n", psm_name,
   1764 		    *pci_irqp, ddi_get_name(dip), ddi_get_instance(dip)));
   1765 	}
   1766 
   1767 	return (status);
   1768 }
   1769 
   1770 /*
   1771  * Adds an entry to the irq list passed in, and returns the new list.
   1772  * Entries are added in priority order (lower numerical priorities are
   1773  * placed closer to the head of the list)
   1774  */
   1775 static prs_irq_list_t *
   1776 acpi_insert_prs_irq_ent(prs_irq_list_t *listp, int priority, int irq,
   1777     iflag_t *iflagp, acpi_prs_private_t *prsprvp)
   1778 {
   1779 	struct prs_irq_list_ent *newent, *prevp = NULL, *origlistp;
   1780 
   1781 	newent = kmem_zalloc(sizeof (struct prs_irq_list_ent), KM_SLEEP);
   1782 
   1783 	newent->list_prio = priority;
   1784 	newent->irq = irq;
   1785 	newent->intrflags = *iflagp;
   1786 	newent->prsprv = *prsprvp;
   1787 	/* ->next is NULL from kmem_zalloc */
   1788 
   1789 	/*
   1790 	 * New list -- return the new entry as the list.
   1791 	 */
   1792 	if (listp == NULL)
   1793 		return (newent);
   1794 
   1795 	/*
   1796 	 * Save original list pointer for return (since we're not modifying
   1797 	 * the head)
   1798 	 */
   1799 	origlistp = listp;
   1800 
   1801 	/*
   1802 	 * Insertion sort, with entries with identical keys stored AFTER
   1803 	 * existing entries (the less-than-or-equal test of priority does
   1804 	 * this for us).
   1805 	 */
   1806 	while (listp != NULL && listp->list_prio <= priority) {
   1807 		prevp = listp;
   1808 		listp = listp->next;
   1809 	}
   1810 
   1811 	newent->next = listp;
   1812 
   1813 	if (prevp == NULL) { /* Add at head of list (newent is the new head) */
   1814 		return (newent);
   1815 	} else {
   1816 		prevp->next = newent;
   1817 		return (origlistp);
   1818 	}
   1819 }
   1820 
   1821 /*
   1822  * Frees the list passed in, deallocating all memory and leaving *listpp
   1823  * set to NULL.
   1824  */
   1825 static void
   1826 acpi_destroy_prs_irq_list(prs_irq_list_t **listpp)
   1827 {
   1828 	struct prs_irq_list_ent *nextp;
   1829 
   1830 	ASSERT(listpp != NULL);
   1831 
   1832 	while (*listpp != NULL) {
   1833 		nextp = (*listpp)->next;
   1834 		kmem_free(*listpp, sizeof (struct prs_irq_list_ent));
   1835 		*listpp = nextp;
   1836 	}
   1837 }
   1838 
   1839 /*
   1840  * apic_choose_irqs_from_prs returns a list of irqs selected from the list of
   1841  * irqs returned by the link device's _PRS method.  The irqs are chosen
   1842  * to minimize contention in situations where the interrupt link device
   1843  * can be programmed to steer interrupts to different interrupt controller
   1844  * inputs (some of which may already be in use).  The list is sorted in order
   1845  * of irqs to use, with the highest priority given to interrupt controller
   1846  * inputs that are not shared.   When an interrupt controller input
   1847  * must be shared, apic_choose_irqs_from_prs adds the possible irqs to the
   1848  * returned list in the order that minimizes sharing (thereby ensuring lowest
   1849  * possible latency from interrupt trigger time to ISR execution time).
   1850  */
   1851 static prs_irq_list_t *
   1852 apic_choose_irqs_from_prs(acpi_irqlist_t *irqlistent, dev_info_t *dip,
   1853     int crs_irq)
   1854 {
   1855 	int32_t irq;
   1856 	int i;
   1857 	prs_irq_list_t *prsirqlistp = NULL;
   1858 	iflag_t iflags;
   1859 
   1860 	while (irqlistent != NULL) {
   1861 		irqlistent->intr_flags.bustype = BUS_PCI;
   1862 
   1863 		for (i = 0; i < irqlistent->num_irqs; i++) {
   1864 
   1865 			irq = irqlistent->irqs[i];
   1866 
   1867 			if (irq <= 0) {
   1868 				/* invalid irq number */
   1869 				continue;
   1870 			}
   1871 
   1872 			if ((irq < 16) && (apic_reserved_irqlist[irq]))
   1873 				continue;
   1874 
   1875 			if ((apic_irq_table[irq] == NULL) ||
   1876 			    (apic_irq_table[irq]->airq_dip == dip)) {
   1877 
   1878 				prsirqlistp = acpi_insert_prs_irq_ent(
   1879 				    prsirqlistp, 0 /* Highest priority */, irq,
   1880 				    &irqlistent->intr_flags,
   1881 				    &irqlistent->acpi_prs_prv);
   1882 
   1883 				/*
   1884 				 * If we do not prefer the current irq from _CRS
   1885 				 * or if we do and this irq is the same as the
   1886 				 * current irq from _CRS, this is the one
   1887 				 * to pick.
   1888 				 */
   1889 				if (!(apic_prefer_crs) || (irq == crs_irq)) {
   1890 					return (prsirqlistp);
   1891 				}
   1892 				continue;
   1893 			}
   1894 
   1895 			/*
   1896 			 * Edge-triggered interrupts cannot be shared
   1897 			 */
   1898 			if (irqlistent->intr_flags.intr_el == INTR_EL_EDGE)
   1899 				continue;
   1900 
   1901 			/*
   1902 			 * To work around BIOSes that contain incorrect
   1903 			 * interrupt polarity information in interrupt
   1904 			 * descriptors returned by _PRS, we assume that
   1905 			 * the polarity of the other device sharing this
   1906 			 * interrupt controller input is compatible.
   1907 			 * If it's not, the caller will catch it when
   1908 			 * the caller invokes the link device's _CRS method
   1909 			 * (after invoking its _SRS method).
   1910 			 */
   1911 			iflags = irqlistent->intr_flags;
   1912 			iflags.intr_po =
   1913 			    apic_irq_table[irq]->airq_iflag.intr_po;
   1914 
   1915 			if (!acpi_intr_compatible(iflags,
   1916 			    apic_irq_table[irq]->airq_iflag)) {
   1917 				APIC_VERBOSE_IRQ((CE_CONT, "!%s: irq %d "
   1918 				    "not compatible [%x:%x:%x !~ %x:%x:%x]",
   1919 				    psm_name, irq,
   1920 				    iflags.intr_po,
   1921 				    iflags.intr_el,
   1922 				    iflags.bustype,
   1923 				    apic_irq_table[irq]->airq_iflag.intr_po,
   1924 				    apic_irq_table[irq]->airq_iflag.intr_el,
   1925 				    apic_irq_table[irq]->airq_iflag.bustype));
   1926 				continue;
   1927 			}
   1928 
   1929 			/*
   1930 			 * If we prefer the irq from _CRS, no need
   1931 			 * to search any further (and make sure
   1932 			 * to add this irq with the highest priority
   1933 			 * so it's tried first).
   1934 			 */
   1935 			if (crs_irq == irq && apic_prefer_crs) {
   1936 
   1937 				return (acpi_insert_prs_irq_ent(
   1938 				    prsirqlistp,
   1939 				    0 /* Highest priority */,
   1940 				    irq, &iflags,
   1941 				    &irqlistent->acpi_prs_prv));
   1942 			}
   1943 
   1944 			/*
   1945 			 * Priority is equal to the share count (lower
   1946 			 * share count is higher priority). Note that
   1947 			 * the intr flags passed in here are the ones we
   1948 			 * changed above -- if incorrect, it will be
   1949 			 * caught by the caller's _CRS flags comparison.
   1950 			 */
   1951 			prsirqlistp = acpi_insert_prs_irq_ent(
   1952 			    prsirqlistp,
   1953 			    apic_irq_table[irq]->airq_share, irq,
   1954 			    &iflags, &irqlistent->acpi_prs_prv);
   1955 		}
   1956 
   1957 		/* Go to the next irqlist entry */
   1958 		irqlistent = irqlistent->next;
   1959 	}
   1960 
   1961 	return (prsirqlistp);
   1962 }
   1963 
   1964 /*
   1965  * Configures the irq for the interrupt link device identified by
   1966  * acpipsmlnkp.
   1967  *
   1968  * Gets the current and the list of possible irq settings for the
   1969  * device. If apic_unconditional_srs is not set, and the current
   1970  * resource setting is in the list of possible irq settings,
   1971  * current irq resource setting is passed to the caller.
   1972  *
   1973  * Otherwise, picks an irq number from the list of possible irq
   1974  * settings, and sets the irq of the device to this value.
   1975  * If prefer_crs is set, among a set of irq numbers in the list that have
   1976  * the least number of devices sharing the interrupt, we pick current irq
   1977  * resource setting if it is a member of this set.
   1978  *
   1979  * Passes the irq number in the value pointed to by pci_irqp, and
   1980  * polarity and sensitivity in the structure pointed to by dipintrflagp
   1981  * to the caller.
   1982  *
   1983  * Note that if setting the irq resource failed, but successfuly obtained
   1984  * the current irq resource settings, passes the current irq resources
   1985  * and considers it a success.
   1986  *
   1987  * Returns:
   1988  * ACPI_PSM_SUCCESS on success.
   1989  *
   1990  * ACPI_PSM_FAILURE if an error occured during the configuration or
   1991  * if a suitable irq was not found for this device, or if setting the
   1992  * irq resource and obtaining the current resource fails.
   1993  *
   1994  */
   1995 static int
   1996 apic_acpi_irq_configure(acpi_psm_lnk_t *acpipsmlnkp, dev_info_t *dip,
   1997     int *pci_irqp, iflag_t *dipintr_flagp)
   1998 {
   1999 	int32_t irq;
   2000 	int cur_irq = -1;
   2001 	acpi_irqlist_t *irqlistp;
   2002 	prs_irq_list_t *prs_irq_listp, *prs_irq_entp;
   2003 	boolean_t found_irq = B_FALSE;
   2004 
   2005 	dipintr_flagp->bustype = BUS_PCI;
   2006 
   2007 	if ((acpi_get_possible_irq_resources(acpipsmlnkp, &irqlistp))
   2008 	    == ACPI_PSM_FAILURE) {
   2009 		APIC_VERBOSE_IRQ((CE_WARN, "!%s: Unable to determine "
   2010 		    "or assign IRQ for device %s, instance #%d: The system was "
   2011 		    "unable to get the list of potential IRQs from ACPI.",
   2012 		    psm_name, ddi_get_name(dip), ddi_get_instance(dip)));
   2013 
   2014 		return (ACPI_PSM_FAILURE);
   2015 	}
   2016 
   2017 	if ((acpi_get_current_irq_resource(acpipsmlnkp, &cur_irq,
   2018 	    dipintr_flagp) == ACPI_PSM_SUCCESS) && (!apic_unconditional_srs) &&
   2019 	    (cur_irq > 0)) {
   2020 		/*
   2021 		 * If an IRQ is set in CRS and that IRQ exists in the set
   2022 		 * returned from _PRS, return that IRQ, otherwise print
   2023 		 * a warning
   2024 		 */
   2025 
   2026 		if (acpi_irqlist_find_irq(irqlistp, cur_irq, NULL)
   2027 		    == ACPI_PSM_SUCCESS) {
   2028 
   2029 			ASSERT(pci_irqp != NULL);
   2030 			*pci_irqp = cur_irq;
   2031 			acpi_free_irqlist(irqlistp);
   2032 			return (ACPI_PSM_SUCCESS);
   2033 		}
   2034 
   2035 		APIC_VERBOSE_IRQ((CE_WARN, "!%s: Could not find the "
   2036 		    "current irq %d for device %s, instance #%d in ACPI's "
   2037 		    "list of possible irqs for this device. Picking one from "
   2038 		    " the latter list.", psm_name, cur_irq, ddi_get_name(dip),
   2039 		    ddi_get_instance(dip)));
   2040 	}
   2041 
   2042 	if ((prs_irq_listp = apic_choose_irqs_from_prs(irqlistp, dip,
   2043 	    cur_irq)) == NULL) {
   2044 
   2045 		APIC_VERBOSE_IRQ((CE_WARN, "!%s: Could not find a "
   2046 		    "suitable irq from the list of possible irqs for device "
   2047 		    "%s, instance #%d in ACPI's list of possible irqs",
   2048 		    psm_name, ddi_get_name(dip), ddi_get_instance(dip)));
   2049 
   2050 		acpi_free_irqlist(irqlistp);
   2051 		return (ACPI_PSM_FAILURE);
   2052 	}
   2053 
   2054 	acpi_free_irqlist(irqlistp);
   2055 
   2056 	for (prs_irq_entp = prs_irq_listp;
   2057 	    prs_irq_entp != NULL && found_irq == B_FALSE;
   2058 	    prs_irq_entp = prs_irq_entp->next) {
   2059 
   2060 		acpipsmlnkp->acpi_prs_prv = prs_irq_entp->prsprv;
   2061 		irq = prs_irq_entp->irq;
   2062 
   2063 		APIC_VERBOSE_IRQ((CE_CONT, "!%s: Setting irq %d for "
   2064 		    "device %s instance #%d\n", psm_name, irq,
   2065 		    ddi_get_name(dip), ddi_get_instance(dip)));
   2066 
   2067 		if ((acpi_set_irq_resource(acpipsmlnkp, irq))
   2068 		    == ACPI_PSM_SUCCESS) {
   2069 			/*
   2070 			 * setting irq was successful, check to make sure CRS
   2071 			 * reflects that. If CRS does not agree with what we
   2072 			 * set, return the irq that was set.
   2073 			 */
   2074 
   2075 			if (acpi_get_current_irq_resource(acpipsmlnkp, &cur_irq,
   2076 			    dipintr_flagp) == ACPI_PSM_SUCCESS) {
   2077 
   2078 				if (cur_irq != irq)
   2079 					APIC_VERBOSE_IRQ((CE_WARN,
   2080 					    "!%s: IRQ resource set "
   2081 					    "(irqno %d) for device %s "
   2082 					    "instance #%d, differs from "
   2083 					    "current setting irqno %d",
   2084 					    psm_name, irq, ddi_get_name(dip),
   2085 					    ddi_get_instance(dip), cur_irq));
   2086 			} else {
   2087 				/*
   2088 				 * On at least one system, there was a bug in
   2089 				 * a DSDT method called by _STA, causing _STA to
   2090 				 * indicate that the link device was disabled
   2091 				 * (when, in fact, it was enabled).  Since _SRS
   2092 				 * succeeded, assume that _CRS is lying and use
   2093 				 * the iflags from this _PRS interrupt choice.
   2094 				 * If we're wrong about the flags, the polarity
   2095 				 * will be incorrect and we may get an interrupt
   2096 				 * storm, but there's not much else we can do
   2097 				 * at this point.
   2098 				 */
   2099 				*dipintr_flagp = prs_irq_entp->intrflags;
   2100 			}
   2101 
   2102 			/*
   2103 			 * Return the irq that was set, and not what _CRS
   2104 			 * reports, since _CRS has been seen to return
   2105 			 * different IRQs than what was passed to _SRS on some
   2106 			 * systems (and just not return successfully on others).
   2107 			 */
   2108 			cur_irq = irq;
   2109 			found_irq = B_TRUE;
   2110 		} else {
   2111 			APIC_VERBOSE_IRQ((CE_WARN, "!%s: set resource "
   2112 			    "irq %d failed for device %s instance #%d",
   2113 			    psm_name, irq, ddi_get_name(dip),
   2114 			    ddi_get_instance(dip)));
   2115 
   2116 			if (cur_irq == -1) {
   2117 				acpi_destroy_prs_irq_list(&prs_irq_listp);
   2118 				return (ACPI_PSM_FAILURE);
   2119 			}
   2120 		}
   2121 	}
   2122 
   2123 	acpi_destroy_prs_irq_list(&prs_irq_listp);
   2124 
   2125 	if (!found_irq)
   2126 		return (ACPI_PSM_FAILURE);
   2127 
   2128 	ASSERT(pci_irqp != NULL);
   2129 	*pci_irqp = cur_irq;
   2130 	return (ACPI_PSM_SUCCESS);
   2131 }
   2132 
   2133 void
   2134 ioapic_disable_redirection()
   2135 {
   2136 	int ioapic_ix;
   2137 	int intin_max;
   2138 	int intin_ix;
   2139 
   2140 	/* Disable the I/O APIC redirection entries */
   2141 	for (ioapic_ix = 0; ioapic_ix < apic_io_max; ioapic_ix++) {
   2142 
   2143 		/* Bits 23-16 define the maximum redirection entries */
   2144 		intin_max = (ioapic_read(ioapic_ix, APIC_VERS_CMD) >> 16)
   2145 		    & 0xff;
   2146 
   2147 		for (intin_ix = 0; intin_ix <= intin_max; intin_ix++) {
   2148 			/*
   2149 			 * The assumption here is that this is safe, even for
   2150 			 * systems with IOAPICs that suffer from the hardware
   2151 			 * erratum because all devices have been quiesced before
   2152 			 * this function is called from apic_shutdown()
   2153 			 * (or equivalent). If that assumption turns out to be
   2154 			 * false, this mask operation can induce the same
   2155 			 * erratum result we're trying to avoid.
   2156 			 */
   2157 			ioapic_write(ioapic_ix, APIC_RDT_CMD + 2 * intin_ix,
   2158 			    AV_MASK);
   2159 		}
   2160 	}
   2161 }
   2162 
   2163 /*
   2164  * Looks for an IOAPIC with the specified physical address in the /ioapics
   2165  * node in the device tree (created by the PCI enumerator).
   2166  */
   2167 static boolean_t
   2168 apic_is_ioapic_AMD_813x(uint32_t physaddr)
   2169 {
   2170 	/*
   2171 	 * Look in /ioapics, for the ioapic with
   2172 	 * the physical address given
   2173 	 */
   2174 	dev_info_t *ioapicsnode = ddi_find_devinfo(IOAPICS_NODE_NAME, -1, 0);
   2175 	dev_info_t *ioapic_child;
   2176 	boolean_t rv = B_FALSE;
   2177 	int vid, did;
   2178 	uint64_t ioapic_paddr;
   2179 	boolean_t done = B_FALSE;
   2180 
   2181 	if (ioapicsnode == NULL)
   2182 		return (B_FALSE);
   2183 
   2184 	/* Load first child: */
   2185 	ioapic_child = ddi_get_child(ioapicsnode);
   2186 	while (!done && ioapic_child != 0) { /* Iterate over children */
   2187 
   2188 		if ((ioapic_paddr = (uint64_t)ddi_prop_get_int64(DDI_DEV_T_ANY,
   2189 		    ioapic_child, DDI_PROP_DONTPASS, "reg", 0))
   2190 		    != 0 && physaddr == ioapic_paddr) {
   2191 
   2192 			vid = ddi_prop_get_int(DDI_DEV_T_ANY, ioapic_child,
   2193 			    DDI_PROP_DONTPASS, IOAPICS_PROP_VENID, 0);
   2194 
   2195 			if (vid == VENID_AMD) {
   2196 
   2197 				did = ddi_prop_get_int(DDI_DEV_T_ANY,
   2198 				    ioapic_child, DDI_PROP_DONTPASS,
   2199 				    IOAPICS_PROP_DEVID, 0);
   2200 
   2201 				if (did == DEVID_8131_IOAPIC ||
   2202 				    did == DEVID_8132_IOAPIC) {
   2203 					rv = B_TRUE;
   2204 					done = B_TRUE;
   2205 				}
   2206 			}
   2207 		}
   2208 
   2209 		if (!done)
   2210 			ioapic_child = ddi_get_next_sibling(ioapic_child);
   2211 	}
   2212 
   2213 	/* The ioapics node was held by ddi_find_devinfo, so release it */
   2214 	ndi_rele_devi(ioapicsnode);
   2215 	return (rv);
   2216 }
   2217 
   2218 struct apic_state {
   2219 	int32_t as_task_reg;
   2220 	int32_t as_dest_reg;
   2221 	int32_t as_format_reg;
   2222 	int32_t as_local_timer;
   2223 	int32_t as_pcint_vect;
   2224 	int32_t as_int_vect0;
   2225 	int32_t as_int_vect1;
   2226 	int32_t as_err_vect;
   2227 	int32_t as_init_count;
   2228 	int32_t as_divide_reg;
   2229 	int32_t as_spur_int_reg;
   2230 	uint32_t as_ioapic_ids[MAX_IO_APIC];
   2231 };
   2232 
   2233 
   2234 static int
   2235 apic_acpi_enter_apicmode(void)
   2236 {
   2237 	ACPI_OBJECT_LIST	arglist;
   2238 	ACPI_OBJECT		arg;
   2239 	ACPI_STATUS		status;
   2240 
   2241 	/* Setup parameter object */
   2242 	arglist.Count = 1;
   2243 	arglist.Pointer = &arg;
   2244 	arg.Type = ACPI_TYPE_INTEGER;
   2245 	arg.Integer.Value = ACPI_APIC_MODE;
   2246 
   2247 	status = AcpiEvaluateObject(NULL, "\\_PIC", &arglist, NULL);
   2248 	if (ACPI_FAILURE(status))
   2249 		return (PSM_FAILURE);
   2250 	else
   2251 		return (PSM_SUCCESS);
   2252 }
   2253 
   2254 
   2255 static void
   2256 apic_save_state(struct apic_state *sp)
   2257 {
   2258 	int	i, cpuid;
   2259 	ulong_t	iflag;
   2260 
   2261 	PMD(PMD_SX, ("apic_save_state %p\n", (void *)sp))
   2262 	/*
   2263 	 * First the local APIC.
   2264 	 */
   2265 	sp->as_task_reg = apic_reg_ops->apic_get_pri();
   2266 	sp->as_dest_reg =  apic_reg_ops->apic_read(APIC_DEST_REG);
   2267 	if (apic_mode == LOCAL_APIC)
   2268 		sp->as_format_reg = apic_reg_ops->apic_read(APIC_FORMAT_REG);
   2269 	sp->as_local_timer = apic_reg_ops->apic_read(APIC_LOCAL_TIMER);
   2270 	sp->as_pcint_vect = apic_reg_ops->apic_read(APIC_PCINT_VECT);
   2271 	sp->as_int_vect0 = apic_reg_ops->apic_read(APIC_INT_VECT0);
   2272 	sp->as_int_vect1 = apic_reg_ops->apic_read(APIC_INT_VECT1);
   2273 	sp->as_err_vect = apic_reg_ops->apic_read(APIC_ERR_VECT);
   2274 	sp->as_init_count = apic_reg_ops->apic_read(APIC_INIT_COUNT);
   2275 	sp->as_divide_reg = apic_reg_ops->apic_read(APIC_DIVIDE_REG);
   2276 	sp->as_spur_int_reg = apic_reg_ops->apic_read(APIC_SPUR_INT_REG);
   2277 
   2278 	/*
   2279 	 * If on the boot processor then save the IOAPICs' IDs
   2280 	 */
   2281 	if ((cpuid = psm_get_cpu_id()) == 0) {
   2282 
   2283 		iflag = intr_clear();
   2284 		lock_set(&apic_ioapic_lock);
   2285 
   2286 		for (i = 0; i < apic_io_max; i++)
   2287 			sp->as_ioapic_ids[i] = ioapic_read(i, APIC_ID_CMD);
   2288 
   2289 		lock_clear(&apic_ioapic_lock);
   2290 		intr_restore(iflag);
   2291 	}
   2292 
   2293 	/* apic_state() is currently invoked only in Suspend/Resume */
   2294 	apic_cpus[cpuid].aci_status |= APIC_CPU_SUSPEND;
   2295 }
   2296 
   2297 static void
   2298 apic_restore_state(struct apic_state *sp)
   2299 {
   2300 	int	i;
   2301 	ulong_t	iflag;
   2302 
   2303 	/*
   2304 	 * First the local APIC.
   2305 	 */
   2306 	apic_reg_ops->apic_write_task_reg(sp->as_task_reg);
   2307 	if (apic_mode == LOCAL_APIC) {
   2308 		apic_reg_ops->apic_write(APIC_DEST_REG, sp->as_dest_reg);
   2309 		apic_reg_ops->apic_write(APIC_FORMAT_REG, sp->as_format_reg);
   2310 	}
   2311 	apic_reg_ops->apic_write(APIC_LOCAL_TIMER, sp->as_local_timer);
   2312 	apic_reg_ops->apic_write(APIC_PCINT_VECT, sp->as_pcint_vect);
   2313 	apic_reg_ops->apic_write(APIC_INT_VECT0, sp->as_int_vect0);
   2314 	apic_reg_ops->apic_write(APIC_INT_VECT1, sp->as_int_vect1);
   2315 	apic_reg_ops->apic_write(APIC_ERR_VECT, sp->as_err_vect);
   2316 	apic_reg_ops->apic_write(APIC_INIT_COUNT, sp->as_init_count);
   2317 	apic_reg_ops->apic_write(APIC_DIVIDE_REG, sp->as_divide_reg);
   2318 	apic_reg_ops->apic_write(APIC_SPUR_INT_REG, sp->as_spur_int_reg);
   2319 
   2320 	/*
   2321 	 * the following only needs to be done once, so we do it on the
   2322 	 * boot processor, since we know that we only have one of those
   2323 	 */
   2324 	if (psm_get_cpu_id() == 0) {
   2325 
   2326 		iflag = intr_clear();
   2327 		lock_set(&apic_ioapic_lock);
   2328 
   2329 		/* Restore IOAPICs' APIC IDs */
   2330 		for (i = 0; i < apic_io_max; i++) {
   2331 			ioapic_write(i, APIC_ID_CMD, sp->as_ioapic_ids[i]);
   2332 		}
   2333 
   2334 		lock_clear(&apic_ioapic_lock);
   2335 		intr_restore(iflag);
   2336 
   2337 		/*
   2338 		 * Reenter APIC mode before restoring LNK devices
   2339 		 */
   2340 		(void) apic_acpi_enter_apicmode();
   2341 
   2342 		/*
   2343 		 * restore acpi link device mappings
   2344 		 */
   2345 		acpi_restore_link_devices();
   2346 	}
   2347 }
   2348 
   2349 /*
   2350  * Returns 0 on success
   2351  */
   2352 int
   2353 apic_state(psm_state_request_t *rp)
   2354 {
   2355 	PMD(PMD_SX, ("apic_state "))
   2356 	switch (rp->psr_cmd) {
   2357 	case PSM_STATE_ALLOC:
   2358 		rp->req.psm_state_req.psr_state =
   2359 		    kmem_zalloc(sizeof (struct apic_state), KM_NOSLEEP);
   2360 		if (rp->req.psm_state_req.psr_state == NULL)
   2361 			return (ENOMEM);
   2362 		rp->req.psm_state_req.psr_state_size =
   2363 		    sizeof (struct apic_state);
   2364 		PMD(PMD_SX, (":STATE_ALLOC: state %p, size %lx\n",
   2365 		    rp->req.psm_state_req.psr_state,
   2366 		    rp->req.psm_state_req.psr_state_size))
   2367 		return (0);
   2368 
   2369 	case PSM_STATE_FREE:
   2370 		kmem_free(rp->req.psm_state_req.psr_state,
   2371 		    rp->req.psm_state_req.psr_state_size);
   2372 		PMD(PMD_SX, (" STATE_FREE: state %p, size %lx\n",
   2373 		    rp->req.psm_state_req.psr_state,
   2374 		    rp->req.psm_state_req.psr_state_size))
   2375 		return (0);
   2376 
   2377 	case PSM_STATE_SAVE:
   2378 		PMD(PMD_SX, (" STATE_SAVE: state %p, size %lx\n",
   2379 		    rp->req.psm_state_req.psr_state,
   2380 		    rp->req.psm_state_req.psr_state_size))
   2381 		apic_save_state(rp->req.psm_state_req.psr_state);
   2382 		return (0);
   2383 
   2384 	case PSM_STATE_RESTORE:
   2385 		apic_restore_state(rp->req.psm_state_req.psr_state);
   2386 		PMD(PMD_SX, (" STATE_RESTORE: state %p, size %lx\n",
   2387 		    rp->req.psm_state_req.psr_state,
   2388 		    rp->req.psm_state_req.psr_state_size))
   2389 		return (0);
   2390 
   2391 	default:
   2392 		return (EINVAL);
   2393 	}
   2394 }
   2395