Skip to contentSkip to conversation

ppc: Add "native" POWER8 platform

PATCH In review Benjamin Herrenschmidt 11 participants 198 messages Nov 11, 2015 – Mar 17, 2017 Page 2 of 2

lore
Share & tools
lore
#93 lore raw

Re: [Qemu-devel] [Qemu-ppc] [PATCH 33/77] ppc/xics: Make the ICSState a list

In reply to Benjamin Herrenschmidt
Quoted 90 lines · Benjamin Herrenschmidt

Instead of an array of fixed sized blocks, use a list, as we will need to have sources with variable number of interrupts. SPAPR only uses a single entry. Native will create more. If performance becomes an issue we can add some hashed lookup but for now this will do fine.

---
 hw/intc/xics.c        | 86 +++++++++++++++++++++++++++++++--------------------
 hw/intc/xics_kvm.c    | 28 +++++++++--------
 hw/intc/xics_spapr.c  | 75 ++++++++++++++++++++++++--------------------
 hw/ppc/spapr_events.c |  2 +-
 hw/ppc/spapr_pci.c    |  4 +--
 hw/ppc/spapr_vio.c    |  2 +-
 include/hw/ppc/xics.h | 10 +++---
 7 files changed, 118 insertions(+), 89 deletions(-)
hw/intc/xics.c +13 -9
index d21471f..c4ac057 100644
@@ -79,13 +79,16 @@ void xics_cpu_setup(XICSState *xics, PowerPCCPU *cpu)
 static void xics_common_reset(DeviceState *d)
 {
     XICSState *xics = XICS_COMMON(d);
+    ICSState *ics;
     int i;
 
     for (i = 0; i < xics->nr_servers; i++) {
         device_reset(DEVICE(&xics->ss[i]));
     }
 
-    device_reset(DEVICE(xics->ics));
+    QLIST_FOREACH(ics, &xics->ics, list) {
+        device_reset(DEVICE(ics));
+    }
 }
 
 static void xics_prop_get_nr_irqs(Object *obj, Visitor *v,
@@ -117,7 +120,6 @@ static void xics_prop_set_nr_irqs(Object *obj, Visitor *v,
     }
 
     assert(info->set_nr_irqs);
-    assert(xics->ics);
     info->set_nr_irqs(xics, value, errp);
 }
 
@@ -195,33 +197,35 @@ static void ics_reject(ICSState *ics, int nr);
 static void ics_resend(ICSState *ics);
 static void ics_eoi(ICSState *ics, int nr);
 
-static void icp_check_ipi(XICSState *xics, int server)
+static void icp_check_ipi(ICPState *ss, int server)
 {
-    ICPState *ss = xics->ss + server;
-
     if (XISR(ss) && (ss->pending_priority <= ss->mfrr)) {
         return;
     }
 
     trace_xics_icp_check_ipi(server, ss->mfrr);
 
-    if (XISR(ss)) {
-        ics_reject(xics->ics, XISR(ss));
+    if (XISR(ss) && ss->xirr_owner) {
+        ics_reject(ss->xirr_owner, XISR(ss));
     }
 
     ss->xirr = (ss->xirr & ~XISR_MASK) | XICS_IPI;
     ss->pending_priority = ss->mfrr;
+    ss->xirr_owner = NULL;
     qemu_irq_raise(ss->output);
 }
 
 static void icp_resend(XICSState *xics, int server)
 {
     ICPState *ss = xics->ss + server;
+    ICSState *ics;
 
     if (ss->mfrr < CPPR(ss)) {
-        icp_check_ipi(xics, server);
+        icp_check_ipi(ss, server);
+    }
+    QLIST_FOREACH(ics, &xics->ics, list) {
+        ics_resend(ics);
     }
-    ics_resend(xics->ics);
 }
 
 void icp_set_cppr(XICSState *xics, int server, uint8_t cppr)

hw/intc/xics.c void icp_set_cppr(XICSState *xics, int server, uint8_t cppr) · line 249

Quoted 8 lines
hw/intc/xics.c +4 -1
@@ -239,7 +243,10 @@ void icp_set_cppr(XICSState *xics, int server, uint8_t cppr)
             ss->xirr &= ~XISR_MASK; /* Clear XISR */
             ss->pending_priority = 0xff;
             qemu_irq_lower(ss->output);
-            ics_reject(xics->ics, old_xisr);
+            if (ss->xirr_owner) {
+                ics_reject(ss->xirr_owner, old_xisr);
+                ss->xirr_owner = NULL;
+            }

To match the layour of the rest of things, this little fragment should probably go into an icp_reject() function.

Quoted 48 lines
hw/intc/xics.c +12 -3
         }
     } else {
         if (!XISR(ss)) {
@@ -254,7 +261,7 @@ void icp_set_mfrr(XICSState *xics, int server, uint8_t mfrr)
 
     ss->mfrr = mfrr;
     if (mfrr < CPPR(ss)) {
-        icp_check_ipi(xics, server);
+        icp_check_ipi(ss, server);
     }
 }
 
@@ -265,6 +272,7 @@ uint32_t icp_accept(ICPState *ss)
     qemu_irq_lower(ss->output);
     ss->xirr = ss->pending_priority << 24;
     ss->pending_priority = 0xff;
+    ss->xirr_owner = NULL;
 
     trace_xics_icp_accept(xirr, ss->xirr);
 
@@ -282,30 +290,40 @@ uint32_t icp_ipoll(ICPState *ss, uint32_t *mfrr)
 void icp_eoi(XICSState *xics, int server, uint32_t xirr)
 {
     ICPState *ss = xics->ss + server;
+    ICSState *ics;
+    uint32_t irq;
 
     /* Send EOI -> ICS */
     ss->xirr = (ss->xirr & ~CPPR_MASK) | (xirr & CPPR_MASK);
     trace_xics_icp_eoi(server, xirr, ss->xirr);
-    ics_eoi(xics->ics, xirr & XISR_MASK);
+    irq = xirr & XISR_MASK;
+    QLIST_FOREACH(ics, &xics->ics, list) {
+        if (ics_valid_irq(ics, irq)) {
+            ics_eoi(ics, irq);
+        }
+    }
     if (!XISR(ss)) {
         icp_resend(xics, server);
     }
 }
 
-static void icp_irq(XICSState *xics, int server, int nr, uint8_t priority)
+static void icp_irq(ICSState *ics, int server, int nr, uint8_t priority)
 {
+    XICSState *xics = ics->xics;
     ICPState *ss = xics->ss + server;
 

hw/intc/xics.c uint32_t icp_ipoll(ICPState *ss, uint32_t *mfrr) · line 321

Quoted 10 lines
hw/intc/xics.c +2 -3
     trace_xics_icp_irq(server, nr, priority);
 
     if ((priority >= CPPR(ss))
         || (XISR(ss) && (ss->pending_priority <= priority))) {
-        ics_reject(xics->ics, nr);
+        ics_reject(ics, nr);
     } else {
-        if (XISR(ss)) {
-            ics_reject(xics->ics, XISR(ss));
+        if (XISR(ss) && ss->xirr_owner) {

I'm guessing the only case where we should get XISR(ss) && !ss->xirr_owner will be an IPI, is that right?

Quoted 82 lines
hw/intc/xics.c +14 -17
+            ics_reject(ss->xirr_owner, XISR(ss));
+            ss->xirr_owner = NULL;
         }
         ss->xirr = (ss->xirr & ~XISR_MASK) | (nr & XISR_MASK);
+        ss->xirr_owner = ics;
         ss->pending_priority = priority;
         trace_xics_icp_raise(ss->xirr, ss->pending_priority);
         qemu_irq_raise(ss->output);
@@ -388,8 +406,7 @@ static void resend_msi(ICSState *ics, int srcno)
     if (irq->status & XICS_STATUS_REJECTED) {
         irq->status &= ~XICS_STATUS_REJECTED;
         if (irq->priority != 0xff) {
-            icp_irq(ics->xics, irq->server, srcno + ics->offset,
-                    irq->priority);
+            icp_irq(ics, irq->server, srcno + ics->offset, irq->priority);
         }
     }
 }
@@ -402,7 +419,7 @@ static void resend_lsi(ICSState *ics, int srcno)
         && (irq->status & XICS_STATUS_ASSERTED)
         && !(irq->status & XICS_STATUS_SENT)) {
         irq->status |= XICS_STATUS_SENT;
-        icp_irq(ics->xics, irq->server, srcno + ics->offset, irq->priority);
+        icp_irq(ics, irq->server, srcno + ics->offset, irq->priority);
     }
 }
 
@@ -417,7 +434,7 @@ static void set_irq_msi(ICSState *ics, int srcno, int val)
             irq->status |= XICS_STATUS_MASKED_PENDING;
             trace_xics_masked_pending();
         } else  {
-            icp_irq(ics->xics, irq->server, srcno + ics->offset, irq->priority);
+            icp_irq(ics, irq->server, srcno + ics->offset, irq->priority);
         }
     }
 }
@@ -456,7 +473,7 @@ static void write_xive_msi(ICSState *ics, int srcno)
     }
 
     irq->status &= ~XICS_STATUS_MASKED_PENDING;
-    icp_irq(ics->xics, irq->server, srcno + ics->offset, irq->priority);
+    icp_irq(ics, irq->server, srcno + ics->offset, irq->priority);
 }
 
 static void write_xive_lsi(ICSState *ics, int srcno)
@@ -642,28 +659,23 @@ static const TypeInfo ics_info = {
 /*
  * Exported functions
  */
-int xics_find_source(XICSState *xics, int irq)
+ICSState *xics_find_source(XICSState *xics, int irq)
 {
-    int sources = 1;
-    int src;
+    ICSState *ics;
 
-    /* FIXME: implement multiple sources */
-    for (src = 0; src < sources; ++src) {
-        ICSState *ics = &xics->ics[src];
+    QLIST_FOREACH(ics, &xics->ics, list) {
         if (ics_valid_irq(ics, irq)) {
-            return src;
+            return ics;
         }
     }
-
-    return -1;
+    return NULL;
 }
 
 qemu_irq xics_get_qirq(XICSState *xics, int irq)
 {
-    int src = xics_find_source(xics, irq);
+    ICSState *ics = xics_find_source(xics, irq);
 
-    if (src >= 0) {
-        ICSState *ics = &xics->ics[src];
+    if (ics) {
         return ics->qirqs[irq - ics->offset];
     }
 

hw/intc/xics.c void ics_set_irq_type(ICSState *ics, int srcno, bool lsi) · line 701

Quoted 7 lines
hw/intc/xics.c +3 -1
@@ -684,7 +696,13 @@ void ics_set_irq_type(ICSState *ics, int srcno, bool lsi)
 
 void xics_set_nr_irqs(XICSState *xics, uint32_t nr_irqs, Error **errp)
 {
-    xics->nr_irqs = xics->ics->nr_irqs = nr_irqs;
+    ICSState *ics = QLIST_FIRST(&xics->ics);
+
+    /* This needs to be deprecated ... */

Yeah..

I can't even remember what this was really for. We probably need to move it to a property on the ics objects, with a backwards compat shim for PAPR to copy the xics "master" object value to the single ics.

Quoted 67 lines
hw/intc/xics.c +4 -0
+    xics->nr_irqs = nr_irqs;
+    if (ics) {
+        ics->nr_irqs = nr_irqs;
+    }
 }
 
 void xics_set_nr_servers(XICSState *xics, uint32_t nr_servers, Error **errp)
hw/intc/xics_kvm.c +14 -12
index 7d86157..a478d25 100644
@@ -356,11 +356,6 @@ static void xics_kvm_cpu_setup(XICSState *xics, PowerPCCPU *cpu)
     }
 }
 
-static void xics_kvm_set_nr_irqs(XICSState *xics, uint32_t nr_irqs, Error **errp)
-{
-    xics->nr_irqs = xics->ics->nr_irqs = nr_irqs;
-}
-
 static void xics_kvm_set_nr_servers(XICSState *xics, uint32_t nr_servers,
                                     Error **errp)
 {
@@ -391,6 +386,7 @@ static void xics_kvm_realize(DeviceState *dev, Error **errp)
 {
     KVMXICSState *xicskvm = KVM_XICS(dev);
     XICSState *xics = XICS_COMMON(dev);
+    ICSState *ics;
     int i, rc;
     Error *error = NULL;
     struct kvm_create_device xics_create_device = {
@@ -442,10 +438,12 @@ static void xics_kvm_realize(DeviceState *dev, Error **errp)
 
     xicskvm->kernel_xics_fd = xics_create_device.fd;
 
-    object_property_set_bool(OBJECT(xics->ics), true, "realized", &error);
-    if (error) {
-        error_propagate(errp, error);
-        goto fail;
+    QLIST_FOREACH(ics, &xics->ics, list) {
+        object_property_set_bool(OBJECT(ics), true, "realized", &error);
+        if (error) {
+            error_propagate(errp, error);
+            goto fail;
+        }
     }
 
     assert(xics->nr_servers);
@@ -473,10 +471,14 @@ fail:
 static void xics_kvm_initfn(Object *obj)
 {
     XICSState *xics = XICS_COMMON(obj);
+    ICSState *ics;
+
+    QLIST_INIT(&xics->ics);
 
-    xics->ics = ICS(object_new(TYPE_KVM_ICS));
-    object_property_add_child(obj, "ics", OBJECT(xics->ics), NULL);
-    xics->ics->xics = xics;
+    ics = ICS(object_new(TYPE_KVM_ICS));
+    object_property_add_child(obj, "ics", OBJECT(ics), NULL);
+    ics->xics = xics;
+    QLIST_INSERT_HEAD(&xics->ics, ics, list);
 }
 
 static void xics_kvm_class_init(ObjectClass *oc, void *data)

hw/intc/xics_kvm.c static void xics_kvm_class_init(ObjectClass *oc, void *data) · line 491

Quoted 5 lines
hw/intc/xics_kvm.c +1 -1
@@ -486,7 +488,7 @@ static void xics_kvm_class_init(ObjectClass *oc, void *data)
 
     dc->realize = xics_kvm_realize;
     xsc->cpu_setup = xics_kvm_cpu_setup;
-    xsc->set_nr_irqs = xics_kvm_set_nr_irqs;
+    xsc->set_nr_irqs = xics_set_nr_irqs;

Wow.. why were xics_kvm_set_nr_irqs and xics_set_nr_irqs ever separate, I wonder.

Quoted 10 lines
hw/intc/xics_kvm.c +0 -0
     xsc->set_nr_servers = xics_kvm_set_nr_servers;
 }
 
hw/intc/xics_spapr.c +0 -0
index fb508cd..d75fcf0 100644
@@ -111,10 +111,10 @@ static void rtas_set_xive(PowerPCCPU *cpu, sPAPRMachineState *spapr,
                           uint32_t nargs, target_ulong args,
                           uint32_t nret, target_ulong rets)

hw/intc/xics_spapr.c static void rtas_set_xive(PowerPCCPU *cpu, sPAPRMachineState *spapr, · line 120

Quoted 10 lines
hw/intc/xics_spapr.c +2 -2
 {
-    ICSState *ics = spapr->xics->ics;
+    ICSState *ics = QLIST_FIRST(&spapr->xics->ics);
     uint32_t nr, server, priority;
 
-    if ((nargs != 3) || (nret != 1)) {
+    if ((nargs != 3) || (nret != 1) || !ics) {
         rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
         return;
     }

!ics should probably be a HW_ERROR (or even an assert).

Quoted 107 lines
hw/intc/xics_spapr.c +26 -17
@@ -139,10 +139,10 @@ static void rtas_get_xive(PowerPCCPU *cpu, sPAPRMachineState *spapr,
                           uint32_t nargs, target_ulong args,
                           uint32_t nret, target_ulong rets)
 {
-    ICSState *ics = spapr->xics->ics;
+    ICSState *ics = QLIST_FIRST(&spapr->xics->ics);
     uint32_t nr;
 
-    if ((nargs != 1) || (nret != 3)) {
+    if ((nargs != 1) || (nret != 3) || !ics) {
         rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
         return;
     }
@@ -164,10 +164,10 @@ static void rtas_int_off(PowerPCCPU *cpu, sPAPRMachineState *spapr,
                          uint32_t nargs, target_ulong args,
                          uint32_t nret, target_ulong rets)
 {
-    ICSState *ics = spapr->xics->ics;
+    ICSState *ics = QLIST_FIRST(&spapr->xics->ics);
     uint32_t nr;
 
-    if ((nargs != 1) || (nret != 1)) {
+    if ((nargs != 1) || (nret != 1) || !ics) {
         rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
         return;
     }
@@ -190,10 +190,10 @@ static void rtas_int_on(PowerPCCPU *cpu, sPAPRMachineState *spapr,
                         uint32_t nargs, target_ulong args,
                         uint32_t nret, target_ulong rets)
 {
-    ICSState *ics = spapr->xics->ics;
+    ICSState *ics = QLIST_FIRST(&spapr->xics->ics);
     uint32_t nr;
 
-    if ((nargs != 1) || (nret != 1)) {
+    if ((nargs != 1) || (nret != 1) || !ics) {
         rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
         return;
     }
@@ -215,6 +215,7 @@ static void rtas_int_on(PowerPCCPU *cpu, sPAPRMachineState *spapr,
 static void xics_spapr_realize(DeviceState *dev, Error **errp)
 {
     XICSState *xics = XICS(dev);
+    ICSState *ics;
     Error *error = NULL;
     int i;
 
@@ -236,10 +237,12 @@ static void xics_spapr_realize(DeviceState *dev, Error **errp)
     spapr_register_hypercall(H_EOI, h_eoi);
     spapr_register_hypercall(H_IPOLL, h_ipoll);
 
-    object_property_set_bool(OBJECT(xics->ics), true, "realized", &error);
-    if (error) {
-        error_propagate(errp, error);
-        return;
+    QLIST_FOREACH(ics, &xics->ics, list) {
+        object_property_set_bool(OBJECT(ics), true, "realized", &error);
+        if (error) {
+            error_propagate(errp, error);
+            return;
+        }
     }
 
     for (i = 0; i < xics->nr_servers; i++) {
@@ -254,10 +257,14 @@ static void xics_spapr_realize(DeviceState *dev, Error **errp)
 static void xics_spapr_initfn(Object *obj)
 {
     XICSState *xics = XICS(obj);
+    ICSState *ics;
+
+    QLIST_INIT(&xics->ics);
 
-    xics->ics = ICS(object_new(TYPE_ICS));
-    object_property_add_child(obj, "ics", OBJECT(xics->ics), NULL);
-    xics->ics->xics = xics;
+    ics = ICS(object_new(TYPE_ICS));    
+    object_property_add_child(obj, "ics", OBJECT(ics), NULL);
+    ics->xics = xics;
+    QLIST_INSERT_HEAD(&xics->ics, ics, list);
 }
 
 static void xics_spapr_class_init(ObjectClass *oc, void *data)
@@ -303,29 +310,31 @@ static int ics_find_free_block(ICSState *ics, int num, int alignnum)
     return -1;
 }
 
-int xics_spapr_alloc(XICSState *xics, int src, int irq_hint, bool lsi)
+int xics_spapr_alloc(XICSState *xics, int irq_hint, bool lsi)
 {
-    ICSState *ics = &xics->ics[src];
+    ICSState *ics = QLIST_FIRST(&xics->ics);
     int irq;
 
+    if (!ics) {
+        return -1;
+    }
     if (irq_hint) {
-        assert(src == xics_find_source(xics, irq_hint));
         if (!ICS_IRQ_FREE(ics, irq_hint - ics->offset)) {
-            trace_xics_alloc_failed_hint(src, irq_hint);
+            trace_xics_alloc_failed_hint(0, irq_hint);
             return -1;
         }
         irq = irq_hint;
     } else {
         irq = ics_find_free_block(ics, 1, 1);
         if (irq < 0) {

hw/intc/xics_spapr.c static int ics_find_free_block(ICSState *ics, int num, int alignnum) · line 337

Quoted 10 lines
hw/intc/xics_spapr.c +2 -2
-            trace_xics_alloc_failed_no_left(src);
+            trace_xics_alloc_failed_no_left(0);
             return -1;
         }
         irq += ics->offset;
     }
 
     ics_set_irq_type(ics, irq - ics->offset, lsi);
-    trace_xics_alloc(src, irq);
+    trace_xics_alloc(0, irq);

Actually we should really deprecate xics_spapr_alloc(). I hadn't realised it at the time, but dynamically allocating resources like this is a PITA for migration and cross-version compatibility. So we should avoid it, instead having the caller explicitly assign numbers based on explicit parameters.

Quoted 120 lines
hw/intc/xics_spapr.c +11 -13
     return irq;
 }
@@ -334,12 +343,15 @@ int xics_spapr_alloc(XICSState *xics, int src, int irq_hint, bool lsi)
  * Allocate block of consecutive IRQs, and return the number of the first IRQ in the block.
  * If align==true, aligns the first IRQ number to num.
  */
-int xics_spapr_alloc_block(XICSState *xics, int src, int num, bool lsi, bool align)
+int xics_spapr_alloc_block(XICSState *xics, int num, bool lsi, bool align)
 {
+    ICSState *ics = QLIST_FIRST(&xics->ics);
     int i, first = -1;
-    ICSState *ics = &xics->ics[src];
 
-    assert(src == 0);
+    if (!ics) {
+        return -1;
+    }
+
     /*
      * MSIMesage::data is used for storing VIRQ so
      * it has to be aligned to num to support multiple
@@ -362,7 +374,7 @@ int xics_spapr_alloc_block(XICSState *xics, int src, int num, bool lsi, bool ali
     }
     first += ics->offset;
 
-    trace_xics_alloc_block(src, first, num, lsi, align);
+    trace_xics_alloc_block(0, first, num, lsi, align);
 
     return first;
 }
@@ -373,7 +385,7 @@ static void ics_free(ICSState *ics, int srcno, int num)
 
     for (i = srcno; i < srcno + num; ++i) {
         if (ICS_IRQ_FREE(ics, i)) {
-            trace_xics_ics_free_warn(ics - ics->xics->ics, i + ics->offset);
+            trace_xics_ics_free_warn(0, i + ics->offset);
         }
         memset(&ics->irqs[i], 0, sizeof(ICSIRQState));
     }
@@ -381,15 +393,10 @@ static void ics_free(ICSState *ics, int srcno, int num)
 
 void xics_spapr_free(XICSState *xics, int irq, int num)
 {
-    int src = xics_find_source(xics, irq);
-
-    if (src >= 0) {
-        ICSState *ics = &xics->ics[src];
-
-        /* FIXME: implement multiple sources */
-        assert(src == 0);
+    ICSState *ics = xics_find_source(xics, irq);
 
-        trace_xics_ics_free(ics - xics->ics, irq, num);
+    if (ics) {
+        trace_xics_ics_free(0, irq, num);
         ics_free(ics, irq - ics->offset, num);
     }
 }
hw/ppc/spapr_events.c +1 -1
index c06deea..6335ead 100644
@@ -587,7 +587,7 @@ out_no_events:
 void spapr_events_init(sPAPRMachineState *spapr)
 {
     QTAILQ_INIT(&spapr->pending_events);
-    spapr->check_exception_irq = xics_spapr_alloc(spapr->xics, 0, 0, false);
+    spapr->check_exception_irq = xics_spapr_alloc(spapr->xics, 0, false);
     spapr->epow_notifier.notify = spapr_powerdown_req;
     qemu_register_powerdown_notifier(&spapr->epow_notifier);
     spapr_rtas_register(RTAS_CHECK_EXCEPTION, "check-exception",
hw/ppc/spapr_pci.c +2 -2
index cf3192e..9b13f85 100644
@@ -351,7 +351,7 @@ static void rtas_ibm_change_msi(PowerPCCPU *cpu, sPAPRMachineState *spapr,
     }
 
     /* Allocate MSIs */
-    irq = xics_spapr_alloc_block(spapr->xics, 0, req_num, false,
+    irq = xics_spapr_alloc_block(spapr->xics, req_num, false,
                            ret_intr_type == RTAS_TYPE_MSI);
     if (!irq) {
         error_report("Cannot allocate MSIs for device %x", config_addr);
@@ -1360,7 +1360,7 @@ static void spapr_phb_realize(DeviceState *dev, Error **errp)
     for (i = 0; i < PCI_NUM_PINS; i++) {
         uint32_t irq;
 
-        irq = xics_spapr_alloc_block(spapr->xics, 0, 1, true, false);
+        irq = xics_spapr_alloc_block(spapr->xics, 1, true, false);
         if (!irq) {
             error_setg(errp, "spapr_allocate_lsi failed");
             return;
hw/ppc/spapr_vio.c +1 -1
index fc731eb..1a84815 100644
@@ -462,7 +462,7 @@ static void spapr_vio_busdev_realize(DeviceState *qdev, Error **errp)
         dev->qdev.id = id;
     }
 
-    dev->irq = xics_spapr_alloc(spapr->xics, 0, dev->irq, false);
+    dev->irq = xics_spapr_alloc(spapr->xics, dev->irq, false);
     if (!dev->irq) {
         error_setg(errp, "can't allocate IRQ");
         return;
include/hw/ppc/xics.h +1 -1
index e670e89..12fc584 100644
@@ -79,7 +79,7 @@ struct XICSState {
     uint32_t nr_servers;
     uint32_t nr_irqs;
     ICPState *ss;
-    ICSState *ics;
+    QLIST_HEAD(, ICSState) ics;
 };
 
 #define TYPE_ICP "icp"

include/hw/ppc/xics.h struct ICPState { · line 108

Quoted 4 lines
include/hw/ppc/xics.h +1 -0
@@ -105,6 +105,7 @@ struct ICPState {
     DeviceState parent_obj;
     /*< public >*/
     CPUState *cs;
+    ICSState *xirr_owner;

Currently xirr_owner will be lost across migration, which will break things.

Am I right in thinking that it's basically an optimization, and could be reconstructed from the XISR value and list of ICS ranges? If so we can do that easily enough in a post_load function.

Quoted 30 lines
include/hw/ppc/xics.h +4 -3
     uint32_t xirr;
     uint8_t pending_priority;
     uint8_t mfrr;
@@ -139,6 +140,7 @@ struct ICSState {
     qemu_irq *qirqs;
     ICSIRQState *irqs;
     XICSState *xics;
+    QLIST_ENTRY(ICSState) list;
 };
 
 static inline bool ics_valid_irq(ICSState *ics, uint32_t nr)
@@ -167,8 +169,8 @@ struct ICSIRQState {
 
 qemu_irq xics_get_qirq(XICSState *icp, int irq);
 
-int xics_spapr_alloc(XICSState *icp, int src, int irq_hint, bool lsi);
-int xics_spapr_alloc_block(XICSState *icp, int src, int num, bool lsi, bool align);
+int xics_spapr_alloc(XICSState *icp, int irq_hint, bool lsi);
+int xics_spapr_alloc_block(XICSState *icp, int num, bool lsi, bool align);
 void xics_spapr_free(XICSState *icp, int irq, int num);
 
 void xics_cpu_setup(XICSState *icp, PowerPCCPU *cpu);
@@ -189,6 +191,6 @@ void ics_set_irq_type(ICSState *ics, int srcno, bool lsi);
 
 void xics_set_nr_irqs(XICSState *icp, uint32_t nr_irqs, Error **errp);
 void xics_set_nr_servers(XICSState *icp, uint32_t nr_servers, Error **errp);
-int xics_find_source(XICSState *icp, int irq);
+ICSState *xics_find_source(XICSState *icp, int irq);
 
 #endif /* __XICS_H__ */
Signature · 4 lines
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson
#94 lore raw

PATCH 34/77 ppc/xics: An ICS with offset 0 is assumed to be uninitialized

In reply to Benjamin Herrenschmidt

This will make life easier for dealing with dynamically configured ICSes such as PHB3

---
 include/hw/ppc/xics.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
include/hw/ppc/xics.h +1 -1
index 12fc584..51a63cb 100644
@@ -145,7 +145,7 @@ struct ICSState {
 
 static inline bool ics_valid_irq(ICSState *ics, uint32_t nr)
 {
-    return (nr >= ics->offset)
+    return (ics->offset != 0) && (nr >= ics->offset)
         && (nr < (ics->offset + ics->nr_irqs));
 }
 
Signature · 1 line
2.5.0
Reviewed-by on v1 34/77
#95 lore raw

Re: [Qemu-devel] [Qemu-ppc] [PATCH 34/77] ppc/xics: An ICS with offset 0 is assumed to be uninitialized

Quoted 4 lines · Benjamin Herrenschmidt

This will make life easier for dealing with dynamically configured ICSes such as PHB3

Quoted 17 lines
---
 include/hw/ppc/xics.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
include/hw/ppc/xics.h +1 -1
index 12fc584..51a63cb 100644
@@ -145,7 +145,7 @@ struct ICSState {
 
 static inline bool ics_valid_irq(ICSState *ics, uint32_t nr)
 {
-    return (nr >= ics->offset)
+    return (ics->offset != 0) && (nr >= ics->offset)
         && (nr < (ics->offset + ics->nr_irqs));
 }
 
Signature · 4 lines
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson
#96 lore raw

PATCH 35/77 ppc/xics: Move xics_set_nr_irqs() to xics_spapr.c and xics_kvm.c

In reply to Benjamin Herrenschmidt

It will not be used by the native implementation. This allows us to also remove the include of spapr.h from the common code

---
 hw/intc/xics.c        | 12 ------------
 hw/intc/xics_kvm.c    | 13 ++++++++++++-
 hw/intc/xics_spapr.c  | 13 ++++++++++++-
 include/hw/ppc/xics.h |  1 -
 4 files changed, 24 insertions(+), 15 deletions(-)
hw/intc/xics.c +0 -12
index c4ac057..0c355f4 100644
@@ -28,7 +28,6 @@
 #include "hw/hw.h"
 #include "trace.h"
 #include "qemu/timer.h"
-#include "hw/ppc/spapr.h"
 #include "hw/ppc/xics.h"
 #include "qemu/error-report.h"
 #include "qapi/visitor.h"
@@ -694,17 +693,6 @@ void ics_set_irq_type(ICSState *ics, int srcno, bool lsi)
  * XICS
  */
 
-void xics_set_nr_irqs(XICSState *xics, uint32_t nr_irqs, Error **errp)
-{
-    ICSState *ics = QLIST_FIRST(&xics->ics);
-
-    /* This needs to be deprecated ... */
-    xics->nr_irqs = nr_irqs;
-    if (ics) {
-        ics->nr_irqs = nr_irqs;
-    }
-}
-
 void xics_set_nr_servers(XICSState *xics, uint32_t nr_servers, Error **errp)
 {
     int i;
hw/intc/xics_kvm.c +12 -1
index a478d25..6fbc715 100644
@@ -468,6 +468,17 @@ fail:
     kvmppc_define_rtas_kernel_token(0, "ibm,int-off");
 }
 
+static void xics_kvm_set_nr_irqs(XICSState *xics, uint32_t nr_irqs, Error **errp)
+{
+    ICSState *ics = QLIST_FIRST(&xics->ics);
+
+    /* This needs to be deprecated ... */
+    xics->nr_irqs = nr_irqs;
+    if (ics) {
+        ics->nr_irqs = nr_irqs;
+    }
+}
+
 static void xics_kvm_initfn(Object *obj)
 {
     XICSState *xics = XICS_COMMON(obj);
@@ -488,7 +499,7 @@ static void xics_kvm_class_init(ObjectClass *oc, void *data)
 
     dc->realize = xics_kvm_realize;
     xsc->cpu_setup = xics_kvm_cpu_setup;
-    xsc->set_nr_irqs = xics_set_nr_irqs;
+    xsc->set_nr_irqs = xics_kvm_set_nr_irqs;
     xsc->set_nr_servers = xics_kvm_set_nr_servers;
 }
 
hw/intc/xics_spapr.c +12 -1
index d75fcf0..3092f8d 100644
@@ -267,13 +267,24 @@ static void xics_spapr_initfn(Object *obj)
     QLIST_INSERT_HEAD(&xics->ics, ics, list);
 }
 
+static void xics_spapr_set_nr_irqs(XICSState *xics, uint32_t nr_irqs, Error **errp)
+{
+    ICSState *ics = QLIST_FIRST(&xics->ics);
+
+    /* This needs to be deprecated ... */
+    xics->nr_irqs = nr_irqs;
+    if (ics) {
+        ics->nr_irqs = nr_irqs;
+    }
+}
+
 static void xics_spapr_class_init(ObjectClass *oc, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(oc);
     XICSStateClass *xsc = XICS_SPAPR_CLASS(oc);
 
     dc->realize = xics_spapr_realize;
-    xsc->set_nr_irqs = xics_set_nr_irqs;
+    xsc->set_nr_irqs = xics_spapr_set_nr_irqs;
     xsc->set_nr_servers = xics_set_nr_servers;
 }
 
include/hw/ppc/xics.h +0 -1
index 51a63cb..9e5b751 100644
@@ -189,7 +189,6 @@ void ics_write_xive(ICSState *ics, int nr, int server,
 
 void ics_set_irq_type(ICSState *ics, int srcno, bool lsi);
 
-void xics_set_nr_irqs(XICSState *icp, uint32_t nr_irqs, Error **errp);
 void xics_set_nr_servers(XICSState *icp, uint32_t nr_servers, Error **errp);
 ICSState *xics_find_source(XICSState *icp, int irq);
 
Signature · 1 line
2.5.0
#97 lore raw

Re: [Qemu-devel] [Qemu-ppc] [PATCH 35/77] ppc/xics: Move xics_set_nr_irqs() to xics_spapr.c and xics_kvm.c

Quoted 50 lines · Benjamin Herrenschmidt

It will not be used by the native implementation. This allows us to also remove the include of spapr.h from the common code

---
 hw/intc/xics.c        | 12 ------------
 hw/intc/xics_kvm.c    | 13 ++++++++++++-
 hw/intc/xics_spapr.c  | 13 ++++++++++++-
 include/hw/ppc/xics.h |  1 -
 4 files changed, 24 insertions(+), 15 deletions(-)
hw/intc/xics.c +0 -12
index c4ac057..0c355f4 100644
@@ -28,7 +28,6 @@
 #include "hw/hw.h"
 #include "trace.h"
 #include "qemu/timer.h"
-#include "hw/ppc/spapr.h"
 #include "hw/ppc/xics.h"
 #include "qemu/error-report.h"
 #include "qapi/visitor.h"
@@ -694,17 +693,6 @@ void ics_set_irq_type(ICSState *ics, int srcno, bool lsi)
  * XICS
  */
 
-void xics_set_nr_irqs(XICSState *xics, uint32_t nr_irqs, Error **errp)
-{
-    ICSState *ics = QLIST_FIRST(&xics->ics);
-
-    /* This needs to be deprecated ... */
-    xics->nr_irqs = nr_irqs;
-    if (ics) {
-        ics->nr_irqs = nr_irqs;
-    }
-}
-
 void xics_set_nr_servers(XICSState *xics, uint32_t nr_servers, Error **errp)
 {
     int i;
hw/intc/xics_kvm.c +1 -0
index a478d25..6fbc715 100644
@@ -468,6 +468,17 @@ fail:
     kvmppc_define_rtas_kernel_token(0, "ibm,int-off");
 }
 
+static void xics_kvm_set_nr_irqs(XICSState *xics, uint32_t nr_irqs, Error **errp)

hw/intc/xics_kvm.c fail: · line 481

Quoted 10 lines
hw/intc/xics_kvm.c +10 -0
+{
+    ICSState *ics = QLIST_FIRST(&xics->ics);
+
+    /* This needs to be deprecated ... */
+    xics->nr_irqs = nr_irqs;
+    if (ics) {
+        ics->nr_irqs = nr_irqs;
+    }
+}
+

Looks like you have a bit of unnecessary churn here, since you unified xics_kvm_set_nr_irqs() with xics_set_nr_irqs() earlier in the series only to split them again here.

Quoted 54 lines
hw/intc/xics_kvm.c +1 -1
 static void xics_kvm_initfn(Object *obj)
 {
     XICSState *xics = XICS_COMMON(obj);
@@ -488,7 +499,7 @@ static void xics_kvm_class_init(ObjectClass *oc, void *data)
 
     dc->realize = xics_kvm_realize;
     xsc->cpu_setup = xics_kvm_cpu_setup;
-    xsc->set_nr_irqs = xics_set_nr_irqs;
+    xsc->set_nr_irqs = xics_kvm_set_nr_irqs;
     xsc->set_nr_servers = xics_kvm_set_nr_servers;
 }
 
hw/intc/xics_spapr.c +12 -1
index d75fcf0..3092f8d 100644
@@ -267,13 +267,24 @@ static void xics_spapr_initfn(Object *obj)
     QLIST_INSERT_HEAD(&xics->ics, ics, list);
 }
 
+static void xics_spapr_set_nr_irqs(XICSState *xics, uint32_t nr_irqs, Error **errp)
+{
+    ICSState *ics = QLIST_FIRST(&xics->ics);
+
+    /* This needs to be deprecated ... */
+    xics->nr_irqs = nr_irqs;
+    if (ics) {
+        ics->nr_irqs = nr_irqs;
+    }
+}
+
 static void xics_spapr_class_init(ObjectClass *oc, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(oc);
     XICSStateClass *xsc = XICS_SPAPR_CLASS(oc);
 
     dc->realize = xics_spapr_realize;
-    xsc->set_nr_irqs = xics_set_nr_irqs;
+    xsc->set_nr_irqs = xics_spapr_set_nr_irqs;
     xsc->set_nr_servers = xics_set_nr_servers;
 }
 
include/hw/ppc/xics.h +0 -1
index 51a63cb..9e5b751 100644
@@ -189,7 +189,6 @@ void ics_write_xive(ICSState *ics, int nr, int server,
 
 void ics_set_irq_type(ICSState *ics, int srcno, bool lsi);
 
-void xics_set_nr_irqs(XICSState *icp, uint32_t nr_irqs, Error **errp);
 void xics_set_nr_servers(XICSState *icp, uint32_t nr_servers, Error **errp);
 ICSState *xics_find_source(XICSState *icp, int irq);
 
Signature · 4 lines
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson
#98 lore raw

PATCH 36/77 ppc/xics: Use a helper to add a new ICS

In reply to Benjamin Herrenschmidt
---
 hw/intc/xics.c        | 6 ++++++
 hw/intc/xics_spapr.c  | 3 +--
 include/hw/ppc/xics.h | 1 +
 3 files changed, 8 insertions(+), 2 deletions(-)
hw/intc/xics.c +6 -0
index 0c355f4..3cd696f 100644
@@ -90,6 +90,12 @@ static void xics_common_reset(DeviceState *d)
     }
 }
 
+void xics_add_ics(XICSState *xics, ICSState *ics)
+{
+    ics->xics = xics;
+    QLIST_INSERT_HEAD(&xics->ics, ics, list);
+}
+
 static void xics_prop_get_nr_irqs(Object *obj, Visitor *v,
                                   void *opaque, const char *name, Error **errp)
 {
hw/intc/xics_spapr.c +1 -2
index 3092f8d..fc331d8 100644
@@ -263,8 +263,7 @@ static void xics_spapr_initfn(Object *obj)
 
     ics = ICS(object_new(TYPE_ICS));    
     object_property_add_child(obj, "ics", OBJECT(ics), NULL);
-    ics->xics = xics;
-    QLIST_INSERT_HEAD(&xics->ics, ics, list);
+    xics_add_ics(xics, ics);
 }
 
 static void xics_spapr_set_nr_irqs(XICSState *xics, uint32_t nr_irqs, Error **errp)
include/hw/ppc/xics.h +1 -0
index 9e5b751..5acb329 100644
@@ -191,5 +191,6 @@ void ics_set_irq_type(ICSState *ics, int srcno, bool lsi);
 
 void xics_set_nr_servers(XICSState *icp, uint32_t nr_servers, Error **errp);
 ICSState *xics_find_source(XICSState *icp, int irq);
+void xics_add_ics(XICSState *xics, ICSState *ics);
 
 #endif /* __XICS_H__ */
Signature · 1 line
2.5.0
#99 lore raw

Re: [Qemu-devel] [Qemu-ppc] [PATCH 36/77] ppc/xics: Use a helper to add a new ICS

Quoted 1 line · Benjamin Herrenschmidt

Hmm.. does it make sense for the helper to do the object_new() and add_child() as well?

Quoted 48 lines
---
 hw/intc/xics.c        | 6 ++++++
 hw/intc/xics_spapr.c  | 3 +--
 include/hw/ppc/xics.h | 1 +
 3 files changed, 8 insertions(+), 2 deletions(-)
hw/intc/xics.c +6 -0
index 0c355f4..3cd696f 100644
@@ -90,6 +90,12 @@ static void xics_common_reset(DeviceState *d)
     }
 }
 
+void xics_add_ics(XICSState *xics, ICSState *ics)
+{
+    ics->xics = xics;
+    QLIST_INSERT_HEAD(&xics->ics, ics, list);
+}
+
 static void xics_prop_get_nr_irqs(Object *obj, Visitor *v,
                                   void *opaque, const char *name, Error **errp)
 {
hw/intc/xics_spapr.c +1 -2
index 3092f8d..fc331d8 100644
@@ -263,8 +263,7 @@ static void xics_spapr_initfn(Object *obj)
 
     ics = ICS(object_new(TYPE_ICS));    
     object_property_add_child(obj, "ics", OBJECT(ics), NULL);
-    ics->xics = xics;
-    QLIST_INSERT_HEAD(&xics->ics, ics, list);
+    xics_add_ics(xics, ics);
 }
 
 static void xics_spapr_set_nr_irqs(XICSState *xics, uint32_t nr_irqs, Error **errp)
include/hw/ppc/xics.h +1 -0
index 9e5b751..5acb329 100644
@@ -191,5 +191,6 @@ void ics_set_irq_type(ICSState *ics, int srcno, bool lsi);
 
 void xics_set_nr_servers(XICSState *icp, uint32_t nr_servers, Error **errp);
 ICSState *xics_find_source(XICSState *icp, int irq);
+void xics_add_ics(XICSState *xics, ICSState *ics);
 
 #endif /* __XICS_H__ */
Signature · 4 lines
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson
#100 lore raw

PATCH 37/77 ppc/xics: Split ICS into base class and "simple" implementation

In reply to Benjamin Herrenschmidt

The existing implementation becomes the "ics-simple" subclass of ICS, so there should be no change in behaviour for SPAPR.

This will allow different implementations for the source controllers such as the MSI support of PHB3 on Power8 which uses in-memory state tables for example.

---
 hw/intc/xics.c        | 123 ++++++++++++++++++++++++++++++++------------------
 hw/intc/xics_kvm.c    |   2 +-
 hw/intc/xics_spapr.c  |  34 ++++++++------
 include/hw/ppc/xics.h |  12 +++--
 4 files changed, 108 insertions(+), 63 deletions(-)
hw/intc/xics.c +79 -44
index 3cd696f..4b33e6d 100644
@@ -198,9 +198,32 @@ static const TypeInfo xics_common_info = {
 #define XISR(ss)   (((ss)->xirr) & XISR_MASK)
 #define CPPR(ss)   (((ss)->xirr) >> 24)
 
-static void ics_reject(ICSState *ics, int nr);
-static void ics_resend(ICSState *ics);
-static void ics_eoi(ICSState *ics, int nr);
+static void ics_reject(ICSState *ics, uint32_t nr)
+{
+    ICSStateClass *k = ICS_GET_CLASS(ics);
+
+    if (k->reject) {
+        k->reject(ics, nr);
+    }
+}
+
+static void ics_resend(ICSState *ics)
+{
+    ICSStateClass *k = ICS_GET_CLASS(ics);
+
+    if (k->resend) {
+        k->resend(ics);
+    }
+}
+
+static void ics_eoi(ICSState *ics, int nr)
+{
+    ICSStateClass *k = ICS_GET_CLASS(ics);
+
+    if (k->eoi) {
+        k->eoi(ics, nr);
+    }
+}
 
 static void icp_check_ipi(ICPState *ss, int server)
 {
@@ -403,7 +426,7 @@ static const TypeInfo icp_info = {
 /*
  * ICS: Source layer
  */
-static void resend_msi(ICSState *ics, int srcno)
+static void ics_simple_resend_msi(ICSState *ics, int srcno)
 {
     ICSIRQState *irq = ics->irqs + srcno;
 
@@ -416,7 +439,7 @@ static void resend_msi(ICSState *ics, int srcno)
     }
 }
 
-static void resend_lsi(ICSState *ics, int srcno)
+static void ics_simple_resend_lsi(ICSState *ics, int srcno)
 {
     ICSIRQState *irq = ics->irqs + srcno;
 
@@ -428,7 +451,7 @@ static void resend_lsi(ICSState *ics, int srcno)
     }
 }
 
-static void set_irq_msi(ICSState *ics, int srcno, int val)
+static void ics_simple_set_irq_msi(ICSState *ics, int srcno, int val)
 {
     ICSIRQState *irq = ics->irqs + srcno;
 
@@ -444,7 +467,7 @@ static void set_irq_msi(ICSState *ics, int srcno, int val)
     }
 }
 
-static void set_irq_lsi(ICSState *ics, int srcno, int val)
+static void ics_simple_set_irq_lsi(ICSState *ics, int srcno, int val)
 {
     ICSIRQState *irq = ics->irqs + srcno;
 
@@ -454,21 +477,21 @@ static void set_irq_lsi(ICSState *ics, int srcno, int val)
     } else {
         irq->status &= ~XICS_STATUS_ASSERTED;
     }
-    resend_lsi(ics, srcno);
+    ics_simple_resend_lsi(ics, srcno);
 }
 
-static void ics_set_irq(void *opaque, int srcno, int val)
+static void ics_simple_set_irq(void *opaque, int srcno, int val)
 {
     ICSState *ics = (ICSState *)opaque;
 
     if (ics->irqs[srcno].flags & XICS_FLAGS_IRQ_LSI) {
-        set_irq_lsi(ics, srcno, val);
+        ics_simple_set_irq_lsi(ics, srcno, val);
     } else {
-        set_irq_msi(ics, srcno, val);
+        ics_simple_set_irq_msi(ics, srcno, val);
     }
 }
 
-static void write_xive_msi(ICSState *ics, int srcno)
+static void ics_simple_write_xive_msi(ICSState *ics, int srcno)
 {
     ICSIRQState *irq = ics->irqs + srcno;
 
@@ -481,31 +504,30 @@ static void write_xive_msi(ICSState *ics, int srcno)
     icp_irq(ics, irq->server, srcno + ics->offset, irq->priority);
 }
 
-static void write_xive_lsi(ICSState *ics, int srcno)
+static void ics_simple_write_xive_lsi(ICSState *ics, int srcno)
 {
-    resend_lsi(ics, srcno);
+    ics_simple_resend_lsi(ics, srcno);
 }
 
-void ics_write_xive(ICSState *ics, int nr, int server,
-                    uint8_t priority, uint8_t saved_priority)
+void ics_simple_write_xive(ICSState *ics, int srcno, int server,
+                           uint8_t priority, uint8_t saved_priority)
 {
-    int srcno = nr - ics->offset;
     ICSIRQState *irq = ics->irqs + srcno;
 
     irq->server = server;
     irq->priority = priority;
     irq->saved_priority = saved_priority;
 
-    trace_xics_ics_write_xive(nr, srcno, server, priority);
+    trace_xics_ics_write_xive(ics->offset + srcno, srcno, server, priority);
 
     if (ics->irqs[srcno].flags & XICS_FLAGS_IRQ_LSI) {
-        write_xive_lsi(ics, srcno);
+        ics_simple_write_xive_lsi(ics, srcno);
     } else {
-        write_xive_msi(ics, srcno);
+        ics_simple_write_xive_msi(ics, srcno);
     }
 }
 
-static void ics_reject(ICSState *ics, int nr)
+static void ics_simple_reject(ICSState *ics, uint32_t nr)
 {
     ICSIRQState *irq = ics->irqs + nr - ics->offset;
 
@@ -514,21 +536,21 @@ static void ics_reject(ICSState *ics, int nr)
     irq->status &= ~XICS_STATUS_SENT; /* Irrelevant but harmless for MSI */
 }
 
-static void ics_resend(ICSState *ics)
+static void ics_simple_resend(ICSState *ics)
 {
     int i;
 
     for (i = 0; i < ics->nr_irqs; i++) {
         /* FIXME: filter by server#? */
         if (ics->irqs[i].flags & XICS_FLAGS_IRQ_LSI) {
-            resend_lsi(ics, i);
+            ics_simple_resend_lsi(ics, i);
         } else {
-            resend_msi(ics, i);
+            ics_simple_resend_msi(ics, i);
         }
     }
 }
 
-static void ics_eoi(ICSState *ics, int nr)
+static void ics_simple_eoi(ICSState *ics, uint32_t nr)
 {
     int srcno = nr - ics->offset;
     ICSIRQState *irq = ics->irqs + srcno;
@@ -540,9 +562,9 @@ static void ics_eoi(ICSState *ics, int nr)
     }
 }
 
-static void ics_reset(DeviceState *dev)
+static void ics_simple_reset(DeviceState *dev)
 {
-    ICSState *ics = ICS(dev);
+    ICSState *ics = ICS_SIMPLE(dev);
     int i;
     uint8_t flags[ics->nr_irqs];
 
@@ -559,7 +581,7 @@ static void ics_reset(DeviceState *dev)
     }
 }
 
-static int ics_post_load(ICSState *ics, int version_id)
+static int ics_simple_post_load(ICSState *ics, int version_id)
 {
     int i;
 
@@ -592,7 +614,7 @@ static int ics_dispatch_post_load(void *opaque, int version_id)
     return 0;
 }
 
-static const VMStateDescription vmstate_ics_irq = {
+static const VMStateDescription vmstate_ics_simple_irq = {
     .name = "ics/irq",
     .version_id = 2,
     .minimum_version_id = 1,
@@ -606,7 +628,7 @@ static const VMStateDescription vmstate_ics_irq = {
     },
 };
 
-static const VMStateDescription vmstate_ics = {
+static const VMStateDescription vmstate_ics_simple = {
     .name = "ics",
     .version_id = 1,
     .minimum_version_id = 1,
@@ -617,48 +639,60 @@ static const VMStateDescription vmstate_ics = {
         VMSTATE_UINT32_EQUAL(nr_irqs, ICSState),
 
         VMSTATE_STRUCT_VARRAY_POINTER_UINT32(irqs, ICSState, nr_irqs,
-                                             vmstate_ics_irq, ICSIRQState),
+                                             vmstate_ics_simple_irq,
+                                             ICSIRQState),
         VMSTATE_END_OF_LIST()
     },
 };
 
-static void ics_initfn(Object *obj)
+static void ics_simple_initfn(Object *obj)
 {
-    ICSState *ics = ICS(obj);
+    ICSState *ics = ICS_SIMPLE(obj);
 
     ics->offset = XICS_IRQ_BASE;
 }
 
-static void ics_realize(DeviceState *dev, Error **errp)
+static void ics_simple_realize(DeviceState *dev, Error **errp)
 {
-    ICSState *ics = ICS(dev);
+    ICSState *ics = ICS_SIMPLE(dev);
 
     if (!ics->nr_irqs) {
         error_setg(errp, "Number of interrupts needs to be greater 0");
         return;
     }
     ics->irqs = g_malloc0(ics->nr_irqs * sizeof(ICSIRQState));
-    ics->qirqs = qemu_allocate_irqs(ics_set_irq, ics, ics->nr_irqs);
+    ics->qirqs = qemu_allocate_irqs(ics_simple_set_irq, ics, ics->nr_irqs);
 }
 
-static void ics_class_init(ObjectClass *klass, void *data)
+static void ics_simple_class_init(ObjectClass *klass, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
     ICSStateClass *isc = ICS_CLASS(klass);
 
-    dc->realize = ics_realize;
-    dc->vmsd = &vmstate_ics;
-    dc->reset = ics_reset;
-    isc->post_load = ics_post_load;
+    dc->realize = ics_simple_realize;
+    dc->vmsd = &vmstate_ics_simple;
+    dc->reset = ics_simple_reset;
+    isc->post_load = ics_simple_post_load;
+    isc->reject = ics_simple_reject;
+    isc->resend = ics_simple_resend;
+    isc->eoi = ics_simple_eoi;
 }
 
+static const TypeInfo ics_simple_info = {
+    .name = TYPE_ICS_SIMPLE,
+    .parent = TYPE_ICS,
+    .instance_size = sizeof(ICSState),
+    .class_init = ics_simple_class_init,
+    .class_size = sizeof(ICSStateClass),
+    .instance_init = ics_simple_initfn,
+};
+
 static const TypeInfo ics_info = {
     .name = TYPE_ICS,
     .parent = TYPE_DEVICE,
+    .abstract = true,
     .instance_size = sizeof(ICSState),
-    .class_init = ics_class_init,
     .class_size = sizeof(ICSStateClass),
-    .instance_init = ics_initfn,
 };
 
 /*
@@ -687,7 +721,7 @@ qemu_irq xics_get_qirq(XICSState *xics, int irq)
     return NULL;
 }
 
-void ics_set_irq_type(ICSState *ics, int srcno, bool lsi)
+void ics_simple_set_irq_type(ICSState *ics, int srcno, bool lsi)
 {
     assert(!(ics->irqs[srcno].flags & XICS_FLAGS_IRQ_MASK));
 
@@ -718,6 +752,7 @@ void xics_set_nr_servers(XICSState *xics, uint32_t nr_servers, Error **errp)
 static void xics_register_types(void)
 {
     type_register_static(&xics_common_info);
+    type_register_static(&ics_simple_info);
     type_register_static(&ics_info);
     type_register_static(&icp_info);
 }
hw/intc/xics_kvm.c +1 -1
index 6fbc715..aeae68a 100644
@@ -309,7 +309,7 @@ static void ics_kvm_class_init(ObjectClass *klass, void *data)
 
 static const TypeInfo ics_kvm_info = {
     .name = TYPE_KVM_ICS,
-    .parent = TYPE_ICS,
+    .parent = TYPE_ICS_SIMPLE,
     .instance_size = sizeof(ICSState),
     .class_init = ics_kvm_class_init,
 };
hw/intc/xics_spapr.c +19 -15
index fc331d8..f7d444a 100644
@@ -112,7 +112,7 @@ static void rtas_set_xive(PowerPCCPU *cpu, sPAPRMachineState *spapr,
                           uint32_t nret, target_ulong rets)
 {
     ICSState *ics = QLIST_FIRST(&spapr->xics->ics);
-    uint32_t nr, server, priority;
+    uint32_t nr, src_no, server, priority;
 
     if ((nargs != 3) || (nret != 1) || !ics) {
         rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
@@ -129,7 +129,8 @@ static void rtas_set_xive(PowerPCCPU *cpu, sPAPRMachineState *spapr,
         return;
     }
 
-    ics_write_xive(ics, nr, server, priority, priority);
+    src_no = nr - ics->offset;
+    ics_simple_write_xive(ics, src_no, server, priority, priority);
 
     rtas_st(rets, 0, RTAS_OUT_SUCCESS);
 }
@@ -140,7 +141,7 @@ static void rtas_get_xive(PowerPCCPU *cpu, sPAPRMachineState *spapr,
                           uint32_t nret, target_ulong rets)
 {
     ICSState *ics = QLIST_FIRST(&spapr->xics->ics);
-    uint32_t nr;
+    uint32_t nr, src_no;
 
     if ((nargs != 1) || (nret != 3) || !ics) {
         rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
@@ -155,8 +156,9 @@ static void rtas_get_xive(PowerPCCPU *cpu, sPAPRMachineState *spapr,
     }
 
     rtas_st(rets, 0, RTAS_OUT_SUCCESS);
-    rtas_st(rets, 1, ics->irqs[nr - ics->offset].server);
-    rtas_st(rets, 2, ics->irqs[nr - ics->offset].priority);
+    src_no = nr - ics->offset;
+    rtas_st(rets, 1, ics->irqs[src_no].server);
+    rtas_st(rets, 2, ics->irqs[src_no].priority);
 }
 
 static void rtas_int_off(PowerPCCPU *cpu, sPAPRMachineState *spapr,
@@ -165,7 +167,7 @@ static void rtas_int_off(PowerPCCPU *cpu, sPAPRMachineState *spapr,
                          uint32_t nret, target_ulong rets)
 {
     ICSState *ics = QLIST_FIRST(&spapr->xics->ics);
-    uint32_t nr;
+    uint32_t nr, src_no;
 
     if ((nargs != 1) || (nret != 1) || !ics) {
         rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
@@ -179,8 +181,9 @@ static void rtas_int_off(PowerPCCPU *cpu, sPAPRMachineState *spapr,
         return;
     }
 
-    ics_write_xive(ics, nr, ics->irqs[nr - ics->offset].server, 0xff,
-                   ics->irqs[nr - ics->offset].priority);
+    src_no = nr - ics->offset;
+    ics_simple_write_xive(ics, src_no, ics->irqs[src_no].server, 0xff,
+                          ics->irqs[src_no].priority);
 
     rtas_st(rets, 0, RTAS_OUT_SUCCESS);
 }
@@ -191,7 +194,7 @@ static void rtas_int_on(PowerPCCPU *cpu, sPAPRMachineState *spapr,
                         uint32_t nret, target_ulong rets)
 {
     ICSState *ics = QLIST_FIRST(&spapr->xics->ics);
-    uint32_t nr;
+    uint32_t nr, src_no;
 
     if ((nargs != 1) || (nret != 1) || !ics) {
         rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
@@ -205,9 +208,10 @@ static void rtas_int_on(PowerPCCPU *cpu, sPAPRMachineState *spapr,
         return;
     }
 
-    ics_write_xive(ics, nr, ics->irqs[nr - ics->offset].server,
-                   ics->irqs[nr - ics->offset].saved_priority,
-                   ics->irqs[nr - ics->offset].saved_priority);
+    src_no = nr - ics->offset;
+    ics_simple_write_xive(ics, src_no, ics->irqs[src_no].server,
+                          ics->irqs[src_no].saved_priority,
+                          ics->irqs[src_no].saved_priority);
 
     rtas_st(rets, 0, RTAS_OUT_SUCCESS);
 }
@@ -261,7 +265,7 @@ static void xics_spapr_initfn(Object *obj)
 
     QLIST_INIT(&xics->ics);
 
-    ics = ICS(object_new(TYPE_ICS));    
+    ics = ICS(object_new(TYPE_ICS_SIMPLE));
     object_property_add_child(obj, "ics", OBJECT(ics), NULL);
     xics_add_ics(xics, ics);
 }
@@ -343,7 +347,7 @@ int xics_spapr_alloc(XICSState *xics, int irq_hint, bool lsi)
         irq += ics->offset;
     }
 
-    ics_set_irq_type(ics, irq - ics->offset, lsi);
+    ics_simple_set_irq_type(ics, irq - ics->offset, lsi);
     trace_xics_alloc(0, irq);
 
     return irq;
@@ -379,7 +383,7 @@ int xics_spapr_alloc_block(XICSState *xics, int num, bool lsi, bool align)
 
     if (first >= 0) {
         for (i = first; i < first + num; ++i) {
-            ics_set_irq_type(ics, i, lsi);
+            ics_simple_set_irq_type(ics, i, lsi);
         }
     }
     first += ics->offset;
include/hw/ppc/xics.h +9 -3
index 5acb329..93a627b 100644
@@ -116,6 +116,9 @@ struct ICPState {
 #define TYPE_ICS "ics"
 #define ICS(obj) OBJECT_CHECK(ICSState, (obj), TYPE_ICS)
 
+#define TYPE_ICS_SIMPLE "ics-simple"
+#define ICS_SIMPLE(obj) OBJECT_CHECK(ICSState, (obj), TYPE_ICS_SIMPLE)
+
 #define TYPE_KVM_ICS "icskvm"
 #define KVM_ICS(obj) OBJECT_CHECK(ICSState, (obj), TYPE_KVM_ICS)
 
@@ -129,6 +132,9 @@ struct ICSStateClass {
 
     void (*pre_save)(ICSState *s);
     int (*post_load)(ICSState *s, int version_id);
+    void (*reject)(ICSState *s, uint32_t irq);
+    void (*resend)(ICSState *s);
+    void (*eoi)(ICSState *s, uint32_t irq);
 };
 
 struct ICSState {
@@ -184,10 +190,10 @@ uint32_t icp_accept(ICPState *ss);
 uint32_t icp_ipoll(ICPState *ss, uint32_t *mfrr);
 void icp_eoi(XICSState *icp, int server, uint32_t xirr);
 
-void ics_write_xive(ICSState *ics, int nr, int server,
-                    uint8_t priority, uint8_t saved_priority);
+void ics_simple_write_xive(ICSState *ics, int nr, int server,
+                           uint8_t priority, uint8_t saved_priority);
 
-void ics_set_irq_type(ICSState *ics, int srcno, bool lsi);
+void ics_simple_set_irq_type(ICSState *ics, int srcno, bool lsi);
 
 void xics_set_nr_servers(XICSState *icp, uint32_t nr_servers, Error **errp);
 ICSState *xics_find_source(XICSState *icp, int irq);
Signature · 1 line
2.5.0
#101 lore raw

Re: [Qemu-devel] [Qemu-ppc] [PATCH 37/77] ppc/xics: Split ICS into base class and "simple" implementation

Quoted 8 lines · Benjamin Herrenschmidt

The existing implementation becomes the "ics-simple" subclass of ICS, so there should be no change in behaviour for SPAPR.

This will allow different implementations for the source controllers such as the MSI support of PHB3 on Power8 which uses in-memory state tables for example.

[snip]

hw/intc/xics_spapr.c static void rtas_set_xive(PowerPCCPU *cpu, sPAPRMachineState *spapr, · line 115

Quoted 10 lines
hw/intc/xics_spapr.c +1 -1
index fc331d8..f7d444a 100644
@@ -112,7 +112,7 @@ static void rtas_set_xive(PowerPCCPU *cpu, sPAPRMachineState *spapr,
                           uint32_t nret, target_ulong rets)
 {
     ICSState *ics = QLIST_FIRST(&spapr->xics->ics);
-    uint32_t nr, server, priority;
+    uint32_t nr, src_no, server, priority;

Nit: elsewhere I use srcno without a _ for this value.

[snip]

include/hw/ppc/xics.h struct ICPState { · line 120

Quoted 10 lines
include/hw/ppc/xics.h +2 -0
index 5acb329..93a627b 100644
@@ -116,6 +116,9 @@ struct ICPState {
 #define TYPE_ICS "ics"
 #define ICS(obj) OBJECT_CHECK(ICSState, (obj), TYPE_ICS)
 
+#define TYPE_ICS_SIMPLE "ics-simple"
+#define ICS_SIMPLE(obj) OBJECT_CHECK(ICSState, (obj), TYPE_ICS_SIMPLE)

Again, changing type names will break migration, I believe. So better to leave this as ics and add "ics-base" and "ics-native" or similar.

Quoted 28 lines
include/hw/ppc/xics.h +7 -3
+
 #define TYPE_KVM_ICS "icskvm"
 #define KVM_ICS(obj) OBJECT_CHECK(ICSState, (obj), TYPE_KVM_ICS)
 
@@ -129,6 +132,9 @@ struct ICSStateClass {
 
     void (*pre_save)(ICSState *s);
     int (*post_load)(ICSState *s, int version_id);
+    void (*reject)(ICSState *s, uint32_t irq);
+    void (*resend)(ICSState *s);
+    void (*eoi)(ICSState *s, uint32_t irq);
 };
 
 struct ICSState {
@@ -184,10 +190,10 @@ uint32_t icp_accept(ICPState *ss);
 uint32_t icp_ipoll(ICPState *ss, uint32_t *mfrr);
 void icp_eoi(XICSState *icp, int server, uint32_t xirr);
 
-void ics_write_xive(ICSState *ics, int nr, int server,
-                    uint8_t priority, uint8_t saved_priority);
+void ics_simple_write_xive(ICSState *ics, int nr, int server,
+                           uint8_t priority, uint8_t saved_priority);
 
-void ics_set_irq_type(ICSState *ics, int srcno, bool lsi);
+void ics_simple_set_irq_type(ICSState *ics, int srcno, bool lsi);
 
 void xics_set_nr_servers(XICSState *icp, uint32_t nr_servers, Error **errp);
 ICSState *xics_find_source(XICSState *icp, int irq);
Signature · 4 lines
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson
#102 lore raw

PATCH 38/77 ppc/xics: Add "native" XICS subclass

In reply to Benjamin Herrenschmidt

This provides MMIO based ICP access as found on POWER8

---
 default-configs/ppc64-softmmu.mak |   3 +-
 hw/intc/Makefile.objs             |   1 +
 hw/intc/xics_native.c             | 294 ++++++++++++++++++++++++++++++++++++++
 include/hw/ppc/xics.h             |  14 ++
 4 files changed, 311 insertions(+), 1 deletion(-)
 create mode 100644 hw/intc/xics_native.c
default-configs/ppc64-softmmu.mak +2 -1
index 516a6e2..d30176e 100644
@@ -49,8 +49,9 @@ CONFIG_PLATFORM_BUS=y
 CONFIG_ETSEC=y
 CONFIG_LIBDECNUMBER=y
 # For pSeries
-CONFIG_XICS=$(CONFIG_PSERIES)
+CONFIG_XICS=$(or $(CONFIG_PSERIES),$(CONFIG_POWERNV))
 CONFIG_XICS_SPAPR=$(CONFIG_PSERIES)
+CONFIG_XICS_NATIVE=$(CONFIG_POWERNV)
 CONFIG_XICS_KVM=$(and $(CONFIG_PSERIES),$(CONFIG_KVM))
 # For PReP
 CONFIG_MC146818RTC=y
hw/intc/Makefile.objs +1 -0
index e24cb03..104a169 100644
@@ -27,6 +27,7 @@ obj-$(CONFIG_OPENPIC_KVM) += openpic_kvm.o
 obj-$(CONFIG_SH4) += sh_intc.o
 obj-$(CONFIG_XICS) += xics.o
 obj-$(CONFIG_XICS_SPAPR) += xics_spapr.o
+obj-$(CONFIG_XICS_NATIVE) += xics_native.o
 obj-$(CONFIG_XICS_KVM) += xics_kvm.o
 obj-$(CONFIG_ALLWINNER_A10_PIC) += allwinner-a10-pic.o
 obj-$(CONFIG_S390_FLIC) += s390_flic.o
hw/intc/xics_native.c new file +294 -0

294 lines not on this page · raw message

include/hw/ppc/xics.h +14 -0
index 93a627b..f32f409 100644
@@ -38,6 +38,9 @@
 #define TYPE_XICS_SPAPR_KVM "xics-spapr-kvm"
 #define KVM_XICS(obj) OBJECT_CHECK(KVMXICSState, (obj), TYPE_XICS_SPAPR_KVM)
 
+#define TYPE_XICS_NATIVE "xics-native"
+#define XICS_NATIVE(obj) OBJECT_CHECK(XICSState, (obj), TYPE_XICS_NATIVE)
+
 #define XICS_COMMON_CLASS(klass) \
      OBJECT_CLASS_CHECK(XICSStateClass, (klass), TYPE_XICS_COMMON)
 #define XICS_SPAPR_CLASS(klass) \
@@ -46,6 +49,8 @@
      OBJECT_GET_CLASS(XICSStateClass, (obj), TYPE_XICS_COMMON)
 #define XICS_SPAPR_GET_CLASS(obj) \
      OBJECT_GET_CLASS(XICSStateClass, (obj), TYPE_XICS_SPAPR)
+#define XICS_NATIVE_CLASS(klass) \
+     OBJECT_CLASS_CHECK(XICSStateClass, (klass), TYPE_XICS_NATIVE)
 
 #define XICS_IPI        0x2
 #define XICS_BUID       0x1
@@ -80,6 +85,7 @@ struct XICSState {
     uint32_t nr_irqs;
     ICPState *ss;
     QLIST_HEAD(, ICSState) ics;
+    MemoryRegion icp_mmio;
 };
 
 #define TYPE_ICP "icp"
@@ -111,8 +117,13 @@ struct ICPState {
     uint8_t mfrr;
     qemu_irq output;
     bool cap_irq_xics_enabled;
+    uint32_t links[3];
 };
 
+/* This should be an XSCOM BAR ... the size is arbitrary as well */
+#define ICP_MM_BASE     0x0003FFFF80000000
+#define ICP_MM_SIZE     0x0000000010000000
+
 #define TYPE_ICS "ics"
 #define ICS(obj) OBJECT_CHECK(ICSState, (obj), TYPE_ICS)
 
@@ -181,6 +192,9 @@ void xics_spapr_free(XICSState *icp, int irq, int num);
 
 void xics_cpu_setup(XICSState *icp, PowerPCCPU *cpu);
 
+void xics_create_native_icp_node(XICSState *s, void *fdt,
+                                 uint32_t base, uint32_t count);
+
 /* Internal XICS interfaces */
 int get_cpu_index_by_dt_id(int cpu_dt_id);
 
Signature · 1 line
2.5.0
#103 lore raw

Re: [Qemu-devel] [Qemu-ppc] [PATCH 38/77] ppc/xics: Add "native" XICS subclass

Quoted 1 line · Benjamin Herrenschmidt

This provides MMIO based ICP access as found on POWER8

Mostly looks sound.

I note that the links registers don't actually do anything at this point, I assume thats intentional. It probably deserves a comment somewhere (in the commit message at least).

Quoted 42 lines
---
 default-configs/ppc64-softmmu.mak |   3 +-
 hw/intc/Makefile.objs             |   1 +
 hw/intc/xics_native.c             | 294 ++++++++++++++++++++++++++++++++++++++
 include/hw/ppc/xics.h             |  14 ++
 4 files changed, 311 insertions(+), 1 deletion(-)
 create mode 100644 hw/intc/xics_native.c
default-configs/ppc64-softmmu.mak +2 -1
index 516a6e2..d30176e 100644
@@ -49,8 +49,9 @@ CONFIG_PLATFORM_BUS=y
 CONFIG_ETSEC=y
 CONFIG_LIBDECNUMBER=y
 # For pSeries
-CONFIG_XICS=$(CONFIG_PSERIES)
+CONFIG_XICS=$(or $(CONFIG_PSERIES),$(CONFIG_POWERNV))
 CONFIG_XICS_SPAPR=$(CONFIG_PSERIES)
+CONFIG_XICS_NATIVE=$(CONFIG_POWERNV)
 CONFIG_XICS_KVM=$(and $(CONFIG_PSERIES),$(CONFIG_KVM))
 # For PReP
 CONFIG_MC146818RTC=y
hw/intc/Makefile.objs +1 -0
index e24cb03..104a169 100644
@@ -27,6 +27,7 @@ obj-$(CONFIG_OPENPIC_KVM) += openpic_kvm.o
 obj-$(CONFIG_SH4) += sh_intc.o
 obj-$(CONFIG_XICS) += xics.o
 obj-$(CONFIG_XICS_SPAPR) += xics_spapr.o
+obj-$(CONFIG_XICS_NATIVE) += xics_native.o
 obj-$(CONFIG_XICS_KVM) += xics_kvm.o
 obj-$(CONFIG_ALLWINNER_A10_PIC) += allwinner-a10-pic.o
 obj-$(CONFIG_S390_FLIC) += s390_flic.o
hw/intc/xics_native.c new file +0 -0
new file mode 100644
index 0000000..3f488f3

hw/intc/xics_native.c line 6

Quoted 6 lines
hw/intc/xics_native.c new file +6 -0
@@ -0,0 +1,294 @@
+/*
+ * QEMU PowerPC hardware System Emulator
+ *
+ * Native version of ICS/ICP
+ *
+ * Copyright (c) 2010,2011 David Gibson, IBM Corporation.

It should probably have your copyright too; I'm pretty sure this is not all my code ;).

Quoted 244 lines
hw/intc/xics_native.c new file +244 -0
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ */
+
+#include "hw/hw.h"
+#include "trace.h"
+#include "qemu/timer.h"
+#include "hw/ppc/xics.h"
+#include "qemu/error-report.h"
+#include "qapi/visitor.h"
+
+#include <libfdt.h>
+
+//#define DEBUG_MM(fmt...)      printf(fmt)
+#define DEBUG_MM(fmt...)        do { } while(0)
+
+static void xics_native_initfn(Object *obj)
+{
+    XICSState *xics = XICS_NATIVE(obj);
+
+    QLIST_INIT(&xics->ics);
+}
+
+static uint64_t icp_mm_read(void *opaque, hwaddr addr, unsigned width)
+{
+    XICSState *s = opaque;
+    int32_t cpu_id, server;
+    uint32_t val;
+    ICPState *ss;
+    bool byte0 = (width == 1 && (addr & 0x3) == 0);
+
+    cpu_id = (addr & (ICP_MM_SIZE - 1)) >> 12;
+    server = get_cpu_index_by_dt_id(cpu_id);
+    if (server < 0) {
+        fprintf(stderr, "XICS: Bad ICP server %d\n", server);
+        goto bad_access;
+    }
+    ss = &s->ss[server];
+
+    switch(addr & 0xffc) {
+    case 0: /* poll */
+        val = icp_ipoll(ss, NULL);
+        if (byte0) {
+            val >>= 24;
+        } else if (width != 4) {
+            goto bad_access;
+        }
+        break;
+    case 4: /* xirr */
+        if (byte0) {
+            val = icp_ipoll(ss, NULL) >> 24;
+        } else if (width == 4) {
+            val = icp_accept(ss);
+        } else {
+            goto bad_access;
+        }
+        break;
+    case 12:
+        if (byte0) {
+            val = ss->mfrr;
+        } else {
+            goto bad_access;
+        }
+        break;
+    case 16:
+        if (width == 4) {
+            val = ss->links[0];
+        } else {
+            goto bad_access;
+        }
+        break;
+    case 20:
+        if (width == 4) {
+            val = ss->links[1];
+        } else {
+            goto bad_access;
+        }
+        break;
+    case 24:
+        if (width == 4) {
+            val = ss->links[2];
+        } else {
+            goto bad_access;
+        }
+        break;
+    default:
+bad_access:
+        fprintf(stderr, "XICS: Bad ICP access %llx/%d\n",
+                (unsigned long long)addr, width);
+        val = 0xffffffff;
+    }
+    DEBUG_MM("icp_mm_read(addr=%016llx,serv=0x%x/%d,off=%d,w=%d,val=0x%08x)\n",
+             (unsigned long long)addr, cpu_id, server, (int)(addr & 0xffc),
+             width, val);
+
+    return val;
+}
+
+static void icp_mm_write(void *opaque, hwaddr addr, uint64_t val,
+                        unsigned width)
+{
+    XICSState *s = opaque;
+    int32_t cpu_id, server;
+    ICPState *ss;
+    bool byte0 = (width == 1 && (addr & 0x3) == 0);
+
+    cpu_id = (addr & (ICP_MM_SIZE - 1)) >> 12;
+    server = get_cpu_index_by_dt_id(cpu_id);
+    if (server < 0) {
+        fprintf(stderr, "XICS: Bad ICP server %d\n", server);
+        goto bad_access;
+    }
+    ss = &s->ss[server];
+
+    DEBUG_MM("icp_mm_write(addr=%016llx,serv=0x%x/%d,off=%d,w=%d,val=0x%08x)\n",
+             (unsigned long long)addr, cpu_id, server,
+             (int)(addr & 0xffc), width, (uint32_t)val);
+
+    switch(addr & 0xffc) {
+    case 4: /* xirr */
+        if (byte0) {
+            icp_set_cppr(s, server, val);
+        } else if (width == 4) {
+            icp_eoi(s, server, val);
+        } else {
+            goto bad_access;
+        }
+        break;
+    case 12:
+        if (byte0) {
+            icp_set_mfrr(s, server, val);
+        } else {
+            goto bad_access;
+        }
+        break;
+    case 16:
+        if (width == 4) {
+            ss->links[0] = val;
+        } else {
+            goto bad_access;
+        }
+        break;
+    case 20:
+        if (width == 4) {
+            ss->links[1] = val;
+        } else {
+            goto bad_access;
+        }
+        break;
+    case 24:
+        if (width == 4) {
+            ss->links[2] = val;
+        } else {
+            goto bad_access;
+        }
+        break;
+    default:
+ bad_access:
+        val = 0xffffffff;
+    }
+}
+
+static const MemoryRegionOps icp_mm_ops = {
+    .read = icp_mm_read,
+    .write = icp_mm_write,
+    .valid.min_access_size = 1,
+    .valid.max_access_size = 4,
+    .impl.min_access_size = 1,
+    .impl.max_access_size = 4,
+    .endianness = DEVICE_BIG_ENDIAN,
+};
+
+#define _FDT(exp) \
+    do { \
+        int ret = (exp);                                           \
+        if (ret < 0) {                                             \
+            fprintf(stderr, "qemu: error creating device tree: %s: %s\n", \
+                    #exp, fdt_strerror(ret));                      \
+            exit(1);                                               \
+        }                                                          \
+    } while (0)
+
+void xics_create_native_icp_node(XICSState *s, void *fdt,
+                                 uint32_t base, uint32_t count)
+{
+    uint64_t addr;
+    char *name;
+    const char compat[] = "IBM,power8-icp\0IBM,ppc-xicp";
+    uint32_t irange[2], i, rsize;
+    uint64_t *reg;
+
+    addr = ICP_MM_BASE | (base << 12);
+
+    irange[0] = cpu_to_be32(base);
+    irange[1] = cpu_to_be32(count);
+
+    rsize = sizeof(uint64_t) * 2 * count;
+    reg = g_malloc(rsize);
+    for (i = 0; i < count; i++) {
+        reg[i * 2] = cpu_to_be64(addr | ((base + i) * 0x1000));
+        reg[i * 2 + 1] = cpu_to_be64(0x1000);
+    }
+
+    name = g_strdup_printf("interrupt-controller@%"PRIX64, addr);
+
+    /* interrupt controller */
+    _FDT((fdt_begin_node(fdt, name)));
+    g_free(name);
+
+    _FDT((fdt_property(fdt, "compatible", compat, sizeof(compat))));
+    _FDT((fdt_property(fdt, "reg", reg, rsize)));
+    _FDT((fdt_property_string(fdt, "device_type",
+                              "PowerPC-External-Interrupt-Presentation")));
+    _FDT((fdt_property(fdt, "interrupt-controller", NULL, 0)));
+    _FDT((fdt_property(fdt, "ibm,interrupt-server-ranges",
+                       irange, sizeof(irange))));
+    _FDT((fdt_property_cell(fdt, "#interrupt-cells", 1)));
+    _FDT((fdt_property_cell(fdt, "#address-cells", 0)));
+    _FDT((fdt_end_node(fdt)));
+}
+
+static void xics_native_realize(DeviceState *dev, Error **errp)
+{
+    XICSState *s = XICS_NATIVE(dev);
+    SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
+    Error *error = NULL;
+    int i;
+

hw/intc/xics_native.c line 261

Quoted 10 lines
hw/intc/xics_native.c new file +10 -0
+    if (!s->nr_servers) {
+        error_setg(errp, "Number of servers needs to be greater 0");
+        return;
+    }
+
+    /* Register MMIO regions */
+    memory_region_init_io(&s->icp_mmio, OBJECT(s), &icp_mm_ops, s, "icp",
+                          ICP_MM_SIZE);
+    sysbus_init_mmio(sbd, &s->icp_mmio);
+    sysbus_mmio_map(sbd, 0, ICP_MM_BASE);

As a rule it's better to have MMIO addresses of things as a property and have the thing creating them assign it, rather than having the knowledge of the address internally.

Quoted 7 lines
hw/intc/xics_native.c new file +7 -0
+
+    for (i = 0; i < s->nr_servers; i++) {
+        object_property_set_bool(OBJECT(&s->ss[i]), true, "realized", &error);
+        if (error) {
+            error_propagate(errp, error);
+            return;
+        }

hw/intc/xics_native.c line 278

Quoted 10 lines
hw/intc/xics_native.c new file +10 -0
+    }
+}
+
+static void xics_native_class_init(ObjectClass *oc, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(oc);
+    XICSStateClass *xsc = XICS_NATIVE_CLASS(oc);
+
+    dc->realize = xics_native_realize;
+    xsc->set_nr_servers = xics_set_nr_servers;

I thought you weren't going to be using the set_nr_servers stuff in the native mode xics?

Quoted 71 lines
hw/intc/xics_native.c new file +16 -0
+}
+
+static const TypeInfo xics_native_info = {
+    .name          = TYPE_XICS_NATIVE,
+    .parent        = TYPE_XICS_COMMON,
+    .instance_size = sizeof(XICSState),
+    .class_size = sizeof(XICSStateClass),
+    .class_init    = xics_native_class_init,
+    .instance_init = xics_native_initfn,
+};
+
+static void xics_native_register_types(void)
+{
+    type_register_static(&xics_native_info);
+}
+type_init(xics_native_register_types)
include/hw/ppc/xics.h +14 -0
index 93a627b..f32f409 100644
@@ -38,6 +38,9 @@
 #define TYPE_XICS_SPAPR_KVM "xics-spapr-kvm"
 #define KVM_XICS(obj) OBJECT_CHECK(KVMXICSState, (obj), TYPE_XICS_SPAPR_KVM)
 
+#define TYPE_XICS_NATIVE "xics-native"
+#define XICS_NATIVE(obj) OBJECT_CHECK(XICSState, (obj), TYPE_XICS_NATIVE)
+
 #define XICS_COMMON_CLASS(klass) \
      OBJECT_CLASS_CHECK(XICSStateClass, (klass), TYPE_XICS_COMMON)
 #define XICS_SPAPR_CLASS(klass) \
@@ -46,6 +49,8 @@
      OBJECT_GET_CLASS(XICSStateClass, (obj), TYPE_XICS_COMMON)
 #define XICS_SPAPR_GET_CLASS(obj) \
      OBJECT_GET_CLASS(XICSStateClass, (obj), TYPE_XICS_SPAPR)
+#define XICS_NATIVE_CLASS(klass) \
+     OBJECT_CLASS_CHECK(XICSStateClass, (klass), TYPE_XICS_NATIVE)
 
 #define XICS_IPI        0x2
 #define XICS_BUID       0x1
@@ -80,6 +85,7 @@ struct XICSState {
     uint32_t nr_irqs;
     ICPState *ss;
     QLIST_HEAD(, ICSState) ics;
+    MemoryRegion icp_mmio;
 };
 
 #define TYPE_ICP "icp"
@@ -111,8 +117,13 @@ struct ICPState {
     uint8_t mfrr;
     qemu_irq output;
     bool cap_irq_xics_enabled;
+    uint32_t links[3];
 };
 
+/* This should be an XSCOM BAR ... the size is arbitrary as well */
+#define ICP_MM_BASE     0x0003FFFF80000000
+#define ICP_MM_SIZE     0x0000000010000000
+
 #define TYPE_ICS "ics"
 #define ICS(obj) OBJECT_CHECK(ICSState, (obj), TYPE_ICS)
 
@@ -181,6 +192,9 @@ void xics_spapr_free(XICSState *icp, int irq, int num);
 
 void xics_cpu_setup(XICSState *icp, PowerPCCPU *cpu);
 
+void xics_create_native_icp_node(XICSState *s, void *fdt,
+                                 uint32_t base, uint32_t count);
+
 /* Internal XICS interfaces */
 int get_cpu_index_by_dt_id(int cpu_dt_id);
 
Signature · 4 lines
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson
#104 lore raw

Re: [Qemu-devel] [Qemu-ppc] [PATCH 38/77] ppc/xics: Add "native" XICS subclass

In reply to Benjamin Herrenschmidt
Quoted 3 lines · Benjamin Herrenschmidt

This provides MMIO based ICP access as found on POWER8

[snip]

hw/intc/xics_native.c line 248

Quoted 4 lines
hw/intc/xics_native.c new file +4 -0
+static void xics_native_realize(DeviceState *dev, Error **errp)
+{
+    XICSState *s = XICS_NATIVE(dev);
+    SysBusDevice *sbd = SYS_BUS_DEVICE(dev);

Ah.. here's another wrinkle. So the current XICS is defined as a SysBusDevice, but that's not actually correct because it doesn't have MMIO. But your xics native does have MMIO, so my understanding is that SysBusDevice is appropriate. Not sure how to handle that

Signature · 4 lines
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson
#105 lore raw

PATCH 39/77 ppc/xics: Add xics to the monitor "info pic" command

In reply to Benjamin Herrenschmidt

Useful to debug interrupt problems.

---
 hmp-commands-info.hx  |  2 ++
 hw/intc/xics.c        | 38 ++++++++++++++++++++++++++++++++++++++
 hw/ppc/ppc.c          | 14 ++++++++++++++
 include/hw/ppc/ppc.h  |  2 ++
 include/hw/ppc/xics.h |  2 ++
 monitor.c             |  3 +++
 6 files changed, 61 insertions(+)
hmp-commands-info.hx +2 -0
index 9b71351..2f1dc86 100644
@@ -203,6 +203,8 @@ ETEXI
         .mhandler.cmd = sun4m_hmp_info_pic,
 #elif defined(TARGET_LM32)
         .mhandler.cmd = lm32_hmp_info_pic,
+#elif defined(TARGET_PPC)
+        .mhandler.cmd = ppc_hmp_info_pic,
 #else
         .mhandler.cmd = hmp_info_pic,
 #endif
hw/intc/xics.c +38 -0
index 4b33e6d..d027a24 100644
@@ -31,6 +31,9 @@
 #include "hw/ppc/xics.h"
 #include "qemu/error-report.h"
 #include "qapi/visitor.h"
+#include "monitor/monitor.h"
+
+static XICSState *g_xics;
 
 int get_cpu_index_by_dt_id(int cpu_dt_id)
 {
@@ -170,6 +173,9 @@ static void xics_common_initfn(Object *obj)
     object_property_add(obj, "nr_servers", "int",
                         xics_prop_get_nr_servers, xics_prop_set_nr_servers,
                         NULL, NULL, NULL);
+
+    /* For exclusive use of monitor command */
+    g_xics = XICS_COMMON(obj);
 }
 
 static void xics_common_class_init(ObjectClass *oc, void *data)
@@ -614,6 +620,38 @@ static int ics_dispatch_post_load(void *opaque, int version_id)
     return 0;
 }
 
+void xics_hmp_info_pic(Monitor *mon, const QDict *qdict)
+{
+    ICSState *ics;
+    uint32_t i;
+
+    for (i = 0; i < g_xics->nr_servers; i++) {
+        ICPState *icp = &g_xics->ss[i];
+
+        if (!icp->output) {
+            continue;
+        }
+        monitor_printf(mon, "CPU %d XIRR=%08x (%p) PP=%02x MFRR=%02x\n",
+                       i, icp->xirr, icp->xirr_owner,
+                       icp->pending_priority, icp->mfrr);
+    }
+    QLIST_FOREACH(ics, &g_xics->ics, list) {
+        monitor_printf(mon, "ICS %4x..%4x %p\n",
+                       ics->offset, ics->offset + ics->nr_irqs - 1, ics);
+        for (i = 0; i < ics->nr_irqs; i++) {
+            ICSIRQState *irq = ics->irqs + i;
+
+            if (!(irq->flags & XICS_FLAGS_IRQ_MASK)) {
+                continue;
+            }
+            monitor_printf(mon, "  %4x %s %02x %02x\n",
+                           ics->offset + i,
+                           (irq->flags & XICS_FLAGS_IRQ_LSI) ? "LSI" : "MSI",
+                           irq->priority, irq->status);
+        }
+    }
+}
+
 static const VMStateDescription vmstate_ics_simple_irq = {
     .name = "ics/irq",
     .version_id = 2,
hw/ppc/ppc.c +14 -0
index 2c604ef..3b14f09 100644
@@ -24,6 +24,7 @@
 #include "hw/hw.h"
 #include "hw/ppc/ppc.h"
 #include "hw/ppc/ppc_e500.h"
+#include "hw/i386/pc.h"
 #include "qemu/timer.h"
 #include "sysemu/sysemu.h"
 #include "sysemu/cpus.h"
@@ -35,6 +36,10 @@
 #include "kvm_ppc.h"
 #include "trace.h"
 
+#if defined(TARGET_PPC64)
+#include "hw/ppc/xics.h"
+#endif
+
 //#define PPC_DEBUG_IRQ
 //#define PPC_DEBUG_TB
 
@@ -1337,3 +1342,12 @@ PowerPCCPU *ppc_get_vcpu_by_dt_id(int cpu_dt_id)
 
     return NULL;
 }
+
+void ppc_hmp_info_pic(Monitor *mon, const QDict *qdict)
+{
+    /* Call in turn every PIC around. OpenPIC doesn't have one yet */
+#ifdef TARGET_PPC64
+    xics_hmp_info_pic(mon, qdict);
+#endif
+    hmp_info_pic(mon, qdict);
+}
include/hw/ppc/ppc.h +2 -0
index 14efd0c..d5c648d 100644
@@ -1,6 +1,8 @@
 #ifndef HW_PPC_H
 #define HW_PPC_H 1
 
+void ppc_hmp_info_pic(Monitor *mon, const QDict *qdict);
+
 void ppc_set_irq(PowerPCCPU *cpu, int n_IRQ, int level);
 
 /* PowerPC hardware exceptions management helpers */
include/hw/ppc/xics.h +2 -0
index f32f409..1cf7037 100644
@@ -213,4 +213,6 @@ void xics_set_nr_servers(XICSState *icp, uint32_t nr_servers, Error **errp);
 ICSState *xics_find_source(XICSState *icp, int irq);
 void xics_add_ics(XICSState *xics, ICSState *ics);
 
+void xics_hmp_info_pic(Monitor *mon, const QDict *qdict);
+
 #endif /* __XICS_H__ */
monitor.c +3 -0
index 3295840..988477e 100644
@@ -76,6 +76,9 @@
 #include "qapi-event.h"
 #include "qmp-introspect.h"
 #include "sysemu/block-backend.h"
+#if defined(TARGET_PPC)
+#include "hw/ppc/ppc.h"
+#endif
 
 /* for hmp_info_irq/pic */
 #if defined(TARGET_SPARC)
Signature · 1 line
2.5.0
#106 lore raw

Re: [Qemu-devel] [Qemu-ppc] [PATCH 39/77] ppc/xics: Add xics to the monitor "info pic" command

Quoted 1 line · Benjamin Herrenschmidt

Useful to debug interrupt problems.

Ugh.. I can see the use of this, but we really want to just deprecate info pic entirely, it's an awful, awful interface.

I think the right way to do this is to allow some state introspection via the QOM interfaces on the xics devices themselves, but I'm not immediately sure how to go about that.

Quoted 161 lines
---
 hmp-commands-info.hx  |  2 ++
 hw/intc/xics.c        | 38 ++++++++++++++++++++++++++++++++++++++
 hw/ppc/ppc.c          | 14 ++++++++++++++
 include/hw/ppc/ppc.h  |  2 ++
 include/hw/ppc/xics.h |  2 ++
 monitor.c             |  3 +++
 6 files changed, 61 insertions(+)
hmp-commands-info.hx +2 -0
index 9b71351..2f1dc86 100644
@@ -203,6 +203,8 @@ ETEXI
         .mhandler.cmd = sun4m_hmp_info_pic,
 #elif defined(TARGET_LM32)
         .mhandler.cmd = lm32_hmp_info_pic,
+#elif defined(TARGET_PPC)
+        .mhandler.cmd = ppc_hmp_info_pic,
 #else
         .mhandler.cmd = hmp_info_pic,
 #endif
hw/intc/xics.c +38 -0
index 4b33e6d..d027a24 100644
@@ -31,6 +31,9 @@
 #include "hw/ppc/xics.h"
 #include "qemu/error-report.h"
 #include "qapi/visitor.h"
+#include "monitor/monitor.h"
+
+static XICSState *g_xics;
 
 int get_cpu_index_by_dt_id(int cpu_dt_id)
 {
@@ -170,6 +173,9 @@ static void xics_common_initfn(Object *obj)
     object_property_add(obj, "nr_servers", "int",
                         xics_prop_get_nr_servers, xics_prop_set_nr_servers,
                         NULL, NULL, NULL);
+
+    /* For exclusive use of monitor command */
+    g_xics = XICS_COMMON(obj);
 }
 
 static void xics_common_class_init(ObjectClass *oc, void *data)
@@ -614,6 +620,38 @@ static int ics_dispatch_post_load(void *opaque, int version_id)
     return 0;
 }
 
+void xics_hmp_info_pic(Monitor *mon, const QDict *qdict)
+{
+    ICSState *ics;
+    uint32_t i;
+
+    for (i = 0; i < g_xics->nr_servers; i++) {
+        ICPState *icp = &g_xics->ss[i];
+
+        if (!icp->output) {
+            continue;
+        }
+        monitor_printf(mon, "CPU %d XIRR=%08x (%p) PP=%02x MFRR=%02x\n",
+                       i, icp->xirr, icp->xirr_owner,
+                       icp->pending_priority, icp->mfrr);
+    }
+    QLIST_FOREACH(ics, &g_xics->ics, list) {
+        monitor_printf(mon, "ICS %4x..%4x %p\n",
+                       ics->offset, ics->offset + ics->nr_irqs - 1, ics);
+        for (i = 0; i < ics->nr_irqs; i++) {
+            ICSIRQState *irq = ics->irqs + i;
+
+            if (!(irq->flags & XICS_FLAGS_IRQ_MASK)) {
+                continue;
+            }
+            monitor_printf(mon, "  %4x %s %02x %02x\n",
+                           ics->offset + i,
+                           (irq->flags & XICS_FLAGS_IRQ_LSI) ? "LSI" : "MSI",
+                           irq->priority, irq->status);
+        }
+    }
+}
+
 static const VMStateDescription vmstate_ics_simple_irq = {
     .name = "ics/irq",
     .version_id = 2,
hw/ppc/ppc.c +14 -0
index 2c604ef..3b14f09 100644
@@ -24,6 +24,7 @@
 #include "hw/hw.h"
 #include "hw/ppc/ppc.h"
 #include "hw/ppc/ppc_e500.h"
+#include "hw/i386/pc.h"
 #include "qemu/timer.h"
 #include "sysemu/sysemu.h"
 #include "sysemu/cpus.h"
@@ -35,6 +36,10 @@
 #include "kvm_ppc.h"
 #include "trace.h"
 
+#if defined(TARGET_PPC64)
+#include "hw/ppc/xics.h"
+#endif
+
 //#define PPC_DEBUG_IRQ
 //#define PPC_DEBUG_TB
 
@@ -1337,3 +1342,12 @@ PowerPCCPU *ppc_get_vcpu_by_dt_id(int cpu_dt_id)
 
     return NULL;
 }
+
+void ppc_hmp_info_pic(Monitor *mon, const QDict *qdict)
+{
+    /* Call in turn every PIC around. OpenPIC doesn't have one yet */
+#ifdef TARGET_PPC64
+    xics_hmp_info_pic(mon, qdict);
+#endif
+    hmp_info_pic(mon, qdict);
+}
include/hw/ppc/ppc.h +2 -0
index 14efd0c..d5c648d 100644
@@ -1,6 +1,8 @@
 #ifndef HW_PPC_H
 #define HW_PPC_H 1
 
+void ppc_hmp_info_pic(Monitor *mon, const QDict *qdict);
+
 void ppc_set_irq(PowerPCCPU *cpu, int n_IRQ, int level);
 
 /* PowerPC hardware exceptions management helpers */
include/hw/ppc/xics.h +2 -0
index f32f409..1cf7037 100644
@@ -213,4 +213,6 @@ void xics_set_nr_servers(XICSState *icp, uint32_t nr_servers, Error **errp);
 ICSState *xics_find_source(XICSState *icp, int irq);
 void xics_add_ics(XICSState *xics, ICSState *ics);
 
+void xics_hmp_info_pic(Monitor *mon, const QDict *qdict);
+
 #endif /* __XICS_H__ */
monitor.c +3 -0
index 3295840..988477e 100644
@@ -76,6 +76,9 @@
 #include "qapi-event.h"
 #include "qmp-introspect.h"
 #include "sysemu/block-backend.h"
+#if defined(TARGET_PPC)
+#include "hw/ppc/ppc.h"
+#endif
 
 /* for hmp_info_irq/pic */
 #if defined(TARGET_SPARC)
Signature · 4 lines
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson
#107 lore raw

PATCH 40/77 ppc/pnv: Wire up XICS native with PowerNV platform

In reply to Benjamin Herrenschmidt
---
 hw/ppc/pnv.c          | 69 +++++++++++++++++++++++++++++++++++++++++++++++++++
 include/hw/ppc/pnv.h  |  2 ++
 include/hw/ppc/xics.h |  2 ++
 3 files changed, 73 insertions(+)
hw/ppc/pnv.c +69 -0
index 2eac877..a7a9b0f 100644
@@ -41,6 +41,7 @@
 #include "hw/ppc/ppc.h"
 #include "hw/ppc/pnv.h"
 #include "hw/loader.h"
+#include "hw/ppc/xics.h"
 #include "hw/ppc/pnv_xscom.h"
 
 #include "exec/address-spaces.h"
@@ -81,6 +82,59 @@ struct sPowerNVMachineState {
     PnvSystem sys;
 };
 
+static XICSState *try_create_xics(const char *type, int nr_servers,
+                                  int nr_irqs, Error **errp)
+{
+    Error *err = NULL;
+    DeviceState *dev;
+
+    dev = qdev_create(NULL, type);
+    qdev_prop_set_uint32(dev, "nr_servers", nr_servers);
+    object_property_set_bool(OBJECT(dev), true, "realized", &err);
+    if (err) {
+        error_propagate(errp, err);
+        object_unparent(OBJECT(dev));
+        return NULL;
+    }
+
+    return XICS_COMMON(dev);
+}
+
+static XICSState *xics_system_init(int nr_servers, int nr_irqs)
+{
+    XICSState *xics = NULL;
+
+#if 0 /* Some fixing needed to handle native ICS in KVM mode */
+    if (kvm_enabled()) {
+        QemuOpts *machine_opts = qemu_get_machine_opts();
+        bool irqchip_allowed = qemu_opt_get_bool(machine_opts,
+                                                "kernel_irqchip", true);
+        bool irqchip_required = qemu_opt_get_bool(machine_opts,
+                                                  "kernel_irqchip", false);
+        if (irqchip_allowed) {
+                icp = try_create_xics(TYPE_KVM_XICS, nr_servers, nr_irqs,
+                                      &error_abort);
+        }
+
+        if (irqchip_required && !icp) {
+            perror("Failed to create in-kernel XICS\n");
+            abort();
+        }
+    }
+#endif
+
+    if (!xics) {
+        xics = try_create_xics(TYPE_XICS_NATIVE, nr_servers, nr_irqs,
+                               &error_abort);
+    }
+
+    if (!xics) {
+        perror("Failed to create XICS\n");
+        abort();
+    }
+    return xics;
+}
+
 static size_t create_page_sizes_prop(CPUPPCState *env, uint32_t *prop,
                                      size_t maxsize)
 {
@@ -366,6 +420,13 @@ static void *powernv_create_fdt(PnvSystem *sys, uint32_t initrd_base, uint32_t i
 
     _FDT((fdt_end_node(fdt)));
 
+    /* ICPs */
+    CPU_FOREACH(cs) {
+        PowerPCCPU *cpu = POWERPC_CPU(cs);
+        uint32_t base_server = ppc_get_vcpu_dt_id(cpu);
+        xics_create_native_icp_node(sys->xics, fdt, base_server, smt);
+    }
+
     /* Memory */
     _FDT((powernv_populate_memory(fdt)));
 
@@ -451,11 +512,17 @@ static void ppc_powernv_init(MachineState *machine)
     MemoryRegion *ram = g_new(MemoryRegion, 1);
     sPowerNVMachineState *pnv_machine = POWERNV_MACHINE(machine);
     PnvSystem *sys = &pnv_machine->sys;
+    XICSState *xics;
     long fw_size;
     char *filename;
     void *fdt;
     int i;
 
+    /* Set up Interrupt Controller before we create the VCPUs */
+    xics = xics_system_init(smp_cpus * kvmppc_smt_threads() / smp_threads,
+                            XICS_IRQS_POWERNV);
+    sys->xics = xics;
+
     /* init CPUs */
     if (cpu_model == NULL) {
         cpu_model = kvm_enabled() ? "host" : "POWER8";
@@ -475,6 +542,8 @@ static void ppc_powernv_init(MachineState *machine)
         /* MSR[IP] doesn't exist nowadays */
         env->msr_mask &= ~(1 << 6);
 
+        xics_cpu_setup(xics, cpu);
+
         qemu_register_reset(powernv_cpu_reset, cpu);
     }
 
include/hw/ppc/pnv.h +2 -0
index cb157eb..80617b4 100644
@@ -21,6 +21,7 @@
 
 #include "hw/hw.h"
 typedef struct XScomBus XScomBus;
+typedef struct XICSState XICSState;
 
 /* Should we turn that into a QOjb of some sort ? */
 typedef struct PnvChip {
@@ -29,6 +30,7 @@ typedef struct PnvChip {
 } PnvChip;
 
 typedef struct PnvSystem {
+    XICSState *xics;
     uint32_t  num_chips;
 #define PNV_MAX_CHIPS		1
     PnvChip   chips[PNV_MAX_CHIPS];
include/hw/ppc/xics.h +2 -0
index 1cf7037..85d2fb9 100644
@@ -183,6 +183,8 @@ struct ICSIRQState {
 };
 
 #define XICS_IRQS_SPAPR               1024
+#define XICS_IRQS_POWERNV             (1 << 19)
+
 
 qemu_irq xics_get_qirq(XICSState *icp, int irq);
 
Signature · 1 line
2.5.0
#108 lore raw

Re: [Qemu-devel] [Qemu-ppc] [PATCH 40/77] ppc/pnv: Wire up XICS native with PowerNV platform

Quoted 1 line · Benjamin Herrenschmidt

Looks sound enough, but will probably need some rework due to other suggested changes in the new xics stuff.

Quoted 152 lines
---
 hw/ppc/pnv.c          | 69 +++++++++++++++++++++++++++++++++++++++++++++++++++
 include/hw/ppc/pnv.h  |  2 ++
 include/hw/ppc/xics.h |  2 ++
 3 files changed, 73 insertions(+)
hw/ppc/pnv.c +69 -0
index 2eac877..a7a9b0f 100644
@@ -41,6 +41,7 @@
 #include "hw/ppc/ppc.h"
 #include "hw/ppc/pnv.h"
 #include "hw/loader.h"
+#include "hw/ppc/xics.h"
 #include "hw/ppc/pnv_xscom.h"
 
 #include "exec/address-spaces.h"
@@ -81,6 +82,59 @@ struct sPowerNVMachineState {
     PnvSystem sys;
 };
 
+static XICSState *try_create_xics(const char *type, int nr_servers,
+                                  int nr_irqs, Error **errp)
+{
+    Error *err = NULL;
+    DeviceState *dev;
+
+    dev = qdev_create(NULL, type);
+    qdev_prop_set_uint32(dev, "nr_servers", nr_servers);
+    object_property_set_bool(OBJECT(dev), true, "realized", &err);
+    if (err) {
+        error_propagate(errp, err);
+        object_unparent(OBJECT(dev));
+        return NULL;
+    }
+
+    return XICS_COMMON(dev);
+}
+
+static XICSState *xics_system_init(int nr_servers, int nr_irqs)
+{
+    XICSState *xics = NULL;
+
+#if 0 /* Some fixing needed to handle native ICS in KVM mode */
+    if (kvm_enabled()) {
+        QemuOpts *machine_opts = qemu_get_machine_opts();
+        bool irqchip_allowed = qemu_opt_get_bool(machine_opts,
+                                                "kernel_irqchip", true);
+        bool irqchip_required = qemu_opt_get_bool(machine_opts,
+                                                  "kernel_irqchip", false);
+        if (irqchip_allowed) {
+                icp = try_create_xics(TYPE_KVM_XICS, nr_servers, nr_irqs,
+                                      &error_abort);
+        }
+
+        if (irqchip_required && !icp) {
+            perror("Failed to create in-kernel XICS\n");
+            abort();
+        }
+    }
+#endif
+
+    if (!xics) {
+        xics = try_create_xics(TYPE_XICS_NATIVE, nr_servers, nr_irqs,
+                               &error_abort);
+    }
+
+    if (!xics) {
+        perror("Failed to create XICS\n");
+        abort();
+    }
+    return xics;
+}
+
 static size_t create_page_sizes_prop(CPUPPCState *env, uint32_t *prop,
                                      size_t maxsize)
 {
@@ -366,6 +420,13 @@ static void *powernv_create_fdt(PnvSystem *sys, uint32_t initrd_base, uint32_t i
 
     _FDT((fdt_end_node(fdt)));
 
+    /* ICPs */
+    CPU_FOREACH(cs) {
+        PowerPCCPU *cpu = POWERPC_CPU(cs);
+        uint32_t base_server = ppc_get_vcpu_dt_id(cpu);
+        xics_create_native_icp_node(sys->xics, fdt, base_server, smt);
+    }
+
     /* Memory */
     _FDT((powernv_populate_memory(fdt)));
 
@@ -451,11 +512,17 @@ static void ppc_powernv_init(MachineState *machine)
     MemoryRegion *ram = g_new(MemoryRegion, 1);
     sPowerNVMachineState *pnv_machine = POWERNV_MACHINE(machine);
     PnvSystem *sys = &pnv_machine->sys;
+    XICSState *xics;
     long fw_size;
     char *filename;
     void *fdt;
     int i;
 
+    /* Set up Interrupt Controller before we create the VCPUs */
+    xics = xics_system_init(smp_cpus * kvmppc_smt_threads() / smp_threads,
+                            XICS_IRQS_POWERNV);
+    sys->xics = xics;
+
     /* init CPUs */
     if (cpu_model == NULL) {
         cpu_model = kvm_enabled() ? "host" : "POWER8";
@@ -475,6 +542,8 @@ static void ppc_powernv_init(MachineState *machine)
         /* MSR[IP] doesn't exist nowadays */
         env->msr_mask &= ~(1 << 6);
 
+        xics_cpu_setup(xics, cpu);
+
         qemu_register_reset(powernv_cpu_reset, cpu);
     }
 
include/hw/ppc/pnv.h +2 -0
index cb157eb..80617b4 100644
@@ -21,6 +21,7 @@
 
 #include "hw/hw.h"
 typedef struct XScomBus XScomBus;
+typedef struct XICSState XICSState;
 
 /* Should we turn that into a QOjb of some sort ? */
 typedef struct PnvChip {
@@ -29,6 +30,7 @@ typedef struct PnvChip {
 } PnvChip;
 
 typedef struct PnvSystem {
+    XICSState *xics;
     uint32_t  num_chips;
 #define PNV_MAX_CHIPS		1
     PnvChip   chips[PNV_MAX_CHIPS];
include/hw/ppc/xics.h +2 -0
index 1cf7037..85d2fb9 100644
@@ -183,6 +183,8 @@ struct ICSIRQState {
 };
 
 #define XICS_IRQS_SPAPR               1024
+#define XICS_IRQS_POWERNV             (1 << 19)
+
 
 qemu_irq xics_get_qirq(XICSState *icp, int irq);
 
Signature · 4 lines
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson
#109 lore raw

PATCH 41/77 ppc/pnv: Add LPC controller and hook it up with a UART and RTC

In reply to Benjamin Herrenschmidt

This adds a model of the POWER8 LPC controller. It is then used by the PowerNV code to attach a UART and RTC, which, with the right version of OPAL firmware, will provide a working console.

This version of the LPC controller model doesn't yet implement support for the SerIRQ deserializer present in the Naples version of the chip though some preliminary work is there.

---
 hw/ppc/Makefile.objs |   2 +-
 hw/ppc/pnv.c         |  49 ++++-
 hw/ppc/pnv_lpc.c     | 527 +++++++++++++++++++++++++++++++++++++++++++++++++++
 include/hw/ppc/pnv.h |   5 +
 4 files changed, 578 insertions(+), 5 deletions(-)
 create mode 100644 hw/ppc/pnv_lpc.c
hw/ppc/Makefile.objs +1 -1
index 2a7dd42..5ebf0e0 100644
@@ -5,7 +5,7 @@ obj-$(CONFIG_PSERIES) += spapr.o spapr_vio.o spapr_events.o
 obj-$(CONFIG_PSERIES) += spapr_hcall.o spapr_iommu.o spapr_rtas.o
 obj-$(CONFIG_PSERIES) += spapr_pci.o spapr_rtc.o spapr_drc.o spapr_rng.o
 # IBM PowerNV
-obj-$(CONFIG_POWERNV) += pnv.o pnv_xscom.o
+obj-$(CONFIG_POWERNV) += pnv.o pnv_xscom.o pnv_lpc.o
 ifeq ($(CONFIG_PCI)$(CONFIG_PSERIES)$(CONFIG_LINUX), yyy)
 obj-y += spapr_pci_vfio.o
 endif
hw/ppc/pnv.c +45 -4

80 lines not on this page · raw message

hw/ppc/pnv_lpc.c new file +527 -0

527 lines not on this page · raw message

include/hw/ppc/pnv.h +5 -0
index 80617b4..77b809a 100644
@@ -21,12 +21,16 @@
 
 #include "hw/hw.h"
 typedef struct XScomBus XScomBus;
+typedef struct ISABus ISABus;
+typedef struct PnvLpcController PnvLpcController;
 typedef struct XICSState XICSState;
 
 /* Should we turn that into a QOjb of some sort ? */
 typedef struct PnvChip {
     uint32_t         chip_id;
     XScomBus         *xscom;
+    PnvLpcController *lpc;
+    ISABus           *lpc_bus;
 } PnvChip;
 
 typedef struct PnvSystem {
@@ -36,5 +40,6 @@ typedef struct PnvSystem {
     PnvChip   chips[PNV_MAX_CHIPS];
 } PnvSystem;
 
+extern void pnv_lpc_create(PnvChip *chip, bool has_serirq);
 #endif /* _HW_PNV_LPC_H */
 
Signature · 1 line
2.5.0
#110 lore raw

Re: [Qemu-devel] [PATCH 41/77] ppc/pnv: Add LPC controller and hook it up with a UART and RTC

Quoted 8 lines · Benjamin Herrenschmidt

This adds a model of the POWER8 LPC controller. It is then used by the PowerNV code to attach a UART and RTC, which, with the right version of OPAL firmware, will provide a working console.

This version of the LPC controller model doesn't yet implement support for the SerIRQ deserializer present in the Naples version of the chip though some preliminary work is there.

Is this LPC controller one per a chip or per a machine?
In general it is quite nice when "-nodefaults" does not create neither PHB nor LPC so the user can add them manually with parameters different than defaults.

Signature · 1 line
Alexey
#111 lore raw

Re: [Qemu-devel] [PATCH 41/77] ppc/pnv: Add LPC controller and hook it up with a UART and RTC

Quoted 11 lines · Alexey Kardashevskiy
Quoted 8 lines · Benjamin Herrenschmidt

This adds a model of the POWER8 LPC controller. It is then used by the PowerNV code to attach a UART and RTC, which, with the right version of OPAL firmware, will provide a working console.

This version of the LPC controller model doesn't yet implement support for the SerIRQ deserializer present in the Naples version of the chip though some preliminary work is there.

Is this LPC controller one per a chip or per a machine?

Per chip but we usually only wire one up per machine.

Quoted 3 lines

In general it is quite nice when "-nodefaults" does not create neither PHB nor LPC so the user can add them manually with parameters different than defaults.

In this case though, PHB and LPC bridges are all part of the P8 chip, and I'm trying to represent that topology as best as possible.

I think "-nodefaults" for Pnv should only be about the devices we attach to the LPC/PHB not the busses themselves.

Cheers,
Ben.

#112 lore raw

Re: [Qemu-devel] [Qemu-ppc] [PATCH 41/77] ppc/pnv: Add LPC controller and hook it up with a UART and RTC

Quoted 19 lines · Benjamin Herrenschmidt
Quoted 11 lines · Alexey Kardashevskiy
Quoted 8 lines · Benjamin Herrenschmidt

This adds a model of the POWER8 LPC controller. It is then used by the PowerNV code to attach a UART and RTC, which, with the right version of OPAL firmware, will provide a working console.

This version of the LPC controller model doesn't yet implement support for the SerIRQ deserializer present in the Naples version of the chip though some preliminary work is there.

Is this LPC controller one per a chip or per a machine?

Per chip but we usually only wire one up per machine.

Quoted 3 lines

In general it is quite nice when "-nodefaults" does not create neither PHB nor LPC so the user can add them manually with parameters different than defaults.

Quoted 5 lines

In this case though, PHB and LPC bridges are all part of the P8 chip, and I'm trying to represent that topology as best as possible.

I think "-nodefaults" for Pnv should only be about the devices we attach to the LPC/PHB not the busses themselves.

Exactly what is and isn't covered by -nodefaults is a bit of a mess - part of the topic of my talk at KVM Forum.

But on the whole I agree with you, since the LPC is part of the P8 chip, I think it makes sense to include it even with -nodefaults.

Signature · 4 lines
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson
#113 lore raw

Re: [Qemu-devel] [Qemu-ppc] [PATCH 41/77] ppc/pnv: Add LPC controller and hook it up with a UART and RTC

Quoted 23 lines · David Gibson
Quoted 22 lines · Benjamin Herrenschmidt
Quoted 11 lines · Alexey Kardashevskiy
Quoted 8 lines · Benjamin Herrenschmidt

This adds a model of the POWER8 LPC controller. It is then used by the PowerNV code to attach a UART and RTC, which, with the right version of OPAL firmware, will provide a working console.

This version of the LPC controller model doesn't yet implement support for the SerIRQ deserializer present in the Naples version of the chip though some preliminary work is there.

Is this LPC controller one per a chip or per a machine?

Per chip but we usually only wire one up per machine.

Quoted 3 lines

In general it is quite nice when "-nodefaults" does not create neither PHB nor LPC so the user can add them manually with parameters different than defaults.

In this case though, PHB and LPC bridges are all part of the P8 chip, and I'm trying to represent that topology as best as possible.

Quoted 8 lines
Quoted 2 lines

I think "-nodefaults" for Pnv should only be about the devices we attach to the LPC/PHB not the busses themselves.

Exactly what is and isn't covered by -nodefaults is a bit of a mess - part of the topic of my talk at KVM Forum.

But on the whole I agree with you, since the LPC is part of the P8 chip, I think it makes sense to include it even with -nodefaults.

POWER8 chips all have 8 threads per core but we do not always assume -smt ...,threads=8, how are LPC or PHB different? PHB is more interesting - how is the user supposed to add more? And there always will be the default one which properties are set in a separate way (via -global, not -device). I found it sometime really annoying to debug the existing pseries which always adds a default PHB (I know, this was to make libvirt happy but this is not the case here).

Out of curiosity - if we have 2 chips, will the system work if the second chip does not get any LPC or PHB attached?

Signature · 1 line
Alexey
#114 lore raw

Re: [Qemu-devel] [Qemu-ppc] [PATCH 41/77] ppc/pnv: Add LPC controller and hook it up with a UART and RTC

Quoted 5 lines · Alexey Kardashevskiy
Quoted 2 lines

But on the whole I agree with you, since the LPC is part of the P8 chip, I think it makes sense to include it even with -nodefaults.

POWER8 chips all have 8 threads per core but we do not always assume -smt ...,threads=8, how are LPC or PHB different?

First, for pseries which is paravirtualized it's a different can of worms completely. For powernv, we *should* represent all 8 threads, we just can't yet due to TCG limitations.

Quoted 1 line

PHB is more interesting - how is the user supposed to add more?

That's an open question. Since we model a real P8 chip we can only model the PHBs as they exist on it, which is up to 3 per chip at very specific XSCOM addresses. We could try to model some non-existing P8 chip with more but bad things will happen when the FW try to assign interrupt numbers for example.

We simulate a machine that has been primed by HostBoot before OPAL starts. So we rely on what the device-tree tells us of what PHB were enabled but appart from that, we have to stick to the limitations.

Quoted 8 lines

And there always will be the default one
which properties are set in a separate way (via -global, not -device). I found it sometime really annoying to debug the existing pseries which always adds a default PHB (I know, this was to make libvirt happy but this is not the case here).

Out of curiosity - if we have 2 chips, will the system work if the second chip does not get any LPC or PHB attached?

This is something I need to look into, there's a lot of work needed to properly model "chips" that I haven't done yet, but what is there is sufficient for a lot of usages already.

Cheers,
Ben.

#115 lore raw

Re: [Qemu-devel] [Qemu-ppc] [PATCH 41/77] ppc/pnv: Add LPC controller and hook it up with a UART and RTC

Quoted 10 lines · Benjamin Herrenschmidt
Quoted 5 lines · Alexey Kardashevskiy
Quoted 2 lines

But on the whole I agree with you, since the LPC is part of the P8 chip, I think it makes sense to include it even with -nodefaults.

POWER8 chips all have 8 threads per core but we do not always assume -smt ...,threads=8, how are LPC or PHB different?

First, for pseries which is paravirtualized it's a different can of worms completely. For powernv, we *should* represent all 8 threads, we just can't yet due to TCG limitations.

Out of curiosity - for pseries we should not? I know it works with various numbers of threads but is not that because we also control guest linux kernel and, for example, the Other OS (AIX) might be upset on non-multiply-of-2 number of threads?

Quoted 18 lines
Quoted 1 line

PHB is more interesting - how is the user supposed to add more?

That's an open question. Since we model a real P8 chip we can only model the PHBs as they exist on it, which is up to 3 per chip at very specific XSCOM addresses. We could try to model some non-existing P8 chip with more but bad things will happen when the FW try to assign interrupt numbers for example.

We simulate a machine that has been primed by HostBoot before OPAL starts. So we rely on what the device-tree tells us of what PHB were enabled but appart from that, we have to stick to the limitations.

Quoted 6 lines

And there always will be the default one
which properties are set in a separate way (via -global, not -device). I found it sometime really annoying to debug the existing pseries which always adds a default PHB (I know, this was to make libvirt happy but this is not the case here).

Quoted 6 lines
Quoted 2 lines

Out of curiosity - if we have 2 chips, will the system work if the second chip does not get any LPC or PHB attached?

This is something I need to look into, there's a lot of work needed to properly model "chips" that I haven't done yet, but what is there is sufficient for a lot of usages already.

For now, if possible, I'd suggest implementing -nodefaults with no defaults whatsoever and create a config somewhere in the qemu tree to pass it via -readconfig to get reasonably configured machine so people will know what is expected to work but there will still be possibility for experiments (do not we secretly hope that other vendors will start designing/manufacturing their ppc64 chips?). It could be a config file per an actual POWER8 chip (we have two already).

Signature · 1 line
Alexey
#116 lore raw

Re: [Qemu-devel] [Qemu-ppc] [PATCH 41/77] ppc/pnv: Add LPC controller and hook it up with a UART and RTC

Quoted 8 lines · Alexey Kardashevskiy
Quoted 7 lines · Benjamin Herrenschmidt
Quoted 5 lines · Alexey Kardashevskiy
Quoted 2 lines

But on the whole I agree with you, since the LPC is part of the P8 chip, I think it makes sense to include it even with -nodefaults.

POWER8 chips all have 8 threads per core but we do not always assume -smt ...,threads=8, how are LPC or PHB different?

Quoted 8 lines
Quoted 3 lines

First, for pseries which is paravirtualized it's a different can of worms completely. For powernv, we *should* represent all 8 threads, we just can't yet due to TCG limitations.

Out of curiosity - for pseries we should not? I know it works with various numbers of threads but is not that because we also control guest linux kernel and, for example, the Other OS (AIX) might be upset on non-multiply-of-2 number of threads?

There are several different cases here and I'm not sure which you're thinking about.

1) Guest has different number of threads-per-core than the host

This one is just fine - PAPR defines how the guest should get the number of threads from the device tree, and qemu sets that correctly.

2) Guest threads-per-core not a power of two

The PAPR thread mechanism allows this to be communicated to the guest, and I don't know if PAPR explicitly permits or prohibitis this situation. Guests could get confused by it, although that's arguably a guest bug.

2) "Partially filled core", e.g. guest has 8 threads-per-core declared but only one vcpu available

This is the only one I can see as relying on Linux guest behaviour. We kind of get away with this by accident with a Linux guest - it will try to bring up all 8 threads, but fail non fatally. We shouldn't allow this situation, although we do right now. Bharata posted a patch which would prevent this in qemu, and I have a BZ to make libvirt not allow this construction either.

Quoted 25 lines
Quoted 18 lines
Quoted 1 line

PHB is more interesting - how is the user supposed to add more?

That's an open question. Since we model a real P8 chip we can only model the PHBs as they exist on it, which is up to 3 per chip at very specific XSCOM addresses. We could try to model some non-existing P8 chip with more but bad things will happen when the FW try to assign interrupt numbers for example.

We simulate a machine that has been primed by HostBoot before OPAL starts. So we rely on what the device-tree tells us of what PHB were enabled but appart from that, we have to stick to the limitations.

Quoted 6 lines

And there always will be the default one
which properties are set in a separate way (via -global, not -device). I found it sometime really annoying to debug the existing pseries which always adds a default PHB (I know, this was to make libvirt happy but this is not the case here).

Quoted 6 lines
Quoted 2 lines

Out of curiosity - if we have 2 chips, will the system work if the second chip does not get any LPC or PHB attached?

This is something I need to look into, there's a lot of work needed to properly model "chips" that I haven't done yet, but what is there is sufficient for a lot of usages already.

Quoted 7 lines

For now, if possible, I'd suggest implementing -nodefaults with no defaults whatsoever and create a config somewhere in the qemu tree to pass it via -readconfig to get reasonably configured machine so people will know what is expected to work but there will still be possibility for experiments (do not we secretly hope that other vendors will start designing/manufacturing their ppc64 chips?). It could be a config file per an actual POWER8 chip (we have two already).

I can see some benefit to that approach, but it does stray away from current qemu practice (in general, not just compared to spapr). Hmm.. not sure.

What I do think would be a good idea is to represent a POWER8 "chip" as a instantiable qdev device, which will create the scoms and PHBs under itself as per the hardware. We can add device properties as needed to make that construction more flexible.

We probably don't want to link the number of CPUs to the chip qdevs, partly because that doesn't really fit the qemu model, but also because we'll probably want some extra flexibility. e.g. making a UP system for experimentation, even though a single chip would have multiple cores (IIUC) - SMP TCG is super slow, so we probably want that.

Signature · 4 lines
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson
#117 lore raw

Re: [Qemu-devel] [Qemu-ppc] [PATCH 41/77] ppc/pnv: Add LPC controller and hook it up with a UART and RTC

Quoted 9 lines · David Gibson

There are several different cases here and I'm not sure which you're thinking about.

1) Guest has different number of threads-per-core than the host

This one is just fine - PAPR defines how the guest should get the number of threads from the device tree, and qemu sets that correctly.

Quoted 6 lines

2) Guest threads-per-core not a power of two

The PAPR thread mechanism allows this to be communicated to the guest, and I don't know if PAPR explicitly permits or prohibitis this situation.  Guests could get confused by it, although that's arguably a guest bug.

Linux only supports powers of 2

 .../...

Quoted 11 lines
Quoted 7 lines

For now, if possible, I'd suggest implementing -nodefaults with no defaults whatsoever and create a config somewhere in the qemu tree to pass it via -readconfig to get reasonably configured machine so people will know what is expected to work but there will still be possibility for experiments (do not we secretly hope that other vendors will start designing/manufacturing their ppc64 chips?). It could be a config file per an actual POWER8 chip (we have two already).

I can see some benefit to that approach, but it does stray away from current qemu practice (in general, not just compared to spapr). Hmm.. not sure.

I don't see an urgent need. We can do that in a separate series if we want to. As I said in another email, I don't want powernv to be "set in stone" in term of ABIs & migration for a while, so we have latitude to play with the model for a while before we lock things down. At least until after P9.

Quoted 4 lines

What I do think would be a good idea is to represent a POWER8 "chip" as a instantiable qdev device, which will create the scoms and PHBs under itself as per the hardware.  We can add device properties as needed to make that construction more flexible.

It would also instanciate the CPUs. I want to change that in the current model, just haven't got to it yet.

Quoted 5 lines

We probably don't want to link the number of CPUs to the chip qdevs, partly because that doesn't really fit the qemu model, but also because we'll probably want some extra flexibility.  e.g. making a UP system for experimentation, even though a single chip would have multiple cores (IIUC) - SMP TCG is super slow, so we probably want that.

We want to eventually represent the EX units properly on XSCOM (the cores). So we will need that tie between chip and CPU. But we don't have to mark all cores in a chip as "enabled". It's ok to have chips with only one good core for example.

Cheers,
Ben.

#118 lore raw

Re: [Qemu-devel] [Qemu-ppc] [PATCH 41/77] ppc/pnv: Add LPC controller and hook it up with a UART and RTC

In reply to Alexey Kardashevskiy
Quoted 5 lines · Alexey Kardashevskiy
Quoted 4 lines · Benjamin Herrenschmidt
Quoted 3 lines · Alexey Kardashevskiy
Quoted 2 lines

But on the whole I agree with you, since the LPC is part of the P8 chip, I think it makes sense to include it even with -nodefaults.

Quoted 8 lines
Quoted 6 lines
Quoted 2 lines

POWER8 chips all have 8 threads per core but we do not always assume -smt ...,threads=8, how are LPC or PHB different?

First, for pseries which is paravirtualized it's a different can of worms completely. For powernv, we *should* represent all 8 threads, we just can't yet due to TCG limitations.

Out of curiosity - for pseries we should not?

Not that we should not, more like, it makes sense to offer whatever choice, it would be indeed better to have the ability to support them however.

Quoted 4 lines

I know it works with various
numbers of threads but is not that because we also control guest linux kernel and, for example, the Other OS (AIX) might be upset on non-multiply-of-2 number of threads?

Quite possibly. I have some plans to add threads support, just haven't got to it yet :-)

Quoted 26 lines
Quoted 8 lines
Quoted 2 lines

PHB is more interesting - how is the user supposed to add more?

That's an open question. Since we model a real P8 chip we can only model the PHBs as they exist on it, which is up to 3 per chip at very specific XSCOM addresses. We could try to model some non-existing P8 chip with more but bad things will happen when the FW try to assign interrupt numbers for example.

 >

Quoted 3 lines

We simulate a machine that has been primed by HostBoot before OPAL starts. So we rely on what the device-tree tells us of what PHB were enabled but appart from that, we have to stick to the limitations.

 >

Quoted 6 lines
Quoted 6 lines

And there always will be the default one
which properties are set in a separate way (via -global, not -device). I found it sometime really annoying to debug the existing pseries which always adds a default PHB (I know, this was to make libvirt happy but this is not the case here).

Quoted 6 lines
Quoted 2 lines

Out of curiosity - if we have 2 chips, will the system work if the second chip does not get any LPC or PHB attached?

This is something I need to look into, there's a lot of work needed to properly model "chips" that I haven't done yet, but what is there is sufficient for a lot of usages already.

Quoted 7 lines

For now, if possible, I'd suggest implementing -nodefaults with no defaults whatsoever and create a config somewhere in the qemu tree to pass it via -readconfig to get reasonably configured machine so people will know what is expected to work but there will still be possibility for experiments (do not we secretly hope that other vendors will start designing/manufacturing their ppc64 chips?). It could be a config file per an actual POWER8 chip (we have two already).

There could be, but we'd need ways to specify a bunch of things, it's not that trivial. IE, the xscom addresses of the 3 ranges for each PHB for example etc.. For now let's keep things simple.

I also am in no hurry to support migration with powernv, so we have quite a bit of flexibility to change things.

Cheers,
Ben.

#119 lore raw

PATCH 42/77 ppc/pnv: Add cut down PSI bridge model and hookup external interrupt

In reply to Benjamin Herrenschmidt

This adds just enough of the PSI bridge to handle various on-chip and the one external interrupt. The rest of PSI has to do with the link to the IBM FSP service processor which we don't plan to emulate (not used on OpenPower machines).

---
 hw/ppc/Makefile.objs |   2 +-
 hw/ppc/pnv.c         |  28 ++-
 hw/ppc/pnv_psi.c     | 594 +++++++++++++++++++++++++++++++++++++++++++++++++++
 include/hw/ppc/pnv.h |  16 ++
 4 files changed, 632 insertions(+), 8 deletions(-)
 create mode 100644 hw/ppc/pnv_psi.c
hw/ppc/Makefile.objs +1 -1
index 5ebf0e0..a5b3ce6 100644
@@ -5,7 +5,7 @@ obj-$(CONFIG_PSERIES) += spapr.o spapr_vio.o spapr_events.o
 obj-$(CONFIG_PSERIES) += spapr_hcall.o spapr_iommu.o spapr_rtas.o
 obj-$(CONFIG_PSERIES) += spapr_pci.o spapr_rtc.o spapr_drc.o spapr_rng.o
 # IBM PowerNV
-obj-$(CONFIG_POWERNV) += pnv.o pnv_xscom.o pnv_lpc.o
+obj-$(CONFIG_POWERNV) += pnv.o pnv_xscom.o pnv_lpc.o pnv_psi.o
 ifeq ($(CONFIG_PCI)$(CONFIG_PSERIES)$(CONFIG_LINUX), yyy)
 obj-y += spapr_pci_vfio.o
 endif
hw/ppc/pnv.c +21 -7
index b4c6dd4..a10fa60 100644
@@ -488,9 +488,22 @@ static const VMStateDescription vmstate_powernv = {
 
 static void pnv_lpc_irq_handler_cpld(void *opaque, int n, int level)
 {
-    /* We don't yet emulate the PSI bridge which provides the external
-     * interrupt, so just drop interrupts on the floor
-     */
+#define MAX_ISA_IRQ 16
+    static uint32_t irqstate;
+    uint32_t old_state = irqstate;
+    PnvPsiController *psi = opaque;
+
+    if (n >= MAX_ISA_IRQ) {
+        return;
+    }
+    if (level) {
+        irqstate |= 1u << n;
+    } else {
+        irqstate &= ~(1u << n);
+    }
+    if (irqstate != old_state) {
+        pnv_psi_irq_set(psi, PSIHB_IRQ_EXTERNAL, irqstate != 0);
+    }
 }
 
 static void pnv_create_chip(PnvSystem *sys, unsigned int chip_no,
@@ -508,6 +521,9 @@ static void pnv_create_chip(PnvSystem *sys, unsigned int chip_no,
     /* Set up XSCOM bus */
     xscom_create(chip);
 
+    /* Create PSI */
+    pnv_psi_create(chip, sys->xics);
+
     /* Create LPC controller */
     if (has_lpc) {
         pnv_lpc_create(chip, has_lpc_irq);
@@ -519,13 +535,11 @@ static void pnv_create_chip(PnvSystem *sys, unsigned int chip_no,
          * have a CPLD that will collect the SerIRQ and shoot them as a
          * single level interrupt to the P8 chip. So let's setup a hook
          * for doing just that.
-         *
-         * Note: The actual interrupt input isn't emulated yet, this will
-         * come with the PSI bridge model.
          */
         if (!has_lpc_irq) {
             isa_bus_irqs(chip->lpc_bus,
-                         qemu_allocate_irqs(pnv_lpc_irq_handler_cpld, NULL, 16));
+                         qemu_allocate_irqs(pnv_lpc_irq_handler_cpld,
+                                            chip->psi, 16));
         }
     }
 }
hw/ppc/pnv_psi.c new file +594 -0

594 lines not on this page · raw message

include/hw/ppc/pnv.h +16 -0
index 77b809a..73bbef9 100644
@@ -23,6 +23,7 @@
 typedef struct XScomBus XScomBus;
 typedef struct ISABus ISABus;
 typedef struct PnvLpcController PnvLpcController;
+typedef struct PnvPsiController PnvPsiController;
 typedef struct XICSState XICSState;
 
 /* Should we turn that into a QOjb of some sort ? */
@@ -31,6 +32,7 @@ typedef struct PnvChip {
     XScomBus         *xscom;
     PnvLpcController *lpc;
     ISABus           *lpc_bus;
+    PnvPsiController *psi;
 } PnvChip;
 
 typedef struct PnvSystem {
@@ -41,5 +43,19 @@ typedef struct PnvSystem {
 } PnvSystem;
 
 extern void pnv_lpc_create(PnvChip *chip, bool has_serirq);
+extern void pnv_psi_create(PnvChip *chip, XICSState *xics);
+
+typedef enum PnvPsiIrq {
+    PSIHB_IRQ_PSI, /* internal use only */
+    PSIHB_IRQ_FSP, /* internal use only */
+    PSIHB_IRQ_OCC,
+    PSIHB_IRQ_FSI,
+    PSIHB_IRQ_LPC_I2C,
+    PSIHB_IRQ_LOCAL_ERR,
+    PSIHB_IRQ_EXTERNAL,
+} PnvPsiIrq;
+
+extern void pnv_psi_irq_set(PnvPsiController *psi, PnvPsiIrq irq, bool state);
+
 #endif /* _HW_PNV_LPC_H */
 
Signature · 1 line
2.5.0
#120 lore raw

PATCH 43/77 ppc/pnv: Add OCC model stub with interrupt support

In reply to Benjamin Herrenschmidt

The OCC is an on-chip microcontroller based on a ppc405 core used for various power management tasks. It comes with a pile of additional hardware sitting on the PIB (aka XSCOM bus). At this point we don't emulate it (nor plan to do so). However there is one facility which is provided by the surrounding hardware that we do need, which is the interrupt generation facility. OPAL uses it to send itself interrupts under some circumstances and there are other uses around the corner.

So this implement just enough to support this.

---
 hw/ppc/Makefile.objs |   2 +-
 hw/ppc/pnv.c         |   3 ++
 hw/ppc/pnv_occ.c     | 125 +++++++++++++++++++++++++++++++++++++++++++++++++++
 include/hw/ppc/pnv.h |   3 ++
 4 files changed, 132 insertions(+), 1 deletion(-)
 create mode 100644 hw/ppc/pnv_occ.c
hw/ppc/Makefile.objs +1 -1
index a5b3ce6..a795b1c 100644
@@ -5,7 +5,7 @@ obj-$(CONFIG_PSERIES) += spapr.o spapr_vio.o spapr_events.o
 obj-$(CONFIG_PSERIES) += spapr_hcall.o spapr_iommu.o spapr_rtas.o
 obj-$(CONFIG_PSERIES) += spapr_pci.o spapr_rtc.o spapr_drc.o spapr_rng.o
 # IBM PowerNV
-obj-$(CONFIG_POWERNV) += pnv.o pnv_xscom.o pnv_lpc.o pnv_psi.o
+obj-$(CONFIG_POWERNV) += pnv.o pnv_xscom.o pnv_lpc.o pnv_psi.o pnv_occ.o
 ifeq ($(CONFIG_PCI)$(CONFIG_PSERIES)$(CONFIG_LINUX), yyy)
 obj-y += spapr_pci_vfio.o
 endif
hw/ppc/pnv.c +3 -0
index a10fa60..ae6efbd 100644
@@ -542,6 +542,9 @@ static void pnv_create_chip(PnvSystem *sys, unsigned int chip_no,
                                             chip->psi, 16));
         }
     }
+
+    /* Create the simplified OCC model */
+    pnv_occ_create(chip);
 }
 
 static void ppc_powernv_init(MachineState *machine)
hw/ppc/pnv_occ.c new file +125 -0

125 lines not on this page · raw message

include/hw/ppc/pnv.h +3 -0
index 73bbef9..c488f12 100644
@@ -25,6 +25,7 @@ typedef struct ISABus ISABus;
 typedef struct PnvLpcController PnvLpcController;
 typedef struct PnvPsiController PnvPsiController;
 typedef struct XICSState XICSState;
+typedef struct PnvOCCState PnvOCCState;
 
 /* Should we turn that into a QOjb of some sort ? */
 typedef struct PnvChip {
@@ -33,6 +34,7 @@ typedef struct PnvChip {
     PnvLpcController *lpc;
     ISABus           *lpc_bus;
     PnvPsiController *psi;
+    PnvOCCState      *occ;
 } PnvChip;
 
 typedef struct PnvSystem {
@@ -44,6 +46,7 @@ typedef struct PnvSystem {
 
 extern void pnv_lpc_create(PnvChip *chip, bool has_serirq);
 extern void pnv_psi_create(PnvChip *chip, XICSState *xics);
+extern void pnv_occ_create(PnvChip *chip);
 
 typedef enum PnvPsiIrq {
     PSIHB_IRQ_PSI, /* internal use only */
Signature · 1 line
2.5.0
#121 lore raw

PATCH 44/77 pci-bridge: Set a supported devfn_min for bridge

In reply to Benjamin Herrenschmidt

Otherwise QEMU might add a device at slot 0 which isn't supported by the SHPC controller.

---
 hw/pci-bridge/pci_bridge_dev.c | 3 +++
 1 file changed, 3 insertions(+)
hw/pci-bridge/pci_bridge_dev.c +3 -0
index 26aded9..c0355c2 100644
@@ -1,3 +1,4 @@
+
 /*
  * Standard PCI Bridge Device
  *
@@ -57,6 +58,8 @@ static int pci_bridge_dev_initfn(PCIDevice *dev)
         goto bridge_error;
     }
     if (bridge_dev->flags & (1 << PCI_BRIDGE_DEV_F_SHPC_REQ)) {
+        /* SHCP gets upset if we try to use slot 0 */
+        br->sec_bus.devfn_min = PCI_FUNC_MAX;
         dev->config[PCI_INTERRUPT_PIN] = 0x1;
         memory_region_init(&bridge_dev->bar, OBJECT(dev), "shpc-bar",
                            shpc_bar_size(dev));
Signature · 1 line
2.5.0
#122 lore raw

Re: [Qemu-devel] [PATCH 44/77] pci-bridge: Set a supported devfn_min for bridge

hw/pci-bridge/pci_bridge_dev.c static int pci_bridge_dev_initfn(PCIDevice *dev) · line 65

Quoted 6 lines · Benjamin Herrenschmidt
     if (bridge_dev->flags & (1 << PCI_BRIDGE_DEV_F_SHPC_REQ)) {
hw/pci-bridge/pci_bridge_dev.c +2 -0
+        /* SHCP gets upset if we try to use slot 0 */
+        br->sec_bus.devfn_min = PCI_FUNC_MAX;
         dev->config[PCI_INTERRUPT_PIN] = 0x1;
         memory_region_init(&bridge_dev->bar, OBJECT(dev), "shpc-bar",
                            shpc_bar_size(dev));

This needs backwards compatibility gunk unfortunately. However we should fix it in 2.5 because it's a bug. I'll send a patch.

Paolo

#123 lore raw

Re: [Qemu-devel] [PATCH for-2.5 44/77] pci-bridge: Set a supported devfn_min for bridge

Quoted 10 lines · Paolo Bonzini

hw/pci-bridge/pci_bridge_dev.c static int pci_bridge_dev_initfn(PCIDevice *dev) · line 65

Quoted 6 lines · Benjamin Herrenschmidt
     if (bridge_dev->flags & (1 << PCI_BRIDGE_DEV_F_SHPC_REQ)) {
hw/pci-bridge/pci_bridge_dev.c +2 -0
+        /* SHCP gets upset if we try to use slot 0 */
+        br->sec_bus.devfn_min = PCI_FUNC_MAX;
         dev->config[PCI_INTERRUPT_PIN] = 0x1;
         memory_region_init(&bridge_dev->bar, OBJECT(dev), "shpc-bar",
                            shpc_bar_size(dev));
Quoted 2 lines

This needs backwards compatibility gunk unfortunately. However we should fix it in 2.5 because it's a bug. I'll send a patch.

Actually it turns out that the forbidden configuration is blocked elsewhere:

$ x86_64-softmmu/qemu-system-x86_64 \
	-device pci-bridge,id=foo,chassis_nr=1 \
	-device virtio-scsi-pci,bus=foo
qemu-system-x86_64: -device virtio-scsi-pci,bus=foo: Unsupported PCI
slot 0 for standard hotplug controller. Valid slots are between 1 and 31.

so this patch is just allowing the above command line to work. There's no effect with or without the patch if addr=0, so the patch is good for 2.5 IMO.

Michael, can you queue it?

Paolo

#124 lore raw

Re: [Qemu-devel] [PATCH for-2.5 44/77] pci-bridge: Set a supported devfn_min for bridge

Quoted 22 lines · Paolo Bonzini
Quoted 10 lines · Paolo Bonzini

hw/pci-bridge/pci_bridge_dev.c static int pci_bridge_dev_initfn(PCIDevice *dev) · line 65

Quoted 6 lines · Benjamin Herrenschmidt
     if (bridge_dev->flags & (1 << PCI_BRIDGE_DEV_F_SHPC_REQ)) {
hw/pci-bridge/pci_bridge_dev.c +2 -0
+        /* SHCP gets upset if we try to use slot 0 */
+        br->sec_bus.devfn_min = PCI_FUNC_MAX;
         dev->config[PCI_INTERRUPT_PIN] = 0x1;
         memory_region_init(&bridge_dev->bar, OBJECT(dev), "shpc-bar",
                            shpc_bar_size(dev));
Quoted 2 lines

This needs backwards compatibility gunk unfortunately. However we should fix it in 2.5 because it's a bug. I'll send a patch.

Actually it turns out that the forbidden configuration is blocked elsewhere:

$ x86_64-softmmu/qemu-system-x86_64 \
	-device pci-bridge,id=foo,chassis_nr=1 \
	-device virtio-scsi-pci,bus=foo
qemu-system-x86_64: -device virtio-scsi-pci,bus=foo: Unsupported PCI
slot 0 for standard hotplug controller. Valid slots are between 1 and 31.
Quoted 7 lines

so this patch is just allowing the above command line to work. There's no effect with or without the patch if addr=0, so the patch is good for 2.5 IMO.

Michael, can you queue it?

Paolo

This depends on the devfn_min thing, right? I'm yet to review it, generally I'd prefer to avoid changing device allocation rules since that makes it so easy to break compatibility.

Assuming addresses are all explicitly stated, is there even a problem?
If not, maybe we can defer everything to after 2.5.

Signature · 1 line
MST
#125 lore raw

Re: [Qemu-devel] [PATCH for-2.5 44/77] pci-bridge: Set a supported devfn_min for bridge

Quoted 7 lines · Michael S. Tsirkin

This depends on the devfn_min thing, right? I'm yet to review it, generally I'd prefer to avoid changing device allocation rules since that makes it so easy to break compatibility.

Assuming addresses are all explicitly stated, is there even a problem?

It makes it a bit easier to use pci-bridge; it is a bug, albeit one that only affects direct usage through the command line of PCI bridges.

Paolo

#126 lore raw

Re: [Qemu-devel] [PATCH for-2.5 44/77] pci-bridge: Set a supported devfn_min for bridge

Quoted 8 lines · Paolo Bonzini
Quoted 5 lines · Michael S. Tsirkin

This depends on the devfn_min thing, right? I'm yet to review it, generally I'd prefer to avoid changing device allocation rules since that makes it so easy to break compatibility.

Quoted 7 lines
Quoted 2 lines

Assuming addresses are all explicitly stated, is there even a problem?

It makes it a bit easier to use pci-bridge; it is a bug, albeit one that only affects direct usage through the command line of PCI bridges.

Paolo

Yes but not a regression ... I'll look at how
invasive the change it depends on is.

#127 lore raw

PATCH 45/77 qdev: Add a hook for a bus to device if it can add devices

In reply to Benjamin Herrenschmidt

This allows a bus class to tell whether a given bus has room for any new device. max_dev isn't sufficient as the rules can depend on some arguments or can differ between instances of a bus. This will be used by PCI in subsequent patches

---
 include/hw/qdev-core.h |  1 +
 qdev-monitor.c         | 13 ++++++++-----
 2 files changed, 9 insertions(+), 5 deletions(-)
include/hw/qdev-core.h +1 -0
index 8057aed..6f3dd8d 100644
@@ -202,6 +202,7 @@ struct BusClass {
      */
     char *(*get_fw_dev_path)(DeviceState *dev);
     void (*reset)(BusState *bus);
+    bool (*can_add_device)(BusState *bus, QemuOpts *opts);
     BusRealize realize;
     BusUnrealize unrealize;
 
qdev-monitor.c +8 -5
index a35098f..4023357 100644
@@ -384,7 +384,7 @@ static inline bool qbus_is_full(BusState *bus)
  * Return the bus if found, else %NULL.
  */
 static BusState *qbus_find_recursive(BusState *bus, const char *name,
-                                     const char *bus_typename)
+                                     const char *bus_typename, QemuOpts *opts)
 {
     BusChild *kid;
     BusState *pick, *child, *ret;
@@ -398,7 +398,10 @@ static BusState *qbus_find_recursive(BusState *bus, const char *name,
     }
 
     if (match && !qbus_is_full(bus)) {
-        return bus;             /* root matches and isn't full */
+        BusClass *bc = BUS_GET_CLASS(bus);
+        if (!bc->can_add_device || bc->can_add_device(bus, opts)) {
+            return bus;             /* root matches and isn't full */
+	}
     }
 
     pick = match ? bus : NULL;
@@ -406,7 +409,7 @@ static BusState *qbus_find_recursive(BusState *bus, const char *name,
     QTAILQ_FOREACH(kid, &bus->children, sibling) {
         DeviceState *dev = kid->child;
         QLIST_FOREACH(child, &dev->child_bus, sibling) {
-            ret = qbus_find_recursive(child, name, bus_typename);
+		ret = qbus_find_recursive(child, name, bus_typename, opts);
             if (ret && !qbus_is_full(ret)) {
                 return ret;     /* a descendant matches and isn't full */
             }
@@ -436,7 +439,7 @@ static BusState *qbus_find(const char *path, Error **errp)
             assert(!path[0]);
             elem[0] = len = 0;
         }
-        bus = qbus_find_recursive(sysbus_get_default(), elem, NULL);
+        bus = qbus_find_recursive(sysbus_get_default(), elem, NULL, NULL);
         if (!bus) {
             error_setg(errp, "Bus '%s' not found", elem);
             return NULL;
@@ -542,7 +545,7 @@ DeviceState *qdev_device_add(QemuOpts *opts, Error **errp)
             return NULL;
         }
     } else if (dc->bus_type != NULL) {
-        bus = qbus_find_recursive(sysbus_get_default(), NULL, dc->bus_type);
+	    bus = qbus_find_recursive(sysbus_get_default(), NULL, dc->bus_type, opts);
         if (!bus || qbus_is_full(bus)) {
             error_setg(errp, "No '%s' bus found for device '%s'",
                        dc->bus_type, driver);
Signature · 1 line
2.5.0
Reviewed-by Acked-by on v1 45/77
#128 lore raw

Re: [Qemu-devel] [PATCH 45/77] qdev: Add a hook for a bus to device if it can add devices

Quoted 49 lines · Benjamin Herrenschmidt

This allows a bus class to tell whether a given bus has room for any new device. max_dev isn't sufficient as the rules can depend on some arguments or can differ between instances of a bus. This will be used by PCI in subsequent patches

---
 include/hw/qdev-core.h |  1 +
 qdev-monitor.c         | 13 ++++++++-----
 2 files changed, 9 insertions(+), 5 deletions(-)
include/hw/qdev-core.h +1 -0
index 8057aed..6f3dd8d 100644
@@ -202,6 +202,7 @@ struct BusClass {
      */
     char *(*get_fw_dev_path)(DeviceState *dev);
     void (*reset)(BusState *bus);
+    bool (*can_add_device)(BusState *bus, QemuOpts *opts);
     BusRealize realize;
     BusUnrealize unrealize;
 
qdev-monitor.c +5 -2
index a35098f..4023357 100644
@@ -384,7 +384,7 @@ static inline bool qbus_is_full(BusState *bus)
  * Return the bus if found, else %NULL.
  */
 static BusState *qbus_find_recursive(BusState *bus, const char *name,
-                                     const char *bus_typename)
+                                     const char *bus_typename, QemuOpts *opts)
 {
     BusChild *kid;
     BusState *pick, *child, *ret;
@@ -398,7 +398,10 @@ static BusState *qbus_find_recursive(BusState *bus, const char *name,
     }
 
     if (match && !qbus_is_full(bus)) {
-        return bus;             /* root matches and isn't full */
+        BusClass *bc = BUS_GET_CLASS(bus);
+        if (!bc->can_add_device || bc->can_add_device(bus, opts)) {
+            return bus;             /* root matches and isn't full */
+	}
     }
 
     pick = match ? bus : NULL;

qdev-monitor.c static BusState *qbus_find_recursive(BusState *bus, const char *name, · line 412

Quoted 5 lines
qdev-monitor.c +1 -1
@@ -406,7 +409,7 @@ static BusState *qbus_find_recursive(BusState *bus, const char *name,
     QTAILQ_FOREACH(kid, &bus->children, sibling) {
         DeviceState *dev = kid->child;
         QLIST_FOREACH(child, &dev->child_bus, sibling) {
-            ret = qbus_find_recursive(child, name, bus_typename);
+		ret = qbus_find_recursive(child, name, bus_typename, opts);

Tabs for indentation. There are other occurrences in the patch.

Apart from this,

Quoted 22 lines
qdev-monitor.c +2 -2
             if (ret && !qbus_is_full(ret)) {
                 return ret;     /* a descendant matches and isn't full */
             }
@@ -436,7 +439,7 @@ static BusState *qbus_find(const char *path, Error **errp)
             assert(!path[0]);
             elem[0] = len = 0;
         }
-        bus = qbus_find_recursive(sysbus_get_default(), elem, NULL);
+        bus = qbus_find_recursive(sysbus_get_default(), elem, NULL, NULL);
         if (!bus) {
             error_setg(errp, "Bus '%s' not found", elem);
             return NULL;
@@ -542,7 +545,7 @@ DeviceState *qdev_device_add(QemuOpts *opts, Error **errp)
             return NULL;
         }
     } else if (dc->bus_type != NULL) {
-        bus = qbus_find_recursive(sysbus_get_default(), NULL, dc->bus_type);
+	    bus = qbus_find_recursive(sysbus_get_default(), NULL, dc->bus_type, opts);
         if (!bus || qbus_is_full(bus)) {
             error_setg(errp, "No '%s' bus found for device '%s'",
                        dc->bus_type, driver);
#129 lore raw

Re: [Qemu-devel] [PATCH 45/77] qdev: Add a hook for a bus to device if it can add devices

On Wed, 2015-11-18 at 13:34 +0100, Paolo Bonzini wrote:

 ../..

Quoted 1 line

Tabs for indentation.  There are other occurrences in the patch.

Ooops. sorry, missed those. Do you need a respin ?

Quoted 34 lines

Apart from this,

Quoted 29 lines

             if (ret && !qbus_is_full(ret)) {
                 return ret;     /* a descendant matches and isn't full */
             }

(quoted diff) +1 -1
@@ -436,7 +439,7 @@ static BusState *qbus_find(const char *path,
 Error **errp)
              assert(!path[0]);
              elem[0] = len = 0;
          }
-        bus = qbus_find_recursive(sysbus_get_default(), elem,
 NULL);
+        bus = qbus_find_recursive(sysbus_get_default(), elem,
 NULL, NULL);

         if (!bus) {
             error_setg(errp, "Bus '%s' not found", elem); return NULL;

(quoted diff) +1 -1
@@ -542,7 +545,7 @@ DeviceState *qdev_device_add(QemuOpts *opts,
 Error **errp)
              return NULL;
          }
      } else if (dc->bus_type != NULL) {
-        bus = qbus_find_recursive(sysbus_get_default(), NULL, dc-
 >bus_type);
+	    bus = qbus_find_recursive(sysbus_get_default(), NULL,
 dc->bus_type, opts);

         if (!bus || qbus_is_full(bus)) { error_setg(errp, "No '%s' bus found for device '%s'", dc->bus_type, driver);

#130 lore raw

PATCH 46/77 pci: Use the new pci_can_add_device() to enforce devfn_min/max

In reply to Benjamin Herrenschmidt

This adds a devfn_max field to PCIBus and adds a pci_can_add_device() function which, if no "addr" (aka devfn) is specified, will tell whether there is any slot free between devfn_min and devfn_max.

This will be used by some PCI root complex implementations that support only one direct child to avoid having qemu put dumb devices at different slot numbers.

---
 hw/pci/pci.c             | 22 ++++++++++++++++++++++
 include/hw/pci/pci_bus.h |  1 +
 2 files changed, 23 insertions(+)
hw/pci/pci.c +22 -0
index 168b9cc..7003f7c 100644
@@ -108,6 +108,27 @@ static uint16_t pcibus_numa_node(PCIBus *bus)
     return NUMA_NODE_UNASSIGNED;
 }
 
+static bool pci_can_add_device(BusState *bus, QemuOpts *opts)
+{
+    unsigned int devfn, max;
+    PCIBus *pbus = PCI_BUS(bus);
+
+    /* If address is specified, say yes and let it fail if that doesn't work */
+    if (qemu_opt_get(opts, "addr") != NULL) {
+        return true;
+    }
+    max = ARRAY_SIZE(pbus->devices);
+    if (pbus->devfn_max && pbus->devfn_max < max) {
+       max = pbus->devfn_max;
+    }
+    for (devfn = pbus->devfn_min ; devfn < max; devfn += PCI_FUNC_MAX) {
+        if (!pbus->devices[devfn]) {
+            break;
+        }
+    }
+    return devfn < max;
+}
+
 static void pci_bus_class_init(ObjectClass *klass, void *data)
 {
     BusClass *k = BUS_CLASS(klass);
@@ -119,6 +140,7 @@ static void pci_bus_class_init(ObjectClass *klass, void *data)
     k->realize = pci_bus_realize;
     k->unrealize = pci_bus_unrealize;
     k->reset = pcibus_reset;
+    k->can_add_device = pci_can_add_device;
 
     pbc->is_root = pcibus_is_root;
     pbc->bus_num = pcibus_num;
include/hw/pci/pci_bus.h +1 -0
index 403fec6..02055d4 100644
@@ -23,6 +23,7 @@ struct PCIBus {
     PCIIOMMUFunc iommu_fn;
     void *iommu_opaque;
     uint8_t devfn_min;
+    uint8_t devfn_max;
     pci_set_irq_fn set_irq;
     pci_map_irq_fn map_irq;
     pci_route_irq_fn route_intx_to_irq;
Signature · 1 line
2.5.0
#131 lore raw

Re: [Qemu-devel] [PATCH 46/77] pci: Use the new pci_can_add_device() to enforce devfn_min/max

Quoted 9 lines · Benjamin Herrenschmidt

This adds a devfn_max field to PCIBus and adds a pci_can_add_device() function which, if no "addr" (aka devfn) is specified, will tell whether there is any slot free between devfn_min and devfn_max.

This will be used by some PCI root complex implementations that support only one direct child to avoid having qemu put dumb devices at different slot numbers.

CCing maintainer.

Paolo

Quoted 58 lines
---
 hw/pci/pci.c             | 22 ++++++++++++++++++++++
 include/hw/pci/pci_bus.h |  1 +
 2 files changed, 23 insertions(+)
hw/pci/pci.c +22 -0
index 168b9cc..7003f7c 100644
@@ -108,6 +108,27 @@ static uint16_t pcibus_numa_node(PCIBus *bus)
     return NUMA_NODE_UNASSIGNED;
 }
 
+static bool pci_can_add_device(BusState *bus, QemuOpts *opts)
+{
+    unsigned int devfn, max;
+    PCIBus *pbus = PCI_BUS(bus);
+
+    /* If address is specified, say yes and let it fail if that doesn't work */
+    if (qemu_opt_get(opts, "addr") != NULL) {
+        return true;
+    }
+    max = ARRAY_SIZE(pbus->devices);
+    if (pbus->devfn_max && pbus->devfn_max < max) {
+       max = pbus->devfn_max;
+    }
+    for (devfn = pbus->devfn_min ; devfn < max; devfn += PCI_FUNC_MAX) {
+        if (!pbus->devices[devfn]) {
+            break;
+        }
+    }
+    return devfn < max;
+}
+
 static void pci_bus_class_init(ObjectClass *klass, void *data)
 {
     BusClass *k = BUS_CLASS(klass);
@@ -119,6 +140,7 @@ static void pci_bus_class_init(ObjectClass *klass, void *data)
     k->realize = pci_bus_realize;
     k->unrealize = pci_bus_unrealize;
     k->reset = pcibus_reset;
+    k->can_add_device = pci_can_add_device;
 
     pbc->is_root = pcibus_is_root;
     pbc->bus_num = pcibus_num;
include/hw/pci/pci_bus.h +1 -0
index 403fec6..02055d4 100644
@@ -23,6 +23,7 @@ struct PCIBus {
     PCIIOMMUFunc iommu_fn;
     void *iommu_opaque;
     uint8_t devfn_min;
+    uint8_t devfn_max;
     pci_set_irq_fn set_irq;
     pci_map_irq_fn map_irq;
     pci_route_irq_fn route_intx_to_irq;
#132 lore raw

PATCH 47/77 pci: Don't call pci_irq_handler() for a negative intx

In reply to Benjamin Herrenschmidt

Under some circumstances, pci_intx() can return -1 (when the interrupt pin in the config space is 0 which normally means no interrupt).

I have seen cases of pci_set_irq() being called on such devices, in turn causing pci_irq_handler() to be called with "-1" as an argument which doesn't seem like a terribly good idea.

---
 hw/pci/pci.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)
hw/pci/pci.c +3 -1
index 7003f7c..b364eff 100644
@@ -1298,7 +1298,9 @@ qemu_irq pci_allocate_irq(PCIDevice *pci_dev)
 void pci_set_irq(PCIDevice *pci_dev, int level)
 {
     int intx = pci_intx(pci_dev);
-    pci_irq_handler(pci_dev, intx, level);
+    if (intx >= 0) {
+        pci_irq_handler(pci_dev, intx, level);
+    }
 }
 
 /* Special hooks used by device assignment */
Signature · 1 line
2.5.0
#133 lore raw

PATCH 48/77 ppc/pnv: Add model for Power8 PHB3 PCIe Host bridge

In reply to Benjamin Herrenschmidt

This is a model of the PCIe host bridge found on Power8 chips, including IOMMU support, PCIe root complex etc...

This implementation doesn't emulate the EEH error handling (and may never do).

---
 hw/intc/xics.c                      |    2 +-
 hw/pci-host/Makefile.objs           |    2 +
 hw/pci-host/pnv_phb3.c              | 1083 +++++++++++++++++++++++++++++++++++
 hw/pci-host/pnv_phb3_msi.c          |  338 +++++++++++
 hw/pci-host/pnv_phb3_pbcq.c         |  314 ++++++++++
 hw/pci-host/pnv_phb3_rc.c           |  132 +++++
 hw/ppc/pnv.c                        |   22 +-
 include/hw/pci-host/pnv_phb3.h      |  145 +++++
 include/hw/pci-host/pnv_phb3_regs.h |  505 ++++++++++++++++
 include/hw/ppc/pnv.h                |    3 +
 include/hw/ppc/xics.h               |    1 +
 11 files changed, 2543 insertions(+), 4 deletions(-)
 create mode 100644 hw/pci-host/pnv_phb3.c
 create mode 100644 hw/pci-host/pnv_phb3_msi.c
 create mode 100644 hw/pci-host/pnv_phb3_pbcq.c
 create mode 100644 hw/pci-host/pnv_phb3_rc.c
 create mode 100644 include/hw/pci-host/pnv_phb3.h
 create mode 100644 include/hw/pci-host/pnv_phb3_regs.h
hw/intc/xics.c +1 -1
index d027a24..eaeb1e1 100644
@@ -341,7 +341,7 @@ void icp_eoi(XICSState *xics, int server, uint32_t xirr)
     }
 }
 
-static void icp_irq(ICSState *ics, int server, int nr, uint8_t priority)
+void icp_irq(ICSState *ics, int server, int nr, uint8_t priority)
 {
     XICSState *xics = ics->xics;
     ICPState *ss = xics->ss + server;
hw/pci-host/Makefile.objs +2 -0
index 45f1f0e..961fe5b 100644
@@ -16,3 +16,5 @@ common-obj-$(CONFIG_FULONG) += bonito.o
 common-obj-$(CONFIG_PCI_PIIX) += piix.o
 common-obj-$(CONFIG_PCI_Q35) += q35.o
 common-obj-$(CONFIG_PCI_GENERIC) += gpex.o
+
+obj-$(CONFIG_POWERNV) += pnv_phb3.o pnv_phb3_pbcq.o pnv_phb3_rc.o pnv_phb3_msi.o
hw/pci-host/pnv_phb3.c new file +1083 -0

1,083 lines not on this page · raw message

hw/pci-host/pnv_phb3_msi.c new file +338 -0

338 lines not on this page · raw message

hw/pci-host/pnv_phb3_pbcq.c new file +314 -0

314 lines not on this page · raw message

hw/pci-host/pnv_phb3_rc.c new file +132 -0

132 lines not on this page · raw message

hw/ppc/pnv.c +19 -3
index ae6efbd..d808802 100644
@@ -44,9 +44,15 @@
 #include "hw/ppc/xics.h"
 #include "hw/ppc/pnv_xscom.h"
 
+#include "hw/pci/pci.h"
+#include "hw/pci/pci_bus.h"
+#include "hw/pci/pci_bridge.h"
+#include "hw/pci/msi.h"
 #include "hw/isa/isa.h"
 #include "hw/char/serial.h"
 #include "hw/timer/mc146818rtc.h"
+#include "hw/pci-host/pnv_phb3.h"
+
 #include "exec/address-spaces.h"
 #include "qemu/config-file.h"
 #include "qemu/error-report.h"
@@ -507,9 +513,11 @@ static void pnv_lpc_irq_handler_cpld(void *opaque, int n, int level)
 }
 
 static void pnv_create_chip(PnvSystem *sys, unsigned int chip_no,
-                            bool has_lpc, bool has_lpc_irq)
+                            bool has_lpc, bool has_lpc_irq,
+                            unsigned int num_phbs)
 {
     PnvChip *chip = &sys->chips[chip_no];
+    unsigned int i;
 
     if (chip_no >= PNV_MAX_CHIPS) {
             return;
@@ -545,6 +553,11 @@ static void pnv_create_chip(PnvSystem *sys, unsigned int chip_no,
 
     /* Create the simplified OCC model */
     pnv_occ_create(chip);
+
+    /* Create a PCI, for now do one chip with 2 PHBs */
+    for (i = 0; i < num_phbs; i++) {
+        pnv_phb3_create(chip, sys->xics, i);
+    }
 }
 
 static void ppc_powernv_init(MachineState *machine)
@@ -568,6 +581,9 @@ static void ppc_powernv_init(MachineState *machine)
     void *fdt;
     int i;
 
+    /* MSIs are supported on this platform */
+    msi_supported = true;
+
     /* Set up Interrupt Controller before we create the VCPUs */
     xics = xics_system_init(smp_cpus * kvmppc_smt_threads() / smp_threads,
                             XICS_IRQS_POWERNV);
@@ -607,9 +623,9 @@ static void ppc_powernv_init(MachineState *machine)
      */
     sys->num_chips = 1;
 
-    /* Create only one chip for now with an LPC bus
+    /* Create only one chip for now with an LPC bus and one PHB
      */
-    pnv_create_chip(sys, 0, true, false);
+    pnv_create_chip(sys, 0, true, false, 1);
 
     /* Grab chip 0's ISA bus */
     isa_bus = sys->chips[0].lpc_bus;
include/hw/pci-host/pnv_phb3.h new file +145 -0

145 lines not on this page · raw message

include/hw/pci-host/pnv_phb3_regs.h new file +505 -0

505 lines not on this page · raw message

include/hw/ppc/pnv.h +3 -0
index c488f12..98d75b0 100644
@@ -26,6 +26,7 @@ typedef struct PnvLpcController PnvLpcController;
 typedef struct PnvPsiController PnvPsiController;
 typedef struct XICSState XICSState;
 typedef struct PnvOCCState PnvOCCState;
+typedef struct PCIBus PCIBus;
 
 /* Should we turn that into a QOjb of some sort ? */
 typedef struct PnvChip {
@@ -35,6 +36,8 @@ typedef struct PnvChip {
     ISABus           *lpc_bus;
     PnvPsiController *psi;
     PnvOCCState      *occ;
+#define PNV_MAX_CHIP_PHB	4
+    PCIBus           *phb[PNV_MAX_CHIP_PHB];
 } PnvChip;
 
 typedef struct PnvSystem {
include/hw/ppc/xics.h +1 -0
index 85d2fb9..31dab8b 100644
@@ -205,6 +205,7 @@ void icp_set_mfrr(XICSState *icp, int server, uint8_t mfrr);
 uint32_t icp_accept(ICPState *ss);
 uint32_t icp_ipoll(ICPState *ss, uint32_t *mfrr);
 void icp_eoi(XICSState *icp, int server, uint32_t xirr);
+void icp_irq(ICSState *ics, int server, int nr, uint8_t priority);
 
 void ics_simple_write_xive(ICSState *ics, int nr, int server,
                            uint8_t priority, uint8_t saved_priority);
Signature · 1 line
2.5.0
#134 lore raw

Re: [Qemu-devel] [Qemu-ppc] [PATCH 48/77] ppc/pnv: Add model for Power8 PHB3 PCIe Host bridge

Ben,

Quick question,

Quoted 48 lines
hw/pci-host/pnv_phb3.c new file +48 -0
+/* This is called whenever the PHB LSI, MSI source ID register or
+ * the PBCQ irq filters are written.
+ */
+void pnv_phb3_remap_irqs(PnvPhb3State *phb)
+{
+    uint32_t local, global, count, mask, comp;
+    uint64_t baren;
+
+    /* First check if we are enabled. Unlike real HW we don't separate TX and RX
+     * so we enable if both are set
+     */
+    baren = phb->pbcq->nest_regs[PBCQ_NEST_BAR_EN];
+    if (!(baren & PBCQ_NEST_BAR_EN_IRSN_RX) ||
+        !(baren & PBCQ_NEST_BAR_EN_IRSN_TX)) {
+        phb->lsi_ics->offset = 0;
+        return;
+    }
+
+    /* Grab local LSI source ID */
+    local = GETFIELD(PHB_LSI_SRC_ID, phb->regs[PHB_LSI_SOURCE_ID >> 3]) << 3;
+
+    /* Grab global one and compare */
+    global = GETFIELD(PBCQ_NEST_LSI_SRC,
+                      phb->pbcq->nest_regs[PBCQ_NEST_LSI_SRC_ID]) << 3;
+    if (global != local) {
+        /* This happens during initialization, let's come back when we
+         * are properly configured
+         */
+        phb->lsi_ics->offset = 0;
+        return;
+    }
+
+    /* Get the base on the powerbus */
+    comp = GETFIELD(PBCQ_NEST_IRSN_COMP,
+                    phb->pbcq->nest_regs[PBCQ_NEST_IRSN_COMPARE]);
+    mask = GETFIELD(PBCQ_NEST_IRSN_COMP,
+                    phb->pbcq->nest_regs[PBCQ_NEST_IRSN_MASK]);
+    count = ((~mask) + 1) & 0x7ffff;
+    phb->total_irq = count;
+
+    /* Sanity checks */
+    if ((global + 8) > count) {
+        DBG_MAP(phb, "LSIs out of reach: LSI base=%d total irq=%d",
+                global, count);
+    }
+    if (count > 2048) {
+        DBG_MAP(phb, "More interrupts than supported: %d", count);
+    }

hw/pci-host/pnv_phb3.c line 420

Quoted 10 lines
hw/pci-host/pnv_phb3.c new file +10 -0
+    if ((comp & mask) != comp) {
+        DBG_MAP(phb, "IRQ compare bits not in mask: comp=0x%x mask=0x%x",
+                comp, mask);
+        comp &= mask;
+    }
+    /* Setup LSI offset */
+    phb->lsi_ics->offset = comp + global;
+
+    /* Setup MSI offset */
+    pnv_phb3_msi_update_config(phb->msis, comp, count);

I changed that to :

    pnv_phb3_msi_update_config(phb->msis, comp, count - PHB_NUM_LSI);

else the IRQ numbers overlap with the LSI and I think this why we were uselessly looping on the EOI.

Correct ?

C.

Quoted 5 lines
hw/pci-host/pnv_phb3.c new file +5 -0
+
+    DBG_MAP(phb, "Initialized for %d interrupts @0x%x, LSI off=%d",
+            count, comp, global);
+}
+
#135 lore raw

Re: [Qemu-devel] [Qemu-ppc] [PATCH 48/77] ppc/pnv: Add model for Power8 PHB3 PCIe Host bridge

Quoted 9 lines · Cédric Le Goater

I changed that to :

    pnv_phb3_msi_update_config(phb->msis, comp, count - PHB_NUM_LSI);

else the IRQ numbers overlap with the LSI and I think this why we were
uselessly looping on the EOI.

Correct ?

Quite possibly though to be honest, I have swapped out a lot of that out of my brain :-)

Cheers,
Ben.

#136 lore raw

PATCH 49/77 ppc/pnv: Create a default PCI layout

In reply to Benjamin Herrenschmidt

This creates a legacy PCIe->PCI bridge under the PHB by default to which a bunch of standard devices are attached. Currently:

- VGA (as specified by -vga)
- USB (with keyboard and mouse if graphcis is enabled)
- AHCI
- e1000

This gives us something close to a standard OpenPower platform.

---
 hw/ppc/pnv.c | 99 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 98 insertions(+), 1 deletion(-)
hw/ppc/pnv.c +98 -1
index d808802..179f93b 100644
@@ -52,6 +52,9 @@
 #include "hw/char/serial.h"
 #include "hw/timer/mc146818rtc.h"
 #include "hw/pci-host/pnv_phb3.h"
+#include "hw/usb.h"
+#include "hw/ide/pci.h"
+#include "hw/ide/ahci.h"
 
 #include "exec/address-spaces.h"
 #include "qemu/config-file.h"
@@ -85,6 +88,9 @@ typedef struct sPowerNVMachineState sPowerNVMachineState;
 /**
  * sPowerNVMachineState:
  */
+
+#define MAX_SATA_PORTS     6
+
 struct sPowerNVMachineState {
     /*< private >*/
     MachineState parent_obj;
@@ -492,6 +498,71 @@ static const VMStateDescription vmstate_powernv = {
     .minimum_version_id = 1,
 };
 
+/* Returns whether we want to use VGA or not */
+static int pnv_vga_init(PCIBus *pci_bus)
+{
+    switch (vga_interface_type) {
+    case VGA_NONE:
+        return false;
+    case VGA_DEVICE:
+        return true;
+    case VGA_STD:
+    case VGA_VIRTIO:
+        return pci_vga_init(pci_bus) != NULL;
+    default:
+        fprintf(stderr, "This vga model is not supported,"
+                "currently it only supports -vga std\n");
+        exit(0);
+    }
+}
+
+static void pnv_nic_init(PCIBus *pci_bus)
+{
+    int i;
+
+    for (i = 0; i < nb_nics; i++) {
+        NICInfo *nd = &nd_table[i];
+        DeviceState *dev;
+        PCIDevice *pdev;
+        Error *err = NULL;
+
+        pdev = pci_create(pci_bus, -1, "e1000");
+        dev = &pdev->qdev;
+        qdev_set_nic_properties(dev, nd);
+        object_property_set_bool(OBJECT(dev), true, "realized", &err);
+        if (err) {
+            error_report_err(err);
+            object_unparent(OBJECT(dev));
+            exit(1);
+        }
+    }
+}
+
+static void pnv_storage_init(PCIBus *pci_bus)
+{
+    DriveInfo *hd[MAX_SATA_PORTS];
+    PCIDevice *ahci;
+
+    /* Add an AHCI device. We use an ICH9 since that's all we have
+     * at hand for PCI AHCI but it shouldn't really matter
+     */
+    ahci = pci_create_simple(pci_bus, -1, "ich9-ahci");
+    g_assert(MAX_SATA_PORTS == ICH_AHCI(ahci)->ahci.ports);
+    ide_drive_get(hd, ICH_AHCI(ahci)->ahci.ports);
+    ahci_ide_create_devs(ahci, hd);
+}
+
+static PCIBus *pnv_create_pci_legacy_bridge(PCIBus *parent, uint8_t chassis_nr)
+{
+    PCIDevice *dev;
+
+    dev = pci_create_multifunction(parent, 0, false, "pci-bridge");
+    qdev_prop_set_uint8(&dev->qdev, "chassis_nr", chassis_nr);
+    dev->qdev.id = "pci";
+    qdev_init_nofail(&dev->qdev);
+    return pci_bridge_get_sec_bus(PCI_BRIDGE(dev));
+}
+
 static void pnv_lpc_irq_handler_cpld(void *opaque, int n, int level)
 {
 #define MAX_ISA_IRQ 16
@@ -575,7 +646,9 @@ static void ppc_powernv_init(MachineState *machine)
     sPowerNVMachineState *pnv_machine = POWERNV_MACHINE(machine);
     PnvSystem *sys = &pnv_machine->sys;
     XICSState *xics;
+    PCIBus *pbus;
     ISABus *isa_bus;
+    bool has_gfx = false;
     long fw_size;
     char *filename;
     void *fdt;
@@ -636,6 +709,30 @@ static void ppc_powernv_init(MachineState *machine)
     /* Create an RTC ISA device too */
     rtc_init(isa_bus, 2000, NULL);
 
+    /* Add a PCI switch */
+    pbus = pnv_create_pci_legacy_bridge(sys->chips[0].phb[0], 128);
+
+    /* Graphics */
+    if (pnv_vga_init(pbus)) {
+        has_gfx = true;
+        machine->usb |= defaults_enabled() && !machine->usb_disabled;
+    }
+    if (machine->usb) {
+        pci_create_simple(pbus, -1, "nec-usb-xhci");
+        if (has_gfx) {
+            USBBus *usb_bus = usb_bus_find(-1);
+
+            usb_create_simple(usb_bus, "usb-kbd");
+            usb_create_simple(usb_bus, "usb-mouse");
+        }
+    }
+
+    /* Add NIC */
+    pnv_nic_init(pbus);
+
+    /* Add storage */
+    pnv_storage_init(pbus);
+
     if (bios_name == NULL) {
         bios_name = FW_FILE_NAME;
     }
@@ -709,7 +806,7 @@ static void powernv_machine_class_init(ObjectClass *oc, void *data)
     NMIClass *nc = NMI_CLASS(oc);
 
     mc->init = ppc_powernv_init;
-    mc->block_default_type = IF_SCSI;
+    mc->block_default_type = IF_IDE;
     mc->max_cpus = MAX_CPUS;
     mc->no_parallel = 1;
     mc->default_boot_order = NULL;
Signature · 1 line
2.5.0
#137 lore raw

PATCH 50/77 ppc: Update LPCR definitions

In reply to Benjamin Herrenschmidt

Includes all the bits up to ISA 2.07

---
 target-ppc/cpu.h | 16 +++++++++++++---
 1 file changed, 13 insertions(+), 3 deletions(-)
target-ppc/cpu.h +13 -3
index a7236cf..ca6c961 100644
@@ -493,12 +493,16 @@ struct ppc_slb_t {
 #define LPCR_VPM1         (1ull << (63-1))
 #define LPCR_ISL          (1ull << (63-2))
 #define LPCR_KBV          (1ull << (63-3))
+#define LPCR_DPFD_SHIFT   (63-11)
+#define LPCR_DPFD         (0x3ull << LPCR_DPFD_SHIFT)
+#define LPCR_VRMASD_SHIFT (63-16)
+#define LPCR_VRMASD       (0x1full << LPCR_VRMASD_SHIFT)
+#define LPCR_RMLS_SHIFT   (63-37)
+#define LPCR_RMLS         (0xfull << LPCR_RMLS_SHIFT)
 #define LPCR_ILE          (1ull << (63-38))
-#define LPCR_MER          (1ull << (63-52))
-#define LPCR_LPES0        (1ull << (63-60))
-#define LPCR_LPES1        (1ull << (63-61))
 #define LPCR_AIL_SHIFT    (63-40)      /* Alternate interrupt location */
 #define LPCR_AIL          (3ull << LPCR_AIL_SHIFT)
+#define LPCR_ONL          (1ull << (63-45))
 #define LPCR_P7_PECE0     (1ull << (63-49))
 #define LPCR_P7_PECE1     (1ull << (63-50))
 #define LPCR_P7_PECE2     (1ull << (63-51))
@@ -507,6 +511,12 @@ struct ppc_slb_t {
 #define LPCR_P8_PECE2     (1ull << (63-49))
 #define LPCR_P8_PECE3     (1ull << (63-50))
 #define LPCR_P8_PECE4     (1ull << (63-51))
+#define LPCR_MER          (1ull << (63-52))
+#define LPCR_TC           (1ull << (63-54))
+#define LPCR_LPES0        (1ull << (63-60))
+#define LPCR_LPES1        (1ull << (63-61))
+#define LPCR_RMI          (1ull << (63-62))
+#define LPCR_HDICE        (1ull << (63-63))
 
 #define msr_sf   ((env->msr >> MSR_SF)   & 1)
 #define msr_isf  ((env->msr >> MSR_ISF)  & 1)
Signature · 1 line
2.5.0
#138 lore raw

PATCH 51/77 ppc: Use a helper to filter writes to LPCR

In reply to Benjamin Herrenschmidt

This handles filtering bits based on what is implemented by a given architecture version. We also use it to copy to LPCR some of the relevant 970 HID4 bits.

---
 target-ppc/helper.h         |  1 +
 target-ppc/mmu-hash64.c     | 58 +++++++++++++++++++++++++++++++++++++++++++++
 target-ppc/translate_init.c | 56 ++++++++++++++++++++++++++++---------------
 3 files changed, 96 insertions(+), 19 deletions(-)
target-ppc/helper.h +1 -0
index 8292dd8..23889fe 100644
@@ -16,6 +16,7 @@ DEF_HELPER_1(rfmci, void, env)
 DEF_HELPER_2(pminsn, void, env, i32)
 DEF_HELPER_1(rfid, void, env)
 DEF_HELPER_1(hrfid, void, env)
+DEF_HELPER_2(store_lpcr, void, env, tl)
 #endif
 DEF_HELPER_1(check_tlb_flush, void, env)
 #endif
target-ppc/mmu-hash64.c +58 -0

61 lines not on this page · raw message

target-ppc/translate_init.c +37 -19

75 lines not on this page · raw message

Signature · 1 line
2.5.0
#139 lore raw

PATCH 52/77 ppc: Cosmetic, align some comments

In reply to Benjamin Herrenschmidt
---
 target-ppc/mmu-hash32.c | 4 ++--
 target-ppc/mmu_helper.c | 8 ++++----
 2 files changed, 6 insertions(+), 6 deletions(-)
target-ppc/mmu-hash32.c +2 -2
index dfee358..a2f4ce2 100644
@@ -41,8 +41,8 @@
 
 struct mmu_ctx_hash32 {
     hwaddr raddr;      /* Real address              */
-    int prot;                      /* Protection bits           */
-    int key;                       /* Access key                */
+    int prot;          /* Protection bits           */
+    int key;           /* Access key                */
 };
 
 static int ppc_hash32_pp_prot(int key, int pp, int nx)
target-ppc/mmu_helper.c +4 -4
index 54bc5d1..18d34cc 100644
@@ -58,11 +58,11 @@ typedef struct mmu_ctx_t mmu_ctx_t;
 struct mmu_ctx_t {
     hwaddr raddr;      /* Real address              */
     hwaddr eaddr;      /* Effective address         */
-    int prot;                      /* Protection bits           */
+    int prot;          /* Protection bits           */
     hwaddr hash[2];    /* Pagetable hash values     */
-    target_ulong ptem;             /* Virtual segment ID | API  */
-    int key;                       /* Access key                */
-    int nx;                        /* Non-execute area          */
+    target_ulong ptem; /* Virtual segment ID | API  */
+    int key;           /* Access key                */
+    int nx;            /* Non-execute area          */
 };
 
 /* Common routines used by software and hardware TLBs emulation */
Signature · 1 line
2.5.0
#140 lore raw

PATCH 53/77 ppc: Add proper real mode translation support

In reply to Benjamin Herrenschmidt

This adds proper support for translating real mode addresses based on the combination of HV and LPCR bits. This handles HRMOR offset for hypervisor real mode, and both RMA and VRMA modes for guest real mode. PAPR mode adjusts the offsets appropriately to match the RMA used in TCG, but we need to limit to the max supported by the implementation (16G).

---
 hw/ppc/spapr.c              |   7 +++
 target-ppc/mmu-hash64.c     | 146 ++++++++++++++++++++++++++++++++++++++------
 target-ppc/mmu-hash64.h     |   1 +
 target-ppc/translate_init.c |  10 ++-
 4 files changed, 144 insertions(+), 20 deletions(-)
hw/ppc/spapr.c +7 -0
index d8a84ca..13fe2d5 100644
@@ -1741,6 +1741,13 @@ static void ppc_spapr_init(MachineState *machine)
             spapr->vrma_adjust = 1;
             spapr->rma_size = MIN(spapr->rma_size, 0x10000000);
         }
+
+        /* Actually we don't support unbounded RMA anymore since we
+         * added proper emulation of HV mode. The max we can get is
+         * 16G which also happens to be what we configure for PAPR
+         * mode so make sure we don't do anything bigger than that
+         */
+        spapr->rma_size = MIN(spapr->rma_size, 0x400000000ull);
     }
 
     if (spapr->rma_size > node0_size) {
target-ppc/mmu-hash64.c +127 -19

213 lines not on this page · raw message

target-ppc/mmu-hash64.h +1 -0
index 291750f..729f718 100644
@@ -29,6 +29,7 @@ void ppc_hash64_store_hpte(CPUPPCState *env, target_ulong index,
 #define SLB_VSID_B_256M         0x0000000000000000ULL
 #define SLB_VSID_B_1T           0x4000000000000000ULL
 #define SLB_VSID_VSID           0x3FFFFFFFFFFFF000ULL
+#define SLB_VSID_VRMA           (0x0001FFFFFF000000ULL | SLB_VSID_B_1T)
 #define SLB_VSID_PTEM           (SLB_VSID_B | SLB_VSID_VSID)
 #define SLB_VSID_KS             0x0000000000000800ULL
 #define SLB_VSID_KP             0x0000000000000400ULL
target-ppc/translate_init.c +9 -1
index 853a084..504564d 100644
@@ -8558,11 +8558,19 @@ void cpu_ppc_set_papr(PowerPCCPU *cpu)
     /* Set emulated LPCR to not send interrupts to hypervisor. Note that
      * under KVM, the actual HW LPCR will be set differently by KVM itself,
      * the settings below ensure proper operations with TCG in absence of
-     * a real hypervisor
+     * a real hypervisor.
+     *
+     * Clearing VPM0 will also cause us to use RMOR in mmu-hash64.c for
+     * real mode accesses, which thankfully defaults to 0 and isn't
+     * accessible in guest mode.
      */
     lpcr->default_value &= ~(LPCR_VPM0 | LPCR_VPM1 | LPCR_ISL | LPCR_KBV);
     lpcr->default_value |= LPCR_LPES0 | LPCR_LPES1;
 
+    /* Set RMLS to the max (ie, 16G) */
+    lpcr->default_value &= ~LPCR_RMLS;
+    lpcr->default_value |= 1ull << LPCR_RMLS_SHIFT;
+
     /* P7 and P8 has slightly different PECE bits, mostly because P8 adds
      * bit 47 and 48 which are reserved on P7. Here we set them all, which
      * will work as expected for both implementations
Signature · 1 line
2.5.0
#141 lore raw

PATCH 54/77 ppc: Fix 64K pages support in full emulation

In reply to Benjamin Herrenschmidt

We were always advertising only 4K & 16M. Additionally the code wasn't properly matching the page size with the PTE content, which meant we could potentially hit an incorrect PTE if the guest used multiple sizes.

Finally, honor the CPU capabilities when decoding the size from the SLB so we don't try to use 64K pages on 970.

This still doesn't add support for MPSS (Multiple Page Sizes per Segment)

---
 hw/ppc/spapr_hcall.c        | 10 +++------
 target-ppc/cpu.h            |  7 ++++--
 target-ppc/mmu-hash64.c     | 54 +++++++++++++++++++++++++++++++++++----------
 target-ppc/translate_init.c | 22 +++++++++++++++---
 4 files changed, 69 insertions(+), 24 deletions(-)
hw/ppc/spapr_hcall.c +3 -7
index 7e2cb4b..ba1bcaf 100644
@@ -56,7 +56,6 @@ static target_ulong compute_tlbie_rb(target_ulong v, target_ulong r,
     va_low &= 0x7ff;
     if (v & HPTE64_V_LARGE) {
         rb |= 1;                         /* L field */
-#if 0 /* Disable that P7 specific bit for now */
         if (r & 0xff000) {
             /* non-16MB large page, must be 64k */
             /* (masks depend on page size) */
@@ -64,7 +63,6 @@ static target_ulong compute_tlbie_rb(target_ulong v, target_ulong r,
             rb |= (va_low & 0x7f) << 16; /* 7b of VA in AVA/LP field */
             rb |= (va_low & 0xfe);       /* AVAL field */
         }
-#endif
     } else {
         /* 4kB page */
         rb |= (va_low & 0x7ff) << 12;   /* remaining 11b of AVA */
@@ -98,14 +96,12 @@ static target_ulong h_enter(PowerPCCPU *cpu, sPAPRMachineState *spapr,
     target_ulong index;
     uint64_t token;
 
-    /* only handle 4k and 16M pages for now */
+    /* Handle non-4K pages */
     if (pteh & HPTE64_V_LARGE) {
-#if 0 /* We don't support 64k pages yet */
         if ((ptel & 0xf000) == 0x1000) {
             /* 64k page */
-        } else
-#endif
-        if ((ptel & 0xff000) == 0) {
+            page_shift = 16;
+        } else if ((ptel & 0xff000) == 0) {
             /* 16M page */
             page_shift = 24;
             /* lowest AVA bit must be 0 for 16M pages */
target-ppc/cpu.h +5 -2
index ca6c961..3fc3e1d 100644
@@ -115,16 +115,19 @@ enum powerpc_mmu_t {
 #define POWERPC_MMU_64       0x00010000
 #define POWERPC_MMU_1TSEG    0x00020000
 #define POWERPC_MMU_AMR      0x00040000
+#define POWERPC_MMU_64K      0x00080000
     /* 64 bits PowerPC MMU                                     */
     POWERPC_MMU_64B        = POWERPC_MMU_64 | 0x00000001,
     /* Architecture 2.03 and later (has LPCR) */
     POWERPC_MMU_2_03       = POWERPC_MMU_64 | 0x00000002,
     /* Architecture 2.06 variant                               */
     POWERPC_MMU_2_06       = POWERPC_MMU_64 | POWERPC_MMU_1TSEG
-                             | POWERPC_MMU_AMR | 0x00000003,
+                             | POWERPC_MMU_AMR | POWERPC_MMU_64K
+                             | 0x00000003,
     /* Architecture 2.07 variant                               */
     POWERPC_MMU_2_07       = POWERPC_MMU_64 | POWERPC_MMU_1TSEG
-                             | POWERPC_MMU_AMR | 0x00000004,
+                             | POWERPC_MMU_AMR | POWERPC_MMU_64K
+                             | 0x00000004,
 #endif /* defined(TARGET_PPC64) */
 };
 
target-ppc/mmu-hash64.c +42 -12

120 lines not on this page · raw message

target-ppc/translate_init.c +19 -3
index 504564d..b623206 100644
@@ -9998,8 +9998,8 @@ static void ppc_cpu_initfn(Object *obj)
     if (pcc->sps) {
         env->sps = *pcc->sps;
     } else if (env->mmu_model & POWERPC_MMU_64) {
-        /* Use default sets of page sizes */
-        static const struct ppc_segment_page_sizes defsps = {
+	/* Use default sets of page sizes. We don't support MPSS */
+        static const struct ppc_segment_page_sizes defsps_4k = {
             .sps = {
                 { .page_shift = 12, /* 4K */
                   .slb_enc = 0,
@@ -10011,7 +10011,23 @@ static void ppc_cpu_initfn(Object *obj)
                 },
             },
         };
-        env->sps = defsps;
+        static const struct ppc_segment_page_sizes defsps_64k = {
+            .sps = {
+                { .page_shift = 12, /* 4K */
+                  .slb_enc = 0,
+                  .enc = { { .page_shift = 12, .pte_enc = 0 } }
+                },
+                { .page_shift = 16, /* 64K */
+                  .slb_enc = 0x110,
+                  .enc = { { .page_shift = 16, .pte_enc = 1 } }
+                },
+                { .page_shift = 24, /* 16M */
+                  .slb_enc = 0x100,
+                  .enc = { { .page_shift = 24, .pte_enc = 0 } }
+                },
+            },
+        };
+        env->sps = (env->mmu_model & POWERPC_MMU_64K) ? defsps_64k : defsps_4k;
     }
 #endif /* defined(TARGET_PPC64) */
 
Signature · 1 line
2.5.0
#142 lore raw

PATCH 55/77 ppc/pnv+spapr: Add "ibm, pa-features" property to the device-tree

In reply to Benjamin Herrenschmidt

This is currently missing on both PowerNV and PAPR

FIXME: Split patch & fix tabs

---
 hw/ppc/pnv.c                | 8 ++++++++
 target-ppc/translate_init.c | 1 +
 2 files changed, 9 insertions(+)
hw/ppc/pnv.c +8 -0
index 179f93b..1787dd1 100644
@@ -275,6 +275,11 @@ static void powernv_create_cpu_node(void *fdt, CPUState *cs, int smt_threads)
     uint32_t page_sizes_prop[64];
     size_t page_sizes_prop_size;
     char *nodename;
+    const uint8_t pa_features[] = { 24, 0,
+                                    0xf6, 0x3f, 0xc7, 0xc0, 0x80, 0xf0,
+                                    0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
+                                    0x00, 0x00, 0x00, 0x00, 0x80, 0x00,
+                                    0x80, 0x00, 0x80, 0x00, 0x80, 0x00 };
 
     if ((index % smt_threads) != 0) {
         return;
@@ -349,6 +354,9 @@ static void powernv_create_cpu_node(void *fdt, CPUState *cs, int smt_threads)
                            page_sizes_prop, page_sizes_prop_size)));
     }
 
+    _FDT((fdt_property(fdt, "ibm,pa-features",
+                       pa_features, sizeof(pa_features))));
+
     /* XXX Just a hack for now */
     _FDT((fdt_property_cell(fdt, "ibm,chip-id", 0)));
 
target-ppc/translate_init.c +1 -0
index b623206..25f5b18 100644
@@ -10028,6 +10028,7 @@ static void ppc_cpu_initfn(Object *obj)
             },
         };
         env->sps = (env->mmu_model & POWERPC_MMU_64K) ? defsps_64k : defsps_4k;
+	env->ci_large_pages = env->mmu_model >= POWERPC_MMU_2_06;
     }
 #endif /* defined(TARGET_PPC64) */
 
Signature · 1 line
2.5.0
#143 lore raw

PATCH 56/77 ppc: Fix conditions for delivering external interrupts to a guest

In reply to Benjamin Herrenschmidt

External interrupts can bypass the MSR_EE test if they occur in guest mode and LPES0 is clear. In that case they are directed to the hypervisor

---
 target-ppc/excp_helper.c | 19 ++++++++-----------
 1 file changed, 8 insertions(+), 11 deletions(-)
target-ppc/excp_helper.c +8 -11
index 3f77df7..eb65eee 100644
@@ -795,6 +795,14 @@ static void ppc_hw_interrupt(CPUPPCState *env)
             return;
         }
     }
+    /* Extermal interrupt can ignore MSR:EE under some circumstances */
+    if (env->pending_interrupts & (1 << PPC_INTERRUPT_EXT)) {
+        bool lpes0 = !!(env->spr[SPR_LPCR] & LPCR_LPES0);
+        if (msr_ee != 0 || (env->has_hv_mode && msr_hv == 0 && !lpes0)) {
+            powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_EXTERNAL);
+            return;
+        }
+    }
     if (msr_ce != 0) {
         /* External critical interrupt */
         if (env->pending_interrupts & (1 << PPC_INTERRUPT_CEXT)) {
@@ -840,17 +848,6 @@ static void ppc_hw_interrupt(CPUPPCState *env)
             powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_DECR);
             return;
         }
-        /* External interrupt */
-        if (env->pending_interrupts & (1 << PPC_INTERRUPT_EXT)) {
-            /* Taking an external interrupt does not clear the external
-             * interrupt status
-             */
-#if 0
-            env->pending_interrupts &= ~(1 << PPC_INTERRUPT_EXT);
-#endif
-            powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_EXTERNAL);
-            return;
-        }
         if (env->pending_interrupts & (1 << PPC_INTERRUPT_DOORBELL)) {
             env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DOORBELL);
             powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_DOORI);
Signature · 1 line
2.5.0
#144 lore raw

PATCH 57/77 ppc: Enforce setting MSR:EE, IR and DR when MSR:PR is set

In reply to Benjamin Herrenschmidt

The architecture specifies that any instruction that sets MSR:PR will also set MSR:EE, IR and DR.

---
 target-ppc/helper_regs.h | 4 ++++
 1 file changed, 4 insertions(+)
target-ppc/helper_regs.h +4 -0
index 12af61c..09bc450 100644
@@ -136,6 +136,10 @@ static inline int hreg_store_msr(CPUPPCState *env, target_ulong value,
         /* Change the exception prefix on PowerPC 601 */
         env->excp_prefix = ((value >> MSR_EP) & 1) * 0xFFF00000;
     }
+    /* If PR=1 then EE, IR and DR must be 1 */
+    if ((value >> MSR_PR) & 1) {
+        value |= (1 << MSR_EE) | (1 << MSR_DR) | (1 << MSR_IR);
+    }
 #endif
     env->msr = value;
     hreg_compute_hflags(env);
Signature · 1 line
2.5.0
#145 lore raw

PATCH 58/77 ppc: Initial HDEC support

In reply to Benjamin Herrenschmidt

The current behaviour isn't completely right, as for the DEC, we don't properly re-arm when wrapping around, but I will fix this in a separate patch.

---
 hw/ppc/ppc.c                 | 17 ++++++++++++-----
 target-ppc/excp_helper.c     | 22 ++++++++++++----------
 target-ppc/helper.h          |  2 ++
 target-ppc/timebase_helper.c | 10 ++++++++++
 target-ppc/translate_init.c  | 30 ++++++++++++++++++++++++++++++
 5 files changed, 66 insertions(+), 15 deletions(-)
hw/ppc/ppc.c +12 -5
index 3b14f09..ac3f65c 100644
@@ -698,9 +698,18 @@ static inline void cpu_ppc_decr_lower(PowerPCCPU *cpu)
 
 static inline void cpu_ppc_hdecr_excp(PowerPCCPU *cpu)
 {
+    CPUPPCState *env = &cpu->env;
+
     /* Raise it */
-    LOG_TB("raise decrementer exception\n");
-    ppc_set_irq(cpu, PPC_INTERRUPT_HDECR, 1);
+    LOG_TB("raise hv decrementer exception\n");
+
+    /* The architecture specifies that we don't deliver HDEC
+     * interrupts in a PM state. Not only they don't cause a
+     * wakeup but they also get effectively discarded.
+     */
+    if (!env->in_pm_state) {
+        ppc_set_irq(cpu, PPC_INTERRUPT_HDECR, 1);
+    }
 }
 
 static inline void cpu_ppc_hdecr_lower(PowerPCCPU *cpu)
@@ -927,9 +936,7 @@ clk_setup_cb cpu_ppc_tb_init (CPUPPCState *env, uint32_t freq)
     }
     /* Create new timer */
     tb_env->decr_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, &cpu_ppc_decr_cb, cpu);
-    if (0) {
-        /* XXX: find a suitable condition to enable the hypervisor decrementer
-         */
+    if (env->has_hv_mode) {
         tb_env->hdecr_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, &cpu_ppc_hdecr_cb,
                                                 cpu);
     } else {
target-ppc/excp_helper.c +12 -10
index eb65eee..28a529a 100644
@@ -753,7 +753,6 @@ void ppc_cpu_do_interrupt(CPUState *cs)
 static void ppc_hw_interrupt(CPUPPCState *env)
 {
     PowerPCCPU *cpu = ppc_env_get_cpu(env);
-    int hdice;
 #if 0
     CPUState *cs = CPU(cpu);
 
@@ -782,15 +781,13 @@ static void ppc_hw_interrupt(CPUPPCState *env)
         return;
     }
 #endif
-    if (0) {
-        /* XXX: find a suitable condition to enable the hypervisor mode */
-        hdice = env->spr[SPR_LPCR] & 1;
-    } else {
-        hdice = 0;
-    }
-    if ((msr_ee != 0 || msr_hv == 0 || msr_pr != 0) && hdice != 0) {
-        /* Hypervisor decrementer exception */
-        if (env->pending_interrupts & (1 << PPC_INTERRUPT_HDECR)) {
+    /* Hypervisor decrementer exception */
+    if (env->pending_interrupts & (1 << PPC_INTERRUPT_HDECR)) {
+        /* LPCR will be clear when not supported so this will work */
+        bool hdice = !!(env->spr[SPR_LPCR] & LPCR_HDICE);
+        if ((msr_ee != 0 || msr_hv == 0) && hdice) {
+            /* HDEC clears on delivery */
+            env->pending_interrupts &= ~(1 << PPC_INTERRUPT_HDECR);
             powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_HDECR);
             return;
         }
@@ -942,6 +939,11 @@ void helper_pminsn(CPUPPCState *env, powerpc_pm_insn_t insn)
     cs->halted = 1;
     env->in_pm_state = true;
 
+    /* The architecture specifies that HDEC interrupts are
+     * discarded in PM states
+     */
+    env->pending_interrupts &= ~(1 << PPC_INTERRUPT_HDECR);
+
     /* Technically, nap doesn't set EE, but if we don't set it
      * then ppc_hw_interrupt() won't deliver. We could add some
      * other tests there based on LPCR but it's simpler to just
target-ppc/helper.h +2 -0
index 23889fe..9890920 100644
@@ -598,6 +598,8 @@ DEF_HELPER_2(store_601_rtcl, void, env, tl)
 DEF_HELPER_2(store_601_rtcu, void, env, tl)
 DEF_HELPER_1(load_decr, tl, env)
 DEF_HELPER_2(store_decr, void, env, tl)
+DEF_HELPER_1(load_hdecr, tl, env)
+DEF_HELPER_2(store_hdecr, void, env, tl)
 DEF_HELPER_2(store_hid0_601, void, env, tl)
 DEF_HELPER_3(store_403_pbr, void, env, i32, tl)
 DEF_HELPER_1(load_40x_pit, tl, env)
target-ppc/timebase_helper.c +10 -0
index 865dcbe..798b803 100644
@@ -100,6 +100,16 @@ void helper_store_decr(CPUPPCState *env, target_ulong val)
     cpu_ppc_store_decr(env, val);
 }
 
+target_ulong helper_load_hdecr(CPUPPCState *env)
+{
+    return cpu_ppc_load_hdecr(env);
+}
+
+void helper_store_hdecr(CPUPPCState *env, target_ulong val)
+{
+    cpu_ppc_store_hdecr(env, val);
+}
+
 target_ulong helper_load_40x_pit(CPUPPCState *env)
 {
     return load_40x_pit(env);
target-ppc/translate_init.c +30 -0
index 25f5b18..06061e2 100644
@@ -292,6 +292,32 @@ static void spr_read_purr (DisasContext *ctx, int gprn, int sprn)
 {
     gen_helper_load_purr(cpu_gpr[gprn], cpu_env);
 }
+
+/* HDECR */
+static void spr_read_hdecr (DisasContext *ctx, int gprn, int sprn)
+{
+    if (ctx->tb->cflags & CF_USE_ICOUNT) {
+        gen_io_start();
+    }
+    gen_helper_load_hdecr(cpu_gpr[gprn], cpu_env);
+    if (ctx->tb->cflags & CF_USE_ICOUNT) {
+        gen_io_end();
+        gen_stop_exception(ctx);
+    }
+}
+
+static void spr_write_hdecr (DisasContext *ctx, int sprn, int gprn)
+{
+    if (ctx->tb->cflags & CF_USE_ICOUNT) {
+        gen_io_start();
+    }
+    gen_helper_store_hdecr(cpu_env, cpu_gpr[gprn]);
+    if (ctx->tb->cflags & CF_USE_ICOUNT) {
+        gen_io_end();
+        gen_stop_exception(ctx);
+    }
+}
+
 #endif
 #endif
 
@@ -7716,6 +7742,10 @@ static void gen_spr_power5p_lpar(CPUPPCState *env)
                      SPR_NOACCESS, SPR_NOACCESS,
                      &spr_read_generic, &spr_write_lpcr,
                      KVM_REG_PPC_LPCR, LPCR_LPES0 | LPCR_LPES1);
+    spr_register_hv(env, SPR_HDEC, "HDEC",
+                    SPR_NOACCESS, SPR_NOACCESS,
+                    SPR_NOACCESS, SPR_NOACCESS,
+                    &spr_read_hdecr, &spr_write_hdecr, 0);
 #endif
 }
 
Signature · 1 line
2.5.0
#146 lore raw

PATCH 59/77 ppc: Add placeholder SPRs for DPDES and DHDES on P8

In reply to Benjamin Herrenschmidt

We still need to eventually implement doorbells but at least this makes us not crash when the SPRs are accessed.

---
 target-ppc/cpu.h            |  2 ++
 target-ppc/translate_init.c | 17 +++++++++++++++++
 2 files changed, 19 insertions(+)
target-ppc/cpu.h +2 -0
index 3fc3e1d..099b8da 100644
@@ -1395,6 +1395,8 @@ static inline int cpu_mmu_index (CPUPPCState *env, bool ifetch)
 #define SPR_UAMOR             (0x09D)
 #define SPR_MPC_ICTRL         (0x09E)
 #define SPR_MPC_BAR           (0x09F)
+#define SPR_DHDES             (0x0B1)
+#define SPR_DPDES             (0x0B0)
 #define SPR_DAWR              (0x0B4)
 #define SPR_RPR               (0x0BA)
 #define SPR_DAWRX             (0x0BC)
target-ppc/translate_init.c +17 -0
index 06061e2..bfc7a6d 100644
@@ -8059,6 +8059,22 @@ static void gen_spr_power8_rpr(CPUPPCState *env)
 #endif
 }
 
+static void gen_spr_power8_dbell(CPUPPCState *env)
+{
+#if !defined(CONFIG_USER_ONLY)
+    spr_register_hv(env, SPR_DPDES, "DPDES",
+                    SPR_NOACCESS, SPR_NOACCESS,
+                    &spr_read_generic, SPR_NOACCESS,
+                    &spr_read_generic, &spr_write_generic,
+                    0);
+    spr_register_hv(env, SPR_DHDES, "DHDES",
+                    SPR_NOACCESS, SPR_NOACCESS,
+                    SPR_NOACCESS, SPR_NOACCESS,
+                    &spr_read_generic, &spr_write_generic,
+                    0);
+#endif
+}
+
 static void init_proc_book3s_64(CPUPPCState *env, int version)
 {
     gen_spr_ne_601(env);
@@ -8111,6 +8127,7 @@ static void init_proc_book3s_64(CPUPPCState *env, int version)
         gen_spr_power8_tm(env);
         gen_spr_vtb(env);
         gen_spr_power8_rpr(env);
+        gen_spr_power8_dbell(env);
     }
     if (version < BOOK3S_CPU_POWER8) {
         gen_spr_book3s_dbg(env);
Signature · 1 line
2.5.0
#147 lore raw

PATCH 60/77 ppc: LPCR is a HV resource

In reply to Benjamin Herrenschmidt

Don't allow access in guest mode

---
 target-ppc/translate_init.c | 9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)
target-ppc/translate_init.c +5 -4
index bfc7a6d..e3887e7 100644
@@ -7738,10 +7738,11 @@ static void gen_spr_power5p_lpar(CPUPPCState *env)
 {
 #if !defined(CONFIG_USER_ONLY)
     /* Logical partitionning */
-    spr_register_kvm(env, SPR_LPCR, "LPCR",
-                     SPR_NOACCESS, SPR_NOACCESS,
-                     &spr_read_generic, &spr_write_lpcr,
-                     KVM_REG_PPC_LPCR, LPCR_LPES0 | LPCR_LPES1);
+    spr_register_kvm_hv(env, SPR_LPCR, "LPCR",
+                        SPR_NOACCESS, SPR_NOACCESS,
+                        SPR_NOACCESS, SPR_NOACCESS,
+                        &spr_read_generic, &spr_write_lpcr,
+                        KVM_REG_PPC_LPCR, LPCR_LPES0 | LPCR_LPES1);
     spr_register_hv(env, SPR_HDEC, "HDEC",
                     SPR_NOACCESS, SPR_NOACCESS,
                     SPR_NOACCESS, SPR_NOACCESS,
Signature · 1 line
2.5.0
#148 lore raw

PATCH 61/77 ppc: SPURR & PURR are HV writeable and privileged

In reply to Benjamin Herrenschmidt

Those are HV writeable, so we provide a dummy write. We eventually need to provide a better emulation but for now this will get us going.

We also make them non-user readable as per the architecture.

---
 target-ppc/translate_init.c | 24 ++++++++++++++++--------
 1 file changed, 16 insertions(+), 8 deletions(-)
target-ppc/translate_init.c +16 -8
index e3887e7..e2efdf3 100644
@@ -293,6 +293,12 @@ static void spr_read_purr (DisasContext *ctx, int gprn, int sprn)
     gen_helper_load_purr(cpu_gpr[gprn], cpu_env);
 }
 
+__attribute__ (( unused ))
+static void spr_write_purr (DisasContext *ctx, int gprn, int sprn)
+{
+    // Temporary placeholder
+}
+
 /* HDECR */
 static void spr_read_hdecr (DisasContext *ctx, int gprn, int sprn)
 {
@@ -7860,14 +7866,16 @@ static void gen_spr_book3s_purr(CPUPPCState *env)
 {
 #if !defined(CONFIG_USER_ONLY)
     /* PURR & SPURR: Hack - treat these as aliases for the TB for now */
-    spr_register_kvm(env, SPR_PURR,   "PURR",
-                     &spr_read_purr, SPR_NOACCESS,
-                     &spr_read_purr, SPR_NOACCESS,
-                     KVM_REG_PPC_PURR, 0x00000000);
-    spr_register_kvm(env, SPR_SPURR,   "SPURR",
-                     &spr_read_purr, SPR_NOACCESS,
-                     &spr_read_purr, SPR_NOACCESS,
-                     KVM_REG_PPC_SPURR, 0x00000000);
+    spr_register_kvm_hv(env, SPR_PURR,   "PURR",
+                        SPR_NOACCESS, SPR_NOACCESS,
+                        &spr_read_purr, SPR_NOACCESS,
+                        &spr_read_purr, &spr_write_purr,
+                        KVM_REG_PPC_PURR, 0x00000000);
+    spr_register_kvm_hv(env, SPR_SPURR,   "SPURR",
+                        SPR_NOACCESS, SPR_NOACCESS,
+                        &spr_read_purr, SPR_NOACCESS,
+                        &spr_read_purr, &spr_write_purr,
+                        KVM_REG_PPC_SPURR, 0x00000000);
 #endif
 }
 
Signature · 1 line
2.5.0
#149 lore raw

PATCH 62/77 ppc: Add dummy SPR_IC for POWER8

In reply to Benjamin Herrenschmidt

It's supposed to be an instruction counter. For now make us not crash when accessing it.

---
 target-ppc/cpu.h            |  1 +
 target-ppc/translate_init.c | 12 ++++++++++++
 2 files changed, 13 insertions(+)
target-ppc/cpu.h +1 -0
index 099b8da..eb94244 100644
@@ -1690,6 +1690,7 @@ static inline int cpu_mmu_index (CPUPPCState *env, bool ifetch)
 #define SPR_MPC_MD_DBRAM1     (0x32A)
 #define SPR_RCPU_L2U_RA3      (0x32B)
 #define SPR_TAR               (0x32F)
+#define SPR_IC                (0x350)
 #define SPR_VTB               (0x351)
 #define SPR_MMCRC             (0x353)
 #define SPR_440_INV0          (0x370)
target-ppc/translate_init.c +12 -0
index e2efdf3..f3f6cf5 100644
@@ -8084,6 +8084,17 @@ static void gen_spr_power8_dbell(CPUPPCState *env)
 #endif
 }
 
+static void gen_spr_power8_ic(CPUPPCState *env)
+{
+#if !defined(CONFIG_USER_ONLY)
+    spr_register_hv(env, SPR_IC, "IC",
+                    SPR_NOACCESS, SPR_NOACCESS,
+                    &spr_read_generic, SPR_NOACCESS,
+                    &spr_read_generic, &spr_write_generic,
+                    0);
+#endif
+}
+
 static void init_proc_book3s_64(CPUPPCState *env, int version)
 {
     gen_spr_ne_601(env);
@@ -8137,6 +8148,7 @@ static void init_proc_book3s_64(CPUPPCState *env, int version)
         gen_spr_vtb(env);
         gen_spr_power8_rpr(env);
         gen_spr_power8_dbell(env);
+        gen_spr_power8_ic(env);
     }
     if (version < BOOK3S_CPU_POWER8) {
         gen_spr_book3s_dbg(env);
Signature · 1 line
2.5.0
#150 lore raw

PATCH 63/77 ppc: Initialize AMOR in PAPR mode

In reply to Benjamin Herrenschmidt

Make sure we give the guest full authorization

---
 target-ppc/translate_init.c | 4 ++++
 1 file changed, 4 insertions(+)
target-ppc/translate_init.c +4 -0
index f3f6cf5..df24b97 100644
@@ -8615,6 +8615,7 @@ void cpu_ppc_set_papr(PowerPCCPU *cpu)
 {
     CPUPPCState *env = &cpu->env;
     ppc_spr_t *lpcr = &env->spr_cb[SPR_LPCR];
+    ppc_spr_t *amor = &env->spr_cb[SPR_AMOR];
 
     /* PAPR always has exception vectors in RAM not ROM. To ensure this,
      * MSR[IP] should never be set.
@@ -8651,6 +8652,9 @@ void cpu_ppc_set_papr(PowerPCCPU *cpu)
      */
     env->spr[SPR_LPCR] = lpcr->default_value;
 
+    /* Set a full AMOR so guest can use the AMR as it sees fit */
+    env->spr[SPR_AMOR] = amor->default_value = 0xffffffffffffffffull;
+
     /* Tell KVM that we're in PAPR mode */
     if (kvm_enabled()) {
         kvmppc_set_papr(cpu);
Signature · 1 line
2.5.0
#151 lore raw

PATCH 64/77 ppc: Fix writing to AMR/UAMOR

In reply to Benjamin Herrenschmidt

The masks weren't chosen nor applied properly. The architecture specifies that writes to AMR are masked by UAMOR for PR=1, otherwise AMOR for HV=0.

The writes to UAMOR are masked by AMOR for HV=0

---
 target-ppc/translate_init.c | 76 +++++++++++++++++++++++++++++++++++----------
 1 file changed, 60 insertions(+), 16 deletions(-)
target-ppc/translate_init.c +60 -16
index df24b97..aa9eecf 100644
@@ -1094,30 +1094,72 @@ static void gen_spr_7xx (CPUPPCState *env)
 
 #ifdef TARGET_PPC64
 #ifndef CONFIG_USER_ONLY
-static void spr_read_uamr (DisasContext *ctx, int gprn, int sprn)
+static void spr_write_amr (DisasContext *ctx, int sprn, int gprn)
 {
-    gen_load_spr(cpu_gpr[gprn], SPR_AMR);
-    spr_load_dump_spr(SPR_AMR);
-}
+    TCGv t0 = tcg_temp_new();
+    TCGv t1 = tcg_temp_new();
+    TCGv t2 = tcg_temp_new();
 
-static void spr_write_uamr (DisasContext *ctx, int sprn, int gprn)
-{
-    gen_store_spr(SPR_AMR, cpu_gpr[gprn]);
+    /* Note, the HV=1 PR=0 case is handled earlier by simply using
+     * spr_write_generic for HV mode in the SPR table
+     */
+
+    /* Build insertion mask into t1 based on context */
+    if (ctx->pr) {
+	gen_load_spr(t1, SPR_UAMOR);
+    } else {
+        gen_load_spr(t1, SPR_AMOR);
+    }
+
+    /* Mask new bits into t2 */
+    tcg_gen_and_tl(t2, t1, cpu_gpr[gprn]);
+
+    /* Load AMR and clear new bits in t0 */
+    gen_load_spr(t0, SPR_AMR);
+    tcg_gen_andc_tl(t0, t0, t1);
+
+    /* Or'in new bits and write it out */
+    tcg_gen_or_tl(t0, t0, t2);
+    gen_store_spr(SPR_AMR, t0);
     spr_store_dump_spr(SPR_AMR);
+
+    tcg_temp_free(t0);
+    tcg_temp_free(t1);
+    tcg_temp_free(t2);
 }
 
-static void spr_write_uamr_pr (DisasContext *ctx, int sprn, int gprn)
+static void spr_write_uamor (DisasContext *ctx, int sprn, int gprn)
 {
     TCGv t0 = tcg_temp_new();
+    TCGv t1 = tcg_temp_new();
+    TCGv t2 = tcg_temp_new();
+
+    /* Note, the HV=1 case is handled earlier by simply using
+     * spr_write_generic for HV mode in the SPR table
+     */
 
+    /* Build insertion mask into t1 based on context */
+    gen_load_spr(t1, SPR_AMOR);
+
+    /* Mask new bits into t2 */
+    tcg_gen_and_tl(t2, t1, cpu_gpr[gprn]);
+
+    /* Load AMR and clear new bits in t0 */
     gen_load_spr(t0, SPR_UAMOR);
-    tcg_gen_and_tl(t0, t0, cpu_gpr[gprn]);
-    gen_store_spr(SPR_AMR, t0);
-    spr_store_dump_spr(SPR_AMR);
+    tcg_gen_andc_tl(t0, t0, t1);
+
+    /* Or'in new bits and write it out */
+    tcg_gen_or_tl(t0, t0, t2);
+    gen_store_spr(SPR_UAMOR, t0);
+    spr_store_dump_spr(SPR_UAMOR);
+
+    tcg_temp_free(t0);
+    tcg_temp_free(t1);
+    tcg_temp_free(t2);
 }
 #endif /* CONFIG_USER_ONLY */
 
-static void gen_spr_amr (CPUPPCState *env)
+static void gen_spr_amr (CPUPPCState *env, bool has_iamr)
 {
 #ifndef CONFIG_USER_ONLY
     /* Virtual Page Class Key protection */
@@ -1125,15 +1167,17 @@ static void gen_spr_amr (CPUPPCState *env)
      * userspace accessible, 29 is privileged.  So we only need to set
      * the kvm ONE_REG id on one of them, we use 29 */
     spr_register(env, SPR_UAMR, "UAMR",
-                 &spr_read_uamr, &spr_write_uamr_pr,
-                 &spr_read_uamr, &spr_write_uamr,
+                 &spr_read_generic, &spr_write_amr,
+                 &spr_read_generic, &spr_write_amr,
                  0);
-    spr_register_kvm(env, SPR_AMR, "AMR",
+    spr_register_kvm_hv(env, SPR_AMR, "AMR",
                      SPR_NOACCESS, SPR_NOACCESS,
+                     &spr_read_generic, &spr_write_amr,
                      &spr_read_generic, &spr_write_generic,
                      KVM_REG_PPC_AMR, 0);
-    spr_register_kvm(env, SPR_UAMOR, "UAMOR",
+    spr_register_kvm_hv(env, SPR_UAMOR, "UAMOR",
                      SPR_NOACCESS, SPR_NOACCESS,
+                     &spr_read_generic, &spr_write_uamor,
                      &spr_read_generic, &spr_write_generic,
                      KVM_REG_PPC_UAMOR, 0);
     spr_register_hv(env, SPR_AMOR, "AMOR",
Signature · 1 line
2.5.0
#152 lore raw

PATCH 65/77 ppc: Add POWER8 IAMR register

In reply to Benjamin Herrenschmidt

With appropriate AMR-like masks. Not actually used by the translation logic at that point

---
 target-ppc/cpu.h            |  1 +
 target-ppc/translate_init.c | 40 +++++++++++++++++++++++++++++++++++++++-
 2 files changed, 40 insertions(+), 1 deletion(-)
target-ppc/cpu.h +1 -0
index eb94244..756a66f 100644
@@ -1366,6 +1366,7 @@ static inline int cpu_mmu_index (CPUPPCState *env, bool ifetch)
 #define SPR_BOOKE_CSRR0       (0x03A)
 #define SPR_BOOKE_CSRR1       (0x03B)
 #define SPR_BOOKE_DEAR        (0x03D)
+#define SPR_IAMR              (0x03D)
 #define SPR_BOOKE_ESR         (0x03E)
 #define SPR_BOOKE_IVPR        (0x03F)
 #define SPR_MPC_EIE           (0x050)
target-ppc/translate_init.c +39 -1
index aa9eecf..eaa2ac5 100644
@@ -1157,6 +1157,36 @@ static void spr_write_uamor (DisasContext *ctx, int sprn, int gprn)
     tcg_temp_free(t1);
     tcg_temp_free(t2);
 }
+
+static void spr_write_iamr (DisasContext *ctx, int sprn, int gprn)
+{
+    TCGv t0 = tcg_temp_new();
+    TCGv t1 = tcg_temp_new();
+    TCGv t2 = tcg_temp_new();
+
+    /* Note, the HV=1 case is handled earlier by simply using
+     * spr_write_generic for HV mode in the SPR table
+     */
+
+    /* Build insertion mask into t1 based on context */
+    gen_load_spr(t1, SPR_AMOR);
+
+    /* Mask new bits into t2 */
+    tcg_gen_and_tl(t2, t1, cpu_gpr[gprn]);
+
+    /* Load AMR and clear new bits in t0 */
+    gen_load_spr(t0, SPR_IAMR);
+    tcg_gen_andc_tl(t0, t0, t1);
+
+    /* Or'in new bits and write it out */
+    tcg_gen_or_tl(t0, t0, t2);
+    gen_store_spr(SPR_IAMR, t0);
+    spr_store_dump_spr(SPR_IAMR);
+
+    tcg_temp_free(t0);
+    tcg_temp_free(t1);
+    tcg_temp_free(t2);
+}
 #endif /* CONFIG_USER_ONLY */
 
 static void gen_spr_amr (CPUPPCState *env, bool has_iamr)
@@ -1185,6 +1215,14 @@ static void gen_spr_amr (CPUPPCState *env, bool has_iamr)
                     SPR_NOACCESS, SPR_NOACCESS,
                     &spr_read_generic, &spr_write_generic,
                     0);
+    if (!has_iamr) {
+        return;
+    }
+    spr_register_hv(env, SPR_IAMR, "IAMR",
+                    SPR_NOACCESS, SPR_NOACCESS,
+                    &spr_read_generic, &spr_write_iamr,
+                    &spr_read_generic, &spr_write_generic,
+                    0);
 #endif /* !CONFIG_USER_ONLY */
 }
 #endif /* TARGET_PPC64 */
@@ -8160,7 +8198,7 @@ static void init_proc_book3s_64(CPUPPCState *env, int version)
     case BOOK3S_CPU_POWER7:
     case BOOK3S_CPU_POWER8:
         gen_spr_book3s_ids(env);
-        gen_spr_amr(env);
+        gen_spr_amr(env, version >= BOOK3S_CPU_POWER8);
         gen_spr_book3s_purr(env);
         env->ci_large_pages = true;
         break;
Signature · 1 line
2.5.0
#153 lore raw

PATCH 66/77 ppc: Add a few more P8 PMU SPRs

In reply to Benjamin Herrenschmidt
---
 target-ppc/cpu.h            |  7 +++++++
 target-ppc/translate_init.c | 28 ++++++++++++++++++++++++++++
 2 files changed, 35 insertions(+)
target-ppc/cpu.h +7 -0
index 756a66f..f7e653b 100644
@@ -1591,6 +1591,7 @@ static inline int cpu_mmu_index (CPUPPCState *env, bool ifetch)
 #define SPR_PERF0             (0x300)
 #define SPR_RCPU_MI_RBA0      (0x300)
 #define SPR_MPC_MI_CTR        (0x300)
+#define SPR_POWER_USIER       (0x300)
 #define SPR_PERF1             (0x301)
 #define SPR_RCPU_MI_RBA1      (0x301)
 #define SPR_POWER_UMMCR2      (0x301)
@@ -1640,6 +1641,7 @@ static inline int cpu_mmu_index (CPUPPCState *env, bool ifetch)
 #define SPR_PERFF             (0x30F)
 #define SPR_MPC_MD_TW         (0x30F)
 #define SPR_UPERF0            (0x310)
+#define SPR_POWER_SIER        (0x310)
 #define SPR_UPERF1            (0x311)
 #define SPR_POWER_MMCR2       (0x311)
 #define SPR_UPERF2            (0x312)
@@ -1703,7 +1705,12 @@ static inline int cpu_mmu_index (CPUPPCState *env, bool ifetch)
 #define SPR_440_ITV2          (0x376)
 #define SPR_440_ITV3          (0x377)
 #define SPR_440_CCR1          (0x378)
+#define SPR_TACR              (0x378)
+#define SPR_TCSCR             (0x379)
+#define SPR_CSIGR             (0x37a)
 #define SPR_DCRIPR            (0x37B)
+#define SPR_POWER_SPMC1       (0x37C)
+#define SPR_POWER_SPMC2       (0x37D)
 #define SPR_POWER_MMCRS       (0x37E)
 #define SPR_PPR               (0x380)
 #define SPR_750_GQR0          (0x390)
target-ppc/translate_init.c +28 -0
index eaa2ac5..08730b6 100644
@@ -7764,6 +7764,30 @@ static void gen_spr_power8_pmu_sup(CPUPPCState *env)
                      SPR_NOACCESS, SPR_NOACCESS,
                      &spr_read_generic, &spr_write_generic,
                      KVM_REG_PPC_MMCRS, 0x00000000);
+    spr_register_kvm(env, SPR_POWER_SIER, "SIER",
+                     SPR_NOACCESS, SPR_NOACCESS,
+                     &spr_read_generic, &spr_write_generic,
+                     KVM_REG_PPC_SIER, 0x00000000);
+    spr_register_kvm(env, SPR_POWER_SPMC1, "SPMC1",
+                     SPR_NOACCESS, SPR_NOACCESS,
+                     &spr_read_generic, &spr_write_generic,
+                     KVM_REG_PPC_SPMC1, 0x00000000);
+    spr_register_kvm(env, SPR_POWER_SPMC2, "SPMC2",
+                     SPR_NOACCESS, SPR_NOACCESS,
+                     &spr_read_generic, &spr_write_generic,
+                     KVM_REG_PPC_SPMC2, 0x00000000);
+    spr_register_kvm(env, SPR_TACR, "TACR",
+                     SPR_NOACCESS, SPR_NOACCESS,
+                     &spr_read_generic, &spr_write_generic,
+                     KVM_REG_PPC_TACR, 0x00000000);
+    spr_register_kvm(env, SPR_TCSCR, "TCSCR",
+                     SPR_NOACCESS, SPR_NOACCESS,
+                     &spr_read_generic, &spr_write_generic,
+                     KVM_REG_PPC_TCSCR, 0x00000000);
+    spr_register_kvm(env, SPR_CSIGR, "CSIGR",
+                     SPR_NOACCESS, SPR_NOACCESS,
+                     &spr_read_generic, &spr_write_generic,
+                     KVM_REG_PPC_CSIGR, 0x00000000);
 }
 
 static void gen_spr_power8_pmu_user(CPUPPCState *env)
@@ -7772,6 +7796,10 @@ static void gen_spr_power8_pmu_user(CPUPPCState *env)
                  &spr_read_ureg, SPR_NOACCESS,
                  &spr_read_ureg, &spr_write_ureg,
                  0x00000000);
+    spr_register(env, SPR_POWER_USIER, "USIER",
+                 &spr_read_generic, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+		 0x00000000);
 }
 
 static void gen_spr_power5p_ear(CPUPPCState *env)
Signature · 1 line
2.5.0
#154 lore raw

PATCH 67/77 ppc: Add dummy write to VTB

In reply to Benjamin Herrenschmidt

The Hypervisor can write it. We don't handle that properly yet but at least let's not blow up when it is written.

---
 target-ppc/translate_init.c | 15 +++++++++++----
 1 file changed, 11 insertions(+), 4 deletions(-)
target-ppc/translate_init.c +11 -4
index 08730b6..4ad2c94 100644
@@ -299,6 +299,12 @@ static void spr_write_purr (DisasContext *ctx, int gprn, int sprn)
     // Temporary placeholder
 }
 
+__attribute__ (( unused ))
+static void spr_write_vtb (DisasContext *ctx, int gprn, int sprn)
+{
+    // Temporary placeholder
+}
+
 /* HDECR */
 static void spr_read_hdecr (DisasContext *ctx, int gprn, int sprn)
 {
@@ -8148,10 +8154,11 @@ static void gen_spr_power8_ebb(CPUPPCState *env)
 /* Virtual Time Base */
 static void gen_spr_vtb(CPUPPCState *env)
 {
-    spr_register(env, SPR_VTB, "VTB",
-                 SPR_NOACCESS, SPR_NOACCESS,
-                 &spr_read_tbl, SPR_NOACCESS,
-                 0x00000000);
+    spr_register_hv(env, SPR_VTB, "VTB",
+                   SPR_NOACCESS, SPR_NOACCESS,
+                   &spr_read_tbl, SPR_NOACCESS,
+                   &spr_read_tbl, spr_write_vtb,
+                   0x00000000);
 }
 
 static void gen_spr_power8_fscr(CPUPPCState *env)
Signature · 1 line
2.5.0
#155 lore raw

PATCH 68/77 ppc: Add dummy POWER8 MPPR register

In reply to Benjamin Herrenschmidt

Controls the micropartition prefetch, this is pretty much meaningless in full emulation (used for priming the caches on real HW).

---
 target-ppc/cpu.h            |  1 +
 target-ppc/translate_init.c | 13 +++++++++++++
 2 files changed, 14 insertions(+)
target-ppc/cpu.h +1 -0
index f7e653b..253d04b 100644
@@ -1399,6 +1399,7 @@ static inline int cpu_mmu_index (CPUPPCState *env, bool ifetch)
 #define SPR_DHDES             (0x0B1)
 #define SPR_DPDES             (0x0B0)
 #define SPR_DAWR              (0x0B4)
+#define SPR_MPPR              (0x0B8)
 #define SPR_RPR               (0x0BA)
 #define SPR_DAWRX             (0x0BC)
 #define SPR_HFSCR             (0x0BE)
target-ppc/translate_init.c +13 -0
index 4ad2c94..a178696 100644
@@ -8212,6 +8212,18 @@ static void gen_spr_power8_ic(CPUPPCState *env)
 #endif
 }
 
+static void gen_spr_power8_book4(CPUPPCState *env)
+{
+    /* Add a number of P8 book4 registers */
+#if !defined(CONFIG_USER_ONLY)
+    spr_register_hv(env, SPR_MPPR, "MPPR",
+                    SPR_NOACCESS, SPR_NOACCESS,
+                    &spr_read_generic, SPR_NOACCESS,
+                    &spr_read_generic, &spr_write_generic,
+                    0);
+#endif
+}
+
 static void init_proc_book3s_64(CPUPPCState *env, int version)
 {
     gen_spr_ne_601(env);
@@ -8266,6 +8278,7 @@ static void init_proc_book3s_64(CPUPPCState *env, int version)
         gen_spr_power8_rpr(env);
         gen_spr_power8_dbell(env);
         gen_spr_power8_ic(env);
+        gen_spr_power8_book4(env);
     }
     if (version < BOOK3S_CPU_POWER8) {
         gen_spr_book3s_dbg(env);
Signature · 1 line
2.5.0
#156 lore raw

PATCH 69/77 ppc: Add dummy POWER8 PSPB SPR

In reply to Benjamin Herrenschmidt

On real hardware it allows temporary thread priority boosts, we don't do threads and implementing it would be fairly tricky, so we just dummy it or now.

---
 target-ppc/cpu.h            |  1 +
 target-ppc/translate_init.c | 11 +++++++++++
 2 files changed, 12 insertions(+)
target-ppc/cpu.h +1 -0
index 253d04b..334fcfe 100644
@@ -1396,6 +1396,7 @@ static inline int cpu_mmu_index (CPUPPCState *env, bool ifetch)
 #define SPR_UAMOR             (0x09D)
 #define SPR_MPC_ICTRL         (0x09E)
 #define SPR_MPC_BAR           (0x09F)
+#define SPR_PSPB              (0x09F)
 #define SPR_DHDES             (0x0B1)
 #define SPR_DPDES             (0x0B0)
 #define SPR_DAWR              (0x0B4)
target-ppc/translate_init.c +11 -0
index a178696..b1eba73 100644
@@ -8224,6 +8224,16 @@ static void gen_spr_power8_book4(CPUPPCState *env)
 #endif
 }
 
+static void gen_spr_power8_pspb(CPUPPCState *env)
+{
+#if !defined(CONFIG_USER_ONLY)
+    spr_register(env, SPR_PSPB, "PSPB",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0);
+#endif
+}
+
 static void init_proc_book3s_64(CPUPPCState *env, int version)
 {
     gen_spr_ne_601(env);
@@ -8278,6 +8288,7 @@ static void init_proc_book3s_64(CPUPPCState *env, int version)
         gen_spr_power8_rpr(env);
         gen_spr_power8_dbell(env);
         gen_spr_power8_ic(env);
+        gen_spr_power8_pspb(env);
         gen_spr_power8_book4(env);
     }
     if (version < BOOK3S_CPU_POWER8) {
Signature · 1 line
2.5.0
#157 lore raw

PATCH 70/77 ppc: Add dummy CIABR SPR

In reply to Benjamin Herrenschmidt

We should implement HW breakpoint/watchpoint, qemu supports them...

---
 target-ppc/cpu.h            | 1 +
 target-ppc/translate_init.c | 5 +++++
 2 files changed, 6 insertions(+)
target-ppc/cpu.h +1 -0
index 334fcfe..bf8892a 100644
@@ -1402,6 +1402,7 @@ static inline int cpu_mmu_index (CPUPPCState *env, bool ifetch)
 #define SPR_DAWR              (0x0B4)
 #define SPR_MPPR              (0x0B8)
 #define SPR_RPR               (0x0BA)
+#define SPR_CIABR             (0x0BB)
 #define SPR_DAWRX             (0x0BC)
 #define SPR_HFSCR             (0x0BE)
 #define SPR_VRSAVE            (0x100)
target-ppc/translate_init.c +5 -0
index b1eba73..b5fd076 100644
@@ -7629,6 +7629,11 @@ static void gen_spr_book3s_207_dbg(CPUPPCState *env)
                     SPR_NOACCESS, SPR_NOACCESS,
                     &spr_read_generic, &spr_write_generic,
                     0x00000000);
+    spr_register_kvm_hv(env, SPR_CIABR, "CIABR",
+                        SPR_NOACCESS, SPR_NOACCESS,
+                        SPR_NOACCESS, SPR_NOACCESS,
+                        &spr_read_generic, &spr_write_generic,
+		        KVM_REG_PPC_CIABR, 0x00000000);
 }
 
 static void gen_spr_970_dbg(CPUPPCState *env)
Signature · 1 line
2.5.0
#158 lore raw
In reply to Benjamin Herrenschmidt
Quoted 3 lines · Benjamin Herrenschmidt

This requires an OPAL firmware file which isn't included yet, will emulate enough to boot existing distros and run KVM inside TCG

Note that this doesn't migrate nor supports running under PR KVM, both are possible but will take significantly more work (the latter will need updates to PR KVM to emulate various aspects of the MMU that it ignores for now).

Cheers,
Ben.

#159 lore raw
In reply to Benjamin Herrenschmidt
Quoted 3 lines · Benjamin Herrenschmidt

This requires an OPAL firmware file which isn't included yet, will emulate enough to boot existing distros and run KVM inside TCG

[meta-comment]

It would be nice to include a diffstat (git defaults to doing this if you use 'git format-patch --cover-letter' for generating the 0/77 letter), so that we can see at a glance how big this series is and what files it touches.

In particular, I can't tell, without poking through 77 patches, if you update the MAINTAINERS file to claim any new files added here.

Also, for a series this big, it's nice to point to a scratch git repo that we can browse/clone from, without having to 'git am' all 77 mails.

Signature · 2 lines
Eric Blake   eblake redhat com    +1-919-301-3266
Libvirt virtualization library http://libvirt.org
#160 lore raw
Quoted 5 lines · Eric Blake

It would be nice to include a diffstat (git defaults to doing this if you use 'git format-patch --cover-letter' for generating the 0/77 letter), so that we can see at a glance how big this series is and what files it touches.

Right. I'll do that next time. In the meantime, I've appended the diffstat below.

Quoted 2 lines

In particular, I can't tell, without poking through 77 patches, if you update the MAINTAINERS file to claim any new files added here.

I don't ... yet. I'll do it in the next spin. Thanks for pointing that out.

Quoted 3 lines

Also, for a series this big, it's nice to point to a scratch git repo that we can browse/clone from, without having to 'git am' all 77 mails.

https://github.com/ozbenh/qemu

Cheers,
Ben.

 default-configs/ppc64-softmmu.mak   |    5 +- hmp-commands-info.hx                |    2 + hw/intc/Makefile.objs               |    2 +
 hw/intc/xics.c                      |  722 +++++++---------------- hw/intc/xics_kvm.c                  |   91 +-- hw/intc/xics_native.c               |  294 ++++++++++ hw/intc/xics_spapr.c                |  423 ++++++++++++++ hw/pci-bridge/pci_bridge_dev.c      |    3 + hw/pci-host/Makefile.objs           |    2 + hw/pci-host/pnv_phb3.c              | 1083 +++++++++++++++++++++++++++++++++++ hw/pci-host/pnv_phb3_msi.c          |  338 +++++++++++ hw/pci-host/pnv_phb3_pbcq.c         |  314 ++++++++++ hw/pci-host/pnv_phb3_rc.c           |  132 +++++
 hw/pci/pci.c                        |   26 +- hw/ppc/Makefile.objs                |    2 +
 hw/ppc/pnv.c                        |  859 +++++++++++++++++++++++++++

 hw/ppc/pnv_lpc.c                    |  527 +++++++++++++++++
 hw/ppc/pnv_occ.c                    |  125 ++++
 hw/ppc/pnv_psi.c                    |  594 +++++++++++++++++++

 hw/ppc/pnv_xscom.c                  |  415 ++++++++++++++ hw/ppc/ppc.c                        |   31 +- hw/ppc/spapr.c                      |   41 +- hw/ppc/spapr_events.c               |    8 +- hw/ppc/spapr_hcall.c                |   22 +- hw/ppc/spapr_pci.c                  |   10 +- hw/ppc/spapr_vio.c                  |    2 +- include/hw/pci-host/pnv_phb3.h      |  145 +++++ include/hw/pci-host/pnv_phb3_regs.h |  505 ++++++++++++++++ include/hw/pci-host/spapr.h         |    2 +- include/hw/pci/pci_bus.h            |    1 + include/hw/ppc/pnv.h                |   67 +++ include/hw/ppc/pnv_xscom.h          |   73 +++ include/hw/ppc/ppc.h                |    2 + include/hw/ppc/spapr.h              |    2 +- include/hw/ppc/spapr_vio.h          |    2 +- include/hw/ppc/xics.h               |   81 ++- include/hw/qdev-core.h              |    1 + linux-user/main.c                   |    1 + monitor.c                           |    3 + qdev-monitor.c                      |   13 +- target-ppc/cpu-models.c             |   12 +- target-ppc/cpu-models.h             |    4 +- target-ppc/cpu-qom.h                |    1 + target-ppc/cpu.h                    |  152 ++++- target-ppc/excp_helper.c            |  324 +++++++---- target-ppc/helper.h                 |    6 + target-ppc/helper_regs.h            |   75 ++- target-ppc/machine.c                |    4 +-

 target-ppc/mmu-hash32.c             |    4 +-
 target-ppc/mmu-hash64.c             |  356 ++++++++++--
 target-ppc/mmu-hash64.h             |    1 +
 target-ppc/mmu_helper.c             |   17 +-
 target-ppc/timebase_helper.c        |   10 +
 target-ppc/translate.c              | 1009 +++++++++++++++++---------------
 target-ppc/translate_init.c         |  735 +++++++++++++++++++++---
 55 files changed, 8318 insertions(+), 1363 deletions(-)

 create mode 100644 hw/intc/xics_native.c create mode 100644 hw/intc/xics_spapr.c create mode 100644 hw/pci-host/pnv_phb3.c create mode 100644 hw/pci-host/pnv_phb3_msi.c create mode 100644 hw/pci-host/pnv_phb3_pbcq.c create mode 100644 hw/pci-host/pnv_phb3_rc.c create mode 100644 hw/ppc/pnv.c
 create mode 100644 hw/ppc/pnv_lpc.c
 create mode 100644 hw/ppc/pnv_occ.c
 create mode 100644 hw/ppc/pnv_psi.c
 create mode 100644 hw/ppc/pnv_xscom.c
 create mode 100644 include/hw/pci-host/pnv_phb3.h create mode 100644 include/hw/pci-host/pnv_phb3_regs.h create mode 100644 include/hw/ppc/pnv.h create mode 100644 include/hw/ppc/pnv_xscom.h

#161 lore raw
Quoted 9 lines · Benjamin Herrenschmidt
Quoted 5 lines · Eric Blake

It would be nice to include a diffstat (git defaults to doing this if you use 'git format-patch --cover-letter' for generating the 0/77 letter), so that we can see at a glance how big this series is and what files it touches.

Right. I'll do that next time. In the meantime, I've appended the diffstat below.

Some working example of qemu command line would not hurt. Known limitations as well. Like:

- it does not run under neither kvm-hv nor kvm-pr;
- cannot boot LE kernel;
...

Quoted 12 lines
Quoted 3 lines

In particular, I can't tell, without poking through 77 patches, if you update the MAINTAINERS file to claim any new files added here.

I don't ... yet. I'll do it in the next spin. Thanks for pointing that out.

Quoted 3 lines

Also, for a series this big, it's nice to point to a scratch git repo that we can browse/clone from, without having to 'git am' all 77 mails.

https://github.com/ozbenh/qemu

Signature · 1 line
Alexey
#162 lore raw
Quoted 14 lines · Alexey Kardashevskiy
Quoted 11 lines · Benjamin Herrenschmidt
Quoted 7 lines · Eric Blake

It would be nice to include a diffstat (git defaults to doing this if
you use 'git format-patch --cover-letter' for generating the 0/77 letter), so that we can see at a glance how big this series is and
what files it touches.

Right. I'll do that next time. In the meantime, I've appended the diffstat below.

Quoted 5 lines

Some working example of qemu command line would not hurt. Known limitations
as well. Like:

- it does not run under neither kvm-hv nor kvm-pr;

It will never run under HV KVM,  indeed. I did mention somewhere else that support for PR KVM was possible, just quite a bit of work. I will add it to next version's cover letter.

Quoted 2 lines

- cannot boot LE kernel;
...

It boots an LE kernel just fine :-)

Also next spin will have skiboot.lid

Cheers,
Ben.

#163 lore raw
Quoted 21 lines · Benjamin Herrenschmidt
Quoted 14 lines · Alexey Kardashevskiy
Quoted 11 lines · Benjamin Herrenschmidt
Quoted 7 lines · Eric Blake

It would be nice to include a diffstat (git defaults to doing this if
you use 'git format-patch --cover-letter' for generating the 0/77 letter), so that we can see at a glance how big this series is and
what files it touches.

Right. I'll do that next time. In the meantime, I've appended the diffstat below.

Quoted 5 lines

Some working example of qemu command line would not hurt. Known limitations
as well. Like:

- it does not run under neither kvm-hv nor kvm-pr;

Quoted 8 lines

It will never run under HV KVM, indeed. I did mention somewhere else that support for PR KVM was possible, just quite a bit of work. I will add it to next version's cover letter.

Quoted 2 lines

- cannot boot LE kernel;
...

It boots an LE kernel just fine :-)

aaaaand there is still no working example ;)

This:

p/qemu-powernv/ppc64-softmmu/qemu-system-ppc64 -m 2048 -machine powernv \
-nographic -vga none -initrd t/le.cpio -kernel t/vml420le -bios \
skiboot.lid -smp 1,threads=1

just hangs at:

[1491287872,5] INIT: Waiting for kernel...
[1493257423,5] Assuming kernel at 0x20000000
[1494710040,5] INIT: Kernel loaded, size: 0 bytes (0 = unknown preload) [1497506414,5] INIT: 64-bit LE kernel discovered
[1500827972,5] INIT: 64-bit kernel entry at 0x20010000
[1505594383,3] OCC: No HOMER detected, assuming no pstates [1507983930,3] ELOG: Error getting buffer to log error
[1556792870,5] Free space in HEAP memory regions:
[1559724738,5] Region ibm,firmware-heap free: 12778984
[1561377946,5] Region ibm,firmware-allocs-memory@0000000000000000 free: 376992 [1563789914,5] Total free: 13155976
[1565066925,5] INIT: Starting kernel at 0x20010000, fdt at 0x30350610 (size 0x2ce4)

With BE kernel and initrd, it goes further and boots fine:

[1589979488,5] Total free: 13155976
[1591411784,5] INIT: Starting kernel at 0x20010000, fdt at 0x30350610 (size 0x2ce4) [1687534980,3] OPAL: Trying a CPU re-init with flags: 0x1
CPU maps initialized for 1 thread per core
....

If I try LE disk image (ubuntu 14), it just crashes:

p/qemu-powernv/ppc64-softmmu/qemu-system-ppc64 -m 2048 -machine powernv \
-nographic -vga none img/u14_32GB_cuda7.qcow2 -bios skiboot.lid \
-smp 1,threads=1
qemu: hardware error: qemu: could not load kernel'(null)'

CPU #0:
NIP 0000000000000000 LR 0000000000000000 CTR 0000000000000000 XER 0000000000000000 CPU#0
MSR 0000000000000000 HID0 0000000000000000 HF 0000000000000000 iidx 0 didx 0
TB 00000000 00000000 DECR 00000000
...

Quoted 2 lines

Also next spin will have skiboot.lid

Right. With the note that it goes with -bios :)

Signature · 1 line
Alexey
#164 lore raw
Quoted 8 lines · Alexey Kardashevskiy

p/qemu-powernv/ppc64-softmmu/qemu-system-ppc64 -m 2048 -machine powernv \
-nographic -vga none -initrd t/le.cpio -kernel t/vml420le -bios \
skiboot.lid -smp 1,threads=1

just hangs at:

Quoted 16 lines

[1491287872,5] INIT: Waiting for kernel...
[1493257423,5] Assuming kernel at 0x20000000 [1494710040,5] INIT: Kernel loaded, size: 0 bytes (0 = unknown preload)
[1497506414,5] INIT: 64-bit LE kernel discovered [1500827972,5] INIT: 64-bit kernel entry at 0x20010000 [1505594383,3] OCC: No HOMER detected, assuming no pstates [1507983930,3] ELOG: Error getting buffer to log error [1556792870,5] Free space in HEAP memory regions:
[1559724738,5] Region ibm,firmware-heap free: 12778984 [1561377946,5] Region ibm,firmware-allocs-memory@0000000000000000
free: 376992
[1563789914,5] Total free: 13155976
[1565066925,5] INIT: Starting kernel at 0x20010000, fdt at 0x30350610 (size
0x2ce4)

Hrm, works for me, I've been testing various LE kernels including a full ubuntu distro in there, we need to debug that further. Does that same kernel actually work on real HW ?

Quoted 7 lines

If I try LE disk image (ubuntu 14), it just crashes:

p/qemu-powernv/ppc64-softmmu/qemu-system-ppc64 -m 2048 -machine powernv \

(quoted diff) +0 -2
-nographic -vga none img/u14_32GB_cuda7.qcow2 -bios skiboot.lid \
-smp 1,threads=1

qemu: hardware error: qemu: could not load kernel'(null)'

Right, we don't load kernels from disk, you need to pass a -kernel that typically is the openpower bootloader (Linux + petitboot). My plan is to make the pnv platform automatically extract these things from a ROM image of an openpower eval board (aka palmetto) which you can build from github. It's a bit too big to include as a binary in qemu however (about 16M).

Quoted 1 line

Right. With the note that it goes with -bios :)

Not necessarily, it will be in the right place and loaded without an explicit -bios.

Cheers,
Ben.

#165 lore raw
Quoted 26 lines · Benjamin Herrenschmidt
Quoted 8 lines · Alexey Kardashevskiy

p/qemu-powernv/ppc64-softmmu/qemu-system-ppc64 -m 2048 -machine powernv \
-nographic -vga none -initrd t/le.cpio -kernel t/vml420le -bios \
skiboot.lid -smp 1,threads=1

just hangs at:

Quoted 16 lines

[1491287872,5] INIT: Waiting for kernel...
[1493257423,5] Assuming kernel at 0x20000000 [1494710040,5] INIT: Kernel loaded, size: 0 bytes (0 = unknown preload)
[1497506414,5] INIT: 64-bit LE kernel discovered [1500827972,5] INIT: 64-bit kernel entry at 0x20010000 [1505594383,3] OCC: No HOMER detected, assuming no pstates [1507983930,3] ELOG: Error getting buffer to log error [1556792870,5] Free space in HEAP memory regions:
[1559724738,5] Region ibm,firmware-heap free: 12778984 [1561377946,5] Region ibm,firmware-allocs-memory@0000000000000000
free: 376992
[1563789914,5] Total free: 13155976
[1565066925,5] INIT: Starting kernel at 0x20010000, fdt at 0x30350610 (size
0x2ce4)

Quoted 3 lines

Hrm, works for me, I've been testing various LE kernels including a full ubuntu distro in there, we need to debug that further. Does that same kernel actually work on real HW ?

Ok, as we figured out, CONFIG_PPC_EARLY_DEBUG is responsible for this as it does hypercalls in the very beginning.

Quoted 9 lines
Quoted 7 lines

If I try LE disk image (ubuntu 14), it just crashes:

p/qemu-powernv/ppc64-softmmu/qemu-system-ppc64 -m 2048 -machine powernv \

(quoted diff) +0 -2
-nographic -vga none img/u14_32GB_cuda7.qcow2 -bios skiboot.lid \
-smp 1,threads=1

qemu: hardware error: qemu: could not load kernel'(null)'

Right, we don't load kernels from disk, you need to pass a -kernel that

Worth mentioning as well ;)

Quoted 5 lines

typically is the openpower bootloader (Linux + petitboot). My plan is to make the pnv platform automatically extract these things from a ROM image of an openpower eval board (aka palmetto) which you can build from github. It's a bit too big to include as a binary in qemu however (about 16M).

git submodule?

Another note. I tried to know what the default devices are and got another crash:

(qemu) info qtree
bus: main-system-bus
type System
dev: phb3-msi, id ""
/home/aik/p/qemu-powernv/hw/core/sysbus.c:276:sysbus_dev_print: Object 0x100279e9500 is not an instance of type sys-bus-device

Signature · 1 line
Alexey
#166 lore raw
Quoted 11 lines · Alexey Kardashevskiy

Another note. I tried to know what the default devices are and got another
crash:

(qemu) info qtree
bus: main-system-bus
   type System
   dev: phb3-msi, id "" /home/aik/p/qemu-powernv/hw/core/sysbus.c:276:sysbus_dev_print:
Object
0x100279e9500 is not an instance of type sys-bus-device

Hrm, that would be a new bug I introduced when adding MSIs yesterday, I'll look into it.

Cheers,
Ben.

#167 lore raw
In reply to Alexey Kardashevskiy
Quoted 48 lines · Alexey Kardashevskiy
Quoted 26 lines · Benjamin Herrenschmidt
Quoted 8 lines · Alexey Kardashevskiy

p/qemu-powernv/ppc64-softmmu/qemu-system-ppc64 -m 2048 -machine powernv \
-nographic -vga none -initrd t/le.cpio -kernel t/vml420le -bios \
skiboot.lid -smp 1,threads=1

just hangs at:

Quoted 16 lines

[1491287872,5] INIT: Waiting for kernel...
[1493257423,5] Assuming kernel at 0x20000000 [1494710040,5] INIT: Kernel loaded, size: 0 bytes (0 = unknown preload)
[1497506414,5] INIT: 64-bit LE kernel discovered [1500827972,5] INIT: 64-bit kernel entry at 0x20010000 [1505594383,3] OCC: No HOMER detected, assuming no pstates [1507983930,3] ELOG: Error getting buffer to log error [1556792870,5] Free space in HEAP memory regions:
[1559724738,5] Region ibm,firmware-heap free: 12778984 [1561377946,5] Region ibm,firmware-allocs-memory@0000000000000000
free: 376992
[1563789914,5] Total free: 13155976
[1565066925,5] INIT: Starting kernel at 0x20010000, fdt at 0x30350610 (size
0x2ce4)

Quoted 3 lines

Hrm, works for me, I've been testing various LE kernels including a full ubuntu distro in there, we need to debug that further. Does that same kernel actually work on real HW ?

Ok, as we figured out, CONFIG_PPC_EARLY_DEBUG is responsible for this as it does hypercalls in the very beginning.

Quoted 9 lines
Quoted 7 lines

If I try LE disk image (ubuntu 14), it just crashes:

p/qemu-powernv/ppc64-softmmu/qemu-system-ppc64 -m 2048 -machine powernv \

(quoted diff) +0 -2
-nographic -vga none img/u14_32GB_cuda7.qcow2 -bios skiboot.lid \
-smp 1,threads=1

qemu: hardware error: qemu: could not load kernel'(null)'

Right, we don't load kernels from disk, you need to pass a -kernel that

Worth mentioning as well ;)

Quoted 7 lines
Quoted 5 lines

typically is the openpower bootloader (Linux + petitboot). My plan is to make the pnv platform automatically extract these things from a ROM image of an openpower eval board (aka palmetto) which you can build from github. It's a bit too big to include as a binary in qemu however (about 16M).

git submodule?

How does real hardware store petitboot? If it's flash, you could pass it in using -pflash and thus model things even more closely and allow users to just take the ROM image as is.

Alex

#168 lore raw
Quoted 4 lines · Alexander Graf

How does real hardware store petitboot? If it's flash, you could pass it in using -pflash and thus model things even more closely and allow users to just take the ROM image as is.

It is a flash image, we could use an Open Power machine flash image "as-is" provided we taught qemu to extract skiboot (aka OPAL) from it.

Cheers,
Ben.

#169 lore raw
Quoted 4 lines

Am 28.11.2015 um 08:59 schrieb Benjamin Herrenschmidt <[email protected]>:

Quoted 8 lines
Quoted 5 lines · Alexander Graf

How does real hardware store petitboot? If it's flash, you could pass it in using -pflash and thus model things even more closely and allow users to just take the ROM image as is.

It is a flash image, we could use an Open Power machine flash image "as-is" provided we taught qemu to extract skiboot (aka OPAL) from it.

That's probably the best way. If it's memory mapped, you might not even have to extract anything - just jump to its location ;).

The -kernel syntax is useful to have, but should really be something "on top" of the normal system boot rather than its primary boot interface.

Alex

#170 lore raw
Quoted 12 lines · Alexander Graf
Quoted 12 lines

Am 28.11.2015 um 08:59 schrieb Benjamin Herrenschmidt <benh@kernel. crashing.org>:

Quoted 7 lines · Alexander Graf

How does real hardware store petitboot? If it's flash, you could pass it
in using -pflash and thus model things even more closely and allow users
to just take the ROM image as is.

Quoted 6 lines
Quoted 3 lines

It is a flash image, we could use an Open Power machine flash image "as-is"
provided we taught qemu to extract skiboot (aka OPAL) from it.

That's probably the best way. If it's memory mapped, you might not even have to extract anything - just jump to its location ;).

It's not memory mapped sadly (well not on P8...)

The way a real P8 boots is first a little internal uC executes code from a i2c seeprom to initialize a core and some cache. It then copies a payload from flash into that cache. That payload is HostBoot, which is a huge thing that initializes a pile of stuff such as the internal busses, SMP links, links to memory buffers, trains memory etc... it then constructs an embryo device-tree and loads & run OPAL (aka skiboot).

The model I chose for powernv is to simulate a boot at the hostboot -> skiboot transition point.

Quoted 3 lines

The -kernel syntax is useful to have, but should really be something "on top" of the normal system boot rather than its primary boot interface.

I know, I'm just not keen on committing a 16M "BIOS" to qemu tree ;-)

In any case, this is easy to change / fix. There's a lot more work on the rest of the series first.

Cheers,
Ben.

#171 lore raw
In reply to Benjamin Herrenschmidt
Quoted 8 lines · Benjamin Herrenschmidt
Quoted 4 lines · Alexander Graf

How does real hardware store petitboot? If it's flash, you could pass it in using -pflash and thus model things even more closely and allow users to just take the ROM image as is.

It is a flash image, we could use an Open Power machine flash image "as-is" provided we taught qemu to extract skiboot (aka OPAL) from it.

Couldn't we add an offset argument to load_image_targphys() or make that an extra routine ? If so, we could then load directly from an openpower pnor file.

I gave it a quick (and dirty) try and a powernv guest runs fine up to petitboot with just :

qemu-system-ppc64 -m 2G -M powernv -bios ~/work/open-power/images/palmetto.pnor -nographic -nodefaults -serial stdio

The pnor file is compiled from github. The patch is below (without the dirty cut and paste I did in loader.c). The offset for the PAYLOAD and BOOTKERNEL partitions are hard coded but I guess we don't need to read the flash partition table in qemu, not yet.

Cheers,

C.

hw/ppc/pnv.c +7 -3
Index: qemu-powernv.git/hw/ppc/pnv.c
===================================================================
@@ -69,7 +69,7 @@
 
 #define FDT_ADDR                0x01000000
 #define FDT_MAX_SIZE            0x00100000
-#define FW_MAX_SIZE             0x00400000
+#define FW_MAX_SIZE             0x04000000
 #define FW_FILE_NAME            "skiboot.lid"
 #define KERNEL_FILE_NAME        "skiroot.lid"
 #define KERNEL_LOAD_ADDR        0x20000000
@@ -902,7 +902,9 @@ static void ppc_powernv_init(MachineStat
 {
     ram_addr_t ram_size = machine->ram_size;
     const char *cpu_model = machine->cpu_model;
+#if 0
     const char *kernel_filename = machine->kernel_filename;
+#endif
     const char *initrd_filename = machine->initrd_filename;
     uint32_t initrd_base = 0;
     long initrd_size = 0;
@@ -998,19 +1000,20 @@ static void ppc_powernv_init(MachineStat
         bios_name = FW_FILE_NAME;
     }
     filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
-    fw_size = load_image_targphys(filename, 0, FW_MAX_SIZE);
+    fw_size = load_image_targphys_offset(filename, 0, FW_MAX_SIZE, 0x961000);
     if (fw_size < 0) {
         hw_error("qemu: could not load OPAL '%s'\n", filename);
         exit(1);
     }
+#if 0
     g_free(filename);
 
     if (kernel_filename == NULL) {
         kernel_filename = KERNEL_FILE_NAME;
     }
     filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, kernel_filename);
-    fw_size = load_image_targphys(filename, 0x20000000, 0x2000000);
+#endif
+    fw_size = load_image_targphys_offset(filename, 0x20000000, 0x2000000, 0xa61000);
     if (fw_size < 0) {
         hw_error("qemu: could not load kernel'%s'\n", filename);
         exit(1);
#172 lore raw
Quoted 4 lines · Cédric Le Goater

The pnor file is compiled from github. The patch is below (without the dirty cut and paste I did in loader.c). The offset for the PAYLOAD and BOOTKERNEL partitions are hard coded but I guess we don't need to read the flash partition table in qemu, not yet.

In practice we should read the partition tables, I don't like hard coded offsets... But we should probably create a proper "flash driver" that does a bunch of this, and also adds the BMC style flash interface so OPAL can write to nvram.

Cheers,
Ben.

#173 lore raw
Quoted 10 lines · Benjamin Herrenschmidt
Quoted 4 lines · Cédric Le Goater

The pnor file is compiled from github. The patch is below (without the dirty cut and paste I did in loader.c). The offset for the PAYLOAD and BOOTKERNEL partitions are hard coded but I guess we don't need to read the flash partition table in qemu, not yet.

In practice we should read the partition tables, I don't like hard coded offsets... But we should probably create a proper "flash driver" that does a bunch of this, and also adds the BMC style flash interface so OPAL can write to nvram.

yes that would be better but I don't measure what it takes to implement the LPC/AHB bridge to access the PNOR.

C.

#174 lore raw
Quoted 7 lines · Cédric Le Goater
Quoted 4 lines

In practice we should read the partition tables, I don't like hard coded offsets... But we should probably create a proper "flash driver" that does a bunch of this, and also adds the BMC style flash interface so OPAL can write to nvram.

yes that would be better but I don't measure what it takes to implement the LPC/AHB bridge to access the PNOR.

Yeah that's probably a little bit of work, but then there's also work being done to protect the flash using IPMI commands to do the flashing, so that could be an alternate option. I like emulating more of the BMC though, including the flash controller, as it would improve our testing coverage.

Cheers,
Ben.

#175 lore raw
In reply to Cédric Le Goater
Quoted 17 lines · Cédric Le Goater
Quoted 8 lines · Benjamin Herrenschmidt
Quoted 4 lines · Alexander Graf

How does real hardware store petitboot? If it's flash, you could pass it in using -pflash and thus model things even more closely and allow users to just take the ROM image as is.

It is a flash image, we could use an Open Power machine flash image "as-is" provided we taught qemu to extract skiboot (aka OPAL) from it.

Couldn't we add an offset argument to load_image_targphys() or make that an extra routine ? If so, we could then load directly from an openpower pnor file.

I gave it a quick (and dirty) try and a powernv guest runs fine up to petitboot with just :

Quoted 6 lines

qemu-system-ppc64 -m 2G -M powernv -bios ~/work/open-power/images/palmetto.pnor -nographic -nodefaults -serial stdio

The pnor file is compiled from github. The patch is below (without the dirty cut and paste I did in loader.c). The offset for the PAYLOAD and BOOTKERNEL partitions are hard coded but I guess we don't need to read the flash partition table in qemu, not yet.

One downside to this is that if we don't fall back to being able to load skiboot.lid it becomes more annoying to boot a gcov enabled skiboot as typical PNOR layout only gives 1MB for skiboot, and gcov builds bloat that a *lot*.

We probably don't want NVRAM writes going back to a single system wide PNOR image too, so while using pnor file is great for simulating what hardware does, may not work as the solution for long term model.

#176 lore raw
Quoted 25 lines · Stewart Smith
Quoted 17 lines · Cédric Le Goater
Quoted 8 lines · Benjamin Herrenschmidt
Quoted 4 lines · Alexander Graf

How does real hardware store petitboot? If it's flash, you could pass it in using -pflash and thus model things even more closely and allow users to just take the ROM image as is.

It is a flash image, we could use an Open Power machine flash image "as-is" provided we taught qemu to extract skiboot (aka OPAL) from it.

Couldn't we add an offset argument to load_image_targphys() or make that an extra routine ? If so, we could then load directly from an openpower pnor file.

I gave it a quick (and dirty) try and a powernv guest runs fine up to petitboot with just :

Quoted 6 lines

qemu-system-ppc64 -m 2G -M powernv -bios ~/work/open-power/images/palmetto.pnor -nographic -nodefaults -serial stdio

The pnor file is compiled from github. The patch is below (without the dirty cut and paste I did in loader.c). The offset for the PAYLOAD and BOOTKERNEL partitions are hard coded but I guess we don't need to read the flash partition table in qemu, not yet.

Quoted 4 lines

One downside to this is that if we don't fall back to being able to load skiboot.lid it becomes more annoying to boot a gcov enabled skiboot as typical PNOR layout only gives 1MB for skiboot, and gcov builds bloat that a *lot*.

I guess that what we can imagine having a bigger partition for skiboot in the case of gcov ? This will require a custom pnor build. Might be too complex. Or we could use a -pflash option to load the pnor and an optional -bios for skiboot if we want a custom one.

Quoted 3 lines

We probably don't want NVRAM writes going back to a single system wide PNOR image too, so while using pnor file is great for simulating what hardware does, may not work as the solution for long term model.

we can use a memory backend to start with, which is also much simpler than having to handle the block backend like the cfi pflash is doing. a guest could use its own private pnor if a block backend is needed.

C.

#177 lore raw
In reply to Benjamin Herrenschmidt
Quoted 3 lines · Benjamin Herrenschmidt

This requires an OPAL firmware file which isn't included yet, will emulate enough to boot existing distros and run KVM inside TCG

For anyone wanting to try out this patchset, to build skiboot.lid, grab https://github.com/open-power/skiboot.git and build.

You'll need ppc64 (big endian) cross compilers, available here:
https://www.kernel.org/pub/tools/crosstool/
and with that in your path everything should "just work".

The travis-ci test script for skiboot itself does build a qemu with these patches and boots skiboot, so see:
https://github.com/open-power/skiboot/blob/master/.travis.yml
for how that works.

#178 lore raw

PATCH 71/77 ppc: Add dummy ACOP SPR

In reply to Benjamin Herrenschmidt
---
 target-ppc/cpu.h            | 1 +
 target-ppc/translate_init.c | 4 ++++
 2 files changed, 5 insertions(+)
target-ppc/cpu.h +1 -0
index bf8892a..aa328a7 100644
@@ -1361,6 +1361,7 @@ static inline int cpu_mmu_index (CPUPPCState *env, bool ifetch)
 #define SPR_SRR1              (0x01B)
 #define SPR_CFAR              (0x01C)
 #define SPR_AMR               (0x01D)
+#define SPR_ACOP              (0x01F)
 #define SPR_BOOKE_PID         (0x030)
 #define SPR_BOOKE_DECAR       (0x036)
 #define SPR_BOOKE_CSRR0       (0x03A)
target-ppc/translate_init.c +4 -0
index b5fd076..4ec532c 100644
@@ -8226,6 +8226,10 @@ static void gen_spr_power8_book4(CPUPPCState *env)
                     &spr_read_generic, SPR_NOACCESS,
                     &spr_read_generic, &spr_write_generic,
                     0);
+    spr_register(env, SPR_ACOP, "ACOP",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0);
 #endif
 }
 
Signature · 1 line
2.5.0
#179 lore raw

Re: [Qemu-devel] [PATCH 71/77] ppc: Add dummy ACOP SPR

Quoted 23 lines · Benjamin Herrenschmidt
---
 target-ppc/cpu.h            | 1 +
 target-ppc/translate_init.c | 4 ++++
 2 files changed, 5 insertions(+)
target-ppc/cpu.h +1 -0
index bf8892a..aa328a7 100644
@@ -1361,6 +1361,7 @@ static inline int cpu_mmu_index (CPUPPCState *env, bool ifetch)
 #define SPR_SRR1              (0x01B)
 #define SPR_CFAR              (0x01C)
 #define SPR_AMR               (0x01D)
+#define SPR_ACOP              (0x01F)
 #define SPR_BOOKE_PID         (0x030)
 #define SPR_BOOKE_DECAR       (0x036)
 #define SPR_BOOKE_CSRR0       (0x03A)
target-ppc/translate_init.c +0 -0
index b5fd076..4ec532c 100644

target-ppc/translate_init.c static void gen_spr_power8_book4(CPUPPCState *env) · line 8234

Quoted 9 lines
target-ppc/translate_init.c +4 -0
@@ -8226,6 +8226,10 @@ static void gen_spr_power8_book4(CPUPPCState *env)
                     &spr_read_generic, SPR_NOACCESS,
                     &spr_read_generic, &spr_write_generic,
                     0);
+    spr_register(env, SPR_ACOP, "ACOP",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0);
 #endif
 }

I think this patch should be merged with the next one (where you change the ACOP hunk in translate_init.c again.

Thomas

#180 lore raw

PATCH 72/77 ppc: A couple more dummy POWER8 Book4 regs

In reply to Benjamin Herrenschmidt

WORT and PID this time

---
 target-ppc/cpu.h            |  2 ++
 target-ppc/translate_init.c | 16 ++++++++++++----
 2 files changed, 14 insertions(+), 4 deletions(-)
target-ppc/cpu.h +2 -0
index aa328a7..6179fbc 100644
@@ -1363,6 +1363,7 @@ static inline int cpu_mmu_index (CPUPPCState *env, bool ifetch)
 #define SPR_AMR               (0x01D)
 #define SPR_ACOP              (0x01F)
 #define SPR_BOOKE_PID         (0x030)
+#define SPR_BOOKS_PID         (0x030)
 #define SPR_BOOKE_DECAR       (0x036)
 #define SPR_BOOKE_CSRR0       (0x03A)
 #define SPR_BOOKE_CSRR1       (0x03B)
@@ -1716,6 +1717,7 @@ static inline int cpu_mmu_index (CPUPPCState *env, bool ifetch)
 #define SPR_POWER_SPMC1       (0x37C)
 #define SPR_POWER_SPMC2       (0x37D)
 #define SPR_POWER_MMCRS       (0x37E)
+#define SPR_WORT              (0x37F)
 #define SPR_PPR               (0x380)
 #define SPR_750_GQR0          (0x390)
 #define SPR_440_DNV0          (0x390)
target-ppc/translate_init.c +12 -4
index 4ec532c..bfdf028 100644
@@ -8226,10 +8226,18 @@ static void gen_spr_power8_book4(CPUPPCState *env)
                     &spr_read_generic, SPR_NOACCESS,
                     &spr_read_generic, &spr_write_generic,
                     0);
-    spr_register(env, SPR_ACOP, "ACOP",
-                 SPR_NOACCESS, SPR_NOACCESS,
-                 &spr_read_generic, &spr_write_generic,
-                 0);
+    spr_register_kvm(env, SPR_ACOP, "ACOP",
+                     SPR_NOACCESS, SPR_NOACCESS,
+                     &spr_read_generic, &spr_write_generic,
+                     KVM_REG_PPC_ACOP, 0);
+    spr_register_kvm(env, SPR_BOOKS_PID, "PID",
+                     SPR_NOACCESS, SPR_NOACCESS,
+                     &spr_read_generic, &spr_write_generic,
+                     KVM_REG_PPC_PID, 0);
+    spr_register_kvm(env, SPR_WORT, "WORT",
+                     SPR_NOACCESS, SPR_NOACCESS,
+                     &spr_read_generic, &spr_write_generic,
+                     KVM_REG_PPC_WORT, 0);
 #endif
 }
 
Signature · 1 line
2.5.0
#181 lore raw

Re: [Qemu-devel] [PATCH 72/77] ppc: A couple more dummy POWER8 Book4 regs

Quoted 44 lines · Benjamin Herrenschmidt

WORT and PID this time

---
 target-ppc/cpu.h            |  2 ++
 target-ppc/translate_init.c | 16 ++++++++++++----
 2 files changed, 14 insertions(+), 4 deletions(-)
target-ppc/cpu.h +2 -0
index aa328a7..6179fbc 100644
@@ -1363,6 +1363,7 @@ static inline int cpu_mmu_index (CPUPPCState *env, bool ifetch)
 #define SPR_AMR               (0x01D)
 #define SPR_ACOP              (0x01F)
 #define SPR_BOOKE_PID         (0x030)
+#define SPR_BOOKS_PID         (0x030)
 #define SPR_BOOKE_DECAR       (0x036)
 #define SPR_BOOKE_CSRR0       (0x03A)
 #define SPR_BOOKE_CSRR1       (0x03B)
@@ -1716,6 +1717,7 @@ static inline int cpu_mmu_index (CPUPPCState *env, bool ifetch)
 #define SPR_POWER_SPMC1       (0x37C)
 #define SPR_POWER_SPMC2       (0x37D)
 #define SPR_POWER_MMCRS       (0x37E)
+#define SPR_WORT              (0x37F)
 #define SPR_PPR               (0x380)
 #define SPR_750_GQR0          (0x390)
 #define SPR_440_DNV0          (0x390)
target-ppc/translate_init.c +4 -4
index 4ec532c..bfdf028 100644
@@ -8226,10 +8226,18 @@ static void gen_spr_power8_book4(CPUPPCState *env)
                     &spr_read_generic, SPR_NOACCESS,
                     &spr_read_generic, &spr_write_generic,
                     0);
-    spr_register(env, SPR_ACOP, "ACOP",
-                 SPR_NOACCESS, SPR_NOACCESS,
-                 &spr_read_generic, &spr_write_generic,
-                 0);
+    spr_register_kvm(env, SPR_ACOP, "ACOP",
+                     SPR_NOACCESS, SPR_NOACCESS,
+                     &spr_read_generic, &spr_write_generic,
+                     KVM_REG_PPC_ACOP, 0);

target-ppc/translate_init.c static void gen_spr_power8_book4(CPUPPCState *env) · line 8242

Quoted 10 lines
target-ppc/translate_init.c +8 -0
+    spr_register_kvm(env, SPR_BOOKS_PID, "PID",
+                     SPR_NOACCESS, SPR_NOACCESS,
+                     &spr_read_generic, &spr_write_generic,
+                     KVM_REG_PPC_PID, 0);
+    spr_register_kvm(env, SPR_WORT, "WORT",
+                     SPR_NOACCESS, SPR_NOACCESS,
+                     &spr_read_generic, &spr_write_generic,
+                     KVM_REG_PPC_WORT, 0);
 #endif
 }

AFAICT all patches where you define new SPRs with spr_register_kvm[_hv] are also important independently of the rest of your patch series - otherwise these registers are currently lost during migration since they are not sync'ed with the KVM part in the kernel right now.

So if you've got some spare time, could you maybe extract all those patches that define new SPRs with spr_register_kvm[_hv] and send them as a separate patch series? That could help to fix future migration issues, and also would decrease the size of your really huge "Add native POWER8 platform" patch series a little bit!

Thanks,
Thomas

#182 lore raw

Re: [Qemu-devel] [PATCH 72/77] ppc: A couple more dummy POWER8 Book4 regs

Quoted 5 lines · Thomas Huth

So if you've got some spare time, could you maybe extract all those patches that define new SPRs with spr_register_kvm[_hv] and send them as a separate patch series? That could help to fix future migration issues, and also would decrease the size of your really huge "Add native POWER8 platform" patch series a little bit!

Time is the problem :-) My tree is bitrotting right now, I am completely caught up with a few other things.

I'm trying to get somebody to pick up that work.

Cheers,
Ben.

#183 lore raw

Re: [Qemu-devel] [Qemu-ppc] [PATCH 72/77] ppc: A couple more dummy POWER8 Book4 regs

In reply to Thomas Huth
Quoted 61 lines · Thomas Huth
Quoted 44 lines · Benjamin Herrenschmidt

WORT and PID this time

---
 target-ppc/cpu.h            |  2 ++
 target-ppc/translate_init.c | 16 ++++++++++++----
 2 files changed, 14 insertions(+), 4 deletions(-)
target-ppc/cpu.h +2 -0
index aa328a7..6179fbc 100644
@@ -1363,6 +1363,7 @@ static inline int cpu_mmu_index (CPUPPCState *env, bool ifetch)
 #define SPR_AMR               (0x01D)
 #define SPR_ACOP              (0x01F)
 #define SPR_BOOKE_PID         (0x030)
+#define SPR_BOOKS_PID         (0x030)
 #define SPR_BOOKE_DECAR       (0x036)
 #define SPR_BOOKE_CSRR0       (0x03A)
 #define SPR_BOOKE_CSRR1       (0x03B)
@@ -1716,6 +1717,7 @@ static inline int cpu_mmu_index (CPUPPCState *env, bool ifetch)
 #define SPR_POWER_SPMC1       (0x37C)
 #define SPR_POWER_SPMC2       (0x37D)
 #define SPR_POWER_MMCRS       (0x37E)
+#define SPR_WORT              (0x37F)
 #define SPR_PPR               (0x380)
 #define SPR_750_GQR0          (0x390)
 #define SPR_440_DNV0          (0x390)
target-ppc/translate_init.c +4 -4
index 4ec532c..bfdf028 100644
@@ -8226,10 +8226,18 @@ static void gen_spr_power8_book4(CPUPPCState *env)
                     &spr_read_generic, SPR_NOACCESS,
                     &spr_read_generic, &spr_write_generic,
                     0);
-    spr_register(env, SPR_ACOP, "ACOP",
-                 SPR_NOACCESS, SPR_NOACCESS,
-                 &spr_read_generic, &spr_write_generic,
-                 0);
+    spr_register_kvm(env, SPR_ACOP, "ACOP",
+                     SPR_NOACCESS, SPR_NOACCESS,
+                     &spr_read_generic, &spr_write_generic,
+                     KVM_REG_PPC_ACOP, 0);

target-ppc/translate_init.c static void gen_spr_power8_book4(CPUPPCState *env) · line 8242

Quoted 10 lines
target-ppc/translate_init.c +8 -0
+    spr_register_kvm(env, SPR_BOOKS_PID, "PID",
+                     SPR_NOACCESS, SPR_NOACCESS,
+                     &spr_read_generic, &spr_write_generic,
+                     KVM_REG_PPC_PID, 0);
+    spr_register_kvm(env, SPR_WORT, "WORT",
+                     SPR_NOACCESS, SPR_NOACCESS,
+                     &spr_read_generic, &spr_write_generic,
+                     KVM_REG_PPC_WORT, 0);
 #endif
 }

AFAICT all patches where you define new SPRs with spr_register_kvm[_hv] are also important independently of the rest of your patch series - otherwise these registers are currently lost during migration since they are not sync'ed with the KVM part in the kernel right now.

Quoted 5 lines

So if you've got some spare time, could you maybe extract all those patches that define new SPRs with spr_register_kvm[_hv] and send them as a separate patch series? That could help to fix future migration issues, and also would decrease the size of your really huge "Add native POWER8 platform" patch series a little bit!

I have been maintaining a port of Ben's patchset on the latest qemu for other parts which should come after pnv is merged so I have a framework to test such sub-patchsets. I also have time to work on them but clearly not the expertise in all areas !

What would be nice is to identify the most obvious ones, non controversial that could be merged after a few iterations. I have a vague idea, the ones Reviewed-by David obviously being good candidates, the definition of new SPRs (even the dummy ones ?). That would remove 15/20 patches from the list below I believe. May be more. I will go through the email thread to see what can be taken.

Would follow the xics patches (plenty of conflicts lately), mmu patches (but David has been working on this so it is shrinking), some pci fixes and helpers (should ping maintainers). We would then be at a point where only the core pnv patches are left. I think I am being very optimistic :)

I can start with a first serie. Suggestions welcomed. List below.

065f7f9b1e15 ppc: Fix CFAR updates
f385d52fe9f2 ppc: Add slbfee. instruction
2bf0d4f4239a ppc: Add dummy logmpp instruction
8102a4cc9c30 ppc: Print HSRR0/HSRR1 in "info registers"
730a9b4dc941 ppc: Add KVM numbers to some P8 SPRs
48adf38e9cab ppc: A couple more dummy POWER8 Book4 regs
bce7c738ec1b ppc: Add dummy ACOP SPR
34f1af75e75e ppc: Add dummy CIABR SPR
64f92045e284 ppc: Add dummy POWER8 PSPB SPR
ab003604993b ppc: Add dummy POWER8 MPPR register
b81cf8c41288 ppc: Add dummy write to VTB
490af9c31d8b ppc: Add a few more P8 PMU SPRs
84886e8c188d ppc: Add POWER8 IAMR register
5046c10f9e58 ppc: Fix writing to AMR/UAMOR
c188b86cac90 ppc: Initialize AMOR in PAPR mode
ee62b5581094 ppc: Add dummy SPR_IC for POWER8
83e02b2026ef ppc: SPURR & PURR are HV writeable and privileged
906a513acb1a ppc: LPCR is a HV resource
27f45e80a104 ppc: Add placeholder SPRs for DPDES and DHDES on P8
c1fc6d316f87 ppc: Initial HDEC support
9f5d6c607af5 ppc: Enforce setting MSR:EE,IR and DR when MSR:PR is set
a356d76a11bb ppc: Fix conditions for delivering external interrupts to a guest 6ba5e576d1cc ppc/pnv+spapr: Add "ibm,pa-features" property to the device-tree cf768bc434e5 ppc: Fix 64K pages support in full emulation
dbd6e54fd9c5 ppc: Add proper real mode translation support
7250469a21ce ppc: Cosmetic, align some comments
d94d8c4e7b3f ppc: Use a helper to filter writes to LPCR
0694e0d87fe3 ppc: Update LPCR definitions
20596a008f27 ppc/pnv: Create a default PCI layout
4b393cbdb438 ppc/pnv: Add model for Power8 PHB3 PCIe Host bridge
fa93c24cd3dc pci: Don't call pci_irq_handler() for a negative intx
8872d909a8fb pci: Use the new pci_can_add_device() to enforce devfn_min/max 9204957062b8 qdev: Add a hook for a bus to device if it can add devices 00b55e345926 pci-bridge: Set a supported devfn_min for bridge
e53d84a2716a ppc/pnv: Add OCC model stub with interrupt support
0b6c38406589 ppc/pnv: Add cut down PSI bridge model and hookup external interrupt 2649daef3f73 ppc/pnv: Add LPC controller and hook it up with a UART and RTC 81fff5adcc87 ppc/pnv: Wire up XICS native with PowerNV platform
aed1f862f0cc ppc/xics: Add xics to the monitor "info pic" command
8a9d65a58764 ppc/xics: Add "native" XICS subclass
2f29b84050d0 ppc/xics: Split ICS into base class and "simple" implementation f16e1abac820 ppc/xics: Use a helper to add a new ICS
8311defd2daa ppc/xics: Move xics_set_nr_irqs() to xics_spapr.c and xics_kvm.c 80ff29cbe02c ppc/xics: An ICS with offset 0 is assumed to be uninitialized b051717058cd ppc/xics: Make the ICSState a list
c1498ed62ab9 ppc/xics: Replace "icp" with "xics" in most places
de147c5277ee ppc/xics: Remove unused xics_set_irq_type()
e8322cdda768 ppc/xics: Implement H_IPOLL using an accessor
14597dd4d7c5 ppc/xics: Move SPAPR specific code to a separate file
ea78b4729fe7 ppc/xics: Rename existing XICS classe to XICS_SPAPR
b68322388931 ppc/pnv: Add XSCOM infrastructure
e567fa64df0a ppc/pnv: Add skeletton PowerNV platform
a926d8369e26 ppc: Add P7/P8 Power Management instructions
bba3bf8362cf ppc: Move exception generation code out of line
15411d6de866 ppc: Turn a bunch of booleans from int to bool
554cf2e208d4 ppc: Add real mode CI load/store instructions for P7 and P8 e75b02f8786e ppc: Rework generation of priv and inval interrupts
ec7fde6eb1a6 ppc: Fix generation if ISI/DSI vs. HV mode
91d6d6b8c720 ppc: Fix POWER7 and POWER8 exception definitions
886802ba3a7b ppc: Rework POWER7 & POWER8 exception model
72a37f87f790 ppc: Add PPC_64H instruction flag to POWER7 and POWER8
036b3623c02d ppc: Get out of emulation on SMT "OR" ops
5bf1a7bf1e45 ppc: Fix sign extension issue in mtmsr(d) emulation
fbac2f43e655 ppc: Change 'invalid' bit mask of tlbiel and tlbie
f308c5b1006f ppc: tlbie, tlbia and tlbisync are HV only
317658992d97 ppc: Better figure out if processor has HV mode
e25b26973a4b ppc: Create cpu_ppc_set_papr() helper
14bffe9681df ppc: Fix rfi/rfid/hrfi/... emulation
fb21ea327c61 ppc: Fix hreg_store_msr() so that non-HV mode cannot alter MSR:HV 35fd16185bea ppc: Add number of threads per core to the processor definition e408897526e9 ppc: Add a bunch of hypervisor SPRs to Book3s
5b287e66c751 ppc: Add macros to register hypervisor mode SPRs
295ccb0507dc ppc: Update SPR definitions
ed011d4fb179 ppc: Do some batching of TCG tlb flushes
048a18af1c8d ppc: Use split I/D mmu modes to avoid flushes on interrupts 681fc8d20391 ppc: Remove MMU_MODEn_SUFFIX definitions
065f7f9b1e15 ppc: Fix CFAR updates
2d3b7c0164e1 Merge remote-tracking branch 'remotes/amit-virtio-rng/tags/rng-for-2.6-1' into staging

Quoted 1 line

From :

https://github.com/legoater/qemu/commits/powernv-ipmi

$ git diff 2d3b7c0164e1..065f7f9b1e15  | diffstat 
 default-configs/ppc64-softmmu.mak   |    5 
 hmp-commands-info.hx                |    2 
 hw/intc/Makefile.objs               |    2 
 hw/intc/xics.c                      |  727 +++++++-----------------
 hw/intc/xics_kvm.c                  |   91 +--
 hw/intc/xics_native.c               |  295 +++++++++
 hw/intc/xics_spapr.c                |  429 ++++++++++++++
 hw/pci-bridge/pci_bridge_dev.c      |    2 
 hw/pci-host/Makefile.objs           |    2 
 hw/pci-host/pnv_phb3.c              | 1084 ++++++++++++++++++++++++++++++++++++
 hw/pci-host/pnv_phb3_msi.c          |  354 +++++++++++
 hw/pci-host/pnv_phb3_pbcq.c         |  315 ++++++++++
 hw/pci-host/pnv_phb3_rc.c           |  130 ++++
 hw/pci/pci.c                        |   26 
 hw/ppc/Makefile.objs                |    2 
 hw/ppc/pnv.c                        |  864 ++++++++++++++++++++++++++++
 hw/ppc/pnv_lpc.c                    |  527 +++++++++++++++++
 hw/ppc/pnv_occ.c                    |  126 ++++
 hw/ppc/pnv_psi.c                    |  594 +++++++++++++++++++
 hw/ppc/pnv_xscom.c                  |  415 +++++++++++++
 hw/ppc/ppc.c                        |   31 -
 hw/ppc/spapr.c                      |   28 
 hw/ppc/spapr_events.c               |    8 
 hw/ppc/spapr_hcall.c                |   14 
 hw/ppc/spapr_pci.c                  |   12 
 hw/ppc/spapr_vio.c                  |    2 
 include/hw/pci-host/pnv_phb3.h      |  145 ++++
 include/hw/pci-host/pnv_phb3_regs.h |  505 ++++++++++++++++
 include/hw/pci-host/spapr.h         |    2 
 include/hw/pci/pci_bus.h            |    1 
 include/hw/ppc/pnv.h                |   67 ++
 include/hw/ppc/pnv_xscom.h          |   73 ++
 include/hw/ppc/ppc.h                |    2 
 include/hw/ppc/spapr.h              |    2 
 include/hw/ppc/spapr_vio.h          |    2 
 include/hw/ppc/xics.h               |   81 ++
 include/hw/qdev-core.h              |    1 
 linux-user/main.c                   |    1 
 monitor.c                           |    3 
 qdev-monitor.c                      |   13 
 target-ppc/cpu-qom.h                |    1 
 target-ppc/cpu.h                    |  148 ++++
 target-ppc/excp_helper.c            |  369 +++++++-----
 target-ppc/helper.h                 |    6 
 target-ppc/helper_regs.h            |   75 ++
 target-ppc/machine.c                |    5 
 target-ppc/mmu-hash32.c             |    4 
 target-ppc/mmu-hash64.c             |  344 +++++++++--
 target-ppc/mmu-hash64.h             |    1 
 target-ppc/mmu_helper.c             |   17 
 target-ppc/timebase_helper.c        |   10 
 target-ppc/translate.c              | 1013 ++++++++++++++++++---------------
 target-ppc/translate_init.c         |  738 ++++++++++++++++++++++--
 53 files changed, 8350 insertions(+), 1366 deletions(-)

Thanks,

C.

#184 lore raw

Re: [Qemu-devel] [Qemu-ppc] [PATCH 72/77] ppc: A couple more dummy POWER8 Book4 regs

Quoted 4 lines · Cédric Le Goater
Quoted 3 lines · Thomas Huth
Quoted 2 lines · Benjamin Herrenschmidt

WORT and PID this time

...

Quoted 11 lines
Quoted 10 lines

AFAICT all patches where you define new SPRs with spr_register_kvm[_hv] are also important independently of the rest of your patch series - otherwise these registers are currently lost during migration since they are not sync'ed with the KVM part in the kernel right now.

So if you've got some spare time, could you maybe extract all those patches that define new SPRs with spr_register_kvm[_hv] and send them as a separate patch series? That could help to fix future migration issues, and also would decrease the size of your really huge "Add native POWER8 platform" patch series a little bit!

Quoted 4 lines

I have been maintaining a port of Ben's patchset on the latest qemu for other parts which should come after pnv is merged so I have a framework to test such sub-patchsets. I also have time to work on them but clearly not the expertise in all areas !

That would be great if you could take care of this!

Quoted 4 lines

What would be nice is to identify the most obvious ones, non controversial that could be merged after a few iterations. I have a vague idea, the ones Reviewed-by David obviously being good candidates, the definition of new SPRs (even the dummy ones ?).

I really like to see the KVM SPRs patches first - since they are fixing potential problems with migration of the _current_ KVM machines already! And being bug fixes, maybe these patches could even be included for QEMU 2.6 already? (i.e. before the hard freeze at the end of March)

So my wish-list for a first small patch series looks like this:

5b287e66c7513209  ppc: Add macros to register hypervisor mode SPRs
34f1af75e75e7ba0  ppc: Add dummy CIABR SPR
48adf38e9cab4663  ppc: A couple more dummy POWER8 Book4 regs
730a9b4dc9414818  ppc: Add KVM numbers to some P8 SPRs

There are a couple of other patches touching the SPRs initialization, but they are not important with regards to migration... so not sure whether it makes sense to include them now already...

Thomas

#185 lore raw

Re: [Qemu-devel] [Qemu-ppc] [PATCH 72/77] ppc: A couple more dummy POWER8 Book4 regs

Quoted 1 line · Thomas Huth

On 09.03.2016 21:04, Cédric Le Goater wrote:

....

Quoted 19 lines
Quoted 4 lines

I have been maintaining a port of Ben's patchset on the latest qemu for other parts which should come after pnv is merged so I have a framework to test such sub-patchsets. I also have time to work on them but clearly not the expertise in all areas !

That would be great if you could take care of this!

Quoted 4 lines

What would be nice is to identify the most obvious ones, non controversial that could be merged after a few iterations. I have a vague idea, the ones Reviewed-by David obviously being good candidates, the definition of new SPRs (even the dummy ones ?).

I really like to see the KVM SPRs patches first - since they are fixing potential problems with migration of the _current_ KVM machines already! And being bug fixes, maybe these patches could even be included for QEMU 2.6 already? (i.e. before the hard freeze at the end of March)

So my wish-list for a first small patch series looks like this:

Quoted 8 lines
5b287e66c7513209  ppc: Add macros to register hypervisor mode SPRs
34f1af75e75e7ba0  ppc: Add dummy CIABR SPR
48adf38e9cab4663  ppc: A couple more dummy POWER8 Book4 regs
730a9b4dc9414818  ppc: Add KVM numbers to some P8 SPRs

There are a couple of other patches touching the SPRs initialization, but they are not important with regards to migration... so not sure whether it makes sense to include them now already...

FWIW, I just saw today (by doing some more experiments with kvm-unit-tests) that the IAMR register is also not migrated yet ... so it would be nice if you could include the related patches for IAMR, too, and wire the KVM part up with KVM_REG_PPC_IAMR...

Thomas

#186 lore raw

Re: [Qemu-devel] [Qemu-ppc] [PATCH 72/77] ppc: A couple more dummy POWER8 Book4 regs

Quoted 27 lines · Thomas Huth
Quoted 1 line · Thomas Huth

On 09.03.2016 21:04, Cédric Le Goater wrote:

....

Quoted 24 lines
Quoted 4 lines

I have been maintaining a port of Ben's patchset on the latest qemu for other parts which should come after pnv is merged so I have a framework to test such sub-patchsets. I also have time to work on them but clearly not the expertise in all areas !

That would be great if you could take care of this!

Quoted 4 lines

What would be nice is to identify the most obvious ones, non controversial that could be merged after a few iterations. I have a vague idea, the ones Reviewed-by David obviously being good candidates, the definition of new SPRs (even the dummy ones ?).

I really like to see the KVM SPRs patches first - since they are fixing potential problems with migration of the _current_ KVM machines already! And being bug fixes, maybe these patches could even be included for QEMU 2.6 already? (i.e. before the hard freeze at the end of March)

So my wish-list for a first small patch series looks like this:

5b287e66c7513209  ppc: Add macros to register hypervisor mode SPRs
34f1af75e75e7ba0  ppc: Add dummy CIABR SPR
48adf38e9cab4663  ppc: A couple more dummy POWER8 Book4 regs
730a9b4dc9414818  ppc: Add KVM numbers to some P8 SPRs
Quoted 8 lines
Quoted 3 lines

There are a couple of other patches touching the SPRs initialization, but they are not important with regards to migration... so not sure whether it makes sense to include them now already...

FWIW, I just saw today (by doing some more experiments with kvm-unit-tests) that the IAMR register is also not migrated yet ... so it would be nice if you could include the related patches for IAMR, too, and wire the KVM part up with KVM_REG_PPC_IAMR...

OK. So we should be targeting something like :

ppc: Update SPR definitions
ppc: Add macros to register hypervisor mode SPRs
ppc: Add a bunch of hypervisor SPRs to Book3s

ppc: LPCR is a HV resource
ppc: SPURR & PURR are HV writeable and privileged
ppc: Add dummy SPR_IC for POWER8
ppc: Initialize AMOR in PAPR mode
ppc: Fix writing to AMR/UAMOR
ppc: Add POWER8 IAMR register
ppc: Add a few more P8 PMU SPRs
ppc: Add dummy write to VTB
ppc: Add dummy POWER8 MPPR register
ppc: Add dummy POWER8 PSPB SPR
ppc: Add dummy CIABR SPR
ppc: Add dummy ACOP SPR
ppc: A couple more dummy POWER8 Book4 regs
ppc: Add KVM numbers to some P8 SPRs

Also, there seem to be an issue with qemu's HEAD on ppc64el with the random device :

-object rng-random,filename=/dev/urandom,id=gid0 -device spapr-rng,rng=gid0

qemu "hangs". This is a vague description for a symptom ... Does that ring a bell or do I need to dig in to get more info ?

Thanks,

C.

#187 lore raw

Re: [Qemu-devel] [Qemu-ppc] [PATCH 72/77] ppc: A couple more dummy POWER8 Book4 regs

Quoted 43 lines · Cédric Le Goater
Quoted 27 lines · Thomas Huth
Quoted 1 line · Thomas Huth

On 09.03.2016 21:04, Cédric Le Goater wrote:

....

Quoted 24 lines
Quoted 4 lines

I have been maintaining a port of Ben's patchset on the latest qemu for other parts which should come after pnv is merged so I have a framework to test such sub-patchsets. I also have time to work on them but clearly not the expertise in all areas !

That would be great if you could take care of this!

Quoted 4 lines

What would be nice is to identify the most obvious ones, non controversial that could be merged after a few iterations. I have a vague idea, the ones Reviewed-by David obviously being good candidates, the definition of new SPRs (even the dummy ones ?).

I really like to see the KVM SPRs patches first - since they are fixing potential problems with migration of the _current_ KVM machines already! And being bug fixes, maybe these patches could even be included for QEMU 2.6 already? (i.e. before the hard freeze at the end of March)

So my wish-list for a first small patch series looks like this:

5b287e66c7513209  ppc: Add macros to register hypervisor mode SPRs
34f1af75e75e7ba0  ppc: Add dummy CIABR SPR
48adf38e9cab4663  ppc: A couple more dummy POWER8 Book4 regs
730a9b4dc9414818  ppc: Add KVM numbers to some P8 SPRs
Quoted 8 lines
Quoted 3 lines

There are a couple of other patches touching the SPRs initialization, but they are not important with regards to migration... so not sure whether it makes sense to include them now already...

FWIW, I just saw today (by doing some more experiments with kvm-unit-tests) that the IAMR register is also not migrated yet ... so it would be nice if you could include the related patches for IAMR, too, and wire the KVM part up with KVM_REG_PPC_IAMR...

OK. So we should be targeting something like :

ppc: Update SPR definitions
ppc: Add macros to register hypervisor mode SPRs
ppc: Add a bunch of hypervisor SPRs to Book3s

Quoted 14 lines

ppc: LPCR is a HV resource
ppc: SPURR & PURR are HV writeable and privileged
ppc: Add dummy SPR_IC for POWER8
ppc: Initialize AMOR in PAPR mode
ppc: Fix writing to AMR/UAMOR
ppc: Add POWER8 IAMR register
ppc: Add a few more P8 PMU SPRs
ppc: Add dummy write to VTB
ppc: Add dummy POWER8 MPPR register
ppc: Add dummy POWER8 PSPB SPR
ppc: Add dummy CIABR SPR
ppc: Add dummy ACOP SPR
ppc: A couple more dummy POWER8 Book4 regs
ppc: Add KVM numbers to some P8 SPRs

Sounds good - but you likely can drop the "Add a few more P8 PMU SPRs" from your list since it has already been queued by David already (see
https://github.com/dgibson/qemu/commits/ppc-for-2.6), and the PSPB patch is also not required anymore since I submitted a similar patch to David already when I discovered that it is lost during migration.

Quoted 7 lines

Also, there seem to be an issue with qemu's HEAD on ppc64el with the random device :

-object rng-random,filename=/dev/urandom,id=gid0 -device spapr-rng,rng=gid0

qemu "hangs". This is a vague description for a symptom ... Does that ring a bell or do I need to dig in to get more info ?

Works for me™ ... could you supply more information? Where does it hang? Which exact level of QEMU are you using? ... and please open a new mail thread for this, since it's off-topic to this mail thread.

Thomas

#188 lore raw

Re: [Qemu-devel] [Qemu-ppc] [PATCH 72/77] ppc: A couple more dummy POWER8 Book4 regs

Quoted 59 lines · Thomas Huth
Quoted 43 lines · Cédric Le Goater
Quoted 27 lines · Thomas Huth
Quoted 1 line · Thomas Huth

On 09.03.2016 21:04, Cédric Le Goater wrote:

....

Quoted 24 lines
Quoted 4 lines

I have been maintaining a port of Ben's patchset on the latest qemu for other parts which should come after pnv is merged so I have a framework to test such sub-patchsets. I also have time to work on them but clearly not the expertise in all areas !

That would be great if you could take care of this!

Quoted 4 lines

What would be nice is to identify the most obvious ones, non controversial that could be merged after a few iterations. I have a vague idea, the ones Reviewed-by David obviously being good candidates, the definition of new SPRs (even the dummy ones ?).

I really like to see the KVM SPRs patches first - since they are fixing potential problems with migration of the _current_ KVM machines already! And being bug fixes, maybe these patches could even be included for QEMU 2.6 already? (i.e. before the hard freeze at the end of March)

So my wish-list for a first small patch series looks like this:

5b287e66c7513209  ppc: Add macros to register hypervisor mode SPRs
34f1af75e75e7ba0  ppc: Add dummy CIABR SPR
48adf38e9cab4663  ppc: A couple more dummy POWER8 Book4 regs
730a9b4dc9414818  ppc: Add KVM numbers to some P8 SPRs
Quoted 8 lines
Quoted 3 lines

There are a couple of other patches touching the SPRs initialization, but they are not important with regards to migration... so not sure whether it makes sense to include them now already...

FWIW, I just saw today (by doing some more experiments with kvm-unit-tests) that the IAMR register is also not migrated yet ... so it would be nice if you could include the related patches for IAMR, too, and wire the KVM part up with KVM_REG_PPC_IAMR...

OK. So we should be targeting something like :

ppc: Update SPR definitions
ppc: Add macros to register hypervisor mode SPRs
ppc: Add a bunch of hypervisor SPRs to Book3s

Quoted 14 lines

ppc: LPCR is a HV resource
ppc: SPURR & PURR are HV writeable and privileged
ppc: Add dummy SPR_IC for POWER8
ppc: Initialize AMOR in PAPR mode
ppc: Fix writing to AMR/UAMOR
ppc: Add POWER8 IAMR register
ppc: Add a few more P8 PMU SPRs
ppc: Add dummy write to VTB
ppc: Add dummy POWER8 MPPR register
ppc: Add dummy POWER8 PSPB SPR
ppc: Add dummy CIABR SPR
ppc: Add dummy ACOP SPR
ppc: A couple more dummy POWER8 Book4 regs
ppc: Add KVM numbers to some P8 SPRs

Quoted 5 lines

Sounds good - but you likely can drop the "Add a few more P8 PMU SPRs" from your list since it has already been queued by David already (see
https://github.com/dgibson/qemu/commits/ppc-for-2.6), and the PSPB patch is also not required anymore since I submitted a similar patch to David already when I discovered that it is lost during migration.

Here is a first port on Dave's 2.6 branch. I tried to keep the patchset minimal but I had to pull a few extra patches to keep them more or less in sync with the original version from Ben.

ppc: Update SPR definitions
ppc: Add macros to register hypervisor mode SPRs
ppc: Add a bunch of hypervisor SPRs to Book3s
ppc: Add number of threads per core to the processor definition
ppc: Fix hreg_store_msr() so that non-HV mode cannot alter MSR:HV
ppc: Create cpu_ppc_set_papr() helper
ppc: Better figure out if processor has HV mode
ppc: Add placeholder SPRs for DPDES and DHDES on P8
ppc: SPURR & PURR are HV writeable and privileged
ppc: Add dummy SPR_IC for POWER8
ppc: Initialize AMOR in PAPR mode
ppc: Fix writing to AMR/UAMOR
ppc: Add POWER8 IAMR register
ppc: Add dummy write to VTB
ppc: Add dummy POWER8 MPPR register
ppc: Add dummy CIABR SPR
ppc: Add dummy ACOP SPR
ppc: A couple more dummy POWER8 Book4 regs
ppc: Add KVM numbers to some P8 SPRs

Available here:

https://github.com/legoater/qemu/commits/for-2.6

If you want to take a look, I did some quick test on KVM and TCG on a ppc64le ubuntu host but no migration.

These two will probably need a merge as the first breaks the compile, and I modified the second.

ppc: Fix writing to AMR/UAMOR
ppc: Add POWER8 IAMR register

I guess that I will send on the list for review after.

Thanks,

C.

#189 lore raw

Re: [Qemu-devel] [Qemu-ppc] [PATCH 72/77] ppc: A couple more dummy POWER8 Book4 regs

Quoted 94 lines · Cédric Le Goater
Quoted 59 lines · Thomas Huth
Quoted 43 lines · Cédric Le Goater
Quoted 27 lines · Thomas Huth
Quoted 1 line · Thomas Huth

On 09.03.2016 21:04, Cédric Le Goater wrote:

....

Quoted 24 lines
Quoted 4 lines

I have been maintaining a port of Ben's patchset on the latest qemu for other parts which should come after pnv is merged so I have a framework to test such sub-patchsets. I also have time to work on them but clearly not the expertise in all areas !

That would be great if you could take care of this!

Quoted 4 lines

What would be nice is to identify the most obvious ones, non controversial that could be merged after a few iterations. I have a vague idea, the ones Reviewed-by David obviously being good candidates, the definition of new SPRs (even the dummy ones ?).

I really like to see the KVM SPRs patches first - since they are fixing potential problems with migration of the _current_ KVM machines already! And being bug fixes, maybe these patches could even be included for QEMU 2.6 already? (i.e. before the hard freeze at the end of March)

So my wish-list for a first small patch series looks like this:

5b287e66c7513209  ppc: Add macros to register hypervisor mode SPRs
34f1af75e75e7ba0  ppc: Add dummy CIABR SPR
48adf38e9cab4663  ppc: A couple more dummy POWER8 Book4 regs
730a9b4dc9414818  ppc: Add KVM numbers to some P8 SPRs
Quoted 8 lines
Quoted 3 lines

There are a couple of other patches touching the SPRs initialization, but they are not important with regards to migration... so not sure whether it makes sense to include them now already...

FWIW, I just saw today (by doing some more experiments with kvm-unit-tests) that the IAMR register is also not migrated yet ... so it would be nice if you could include the related patches for IAMR, too, and wire the KVM part up with KVM_REG_PPC_IAMR...

OK. So we should be targeting something like :

ppc: Update SPR definitions
ppc: Add macros to register hypervisor mode SPRs
ppc: Add a bunch of hypervisor SPRs to Book3s

Quoted 14 lines

ppc: LPCR is a HV resource
ppc: SPURR & PURR are HV writeable and privileged
ppc: Add dummy SPR_IC for POWER8
ppc: Initialize AMOR in PAPR mode
ppc: Fix writing to AMR/UAMOR
ppc: Add POWER8 IAMR register
ppc: Add a few more P8 PMU SPRs
ppc: Add dummy write to VTB
ppc: Add dummy POWER8 MPPR register
ppc: Add dummy POWER8 PSPB SPR
ppc: Add dummy CIABR SPR
ppc: Add dummy ACOP SPR
ppc: A couple more dummy POWER8 Book4 regs
ppc: Add KVM numbers to some P8 SPRs

Quoted 5 lines

Sounds good - but you likely can drop the "Add a few more P8 PMU SPRs" from your list since it has already been queued by David already (see
https://github.com/dgibson/qemu/commits/ppc-for-2.6), and the PSPB patch is also not required anymore since I submitted a similar patch to David already when I discovered that it is lost during migration.

Here is a first port on Dave's 2.6 branch. I tried to keep the patchset minimal but I had to pull a few extra patches to keep them more or less in sync with the original version from Ben.

ppc: Update SPR definitions
ppc: Add macros to register hypervisor mode SPRs
ppc: Add a bunch of hypervisor SPRs to Book3s
ppc: Add number of threads per core to the processor definition
ppc: Fix hreg_store_msr() so that non-HV mode cannot alter MSR:HV
ppc: Create cpu_ppc_set_papr() helper
ppc: Better figure out if processor has HV mode
ppc: Add placeholder SPRs for DPDES and DHDES on P8
ppc: SPURR & PURR are HV writeable and privileged
ppc: Add dummy SPR_IC for POWER8
ppc: Initialize AMOR in PAPR mode
ppc: Fix writing to AMR/UAMOR
ppc: Add POWER8 IAMR register
ppc: Add dummy write to VTB
ppc: Add dummy POWER8 MPPR register
ppc: Add dummy CIABR SPR
ppc: Add dummy ACOP SPR
ppc: A couple more dummy POWER8 Book4 regs
ppc: Add KVM numbers to some P8 SPRs

Available here:

https://github.com/legoater/qemu/commits/for-2.6

Quoted 8 lines

If you want to take a look, I did some quick test on KVM and TCG on a ppc64le ubuntu host but no migration.

These two will probably need a merge as the first breaks the compile, and I modified the second.

ppc: Fix writing to AMR/UAMOR
ppc: Add POWER8 IAMR register

Modifying patches is fine as long as you mention the changes in the patch description (in square brackets) and add your Sob - looking at your tree, you already did this for the "ppc: Add POWER8 IAMR register" patch, so that should be OK.

I'd maybe also squash the "Add KVM numbers to some P8 SPRs" patch into the "Add a bunch of hypervisor SPRs to Book3s" to reduce the code churn a little bit (note that the patch description for the "Add a bunch of hypervisor SPRs to Book3s" patch is misleading - DAWR and DAWRX need to be synchronized for migration, since the guest can set this register via the H_SET_MODE hypercall).

You could maybe also merge "Add dummy ACOP SPR" with "A couple more dummy POWER8 Book4 regs" since the latter patch completely reworks the definition of the ACOP register.

Thomas

#190 lore raw

Re: [Qemu-devel] [Qemu-ppc] [PATCH 72/77] ppc: A couple more dummy POWER8 Book4 regs

Hello Thomas,

Quoted 6 lines · Thomas Huth

I'd maybe also squash the "Add KVM numbers to some P8 SPRs" patch into the "Add a bunch of hypervisor SPRs to Book3s" to reduce the code churn a little bit (note that the patch description for the "Add a bunch of hypervisor SPRs to Book3s" patch is misleading - DAWR and DAWRX need to be synchronized for migration, since the guest can set this register via the H_SET_MODE hypercall).

So shall I just remove the comment :

"We don't give them a KVM reg number yet as no current KVM version
supports HV mode."

from patch "Add a bunch of hypervisor SPRs to Book3s" after squashing in "Add KVM numbers to some P8 SPRs" ?

Thanks,

C.

#191 lore raw

Re: [Qemu-devel] [Qemu-ppc] [PATCH 72/77] ppc: A couple more dummy POWER8 Book4 regs

Quoted 10 lines · Cédric Le Goater

Hello Thomas,

Quoted 6 lines · Thomas Huth

I'd maybe also squash the "Add KVM numbers to some P8 SPRs" patch into the "Add a bunch of hypervisor SPRs to Book3s" to reduce the code churn a little bit (note that the patch description for the "Add a bunch of hypervisor SPRs to Book3s" patch is misleading - DAWR and DAWRX need to be synchronized for migration, since the guest can set this register via the H_SET_MODE hypercall).

Quoted 7 lines

So shall I just remove the comment :

"We don't give them a KVM reg number yet as no current KVM version
supports HV mode."

from patch "Add a bunch of hypervisor SPRs to Book3s" after squashing in "Add KVM numbers to some P8 SPRs" ?

Either that, or change it into something like:

"We don't give them a KVM reg number to most of the registers yet as no current KVM version supports HV mode. For DAWR and DAWRX, the KVM reg number is needed since this register can be set by the guest via the H_SET_MODE hypercall."

?

Thomas

#192 lore raw

Re: [Qemu-devel] [Qemu-ppc] [PATCH 72/77] ppc: A couple more dummy POWER8 Book4 regs

Quoted 19 lines · Thomas Huth
Quoted 10 lines · Cédric Le Goater

Hello Thomas,

Quoted 6 lines · Thomas Huth

I'd maybe also squash the "Add KVM numbers to some P8 SPRs" patch into the "Add a bunch of hypervisor SPRs to Book3s" to reduce the code churn a little bit (note that the patch description for the "Add a bunch of hypervisor SPRs to Book3s" patch is misleading - DAWR and DAWRX need to be synchronized for migration, since the guest can set this register via the H_SET_MODE hypercall).

Quoted 7 lines

So shall I just remove the comment :

"We don't give them a KVM reg number yet as no current KVM version
supports HV mode."

from patch "Add a bunch of hypervisor SPRs to Book3s" after squashing in "Add KVM numbers to some P8 SPRs" ?

Quoted 6 lines

Either that, or change it into something like:

"We don't give them a KVM reg number to most of the registers yet as no current KVM version supports HV mode. For DAWR and DAWRX, the KVM reg number is needed since this register can be set by the guest via the H_SET_MODE hypercall."

OK. Good. I should be sending a first patchset soon the list, after a few checks.

Thanks,

C.

#193 lore raw

PATCH 73/77 ppc: Add KVM numbers to some P8 SPRs

In reply to Benjamin Herrenschmidt
---
 target-ppc/translate_init.c | 22 +++++++++++-----------
 1 file changed, 11 insertions(+), 11 deletions(-)
target-ppc/translate_init.c +11 -11
index bfdf028..fd084ca 100644
@@ -7619,21 +7619,21 @@ static void gen_spr_book3s_dbg(CPUPPCState *env)
 
 static void gen_spr_book3s_207_dbg(CPUPPCState *env)
 {
-    spr_register_hv(env, SPR_DAWR, "DAWR",
-                    SPR_NOACCESS, SPR_NOACCESS,
-                    SPR_NOACCESS, SPR_NOACCESS,
-                    &spr_read_generic, &spr_write_generic,
-                    0x00000000);
-    spr_register_hv(env, SPR_DAWRX, "DAWRX",
-                    SPR_NOACCESS, SPR_NOACCESS,
-                    SPR_NOACCESS, SPR_NOACCESS,
-                    &spr_read_generic, &spr_write_generic,
-                    0x00000000);
+    spr_register_kvm_hv(env, SPR_DAWR, "DAWR",
+                        SPR_NOACCESS, SPR_NOACCESS,
+                        SPR_NOACCESS, SPR_NOACCESS,
+                        &spr_read_generic, &spr_write_generic,
+                        KVM_REG_PPC_DAWR, 0x00000000);
+    spr_register_kvm_hv(env, SPR_DAWRX, "DAWRX",
+                        SPR_NOACCESS, SPR_NOACCESS,
+                        SPR_NOACCESS, SPR_NOACCESS,
+                        &spr_read_generic, &spr_write_generic,
+                        KVM_REG_PPC_DAWRX, 0x00000000);
     spr_register_kvm_hv(env, SPR_CIABR, "CIABR",
                         SPR_NOACCESS, SPR_NOACCESS,
                         SPR_NOACCESS, SPR_NOACCESS,
                         &spr_read_generic, &spr_write_generic,
-		        KVM_REG_PPC_CIABR, 0x00000000);
+                        KVM_REG_PPC_CIABR, 0x00000000);
 }
 
 static void gen_spr_970_dbg(CPUPPCState *env)
Signature · 1 line
2.5.0
#194 lore raw

PATCH 74/77 ppc: Print HSRR0/HSRR1 in "info registers"

In reply to Benjamin Herrenschmidt

They are generally useful when debugging HV mode stuff

---
 target-ppc/translate.c | 7 +++++++
 1 file changed, 7 insertions(+)
target-ppc/translate.c +7 -0
index f76a0c3..b34d2c6 100644
@@ -11323,6 +11323,13 @@ void ppc_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
                 env->spr[SPR_SPRG4], env->spr[SPR_SPRG5],
                 env->spr[SPR_SPRG6], env->spr[SPR_SPRG7]);
 
+#if defined(TARGET_PPC64)
+    if (env->excp_model == POWERPC_EXCP_POWER7 ||
+	env->excp_model == POWERPC_EXCP_POWER8) {
+        cpu_fprintf(f, "HSRR0 " TARGET_FMT_lx " HSRR1 " TARGET_FMT_lx "\n",
+                    env->spr[SPR_HSRR0], env->spr[SPR_HSRR1]);
+    }
+#endif
     if (env->excp_model == POWERPC_EXCP_BOOKE) {
         cpu_fprintf(f, "CSRR0 " TARGET_FMT_lx " CSRR1 " TARGET_FMT_lx
                        " MCSRR0 " TARGET_FMT_lx " MCSRR1 " TARGET_FMT_lx "\n",
Signature · 1 line
2.5.0
#195 lore raw

PATCH 75/77 ppc: Add dummy logmpp instruction

In reply to Benjamin Herrenschmidt

It's used by KVM for micropartition prefetch

---
 target-ppc/translate.c | 18 ++++++++++++++++++
 1 file changed, 18 insertions(+)
target-ppc/translate.c +18 -0
index b34d2c6..1e3996d 100644
@@ -3627,6 +3627,16 @@ static void gen_rvwinkle(DisasContext *ctx)
     gen_stop_exception(ctx);
 #endif /* defined(CONFIG_USER_ONLY) */
 }
+
+static void gen_logmpp(DisasContext *ctx)
+{
+#if defined(CONFIG_USER_ONLY)
+    GEN_PRIV;
+#else
+    CHK_HV;
+    /* This doesn't do anything in emulation */
+#endif /* defined(CONFIG_USER_ONLY) */
+}
 #endif /* #if defined(TARGET_PPC64) */
 
 /***                         Floating-point load                           ***/
@@ -9895,6 +9905,14 @@ GEN_HANDLER_E(nap, 0x13, 0x12, 0x0d, 0x03FFF801, PPC_NONE, PPC2_PM_ISA206),
 GEN_HANDLER_E(sleep, 0x13, 0x12, 0x0e, 0x03FFF801, PPC_NONE, PPC2_PM_ISA206),
 GEN_HANDLER_E(rvwinkle, 0x13, 0x12, 0x0f, 0x03FFF801, PPC_NONE, PPC2_PM_ISA206),
 GEN_HANDLER(hrfid, 0x13, 0x12, 0x08, 0x03FF8001, PPC_64H),
+
+/* This should be P8 Book4, not ISA207S, but I don't want to add a bit for that
+ * one dummy instruction. Note also that there's a discrepancy between the
+ * P8 Book4 which documents it as using RA while KVM implementation uses RB,
+ * so for now mark both fields as valid
+ */
+//GEN_HANDLER_E(logmpp, 0x1f, 0x12, 0x1f, 0x03E0F800, PPC_NONE, PPC2_ISA207S),
+GEN_HANDLER_E(logmpp, 0x1f, 0x12, 0x1f, 0x03E00000, PPC_NONE, PPC2_ISA207S),
 #endif
 GEN_HANDLER(sc, 0x11, 0xFF, 0xFF, 0x03FFF01D, PPC_FLOW),
 GEN_HANDLER(tw, 0x1F, 0x04, 0x00, 0x00000001, PPC_FLOW),
Signature · 1 line
2.5.0
#196 lore raw

PATCH 76/77 ppc: Add slbfee. instruction

In reply to Benjamin Herrenschmidt

Used to lookup SLB entries by address, for some reason it was missing.

---
 target-ppc/helper.h     |  1 +
 target-ppc/mmu-hash64.c | 24 ++++++++++++++++++++++++
 target-ppc/translate.c  | 25 +++++++++++++++++++++++++
 3 files changed, 50 insertions(+)
target-ppc/helper.h +1 -0
index 9890920..88ada3b 100644
@@ -551,6 +551,7 @@ DEF_HELPER_FLAGS_2(tlbie, TCG_CALL_NO_RWG, void, env, tl)
 DEF_HELPER_FLAGS_3(store_slb, TCG_CALL_NO_RWG, void, env, tl, tl)
 DEF_HELPER_2(load_slb_esid, tl, env, tl)
 DEF_HELPER_2(load_slb_vsid, tl, env, tl)
+DEF_HELPER_2(find_slb_esid, tl, env, tl)
 DEF_HELPER_FLAGS_1(slbia, TCG_CALL_NO_RWG, void, env)
 DEF_HELPER_FLAGS_2(slbie, TCG_CALL_NO_RWG, void, env, tl)
 #endif
target-ppc/mmu-hash64.c +24 -0
index 9071fe9..f1e9666 100644
@@ -188,6 +188,19 @@ static int ppc_load_slb_vsid(CPUPPCState *env, target_ulong rb,
     return 0;
 }
 
+static int ppc_find_slb_esid(CPUPPCState *env, target_ulong rb,
+                             target_ulong *rt)
+{
+    ppc_slb_t *slb = slb_lookup(env, rb);
+
+    if (!slb) {
+        return -1;
+    }
+
+    *rt = slb->vsid;
+    return 0;
+}
+
 void helper_store_slb(CPUPPCState *env, target_ulong rb, target_ulong rs)
 {
     if (ppc_store_slb(env, rb, rs) < 0) {
@@ -218,6 +231,17 @@ target_ulong helper_load_slb_vsid(CPUPPCState *env, target_ulong rb)
     return rt;
 }
 
+target_ulong helper_find_slb_esid(CPUPPCState *env, target_ulong rb)
+{
+    target_ulong rt = 0;
+
+    if (ppc_find_slb_esid(env, rb, &rt) < 0) {
+        helper_raise_exception_err(env, POWERPC_EXCP_PROGRAM,
+                                   POWERPC_EXCP_INVAL);
+    }
+    return rt;
+}
+
 /*
  * 64-bit hash table MMU handling
  */
target-ppc/translate.c +25 -0
index 1e3996d..b46ad72 100644
@@ -4949,6 +4949,30 @@ static void gen_slbmfev(DisasContext *ctx)
                              cpu_gpr[rB(ctx->opcode)]);
 #endif /* defined(CONFIG_USER_ONLY) */
 }
+
+static void gen_slbfee_(DisasContext *ctx)
+{
+#if defined(CONFIG_USER_ONLY)
+    GEN_PRIV;
+#else
+    TCGLabel *l1;
+    TCGLabel *l2;
+
+    CHK_SV;
+
+    gen_helper_find_slb_esid(cpu_gpr[rS(ctx->opcode)], cpu_env,
+                             cpu_gpr[rB(ctx->opcode)]);
+    l1 = gen_new_label();
+    l2 = gen_new_label();
+    tcg_gen_trunc_tl_i32(cpu_crf[0], cpu_so);
+    tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[rS(ctx->opcode)], -1, l1);
+    tcg_gen_ori_i32(cpu_crf[0], cpu_crf[0], 1 << CRF_EQ);
+    tcg_gen_br(l2);
+    gen_set_label(l1);
+    tcg_gen_movi_tl(cpu_gpr[rS(ctx->opcode)], 0);
+    gen_set_label(l2);
+#endif /* defined(CONFIG_USER_ONLY) */
+}
 #endif /* defined(TARGET_PPC64) */
 
 /***                      Lookaside buffer management                      ***/
@@ -9958,6 +9982,7 @@ GEN_HANDLER2(mtsrin_64b, "mtsrin", 0x1F, 0x12, 0x07, 0x001F0001,
 GEN_HANDLER2(slbmte, "slbmte", 0x1F, 0x12, 0x0C, 0x001F0001, PPC_SEGMENT_64B),
 GEN_HANDLER2(slbmfee, "slbmfee", 0x1F, 0x13, 0x1C, 0x001F0001, PPC_SEGMENT_64B),
 GEN_HANDLER2(slbmfev, "slbmfev", 0x1F, 0x13, 0x1A, 0x001F0001, PPC_SEGMENT_64B),
+GEN_HANDLER2(slbfee_, "slbfee.", 0x1F, 0x13, 0x1E, 0x001F0000, PPC_SEGMENT_64B),
 #endif
 GEN_HANDLER(tlbia, 0x1F, 0x12, 0x0B, 0x03FFFC01, PPC_MEM_TLBIA),
 /* XXX Those instructions will need to be handled differently for
Signature · 1 line
2.5.0
#197 lore raw

PATCH 77/77 ppc: Fix CFAR updates

In reply to Benjamin Herrenschmidt

We need to remove 4 from the NIP since it's already been moved by 4 by the dispatcher before the helper is called

---
 target-ppc/translate.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)
target-ppc/translate.c +4 -4
index b46ad72..d3e7d5b 100644
@@ -4035,7 +4035,7 @@ static void gen_b(DisasContext *ctx)
     if (LK(ctx->opcode)) {
         gen_setlr(ctx, ctx->nip);
     }
-    gen_update_cfar(ctx, ctx->nip);
+    gen_update_cfar(ctx, ctx->nip - 4);
     gen_goto_tb(ctx, 0, target);
 }
 
@@ -4100,7 +4100,7 @@ static inline void gen_bcond(DisasContext *ctx, int type)
         }
         tcg_temp_free_i32(temp);
     }
-    gen_update_cfar(ctx, ctx->nip);
+    gen_update_cfar(ctx, ctx->nip - 4);
     if (type == BCOND_IM) {
         target_ulong li = (target_long)((int16_t)(BD(ctx->opcode)));
         if (likely(AA(ctx->opcode) == 0)) {
@@ -4211,7 +4211,7 @@ static void gen_rfi(DisasContext *ctx)
 #else
     /* Restore CPU state */
     CHK_SV;
-    gen_update_cfar(ctx, ctx->nip);
+    gen_update_cfar(ctx, ctx->nip - 4);
     gen_helper_rfi(cpu_env);
     gen_sync_exception(ctx);
 #endif
@@ -4225,7 +4225,7 @@ static void gen_rfid(DisasContext *ctx)
 #else
     /* Restore CPU state */
     CHK_SV;
-    gen_update_cfar(ctx, ctx->nip);
+    gen_update_cfar(ctx, ctx->nip - 4);
     gen_helper_rfid(cpu_env);
     gen_sync_exception(ctx);
 #endif
Signature · 1 line
2.5.0