This will let the guest create a memory mapping to expose the XIVE MMIO region (TIMA) used for interrupt management at the CPU level. Signed-off-by: Cédric Le Goater <clg@xxxxxxxx> --- arch/powerpc/include/uapi/asm/kvm.h | 1 + arch/powerpc/kvm/book3s_xive_native.c | 49 +++++++++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+) diff --git a/arch/powerpc/include/uapi/asm/kvm.h b/arch/powerpc/include/uapi/asm/kvm.h index cf54fad1faf6..c564ee892cac 100644 --- a/arch/powerpc/include/uapi/asm/kvm.h +++ b/arch/powerpc/include/uapi/asm/kvm.h @@ -677,6 +677,7 @@ struct kvm_ppc_cpu_char { #define KVM_DEV_XIVE_GRP_SOURCES 1 /* 64-bit source attributes */ #define KVM_DEV_XIVE_GRP_CTRL 2 #define KVM_DEV_XIVE_GET_ESB_FD 1 +#define KVM_DEV_XIVE_GET_TIMA_FD 2 /* Layout of 64-bit XIVE source attribute values */ #define KVM_XIVE_LEVEL_SENSITIVE (1ULL << 0) diff --git a/arch/powerpc/kvm/book3s_xive_native.c b/arch/powerpc/kvm/book3s_xive_native.c index 395298c5fca8..cfce8ba327ca 100644 --- a/arch/powerpc/kvm/book3s_xive_native.c +++ b/arch/powerpc/kvm/book3s_xive_native.c @@ -321,6 +321,52 @@ static int kvmppc_xive_native_get_esb_fd(struct kvmppc_xive *xive, u64 addr) return put_user(ret, ubufp); } +static int xive_native_tima_fault(struct vm_fault *vmf) +{ + struct vm_area_struct *vma = vmf->vma; + + if (vmf->pgoff) + return VM_FAULT_SIGBUS; + + vm_insert_pfn(vma, vmf->address, (unsigned long) + local_paca->kvm_hstate.xive_tima_phys >> PAGE_SHIFT); + return VM_FAULT_NOPAGE; +} + +static const struct vm_operations_struct xive_native_tima_vmops = { + .fault = xive_native_tima_fault, +}; + +static int xive_native_tima_mmap(struct file *file, struct vm_area_struct *vma) +{ + unsigned long len = vma->vm_end - vma->vm_start; + + if (len != (1 << PAGE_SHIFT)) + return -EINVAL; + + vma->vm_flags |= VM_IO | VM_PFNMAP; + vma->vm_page_prot = pgprot_noncached_wc(vma->vm_page_prot); + vma->vm_ops = &xive_native_tima_vmops; + return 0; +} + +static const struct file_operations xive_native_tima_fops = { + .mmap = xive_native_tima_mmap, +}; + +static int kvmppc_xive_native_get_tima_fd(struct kvmppc_xive *xive, u64 addr) +{ + u64 __user *ubufp = (u64 __user *) addr; + int ret; + + ret = anon_inode_getfd("tima", &xive_native_tima_fops, xive, + O_RDWR | O_CLOEXEC); + if (ret < 0) + return ret; + + return put_user(ret, ubufp); +} + static int kvmppc_xive_native_set_attr(struct kvm_device *dev, struct kvm_device_attr *attr) { @@ -344,6 +390,8 @@ static int kvmppc_xive_native_get_attr(struct kvm_device *dev, switch (attr->attr) { case KVM_DEV_XIVE_GET_ESB_FD: return kvmppc_xive_native_get_esb_fd(xive, attr->addr); + case KVM_DEV_XIVE_GET_TIMA_FD: + return kvmppc_xive_native_get_tima_fd(xive, attr->addr); } break; } @@ -362,6 +410,7 @@ static int kvmppc_xive_native_has_attr(struct kvm_device *dev, case KVM_DEV_XIVE_GRP_CTRL: switch (attr->attr) { case KVM_DEV_XIVE_GET_ESB_FD: + case KVM_DEV_XIVE_GET_TIMA_FD: return 0; } break; -- 2.13.6