Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 16 Feb 2018 05:17:01 +0000 (UTC)
From:      Anish Gupta <anish@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r329360 - in head/sys: amd64/vmm/amd contrib/dev/acpica/include
Message-ID:  <201802160517.w1G5H1XH047278@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: anish
Date: Fri Feb 16 05:17:00 2018
New Revision: 329360
URL: https://svnweb.freebsd.org/changeset/base/329360

Log:
  This change fixes duplicate detection of same IOMMU/AMD-Vi device for Ryzen with EFR support.
  
  IVRS can have entry of type legacy and non-legacy present at same time for same AMD-Vi device. ivhd driver will ignore legacy if new IVHD type is present as specified in AMD-Vi specification. Earlier both of IVHD entries used and two ivhd devices were created.
  Add support for new IVHD type 0x11 and 0x40 in ACPI. Create new struct of type acpi_ivrs_hardware_new for these new type of IVHDs. Legacy type 0x10 will continue to use acpi_ivrs_hardware.
  
  Reviewed by:	avg
  Approved by:	grehan
  Differential Revision:https://reviews.freebsd.org/D13160

Modified:
  head/sys/amd64/vmm/amd/amdvi_hw.c
  head/sys/amd64/vmm/amd/amdvi_priv.h
  head/sys/amd64/vmm/amd/ivrs_drv.c
  head/sys/contrib/dev/acpica/include/actbl2.h

Modified: head/sys/amd64/vmm/amd/amdvi_hw.c
==============================================================================
--- head/sys/amd64/vmm/amd/amdvi_hw.c	Fri Feb 16 04:59:21 2018	(r329359)
+++ head/sys/amd64/vmm/amd/amdvi_hw.c	Fri Feb 16 05:17:00 2018	(r329360)
@@ -745,23 +745,8 @@ amdvi_print_pci_cap(device_t dev)
 	softc->pci_cap = cap >> 24;
 	device_printf(softc->dev, "PCI cap 0x%x@0x%x feature:%b\n",
 	    cap, off, softc->pci_cap,
-	    "\020\001IOTLB\002HT\003NPCache\004EFR");
+	    "\20\1IOTLB\2HT\3NPCache\4EFR\5CapExt");
 
-	/* IOMMU spec Rev 2.0, section 3.7.2.1 */
-	softc->pci_efr = softc->ctrl->ex_feature;
-	if (softc->pci_efr) {
-		device_printf(softc->dev, "PCI extended Feature:%b\n",
-		    (int)softc->pci_efr,
-		    "\020\001PreFSup\002PPRSup\003XTSup\004NXSup\006IASup"
-		    "\007GASup\008HESup\009PCSup");
-		device_printf(softc->dev,
-		    "PCI HATS = %d GATS = %d GLXSup = %d, max PASID: 0x%x ",
-		    (int)((softc->pci_efr >> 10) & 0x3),
-		    (int)((softc->pci_efr >> 12) & 0x3),
-		    (int)((softc->pci_efr >> 14) & 0x3),
-		    (int)((softc->pci_efr >> 32) & 0x1F) + 1);
-	}
-
 	return (0);
 }
 
@@ -1040,7 +1025,7 @@ amdvi_init(void)
 	}
 	if (!amdvi_enable_user && ivhd_count) {
 		printf("bhyve: Found %d AMD-Vi/IOMMU device(s), "
-		    	"use hw.vmm.amdvi_enable=1 to enable pass-through.\n",
+		    	"use hw.vmm.amdvi.enable=1 to enable pass-through.\n",
 		    ivhd_count);
 		return (EINVAL);
 	}
