vfio: use virtual IOMMU IDs for guests
As we now have UAPI to create pvIOMMU for guests, we should use the
virtual topology in the guest device tree instead of the hardcoding
device ids.
Signed-off-by: Mostafa Saleh <smostafa@google.com>
diff --git a/include/kvm/vfio.h b/include/kvm/vfio.h
index 4da56d1..4973860 100644
--- a/include/kvm/vfio.h
+++ b/include/kvm/vfio.h
@@ -116,6 +116,11 @@
* PCI for now.
*/
struct vfio_platform_device platform;
+
+ /* A device is connected to only one IOMMU. */
+ u64 iommu;
+ u32 *sid;
+ int nr_sid;
};
struct vfio_device_params {
diff --git a/vfio/core.c b/vfio/core.c
index ee4e248..4e1fbd0 100644
--- a/vfio/core.c
+++ b/vfio/core.c
@@ -726,7 +726,13 @@
.attr = KVM_DEV_VFIO_PVIOMMU_GET_INFO,
.addr = (uint64_t)&info,
};
+
ret = ioctl(cd.fd, KVM_SET_DEVICE_ATTR, &attr);
+
+ vfio_devices[i].iommu = pviommufd;
+ vfio_devices[i].sid = malloc(info.nr_sids * sizeof(vfio_devices[i].sid));
+ vfio_devices[i].nr_sid = info.nr_sids;
+
/* Set vSID => SID translation. */
for (j = 0; j < info.nr_sids; ++j) {
struct kvm_vfio_iommu_config config = {
@@ -747,6 +753,7 @@
pr_err("Failed to set vsid(%d) => sid(%d) translation, err %d\n", config.vsid, j, ret);
return ret;
}
+ vfio_devices[i].sid[j] = config.vsid;
}
}
@@ -791,8 +798,11 @@
if (!kvm->cfg.num_vfio_devices)
return 0;
- for (i = 0; i < kvm->cfg.num_vfio_devices; i++)
+ for (i = 0; i < kvm->cfg.num_vfio_devices; i++) {
+ if (vfio_devices[i].nr_sid)
+ free(vfio_devices[i].sid);
vfio_device_exit(kvm, &vfio_devices[i]);
+ }
free(vfio_devices);
diff --git a/vfio/platform.c b/vfio/platform.c
index f108f86..02f6f7d 100644
--- a/vfio/platform.c
+++ b/vfio/platform.c
@@ -35,10 +35,10 @@
_FDT(fdt_end_node(fdt));
}
-static void generate_qemu_iommu(void *fdt) {
+static void generate_qemu_iommu(void *fdt, u64 id) {
_FDT(fdt_begin_node(fdt, "pviommu"));
_FDT(fdt_property_string(fdt, "compatible", "pkvm,pviommu"));
- _FDT(fdt_property_cell(fdt, "id", 0));
+ _FDT(fdt_property_cell(fdt, "id", id));
_FDT(fdt_property_cell(fdt, "phandle", 0x9000));
_FDT(fdt_property_cell(fdt, "#iommu-cells", 1));
_FDT(fdt_end_node(fdt));
@@ -62,7 +62,7 @@
struct vfio_platform_device *pdev = &vdev->platform;
u32 iommu[] = {
cpu_to_fdt32(0x9000), /*phandle of pvIOMMU */
- cpu_to_fdt32(1), /* SID */
+ cpu_to_fdt32(vdev->sid[0]), /* SID */
};
u64 reg_prop[10]; /* Max 5 for now. */
@@ -70,7 +70,7 @@
generate_qemu_virt_clk(fdt);
- generate_qemu_iommu(fdt);
+ generate_qemu_iommu(fdt, vdev->iommu);
for ( ; i < vdev->info.num_regions ; i++) {
reg_prop[2 * i] = cpu_to_fdt64(vdev->regions[i].guest_phys_addr); /* Addr */