Changeset View
Changeset View
Standalone View
Standalone View
sys/amd64/vmm/amd/ivrs_drv.c
Show First 20 Lines • Show All 51 Lines • ▼ Show 20 Lines | |||||
#include "amdvi_priv.h" | #include "amdvi_priv.h" | ||||
device_t *ivhd_devs; /* IVHD or AMD-Vi device list. */ | device_t *ivhd_devs; /* IVHD or AMD-Vi device list. */ | ||||
int ivhd_count; /* Number of IVHD header. */ | int ivhd_count; /* Number of IVHD header. */ | ||||
/* | /* | ||||
* Cached IVHD header list. | * Cached IVHD header list. | ||||
* Single entry for each IVHD, filtered the legacy one. | * Single entry for each IVHD, filtered the legacy one. | ||||
*/ | */ | ||||
ACPI_IVRS_HARDWARE1 *ivhd_hdrs[10]; | ACPI_IVRS_HARDWARE1 **ivhd_hdrs; | ||||
extern int amdvi_ptp_level; /* Page table levels. */ | 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. | * Iterate IVRS table for IVHD and IVMD device type. | ||||
*/ | */ | ||||
static void | static void | ||||
▲ Show 20 Lines • Show All 60 Lines • ▼ Show 20 Lines | 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. */ | ||||
static int | static int | ||||
ivhd_count_iter(ACPI_IVRS_HEADER * ivrs_he, void *arg) | ivhd_count_iter(ACPI_IVRS_HEADER * ivrs_he, void *arg) | ||||
{ | { | ||||
int *count; | |||||
count = (int *)arg; | |||||
if (ivrs_is_ivhd(ivrs_he->Type)) | if (ivrs_is_ivhd(ivrs_he->Type)) | ||||
ivhd_count++; | (*count)++; | ||||
return (1); | return (1); | ||||
} | } | ||||
struct find_ivrs_hdr_args { | struct find_ivrs_hdr_args { | ||||
int i; | int i; | ||||
ACPI_IVRS_HEADER *ptr; | ACPI_IVRS_HEADER *ptr; | ||||
}; | }; | ||||
▲ Show 20 Lines • Show All 186 Lines • ▼ Show 20 Lines | |||||
} | } | ||||
static void | static void | ||||
ivhd_identify(driver_t *driver, device_t parent) | ivhd_identify(driver_t *driver, device_t parent) | ||||
{ | { | ||||
ACPI_TABLE_IVRS *ivrs; | ACPI_TABLE_IVRS *ivrs; | ||||
ACPI_IVRS_HARDWARE1 *ivhd; | ACPI_IVRS_HARDWARE1 *ivhd; | ||||
ACPI_STATUS status; | ACPI_STATUS status; | ||||
int i, count = 0; | int i, j, count = 0; | ||||
uint32_t ivrs_ivinfo; | uint32_t ivrs_ivinfo; | ||||
if (acpi_disabled("ivhd")) | if (acpi_disabled("ivhd")) | ||||
return; | return; | ||||
status = AcpiGetTable(ACPI_SIG_IVRS, 1, (ACPI_TABLE_HEADER **)&ivrs); | status = AcpiGetTable(ACPI_SIG_IVRS, 1, (ACPI_TABLE_HEADER **)&ivrs); | ||||
if (ACPI_FAILURE(status)) | if (ACPI_FAILURE(status)) | ||||
return; | return; | ||||
if (ivrs->Header.Length == 0) { | if (ivrs->Header.Length == 0) { | ||||
return; | return; | ||||
} | } | ||||
ivrs_ivinfo = ivrs->Info; | ivrs_ivinfo = ivrs->Info; | ||||
printf("AMD-Vi: IVRS Info VAsize = %d PAsize = %d GVAsize = %d" | printf("AMD-Vi: IVRS Info VAsize = %d PAsize = %d GVAsize = %d" | ||||
" flags:%b\n", | " flags:%b\n", | ||||
REG_BITS(ivrs_ivinfo, 21, 15), REG_BITS(ivrs_ivinfo, 14, 8), | REG_BITS(ivrs_ivinfo, 21, 15), REG_BITS(ivrs_ivinfo, 14, 8), | ||||
REG_BITS(ivrs_ivinfo, 7, 5), REG_BITS(ivrs_ivinfo, 22, 22), | REG_BITS(ivrs_ivinfo, 7, 5), REG_BITS(ivrs_ivinfo, 22, 22), | ||||
"\020\001EFRSup"); | "\020\001EFRSup"); | ||||
ivrs_hdr_iterate_tbl(ivhd_count_iter, NULL); | ivrs_hdr_iterate_tbl(ivhd_count_iter, &count); | ||||
if (!ivhd_count) | if (!count) | ||||
return; | return; | ||||
for (i = 0; i < ivhd_count; i++) { | ivhd_hdrs = malloc(sizeof(void *) * count, M_DEVBUF, | ||||
M_WAITOK | M_ZERO); | |||||
for (i = 0; i < count; i++) { | |||||
ivhd = ivhd_find_by_index(i); | ivhd = ivhd_find_by_index(i); | ||||
KASSERT(ivhd, ("ivhd%d is NULL\n", i)); | KASSERT(ivhd, ("ivhd%d is NULL\n", i)); | ||||
ivhd_hdrs[i] = ivhd; | |||||
} | |||||
/* | /* | ||||
* Scan for presence of legacy and non-legacy device type | * Scan for presence of legacy and non-legacy device type | ||||
* for same AMD-Vi device and override the old one. | * for same IOMMU device and override the old one. | ||||
* | |||||
* If there is no existing IVHD to the same IOMMU device, | |||||
* the IVHD header pointer is appended. | |||||
*/ | */ | ||||
for (i = ivhd_count - 1 ; i > 0 ; i--){ | for (j = 0; j < ivhd_count; j++) { | ||||
if (ivhd_is_newer(&ivhd_hdrs[i-1]->Header, | if (ivhd_is_newer(&ivhd_hdrs[j]->Header, &ivhd->Header)) | ||||
&ivhd_hdrs[i]->Header)) { | break; | ||||
memmove(&ivhd_hdrs[i-1], &ivhd_hdrs[i], | |||||
sizeof(void *) * (ivhd_count - i)); | |||||
ivhd_count--; | |||||
} | } | ||||
ivhd_hdrs[j] = ivhd; | |||||
if (j == ivhd_count) | |||||
ivhd_count++; | |||||
} | } | ||||
ivhd_devs = malloc(sizeof(device_t) * ivhd_count, M_DEVBUF, | ivhd_devs = malloc(sizeof(device_t) * ivhd_count, M_DEVBUF, | ||||
M_WAITOK | M_ZERO); | M_WAITOK | M_ZERO); | ||||
for (i = 0; i < ivhd_count; i++) { | for (i = 0, j = 0; i < ivhd_count; i++) { | ||||
ivhd = ivhd_hdrs[i]; | ivhd = ivhd_hdrs[i]; | ||||
KASSERT(ivhd, ("ivhd%d is NULL\n", i)); | KASSERT(ivhd, ("ivhd%d is NULL\n", i)); | ||||
/* | /* | ||||
* Use a high order to ensure that this driver is probed after | * Use a high order to ensure that this driver is probed after | ||||
* the Host-PCI bridge and the root PCI bus. | * the Host-PCI bridge and the root PCI bus. | ||||
*/ | */ | ||||
ivhd_devs[i] = BUS_ADD_CHILD(parent, | ivhd_devs[i] = BUS_ADD_CHILD(parent, | ||||
ACPI_DEV_BASE_ORDER + 10 * 10, "ivhd", i); | ACPI_DEV_BASE_ORDER + 10 * 10, "ivhd", i); | ||||
/* | /* | ||||
* XXX: In case device was not destroyed before, add will fail. | * XXX: In case device was not destroyed before, add will fail. | ||||
* locate the old device instance. | * locate the old device instance. | ||||
*/ | */ | ||||
if (ivhd_devs[i] == NULL) { | if (ivhd_devs[i] == NULL) { | ||||
ivhd_devs[i] = device_find_child(parent, "ivhd", i); | ivhd_devs[i] = device_find_child(parent, "ivhd", i); | ||||
if (ivhd_devs[i] == NULL) { | if (ivhd_devs[i] == NULL) { | ||||
printf("AMD-Vi: cant find ivhd%d\n", i); | printf("AMD-Vi: cant find ivhd%d\n", i); | ||||
break; | break; | ||||
} | } | ||||
} | } | ||||
count++; | j++; | ||||
} | } | ||||
/* | /* | ||||
* Update device count in case failed to attach. | * Update device count in case failed to attach. | ||||
*/ | */ | ||||
ivhd_count = count; | ivhd_count = j; | ||||
} | } | ||||
static int | static int | ||||
ivhd_probe(device_t dev) | ivhd_probe(device_t dev) | ||||
{ | { | ||||
ACPI_IVRS_HARDWARE1 *ivhd; | ACPI_IVRS_HARDWARE1 *ivhd; | ||||
int unit; | int unit; | ||||
▲ Show 20 Lines • Show All 324 Lines • Show Last 20 Lines |