powerpc/xive: Share the event-queue page with the Hypervisor.
authorRam Pai <linuxram@us.ibm.com>
Mon, 24 Feb 2020 06:09:48 +0000 (01:09 -0500)
committerMichael Ellerman <mpe@ellerman.id.au>
Thu, 28 May 2020 13:24:40 +0000 (23:24 +1000)
XIVE interrupt controller uses an Event Queue (EQ) to enqueue event
notifications when an exception occurs. The EQ is a single memory page
provided by the O/S defining a circular buffer, one per server and
priority couple.

On baremetal, the EQ page is configured with an OPAL call. On pseries,
an extra hop is necessary and the guest OS uses the hcall
H_INT_SET_QUEUE_CONFIG to configure the XIVE interrupt controller.

The XIVE controller being Hypervisor privileged, it will not be allowed
to enqueue event notifications for a Secure VM unless the EQ pages are
shared by the Secure VM.

Hypervisor/Ultravisor still requires support for the TIMA and ESB page
fault handlers. Until this is complete, QEMU can use the emulated XIVE
device for Secure VMs, option "kernel_irqchip=off" on the QEMU pseries
machine.

Signed-off-by: Ram Pai <linuxram@us.ibm.com>
Reviewed-by: Cedric Le Goater <clg@kaod.org>
Reviewed-by: Greg Kurz <groug@kaod.org>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Link: https://lore.kernel.org/r/20200426020518.GC5853@oc0525413822.ibm.com
arch/powerpc/sysdev/xive/spapr.c

index 7ab5c67809977cab38ed0c5167f9b125218c0f71..f0551a2be9df4039c92b0e7b500f523ed101558a 100644 (file)
@@ -27,6 +27,8 @@
 #include <asm/xive.h>
 #include <asm/xive-regs.h>
 #include <asm/hvcall.h>
+#include <asm/svm.h>
+#include <asm/ultravisor.h>
 
 #include "xive-internal.h"
 
@@ -502,6 +504,9 @@ static int xive_spapr_configure_queue(u32 target, struct xive_q *q, u8 prio,
                rc = -EIO;
        } else {
                q->qpage = qpage;
+               if (is_secure_guest())
+                       uv_share_page(PHYS_PFN(qpage_phys),
+                                       1 << xive_alloc_order(order));
        }
 fail:
        return rc;
@@ -535,6 +540,8 @@ static void xive_spapr_cleanup_queue(unsigned int cpu, struct xive_cpu *xc,
                       hw_cpu, prio);
 
        alloc_order = xive_alloc_order(xive_queue_shift);
+       if (is_secure_guest())
+               uv_unshare_page(PHYS_PFN(__pa(q->qpage)), 1 << alloc_order);
        free_pages((unsigned long)q->qpage, alloc_order);
        q->qpage = NULL;
 }