svn commit: r329360 - in head/sys: amd64/vmm/amd contrib/dev/acpica/include
Anish Gupta
anish at FreeBSD.org
Fri Feb 16 05:17:02 UTC 2018
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 at 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 */
More information about the svn-src-all
mailing list