Skip to content

Commit

Permalink
KVM: PPC: Book3S HV: XIVE: Add a TIMA mapping
Browse files Browse the repository at this point in the history
Each thread has an associated Thread Interrupt Management context
composed of a set of registers. These registers let the thread handle
priority management and interrupt acknowledgment. The most important
are :

    - Interrupt Pending Buffer     (IPB)
    - Current Processor Priority   (CPPR)
    - Notification Source Register (NSR)

They are exposed to software in four different pages each proposing a
view with a different privilege. The first page is for the physical
thread context and the second for the hypervisor. Only the third
(operating system) and the fourth (user level) are exposed the guest.

A custom VM fault handler will populate the VMA with the appropriate
pages, which should only be the OS page for now.

Signed-off-by: Cédric Le Goater <clg@kaod.org>
Reviewed-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
  • Loading branch information
Cédric Le Goater authored and Paul Mackerras committed Apr 30, 2019
1 parent a1cd3f0 commit 39e9af3
Show file tree
Hide file tree
Showing 5 changed files with 76 additions and 0 deletions.
23 changes: 23 additions & 0 deletions Documentation/virtual/kvm/devices/xive.txt
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,29 @@ requires a POWER9 host and the guest OS should have support for the
XIVE native exploitation interrupt mode. If not, it should run using
the legacy interrupt mode, referred as XICS (POWER7/8).

* Device Mappings

The KVM device exposes different MMIO ranges of the XIVE HW which
are required for interrupt management. These are exposed to the
guest in VMAs populated with a custom VM fault handler.

1. Thread Interrupt Management Area (TIMA)

Each thread has an associated Thread Interrupt Management context
composed of a set of registers. These registers let the thread
handle priority management and interrupt acknowledgment. The most
important are :

- Interrupt Pending Buffer (IPB)
- Current Processor Priority (CPPR)
- Notification Source Register (NSR)

They are exposed to software in four different pages each proposing
a view with a different privilege. The first page is for the
physical thread context and the second for the hypervisor. Only the
third (operating system) and the fourth (user level) are exposed the
guest.

* Groups:

1. KVM_DEV_XIVE_GRP_CTRL
Expand Down
1 change: 1 addition & 0 deletions arch/powerpc/include/asm/xive.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
* same offset regardless of where the code is executing
*/
extern void __iomem *xive_tima;
extern unsigned long xive_tima_os;

/*
* Offset in the TM area of our current execution level (provided by
Expand Down
2 changes: 2 additions & 0 deletions arch/powerpc/include/uapi/asm/kvm.h
Original file line number Diff line number Diff line change
Expand Up @@ -720,4 +720,6 @@ struct kvm_ppc_xive_eq {

#define KVM_XIVE_EQ_ALWAYS_NOTIFY 0x00000001

#define KVM_XIVE_TIMA_PAGE_OFFSET 0

#endif /* __LINUX_KVM_POWERPC_H */
39 changes: 39 additions & 0 deletions arch/powerpc/kvm/book3s_xive_native.c
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,44 @@ int kvmppc_xive_native_connect_vcpu(struct kvm_device *dev,
return rc;
}

static vm_fault_t xive_native_tima_fault(struct vm_fault *vmf)
{
struct vm_area_struct *vma = vmf->vma;

switch (vmf->pgoff - vma->vm_pgoff) {
case 0: /* HW - forbid access */
case 1: /* HV - forbid access */
return VM_FAULT_SIGBUS;
case 2: /* OS */
vmf_insert_pfn(vma, vmf->address, xive_tima_os >> PAGE_SHIFT);
return VM_FAULT_NOPAGE;
case 3: /* USER - TODO */
default:
return VM_FAULT_SIGBUS;
}
}

static const struct vm_operations_struct xive_native_tima_vmops = {
.fault = xive_native_tima_fault,
};

static int kvmppc_xive_native_mmap(struct kvm_device *dev,
struct vm_area_struct *vma)
{
/* We only allow mappings at fixed offset for now */
if (vma->vm_pgoff == KVM_XIVE_TIMA_PAGE_OFFSET) {
if (vma_pages(vma) > 4)
return -EINVAL;
vma->vm_ops = &xive_native_tima_vmops;
} else {
return -EINVAL;
}

vma->vm_flags |= VM_IO | VM_PFNMAP;
vma->vm_page_prot = pgprot_noncached_wc(vma->vm_page_prot);
return 0;
}

static int kvmppc_xive_native_set_source(struct kvmppc_xive *xive, long irq,
u64 addr)
{
Expand Down Expand Up @@ -1050,6 +1088,7 @@ struct kvm_device_ops kvm_xive_native_ops = {
.set_attr = kvmppc_xive_native_set_attr,
.get_attr = kvmppc_xive_native_get_attr,
.has_attr = kvmppc_xive_native_has_attr,
.mmap = kvmppc_xive_native_mmap,
};

void kvmppc_xive_native_init_module(void)
Expand Down
11 changes: 11 additions & 0 deletions arch/powerpc/sysdev/xive/native.c
Original file line number Diff line number Diff line change
Expand Up @@ -521,6 +521,9 @@ u32 xive_native_default_eq_shift(void)
}
EXPORT_SYMBOL_GPL(xive_native_default_eq_shift);

unsigned long xive_tima_os;
EXPORT_SYMBOL_GPL(xive_tima_os);

bool __init xive_native_init(void)
{
struct device_node *np;
Expand Down Expand Up @@ -573,6 +576,14 @@ bool __init xive_native_init(void)
for_each_possible_cpu(cpu)
kvmppc_set_xive_tima(cpu, r.start, tima);

/* Resource 2 is OS window */
if (of_address_to_resource(np, 2, &r)) {
pr_err("Failed to get thread mgmnt area resource\n");
return false;
}

xive_tima_os = r.start;

/* Grab size of provisionning pages */
xive_parse_provisioning(np);

Expand Down

0 comments on commit 39e9af3

Please sign in to comment.