Changeset View
Changeset View
Standalone View
Standalone View
sys/amd64/vmm/amd/amdvi_hw.c
Show First 20 Lines • Show All 999 Lines • ▼ Show 20 Lines | if (create && ((softc->pci_cap & AMDVI_PCI_CAP_NPCACHE) == 0)) | ||||
continue; | continue; | ||||
#endif | #endif | ||||
amdvi_inv_domain(softc, domain_id); | amdvi_inv_domain(softc, domain_id); | ||||
amdvi_wait(softc); | amdvi_wait(softc); | ||||
} | } | ||||
} | } | ||||
static void * | static void * | ||||
amdvi_create_domain(vm_paddr_t maxaddr) | amdvi_create_domain(vm_paddr_t maxaddr, bool host_domain __unused) | ||||
{ | { | ||||
struct amdvi_domain *dom; | struct amdvi_domain *dom; | ||||
dom = malloc(sizeof(struct amdvi_domain), M_AMDVI, M_ZERO | M_WAITOK); | dom = malloc(sizeof(struct amdvi_domain), M_AMDVI, M_ZERO | M_WAITOK); | ||||
dom->id = amdvi_domainId(); | dom->id = amdvi_domainId(); | ||||
//dom->maxaddr = maxaddr; | //dom->maxaddr = maxaddr; | ||||
#ifdef AMDVI_DEBUG_CMD | #ifdef AMDVI_DEBUG_CMD | ||||
printf("Created domain #%d\n", dom->id); | printf("Created domain #%d\n", dom->id); | ||||
▲ Show 20 Lines • Show All 136 Lines • ▼ Show 20 Lines | if (!len) { | ||||
return (0); | return (0); | ||||
} | } | ||||
mapped += len; | mapped += len; | ||||
} | } | ||||
return (mapped); | return (mapped); | ||||
} | } | ||||
static uint64_t | static int | ||||
amdvi_create_mapping(void *arg, vm_paddr_t gpa, vm_paddr_t hpa, | amdvi_create_mapping(void *arg, vm_paddr_t gpa, vm_paddr_t hpa, | ||||
uint64_t len) | uint64_t len, uint64_t *res_len) | ||||
{ | { | ||||
struct amdvi_domain *domain; | struct amdvi_domain *domain; | ||||
domain = (struct amdvi_domain *)arg; | domain = (struct amdvi_domain *)arg; | ||||
if (domain->id && !domain->ptp) { | if (domain->id && !domain->ptp) { | ||||
printf("ptp is NULL"); | printf("ptp is NULL"); | ||||
return (-1); | return (EINVAL); | ||||
} | } | ||||
/* | /* | ||||
* If host domain is created w/o page table, skip IOMMU page | * If host domain is created w/o page table, skip IOMMU page | ||||
* table set-up. | * table set-up. | ||||
*/ | */ | ||||
if (domain->ptp) | if (domain->ptp) | ||||
return (amdvi_update_mapping(domain, gpa, hpa, len, true)); | *res_len = amdvi_update_mapping(domain, gpa, hpa, len, true); | ||||
else | else | ||||
return (len); | *res_len = len; | ||||
return (0); | |||||
} | } | ||||
static uint64_t | static int | ||||
amdvi_remove_mapping(void *arg, vm_paddr_t gpa, uint64_t len) | amdvi_remove_mapping(void *arg, vm_paddr_t gpa, uint64_t len, uint64_t *res_len) | ||||
{ | { | ||||
struct amdvi_domain *domain; | struct amdvi_domain *domain; | ||||
domain = (struct amdvi_domain *)arg; | domain = (struct amdvi_domain *)arg; | ||||
/* | /* | ||||
* If host domain is created w/o page table, skip IOMMU page | * If host domain is created w/o page table, skip IOMMU page | ||||
* table set-up. | * table set-up. | ||||
*/ | */ | ||||
if (domain->ptp) | if (domain->ptp) | ||||
return (amdvi_update_mapping(domain, gpa, 0, len, false)); | *res_len = amdvi_update_mapping(domain, gpa, 0, len, false); | ||||
return | else | ||||
(len); | *res_len = len; | ||||
return (0); | |||||
} | } | ||||
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, j; | int i, j; | ||||
▲ Show 20 Lines • Show All 60 Lines • ▼ Show 20 Lines | amdvi_inv_device(struct amdvi_softc *softc, uint16_t devid) | ||||
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 int | ||||
amdvi_add_device(void *arg, uint16_t devid) | amdvi_add_device(void *arg, device_t dev __unused, uint16_t devid) | ||||
{ | { | ||||
struct amdvi_domain *domain; | struct amdvi_domain *domain; | ||||
struct amdvi_softc *softc; | 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 | ||||
softc = amdvi_find_iommu(devid); | softc = amdvi_find_iommu(devid); | ||||
if (softc == NULL) | if (softc == NULL) | ||||
return; | return (ENXIO); | ||||
amdvi_set_dte(domain, softc, devid, true); | amdvi_set_dte(domain, softc, devid, true); | ||||
amdvi_inv_device(softc, devid); | amdvi_inv_device(softc, devid); | ||||
return (0); | |||||
} | } | ||||
static void | static int | ||||
amdvi_remove_device(void *arg, uint16_t devid) | amdvi_remove_device(void *arg, device_t dev __unused, uint16_t devid) | ||||
{ | { | ||||
struct amdvi_domain *domain; | struct amdvi_domain *domain; | ||||
struct amdvi_softc *softc; | 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 | ||||
softc = amdvi_find_iommu(devid); | softc = amdvi_find_iommu(devid); | ||||
if (softc == NULL) | if (softc == NULL) | ||||
return; | return (ENXIO); | ||||
amdvi_set_dte(domain, softc, devid, false); | amdvi_set_dte(domain, softc, devid, false); | ||||
amdvi_inv_device(softc, devid); | amdvi_inv_device(softc, devid); | ||||
return (0); | |||||
} | } | ||||
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 All 38 Lines | for (i = 0; i < ivhd_count; i++) { | ||||
KASSERT(softc, ("softc is NULL\n")); | KASSERT(softc, ("softc is NULL\n")); | ||||
ctrl = softc->ctrl; | ctrl = softc->ctrl; | ||||
KASSERT(ctrl, ("ctrl is NULL\n")); | KASSERT(ctrl, ("ctrl is NULL\n")); | ||||
ctrl->control = 0; | ctrl->control = 0; | ||||
} | } | ||||
} | } | ||||
static void | static int | ||||
amdvi_invalidate_tlb(void *arg) | amdvi_invalidate_tlb(void *arg) | ||||
{ | { | ||||
struct amdvi_domain *domain; | struct amdvi_domain *domain; | ||||
domain = (struct amdvi_domain *)arg; | domain = (struct amdvi_domain *)arg; | ||||
KASSERT(domain, ("domain is NULL")); | KASSERT(domain, ("domain is NULL")); | ||||
amdvi_do_inv_domain(domain->id, false); | amdvi_do_inv_domain(domain->id, false); | ||||
return (0); | |||||
} | } | ||||
const struct iommu_ops iommu_ops_amd = { | const struct iommu_ops iommu_ops_amd = { | ||||
.init = amdvi_init, | .init = amdvi_init, | ||||
.cleanup = amdvi_cleanup, | .cleanup = amdvi_cleanup, | ||||
.enable = amdvi_enable, | .enable = amdvi_enable, | ||||
.disable = amdvi_disable, | .disable = amdvi_disable, | ||||
.create_domain = amdvi_create_domain, | .create_domain = amdvi_create_domain, | ||||
.destroy_domain = amdvi_destroy_domain, | .destroy_domain = amdvi_destroy_domain, | ||||
.create_mapping = amdvi_create_mapping, | .create_mapping = amdvi_create_mapping, | ||||
.remove_mapping = amdvi_remove_mapping, | .remove_mapping = amdvi_remove_mapping, | ||||
.add_device = amdvi_add_device, | .add_device = amdvi_add_device, | ||||
.remove_device = amdvi_remove_device, | .remove_device = amdvi_remove_device, | ||||
.invalidate_tlb = amdvi_invalidate_tlb | .invalidate_tlb = amdvi_invalidate_tlb, | ||||
}; | }; |