Skip to content

Commit 025e90c

Browse files
committed
vfio: Enable in-kernel acceleration via VFIO KVM device
TCE hypercalls (H_PUT_TCE, H_PUT_TCE_INDIRECT, H_STUFF_TCE) use a logical bus number (LIOBN) to identify which TCE table the request is addressed to. However VFIO kernel driver operates with IOMMU group IDs and has no idea about which LIOBN corresponds to which group. If the host kernel supports in-kernel acceleration for TCE calls, we have to provide the LIOBN to IOMMU mapping information. This makes use of a VFIO KVM device's KVM_DEV_VFIO_GROUP_SET_SPAPR_TCE_LIOBN attribute to set the link between LIOBN and IOMMU group. The vfio_container_spapr_set_liobn() helper is implemented completely in vfio.c because kvm_vfio_spapr_tce_liobn needs a group fd and we do not want to share resources likes that outside vfio.c. Signed-off-by: Alexey Kardashevskiy <[email protected]>
1 parent 6302dbc commit 025e90c

File tree

5 files changed

+66
-7
lines changed

5 files changed

+66
-7
lines changed

hw/misc/vfio.c

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4560,3 +4560,43 @@ int vfio_container_ioctl(AddressSpace *as,
45604560

45614561
return vfio_container_do_ioctl(as, req, param);
45624562
}
4563+
4564+
int vfio_container_spapr_set_liobn(AddressSpace *as,
4565+
uint64_t liobn,
4566+
uint64_t start_addr)
4567+
{
4568+
#ifdef CONFIG_KVM
4569+
// VFIOGroup *group;
4570+
int ret;
4571+
struct kvm_vfio_spapr_tce_liobn param = {
4572+
.argsz = sizeof(param),
4573+
.liobn = liobn,
4574+
.start_addr = start_addr
4575+
};
4576+
struct kvm_device_attr attr = {
4577+
.group = KVM_DEV_VFIO_GROUP,
4578+
.attr = KVM_DEV_VFIO_GROUP_SET_SPAPR_TCE_LIOBN,
4579+
.addr = (uint64_t)(unsigned long)&param,
4580+
};
4581+
4582+
if (vfio_kvm_device_fd < 0) {
4583+
return 0;
4584+
}
4585+
4586+
// group = vfio_get_group(groupid, as);
4587+
// if (!group) {
4588+
// return -1;
4589+
// }
4590+
4591+
// param.fd = group->fd;
4592+
ret = ioctl(vfio_kvm_device_fd, KVM_SET_DEVICE_ATTR, &attr);
4593+
if (ret) {
4594+
error_report("vfio: failed to setup liobn for a group: %s",
4595+
strerror(errno));
4596+
}
4597+
4598+
return ret;
4599+
#else
4600+
return 0;
4601+
#endif
4602+
}

hw/ppc/spapr_iommu.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,7 @@ static int spapr_tce_table_realize(DeviceState *dev)
127127
if (!tcet->table) {
128128
size_t table_size = tcet->nb_table * sizeof(uint64_t);
129129
tcet->table = g_malloc0(table_size);
130+
tcet->vfio_accel = false;
130131
}
131132

132133
trace_spapr_iommu_new_table(tcet->liobn, tcet, tcet->table, tcet->fd);

hw/ppc/spapr_pci_vfio.c

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include "hw/pci-host/spapr.h"
2323
#include "linux/vfio.h"
2424
#include "hw/misc/vfio.h"
25+
#include "qemu/error-report.h"
2526

2627
#define DDW_PGSIZE_4K 0x01
2728
#define DDW_PGSIZE_64K 0x02
@@ -92,6 +93,16 @@ static void spapr_phb_vfio_reset(DeviceState *qdev)
9293
sphb->windows_num = 1;
9394

9495
sphb->ddw_enabled = (info.windows_supported > 1);
96+
97+
if (!tcet->vfio_accel) {
98+
return;
99+
}
100+
ret = vfio_container_spapr_set_liobn(&svphb->phb.iommu_as,
101+
tcet->liobn,
102+
tcet->bus_offset);
103+
if (ret) {
104+
error_report("spapr-vfio: failed to create link to IOMMU");
105+
}
95106
}
96107

97108
static int spapr_pci_vfio_ddw_query(sPAPRPHBState *sphb,
@@ -141,6 +152,16 @@ static int spapr_pci_vfio_ddw_create(sPAPRPHBState *sphb, uint32_t page_shift,
141152

142153
++sphb->windows_num;
143154

155+
if (!(*ptcet)->vfio_accel) {
156+
return 0;
157+
}
158+
ret = vfio_container_spapr_set_liobn(&sphb->iommu_as,
159+
liobn, (*ptcet)->bus_offset);
160+
if (ret) {
161+
error_report("spapr-vfio: failed to create link to IOMMU");
162+
ret = 0;
163+
}
164+
144165
return ret;
145166
}
146167

include/hw/misc/vfio.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,8 @@
66
extern int vfio_container_ioctl(AddressSpace *as,
77
int req, void *param);
88

9+
extern int vfio_container_spapr_set_liobn(AddressSpace *as,
10+
uint64_t liobn,
11+
uint64_t start_addr);
12+
913
#endif

linux-headers/linux/kvm.h

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -973,13 +973,6 @@ struct kvm_vfio_spapr_tce_liobn {
973973
__u64 start_addr;
974974
};
975975

976-
struct kvm_vfio_spapr_tce_liobn {
977-
__u32 argsz;
978-
__s32 fd;
979-
__u32 liobn;
980-
__u64 start_addr;
981-
};
982-
983976
/*
984977
* ioctls for VM fds
985978
*/

0 commit comments

Comments
 (0)