17125fcbdSVikram Hegde /*
27125fcbdSVikram Hegde  * CDDL HEADER START
37125fcbdSVikram Hegde  *
47125fcbdSVikram Hegde  * The contents of this file are subject to the terms of the
57125fcbdSVikram Hegde  * Common Development and Distribution License (the "License").
67125fcbdSVikram Hegde  * You may not use this file except in compliance with the License.
77125fcbdSVikram Hegde  *
87125fcbdSVikram Hegde  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97125fcbdSVikram Hegde  * or http://www.opensolaris.org/os/licensing.
107125fcbdSVikram Hegde  * See the License for the specific language governing permissions
117125fcbdSVikram Hegde  * and limitations under the License.
127125fcbdSVikram Hegde  *
137125fcbdSVikram Hegde  * When distributing Covered Code, include this CDDL HEADER in each
147125fcbdSVikram Hegde  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157125fcbdSVikram Hegde  * If applicable, add the following below this CDDL HEADER, with the
167125fcbdSVikram Hegde  * fields enclosed by brackets "[]" replaced with your own identifying
177125fcbdSVikram Hegde  * information: Portions Copyright [yyyy] [name of copyright owner]
187125fcbdSVikram Hegde  *
197125fcbdSVikram Hegde  * CDDL HEADER END
207125fcbdSVikram Hegde  */
217125fcbdSVikram Hegde 
227125fcbdSVikram Hegde /*
23ba758cf1SJerry Gilliam  * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
247125fcbdSVikram Hegde  */
257125fcbdSVikram Hegde 
267125fcbdSVikram Hegde #include "amd_iommu_acpi.h"
277125fcbdSVikram Hegde #include "amd_iommu_impl.h"
287125fcbdSVikram Hegde 
2994f1124eSVikram Hegde static int create_acpi_hash(amd_iommu_acpi_t *acpi);
3094f1124eSVikram Hegde static void amd_iommu_acpi_table_fini(amd_iommu_acpi_t **acpipp);
3194f1124eSVikram Hegde 
3294f1124eSVikram Hegde static void dump_acpi_aliases(void);
3394f1124eSVikram Hegde 
3494f1124eSVikram Hegde 
3594f1124eSVikram Hegde /*
3694f1124eSVikram Hegde  * Globals
3794f1124eSVikram Hegde  */
3894f1124eSVikram Hegde static amd_iommu_acpi_global_t *amd_iommu_acpi_global;
3994f1124eSVikram Hegde static amd_iommu_acpi_ivhd_t **amd_iommu_acpi_ivhd_hash;
4094f1124eSVikram Hegde static amd_iommu_acpi_ivmd_t **amd_iommu_acpi_ivmd_hash;
4194f1124eSVikram Hegde 
427125fcbdSVikram Hegde static int
type_byte_size(char * cp)437125fcbdSVikram Hegde type_byte_size(char *cp)
447125fcbdSVikram Hegde {
457125fcbdSVikram Hegde 	uint8_t type8 = *((uint8_t *)cp);
467125fcbdSVikram Hegde 	uint8_t len_bits;
477125fcbdSVikram Hegde 
4894f1124eSVikram Hegde 	len_bits = AMD_IOMMU_REG_GET8(&type8, AMD_IOMMU_ACPI_DEVENTRY_LEN);
497125fcbdSVikram Hegde 
507125fcbdSVikram Hegde 	switch (len_bits) {
517125fcbdSVikram Hegde 	case 0:
527125fcbdSVikram Hegde 			return (4);
537125fcbdSVikram Hegde 	case 1:
547125fcbdSVikram Hegde 			return (8);
557125fcbdSVikram Hegde 	case 2:
567125fcbdSVikram Hegde 			return (16);
577125fcbdSVikram Hegde 	case 3:
587125fcbdSVikram Hegde 			return (32);
597125fcbdSVikram Hegde 	default:
607125fcbdSVikram Hegde 			cmn_err(CE_WARN, "%s: Invalid deventry len: %d",
617125fcbdSVikram Hegde 			    amd_iommu_modname, len_bits);
627125fcbdSVikram Hegde 			return (len_bits);
637125fcbdSVikram Hegde 	}
647125fcbdSVikram Hegde 	/*NOTREACHED*/
657125fcbdSVikram Hegde }
667125fcbdSVikram Hegde 
677125fcbdSVikram Hegde static void
process_4byte_deventry(ivhd_container_t * c,char * cp)687125fcbdSVikram Hegde process_4byte_deventry(ivhd_container_t *c, char *cp)
697125fcbdSVikram Hegde {
7094f1124eSVikram Hegde 	int entry_type = *((uint8_t *)cp);
7194f1124eSVikram Hegde 	ivhd_deventry_t deventry = {0};
727125fcbdSVikram Hegde 	ivhd_deventry_t *devp;
7394f1124eSVikram Hegde 	uint8_t datsetting8;
7494f1124eSVikram Hegde 	align_16_t al = {0};
7594f1124eSVikram Hegde 	int i;
7694f1124eSVikram Hegde 
7794f1124eSVikram Hegde 	/* 4 byte entry */
7894f1124eSVikram Hegde 	deventry.idev_len = 4;
7994f1124eSVikram Hegde 	deventry.idev_deviceid = -1;
8094f1124eSVikram Hegde 	deventry.idev_src_deviceid = -1;
8194f1124eSVikram Hegde 
8294f1124eSVikram Hegde 	for (i = 0; i < 2; i++) {
8394f1124eSVikram Hegde 		al.ent8[i] = *((uint8_t *)&cp[i + 1]);
8494f1124eSVikram Hegde 	}
857125fcbdSVikram Hegde 
867125fcbdSVikram Hegde 	switch (entry_type) {
877125fcbdSVikram Hegde 	case 1:
8894f1124eSVikram Hegde 		deventry.idev_type = DEVENTRY_ALL;
897125fcbdSVikram Hegde 		break;
907125fcbdSVikram Hegde 	case 2:
9194f1124eSVikram Hegde 		deventry.idev_type = DEVENTRY_SELECT;
9294f1124eSVikram Hegde 		deventry.idev_deviceid = al.ent16;
937125fcbdSVikram Hegde 		break;
947125fcbdSVikram Hegde 	case 3:
9594f1124eSVikram Hegde 		deventry.idev_type = DEVENTRY_RANGE;
9694f1124eSVikram Hegde 		deventry.idev_deviceid = al.ent16;
977125fcbdSVikram Hegde 		break;
987125fcbdSVikram Hegde 	case 4:
9994f1124eSVikram Hegde 		deventry.idev_type = DEVENTRY_RANGE_END;
10094f1124eSVikram Hegde 		deventry.idev_deviceid = al.ent16;
10194f1124eSVikram Hegde 		ASSERT(cp[3] == 0);
1027125fcbdSVikram Hegde 		break;
10394f1124eSVikram Hegde 	case 0:
10494f1124eSVikram Hegde 		ASSERT(al.ent16 == 0);
10594f1124eSVikram Hegde 		ASSERT(cp[3] == 0);
1067125fcbdSVikram Hegde 	default:
1077125fcbdSVikram Hegde 		return;
1087125fcbdSVikram Hegde 	}
1097125fcbdSVikram Hegde 
11094f1124eSVikram Hegde 
1117125fcbdSVikram Hegde 	devp = kmem_alloc(sizeof (ivhd_deventry_t), KM_SLEEP);
1127125fcbdSVikram Hegde 	*devp = deventry;
1137125fcbdSVikram Hegde 
1147125fcbdSVikram Hegde 	if (c->ivhdc_first_deventry == NULL)
1157125fcbdSVikram Hegde 		c->ivhdc_first_deventry =  devp;
1167125fcbdSVikram Hegde 	else
1177125fcbdSVikram Hegde 		c->ivhdc_last_deventry->idev_next = devp;
1187125fcbdSVikram Hegde 
1197125fcbdSVikram Hegde 	c->ivhdc_last_deventry = devp;
1207125fcbdSVikram Hegde 
1217125fcbdSVikram Hegde 	if (entry_type == 4)
1227125fcbdSVikram Hegde 		return;
1237125fcbdSVikram Hegde 
12494f1124eSVikram Hegde 	datsetting8 = (*((uint8_t *)&cp[3]));
1257125fcbdSVikram Hegde 
12694f1124eSVikram Hegde 	devp->idev_Lint1Pass = AMD_IOMMU_REG_GET8(&datsetting8,
1277125fcbdSVikram Hegde 	    AMD_IOMMU_ACPI_LINT1PASS);
1287125fcbdSVikram Hegde 
12994f1124eSVikram Hegde 	devp->idev_Lint0Pass = AMD_IOMMU_REG_GET8(&datsetting8,
1307125fcbdSVikram Hegde 	    AMD_IOMMU_ACPI_LINT0PASS);
1317125fcbdSVikram Hegde 
13294f1124eSVikram Hegde 	devp->idev_SysMgt = AMD_IOMMU_REG_GET8(&datsetting8,
1337125fcbdSVikram Hegde 	    AMD_IOMMU_ACPI_SYSMGT);
1347125fcbdSVikram Hegde 
13594f1124eSVikram Hegde 	ASSERT(AMD_IOMMU_REG_GET8(&datsetting8,
13694f1124eSVikram Hegde 	    AMD_IOMMU_ACPI_DATRSV) == 0);
13794f1124eSVikram Hegde 
13894f1124eSVikram Hegde 	devp->idev_NMIPass = AMD_IOMMU_REG_GET8(&datsetting8,
1397125fcbdSVikram Hegde 	    AMD_IOMMU_ACPI_NMIPASS);
1407125fcbdSVikram Hegde 
14194f1124eSVikram Hegde 	devp->idev_ExtIntPass = AMD_IOMMU_REG_GET8(&datsetting8,
1427125fcbdSVikram Hegde 	    AMD_IOMMU_ACPI_EXTINTPASS);
1437125fcbdSVikram Hegde 
14494f1124eSVikram Hegde 	devp->idev_INITPass = AMD_IOMMU_REG_GET8(&datsetting8,
1457125fcbdSVikram Hegde 	    AMD_IOMMU_ACPI_INITPASS);
1467125fcbdSVikram Hegde }
1477125fcbdSVikram Hegde 
1487125fcbdSVikram Hegde static void
process_8byte_deventry(ivhd_container_t * c,char * cp)1497125fcbdSVikram Hegde process_8byte_deventry(ivhd_container_t *c, char *cp)
1507125fcbdSVikram Hegde {
15194f1124eSVikram Hegde 	uint8_t datsetting8;
1527125fcbdSVikram Hegde 	int entry_type = (uint8_t)*cp;
15394f1124eSVikram Hegde 	ivhd_deventry_t deventry = {0};
1547125fcbdSVikram Hegde 	ivhd_deventry_t *devp;
15594f1124eSVikram Hegde 	align_16_t al1 = {0};
15694f1124eSVikram Hegde 	align_16_t al2 = {0};
15794f1124eSVikram Hegde 	align_32_t al3 = {0};
15894f1124eSVikram Hegde 	int i;
15994f1124eSVikram Hegde 
16094f1124eSVikram Hegde 	/* Length is 8 bytes */
16194f1124eSVikram Hegde 	deventry.idev_len = 8;
16294f1124eSVikram Hegde 	deventry.idev_deviceid = -1;
16394f1124eSVikram Hegde 	deventry.idev_src_deviceid = -1;
16494f1124eSVikram Hegde 
16594f1124eSVikram Hegde 	for (i = 0; i < 2; i++) {
16694f1124eSVikram Hegde 		al1.ent8[i] = *((uint8_t *)&cp[i+1]);
16794f1124eSVikram Hegde 		al2.ent8[i] = *((uint8_t *)&cp[i+5]);
16894f1124eSVikram Hegde 	}
16994f1124eSVikram Hegde 
17094f1124eSVikram Hegde 	datsetting8 = *((uint8_t *)&cp[3]);
1717125fcbdSVikram Hegde 
1727125fcbdSVikram Hegde 	switch (entry_type) {
1737125fcbdSVikram Hegde 	case 66:
17494f1124eSVikram Hegde 		deventry.idev_type = DEVENTRY_ALIAS_SELECT;
17594f1124eSVikram Hegde 		deventry.idev_deviceid = al1.ent16;
17694f1124eSVikram Hegde 		deventry.idev_src_deviceid = al2.ent16;
17794f1124eSVikram Hegde 		ASSERT(cp[4] == 0);
17894f1124eSVikram Hegde 		ASSERT(cp[7] == 0);
1797125fcbdSVikram Hegde 		break;
1807125fcbdSVikram Hegde 	case 67:
18194f1124eSVikram Hegde 		deventry.idev_type = DEVENTRY_ALIAS_RANGE;
18294f1124eSVikram Hegde 		deventry.idev_deviceid = al1.ent16;
18394f1124eSVikram Hegde 		deventry.idev_src_deviceid = al2.ent16;
18494f1124eSVikram Hegde 		ASSERT(cp[4] == 0);
18594f1124eSVikram Hegde 		ASSERT(cp[7] == 0);
1867125fcbdSVikram Hegde 		break;
1877125fcbdSVikram Hegde 	case 70:
18894f1124eSVikram Hegde 		deventry.idev_type = DEVENTRY_EXTENDED_SELECT;
18994f1124eSVikram Hegde 		deventry.idev_deviceid = al1.ent16;
1907125fcbdSVikram Hegde 		break;
1917125fcbdSVikram Hegde 	case 71:
19294f1124eSVikram Hegde 		deventry.idev_type = DEVENTRY_EXTENDED_RANGE;
19394f1124eSVikram Hegde 		deventry.idev_deviceid = al1.ent16;
1947125fcbdSVikram Hegde 		break;
19594f1124eSVikram Hegde 	case 72:
19694f1124eSVikram Hegde 		deventry.idev_type = DEVENTRY_SPECIAL_DEVICE;
19794f1124eSVikram Hegde 		ASSERT(al1.ent16 == 0);
19894f1124eSVikram Hegde 		deventry.idev_deviceid = -1;
19994f1124eSVikram Hegde 		deventry.idev_handle = cp[4];
20094f1124eSVikram Hegde 		deventry.idev_variety = cp[7];
20194f1124eSVikram Hegde 		deventry.idev_src_deviceid = al2.ent16;
2027125fcbdSVikram Hegde 	default:
20394f1124eSVikram Hegde #ifdef BROKEN_ASSERT
20494f1124eSVikram Hegde 		for (i = 0; i < 7; i++) {
20594f1124eSVikram Hegde 			ASSERT(cp[i] == 0);
20694f1124eSVikram Hegde 		}
20794f1124eSVikram Hegde #endif
2087125fcbdSVikram Hegde 		return;
2097125fcbdSVikram Hegde 	}
2107125fcbdSVikram Hegde 
21194f1124eSVikram Hegde 
2127125fcbdSVikram Hegde 	devp = kmem_alloc(sizeof (ivhd_deventry_t), KM_SLEEP);
2137125fcbdSVikram Hegde 	*devp = deventry;
2147125fcbdSVikram Hegde 
2157125fcbdSVikram Hegde 	if (c->ivhdc_first_deventry == NULL)
2167125fcbdSVikram Hegde 		c->ivhdc_first_deventry =  devp;
2177125fcbdSVikram Hegde 	else
2187125fcbdSVikram Hegde 		c->ivhdc_last_deventry->idev_next = devp;
2197125fcbdSVikram Hegde 
2207125fcbdSVikram Hegde 	c->ivhdc_last_deventry = devp;
2217125fcbdSVikram Hegde 
22294f1124eSVikram Hegde 	devp->idev_Lint1Pass = AMD_IOMMU_REG_GET8(&datsetting8,
2237125fcbdSVikram Hegde 	    AMD_IOMMU_ACPI_LINT1PASS);
2247125fcbdSVikram Hegde 
22594f1124eSVikram Hegde 	devp->idev_Lint0Pass = AMD_IOMMU_REG_GET8(&datsetting8,
2267125fcbdSVikram Hegde 	    AMD_IOMMU_ACPI_LINT0PASS);
2277125fcbdSVikram Hegde 
22894f1124eSVikram Hegde 	devp->idev_SysMgt = AMD_IOMMU_REG_GET8(&datsetting8,
2297125fcbdSVikram Hegde 	    AMD_IOMMU_ACPI_SYSMGT);
2307125fcbdSVikram Hegde 
23194f1124eSVikram Hegde 	ASSERT(AMD_IOMMU_REG_GET8(&datsetting8,
23294f1124eSVikram Hegde 	    AMD_IOMMU_ACPI_DATRSV) == 0);
23394f1124eSVikram Hegde 
23494f1124eSVikram Hegde 	devp->idev_NMIPass = AMD_IOMMU_REG_GET8(&datsetting8,
2357125fcbdSVikram Hegde 	    AMD_IOMMU_ACPI_NMIPASS);
2367125fcbdSVikram Hegde 
23794f1124eSVikram Hegde 	devp->idev_ExtIntPass = AMD_IOMMU_REG_GET8(&datsetting8,
2387125fcbdSVikram Hegde 	    AMD_IOMMU_ACPI_EXTINTPASS);
2397125fcbdSVikram Hegde 
24094f1124eSVikram Hegde 	devp->idev_INITPass = AMD_IOMMU_REG_GET8(&datsetting8,
2417125fcbdSVikram Hegde 	    AMD_IOMMU_ACPI_INITPASS);
2427125fcbdSVikram Hegde 
24394f1124eSVikram Hegde 	if (entry_type != 70 && entry_type != 71) {
24494f1124eSVikram Hegde 		return;
24594f1124eSVikram Hegde 	}
2467125fcbdSVikram Hegde 
24794f1124eSVikram Hegde 	/* Type 70 and 71 */
24894f1124eSVikram Hegde 	for (i = 0; i < 4; i++) {
24994f1124eSVikram Hegde 		al3.ent8[i] = *((uint8_t *)&cp[i+4]);
2507125fcbdSVikram Hegde 	}
25194f1124eSVikram Hegde 
25294f1124eSVikram Hegde 	devp->idev_AtsDisabled = AMD_IOMMU_REG_GET8(&al3.ent32,
25394f1124eSVikram Hegde 	    AMD_IOMMU_ACPI_ATSDISABLED);
25494f1124eSVikram Hegde 
25594f1124eSVikram Hegde 	ASSERT(AMD_IOMMU_REG_GET8(&al3.ent32, AMD_IOMMU_ACPI_EXTDATRSV) == 0);
2567125fcbdSVikram Hegde }
2577125fcbdSVikram Hegde 
2587125fcbdSVikram Hegde static void
process_ivhd(amd_iommu_acpi_t * acpi,ivhd_t * ivhdp)2597125fcbdSVikram Hegde process_ivhd(amd_iommu_acpi_t *acpi, ivhd_t *ivhdp)
2607125fcbdSVikram Hegde {
2617125fcbdSVikram Hegde 	ivhd_container_t *c;
2627125fcbdSVikram Hegde 	caddr_t ivhd_end;
2637125fcbdSVikram Hegde 	caddr_t ivhd_tot_end;
2647125fcbdSVikram Hegde 	caddr_t cp;
2657125fcbdSVikram Hegde 
26694f1124eSVikram Hegde 	ASSERT(ivhdp->ivhd_type == 0x10);
26794f1124eSVikram Hegde 
2687125fcbdSVikram Hegde 	c = kmem_zalloc(sizeof (ivhd_container_t), KM_SLEEP);
2697125fcbdSVikram Hegde 	c->ivhdc_ivhd = kmem_alloc(sizeof (ivhd_t), KM_SLEEP);
2707125fcbdSVikram Hegde 	*(c->ivhdc_ivhd) = *ivhdp;
2717125fcbdSVikram Hegde 
2727125fcbdSVikram Hegde 	if (acpi->acp_first_ivhdc == NULL)
2737125fcbdSVikram Hegde 		acpi->acp_first_ivhdc = c;
2747125fcbdSVikram Hegde 	else
2757125fcbdSVikram Hegde 		acpi->acp_last_ivhdc->ivhdc_next = c;
2767125fcbdSVikram Hegde 
2777125fcbdSVikram Hegde 	acpi->acp_last_ivhdc = c;
2787125fcbdSVikram Hegde 
2797125fcbdSVikram Hegde 	ivhd_end = (caddr_t)ivhdp + sizeof (ivhd_t);
2807125fcbdSVikram Hegde 	ivhd_tot_end = (caddr_t)ivhdp + ivhdp->ivhd_len;
2817125fcbdSVikram Hegde 
2827125fcbdSVikram Hegde 	for (cp = ivhd_end; cp < ivhd_tot_end; cp += type_byte_size(cp)) {
2837125fcbdSVikram Hegde 		/* 16 byte and 32 byte size are currently reserved */
2847125fcbdSVikram Hegde 		switch (type_byte_size(cp)) {
2857125fcbdSVikram Hegde 		case 4:
2867125fcbdSVikram Hegde 			process_4byte_deventry(c, cp);
2877125fcbdSVikram Hegde 			break;
2887125fcbdSVikram Hegde 		case 8:
2897125fcbdSVikram Hegde 			process_8byte_deventry(c, cp);
2907125fcbdSVikram Hegde 			break;
2917125fcbdSVikram Hegde 		case 16:
2927125fcbdSVikram Hegde 		case 32:
2937125fcbdSVikram Hegde 			/* Reserved */
2947125fcbdSVikram Hegde 			break;
2957125fcbdSVikram Hegde 		default:
2967125fcbdSVikram Hegde 			cmn_err(CE_WARN, "%s: unsupported length for device "
2977125fcbdSVikram Hegde 			    "entry in ACPI IVRS table's IVHD entry",
2987125fcbdSVikram Hegde 			    amd_iommu_modname);
2997125fcbdSVikram Hegde 			break;
3007125fcbdSVikram Hegde 		}
3017125fcbdSVikram Hegde 	}
3027125fcbdSVikram Hegde }
3037125fcbdSVikram Hegde 
3047125fcbdSVikram Hegde static void
process_ivmd(amd_iommu_acpi_t * acpi,ivmd_t * ivmdp)3057125fcbdSVikram Hegde process_ivmd(amd_iommu_acpi_t *acpi, ivmd_t *ivmdp)
3067125fcbdSVikram Hegde {
3077125fcbdSVikram Hegde 	ivmd_container_t *c;
3087125fcbdSVikram Hegde 
30994f1124eSVikram Hegde 	ASSERT(ivmdp->ivmd_type != 0x10);
31094f1124eSVikram Hegde 
3117125fcbdSVikram Hegde 	c = kmem_zalloc(sizeof (ivmd_container_t), KM_SLEEP);
3127125fcbdSVikram Hegde 	c->ivmdc_ivmd = kmem_alloc(sizeof (ivmd_t), KM_SLEEP);
3137125fcbdSVikram Hegde 	*(c->ivmdc_ivmd) = *ivmdp;
3147125fcbdSVikram Hegde 
3157125fcbdSVikram Hegde 	if (acpi->acp_first_ivmdc == NULL)
3167125fcbdSVikram Hegde 		acpi->acp_first_ivmdc = c;
3177125fcbdSVikram Hegde 	else
3187125fcbdSVikram Hegde 		acpi->acp_last_ivmdc->ivmdc_next = c;
3197125fcbdSVikram Hegde 
3207125fcbdSVikram Hegde 	acpi->acp_last_ivmdc = c;
3217125fcbdSVikram Hegde }
3227125fcbdSVikram Hegde 
3237125fcbdSVikram Hegde int
amd_iommu_acpi_init(void)32494f1124eSVikram Hegde amd_iommu_acpi_init(void)
3257125fcbdSVikram Hegde {
3267125fcbdSVikram Hegde 	ivrs_t *ivrsp;
3277125fcbdSVikram Hegde 	caddr_t ivrsp_end;
3287125fcbdSVikram Hegde 	caddr_t table_end;
3297125fcbdSVikram Hegde 	caddr_t cp;
3307125fcbdSVikram Hegde 	uint8_t type8;
3317125fcbdSVikram Hegde 	amd_iommu_acpi_t *acpi;
33294f1124eSVikram Hegde 	align_ivhd_t al_vhd = {0};
33394f1124eSVikram Hegde 	align_ivmd_t al_vmd = {0};
3347125fcbdSVikram Hegde 
335db2bae30SDana Myers 	if (AcpiGetTable(IVRS_SIG, 1, (ACPI_TABLE_HEADER **)&ivrsp) != AE_OK) {
3367125fcbdSVikram Hegde 		cmn_err(CE_NOTE, "!amd_iommu: No AMD IOMMU ACPI IVRS table");
3377125fcbdSVikram Hegde 		return (DDI_FAILURE);
3387125fcbdSVikram Hegde 	}
3397125fcbdSVikram Hegde 
34094f1124eSVikram Hegde 	/*
34194f1124eSVikram Hegde 	 * Reserved field must be 0
34294f1124eSVikram Hegde 	 */
34394f1124eSVikram Hegde 	ASSERT(ivrsp->ivrs_resv == 0);
34494f1124eSVikram Hegde 
34594f1124eSVikram Hegde 	ASSERT(AMD_IOMMU_REG_GET32(&ivrsp->ivrs_ivinfo,
34694f1124eSVikram Hegde 	    AMD_IOMMU_ACPI_IVINFO_RSV1) == 0);
34794f1124eSVikram Hegde 	ASSERT(AMD_IOMMU_REG_GET32(&ivrsp->ivrs_ivinfo,
34894f1124eSVikram Hegde 	    AMD_IOMMU_ACPI_IVINFO_RSV2) == 0);
3497125fcbdSVikram Hegde 
3507125fcbdSVikram Hegde 	ivrsp_end = (caddr_t)ivrsp + sizeof (struct ivrs);
3517125fcbdSVikram Hegde 	table_end = (caddr_t)ivrsp + ivrsp->ivrs_hdr.Length;
3527125fcbdSVikram Hegde 
3537125fcbdSVikram Hegde 	acpi = kmem_zalloc(sizeof (amd_iommu_acpi_t), KM_SLEEP);
3547125fcbdSVikram Hegde 	acpi->acp_ivrs = kmem_alloc(sizeof (ivrs_t), KM_SLEEP);
3557125fcbdSVikram Hegde 	*(acpi->acp_ivrs) = *ivrsp;
3567125fcbdSVikram Hegde 
35794f1124eSVikram Hegde 	for (cp = ivrsp_end; cp < table_end; cp += (al_vhd.ivhdp)->ivhd_len) {
35894f1124eSVikram Hegde 		al_vhd.cp = cp;
35994f1124eSVikram Hegde 		if (al_vhd.ivhdp->ivhd_type == 0x10)
36094f1124eSVikram Hegde 			process_ivhd(acpi, al_vhd.ivhdp);
3617125fcbdSVikram Hegde 	}
3627125fcbdSVikram Hegde 
36394f1124eSVikram Hegde 	for (cp = ivrsp_end; cp < table_end; cp += (al_vmd.ivmdp)->ivmd_len) {
36494f1124eSVikram Hegde 		al_vmd.cp = cp;
36594f1124eSVikram Hegde 		type8 = al_vmd.ivmdp->ivmd_type;
36694f1124eSVikram Hegde 		if (type8 == 0x20 || type8 == 0x21 || type8 == 0x22)
36794f1124eSVikram Hegde 			process_ivmd(acpi, al_vmd.ivmdp);
3687125fcbdSVikram Hegde 	}
3697125fcbdSVikram Hegde 
37094f1124eSVikram Hegde 	if (create_acpi_hash(acpi) != DDI_SUCCESS) {
37194f1124eSVikram Hegde 		return (DDI_FAILURE);
37294f1124eSVikram Hegde 	}
37394f1124eSVikram Hegde 
37494f1124eSVikram Hegde 	amd_iommu_acpi_table_fini(&acpi);
37594f1124eSVikram Hegde 
37694f1124eSVikram Hegde 	ASSERT(acpi == NULL);
37794f1124eSVikram Hegde 
37894f1124eSVikram Hegde 	if (amd_iommu_debug & AMD_IOMMU_DEBUG_ACPI) {
37994f1124eSVikram Hegde 		dump_acpi_aliases();
38094f1124eSVikram Hegde 		debug_enter("dump");
38194f1124eSVikram Hegde 	}
3827125fcbdSVikram Hegde 
3837125fcbdSVikram Hegde 	return (DDI_SUCCESS);
3847125fcbdSVikram Hegde }
3857125fcbdSVikram Hegde 
3867125fcbdSVikram Hegde static ivhd_deventry_t *
free_ivhd_deventry(ivhd_deventry_t * devp)3877125fcbdSVikram Hegde free_ivhd_deventry(ivhd_deventry_t *devp)
3887125fcbdSVikram Hegde {
3897125fcbdSVikram Hegde 	ivhd_deventry_t *next = devp->idev_next;
3907125fcbdSVikram Hegde 
3917125fcbdSVikram Hegde 	kmem_free(devp, sizeof (ivhd_deventry_t));
3927125fcbdSVikram Hegde 
3937125fcbdSVikram Hegde 	return (next);
3947125fcbdSVikram Hegde }
3957125fcbdSVikram Hegde 
3967125fcbdSVikram Hegde static ivhd_container_t *
free_ivhd_container(ivhd_container_t * ivhdcp)3977125fcbdSVikram Hegde free_ivhd_container(ivhd_container_t *ivhdcp)
3987125fcbdSVikram Hegde {
3997125fcbdSVikram Hegde 	ivhd_container_t *next = ivhdcp->ivhdc_next;
4007125fcbdSVikram Hegde 	ivhd_deventry_t *devp;
4017125fcbdSVikram Hegde 
4027125fcbdSVikram Hegde 	for (devp = ivhdcp->ivhdc_first_deventry; devp; ) {
4037125fcbdSVikram Hegde 		devp = free_ivhd_deventry(devp);
4047125fcbdSVikram Hegde 	}
4057125fcbdSVikram Hegde 
4067125fcbdSVikram Hegde 	kmem_free(ivhdcp->ivhdc_ivhd, sizeof (ivhd_t));
4077125fcbdSVikram Hegde 	kmem_free(ivhdcp, sizeof (ivhd_container_t));
4087125fcbdSVikram Hegde 
4097125fcbdSVikram Hegde 	return (next);
4107125fcbdSVikram Hegde }
4117125fcbdSVikram Hegde 
4127125fcbdSVikram Hegde static ivmd_container_t *
free_ivmd_container(ivmd_container_t * ivmdcp)4137125fcbdSVikram Hegde free_ivmd_container(ivmd_container_t *ivmdcp)
4147125fcbdSVikram Hegde {
4157125fcbdSVikram Hegde 	ivmd_container_t *next = ivmdcp->ivmdc_next;
4167125fcbdSVikram Hegde 
4177125fcbdSVikram Hegde 	kmem_free(ivmdcp->ivmdc_ivmd, sizeof (ivmd_t));
4187125fcbdSVikram Hegde 	kmem_free(ivmdcp, sizeof (ivmd_container_t));
4197125fcbdSVikram Hegde 
4207125fcbdSVikram Hegde 	return (next);
4217125fcbdSVikram Hegde }
4227125fcbdSVikram Hegde 
4237125fcbdSVikram Hegde void
amd_iommu_acpi_fini(void)42494f1124eSVikram Hegde amd_iommu_acpi_fini(void)
42594f1124eSVikram Hegde {
42694f1124eSVikram Hegde }
42794f1124eSVikram Hegde 
42894f1124eSVikram Hegde /*
42994f1124eSVikram Hegde  * TODO: Do we need to free the ACPI table for om GetFirmwareTable()
43094f1124eSVikram Hegde  */
43194f1124eSVikram Hegde static void
amd_iommu_acpi_table_fini(amd_iommu_acpi_t ** acpipp)43294f1124eSVikram Hegde amd_iommu_acpi_table_fini(amd_iommu_acpi_t **acpipp)
4337125fcbdSVikram Hegde {
4347125fcbdSVikram Hegde 	amd_iommu_acpi_t *acpi = *acpipp;
4357125fcbdSVikram Hegde 	ivhd_container_t *ivhdcp;
4367125fcbdSVikram Hegde 	ivmd_container_t *ivmdcp;
4377125fcbdSVikram Hegde 
4387125fcbdSVikram Hegde 	ASSERT(acpi);
4397125fcbdSVikram Hegde 
4407125fcbdSVikram Hegde 	for (ivhdcp = acpi->acp_first_ivhdc; ivhdcp; ) {
4417125fcbdSVikram Hegde 		ivhdcp = free_ivhd_container(ivhdcp);
4427125fcbdSVikram Hegde 	}
4437125fcbdSVikram Hegde 	for (ivmdcp = acpi->acp_first_ivmdc; ivmdcp; ) {
4447125fcbdSVikram Hegde 		ivmdcp = free_ivmd_container(ivmdcp);
4457125fcbdSVikram Hegde 	}
4467125fcbdSVikram Hegde 
4477125fcbdSVikram Hegde 	kmem_free(acpi->acp_ivrs, sizeof (struct ivrs));
4487125fcbdSVikram Hegde 	kmem_free(acpi, sizeof (amd_iommu_acpi_t));
4497125fcbdSVikram Hegde 
4507125fcbdSVikram Hegde 	*acpipp = NULL;
4517125fcbdSVikram Hegde }
4527125fcbdSVikram Hegde 
4537125fcbdSVikram Hegde static uint16_t
deviceid_hashfn(uint16_t deviceid)45494f1124eSVikram Hegde deviceid_hashfn(uint16_t deviceid)
4557125fcbdSVikram Hegde {
45694f1124eSVikram Hegde 	return (deviceid % AMD_IOMMU_ACPI_INFO_HASH_SZ);
4577125fcbdSVikram Hegde }
4587125fcbdSVikram Hegde 
4597125fcbdSVikram Hegde static void
add_deventry_info(ivhd_t * ivhdp,ivhd_deventry_t * deventry,amd_iommu_acpi_ivhd_t ** hash)46094f1124eSVikram Hegde add_deventry_info(ivhd_t *ivhdp, ivhd_deventry_t *deventry,
46194f1124eSVikram Hegde     amd_iommu_acpi_ivhd_t **hash)
4627125fcbdSVikram Hegde {
46394f1124eSVikram Hegde 	static amd_iommu_acpi_ivhd_t *last;
46494f1124eSVikram Hegde 	amd_iommu_acpi_ivhd_t *acpi_ivhdp;
46594f1124eSVikram Hegde 	uint8_t uint8_flags;
46694f1124eSVikram Hegde 	uint16_t uint16_info;
4677125fcbdSVikram Hegde 	uint16_t idx;
4687125fcbdSVikram Hegde 
46994f1124eSVikram Hegde 	if (deventry->idev_type == DEVENTRY_RANGE_END) {
47094f1124eSVikram Hegde 		ASSERT(last);
47194f1124eSVikram Hegde 		acpi_ivhdp = last;
47294f1124eSVikram Hegde 		last = NULL;
47394f1124eSVikram Hegde 		ASSERT(acpi_ivhdp->ach_dev_type == DEVENTRY_RANGE ||
47494f1124eSVikram Hegde 		    acpi_ivhdp->ach_dev_type == DEVENTRY_ALIAS_RANGE ||
47594f1124eSVikram Hegde 		    acpi_ivhdp->ach_dev_type == DEVENTRY_EXTENDED_RANGE);
47694f1124eSVikram Hegde 		ASSERT(acpi_ivhdp->ach_deviceid_end == -1);
47794f1124eSVikram Hegde 		acpi_ivhdp->ach_deviceid_end = deventry->idev_deviceid;
47894f1124eSVikram Hegde 		/* TODO ASSERT data is 0 */
47994f1124eSVikram Hegde 		return;
48094f1124eSVikram Hegde 	}
4817125fcbdSVikram Hegde 
48294f1124eSVikram Hegde 	ASSERT(last == NULL);
48394f1124eSVikram Hegde 	acpi_ivhdp = kmem_zalloc(sizeof (*acpi_ivhdp), KM_SLEEP);
48494f1124eSVikram Hegde 
48594f1124eSVikram Hegde 	uint8_flags = ivhdp->ivhd_flags;
48694f1124eSVikram Hegde 
48794f1124eSVikram Hegde #ifdef BROKEN_ASSERT
48894f1124eSVikram Hegde 	ASSERT(AMD_IOMMU_REG_GET8(&uint8_flags,
48994f1124eSVikram Hegde 	    AMD_IOMMU_ACPI_IVHD_FLAGS_RSV) == 0);
49094f1124eSVikram Hegde #endif
49194f1124eSVikram Hegde 
49294f1124eSVikram Hegde 	acpi_ivhdp->ach_IotlbSup = AMD_IOMMU_REG_GET8(&uint8_flags,
49394f1124eSVikram Hegde 	    AMD_IOMMU_ACPI_IVHD_FLAGS_IOTLBSUP);
49494f1124eSVikram Hegde 	acpi_ivhdp->ach_Isoc = AMD_IOMMU_REG_GET8(&uint8_flags,
49594f1124eSVikram Hegde 	    AMD_IOMMU_ACPI_IVHD_FLAGS_ISOC);
49694f1124eSVikram Hegde 	acpi_ivhdp->ach_ResPassPW = AMD_IOMMU_REG_GET8(&uint8_flags,
49794f1124eSVikram Hegde 	    AMD_IOMMU_ACPI_IVHD_FLAGS_RESPASSPW);
49894f1124eSVikram Hegde 	acpi_ivhdp->ach_PassPW = AMD_IOMMU_REG_GET8(&uint8_flags,
49994f1124eSVikram Hegde 	    AMD_IOMMU_ACPI_IVHD_FLAGS_PASSPW);
50094f1124eSVikram Hegde 	acpi_ivhdp->ach_HtTunEn = AMD_IOMMU_REG_GET8(&uint8_flags,
50194f1124eSVikram Hegde 	    AMD_IOMMU_ACPI_IVHD_FLAGS_HTTUNEN);
50294f1124eSVikram Hegde 
50394f1124eSVikram Hegde 	/* IVHD fields */
50494f1124eSVikram Hegde 	acpi_ivhdp->ach_IOMMU_deviceid = ivhdp->ivhd_deviceid;
50594f1124eSVikram Hegde 	acpi_ivhdp->ach_IOMMU_cap_off = ivhdp->ivhd_cap_off;
50694f1124eSVikram Hegde 	acpi_ivhdp->ach_IOMMU_reg_base = ivhdp->ivhd_reg_base;
50794f1124eSVikram Hegde 	acpi_ivhdp->ach_IOMMU_pci_seg = ivhdp->ivhd_pci_seg;
50894f1124eSVikram Hegde 
50994f1124eSVikram Hegde 	/* IVHD IOMMU info fields */
51094f1124eSVikram Hegde 	uint16_info = ivhdp->ivhd_iommu_info;
51194f1124eSVikram Hegde 
51294f1124eSVikram Hegde #ifdef BROKEN_ASSERT
51394f1124eSVikram Hegde 	ASSERT(AMD_IOMMU_REG_GET16(&uint16_info,
51494f1124eSVikram Hegde 	    AMD_IOMMU_ACPI_IOMMU_INFO_RSV1) == 0);
51594f1124eSVikram Hegde #endif
51694f1124eSVikram Hegde 
51794f1124eSVikram Hegde 	acpi_ivhdp->ach_IOMMU_UnitID = AMD_IOMMU_REG_GET16(&uint16_info,
51894f1124eSVikram Hegde 	    AMD_IOMMU_ACPI_IOMMU_INFO_UNITID);
51994f1124eSVikram Hegde 	ASSERT(AMD_IOMMU_REG_GET16(&uint16_info,
52094f1124eSVikram Hegde 	    AMD_IOMMU_ACPI_IOMMU_INFO_RSV2) == 0);
52194f1124eSVikram Hegde 	acpi_ivhdp->ach_IOMMU_MSInum = AMD_IOMMU_REG_GET16(&uint16_info,
52294f1124eSVikram Hegde 	    AMD_IOMMU_ACPI_IOMMU_INFO_MSINUM);
52394f1124eSVikram Hegde 
52494f1124eSVikram Hegde 	/* Initialize  deviceids to -1 */
52594f1124eSVikram Hegde 	acpi_ivhdp->ach_deviceid_start = -1;
52694f1124eSVikram Hegde 	acpi_ivhdp->ach_deviceid_end = -1;
52794f1124eSVikram Hegde 	acpi_ivhdp->ach_src_deviceid = -1;
52894f1124eSVikram Hegde 
52994f1124eSVikram Hegde 	/* All range type entries are put on hash entry 0 */
53094f1124eSVikram Hegde 	switch (deventry->idev_type) {
53194f1124eSVikram Hegde 	case DEVENTRY_ALL:
53294f1124eSVikram Hegde 		acpi_ivhdp->ach_deviceid_start = 0;
53394f1124eSVikram Hegde 		acpi_ivhdp->ach_deviceid_end = (uint16_t)-1;
53494f1124eSVikram Hegde 		acpi_ivhdp->ach_dev_type = DEVENTRY_ALL;
53594f1124eSVikram Hegde 		idx = AMD_IOMMU_ACPI_INFO_HASH_SZ;
53694f1124eSVikram Hegde 		break;
53794f1124eSVikram Hegde 	case DEVENTRY_SELECT:
53894f1124eSVikram Hegde 		acpi_ivhdp->ach_deviceid_start = deventry->idev_deviceid;
53994f1124eSVikram Hegde 		acpi_ivhdp->ach_deviceid_end = deventry->idev_deviceid;
54094f1124eSVikram Hegde 		acpi_ivhdp->ach_dev_type = DEVENTRY_SELECT;
54194f1124eSVikram Hegde 		idx = deviceid_hashfn(deventry->idev_deviceid);
54294f1124eSVikram Hegde 		break;
54394f1124eSVikram Hegde 	case DEVENTRY_RANGE:
54494f1124eSVikram Hegde 		acpi_ivhdp->ach_deviceid_start = deventry->idev_deviceid;
54594f1124eSVikram Hegde 		acpi_ivhdp->ach_deviceid_end = -1;
54694f1124eSVikram Hegde 		acpi_ivhdp->ach_dev_type = DEVENTRY_RANGE;
54794f1124eSVikram Hegde 		idx = AMD_IOMMU_ACPI_INFO_HASH_SZ;
54894f1124eSVikram Hegde 		last = acpi_ivhdp;
54994f1124eSVikram Hegde 		break;
55094f1124eSVikram Hegde 	case DEVENTRY_RANGE_END:
551*584b574aSToomas Soome 		idx = 0;
55294f1124eSVikram Hegde 		cmn_err(CE_PANIC, "%s: Unexpected Range End Deventry",
55394f1124eSVikram Hegde 		    amd_iommu_modname);
55494f1124eSVikram Hegde 		/*NOTREACHED*/
5557d86488aSToomas Soome 		break;
55694f1124eSVikram Hegde 	case DEVENTRY_ALIAS_SELECT:
55794f1124eSVikram Hegde 		acpi_ivhdp->ach_deviceid_start = deventry->idev_deviceid;
55894f1124eSVikram Hegde 		acpi_ivhdp->ach_deviceid_end = deventry->idev_deviceid;
55994f1124eSVikram Hegde 		acpi_ivhdp->ach_src_deviceid = deventry->idev_src_deviceid;
56094f1124eSVikram Hegde 		acpi_ivhdp->ach_dev_type = DEVENTRY_ALIAS_SELECT;
56194f1124eSVikram Hegde 		idx = deviceid_hashfn(deventry->idev_deviceid);
56294f1124eSVikram Hegde 		break;
56394f1124eSVikram Hegde 	case DEVENTRY_ALIAS_RANGE:
56494f1124eSVikram Hegde 		acpi_ivhdp->ach_deviceid_start = deventry->idev_deviceid;
56594f1124eSVikram Hegde 		acpi_ivhdp->ach_deviceid_end = -1;
56694f1124eSVikram Hegde 		acpi_ivhdp->ach_src_deviceid = deventry->idev_src_deviceid;
56794f1124eSVikram Hegde 		acpi_ivhdp->ach_dev_type = DEVENTRY_ALIAS_RANGE;
56894f1124eSVikram Hegde 		idx = AMD_IOMMU_ACPI_INFO_HASH_SZ;
56994f1124eSVikram Hegde 		last = acpi_ivhdp;
57094f1124eSVikram Hegde 		break;
57194f1124eSVikram Hegde 	case DEVENTRY_EXTENDED_SELECT:
57294f1124eSVikram Hegde 		acpi_ivhdp->ach_deviceid_start = deventry->idev_deviceid;
57394f1124eSVikram Hegde 		acpi_ivhdp->ach_deviceid_end = deventry->idev_deviceid;
57494f1124eSVikram Hegde 		acpi_ivhdp->ach_dev_type = DEVENTRY_EXTENDED_SELECT;
57594f1124eSVikram Hegde 		idx = deviceid_hashfn(deventry->idev_deviceid);
57694f1124eSVikram Hegde 		break;
57794f1124eSVikram Hegde 	case DEVENTRY_EXTENDED_RANGE:
57894f1124eSVikram Hegde 		acpi_ivhdp->ach_deviceid_start = deventry->idev_deviceid;
57994f1124eSVikram Hegde 		acpi_ivhdp->ach_deviceid_end = -1;
58094f1124eSVikram Hegde 		acpi_ivhdp->ach_dev_type = DEVENTRY_EXTENDED_RANGE;
58194f1124eSVikram Hegde 		idx = AMD_IOMMU_ACPI_INFO_HASH_SZ;
58294f1124eSVikram Hegde 		last = acpi_ivhdp;
58394f1124eSVikram Hegde 		break;
58494f1124eSVikram Hegde 	case DEVENTRY_SPECIAL_DEVICE:
58594f1124eSVikram Hegde 		acpi_ivhdp->ach_deviceid_start = -1;
58694f1124eSVikram Hegde 		acpi_ivhdp->ach_deviceid_end = -1;
58794f1124eSVikram Hegde 		acpi_ivhdp->ach_src_deviceid = deventry->idev_src_deviceid;
58894f1124eSVikram Hegde 		acpi_ivhdp->ach_special_handle = deventry->idev_handle;
58994f1124eSVikram Hegde 		acpi_ivhdp->ach_special_variety = deventry->idev_variety;
59094f1124eSVikram Hegde 		idx = AMD_IOMMU_ACPI_INFO_HASH_SZ;
5917d86488aSToomas Soome 		break;
59294f1124eSVikram Hegde 	default:
593*584b574aSToomas Soome 		idx = 0;
59494f1124eSVikram Hegde 		cmn_err(CE_PANIC, "%s: Unsupported deventry type",
59594f1124eSVikram Hegde 		    amd_iommu_modname);
596*584b574aSToomas Soome 		/*NOTREACHED*/
59794f1124eSVikram Hegde 	}
5987125fcbdSVikram Hegde 
59994f1124eSVikram Hegde 	acpi_ivhdp->ach_Lint1Pass = deventry->idev_Lint1Pass;
60094f1124eSVikram Hegde 	acpi_ivhdp->ach_Lint0Pass = deventry->idev_Lint0Pass;
60194f1124eSVikram Hegde 	acpi_ivhdp->ach_SysMgt = deventry->idev_SysMgt;
60294f1124eSVikram Hegde 	acpi_ivhdp->ach_NMIPass = deventry->idev_NMIPass;
60394f1124eSVikram Hegde 	acpi_ivhdp->ach_ExtIntPass = deventry->idev_ExtIntPass;
60494f1124eSVikram Hegde 	acpi_ivhdp->ach_INITPass = deventry->idev_INITPass;
6057125fcbdSVikram Hegde 
60694f1124eSVikram Hegde 
60794f1124eSVikram Hegde 	/* extended data */
60894f1124eSVikram Hegde 	if (acpi_ivhdp->ach_dev_type == DEVENTRY_EXTENDED_SELECT ||
60994f1124eSVikram Hegde 	    acpi_ivhdp->ach_dev_type == DEVENTRY_EXTENDED_RANGE) {
61094f1124eSVikram Hegde 		acpi_ivhdp->ach_AtsDisabled = deventry->idev_AtsDisabled;
6117125fcbdSVikram Hegde 	}
61294f1124eSVikram Hegde 
61394f1124eSVikram Hegde 	/*
61494f1124eSVikram Hegde 	 * Now add it to the hash
61594f1124eSVikram Hegde 	 */
61694f1124eSVikram Hegde 	ASSERT(hash[idx] != acpi_ivhdp);
61794f1124eSVikram Hegde 	acpi_ivhdp->ach_next = hash[idx];
61894f1124eSVikram Hegde 	hash[idx] = acpi_ivhdp;
6197125fcbdSVikram Hegde }
6207125fcbdSVikram Hegde 
621ba758cf1SJerry Gilliam /*
622ba758cf1SJerry Gilliam  * A device entry may be declared implicitly as a source device ID
623ba758cf1SJerry Gilliam  * in an alias entry. This routine adds it to the hash
624ba758cf1SJerry Gilliam  */
625ba758cf1SJerry Gilliam static void
add_implicit_deventry(ivhd_container_t * ivhdcp,amd_iommu_acpi_ivhd_t ** hash)626ba758cf1SJerry Gilliam add_implicit_deventry(ivhd_container_t *ivhdcp, amd_iommu_acpi_ivhd_t **hash)
627ba758cf1SJerry Gilliam {
628ba758cf1SJerry Gilliam 	ivhd_deventry_t *d;
629ba758cf1SJerry Gilliam 	int deviceid;
630ba758cf1SJerry Gilliam 
631ba758cf1SJerry Gilliam 	for (d = ivhdcp->ivhdc_first_deventry; d; d = d->idev_next) {
632ba758cf1SJerry Gilliam 
633ba758cf1SJerry Gilliam 		if ((d->idev_type != DEVENTRY_ALIAS_SELECT) &&
634ba758cf1SJerry Gilliam 		    (d->idev_type != DEVENTRY_ALIAS_RANGE))
635ba758cf1SJerry Gilliam 			continue;
636ba758cf1SJerry Gilliam 
637ba758cf1SJerry Gilliam 		deviceid = d->idev_src_deviceid;
638ba758cf1SJerry Gilliam 
639ba758cf1SJerry Gilliam 		if (amd_iommu_lookup_ivhd(deviceid) == NULL) {
640ba758cf1SJerry Gilliam 			ivhd_deventry_t deventry;
641ba758cf1SJerry Gilliam 
642ba758cf1SJerry Gilliam 			/* Fake a SELECT entry */
643ba758cf1SJerry Gilliam 			deventry.idev_type = DEVENTRY_SELECT;
644ba758cf1SJerry Gilliam 			deventry.idev_len = 4;
645ba758cf1SJerry Gilliam 			deventry.idev_deviceid = deviceid;
646ba758cf1SJerry Gilliam 			deventry.idev_src_deviceid = -1;
647ba758cf1SJerry Gilliam 
648ba758cf1SJerry Gilliam 			deventry.idev_Lint1Pass = d->idev_Lint1Pass;
649ba758cf1SJerry Gilliam 			deventry.idev_Lint0Pass = d->idev_Lint0Pass;
650ba758cf1SJerry Gilliam 			deventry.idev_SysMgt = d->idev_SysMgt;
651ba758cf1SJerry Gilliam 			deventry.idev_NMIPass = d->idev_NMIPass;
652ba758cf1SJerry Gilliam 			deventry.idev_ExtIntPass = d->idev_ExtIntPass;
653ba758cf1SJerry Gilliam 			deventry.idev_INITPass = d->idev_INITPass;
654ba758cf1SJerry Gilliam 
655ba758cf1SJerry Gilliam 			add_deventry_info(ivhdcp->ivhdc_ivhd, &deventry, hash);
656ba758cf1SJerry Gilliam 
657ba758cf1SJerry Gilliam 			if (amd_iommu_debug & AMD_IOMMU_DEBUG_ACPI) {
658ba758cf1SJerry Gilliam 				cmn_err(CE_NOTE, "Added implicit IVHD entry "
659ba758cf1SJerry Gilliam 				    "for: deviceid = %u", deviceid);
660ba758cf1SJerry Gilliam 			}
661ba758cf1SJerry Gilliam 		}
662ba758cf1SJerry Gilliam 	}
663ba758cf1SJerry Gilliam }
664ba758cf1SJerry Gilliam 
6657125fcbdSVikram Hegde static void
add_ivhdc_info(ivhd_container_t * ivhdcp,amd_iommu_acpi_ivhd_t ** hash)66694f1124eSVikram Hegde add_ivhdc_info(ivhd_container_t *ivhdcp, amd_iommu_acpi_ivhd_t **hash)
6677125fcbdSVikram Hegde {
66894f1124eSVikram Hegde 	ivhd_deventry_t *deventry;
66994f1124eSVikram Hegde 	ivhd_t *ivhdp = ivhdcp->ivhdc_ivhd;
6707125fcbdSVikram Hegde 
67194f1124eSVikram Hegde 	for (deventry = ivhdcp->ivhdc_first_deventry; deventry;
67294f1124eSVikram Hegde 	    deventry = deventry->idev_next) {
67394f1124eSVikram Hegde 		add_deventry_info(ivhdp, deventry, hash);
67494f1124eSVikram Hegde 	}
675ba758cf1SJerry Gilliam 
676ba758cf1SJerry Gilliam 	add_implicit_deventry(ivhdcp, hash);
677ba758cf1SJerry Gilliam 
6787125fcbdSVikram Hegde }
6797125fcbdSVikram Hegde 
68094f1124eSVikram Hegde static void
add_ivhd_info(amd_iommu_acpi_t * acpi,amd_iommu_acpi_ivhd_t ** hash)68194f1124eSVikram Hegde add_ivhd_info(amd_iommu_acpi_t *acpi, amd_iommu_acpi_ivhd_t **hash)
6827125fcbdSVikram Hegde {
68394f1124eSVikram Hegde 	ivhd_container_t *ivhdcp;
6847125fcbdSVikram Hegde 
68594f1124eSVikram Hegde 	for (ivhdcp = acpi->acp_first_ivhdc; ivhdcp;
68694f1124eSVikram Hegde 	    ivhdcp = ivhdcp->ivhdc_next) {
68794f1124eSVikram Hegde 		add_ivhdc_info(ivhdcp, hash);
68894f1124eSVikram Hegde 	}
68994f1124eSVikram Hegde }
69094f1124eSVikram Hegde 
69194f1124eSVikram Hegde static void
set_ivmd_info(ivmd_t * ivmdp,amd_iommu_acpi_ivmd_t ** hash)69294f1124eSVikram Hegde set_ivmd_info(ivmd_t *ivmdp, amd_iommu_acpi_ivmd_t **hash)
69394f1124eSVikram Hegde {
69494f1124eSVikram Hegde 	amd_iommu_acpi_ivmd_t *acpi_ivmdp;
69594f1124eSVikram Hegde 	uint8_t uint8_flags;
69694f1124eSVikram Hegde 	uint16_t idx;
6977125fcbdSVikram Hegde 
69894f1124eSVikram Hegde 	uint8_flags = ivmdp->ivmd_flags;
6997125fcbdSVikram Hegde 
70094f1124eSVikram Hegde 	acpi_ivmdp = kmem_zalloc(sizeof (*acpi_ivmdp), KM_SLEEP);
7017125fcbdSVikram Hegde 
70294f1124eSVikram Hegde 	switch (ivmdp->ivmd_type) {
70394f1124eSVikram Hegde 	case 0x20:
70494f1124eSVikram Hegde 		acpi_ivmdp->acm_deviceid_start = 0;
70594f1124eSVikram Hegde 		acpi_ivmdp->acm_deviceid_end = (uint16_t)-1;
70694f1124eSVikram Hegde 		acpi_ivmdp->acm_dev_type = IVMD_DEVICEID_ALL;
70794f1124eSVikram Hegde 		idx = AMD_IOMMU_ACPI_INFO_HASH_SZ;
70894f1124eSVikram Hegde 		break;
70994f1124eSVikram Hegde 	case 0x21:
71094f1124eSVikram Hegde 		acpi_ivmdp->acm_deviceid_start = ivmdp->ivmd_deviceid;
71194f1124eSVikram Hegde 		acpi_ivmdp->acm_deviceid_end = ivmdp->ivmd_deviceid;
71294f1124eSVikram Hegde 		acpi_ivmdp->acm_dev_type = IVMD_DEVICEID_SELECT;
71394f1124eSVikram Hegde 		idx = deviceid_hashfn(ivmdp->ivmd_deviceid);
71494f1124eSVikram Hegde 		break;
71594f1124eSVikram Hegde 	case 0x22:
71694f1124eSVikram Hegde 		acpi_ivmdp->acm_deviceid_start = ivmdp->ivmd_deviceid;
71794f1124eSVikram Hegde 		acpi_ivmdp->acm_deviceid_end = ivmdp->ivmd_auxdata;
71894f1124eSVikram Hegde 		acpi_ivmdp->acm_dev_type = IVMD_DEVICEID_RANGE;
71994f1124eSVikram Hegde 		idx = AMD_IOMMU_ACPI_INFO_HASH_SZ;
72094f1124eSVikram Hegde 		break;
72194f1124eSVikram Hegde 	default:
722*584b574aSToomas Soome 		idx = 0;
72394f1124eSVikram Hegde 		cmn_err(CE_PANIC, "Unknown AMD IOMMU ACPI IVMD deviceid type: "
72494f1124eSVikram Hegde 		    "%x", ivmdp->ivmd_type);
72594f1124eSVikram Hegde 		/*NOTREACHED*/
7267125fcbdSVikram Hegde 	}
7277125fcbdSVikram Hegde 
72894f1124eSVikram Hegde 	ASSERT(AMD_IOMMU_REG_GET8(&uint8_flags,
72994f1124eSVikram Hegde 	    AMD_IOMMU_ACPI_IVMD_RSV) == 0);
7307125fcbdSVikram Hegde 
73194f1124eSVikram Hegde 	acpi_ivmdp->acm_ExclRange = AMD_IOMMU_REG_GET8(&uint8_flags,
73294f1124eSVikram Hegde 	    AMD_IOMMU_ACPI_IVMD_EXCL_RANGE);
73394f1124eSVikram Hegde 	acpi_ivmdp->acm_IW = AMD_IOMMU_REG_GET8(&uint8_flags,
73494f1124eSVikram Hegde 	    AMD_IOMMU_ACPI_IVMD_IW);
73594f1124eSVikram Hegde 	acpi_ivmdp->acm_IR = AMD_IOMMU_REG_GET8(&uint8_flags,
73694f1124eSVikram Hegde 	    AMD_IOMMU_ACPI_IVMD_IR);
73794f1124eSVikram Hegde 	acpi_ivmdp->acm_Unity = AMD_IOMMU_REG_GET8(&uint8_flags,
73894f1124eSVikram Hegde 	    AMD_IOMMU_ACPI_IVMD_UNITY);
73994f1124eSVikram Hegde 
74094f1124eSVikram Hegde 	acpi_ivmdp->acm_ivmd_phys_start = ivmdp->ivmd_phys_start;
74194f1124eSVikram Hegde 	acpi_ivmdp->acm_ivmd_phys_len = ivmdp->ivmd_phys_len;
7427125fcbdSVikram Hegde 
74394f1124eSVikram Hegde 	acpi_ivmdp->acm_next = hash[idx];
74494f1124eSVikram Hegde 	hash[idx] = acpi_ivmdp;
7457125fcbdSVikram Hegde }
7467125fcbdSVikram Hegde 
74794f1124eSVikram Hegde static void
add_ivmdc_info(ivmd_container_t * ivmdcp,amd_iommu_acpi_ivmd_t ** hash)74894f1124eSVikram Hegde add_ivmdc_info(ivmd_container_t *ivmdcp, amd_iommu_acpi_ivmd_t **hash)
7497125fcbdSVikram Hegde {
75094f1124eSVikram Hegde 	set_ivmd_info(ivmdcp->ivmdc_ivmd, hash);
75194f1124eSVikram Hegde }
7527125fcbdSVikram Hegde 
75394f1124eSVikram Hegde static void
add_ivmd_info(amd_iommu_acpi_t * acpi,amd_iommu_acpi_ivmd_t ** hash)75494f1124eSVikram Hegde add_ivmd_info(amd_iommu_acpi_t *acpi, amd_iommu_acpi_ivmd_t **hash)
75594f1124eSVikram Hegde {
75694f1124eSVikram Hegde 	ivmd_container_t *ivmdcp;
75794f1124eSVikram Hegde 
75894f1124eSVikram Hegde 	for (ivmdcp = acpi->acp_first_ivmdc; ivmdcp;
75994f1124eSVikram Hegde 	    ivmdcp = ivmdcp->ivmdc_next) {
76094f1124eSVikram Hegde 		add_ivmdc_info(ivmdcp, hash);
7617125fcbdSVikram Hegde 	}
7627125fcbdSVikram Hegde }
7637125fcbdSVikram Hegde 
7647125fcbdSVikram Hegde static void
add_global_info(amd_iommu_acpi_t * acpi,amd_iommu_acpi_global_t * global)76594f1124eSVikram Hegde add_global_info(amd_iommu_acpi_t *acpi, amd_iommu_acpi_global_t *global)
7667125fcbdSVikram Hegde {
76794f1124eSVikram Hegde 	uint32_t ivrs_ivinfo = acpi->acp_ivrs->ivrs_ivinfo;
76894f1124eSVikram Hegde 
76994f1124eSVikram Hegde 	global->acg_HtAtsResv =
77094f1124eSVikram Hegde 	    AMD_IOMMU_REG_GET32(&ivrs_ivinfo, AMD_IOMMU_ACPI_HT_ATSRSV);
77194f1124eSVikram Hegde 	global->acg_VAsize =
77294f1124eSVikram Hegde 	    AMD_IOMMU_REG_GET32(&ivrs_ivinfo, AMD_IOMMU_ACPI_VA_SIZE);
77394f1124eSVikram Hegde 	global->acg_PAsize =
77494f1124eSVikram Hegde 	    AMD_IOMMU_REG_GET32(&ivrs_ivinfo, AMD_IOMMU_ACPI_PA_SIZE);
77594f1124eSVikram Hegde }
77694f1124eSVikram Hegde 
77794f1124eSVikram Hegde static int
create_acpi_hash(amd_iommu_acpi_t * acpi)77894f1124eSVikram Hegde create_acpi_hash(amd_iommu_acpi_t *acpi)
77994f1124eSVikram Hegde {
78094f1124eSVikram Hegde 	/* Last hash entry is for deviceid ranges including "all" */
78194f1124eSVikram Hegde 
78294f1124eSVikram Hegde 	amd_iommu_acpi_global = kmem_zalloc(sizeof (amd_iommu_acpi_global_t),
78394f1124eSVikram Hegde 	    KM_SLEEP);
78494f1124eSVikram Hegde 
78594f1124eSVikram Hegde 	amd_iommu_acpi_ivhd_hash = kmem_zalloc(sizeof (amd_iommu_acpi_ivhd_t *)
78694f1124eSVikram Hegde 	    * (AMD_IOMMU_ACPI_INFO_HASH_SZ + 1), KM_SLEEP);
7877125fcbdSVikram Hegde 
78894f1124eSVikram Hegde 	amd_iommu_acpi_ivmd_hash = kmem_zalloc(sizeof (amd_iommu_acpi_ivmd_t *)
78994f1124eSVikram Hegde 	    * (AMD_IOMMU_ACPI_INFO_HASH_SZ + 1), KM_SLEEP);
79094f1124eSVikram Hegde 
79194f1124eSVikram Hegde 	add_global_info(acpi, amd_iommu_acpi_global);
79294f1124eSVikram Hegde 
79394f1124eSVikram Hegde 	add_ivhd_info(acpi, amd_iommu_acpi_ivhd_hash);
79494f1124eSVikram Hegde 
79594f1124eSVikram Hegde 	add_ivmd_info(acpi, amd_iommu_acpi_ivmd_hash);
79694f1124eSVikram Hegde 
79794f1124eSVikram Hegde 	return (DDI_SUCCESS);
79894f1124eSVikram Hegde }
79994f1124eSVikram Hegde 
800ba758cf1SJerry Gilliam static void
set_deventry(amd_iommu_t * iommu,int entry,amd_iommu_acpi_ivhd_t * hinfop)801ba758cf1SJerry Gilliam set_deventry(amd_iommu_t *iommu, int entry, amd_iommu_acpi_ivhd_t *hinfop)
802ba758cf1SJerry Gilliam {
803ba758cf1SJerry Gilliam 	uint64_t *dentry;
804ba758cf1SJerry Gilliam 
805ba758cf1SJerry Gilliam 	dentry = (uint64_t *)(intptr_t)
806ba758cf1SJerry Gilliam 	    &iommu->aiomt_devtbl[entry * AMD_IOMMU_DEVTBL_ENTRY_SZ];
807ba758cf1SJerry Gilliam 
808ba758cf1SJerry Gilliam 	AMD_IOMMU_REG_SET64(&(dentry[1]), AMD_IOMMU_DEVTBL_SYSMGT,
809ba758cf1SJerry Gilliam 	    hinfop->ach_SysMgt);
810ba758cf1SJerry Gilliam }
811ba758cf1SJerry Gilliam 
812ba758cf1SJerry Gilliam /* Initialize device table according to IVHD */
813ba758cf1SJerry Gilliam int
amd_iommu_acpi_init_devtbl(amd_iommu_t * iommu)814ba758cf1SJerry Gilliam amd_iommu_acpi_init_devtbl(amd_iommu_t *iommu)
815ba758cf1SJerry Gilliam {
816ba758cf1SJerry Gilliam 	int i, j;
817ba758cf1SJerry Gilliam 	amd_iommu_acpi_ivhd_t *hinfop;
818ba758cf1SJerry Gilliam 
819ba758cf1SJerry Gilliam 	for (i = 0; i <= AMD_IOMMU_ACPI_INFO_HASH_SZ; i++) {
820ba758cf1SJerry Gilliam 		for (hinfop = amd_iommu_acpi_ivhd_hash[i];
821ba758cf1SJerry Gilliam 		    hinfop; hinfop = hinfop->ach_next) {
822ba758cf1SJerry Gilliam 
823ba758cf1SJerry Gilliam 			if (hinfop->ach_IOMMU_deviceid != iommu->aiomt_bdf)
824ba758cf1SJerry Gilliam 				continue;
825ba758cf1SJerry Gilliam 
826ba758cf1SJerry Gilliam 			switch (hinfop->ach_dev_type) {
827ba758cf1SJerry Gilliam 			case DEVENTRY_ALL:
828ba758cf1SJerry Gilliam 				for (j = 0; j < AMD_IOMMU_MAX_DEVICEID; j++)
829ba758cf1SJerry Gilliam 					set_deventry(iommu, j, hinfop);
830ba758cf1SJerry Gilliam 				break;
831ba758cf1SJerry Gilliam 			case DEVENTRY_SELECT:
832ba758cf1SJerry Gilliam 			case DEVENTRY_EXTENDED_SELECT:
833ba758cf1SJerry Gilliam 				set_deventry(iommu,
834ba758cf1SJerry Gilliam 				    hinfop->ach_deviceid_start,
835ba758cf1SJerry Gilliam 				    hinfop);
836ba758cf1SJerry Gilliam 				break;
837ba758cf1SJerry Gilliam 			case DEVENTRY_RANGE:
838ba758cf1SJerry Gilliam 			case DEVENTRY_EXTENDED_RANGE:
839ba758cf1SJerry Gilliam 				for (j = hinfop->ach_deviceid_start;
840ba758cf1SJerry Gilliam 				    j <= hinfop->ach_deviceid_end;
841ba758cf1SJerry Gilliam 				    j++)
842ba758cf1SJerry Gilliam 					set_deventry(iommu, j, hinfop);
843ba758cf1SJerry Gilliam 				break;
844ba758cf1SJerry Gilliam 			case DEVENTRY_ALIAS_SELECT:
845ba758cf1SJerry Gilliam 			case DEVENTRY_ALIAS_RANGE:
846ba758cf1SJerry Gilliam 			case DEVENTRY_SPECIAL_DEVICE:
847ba758cf1SJerry Gilliam 				set_deventry(iommu,
848ba758cf1SJerry Gilliam 				    hinfop->ach_src_deviceid,
849ba758cf1SJerry Gilliam 				    hinfop);
850ba758cf1SJerry Gilliam 				break;
851ba758cf1SJerry Gilliam 			default:
852ba758cf1SJerry Gilliam 				cmn_err(CE_WARN,
853ba758cf1SJerry Gilliam 				    "%s: Unknown deventry type",
854ba758cf1SJerry Gilliam 				    amd_iommu_modname);
855ba758cf1SJerry Gilliam 				return (DDI_FAILURE);
856ba758cf1SJerry Gilliam 			}
857ba758cf1SJerry Gilliam 		}
858ba758cf1SJerry Gilliam 	}
859ba758cf1SJerry Gilliam 
860ba758cf1SJerry Gilliam 	return (DDI_SUCCESS);
861ba758cf1SJerry Gilliam }
862ba758cf1SJerry Gilliam 
86394f1124eSVikram Hegde amd_iommu_acpi_global_t *
amd_iommu_lookup_acpi_global(void)86494f1124eSVikram Hegde amd_iommu_lookup_acpi_global(void)
86594f1124eSVikram Hegde {
86694f1124eSVikram Hegde 	ASSERT(amd_iommu_acpi_global);
86794f1124eSVikram Hegde 
86894f1124eSVikram Hegde 	return (amd_iommu_acpi_global);
86994f1124eSVikram Hegde }
87094f1124eSVikram Hegde 
87194f1124eSVikram Hegde amd_iommu_acpi_ivhd_t *
amd_iommu_lookup_all_ivhd(void)87294f1124eSVikram Hegde amd_iommu_lookup_all_ivhd(void)
87394f1124eSVikram Hegde {
87494f1124eSVikram Hegde 	amd_iommu_acpi_ivhd_t *hinfop;
87594f1124eSVikram Hegde 
87694f1124eSVikram Hegde 	hinfop = amd_iommu_acpi_ivhd_hash[AMD_IOMMU_ACPI_INFO_HASH_SZ];
87794f1124eSVikram Hegde 	for (; hinfop; hinfop = hinfop->ach_next) {
87894f1124eSVikram Hegde 		if (hinfop->ach_deviceid_start == 0 &&
87994f1124eSVikram Hegde 		    hinfop->ach_deviceid_end == (uint16_t)-1) {
88094f1124eSVikram Hegde 			break;
8817125fcbdSVikram Hegde 		}
8827125fcbdSVikram Hegde 	}
88394f1124eSVikram Hegde 
88494f1124eSVikram Hegde 	return (hinfop);
8857125fcbdSVikram Hegde }
8867125fcbdSVikram Hegde 
88794f1124eSVikram Hegde amd_iommu_acpi_ivmd_t *
amd_iommu_lookup_all_ivmd(void)88894f1124eSVikram Hegde amd_iommu_lookup_all_ivmd(void)
8897125fcbdSVikram Hegde {
89094f1124eSVikram Hegde 	amd_iommu_acpi_ivmd_t *minfop;
8917125fcbdSVikram Hegde 
89294f1124eSVikram Hegde 	minfop = amd_iommu_acpi_ivmd_hash[AMD_IOMMU_ACPI_INFO_HASH_SZ];
89394f1124eSVikram Hegde 	for (; minfop; minfop = minfop->acm_next) {
89494f1124eSVikram Hegde 		if (minfop->acm_deviceid_start == 0 &&
89594f1124eSVikram Hegde 		    minfop->acm_deviceid_end == (uint16_t)-1) {
89694f1124eSVikram Hegde 			break;
89794f1124eSVikram Hegde 		}
8987125fcbdSVikram Hegde 	}
89994f1124eSVikram Hegde 
90094f1124eSVikram Hegde 	return (minfop);
9017125fcbdSVikram Hegde }
9027125fcbdSVikram Hegde 
90394f1124eSVikram Hegde amd_iommu_acpi_ivhd_t *
amd_iommu_lookup_any_ivhd(amd_iommu_t * iommu)904ba758cf1SJerry Gilliam amd_iommu_lookup_any_ivhd(amd_iommu_t *iommu)
9057125fcbdSVikram Hegde {
90694f1124eSVikram Hegde 	int i;
90794f1124eSVikram Hegde 	amd_iommu_acpi_ivhd_t *hinfop;
90894f1124eSVikram Hegde 
90994f1124eSVikram Hegde 	for (i = AMD_IOMMU_ACPI_INFO_HASH_SZ; i >= 0; i--) {
910ba758cf1SJerry Gilliam 		hinfop = amd_iommu_acpi_ivhd_hash[i];
911ba758cf1SJerry Gilliam 		if ((hinfop != NULL) &&
912ba758cf1SJerry Gilliam 		    hinfop->ach_IOMMU_deviceid == iommu->aiomt_bdf)
91394f1124eSVikram Hegde 			break;
9147125fcbdSVikram Hegde 	}
9157125fcbdSVikram Hegde 
91694f1124eSVikram Hegde 	return (hinfop);
9177125fcbdSVikram Hegde }
9187125fcbdSVikram Hegde 
91994f1124eSVikram Hegde amd_iommu_acpi_ivmd_t *
amd_iommu_lookup_any_ivmd(void)92094f1124eSVikram Hegde amd_iommu_lookup_any_ivmd(void)
9217125fcbdSVikram Hegde {
92294f1124eSVikram Hegde 	int i;
92394f1124eSVikram Hegde 	amd_iommu_acpi_ivmd_t *minfop;
92494f1124eSVikram Hegde 
92594f1124eSVikram Hegde 	for (i = AMD_IOMMU_ACPI_INFO_HASH_SZ; i >= 0; i--) {
926ba758cf1SJerry Gilliam 		if ((minfop = amd_iommu_acpi_ivmd_hash[i]) != NULL)
92794f1124eSVikram Hegde 			break;
92894f1124eSVikram Hegde 	}
92994f1124eSVikram Hegde 
93094f1124eSVikram Hegde 	return (minfop);
93194f1124eSVikram Hegde }
93294f1124eSVikram Hegde 
93394f1124eSVikram Hegde static void
dump_acpi_aliases(void)93494f1124eSVikram Hegde dump_acpi_aliases(void)
93594f1124eSVikram Hegde {
93694f1124eSVikram Hegde 	amd_iommu_acpi_ivhd_t *hinfop;
9377125fcbdSVikram Hegde 	uint16_t idx;
9387125fcbdSVikram Hegde 
93994f1124eSVikram Hegde 	for (idx = 0; idx <= AMD_IOMMU_ACPI_INFO_HASH_SZ; idx++) {
94094f1124eSVikram Hegde 		hinfop = amd_iommu_acpi_ivhd_hash[idx];
94194f1124eSVikram Hegde 		for (; hinfop; hinfop = hinfop->ach_next) {
94294f1124eSVikram Hegde 			cmn_err(CE_NOTE, "start=%d, end=%d, src_bdf=%d",
94394f1124eSVikram Hegde 			    hinfop->ach_deviceid_start,
94494f1124eSVikram Hegde 			    hinfop->ach_deviceid_end,
94594f1124eSVikram Hegde 			    hinfop->ach_src_deviceid);
94694f1124eSVikram Hegde 		}
94794f1124eSVikram Hegde 	}
94894f1124eSVikram Hegde }
94994f1124eSVikram Hegde 
95094f1124eSVikram Hegde amd_iommu_acpi_ivhd_t *
amd_iommu_lookup_ivhd(int32_t deviceid)95194f1124eSVikram Hegde amd_iommu_lookup_ivhd(int32_t deviceid)
95294f1124eSVikram Hegde {
95394f1124eSVikram Hegde 	amd_iommu_acpi_ivhd_t *hinfop;
95494f1124eSVikram Hegde 	uint16_t idx;
9557125fcbdSVikram Hegde 
956ba758cf1SJerry Gilliam 	if (amd_iommu_debug & AMD_IOMMU_DEBUG_ACPI) {
95794f1124eSVikram Hegde 		cmn_err(CE_NOTE, "Attempting to get ACPI IVHD info "
95894f1124eSVikram Hegde 		    "for deviceid: %d", deviceid);
9597125fcbdSVikram Hegde 	}
9607125fcbdSVikram Hegde 
96194f1124eSVikram Hegde 	ASSERT(amd_iommu_acpi_ivhd_hash);
96294f1124eSVikram Hegde 
96394f1124eSVikram Hegde 	/* check if special device */
96494f1124eSVikram Hegde 	if (deviceid == -1) {
96594f1124eSVikram Hegde 		hinfop = amd_iommu_acpi_ivhd_hash[AMD_IOMMU_ACPI_INFO_HASH_SZ];
96694f1124eSVikram Hegde 		for (; hinfop; hinfop = hinfop->ach_next) {
96794f1124eSVikram Hegde 			if (hinfop->ach_deviceid_start  == -1 &&
96894f1124eSVikram Hegde 			    hinfop->ach_deviceid_end == -1) {
96994f1124eSVikram Hegde 				break;
97094f1124eSVikram Hegde 			}
97194f1124eSVikram Hegde 		}
97294f1124eSVikram Hegde 		return (hinfop);
9737125fcbdSVikram Hegde 	}
9747125fcbdSVikram Hegde 
97594f1124eSVikram Hegde 	/* First search for an exact match */
97694f1124eSVikram Hegde 
97794f1124eSVikram Hegde 	idx = deviceid_hashfn(deviceid);
9787125fcbdSVikram Hegde 
97994f1124eSVikram Hegde 
98094f1124eSVikram Hegde range:
98194f1124eSVikram Hegde 	hinfop = amd_iommu_acpi_ivhd_hash[idx];
98294f1124eSVikram Hegde 
98394f1124eSVikram Hegde 	for (; hinfop; hinfop = hinfop->ach_next) {
98494f1124eSVikram Hegde 		if (deviceid < hinfop->ach_deviceid_start ||
98594f1124eSVikram Hegde 		    deviceid > hinfop->ach_deviceid_end)
98694f1124eSVikram Hegde 			continue;
9877125fcbdSVikram Hegde 
988ba758cf1SJerry Gilliam 		if (amd_iommu_debug & AMD_IOMMU_DEBUG_ACPI) {
98994f1124eSVikram Hegde 			cmn_err(CE_NOTE, "Found ACPI IVHD match: %p, "
99094f1124eSVikram Hegde 			    "actual deviceid = %u, start = %u, end = %u",
99194f1124eSVikram Hegde 			    (void *)hinfop, deviceid,
99294f1124eSVikram Hegde 			    hinfop->ach_deviceid_start,
99394f1124eSVikram Hegde 			    hinfop->ach_deviceid_end);
9947125fcbdSVikram Hegde 		}
99594f1124eSVikram Hegde 		goto out;
99694f1124eSVikram Hegde 	}
9977125fcbdSVikram Hegde 
99894f1124eSVikram Hegde 	if (idx !=  AMD_IOMMU_ACPI_INFO_HASH_SZ) {
99994f1124eSVikram Hegde 		idx = AMD_IOMMU_ACPI_INFO_HASH_SZ;
100094f1124eSVikram Hegde 		goto range;
10017125fcbdSVikram Hegde 	}
10027125fcbdSVikram Hegde 
100394f1124eSVikram Hegde out:
1004ba758cf1SJerry Gilliam 	if (amd_iommu_debug & AMD_IOMMU_DEBUG_ACPI) {
100594f1124eSVikram Hegde 		cmn_err(CE_NOTE, "%u: %s ACPI IVHD %p", deviceid,
100694f1124eSVikram Hegde 		    hinfop ? "GOT" : "Did NOT get", (void *)hinfop);
100794f1124eSVikram Hegde 	}
100894f1124eSVikram Hegde 
100994f1124eSVikram Hegde 	return (hinfop);
101094f1124eSVikram Hegde }
101194f1124eSVikram Hegde 
101294f1124eSVikram Hegde amd_iommu_acpi_ivmd_t *
amd_iommu_lookup_ivmd(int32_t deviceid)101394f1124eSVikram Hegde amd_iommu_lookup_ivmd(int32_t deviceid)
101494f1124eSVikram Hegde {
101594f1124eSVikram Hegde 	amd_iommu_acpi_ivmd_t *minfop;
101694f1124eSVikram Hegde 	uint16_t idx;
101794f1124eSVikram Hegde 
1018ba758cf1SJerry Gilliam 	if (amd_iommu_debug & AMD_IOMMU_DEBUG_ACPI) {
101994f1124eSVikram Hegde 		cmn_err(CE_NOTE, "Attempting to get ACPI IVMD info "
102094f1124eSVikram Hegde 		    "for deviceid: %u", deviceid);
102194f1124eSVikram Hegde 	}
102294f1124eSVikram Hegde 
102394f1124eSVikram Hegde 	ASSERT(amd_iommu_acpi_ivmd_hash);
10247125fcbdSVikram Hegde 
102594f1124eSVikram Hegde 	/* First search for an exact match */
102694f1124eSVikram Hegde 
102794f1124eSVikram Hegde 	idx = deviceid_hashfn(deviceid);
102894f1124eSVikram Hegde 
102994f1124eSVikram Hegde range:
103094f1124eSVikram Hegde 	minfop = amd_iommu_acpi_ivmd_hash[idx];
103194f1124eSVikram Hegde 
103294f1124eSVikram Hegde 	for (; minfop; minfop = minfop->acm_next) {
103394f1124eSVikram Hegde 		if (deviceid < minfop->acm_deviceid_start &&
103494f1124eSVikram Hegde 		    deviceid > minfop->acm_deviceid_end)
103594f1124eSVikram Hegde 			continue;
103694f1124eSVikram Hegde 
1037ba758cf1SJerry Gilliam 		if (amd_iommu_debug & AMD_IOMMU_DEBUG_ACPI) {
103894f1124eSVikram Hegde 			cmn_err(CE_NOTE, "Found ACPI IVMD match: %p, "
103994f1124eSVikram Hegde 			    "actual deviceid = %u, start = %u, end = %u",
104094f1124eSVikram Hegde 			    (void *)minfop, deviceid,
104194f1124eSVikram Hegde 			    minfop->acm_deviceid_start,
104294f1124eSVikram Hegde 			    minfop->acm_deviceid_end);
104394f1124eSVikram Hegde 		}
104494f1124eSVikram Hegde 
104594f1124eSVikram Hegde 		goto out;
10467125fcbdSVikram Hegde 	}
10477125fcbdSVikram Hegde 
104894f1124eSVikram Hegde 	if (idx !=  AMD_IOMMU_ACPI_INFO_HASH_SZ) {
104994f1124eSVikram Hegde 		idx = AMD_IOMMU_ACPI_INFO_HASH_SZ;
105094f1124eSVikram Hegde 		goto range;
105194f1124eSVikram Hegde 	}
105294f1124eSVikram Hegde 
105394f1124eSVikram Hegde out:
1054ba758cf1SJerry Gilliam 	if (amd_iommu_debug & AMD_IOMMU_DEBUG_ACPI) {
105594f1124eSVikram Hegde 		cmn_err(CE_NOTE, "%u: %s ACPI IVMD info %p", deviceid,
105694f1124eSVikram Hegde 		    minfop ? "GOT" : "Did NOT get", (void *)minfop);
10577125fcbdSVikram Hegde 	}
10587125fcbdSVikram Hegde 
105994f1124eSVikram Hegde 	return (minfop);
10607125fcbdSVikram Hegde }
1061