Changeset View
Changeset View
Standalone View
Standalone View
sys/amd64/vmm/amd/ivrs_drv.c
Show First 20 Lines • Show All 80 Lines • ▼ Show 20 Lines | ivrs_hdr_iterate_tbl(ivhd_iter_t iter, void *arg) | ||||
while (ivrs_hdr < end) { | while (ivrs_hdr < end) { | ||||
if ((uint8_t *)ivrs_hdr + ivrs_hdr->Length > (uint8_t *)end) { | if ((uint8_t *)ivrs_hdr + ivrs_hdr->Length > (uint8_t *)end) { | ||||
printf("AMD-Vi:IVHD/IVMD is corrupted, length : %d\n", | printf("AMD-Vi:IVHD/IVMD is corrupted, length : %d\n", | ||||
ivrs_hdr->Length); | ivrs_hdr->Length); | ||||
break; | break; | ||||
} | } | ||||
switch (ivrs_hdr->Type) { | switch (ivrs_hdr->Type) { | ||||
case ACPI_IVRS_TYPE_HARDWARE: /* Legacy */ | case IVRS_TYPE_HARDWARE_LEGACY: /* Legacy */ | ||||
case 0x11: | case IVRS_TYPE_HARDWARE_EFR: | ||||
case 0x40: /* ACPI HID */ | case IVRS_TYPE_HARDWARE_MIXED: | ||||
if (!iter(ivrs_hdr, arg)) | if (!iter(ivrs_hdr, arg)) | ||||
return; | return; | ||||
break; | break; | ||||
case ACPI_IVRS_TYPE_MEMORY1: | case ACPI_IVRS_TYPE_MEMORY1: | ||||
case ACPI_IVRS_TYPE_MEMORY2: | case ACPI_IVRS_TYPE_MEMORY2: | ||||
case ACPI_IVRS_TYPE_MEMORY3: | case ACPI_IVRS_TYPE_MEMORY3: | ||||
if (!iter(ivrs_hdr, arg)) | if (!iter(ivrs_hdr, arg)) | ||||
Show All 11 Lines | ivrs_hdr_iterate_tbl(ivhd_iter_t iter, void *arg) | ||||
} | } | ||||
} | } | ||||
static bool | static bool | ||||
ivrs_is_ivhd(UINT8 type) | ivrs_is_ivhd(UINT8 type) | ||||
{ | { | ||||
switch(type) { | switch(type) { | ||||
case ACPI_IVRS_TYPE_HARDWARE: | case IVRS_TYPE_HARDWARE_LEGACY: | ||||
case ACPI_IVRS_TYPE_HARDWARE_EXT1: | case IVRS_TYPE_HARDWARE_EFR: | ||||
case ACPI_IVRS_TYPE_HARDWARE_EXT2: | case IVRS_TYPE_HARDWARE_MIXED: | ||||
return (true); | return (true); | ||||
default: | default: | ||||
return (false); | return (false); | ||||
} | } | ||||
} | } | ||||
/* Count the number of AMD-Vi devices in the system. */ | /* Count the number of AMD-Vi devices in the system. */ | ||||
▲ Show 20 Lines • Show All 71 Lines • ▼ Show 20 Lines | ivhd_dev_parse(ACPI_IVRS_HARDWARE* ivhd, struct amdvi_softc *softc) | ||||
uint32_t *extended; | uint32_t *extended; | ||||
uint8_t all_data = 0, range_data = 0; | uint8_t all_data = 0, range_data = 0; | ||||
bool range_enable_ats = false, enable_ats; | bool range_enable_ats = false, enable_ats; | ||||
softc->start_dev_rid = ~0; | softc->start_dev_rid = ~0; | ||||
softc->end_dev_rid = 0; | softc->end_dev_rid = 0; | ||||
switch (ivhd->Header.Type) { | switch (ivhd->Header.Type) { | ||||
case ACPI_IVRS_TYPE_HARDWARE_EXT1: | case IVRS_TYPE_HARDWARE_LEGACY: | ||||
case ACPI_IVRS_TYPE_HARDWARE_EXT2: | p = (uint8_t *)ivhd + sizeof(ACPI_IVRS_HARDWARE); | ||||
p = (uint8_t *)ivhd + sizeof(ACPI_IVRS_HARDWARE_NEW); | |||||
de = (ACPI_IVRS_DE_HEADER *) ((uint8_t *)ivhd + | |||||
sizeof(ACPI_IVRS_HARDWARE_NEW)); | |||||
break; | break; | ||||
case ACPI_IVRS_TYPE_HARDWARE: | case IVRS_TYPE_HARDWARE_EFR: | ||||
p = (uint8_t *)ivhd + sizeof(ACPI_IVRS_HARDWARE); | case IVRS_TYPE_HARDWARE_MIXED: | ||||
de = (ACPI_IVRS_DE_HEADER *) ((uint8_t *)ivhd + | p = (uint8_t *)ivhd + sizeof(ACPI_IVRS_HARDWARE_EFRSUP); | ||||
sizeof(ACPI_IVRS_HARDWARE)); | |||||
break; | break; | ||||
default: | default: | ||||
device_printf(softc->dev, | device_printf(softc->dev, | ||||
"unknown type: 0x%x\n", ivhd->Header.Type); | "unknown type: 0x%x\n", ivhd->Header.Type); | ||||
return (-1); | return (-1); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 83 Lines • ▼ Show 20 Lines | |||||
static bool | static bool | ||||
ivhd_is_newer(ACPI_IVRS_HEADER *old, ACPI_IVRS_HEADER *new) | ivhd_is_newer(ACPI_IVRS_HEADER *old, ACPI_IVRS_HEADER *new) | ||||
{ | { | ||||
/* | /* | ||||
* Newer IVRS header type take precedence. | * Newer IVRS header type take precedence. | ||||
*/ | */ | ||||
if ((old->DeviceId == new->DeviceId) && | if ((old->DeviceId == new->DeviceId) && | ||||
(old->Type == ACPI_IVRS_TYPE_HARDWARE) && | (old->Type == IVRS_TYPE_HARDWARE_LEGACY) && | ||||
((new->Type == ACPI_IVRS_TYPE_HARDWARE_EXT1) || | ((new->Type == IVRS_TYPE_HARDWARE_EFR) || | ||||
(new->Type == ACPI_IVRS_TYPE_HARDWARE_EXT1))) { | (new->Type == IVRS_TYPE_HARDWARE_MIXED))) { | ||||
return (true); | return (true); | ||||
} | } | ||||
return (false); | return (false); | ||||
} | } | ||||
static void | static void | ||||
ivhd_identify(driver_t *driver, device_t parent) | ivhd_identify(driver_t *driver, device_t parent) | ||||
▲ Show 20 Lines • Show All 87 Lines • ▼ Show 20 Lines | if (acpi_get_handle(dev) != NULL) | ||||
return (ENXIO); | return (ENXIO); | ||||
unit = device_get_unit(dev); | unit = device_get_unit(dev); | ||||
KASSERT((unit < ivhd_count), | KASSERT((unit < ivhd_count), | ||||
("ivhd unit %d > count %d", unit, ivhd_count)); | ("ivhd unit %d > count %d", unit, ivhd_count)); | ||||
ivhd = ivhd_hdrs[unit]; | ivhd = ivhd_hdrs[unit]; | ||||
KASSERT(ivhd, ("ivhd is NULL")); | KASSERT(ivhd, ("ivhd is NULL")); | ||||
if (ivhd->Header.Type == ACPI_IVRS_TYPE_HARDWARE) | switch (ivhd->Header.Type) { | ||||
device_set_desc(dev, "AMD-Vi/IOMMU ivhd"); | case IVRS_TYPE_HARDWARE_EFR: | ||||
else | |||||
device_set_desc(dev, "AMD-Vi/IOMMU ivhd with EFR"); | device_set_desc(dev, "AMD-Vi/IOMMU ivhd with EFR"); | ||||
break; | |||||
case IVRS_TYPE_HARDWARE_MIXED: | |||||
device_set_desc(dev, "AMD-Vi/IOMMU ivhd in mixed format"); | |||||
break; | |||||
case IVRS_TYPE_HARDWARE_LEGACY: | |||||
default: | |||||
device_set_desc(dev, "AMD-Vi/IOMMU ivhd"); | |||||
break; | |||||
} | |||||
return (BUS_PROBE_NOWILDCARD); | return (BUS_PROBE_NOWILDCARD); | ||||
} | } | ||||
static void | static void | ||||
ivhd_print_flag(device_t dev, enum AcpiIvrsType ivhd_type, uint8_t flag) | ivhd_print_flag(device_t dev, enum IvrsType ivhd_type, uint8_t flag) | ||||
{ | { | ||||
/* | /* | ||||
* IVHD lgeacy type has two extra high bits in flag which has | * IVHD lgeacy type has two extra high bits in flag which has | ||||
* been moved to EFR for non-legacy device. | * been moved to EFR for non-legacy device. | ||||
*/ | */ | ||||
switch (ivhd_type) { | switch (ivhd_type) { | ||||
case ACPI_IVRS_TYPE_HARDWARE: | case IVRS_TYPE_HARDWARE_LEGACY: | ||||
device_printf(dev, "Flag:%b\n", flag, | device_printf(dev, "Flag:%b\n", flag, | ||||
"\020" | "\020" | ||||
"\001HtTunEn" | "\001HtTunEn" | ||||
"\002PassPW" | "\002PassPW" | ||||
"\003ResPassPW" | "\003ResPassPW" | ||||
"\004Isoc" | "\004Isoc" | ||||
"\005IotlbSup" | "\005IotlbSup" | ||||
"\006Coherent" | "\006Coherent" | ||||
"\007PreFSup" | "\007PreFSup" | ||||
"\008PPRSup"); | "\008PPRSup"); | ||||
break; | break; | ||||
case ACPI_IVRS_TYPE_HARDWARE_EXT1: | case IVRS_TYPE_HARDWARE_EFR: | ||||
case ACPI_IVRS_TYPE_HARDWARE_EXT2: | case IVRS_TYPE_HARDWARE_MIXED: | ||||
device_printf(dev, "Flag:%b\n", flag, | device_printf(dev, "Flag:%b\n", flag, | ||||
"\020" | "\020" | ||||
"\001HtTunEn" | "\001HtTunEn" | ||||
"\002PassPW" | "\002PassPW" | ||||
"\003ResPassPW" | "\003ResPassPW" | ||||
"\004Isoc" | "\004Isoc" | ||||
"\005IotlbSup" | "\005IotlbSup" | ||||
"\006Coherent"); | "\006Coherent"); | ||||
break; | break; | ||||
default: | default: | ||||
device_printf(dev, "Can't decode flag of ivhd type :0x%x\n", | device_printf(dev, "Can't decode flag of ivhd type :0x%x\n", | ||||
ivhd_type); | ivhd_type); | ||||
break; | break; | ||||
} | } | ||||
} | } | ||||
/* | /* | ||||
* Feature in legacy IVHD type(0x10) and attribute in newer type(0x11 and 0x40). | * Feature in legacy IVHD type(0x10) and attribute in newer type(0x11 and 0x40). | ||||
*/ | */ | ||||
static void | static void | ||||
ivhd_print_feature(device_t dev, enum AcpiIvrsType ivhd_type, uint32_t feature) | ivhd_print_feature(device_t dev, enum IvrsType ivhd_type, uint32_t feature) | ||||
{ | { | ||||
switch (ivhd_type) { | switch (ivhd_type) { | ||||
case ACPI_IVRS_TYPE_HARDWARE: | case IVRS_TYPE_HARDWARE_LEGACY: | ||||
device_printf(dev, "Features(type:0x%x) HATS = %d GATS = %d" | device_printf(dev, "Features(type:0x%x) HATS = %d GATS = %d" | ||||
" MsiNumPPR = %d PNBanks= %d PNCounters= %d\n", | " MsiNumPPR = %d PNBanks= %d PNCounters= %d\n", | ||||
ivhd_type, | ivhd_type, | ||||
REG_BITS(feature, 31, 30), | REG_BITS(feature, 31, 30), | ||||
REG_BITS(feature, 29, 28), | REG_BITS(feature, 29, 28), | ||||
REG_BITS(feature, 27, 23), | REG_BITS(feature, 27, 23), | ||||
REG_BITS(feature, 22, 17), | REG_BITS(feature, 22, 17), | ||||
REG_BITS(feature, 16, 13)); | REG_BITS(feature, 16, 13)); | ||||
device_printf(dev, "max PASID = %d GLXSup = %d Feature:%b\n", | device_printf(dev, "max PASID = %d GLXSup = %d Feature:%b\n", | ||||
REG_BITS(feature, 12, 8), | REG_BITS(feature, 12, 8), | ||||
REG_BITS(feature, 4, 3), | REG_BITS(feature, 4, 3), | ||||
feature, | feature, | ||||
"\020" | "\020" | ||||
"\002NXSup" | "\002NXSup" | ||||
"\003GTSup" | "\003GTSup" | ||||
"\004<b4>" | "\004<b4>" | ||||
"\005IASup" | "\005IASup" | ||||
"\006GASup" | "\006GASup" | ||||
"\007HESup"); | "\007HESup"); | ||||
break; | break; | ||||
/* Fewer features or attributes are reported in non-legacy type. */ | /* Fewer features or attributes are reported in non-legacy type. */ | ||||
case ACPI_IVRS_TYPE_HARDWARE_EXT1: | case IVRS_TYPE_HARDWARE_EFR: | ||||
case ACPI_IVRS_TYPE_HARDWARE_EXT2: | case IVRS_TYPE_HARDWARE_MIXED: | ||||
device_printf(dev, "Features(type:0x%x) MsiNumPPR = %d" | device_printf(dev, "Features(type:0x%x) MsiNumPPR = %d" | ||||
" PNBanks= %d PNCounters= %d\n", | " PNBanks= %d PNCounters= %d\n", | ||||
ivhd_type, | ivhd_type, | ||||
REG_BITS(feature, 27, 23), | REG_BITS(feature, 27, 23), | ||||
REG_BITS(feature, 22, 17), | REG_BITS(feature, 22, 17), | ||||
REG_BITS(feature, 16, 13)); | REG_BITS(feature, 16, 13)); | ||||
break; | break; | ||||
▲ Show 20 Lines • Show All 87 Lines • ▼ Show 20 Lines | ivhd_print_cap(struct amdvi_softc *softc, ACPI_IVRS_HARDWARE * ivhd) | ||||
return (0); | return (0); | ||||
} | } | ||||
static int | static int | ||||
ivhd_attach(device_t dev) | ivhd_attach(device_t dev) | ||||
{ | { | ||||
ACPI_IVRS_HARDWARE *ivhd; | ACPI_IVRS_HARDWARE *ivhd; | ||||
ACPI_IVRS_HARDWARE_NEW *ivhd1; | ACPI_IVRS_HARDWARE_EFRSUP *ivhd_efr; | ||||
struct amdvi_softc *softc; | struct amdvi_softc *softc; | ||||
int status, unit; | int status, unit; | ||||
unit = device_get_unit(dev); | unit = device_get_unit(dev); | ||||
KASSERT((unit < ivhd_count), | KASSERT((unit < ivhd_count), | ||||
("ivhd unit %d > count %d", unit, ivhd_count)); | ("ivhd unit %d > count %d", unit, ivhd_count)); | ||||
/* Make sure its same device for which attach is called. */ | /* Make sure its same device for which attach is called. */ | ||||
KASSERT((ivhd_devs[unit] == dev), | KASSERT((ivhd_devs[unit] == dev), | ||||
Show All 18 Lines | ivhd_attach(device_t dev) | ||||
*/ | */ | ||||
softc->cap_off = ivhd->CapabilityOffset; | softc->cap_off = ivhd->CapabilityOffset; | ||||
#ifdef notyet | #ifdef notyet | ||||
/* IVHD Info bit[4:0] is event MSI/X number. */ | /* IVHD Info bit[4:0] is event MSI/X number. */ | ||||
softc->event_msix = ivhd->Info & 0x1F; | softc->event_msix = ivhd->Info & 0x1F; | ||||
#endif | #endif | ||||
switch (ivhd->Header.Type) { | switch (ivhd->Header.Type) { | ||||
case ACPI_IVRS_TYPE_HARDWARE_EXT1: | case IVRS_TYPE_HARDWARE_EFR: | ||||
case ACPI_IVRS_TYPE_HARDWARE_EXT2: | case IVRS_TYPE_HARDWARE_MIXED: | ||||
ivhd1 = (ACPI_IVRS_HARDWARE_NEW *)ivhd; | ivhd_efr = (ACPI_IVRS_HARDWARE_EFRSUP *)ivhd; | ||||
softc->ext_feature = ivhd1->ExtFR; | softc->ext_feature = ivhd_efr->ExtFR; | ||||
break; | break; | ||||
} | } | ||||
softc->ctrl = (struct amdvi_ctrl *) PHYS_TO_DMAP(ivhd->BaseAddress); | softc->ctrl = (struct amdvi_ctrl *) PHYS_TO_DMAP(ivhd->BaseAddress); | ||||
status = ivhd_dev_parse(ivhd, softc); | status = ivhd_dev_parse(ivhd, softc); | ||||
if (status != 0) { | if (status != 0) { | ||||
device_printf(dev, | device_printf(dev, | ||||
▲ Show 20 Lines • Show All 73 Lines • Show Last 20 Lines |