diff options
author | Alexey Kardashevskiy <aik@ozlabs.ru> | 2017-03-10 12:41:13 +1100 |
---|---|---|
committer | David Gibson <david@gibson.dropbear.id.au> | 2017-04-26 12:00:41 +1000 |
commit | d6ee2a7c85088d587fb0e0376fba1fa20d59c9f3 (patch) | |
tree | 815d0adc9e6a674b494fda930779436f78c08c0b /target/ppc/kvm.c | |
parent | 9d169fb3c8c8434124677afa52824c4b15b62b65 (diff) |
target-ppc: kvm: make use of KVM_CREATE_SPAPR_TCE_64
KVM_CAP_SPAPR_TCE capability allows creating TCE tables in KVM which
allows having in-kernel acceleration for H_PUT_TCE_xxx hypercalls.
However it only supports 32bit DMA windows at zero bus offset.
There is a new KVM_CAP_SPAPR_TCE_64 capability which supports 64bit
window size, variable page size and bus offset.
This makes use of the new capability. The kernel headers are already
updated as the kernel support went in to v4.6.
Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Diffstat (limited to 'target/ppc/kvm.c')
-rw-r--r-- | target/ppc/kvm.c | 48 |
1 files changed, 37 insertions, 11 deletions
diff --git a/target/ppc/kvm.c b/target/ppc/kvm.c index c3d426292c..79b90a6910 100644 --- a/target/ppc/kvm.c +++ b/target/ppc/kvm.c @@ -74,6 +74,7 @@ static int cap_booke_sregs; static int cap_ppc_smt; static int cap_ppc_rma; static int cap_spapr_tce; +static int cap_spapr_tce_64; static int cap_spapr_multitce; static int cap_spapr_vfio; static int cap_hior; @@ -126,6 +127,7 @@ int kvm_arch_init(MachineState *ms, KVMState *s) cap_ppc_smt = kvm_check_extension(s, KVM_CAP_PPC_SMT); cap_ppc_rma = kvm_check_extension(s, KVM_CAP_PPC_RMA); cap_spapr_tce = kvm_check_extension(s, KVM_CAP_SPAPR_TCE); + cap_spapr_tce_64 = kvm_check_extension(s, KVM_CAP_SPAPR_TCE_64); cap_spapr_multitce = kvm_check_extension(s, KVM_CAP_SPAPR_MULTITCE); cap_spapr_vfio = false; cap_one_reg = kvm_check_extension(s, KVM_CAP_ONE_REG); @@ -2136,13 +2138,10 @@ bool kvmppc_spapr_use_multitce(void) return cap_spapr_multitce; } -void *kvmppc_create_spapr_tce(uint32_t liobn, uint32_t window_size, int *pfd, - bool need_vfio) +void *kvmppc_create_spapr_tce(uint32_t liobn, uint32_t page_shift, + uint64_t bus_offset, uint32_t nb_table, + int *pfd, bool need_vfio) { - struct kvm_create_spapr_tce args = { - .liobn = liobn, - .window_size = window_size, - }; long len; int fd; void *table; @@ -2155,14 +2154,41 @@ void *kvmppc_create_spapr_tce(uint32_t liobn, uint32_t window_size, int *pfd, return NULL; } - fd = kvm_vm_ioctl(kvm_state, KVM_CREATE_SPAPR_TCE, &args); - if (fd < 0) { - fprintf(stderr, "KVM: Failed to create TCE table for liobn 0x%x\n", - liobn); + if (cap_spapr_tce_64) { + struct kvm_create_spapr_tce_64 args = { + .liobn = liobn, + .page_shift = page_shift, + .offset = bus_offset >> page_shift, + .size = nb_table, + .flags = 0 + }; + fd = kvm_vm_ioctl(kvm_state, KVM_CREATE_SPAPR_TCE_64, &args); + if (fd < 0) { + fprintf(stderr, + "KVM: Failed to create TCE64 table for liobn 0x%x\n", + liobn); + return NULL; + } + } else if (cap_spapr_tce) { + uint64_t window_size = (uint64_t) nb_table << page_shift; + struct kvm_create_spapr_tce args = { + .liobn = liobn, + .window_size = window_size, + }; + if ((window_size != args.window_size) || bus_offset) { + return NULL; + } + fd = kvm_vm_ioctl(kvm_state, KVM_CREATE_SPAPR_TCE, &args); + if (fd < 0) { + fprintf(stderr, "KVM: Failed to create TCE table for liobn 0x%x\n", + liobn); + return NULL; + } + } else { return NULL; } - len = (window_size / SPAPR_TCE_PAGE_SIZE) * sizeof(uint64_t); + len = nb_table * sizeof(uint64_t); /* FIXME: round this up to page size */ table = mmap(NULL, len, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); |