@@ -1315,40 +1300,41 @@ static void
 amdvi_set_dte(struct amdvi_domain *domain, uint16_t devid, bool enable)
 {
 	struct amdvi_softc *softc;
-	struct amdvi_dte temp;
+	struct amdvi_dte* temp;
 
+	KASSERT(domain, ("domain is NULL for pci_rid:0x%x\n", devid));
+	
 	softc = amdvi_find_iommu(devid);
 	KASSERT(softc, ("softc is NULL for pci_rid:0x%x\n", devid));
 
-	memset(&temp, 0, sizeof(struct amdvi_dte));
+	temp = &amdvi_dte[devid];
 
 #ifdef AMDVI_ATS_ENABLE
 	/* If IOMMU and device support IOTLB, enable it. */
 	if (amdvi_dev_support_iotlb(softc, devid) && softc->iotlb)
-		temp.iotlb_enable = 1;
+		temp->iotlb_enable = 1;
 #endif
 
 	/* Avoid duplicate I/O faults. */
-	temp.sup_second_io_fault = 1;
-	temp.sup_all_io_fault = amdvi_disable_io_fault;
+	temp->sup_second_io_fault = 1;
+	temp->sup_all_io_fault = amdvi_disable_io_fault;
 
-	temp.dt_valid = 1;
-	temp.domain_id = domain->id;
+	temp->dt_valid = 1;
+	temp->domain_id = domain->id;
 
 	if (enable) {
 		if (domain->ptp) {
-			temp.pt_base = vtophys(domain->ptp) >> 12;
-			temp.pt_level = amdvi_ptp_level;
+			temp->pt_base = vtophys(domain->ptp) >> 12;
+			temp->pt_level = amdvi_ptp_level;
 		}
 		/*
 		 * XXX: Page table valid[TV] bit must be set even if host domain
 		 * page tables are not enabled.
 		 */
-		temp.pt_valid = 1;
-		temp.read_allow = 1;
-		temp.write_allow = 1;
+		temp->pt_valid = 1;
+		temp->read_allow = 1;
+		temp->write_allow = 1;
 	}
-	amdvi_dte[devid] = temp;
 }
 
 static void

Modified: head/sys/amd64/vmm/amd/amdvi_priv.h
==============================================================================
--- head/sys/amd64/vmm/amd/amdvi_priv.h	Fri Feb 16 04:59:21 2018	(r329359)
+++ head/sys/amd64/vmm/amd/amdvi_priv.h	Fri Feb 16 05:17:00 2018	(r329360)
@@ -29,6 +29,8 @@
 #ifndef _AMDVI_PRIV_H_
 #define _AMDVI_PRIV_H_
 
+#include <contrib/dev/acpica/include/acpi.h>
+
 #define	BIT(n)			(1ULL << (n))
 /* Return value of bits[n:m] where n and (n >= ) m are bit positions. */
 #define REG_BITS(x, n, m)	(((x) >> (m)) & 		\
