int vm_assign_pptdev(struct vm *vm, int bus, int slot, int func) { int error; vm_paddr_t maxaddr; /* * Virtual machines with pci passthru devices get special treatment: * - the guest physical memory is wired * - the iommu is programmed to do the 'gpa' to 'hpa' translation * * We need to do this before the first pci passthru device is attached. */ if (ppt_assigned_devices(vm) == 0) { KASSERT(vm->iommu == NULL, ("vm_assign_pptdev: iommu must be NULL")); maxaddr = vmm_mem_maxaddr(); vm->iommu = iommu_create_domain(maxaddr); error = vm_gpa_wire(vm); if (error) return (error); vm_iommu_map(vm); } error = ppt_assign_device(vm, bus, slot, func); return (error); }
void iommu_init(void) { int error, bus, slot, func; vm_paddr_t maxaddr; const char *name; device_t dev; if (vmm_is_intel()) ops = &iommu_ops_intel; else if (vmm_is_amd()) ops = &iommu_ops_amd; else ops = NULL; error = IOMMU_INIT(); if (error) return; iommu_avail = 1; /* * Create a domain for the devices owned by the host */ maxaddr = vmm_mem_maxaddr(); host_domain = IOMMU_CREATE_DOMAIN(maxaddr); if (host_domain == NULL) panic("iommu_init: unable to create a host domain"); /* * Create 1:1 mappings from '0' to 'maxaddr' for devices assigned to * the host */ iommu_create_mapping(host_domain, 0, 0, maxaddr); for (bus = 0; bus <= PCI_BUSMAX; bus++) { for (slot = 0; slot <= PCI_SLOTMAX; slot++) { for (func = 0; func <= PCI_FUNCMAX; func++) { dev = pci_find_dbsf(0, bus, slot, func); if (dev == NULL) continue; /* skip passthrough devices */ name = device_get_name(dev); if (name != NULL && strcmp(name, "ppt") == 0) continue; /* everything else belongs to the host domain */ iommu_add_device(host_domain, bus, slot, func); } } } IOMMU_ENABLE(); }