qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [PATCH v2 04/19] spapr: add support for the LSI interrupt s


From: Cédric Le Goater
Subject: [Qemu-devel] [PATCH v2 04/19] spapr: add support for the LSI interrupt sources
Date: Sat, 9 Dec 2017 09:43:23 +0100

The 'sent' status of the LSI interrupt source is modeled with the 'P'
bit of the ESB and the assertion status of the source is maintained in
an array under the main sPAPRXive object. The type of the source is
stored in the same array for practical reasons.

The OS will use the H_INT_GET_SOURCE_INFO hcall to determine the type
of an interrupt source.

Signed-off-by: Cédric Le Goater <address@hidden>
---
 hw/intc/spapr_xive.c        | 54 +++++++++++++++++++++++++++++++++++++++++----
 include/hw/ppc/spapr_xive.h | 10 ++++++++-
 2 files changed, 59 insertions(+), 5 deletions(-)

diff --git a/hw/intc/spapr_xive.c b/hw/intc/spapr_xive.c
index 43df6814619d..c772c726667f 100644
--- a/hw/intc/spapr_xive.c
+++ b/hw/intc/spapr_xive.c
@@ -144,6 +144,21 @@ static bool spapr_xive_pq_trigger(sPAPRXive *xive, 
uint32_t lisn)
 }
 
 /*
+ * LSI interrupt sources use the P bit and a custom assertion flag
+ */
+static bool spapr_xive_lsi_trigger(sPAPRXive *xive, uint32_t lisn)
+{
+    uint8_t old_pq = spapr_xive_pq_get(xive, lisn);
+
+    if  (old_pq == XIVE_ESB_RESET &&
+         xive->status[lisn] & XIVE_STATUS_ASSERTED) {
+        spapr_xive_pq_set(xive, lisn, XIVE_ESB_PENDING);
+        return true;
+    }
+    return false;
+}
+
+/*
  * XIVE Interrupt Source MMIOs
  */
 
@@ -165,6 +180,14 @@ static uint64_t spapr_xive_esb_read(void *opaque, hwaddr 
addr, unsigned size)
          * XIVE_ESB_STORE_EOI support for the interrupt sources
          */
         ret = spapr_xive_pq_eoi(xive, lisn);
+
+        /* If the LSI source is still asserted, forward a new source
+         * event notification */
+        if (spapr_xive_irq_is_lsi(xive, lisn)) {
+            if (spapr_xive_lsi_trigger(xive, lisn)) {
+                spapr_xive_irq(xive, lisn);
+            }
+        }
         break;
 
     case XIVE_ESB_GET:
