Changeset View
Changeset View
Standalone View
Standalone View
sys/amd64/vmm/amd/amdvi_hw.c
Show First 20 Lines • Show All 803 Lines • ▼ Show 20 Lines | |||||
static void | static void | ||||
amdvi_print_dev_cap(struct amdvi_softc *softc) | amdvi_print_dev_cap(struct amdvi_softc *softc) | ||||
{ | { | ||||
struct ivhd_dev_cfg *cfg; | struct ivhd_dev_cfg *cfg; | ||||
int i; | int i; | ||||
cfg = softc->dev_cfg; | cfg = softc->dev_cfg; | ||||
for (i = 0; i < softc->dev_cfg_cnt; i++) { | for (i = 0; i < softc->dev_cfg_cnt; i++) { | ||||
device_printf(softc->dev, "device [0x%x - 0x%x]" | device_printf(softc->dev, "device [0x%x - 0x%x] " | ||||
"config:%b%s\n", cfg->start_id, cfg->end_id, | "config:%b%s\n", cfg->start_id, cfg->end_id, | ||||
cfg->data, | cfg->data, | ||||
"\020\001INIT\002ExtInt\003NMI" | "\020\001INIT\002ExtInt\003NMI" | ||||
"\007LINT0\008LINT1", | "\007LINT0\010LINT1", | ||||
cfg->enable_ats ? "ATS enabled" : ""); | cfg->enable_ats ? "ATS enabled" : ""); | ||||
cfg++; | cfg++; | ||||
} | } | ||||
} | } | ||||
static int | static int | ||||
amdvi_handle_sysctl(SYSCTL_HANDLER_ARGS) | amdvi_handle_sysctl(SYSCTL_HANDLER_ARGS) | ||||
{ | { | ||||
▲ Show 20 Lines • Show All 44 Lines • ▼ Show 20 Lines | amdvi_add_sysctl(struct amdvi_softc *softc) | ||||
child = SYSCTL_CHILDREN(device_get_sysctl_tree(dev)); | child = SYSCTL_CHILDREN(device_get_sysctl_tree(dev)); | ||||
SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "event_intr_count", CTLFLAG_RD, | SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "event_intr_count", CTLFLAG_RD, | ||||
&softc->event_intr_cnt, "Event interrupt count"); | &softc->event_intr_cnt, "Event interrupt count"); | ||||
SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "command_count", CTLFLAG_RD, | SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "command_count", CTLFLAG_RD, | ||||
&softc->total_cmd, "Command submitted count"); | &softc->total_cmd, "Command submitted count"); | ||||
SYSCTL_ADD_U16(ctx, child, OID_AUTO, "pci_rid", CTLFLAG_RD, | SYSCTL_ADD_U16(ctx, child, OID_AUTO, "pci_rid", CTLFLAG_RD, | ||||
&softc->pci_rid, 0, "IOMMU RID"); | &softc->pci_rid, 0, "IOMMU RID"); | ||||
SYSCTL_ADD_U16(ctx, child, OID_AUTO, "start_dev_rid", CTLFLAG_RD, | |||||
&softc->start_dev_rid, 0, "Start of device under this IOMMU"); | |||||
SYSCTL_ADD_U16(ctx, child, OID_AUTO, "end_dev_rid", CTLFLAG_RD, | |||||
&softc->end_dev_rid, 0, "End of device under this IOMMU"); | |||||
SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "command_head", | SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "command_head", | ||||
CTLTYPE_UINT | CTLFLAG_RD | CTLFLAG_MPSAFE, softc, 0, | CTLTYPE_UINT | CTLFLAG_RD | CTLFLAG_MPSAFE, softc, 0, | ||||
amdvi_handle_sysctl, "IU", "Command head"); | amdvi_handle_sysctl, "IU", "Command head"); | ||||
SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "command_tail", | SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "command_tail", | ||||
CTLTYPE_UINT | CTLFLAG_RD | CTLFLAG_MPSAFE, softc, 1, | CTLTYPE_UINT | CTLFLAG_RD | CTLFLAG_MPSAFE, softc, 1, | ||||
amdvi_handle_sysctl, "IU", "Command tail"); | amdvi_handle_sysctl, "IU", "Command tail"); | ||||
SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "event_head", | SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "event_head", | ||||
CTLTYPE_UINT | CTLFLAG_RD | CTLFLAG_MPSAFE, softc, 2, | CTLTYPE_UINT | CTLFLAG_RD | CTLFLAG_MPSAFE, softc, 2, | ||||
▲ Show 20 Lines • Show All 310 Lines • ▼ Show 20 Lines | amdvi_destroy_mapping(void *arg, vm_paddr_t gpa, uint64_t len) | ||||
return | return | ||||
(len); | (len); | ||||
} | } | ||||
static struct amdvi_softc * | static struct amdvi_softc * | ||||
amdvi_find_iommu(uint16_t devid) | amdvi_find_iommu(uint16_t devid) | ||||
{ | { | ||||
struct amdvi_softc *softc; | struct amdvi_softc *softc; | ||||
int i; | int i, j; | ||||
for (i = 0; i < ivhd_count; i++) { | for (i = 0; i < ivhd_count; i++) { | ||||
softc = device_get_softc(ivhd_devs[i]); | softc = device_get_softc(ivhd_devs[i]); | ||||
if ((devid >= softc->start_dev_rid) && | for (j = 0; j < softc->dev_cfg_cnt; j++) | ||||
(devid <= softc->end_dev_rid)) | if ((devid >= softc->dev_cfg[j].start_id) && | ||||
(devid <= softc->dev_cfg[j].end_id)) | |||||
return (softc); | return (softc); | ||||
} | } | ||||
/* | return (NULL); | ||||
* XXX: BIOS bug, device not in IVRS table, assume its from first IOMMU. | |||||
*/ | |||||
printf("BIOS bug device(%d.%d.%d) doesn't have IVHD entry.\n", | |||||
RID2PCI_STR(devid)); | |||||
return (device_get_softc(ivhd_devs[0])); | |||||
} | } | ||||
/* | /* | ||||
* Set-up device table entry. | * Set-up device table entry. | ||||
* IOMMU spec Rev 2.0, section 3.2.2.2, some of the fields must | * IOMMU spec Rev 2.0, section 3.2.2.2, some of the fields must | ||||
grehan: Hmmm, rev 3.* has been out for a while now: might be time to update spec references (just an… | |||||
* be set concurrently, e.g. read and write bits. | * be set concurrently, e.g. read and write bits. | ||||
*/ | */ | ||||
static void | static void | ||||
amdvi_set_dte(struct amdvi_domain *domain, uint16_t devid, bool enable) | amdvi_set_dte(struct amdvi_domain *domain, struct amdvi_softc *softc, | ||||
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)); | 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)); | KASSERT(softc, ("softc is NULL for pci_rid:0x%x\n", devid)); | ||||
temp = &amdvi_dte[devid]; | temp = &amdvi_dte[devid]; | ||||
#ifdef AMDVI_ATS_ENABLE | #ifdef AMDVI_ATS_ENABLE | ||||
/* If IOMMU and device support IOTLB, enable it. */ | /* If IOMMU and device support IOTLB, enable it. */ | ||||
if (amdvi_dev_support_iotlb(softc, devid) && softc->iotlb) | if (amdvi_dev_support_iotlb(softc, devid) && softc->iotlb) | ||||
temp->iotlb_enable = 1; | temp->iotlb_enable = 1; | ||||
Show All 17 Lines | if (enable) { | ||||
*/ | */ | ||||
temp->pt_valid = 1; | temp->pt_valid = 1; | ||||
temp->read_allow = 1; | temp->read_allow = 1; | ||||
temp->write_allow = 1; | temp->write_allow = 1; | ||||
} | } | ||||
} | } | ||||
static void | static void | ||||
amdvi_inv_device(uint16_t devid) | amdvi_inv_device(struct amdvi_softc *softc, uint16_t devid) | ||||
{ | { | ||||
struct amdvi_softc *softc; | |||||
softc = amdvi_find_iommu(devid); | |||||
KASSERT(softc, ("softc is NULL")); | KASSERT(softc, ("softc is NULL")); | ||||
amdvi_cmd_inv_dte(softc, devid); | amdvi_cmd_inv_dte(softc, devid); | ||||
#ifdef AMDVI_ATS_ENABLE | #ifdef AMDVI_ATS_ENABLE | ||||
if (amdvi_dev_support_iotlb(softc, devid)) | if (amdvi_dev_support_iotlb(softc, devid)) | ||||
amdvi_cmd_inv_iotlb(softc, devid); | amdvi_cmd_inv_iotlb(softc, devid); | ||||
#endif | #endif | ||||
amdvi_wait(softc); | amdvi_wait(softc); | ||||
} | } | ||||
static void | static void | ||||
amdvi_add_device(void *arg, uint16_t devid) | amdvi_add_device(void *arg, uint16_t devid) | ||||
{ | { | ||||
struct amdvi_domain *domain; | struct amdvi_domain *domain; | ||||
struct amdvi_softc *softc; | |||||
domain = (struct amdvi_domain *)arg; | domain = (struct amdvi_domain *)arg; | ||||
KASSERT(domain != NULL, ("domain is NULL")); | KASSERT(domain != NULL, ("domain is NULL")); | ||||
#ifdef AMDVI_DEBUG_CMD | #ifdef AMDVI_DEBUG_CMD | ||||
printf("Assigning device(%d.%d.%d) to domain:%d\n", | printf("Assigning device(%d.%d.%d) to domain:%d\n", | ||||
RID2PCI_STR(devid), domain->id); | RID2PCI_STR(devid), domain->id); | ||||
#endif | #endif | ||||
amdvi_set_dte(domain, devid, true); | softc = amdvi_find_iommu(devid); | ||||
amdvi_inv_device(devid); | if (softc == NULL) | ||||
return; | |||||
amdvi_set_dte(domain, softc, devid, true); | |||||
amdvi_inv_device(softc, devid); | |||||
} | } | ||||
static void | static void | ||||
amdvi_remove_device(void *arg, uint16_t devid) | amdvi_remove_device(void *arg, uint16_t devid) | ||||
{ | { | ||||
struct amdvi_domain *domain; | struct amdvi_domain *domain; | ||||
struct amdvi_softc *softc; | |||||
domain = (struct amdvi_domain *)arg; | domain = (struct amdvi_domain *)arg; | ||||
#ifdef AMDVI_DEBUG_CMD | #ifdef AMDVI_DEBUG_CMD | ||||
printf("Remove device(0x%x) from domain:%d\n", | printf("Remove device(0x%x) from domain:%d\n", | ||||
devid, domain->id); | devid, domain->id); | ||||
#endif | #endif | ||||
amdvi_set_dte(domain, devid, false); | softc = amdvi_find_iommu(devid); | ||||
amdvi_inv_device(devid); | if (softc == NULL) | ||||
return; | |||||
amdvi_set_dte(domain, softc, devid, false); | |||||
amdvi_inv_device(softc, devid); | |||||
} | } | ||||
static void | static void | ||||
amdvi_enable(void) | amdvi_enable(void) | ||||
{ | { | ||||
struct amdvi_ctrl *ctrl; | struct amdvi_ctrl *ctrl; | ||||
struct amdvi_softc *softc; | struct amdvi_softc *softc; | ||||
uint64_t val; | uint64_t val; | ||||
▲ Show 20 Lines • Show All 69 Lines • Show Last 20 Lines |
Hmmm, rev 3.* has been out for a while now: might be time to update spec references (just an fyi, not necessary for this review).