@@ -358,6 +360,7 @@ struct amdvi_domain {
 struct amdvi_softc {
 	struct amdvi_ctrl *ctrl;	/* Control area. */
 	device_t 	dev;		/* IOMMU device. */
+	enum AcpiIvrsType ivhd_type;	/* IOMMU IVHD type 0x10/0x11 or 0x40 */
 	bool		iotlb;		/* IOTLB supported by IOMMU */
 	struct amdvi_cmd *cmd;		/* Command descriptor area. */
 	int 		cmd_max;	/* Max number of commands. */
@@ -370,11 +373,11 @@ struct amdvi_softc {
 	int		event_rid;
 	/* ACPI various flags. */
 	uint32_t 	ivhd_flag;	/* ACPI IVHD flag. */
-	uint32_t 	ivhd_efr;	/* ACPI v1 Reserved or v2 EFR . */
+	uint32_t 	ivhd_feature;	/* ACPI v1 Reserved or v2 attribute. */
+	uint64_t 	ext_feature;	/* IVHD EFR */
 	/* PCI related. */
 	uint16_t 	cap_off;	/* PCI Capability offset. */
 	uint8_t		pci_cap;	/* PCI capability. */
-	uint64_t 	pci_efr;	/* PCI EFR for rev2.0 */
 	uint16_t 	pci_seg;	/* IOMMU PCI domain/segment. */
 	uint16_t 	pci_rid;	/* PCI BDF of IOMMU */
 	/* Device range under this IOMMU. */

Modified: head/sys/amd64/vmm/amd/ivrs_drv.c
==============================================================================
--- head/sys/amd64/vmm/amd/ivrs_drv.c	Fri Feb 16 04:59:21 2018	(r329359)
+++ head/sys/amd64/vmm/amd/ivrs_drv.c	Fri Feb 16 05:17:00 2018	(r329360)
@@ -47,12 +47,16 @@ __FBSDID("$FreeBSD$");
 #include "amdvi_priv.h"
 
 device_t *ivhd_devs;			/* IVHD or AMD-Vi device list. */
-int	ivhd_count;			/* Number of IVHD or AMD-Vi devices. */
+int	ivhd_count;			/* Number of IVHD header. */
+/* 
+ * Cached IVHD header list.
+ * Single entry for each IVHD, filtered the legacy one.
+ */
+ACPI_IVRS_HARDWARE *ivhd_hdrs[10];	
 
 extern int amdvi_ptp_level;		/* Page table levels. */
 
-typedef int (*ivhd_iter_t)(ACPI_IVRS_HEADER * ptr, void *arg);
-
+typedef int (*ivhd_iter_t)(ACPI_IVRS_HEADER *ptr, void *arg);
 /*
  * Iterate IVRS table for IVHD and IVMD device type.
  */
@@ -107,14 +111,19 @@ ivrs_hdr_iterate_tbl(ivhd_iter_t iter, void *arg)
 	}
 }
 
-static  int
+static bool
 ivrs_is_ivhd(UINT8 type)
 {
 
-	if ((type == ACPI_IVRS_TYPE_HARDWARE) || (type == 0x11)	|| (type == 0x40))
-		return (1);
+	switch(type) {
+	case ACPI_IVRS_TYPE_HARDWARE:
+	case ACPI_IVRS_TYPE_HARDWARE_EXT1:
+	case ACPI_IVRS_TYPE_HARDWARE_EXT2:
+		return (true);
 
-	return (0);
+	default:
+		return (false);
+	}
 }
 
 /* Count the number of AMD-Vi devices in the system. */
@@ -184,7 +193,7 @@ ivhd_dev_add_entry(struct amdvi_softc *softc, uint32_t
  * Record device attributes as suggested by BIOS.
  */
 static int
-ivhd_dev_parse(ACPI_IVRS_HARDWARE * ivhd, struct amdvi_softc *softc)
+ivhd_dev_parse(ACPI_IVRS_HARDWARE* ivhd, struct amdvi_softc *softc)
 {
 	ACPI_IVRS_DE_HEADER *de;
 	uint8_t *p, *end;
@@ -196,11 +205,26 @@ ivhd_dev_parse(ACPI_IVRS_HARDWARE * ivhd, struct amdvi
 	softc->start_dev_rid = ~0;
 	softc->end_dev_rid = 0;
 
-	/*
-	 * XXX The following actually depends on Header.Type and
-	 * is only true for 0x10.
-	 */
-	p = (uint8_t *)ivhd + sizeof(ACPI_IVRS_HARDWARE);
+	switch (ivhd->Header.Type) {
+		case ACPI_IVRS_TYPE_HARDWARE_EXT1:
+		case ACPI_IVRS_TYPE_HARDWARE_EXT2:
+			p = (uint8_t *)ivhd + sizeof(ACPI_IVRS_HARDWARE_NEW);
+			de = (ACPI_IVRS_DE_HEADER *) ((uint8_t *)ivhd +
+	    			sizeof(ACPI_IVRS_HARDWARE_NEW));
+			break;
+
+		case ACPI_IVRS_TYPE_HARDWARE:
+			p = (uint8_t *)ivhd + sizeof(ACPI_IVRS_HARDWARE);
+			de = (ACPI_IVRS_DE_HEADER *) ((uint8_t *)ivhd +
+	    			sizeof(ACPI_IVRS_HARDWARE));
+			break;
+
+		default:
+			device_printf(softc->dev, 
+				"unknown type: 0x%x\n", ivhd->Header.Type);
+			return (-1);
+	}
+
 	end = (uint8_t *)ivhd + ivhd->Header.Length;
 
 	while (p < end) {
@@ -285,14 +309,30 @@ ivhd_dev_parse(ACPI_IVRS_HARDWARE * ivhd, struct amdvi
 	return (0);
 }
 
+static bool
+ivhd_is_newer(ACPI_IVRS_HEADER *old, ACPI_IVRS_HEADER  *new)
+{
+	/*
+	 * Newer IVRS header type take precedence.
+	 */
+	if ((old->DeviceId == new->DeviceId) &&
+		(old->Type == ACPI_IVRS_TYPE_HARDWARE) &&
+		((new->Type == ACPI_IVRS_TYPE_HARDWARE_EXT1) ||
+		(new->Type == ACPI_IVRS_TYPE_HARDWARE_EXT1))) {
+		return (true);
+	}
+
+	return (false);
+}
+
 static void
 ivhd_identify(driver_t *driver, device_t parent)
 {
 	ACPI_TABLE_IVRS *ivrs;
 	ACPI_IVRS_HARDWARE *ivhd;
 	ACPI_STATUS status;
-	uint32_t info;
 	int i, count = 0;
+	uint32_t ivrs_ivinfo;
 
 	if (acpi_disabled("ivhd"))
 		return;
@@ -305,25 +345,41 @@ ivhd_identify(driver_t *driver, device_t parent)
 		return;
 	}
 
-	info = ivrs->Info;
-	printf("AMD-Vi IVRS VAsize = %d PAsize = %d GVAsize = %d flags:%b\n",
-		REG_BITS(info, 21, 15), REG_BITS(info, 14, 8), 
-		REG_BITS(info, 7, 5), REG_BITS(info, 22, 22),
-		"\020\001HtAtsResv");
+	ivrs_ivinfo = ivrs->Info;
+	printf("AMD-Vi: IVRS Info VAsize = %d PAsize = %d GVAsize = %d"
+	       " flags:%b\n",
+		REG_BITS(ivrs_ivinfo, 21, 15), REG_BITS(ivrs_ivinfo, 14, 8), 
+		REG_BITS(ivrs_ivinfo, 7, 5), REG_BITS(ivrs_ivinfo, 22, 22),
+		"\020\001EFRSup");
 
 	ivrs_hdr_iterate_tbl(ivhd_count_iter, NULL);
 	if (!ivhd_count)
 		return;
 
-	ivhd_devs = malloc(sizeof(device_t) * ivhd_count, M_DEVBUF,
-		M_WAITOK | M_ZERO);
 	for (i = 0; i < ivhd_count; i++) {
 		ivhd = ivhd_find_by_index(i);
-		if (ivhd == NULL) {
-			printf("Can't find IVHD entry%d\n", i);
-			continue;
+		KASSERT(ivhd, ("ivhd%d is NULL\n", i));
+		ivhd_hdrs[i] = ivhd;
+	}
+
+        /* 
+	 * Scan for presence of legacy and non-legacy device type
+	 * for same AMD-Vi device and override the old one.
+	 */
+	for (i = ivhd_count - 1 ; i > 0 ; i--){
+       		if (ivhd_is_newer(&ivhd_hdrs[i-1]->Header, 
+			&ivhd_hdrs[i]->Header)) {
+			ivhd_hdrs[i-1] = ivhd_hdrs[i];
+			ivhd_count--;
 		}
+       }	       
 
+	ivhd_devs = malloc(sizeof(device_t) * ivhd_count, M_DEVBUF,
+		M_WAITOK | M_ZERO);
+	for (i = 0; i < ivhd_count; i++) {
+		ivhd = ivhd_hdrs[i];
+		KASSERT(ivhd, ("ivhd%d is NULL\n", i));
+
 		/*
 		 * Use a high order to ensure that this driver is probed after
 		 * the Host-PCI bridge and the root PCI bus.
@@ -338,7 +394,7 @@ ivhd_identify(driver_t *driver, device_t parent)
 		if (ivhd_devs[i] == NULL) {
 			ivhd_devs[i] = device_find_child(parent, "ivhd", i);
 			if (ivhd_devs[i] == NULL) {
-				printf("AMD-Vi: cant find AMD-Vi dev%d\n", i);
+				printf("AMD-Vi: cant find ivhd%d\n", i);
 				break;
 			}
 		}
@@ -354,14 +410,169 @@ ivhd_identify(driver_t *driver, device_t parent)
 static int
 ivhd_probe(device_t dev)
 {
+	ACPI_IVRS_HARDWARE *ivhd;
+	int unit;
 
 	if (acpi_get_handle(dev) != NULL)
 		return (ENXIO);
-	device_set_desc(dev, "AMD-Vi/IOMMU or ivhd");
 
+	unit = device_get_unit(dev);
+	KASSERT((unit < ivhd_count), 
+		("ivhd unit %d > count %d", unit, ivhd_count));
+	ivhd = ivhd_hdrs[unit];
+	KASSERT(ivhd, ("ivhd is NULL"));
+
+	if (ivhd->Header.Type == ACPI_IVRS_TYPE_HARDWARE)
+		device_set_desc(dev, "AMD-Vi/IOMMU ivhd");
+	else	
+		device_set_desc(dev, "AMD-Vi/IOMMU ivhd with EFR");
+
 	return (BUS_PROBE_NOWILDCARD);
 }
 
+static void
+ivhd_print_flag(device_t dev, enum AcpiIvrsType ivhd_type, uint8_t flag)
+{
+	/*
+	 * IVHD lgeacy type has two extra high bits in flag which has
+	 * been moved to EFR for non-legacy device.
+	 */
+	switch (ivhd_type) {
+	case ACPI_IVRS_TYPE_HARDWARE:
+		device_printf(dev, "Flag:%b\n", flag,
+			"\020"
+			"\001HtTunEn"
+			"\002PassPW"
+			"\003ResPassPW"
+			"\004Isoc"
+			"\005IotlbSup"
+			"\006Coherent"
+			"\007PreFSup"
+			"\008PPRSup");
+		break;
+
+	case ACPI_IVRS_TYPE_HARDWARE_EXT1:
+	case ACPI_IVRS_TYPE_HARDWARE_EXT2:
+		device_printf(dev, "Flag:%b\n", flag,
+			"\020"
+			"\001HtTunEn"
+			"\002PassPW"
+			"\003ResPassPW"
+			"\004Isoc"
+			"\005IotlbSup"
+			"\006Coherent");
+		break;
+
+	default:
+		device_printf(dev, "Can't decode flag of ivhd type :0x%x\n",
+			ivhd_type);
+		break;
+	}
+}
+
+/*
+ * Feature in legacy IVHD type(0x10) and attribute in newer type(0x11 and 0x40).
+ */
+static void
+ivhd_print_feature(device_t dev, enum AcpiIvrsType ivhd_type, uint32_t feature) 
+{
+	switch (ivhd_type) {
+	case ACPI_IVRS_TYPE_HARDWARE:
+		device_printf(dev, "Features(type:0x%x) HATS = %d GATS = %d"
+			" MsiNumPPR = %d PNBanks= %d PNCounters= %d\n",
+			ivhd_type,
+			REG_BITS(feature, 31, 30),
+			REG_BITS(feature, 29, 28),
+			REG_BITS(feature, 27, 23),
+			REG_BITS(feature, 22, 17),
+			REG_BITS(feature, 16, 13));
+		device_printf(dev, "max PASID = %d GLXSup = %d Feature:%b\n",
+			REG_BITS(feature, 12, 8),
+			REG_BITS(feature, 4, 3),
+			feature,
+			"\020"
+			"\002NXSup"
+			"\003GTSup"
+			"\004<b4>"
+			"\005IASup"
+			"\006GASup"
+			"\007HESup");
+		break;
+
+	/* Fewer features or attributes are reported in non-legacy type. */
+	case ACPI_IVRS_TYPE_HARDWARE_EXT1:
+	case ACPI_IVRS_TYPE_HARDWARE_EXT2:
+		device_printf(dev, "Features(type:0x%x) MsiNumPPR = %d"
+			" PNBanks= %d PNCounters= %d\n",
+			ivhd_type,
+			REG_BITS(feature, 27, 23),
+			REG_BITS(feature, 22, 17),
+			REG_BITS(feature, 16, 13));
+		break;
+
+	default: /* Other ivhd type features are not decoded. */
+		device_printf(dev, "Can't decode ivhd type :0x%x\n", ivhd_type);
+	}
+}
+
+/* Print extended features of IOMMU. */
+static void
+ivhd_print_ext_feature(device_t dev, uint64_t ext_feature)
+{
+	uint32_t ext_low, ext_high;
+
+	if (!ext_feature)
+		return;
+
+	ext_low = ext_feature;
+	device_printf(dev, "Extended features[31:0]:%b "
+		"HATS = 0x%x GATS = 0x%x "
+		"GLXSup = 0x%x SmiFSup = 0x%x SmiFRC = 0x%x "
+		"GAMSup = 0x%x DualPortLogSup = 0x%x DualEventLogSup = 0x%x\n",
+		(int)ext_low,
+		"\020"
+		"\001PreFSup"
+		"\002PPRSup"
+		"\003<b2>"
+		"\004NXSup"
+		"\005GTSup"
+		"\006<b5>"
+		"\007IASup"
+		"\008GASup"
+		"\009HESup"
+		"\010PCSup",
+		REG_BITS(ext_low, 11, 10),
+		REG_BITS(ext_low, 13, 12),
+		REG_BITS(ext_low, 15, 14),
+		REG_BITS(ext_low, 17, 16),
+		REG_BITS(ext_low, 20, 18),
+		REG_BITS(ext_low, 23, 21),
+		REG_BITS(ext_low, 25, 24),
+		REG_BITS(ext_low, 29, 28));
+
+	ext_high = ext_feature >> 32;
+	device_printf(dev, "Extended features[62:32]:%b "
+		"Max PASID: 0x%x DevTblSegSup = 0x%x "
+		"MarcSup = 0x%x\n",
+		(int)(ext_high),
+		"\020"
+		"\006USSup"
+		"\009PprOvrflwEarlySup"
+		"\010PPRAutoRspSup"
+		"\013BlKStopMrkSup"
+		"\014PerfOptSup"
+		"\015MsiCapMmioSup"
+		"\017GIOSup"
+		"\018HASup"
+		"\019EPHSup"
+		"\020AttrFWSup"
+		"\021HDSup"
+		"\023InvIotlbSup",
+	    	REG_BITS(ext_high, 5, 0),
+	    	REG_BITS(ext_high, 8, 7),
+	    	REG_BITS(ext_high, 11, 10));
+}
+
 static int
 ivhd_print_cap(struct amdvi_softc *softc, ACPI_IVRS_HARDWARE * ivhd)
 {
@@ -369,41 +580,23 @@ ivhd_print_cap(struct amdvi_softc *softc, ACPI_IVRS_HA
 	int max_ptp_level;
 
 	dev = softc->dev;
-	device_printf(dev, "Flag:%b\n", softc->ivhd_flag,
-	    "\020\001HtTunEn\002PassPW\003ResPassPW\004Isoc\005IotlbSup"
-	    "\006Coherent\007PreFSup\008PPRSup");
-	/*
-	 * If no extended feature[EFR], its rev1 with maximum paging level as 7.
-	 */
+	
+	ivhd_print_flag(dev, softc->ivhd_type, softc->ivhd_flag);
+	ivhd_print_feature(dev, softc->ivhd_type, softc->ivhd_feature);
+	ivhd_print_ext_feature(dev, softc->ext_feature);
 	max_ptp_level = 7;
-	if (softc->ivhd_efr) {
-		device_printf(dev, "EFR HATS = %d GATS = %d GLXSup = %d "
-		    "MsiNumPr = %d PNBanks= %d PNCounters= %d\n"
-		    "max PASID = %d EFR: %b \n",
-		    REG_BITS(softc->ivhd_efr, 31, 30),
-		    REG_BITS(softc->ivhd_efr, 29, 28),
-		    REG_BITS(softc->ivhd_efr, 4, 3),
-		    REG_BITS(softc->ivhd_efr, 27, 23),
-		    REG_BITS(softc->ivhd_efr, 22, 17),
-		    REG_BITS(softc->ivhd_efr, 16, 13),
-		    REG_BITS(softc->ivhd_efr, 12, 8),
-		    softc->ivhd_efr, "\020\001XTSup\002NXSup\003GTSup\005IASup"
-		    "\006GASup\007HESup\008PPRSup");
-
-		max_ptp_level = REG_BITS(softc->ivhd_efr, 31, 30) + 4;
-	}
-
 	/* Make sure device support minimum page level as requested by user. */
 	if (max_ptp_level < amdvi_ptp_level) {
-		device_printf(dev, "Insufficient PTP level:%d\n",
-		    max_ptp_level);
+		device_printf(dev, "insufficient PTP level:%d\n",
+			max_ptp_level);
 		return (EINVAL);
+	} else {
+		device_printf(softc->dev, "supported paging level:%d, will use only: %d\n",
+	    		max_ptp_level, amdvi_ptp_level);
 	}
 
-	device_printf(softc->dev, "max supported paging level:%d restricting to: %d\n",
-	    max_ptp_level, amdvi_ptp_level);
-	device_printf(softc->dev, "device supported range "
-	    "[0x%x - 0x%x]\n", softc->start_dev_rid, softc->end_dev_rid);
+	device_printf(softc->dev, "device range: 0x%x - 0x%x\n",
+			softc->start_dev_rid, softc->end_dev_rid);
 
 	return (0);
 }
@@ -412,25 +605,32 @@ static int
 ivhd_attach(device_t dev)
 {
 	ACPI_IVRS_HARDWARE *ivhd;
+	ACPI_IVRS_HARDWARE_NEW *ivhd1;
 	struct amdvi_softc *softc;
 	int status, unit;
 
 	unit = device_get_unit(dev);
+	KASSERT((unit < ivhd_count), 
+		("ivhd unit %d > count %d", unit, ivhd_count));
 	/* Make sure its same device for which attach is called. */
-	if (ivhd_devs[unit] != dev)
-		panic("Not same device old %p new %p", ivhd_devs[unit], dev);
+	KASSERT((ivhd_devs[unit] == dev),
+		("Not same device old %p new %p", ivhd_devs[unit], dev));
 
 	softc = device_get_softc(dev);
 	softc->dev = dev;
-	ivhd = ivhd_find_by_index(unit);
-	if (ivhd == NULL)
-		return (EINVAL);
+	ivhd = ivhd_hdrs[unit];
+	KASSERT(ivhd, ("ivhd is NULL"));
 
+	softc->ivhd_type = ivhd->Header.Type;
 	softc->pci_seg = ivhd->PciSegmentGroup;
 	softc->pci_rid = ivhd->Header.DeviceId;
 	softc->ivhd_flag = ivhd->Header.Flags;
-	softc->ivhd_efr = ivhd->Reserved;
 	/* 
+	 * On lgeacy IVHD type(0x10), it is documented as feature
+	 * but in newer type it is attribute.
+	 */
+	softc->ivhd_feature = ivhd->Reserved;
+	/* 
 	 * PCI capability has more capabilities that are not part of IVRS.
 	 */
 	softc->cap_off = ivhd->CapabilityOffset;
@@ -439,6 +639,15 @@ ivhd_attach(device_t dev)
 	/* IVHD Info bit[4:0] is event MSI/X number. */
 	softc->event_msix = ivhd->Info & 0x1F;
 #endif
+	switch (ivhd->Header.Type) {
+		case ACPI_IVRS_TYPE_HARDWARE_EXT1:
+		case ACPI_IVRS_TYPE_HARDWARE_EXT2:
+			ivhd1 = (ACPI_IVRS_HARDWARE_NEW *)ivhd;
+			softc->ext_feature = ivhd1->ExtFR;
+			break;
+
+	}
+
 	softc->ctrl = (struct amdvi_ctrl *) PHYS_TO_DMAP(ivhd->BaseAddress);
 	status = ivhd_dev_parse(ivhd, softc);
 	if (status != 0) {

Modified: head/sys/contrib/dev/acpica/include/actbl2.h
==============================================================================
--- head/sys/contrib/dev/acpica/include/actbl2.h	Fri Feb 16 04:59:21 2018	(r329359)
+++ head/sys/contrib/dev/acpica/include/actbl2.h	Fri Feb 16 05:17:00 2018	(r329360)
@@ -444,6 +444,8 @@ typedef struct acpi_ivrs_header
 enum AcpiIvrsType
 {
     ACPI_IVRS_TYPE_HARDWARE         = 0x10,
+    ACPI_IVRS_TYPE_HARDWARE_EXT1    = 0x11,
+    ACPI_IVRS_TYPE_HARDWARE_EXT2    = 0x40,
     ACPI_IVRS_TYPE_MEMORY1          = 0x20,
     ACPI_IVRS_TYPE_MEMORY2          = 0x21,
     ACPI_IVRS_TYPE_MEMORY3          = 0x22
@@ -481,6 +483,21 @@ typedef struct acpi_ivrs_hardware
     UINT32                  Reserved;
 
 } ACPI_IVRS_HARDWARE;
+
+/* 0x11 and 0x40: I/O Virtualization Hardware Definition Block (IVHD) */
+
+typedef struct acpi_ivrs_hardware_new
+{
+    ACPI_IVRS_HEADER        Header;
+    UINT16                  CapabilityOffset;	/* Offset for IOMMU control fields */
+    UINT64                  BaseAddress;	/* IOMMU control registers */
+    UINT16                  PciSegmentGroup;
+    UINT16                  Info;		/* MSI number and unit ID */
+    UINT32                  Attr;		/* IOMMU Feature */
+    UINT64                  ExtFR;		/* IOMMU Extended Feature */
+    UINT64                  Reserved;		/* v1 feature or v2 attribute */
+
+} ACPI_IVRS_HARDWARE_NEW;
 
 /* Masks for Info field above */
 



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201802160517.w1G5H1XH047278>