@@ -201,6 +224,14 @@ static void spapr_xive_esb_write(void *opaque, hwaddr addr,
          * notification
          */
         notify = spapr_xive_pq_eoi(xive, lisn);
+
+        /* LSI sources do not set the Q bit but they can still be
+         * asserted, in which case we should forward a new source
+         * event notification
+         */
+        if (spapr_xive_irq_is_lsi(xive, lisn)) {
+            notify = spapr_xive_lsi_trigger(xive, lisn);
+        }
         break;
     default:
         qemu_log_mask(LOG_GUEST_ERROR, "XIVE: invalid ESB write addr %d\n",
@@ -233,8 +264,17 @@ static void spapr_xive_source_set_irq(void *opaque, int 
lisn, int val)
     sPAPRXive *xive = SPAPR_XIVE(opaque);
     bool notify = false;
 
-    if (val) {
-        notify = spapr_xive_pq_trigger(xive, lisn);
+    if (spapr_xive_irq_is_lsi(xive, lisn)) {
+        if (val) {
+            xive->status[lisn] |= XIVE_STATUS_ASSERTED;
+        } else {
+            xive->status[lisn] &= ~XIVE_STATUS_ASSERTED;
+        }
+        notify = spapr_xive_lsi_trigger(xive, lisn);
+    } else {
+        if (val) {
+            notify = spapr_xive_pq_trigger(xive, lisn);
+        }
     }
 
     /* Forward the source event notification for routing */
@@ -260,7 +300,8 @@ void spapr_xive_pic_print_info(sPAPRXive *xive, Monitor 
*mon)
 
         pq = spapr_xive_pq_get(xive, i);
 
-        monitor_printf(mon, "  %4x %s %c%c %08x %08x\n", i,
+        monitor_printf(mon, "  %4x %s %s %c%c %08x %08x\n", i,
+                       spapr_xive_irq_is_lsi(xive, i) ? "LSI" : "MSI",
                        ive->w & IVE_MASKED ? "M" : " ",
                        pq & XIVE_ESB_VAL_P ? 'P' : '-',
                        pq & XIVE_ESB_VAL_Q ? 'Q' : '-',
@@ -274,6 +315,8 @@ static void spapr_xive_reset(DeviceState *dev)
     sPAPRXive *xive = SPAPR_XIVE(dev);
     int i;
 
+    /* Do not clear IRQ's status */
+
     /* Mask all valid IVEs in the IRQ number space. */
     for (i = 0; i < xive->nr_irqs; i++) {
         XiveIVE *ive = &xive->ivt[i];
@@ -301,6 +344,7 @@ static void spapr_xive_realize(DeviceState *dev, Error 
**errp)
     /* QEMU IRQs */
     xive->qirqs = qemu_allocate_irqs(spapr_xive_source_set_irq, xive,
                                      xive->nr_irqs);
+    xive->status = g_malloc0(xive->nr_irqs);
 
     /* Allocate SBEs (State Bit Entry). 2 bits, so 4 entries per byte */
     xive->sbe_size = DIV_ROUND_UP(xive->nr_irqs, 4);
@@ -381,7 +425,7 @@ XiveIVE *spapr_xive_get_ive(sPAPRXive *xive, uint32_t lisn)
     return lisn < xive->nr_irqs ? &xive->ivt[lisn] : NULL;
 }
 
-bool spapr_xive_irq_enable(sPAPRXive *xive, uint32_t lisn)
+bool spapr_xive_irq_enable(sPAPRXive *xive, uint32_t lisn, bool lsi)
 {
     XiveIVE *ive = spapr_xive_get_ive(xive, lisn);
 
@@ -390,6 +434,7 @@ bool spapr_xive_irq_enable(sPAPRXive *xive, uint32_t lisn)
     }
 
     ive->w |= IVE_VALID;
+    xive->status[lisn] |= lsi ? XIVE_STATUS_LSI : 0;
     return true;
 }
 
@@ -402,5 +447,6 @@ bool spapr_xive_irq_disable(sPAPRXive *xive, uint32_t lisn)
     }
 
     ive->w &= ~IVE_VALID;
+    xive->status[lisn] = 0;
     return true;
 }
diff --git a/include/hw/ppc/spapr_xive.h b/include/hw/ppc/spapr_xive.h
index ecc15d889b74..a7e59fd601d7 100644
--- a/include/hw/ppc/spapr_xive.h
+++ b/include/hw/ppc/spapr_xive.h
@@ -23,6 +23,9 @@ struct sPAPRXive {
 
     /* Properties */
     uint32_t     nr_irqs;
+#define XIVE_STATUS_LSI                0x1
+#define XIVE_STATUS_ASSERTED           0x2
+    uint8_t      *status;
 
     /* IRQ */
     qemu_irq     *qirqs;
@@ -37,7 +40,12 @@ struct sPAPRXive {
     MemoryRegion esb_iomem;
 };
 
-bool spapr_xive_irq_enable(sPAPRXive *xive, uint32_t lisn);
+static inline bool spapr_xive_irq_is_lsi(sPAPRXive *xive, int lisn)
+{
+    return xive->status[lisn] & XIVE_STATUS_LSI;
+}
+
+bool spapr_xive_irq_enable(sPAPRXive *xive, uint32_t lisn, bool lsi);
 bool spapr_xive_irq_disable(sPAPRXive *xive, uint32_t lisn);
 void spapr_xive_pic_print_info(sPAPRXive *xive, Monitor *mon);
 
-- 
2.13.6




reply via email to

[Prev in Thread] Current Thread [Next in Thread]