Skip to contentSkip to conversation

ppc patch queue 2013-01-07

GIT PULL New Alexander Graf 5 participants 38 messages Jan 7, 2013 – Jan 12, 2013

lore
Share & tools
lore
#0 lore raw

Hi Blue / Aurelien,

This is my current patch queue for ppc. Please pull.

Alex

The following changes since commit 8e4a424b305e29dc0e454f52df3b35577f342975:
Blue Swirl (1):
Revert "virtio-pci: replace byte swap hack"

are available in the git repository at:

git://repo.or.cz/qemu/agraf.git ppc-for-upstream

Alexander Graf (3):
openpic: fix coding style issues
kvm: Update kernel headers
PPC: Bring EPR support closer to reality

Andreas Färber (2):
target-ppc: Slim conversion of model definitions to QOM subclasses
target-ppc: Error out for -cpu host on unknown PVR

Bharat Bhushan (2):
powerpc: linux header sync script includes epapr_hcalls.h
PPC: Reset qemu timers when guest reset

Samuel Seay (2):
PPC: fix segfault in signal handling code
PPC: linux-user: Calculate context pointer explicitly

Scott Wood (21):
openpic: symbolicize some magic numbers
openpic: remove pcsr (CPU sensitivity register)
openpic: support large vectors on FSL mpic
openpic: BRR1 is not a CPU-specific register.
openpic: s/opp->nb_irqs -1/opp->nb_cpus - 1/
openpic: don't crash on a register access without a CPU context
openpic: fix debug prints
openpic: lower interrupt when reading the MSI register ppc/booke: fix crit/mcheck/debug exceptions
openpic: make register names correspond better with hw docs
openpic: rework critical interrupt support
openpic: make ctpr signed
openpic/fsl: critical interrupts ignore mask before v4.1
openpic: always call IRQ_check from IRQ_get_next Revert "openpic: Accelerate pending irq search"
openpic: use standard bitmap operations
openpic: add some bounds checking for IRQ numbers
openpic: fix sense and priority bits
openpic: IRQ_check: search the queue a word at a time
openpic: move IACK to its own function
openpic: fix CTPR and de-assertion of interrupts

Stuart Yoder (1):
PPC: KVM: set has-idle in guest device tree

 hw/openpic.c                             | 1032 ++++++++++++++++++-----------
 hw/ppc/e500.c                            |    8 +-
 hw/ppc_booke.c                           |   13 +
 linux-headers/asm-powerpc/epapr_hcalls.h |   98 +++
 linux-headers/asm-powerpc/kvm.h          |   86 +++
 linux-headers/asm-powerpc/kvm_para.h     |   13 +-
 linux-headers/linux/kvm.h                |   21 +-
 linux-headers/linux/kvm_para.h           |    6 +-
 linux-headers/linux/vfio.h               |    6 +-
 linux-headers/linux/virtio_config.h      |    6 +-
 linux-headers/linux/virtio_ring.h        |    6 +-
 linux-user/signal.c                      |    6 +-
 scripts/update-linux-headers.sh          |    3 +
 target-ppc/Makefile.objs                 |    4 +-
 target-ppc/cpu-qom.h                     |    5 +
 target-ppc/cpu.h                         |    8 +-
 target-ppc/excp_helper.c                 |   35 +-
 target-ppc/helper.c                      |   50 --
 target-ppc/helper.h                      |    1 -
 target-ppc/kvm.c                         |   77 ++-
 target-ppc/kvm_ppc.h                     |    9 +-
 target-ppc/mpic_helper.c                 |   35 -
 target-ppc/translate_init.c              |  352 +++++++----
 23 files changed, 1225 insertions(+), 655 deletions(-)
 create mode 100644 linux-headers/asm-powerpc/epapr_hcalls.h
 delete mode 100644 target-ppc/helper.c
 delete mode 100644 target-ppc/mpic_helper.c
#1 lore raw

PATCH 1/31 openpic: symbolicize some magic numbers

From: Scott Wood <[email protected]>

Deefine symbolic names for some register bits, and use some that have already been defined.

Also convert some register values from hex to decimal when it improves readability.

IPVP_PRIORITY_MASK is corrected from (0x1F << 16) to (0xF << 16), in conjunction with making wider use of the symbolic name. I looked at Freescale and IBM MPIC docs and at the base OpenPIC spec, and all three had priority as 4 bits rather than 5. Plus, the magic nubmer that is being replaced with symbolic values treated the field as 4 bits wide.

---
 hw/openpic.c |   54 ++++++++++++++++++++++++++++++++----------------------
 1 files changed, 32 insertions(+), 22 deletions(-)
hw/openpic.c +32 -22
index 9c956b9..eff1eee 100644
@@ -124,6 +124,11 @@
 
 #define VENI_GENERIC      0x00000000 /* Generic Vendor ID */
 
+#define GLBC_RESET        0x80000000
+
+#define TIBC_CI           0x80000000 /* count inhibit */
+#define TICC_TOG          0x80000000 /* toggles when decrement to zero */
+
 #define IDR_EP_SHIFT      31
 #define IDR_EP_MASK       (1 << IDR_EP_SHIFT)
 #define IDR_CI0_SHIFT     30
@@ -190,11 +195,15 @@ typedef struct IRQ_src_t {
 #define IPVP_SENSE_SHIFT      22
 #define IPVP_SENSE_MASK       (1 << IPVP_SENSE_SHIFT)
 
-#define IPVP_PRIORITY_MASK     (0x1F << 16)
+#define IPVP_PRIORITY_MASK     (0xF << 16)
 #define IPVP_PRIORITY(_ipvpr_) ((int)(((_ipvpr_) & IPVP_PRIORITY_MASK) >> 16))
 #define IPVP_VECTOR_MASK       ((1 << VECTOR_BITS) - 1)
 #define IPVP_VECTOR(_ipvpr_)   ((_ipvpr_) & IPVP_VECTOR_MASK)
 
+/* IDE[EP/CI] are only for FSL MPIC prior to v4.0 */
+#define IDE_EP      0x80000000  /* external pin */
+#define IDE_CI      0x40000000  /* critical interrupt */
+
 typedef struct IRQ_dst_t {
     uint32_t pctp; /* CPU current task priority */
     uint32_t pcsr; /* CPU sensitivity register */
@@ -375,7 +384,7 @@ static void openpic_update_irq(OpenPICState *opp, int n_IRQ)
         DPRINTF("%s: IRQ %d is already active\n", __func__, n_IRQ);
         return;
     }
-    if (src->ide == 0x00000000) {
+    if (src->ide == 0) {
         /* No target */
         DPRINTF("%s: IRQ %d has no target\n", __func__, n_IRQ);
         return;
@@ -432,13 +441,13 @@ static void openpic_reset(DeviceState *d)
     OpenPICState *opp = FROM_SYSBUS(typeof (*opp), sysbus_from_qdev(d));
     int i;
 
-    opp->glbc = 0x80000000;
+    opp->glbc = GLBC_RESET;
     /* Initialise controller registers */
     opp->frep = ((opp->nb_irqs -1) << FREP_NIRQ_SHIFT) |
                 ((opp->nb_cpus -1) << FREP_NCPU_SHIFT) |
                 (opp->vid << FREP_VID_SHIFT);
 
-    opp->pint = 0x00000000;
+    opp->pint = 0;
     opp->spve = -1 & opp->spve_mask;
     opp->tifr = opp->tifr_reset;
     /* Initialise IRQ sources */
@@ -448,7 +457,7 @@ static void openpic_reset(DeviceState *d)
     }
     /* Initialise IRQ destinations */
     for (i = 0; i < MAX_CPU; i++) {
-        opp->dst[i].pctp      = 0x0000000F;
+        opp->dst[i].pctp      = 15;
         opp->dst[i].pcsr      = 0x00000000;
         memset(&opp->dst[i].raised, 0, sizeof(IRQ_queue_t));
         opp->dst[i].raised.next = -1;
@@ -457,11 +466,11 @@ static void openpic_reset(DeviceState *d)
     }
     /* Initialise timers */
     for (i = 0; i < MAX_TMR; i++) {
-        opp->timers[i].ticc = 0x00000000;
-        opp->timers[i].tibc = 0x80000000;
+        opp->timers[i].ticc = 0;
+        opp->timers[i].tibc = TIBC_CI;
     }
     /* Go out of RESET state */
-    opp->glbc = 0x00000000;
+    opp->glbc = 0;
 }
 
 static inline uint32_t read_IRQreg_ide(OpenPICState *opp, int n_IRQ)
@@ -478,7 +487,7 @@ static inline void write_IRQreg_ide(OpenPICState *opp, int n_IRQ, uint32_t val)
 {
     uint32_t tmp;
 
-    tmp = val & 0xC0000000;
+    tmp = val & (IDE_EP | IDE_CI);
     tmp |= val & ((1ULL << MAX_CPU) - 1);
     opp->src[n_IRQ].ide = tmp;
     DPRINTF("Set IDE %d to 0x%08x\n", n_IRQ, opp->src[n_IRQ].ide);
@@ -488,8 +497,8 @@ static inline void write_IRQreg_ipvp(OpenPICState *opp, int n_IRQ, uint32_t val)
 {
     /* NOTE: not fully accurate for special IRQs, but simple and sufficient */
     /* ACTIVITY bit is read-only */
-    opp->src[n_IRQ].ipvp = (opp->src[n_IRQ].ipvp & 0x40000000)
-                         | (val & 0x800F00FF);
+    opp->src[n_IRQ].ipvp = (opp->src[n_IRQ].ipvp & IPVP_ACTIVITY_MASK) |
+        (val & (IPVP_MASK_MASK | IPVP_PRIORITY_MASK | IPVP_VECTOR_MASK));
     openpic_update_irq(opp, n_IRQ);
     DPRINTF("Set IPVP %d to 0x%08x -> 0x%08x\n", n_IRQ, val,
             opp->src[n_IRQ].ipvp);
@@ -521,7 +530,7 @@ static void openpic_gbl_write(void *opaque, hwaddr addr, uint64_t val,
     case 0x1000: /* FREP */
         break;
     case 0x1020: /* GLBC */
-        if (val & 0x80000000) {
+        if (val & GLBC_RESET) {
             openpic_reset(&opp->busdev.qdev);
         }
         break;
@@ -634,10 +643,11 @@ static void openpic_tmr_write(void *opaque, hwaddr addr, uint64_t val,
     case 0x00: /* TICC (GTCCR) */
         break;
     case 0x10: /* TIBC (GTBCR) */
-        if ((opp->timers[idx].ticc & 0x80000000) != 0 &&
-            (val & 0x80000000) == 0 &&
-            (opp->timers[idx].tibc & 0x80000000) != 0)
-            opp->timers[idx].ticc &= ~0x80000000;
+        if ((opp->timers[idx].ticc & TICC_TOG) != 0 &&
+            (val & TIBC_CI) == 0 &&
+            (opp->timers[idx].tibc & TIBC_CI) != 0) {
+            opp->timers[idx].ticc &= ~TICC_TOG;
+        }
         opp->timers[idx].tibc = val;
         break;
     case 0x20: /* TIVP (GTIVPR) */
@@ -1190,9 +1200,9 @@ static int openpic_init(SysBusDevice *dev)
         opp->vid = VID_REVISION_1_2;
         opp->veni = VENI_GENERIC;
         opp->spve_mask = 0xFFFF;
-        opp->tifr_reset = 0x00000000;
-        opp->ipvp_reset = 0x80000000;
-        opp->ide_reset = 0x00000001;
+        opp->tifr_reset = 0;
+        opp->ipvp_reset = IPVP_MASK_MASK;
+        opp->ide_reset = 1 << 0;
         opp->max_irq = FSL_MPIC_20_MAX_IRQ;
         opp->irq_ipi0 = FSL_MPIC_20_IPI_IRQ;
         opp->irq_tim0 = FSL_MPIC_20_TMR_IRQ;
@@ -1206,9 +1216,9 @@ static int openpic_init(SysBusDevice *dev)
         opp->vid = VID_REVISION_1_3;
         opp->veni = VENI_GENERIC;
         opp->spve_mask = 0xFF;
-        opp->tifr_reset = 0x003F7A00;
-        opp->ipvp_reset = 0xA0000000;
-        opp->ide_reset = 0x00000000;
+        opp->tifr_reset = 4160000;
+        opp->ipvp_reset = IPVP_MASK_MASK | IPVP_MODE_MASK;
+        opp->ide_reset = 0;
         opp->max_irq = RAVEN_MAX_IRQ;
         opp->irq_ipi0 = RAVEN_IPI_IRQ;
         opp->irq_tim0 = RAVEN_TMR_IRQ;
Signature · 1 line
1.6.0.2
#2 lore raw

PATCH 2/31 openpic: remove pcsr (CPU sensitivity register)

In reply to Alexander Graf

From: Scott Wood <[email protected]>

I could not find this register in any spec (FSL, IBM, or OpenPIC) and the code doesn't do anything with it but initialize, save, or restore it.

---
 hw/openpic.c |    4 ----
 1 files changed, 0 insertions(+), 4 deletions(-)
hw/openpic.c +0 -4
index eff1eee..44f7cc4 100644
@@ -206,7 +206,6 @@ typedef struct IRQ_src_t {
 
 typedef struct IRQ_dst_t {
     uint32_t pctp; /* CPU current task priority */
-    uint32_t pcsr; /* CPU sensitivity register */
     IRQ_queue_t raised;
     IRQ_queue_t servicing;
     qemu_irq *irqs;
@@ -458,7 +457,6 @@ static void openpic_reset(DeviceState *d)
     /* Initialise IRQ destinations */
     for (i = 0; i < MAX_CPU; i++) {
         opp->dst[i].pctp      = 15;
-        opp->dst[i].pcsr      = 0x00000000;
         memset(&opp->dst[i].raised, 0, sizeof(IRQ_queue_t));
         opp->dst[i].raised.next = -1;
         memset(&opp->dst[i].servicing, 0, sizeof(IRQ_queue_t));
@@ -1083,7 +1081,6 @@ static void openpic_save(QEMUFile* f, void *opaque)
 
     for (i = 0; i < opp->nb_cpus; i++) {
         qemu_put_be32s(f, &opp->dst[i].pctp);
-        qemu_put_be32s(f, &opp->dst[i].pcsr);
         openpic_save_IRQ_queue(f, &opp->dst[i].raised);
         openpic_save_IRQ_queue(f, &opp->dst[i].servicing);
     }
@@ -1130,7 +1127,6 @@ static int openpic_load(QEMUFile* f, void *opaque, int version_id)
 
     for (i = 0; i < opp->nb_cpus; i++) {
         qemu_get_be32s(f, &opp->dst[i].pctp);
-        qemu_get_be32s(f, &opp->dst[i].pcsr);
         openpic_load_IRQ_queue(f, &opp->dst[i].raised);
         openpic_load_IRQ_queue(f, &opp->dst[i].servicing);
     }
Signature · 1 line
1.6.0.2
#3 lore raw

PATCH 3/31 openpic: support large vectors on FSL mpic

In reply to Alexander Graf

From: Scott Wood <[email protected]>

Previously only the spurious vector was sized appropriately to the openpic model.

Also, instances of "IPVP_VECTOR(opp->spve)" were replace with just "opp->spve", as opp->spve is already just a vector and not an IVPR.

---
 hw/openpic.c |   22 ++++++++++------------
 1 files changed, 10 insertions(+), 12 deletions(-)
hw/openpic.c +10 -12
index 44f7cc4..f0877fa 100644
@@ -51,7 +51,6 @@
 #define MAX_CPU     15
 #define MAX_SRC     256
 #define MAX_TMR     4
-#define VECTOR_BITS 8
 #define MAX_IPI     4
 #define MAX_MSI     8
 #define MAX_IRQ     (MAX_SRC + MAX_IPI + MAX_TMR)
@@ -197,8 +196,7 @@ typedef struct IRQ_src_t {
 
 #define IPVP_PRIORITY_MASK     (0xF << 16)
 #define IPVP_PRIORITY(_ipvpr_) ((int)(((_ipvpr_) & IPVP_PRIORITY_MASK) >> 16))
-#define IPVP_VECTOR_MASK       ((1 << VECTOR_BITS) - 1)
-#define IPVP_VECTOR(_ipvpr_)   ((_ipvpr_) & IPVP_VECTOR_MASK)
+#define IPVP_VECTOR(opp, _ipvpr_) ((_ipvpr_) & (opp)->vector_mask)
 
 /* IDE[EP/CI] are only for FSL MPIC prior to v4.0 */
 #define IDE_EP      0x80000000  /* external pin */
@@ -221,7 +219,7 @@ typedef struct OpenPICState {
     uint32_t nb_irqs;
     uint32_t vid;
     uint32_t veni; /* Vendor identification register */
-    uint32_t spve_mask;
+    uint32_t vector_mask;
     uint32_t tifr_reset;
     uint32_t ipvp_reset;
     uint32_t ide_reset;
@@ -447,7 +445,7 @@ static void openpic_reset(DeviceState *d)
                 (opp->vid << FREP_VID_SHIFT);
 
     opp->pint = 0;
-    opp->spve = -1 & opp->spve_mask;
+    opp->spve = -1 & opp->vector_mask;
     opp->tifr = opp->tifr_reset;
     /* Initialise IRQ sources */
     for (i = 0; i < opp->max_irq; i++) {
@@ -496,7 +494,7 @@ static inline void write_IRQreg_ipvp(OpenPICState *opp, int n_IRQ, uint32_t val)
     /* NOTE: not fully accurate for special IRQs, but simple and sufficient */
     /* ACTIVITY bit is read-only */
     opp->src[n_IRQ].ipvp = (opp->src[n_IRQ].ipvp & IPVP_ACTIVITY_MASK) |
-        (val & (IPVP_MASK_MASK | IPVP_PRIORITY_MASK | IPVP_VECTOR_MASK));
+        (val & (IPVP_MASK_MASK | IPVP_PRIORITY_MASK | opp->vector_mask));
     openpic_update_irq(opp, n_IRQ);
     DPRINTF("Set IPVP %d to 0x%08x -> 0x%08x\n", n_IRQ, val,
             opp->src[n_IRQ].ipvp);
@@ -559,7 +557,7 @@ static void openpic_gbl_write(void *opaque, hwaddr addr, uint64_t val,
         }
         break;
     case 0x10E0: /* SPVE */
-        opp->spve = val & opp->spve_mask;
+        opp->spve = val & opp->vector_mask;
         break;
     default:
         break;
@@ -896,7 +894,7 @@ static uint32_t openpic_cpu_read_internal(void *opaque, hwaddr addr,
         DPRINTF("PIAC: irq=%d\n", n_IRQ);
         if (n_IRQ == -1) {
             /* No more interrupt pending */
-            retval = IPVP_VECTOR(opp->spve);
+            retval = opp->spve;
         } else {
             src = &opp->src[n_IRQ];
             if (!(src->ipvp & IPVP_ACTIVITY_MASK) ||
@@ -906,11 +904,11 @@ static uint32_t openpic_cpu_read_internal(void *opaque, hwaddr addr,
                  *   and the pending IRQ isn't allowed anymore
                  */
                 src->ipvp &= ~IPVP_ACTIVITY_MASK;
-                retval = IPVP_VECTOR(opp->spve);
+                retval = opp->spve;
             } else {
                 /* IRQ enter servicing state */
                 IRQ_setbit(&dst->servicing, n_IRQ);
-                retval = IPVP_VECTOR(src->ipvp);
+                retval = IPVP_VECTOR(opp, src->ipvp);
             }
             IRQ_resetbit(&dst->raised, n_IRQ);
             dst->raised.next = -1;
@@ -1195,7 +1193,7 @@ static int openpic_init(SysBusDevice *dev)
         opp->nb_irqs = 80;
         opp->vid = VID_REVISION_1_2;
         opp->veni = VENI_GENERIC;
-        opp->spve_mask = 0xFFFF;
+        opp->vector_mask = 0xFFFF;
         opp->tifr_reset = 0;
         opp->ipvp_reset = IPVP_MASK_MASK;
         opp->ide_reset = 1 << 0;
@@ -1211,7 +1209,7 @@ static int openpic_init(SysBusDevice *dev)
         opp->nb_irqs = RAVEN_MAX_EXT;
         opp->vid = VID_REVISION_1_3;
         opp->veni = VENI_GENERIC;
-        opp->spve_mask = 0xFF;
+        opp->vector_mask = 0xFF;
         opp->tifr_reset = 4160000;
         opp->ipvp_reset = IPVP_MASK_MASK | IPVP_MODE_MASK;
         opp->ide_reset = 0;
Signature · 1 line
1.6.0.2
#4 lore raw

PATCH 4/31 openpic: BRR1 is not a CPU-specific register.

In reply to Alexander Graf

From: Scott Wood <[email protected]>

It's in the address range that normally contains a magic redirection to the CPU-specific region of the curretn CPU, but it isn't actually a per-CPU register. On real hardware BRR1 shows up only at 0x40000, not at 0x60000 or other non-magic per-CPU areas. Plus, this makes it possible to read the register on the QEMU command line with "xp".

---
 hw/openpic.c |    5 ++---
 1 files changed, 2 insertions(+), 3 deletions(-)
hw/openpic.c +2 -3
index f0877fa..337dbf5 100644
@@ -587,6 +587,8 @@ static uint64_t openpic_gbl_read(void *opaque, hwaddr addr, unsigned len)
         retval = 0x00000000;
         break;
     case 0x00: /* Block Revision Register1 (BRR1) */
+        retval = opp->brr1;
+        break;
     case 0x40:
     case 0x50:
     case 0x60:
@@ -878,9 +880,6 @@ static uint32_t openpic_cpu_read_internal(void *opaque, hwaddr addr,
     dst = &opp->dst[idx];
     addr &= 0xFF0;
     switch (addr) {
-    case 0x00: /* Block Revision Register1 (BRR1) */
-        retval = opp->brr1;
-        break;
     case 0x80: /* PCTP */
         retval = dst->pctp;
         break;
Signature · 1 line
1.6.0.2
#5 lore raw

PATCH 5/31 openpic: s/opp->nb_irqs -1/opp->nb_cpus - 1/

In reply to Alexander Graf

From: Scott Wood <[email protected]>

"opp->nb_irqs-1" would have been a minor coding style error, but putting in one space but not the other makes it look confusingly like a numeric literal "-1".

---
 hw/openpic.c |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)
hw/openpic.c +2 -2
index 337dbf5..10dbdf7 100644
@@ -440,8 +440,8 @@ static void openpic_reset(DeviceState *d)
 
     opp->glbc = GLBC_RESET;
     /* Initialise controller registers */
-    opp->frep = ((opp->nb_irqs -1) << FREP_NIRQ_SHIFT) |
-                ((opp->nb_cpus -1) << FREP_NCPU_SHIFT) |
+    opp->frep = ((opp->nb_irqs - 1) << FREP_NIRQ_SHIFT) |
+                ((opp->nb_cpus - 1) << FREP_NCPU_SHIFT) |
                 (opp->vid << FREP_VID_SHIFT);
 
     opp->pint = 0;
Signature · 1 line
1.6.0.2
#6 lore raw

PATCH 6/31 openpic: don't crash on a register access without a CPU context

In reply to Alexander Graf

From: Scott Wood <[email protected]>

If we access a register via the QEMU memory inspection commands (e.g. "xp") rather than from guest code, we won't have a CPU context. Gracefully fail to access the register in that case, rather than crashing.

---
 hw/openpic.c |   16 +++++++++++++++-
 1 files changed, 15 insertions(+), 1 deletions(-)
hw/openpic.c +15 -1
index 10dbdf7..93e8208 100644
@@ -161,7 +161,11 @@ static inline int test_bit(uint32_t *field, int bit)
 
 static int get_current_cpu(void)
 {
-  return cpu_single_env->cpu_index;
+    if (!cpu_single_env) {
+        return -1;
+    }
+
+    return cpu_single_env->cpu_index;
 }
 
 static uint32_t openpic_cpu_read_internal(void *opaque, hwaddr addr,
@@ -810,6 +814,11 @@ static void openpic_cpu_write_internal(void *opaque, hwaddr addr,
 
     DPRINTF("%s: cpu %d addr " TARGET_FMT_plx " <= %08x\n", __func__, idx,
             addr, val);
+
+    if (idx < 0) {
+        return;
+    }
+
     if (addr & 0xF)
         return;
     dst = &opp->dst[idx];
@@ -875,6 +884,11 @@ static uint32_t openpic_cpu_read_internal(void *opaque, hwaddr addr,
 
     DPRINTF("%s: cpu %d addr " TARGET_FMT_plx "\n", __func__, idx, addr);
     retval = 0xFFFFFFFF;
+
+    if (idx < 0) {
+        return retval;
+    }
+
     if (addr & 0xF)
         return retval;
     dst = &opp->dst[idx];
Signature · 1 line
1.6.0.2
#7 lore raw

PATCH 7/31 powerpc: linux header sync script includes epapr_hcalls.h

In reply to Alexander Graf

From: Bharat Bhushan <[email protected]>

epapr_hcalls.h is now referenced by kvm_para.h. so this is needed for QEMU to get compiled on powerpc.

---
 scripts/update-linux-headers.sh |    3 +++
 1 files changed, 3 insertions(+), 0 deletions(-)
scripts/update-linux-headers.sh +3 -0
index 4c7b566..120a694 100755
@@ -54,6 +54,9 @@ for arch in $ARCHLIST; do
     if [ $arch = x86 ]; then
         cp "$tmpdir/include/asm/hyperv.h" "$output/linux-headers/asm-x86"
     fi
+    if [ $arch = powerpc ]; then
+        cp "$tmpdir/include/asm/epapr_hcalls.h" "$output/linux-headers/asm-powerpc/"
+    fi
 done
 
 rm -rf "$output/linux-headers/linux"
Signature · 1 line
1.6.0.2
#8 lore raw

PATCH 8/31 openpic: fix coding style issues

In reply to Alexander Graf

This patch fixes the following coding style violations:

- structs have to be typedef and be CamelCase
- if()s are always surrounded by curly braces

---
 hw/openpic.c |  100 ++++++++++++++++++++++++++++++++--------------------------
 1 files changed, 55 insertions(+), 45 deletions(-)
hw/openpic.c +55 -45
index 93e8208..55e96d1 100644
@@ -173,19 +173,19 @@ static uint32_t openpic_cpu_read_internal(void *opaque, hwaddr addr,
 static void openpic_cpu_write_internal(void *opaque, hwaddr addr,
                                        uint32_t val, int idx);
 
-typedef struct IRQ_queue_t {
+typedef struct IRQQueue {
     uint32_t queue[BF_WIDTH(MAX_IRQ)];
     int next;
     int priority;
     int pending;    /* nr of pending bits in queue */
-} IRQ_queue_t;
+} IRQQueue;
 
-typedef struct IRQ_src_t {
+typedef struct IRQSource {
     uint32_t ipvp;  /* IRQ vector/priority register */
     uint32_t ide;   /* IRQ destination register */
     int last_cpu;
     int pending;    /* TRUE if IRQ is pending */
-} IRQ_src_t;
+} IRQSource;
 
 #define IPVP_MASK_SHIFT       31
 #define IPVP_MASK_MASK        (1 << IPVP_MASK_SHIFT)
@@ -206,12 +206,12 @@ typedef struct IRQ_src_t {
 #define IDE_EP      0x80000000  /* external pin */
 #define IDE_CI      0x40000000  /* critical interrupt */
 
-typedef struct IRQ_dst_t {
+typedef struct IRQDest {
     uint32_t pctp; /* CPU current task priority */
-    IRQ_queue_t raised;
-    IRQ_queue_t servicing;
+    IRQQueue raised;
+    IRQQueue servicing;
     qemu_irq *irqs;
-} IRQ_dst_t;
+} IRQDest;
 
 typedef struct OpenPICState {
     SysBusDevice busdev;
@@ -239,9 +239,9 @@ typedef struct OpenPICState {
     uint32_t spve; /* Spurious vector register */
     uint32_t tifr; /* Timer frequency reporting register */
     /* Source registers */
-    IRQ_src_t src[MAX_IRQ];
+    IRQSource src[MAX_IRQ];
     /* Local registers per output pin */
-    IRQ_dst_t dst[MAX_CPU];
+    IRQDest dst[MAX_CPU];
     uint32_t nb_cpus;
     /* Timer registers */
     struct {
@@ -258,26 +258,26 @@ typedef struct OpenPICState {
     uint32_t irq_msi;
 } OpenPICState;
 
-static void openpic_irq_raise(OpenPICState *opp, int n_CPU, IRQ_src_t *src);
+static void openpic_irq_raise(OpenPICState *opp, int n_CPU, IRQSource *src);
 
-static inline void IRQ_setbit(IRQ_queue_t *q, int n_IRQ)
+static inline void IRQ_setbit(IRQQueue *q, int n_IRQ)
 {
     q->pending++;
     set_bit(q->queue, n_IRQ);
 }
 
-static inline void IRQ_resetbit(IRQ_queue_t *q, int n_IRQ)
+static inline void IRQ_resetbit(IRQQueue *q, int n_IRQ)
 {
     q->pending--;
     reset_bit(q->queue, n_IRQ);
 }
 
-static inline int IRQ_testbit(IRQ_queue_t *q, int n_IRQ)
+static inline int IRQ_testbit(IRQQueue *q, int n_IRQ)
 {
     return test_bit(q->queue, n_IRQ);
 }
 
-static void IRQ_check(OpenPICState *opp, IRQ_queue_t *q)
+static void IRQ_check(OpenPICState *opp, IRQQueue *q)
 {
     int next, i;
     int priority;
@@ -306,7 +306,7 @@ out:
     q->priority = priority;
 }
 
-static int IRQ_get_next(OpenPICState *opp, IRQ_queue_t *q)
+static int IRQ_get_next(OpenPICState *opp, IRQQueue *q)
 {
     if (q->next == -1) {
         /* XXX: optimize */
@@ -318,8 +318,8 @@ static int IRQ_get_next(OpenPICState *opp, IRQ_queue_t *q)
 
 static void IRQ_local_pipe(OpenPICState *opp, int n_CPU, int n_IRQ)
 {
-    IRQ_dst_t *dst;
-    IRQ_src_t *src;
+    IRQDest *dst;
+    IRQSource *src;
     int priority;
 
     dst = &opp->dst[n_CPU];
@@ -360,7 +360,7 @@ static void IRQ_local_pipe(OpenPICState *opp, int n_CPU, int n_IRQ)
 /* update pic state because registers for n_IRQ have changed value */
 static void openpic_update_irq(OpenPICState *opp, int n_IRQ)
 {
-    IRQ_src_t *src;
+    IRQSource *src;
     int i;
 
     src = &opp->src[n_IRQ];
@@ -404,8 +404,9 @@ static void openpic_update_irq(OpenPICState *opp, int n_IRQ)
     } else {
         /* Distributed delivery mode */
         for (i = src->last_cpu + 1; i != src->last_cpu; i++) {
-            if (i == opp->nb_cpus)
+            if (i == opp->nb_cpus) {
                 i = 0;
+            }
             if (src->ide & (1 << i)) {
                 IRQ_local_pipe(opp, i, n_IRQ);
                 src->last_cpu = i;
@@ -418,7 +419,7 @@ static void openpic_update_irq(OpenPICState *opp, int n_IRQ)
 static void openpic_set_irq(void *opaque, int n_IRQ, int level)
 {
     OpenPICState *opp = opaque;
-    IRQ_src_t *src;
+    IRQSource *src;
 
     src = &opp->src[n_IRQ];
     DPRINTF("openpic: set irq %d = %d ipvp=%08x\n",
@@ -431,8 +432,9 @@ static void openpic_set_irq(void *opaque, int n_IRQ, int level)
         }
     } else {
         /* edge-sensitive irq */
-        if (level)
+        if (level) {
             src->pending = 1;
+        }
     }
     openpic_update_irq(opp, n_IRQ);
 }
@@ -459,9 +461,9 @@ static void openpic_reset(DeviceState *d)
     /* Initialise IRQ destinations */
     for (i = 0; i < MAX_CPU; i++) {
         opp->dst[i].pctp      = 15;
-        memset(&opp->dst[i].raised, 0, sizeof(IRQ_queue_t));
+        memset(&opp->dst[i].raised, 0, sizeof(IRQQueue));
         opp->dst[i].raised.next = -1;
-        memset(&opp->dst[i].servicing, 0, sizeof(IRQ_queue_t));
+        memset(&opp->dst[i].servicing, 0, sizeof(IRQQueue));
         opp->dst[i].servicing.next = -1;
     }
     /* Initialise timers */
@@ -508,12 +510,13 @@ static void openpic_gbl_write(void *opaque, hwaddr addr, uint64_t val,
                               unsigned len)
 {
     OpenPICState *opp = opaque;
-    IRQ_dst_t *dst;
+    IRQDest *dst;
     int idx;
 
     DPRINTF("%s: addr " TARGET_FMT_plx " <= %08x\n", __func__, addr, val);
-    if (addr & 0xF)
+    if (addr & 0xF) {
         return;
+    }
     switch (addr) {
     case 0x00: /* Block Revision Register1 (BRR1) is Readonly */
         break;
@@ -575,8 +578,9 @@ static uint64_t openpic_gbl_read(void *opaque, hwaddr addr, unsigned len)
 
     DPRINTF("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
     retval = 0xFFFFFFFF;
-    if (addr & 0xF)
+    if (addr & 0xF) {
         return retval;
+    }
     switch (addr) {
     case 0x1000: /* FREP */
         retval = opp->frep;
@@ -631,8 +635,9 @@ static void openpic_tmr_write(void *opaque, hwaddr addr, uint64_t val,
     int idx;
 
     DPRINTF("%s: addr %08x <= %08x\n", __func__, addr, val);
-    if (addr & 0xF)
+    if (addr & 0xF) {
         return;
+    }
     idx = (addr >> 6) & 0x3;
     addr = addr & 0x30;
 
@@ -705,8 +710,9 @@ static void openpic_src_write(void *opaque, hwaddr addr, uint64_t val,
     int idx;
 
     DPRINTF("%s: addr %08x <= %08x\n", __func__, addr, val);
-    if (addr & 0xF)
+    if (addr & 0xF) {
         return;
+    }
     addr = addr & 0xFFF0;
     idx = addr >> 5;
     if (addr & 0x10) {
@@ -726,8 +732,9 @@ static uint64_t openpic_src_read(void *opaque, uint64_t addr, unsigned len)
 
     DPRINTF("%s: addr %08x\n", __func__, addr);
     retval = 0xFFFFFFFF;
-    if (addr & 0xF)
+    if (addr & 0xF) {
         return retval;
+    }
     addr = addr & 0xFFF0;
     idx = addr >> 5;
     if (addr & 0x10) {
@@ -808,8 +815,8 @@ static void openpic_cpu_write_internal(void *opaque, hwaddr addr,
                                        uint32_t val, int idx)
 {
     OpenPICState *opp = opaque;
-    IRQ_src_t *src;
-    IRQ_dst_t *dst;
+    IRQSource *src;
+    IRQDest *dst;
     int s_IRQ, n_IRQ;
 
     DPRINTF("%s: cpu %d addr " TARGET_FMT_plx " <= %08x\n", __func__, idx,
@@ -819,8 +826,9 @@ static void openpic_cpu_write_internal(void *opaque, hwaddr addr,
         return;
     }
 
-    if (addr & 0xF)
+    if (addr & 0xF) {
         return;
+    }
     dst = &opp->dst[idx];
     addr &= 0xFF0;
     switch (addr) {
@@ -877,8 +885,8 @@ static uint32_t openpic_cpu_read_internal(void *opaque, hwaddr addr,
                                           int idx)
 {
     OpenPICState *opp = opaque;
-    IRQ_src_t *src;
-    IRQ_dst_t *dst;
+    IRQSource *src;
+    IRQDest *dst;
     uint32_t retval;
     int n_IRQ;
 
@@ -889,8 +897,9 @@ static uint32_t openpic_cpu_read_internal(void *opaque, hwaddr addr,
         return retval;
     }
 
-    if (addr & 0xF)
+    if (addr & 0xF) {
         return retval;
+    }
     dst = &opp->dst[idx];
     addr &= 0xFF0;
     switch (addr) {
@@ -1059,7 +1068,7 @@ static const MemoryRegionOps openpic_msi_ops_be = {
     },
 };
 
-static void openpic_save_IRQ_queue(QEMUFile* f, IRQ_queue_t *q)
+static void openpic_save_IRQ_queue(QEMUFile* f, IRQQueue *q)
 {
     unsigned int i;
 
@@ -1102,7 +1111,7 @@ static void openpic_save(QEMUFile* f, void *opaque)
     }
 }
 
-static void openpic_load_IRQ_queue(QEMUFile* f, IRQ_queue_t *q)
+static void openpic_load_IRQ_queue(QEMUFile* f, IRQQueue *q)
 {
     unsigned int i;
 
@@ -1118,8 +1127,9 @@ static int openpic_load(QEMUFile* f, void *opaque, int version_id)
     OpenPICState *opp = (OpenPICState *)opaque;
     unsigned int i;
 
-    if (version_id != 1)
+    if (version_id != 1) {
         return -EINVAL;
+    }
 
     qemu_get_be32s(f, &opp->glbc);
     qemu_get_be32s(f, &opp->veni);
@@ -1150,7 +1160,7 @@ static int openpic_load(QEMUFile* f, void *opaque, int version_id)
     return 0;
 }
 
-static void openpic_irq_raise(OpenPICState *opp, int n_CPU, IRQ_src_t *src)
+static void openpic_irq_raise(OpenPICState *opp, int n_CPU, IRQSource *src)
 {
     int n_ci = IDR_CI0_SHIFT - n_CPU;
 
@@ -1161,19 +1171,19 @@ static void openpic_irq_raise(OpenPICState *opp, int n_CPU, IRQ_src_t *src)
     }
 }
 
-struct memreg {
+typedef struct MemReg {
     const char             *name;
     MemoryRegionOps const  *ops;
     bool                   map;
     hwaddr      start_addr;
     ram_addr_t              size;
-};
+} MemReg;
 
 static int openpic_init(SysBusDevice *dev)
 {
     OpenPICState *opp = FROM_SYSBUS(typeof (*opp), dev);
     int i, j;
-    struct memreg list_le[] = {
+    MemReg list_le[] = {
         {"glb", &openpic_glb_ops_le, true,
                 OPENPIC_GLB_REG_START, OPENPIC_GLB_REG_SIZE},
         {"tmr", &openpic_tmr_ops_le, true,
@@ -1185,7 +1195,7 @@ static int openpic_init(SysBusDevice *dev)
         {"cpu", &openpic_cpu_ops_le, true,
                 OPENPIC_CPU_REG_START, OPENPIC_CPU_REG_SIZE},
     };
-    struct memreg list_be[] = {
+    MemReg list_be[] = {
         {"glb", &openpic_glb_ops_be, true,
                 OPENPIC_GLB_REG_START, OPENPIC_GLB_REG_SIZE},
         {"tmr", &openpic_tmr_ops_be, true,
@@ -1197,7 +1207,7 @@ static int openpic_init(SysBusDevice *dev)
         {"cpu", &openpic_cpu_ops_be, true,
                 OPENPIC_CPU_REG_START, OPENPIC_CPU_REG_SIZE},
     };
-    struct memreg *list;
+    MemReg *list;
 
     switch (opp->model) {
     case OPENPIC_MODEL_FSL_MPIC_20:
Signature · 1 line
1.6.0.2
#9 lore raw

PATCH 9/31 PPC: Reset qemu timers when guest reset

In reply to Alexander Graf

From: Bharat Bhushan <[email protected]>

This patch install the timer reset handler. This will be called when the guest is reset.

[agraf: adjust for QOM'ification]
---
 hw/ppc_booke.c |   13 +++++++++++++
 1 files changed, 13 insertions(+), 0 deletions(-)
hw/ppc_booke.c +13 -0
index 4483b8d..25a4e91 100644
@@ -237,6 +237,17 @@ void store_booke_tcr(CPUPPCState *env, target_ulong val)
 
 }
 
+static void ppc_booke_timer_reset_handle(void *opaque)
+{
+    PowerPCCPU *cpu = opaque;
+    CPUPPCState *env = &cpu->env;
+
+    env->spr[SPR_BOOKE_TSR] = 0;
+    env->spr[SPR_BOOKE_TCR] = 0;
+
+    booke_update_irq(cpu);
+}
+
 void ppc_booke_timers_init(PowerPCCPU *cpu, uint32_t freq, uint32_t flags)
 {
     ppc_tb_t *tb_env;
@@ -257,4 +268,6 @@ void ppc_booke_timers_init(PowerPCCPU *cpu, uint32_t freq, uint32_t flags)
         qemu_new_timer_ns(vm_clock, &booke_fit_cb, cpu);
     booke_timer->wdt_timer =
         qemu_new_timer_ns(vm_clock, &booke_wdt_cb, cpu);
+
+    qemu_register_reset(ppc_booke_timer_reset_handle, cpu);
 }
Signature · 1 line
1.6.0.2
#10 lore raw

PATCH 10/31 PPC: fix segfault in signal handling code

In reply to Alexander Graf

From: Samuel Seay <[email protected]>

Removed h2g() macro around the ka->_sa_handler due to the _sa_handler being a guest memory address.

Changed the __put_user to put_user as it was attempting to put a value at the stack address but the new address is a guest memory address, __put_user is for host memory addresses.

[agraf: change subject line, reformat commit message]
---
 linux-user/signal.c |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)
linux-user/signal.c +2 -2
index 95e2ffa..c43b8ac 100644
@@ -4584,7 +4584,7 @@ static void setup_frame(int sig, struct target_sigaction *ka,
 
     signal = current_exec_domain_sig(sig);
 
-    err |= __put_user(h2g(ka->_sa_handler), &sc->handler);
+    err |= __put_user(ka->_sa_handler, &sc->handler);
     err |= __put_user(set->sig[0], &sc->oldmask);
 #if defined(TARGET_PPC64)
     err |= __put_user(set->sig[0] >> 32, &sc->_unused[3]);
@@ -4606,7 +4606,7 @@ static void setup_frame(int sig, struct target_sigaction *ka,
 
     /* Create a stack frame for the caller of the handler.  */
     newsp = frame_addr - SIGNAL_FRAMESIZE;
-    err |= __put_user(env->gpr[1], (target_ulong *)(uintptr_t) newsp);
+    err |= put_user(env->gpr[1], newsp, target_ulong);
 
     if (err)
         goto sigsegv;
Signature · 1 line
1.6.0.2
#11 lore raw

PATCH 11/31 openpic: fix debug prints

In reply to Alexander Graf

From: Scott Wood <[email protected]>

Fix various format errors when debug prints are enabled. Also cause error checking to happen even when debug prints are not enabled, and consistently use 0x for hex output.

[agraf: adjust for more recent code base, prettify DPRINTF macro]
---
 hw/openpic.c |   44 +++++++++++++++++++++++++++-----------------
 1 files changed, 27 insertions(+), 17 deletions(-)
hw/openpic.c +27 -17
index 55e96d1..9243e70 100644
@@ -43,11 +43,17 @@
 //#define DEBUG_OPENPIC
 
 #ifdef DEBUG_OPENPIC
-#define DPRINTF(fmt, ...) do { printf(fmt , ## __VA_ARGS__); } while (0)
+static const int debug_openpic = 1;
 #else
-#define DPRINTF(fmt, ...) do { } while (0)
+static const int debug_openpic = 0;
 #endif
 
+#define DPRINTF(fmt, ...) do { \
+        if (debug_openpic) { \
+            printf(fmt , ## __VA_ARGS__); \
+        } \
+    } while (0)
+
 #define MAX_CPU     15
 #define MAX_SRC     256
 #define MAX_TMR     4
@@ -422,7 +428,7 @@ static void openpic_set_irq(void *opaque, int n_IRQ, int level)
     IRQSource *src;
 
     src = &opp->src[n_IRQ];
-    DPRINTF("openpic: set irq %d = %d ipvp=%08x\n",
+    DPRINTF("openpic: set irq %d = %d ipvp=0x%08x\n",
             n_IRQ, level, src->ipvp);
     if (src->ipvp & IPVP_SENSE_MASK) {
         /* level-sensitive irq */
@@ -513,7 +519,8 @@ static void openpic_gbl_write(void *opaque, hwaddr addr, uint64_t val,
     IRQDest *dst;
     int idx;
 
-    DPRINTF("%s: addr " TARGET_FMT_plx " <= %08x\n", __func__, addr, val);
+    DPRINTF("%s: addr %#" HWADDR_PRIx " <= %08" PRIx64 "\n",
+            __func__, addr, val);
     if (addr & 0xF) {
         return;
     }
@@ -576,7 +583,7 @@ static uint64_t openpic_gbl_read(void *opaque, hwaddr addr, unsigned len)
     OpenPICState *opp = opaque;
     uint32_t retval;
 
-    DPRINTF("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
+    DPRINTF("%s: addr %#" HWADDR_PRIx "\n", __func__, addr);
     retval = 0xFFFFFFFF;
     if (addr & 0xF) {
         return retval;
@@ -623,7 +630,7 @@ static uint64_t openpic_gbl_read(void *opaque, hwaddr addr, unsigned len)
     default:
         break;
     }
-    DPRINTF("%s: => %08x\n", __func__, retval);
+    DPRINTF("%s: => 0x%08x\n", __func__, retval);
 
     return retval;
 }
@@ -634,7 +641,8 @@ static void openpic_tmr_write(void *opaque, hwaddr addr, uint64_t val,
     OpenPICState *opp = opaque;
     int idx;
 
-    DPRINTF("%s: addr %08x <= %08x\n", __func__, addr, val);
+    DPRINTF("%s: addr %#" HWADDR_PRIx " <= %08" PRIx64 "\n",
+            __func__, addr, val);
     if (addr & 0xF) {
         return;
     }
@@ -672,7 +680,7 @@ static uint64_t openpic_tmr_read(void *opaque, hwaddr addr, unsigned len)
     uint32_t retval = -1;
     int idx;
 
-    DPRINTF("%s: addr %08x\n", __func__, addr);
+    DPRINTF("%s: addr %#" HWADDR_PRIx "\n", __func__, addr);
     if (addr & 0xF) {
         goto out;
     }
@@ -698,7 +706,7 @@ static uint64_t openpic_tmr_read(void *opaque, hwaddr addr, unsigned len)
     }
 
 out:
-    DPRINTF("%s: => %08x\n", __func__, retval);
+    DPRINTF("%s: => 0x%08x\n", __func__, retval);
 
     return retval;
 }
@@ -709,7 +717,8 @@ static void openpic_src_write(void *opaque, hwaddr addr, uint64_t val,
     OpenPICState *opp = opaque;
     int idx;
 
-    DPRINTF("%s: addr %08x <= %08x\n", __func__, addr, val);
+    DPRINTF("%s: addr %#" HWADDR_PRIx " <= %08" PRIx64 "\n",
+            __func__, addr, val);
     if (addr & 0xF) {
         return;
     }
@@ -730,7 +739,7 @@ static uint64_t openpic_src_read(void *opaque, uint64_t addr, unsigned len)
     uint32_t retval;
     int idx;
 
-    DPRINTF("%s: addr %08x\n", __func__, addr);
+    DPRINTF("%s: addr %#" HWADDR_PRIx "\n", __func__, addr);
     retval = 0xFFFFFFFF;
     if (addr & 0xF) {
         return retval;
@@ -744,7 +753,7 @@ static uint64_t openpic_src_read(void *opaque, uint64_t addr, unsigned len)
         /* EXVP / IFEVP / IEEVP */
         retval = read_IRQreg_ipvp(opp, idx);
     }
-    DPRINTF("%s: => %08x\n", __func__, retval);
+    DPRINTF("%s: => 0x%08x\n", __func__, retval);
 
     return retval;
 }
@@ -756,7 +765,8 @@ static void openpic_msi_write(void *opaque, hwaddr addr, uint64_t val,
     int idx = opp->irq_msi;
     int srs, ibs;
 
-    DPRINTF("%s: addr " TARGET_FMT_plx " <= %08x\n", __func__, addr, val);
+    DPRINTF("%s: addr %#" HWADDR_PRIx " <= 0x%08" PRIx64 "\n",
+            __func__, addr, val);
     if (addr & 0xF) {
         return;
     }
@@ -781,7 +791,7 @@ static uint64_t openpic_msi_read(void *opaque, hwaddr addr, unsigned size)
     uint64_t r = 0;
     int i, srs;
 
-    DPRINTF("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
+    DPRINTF("%s: addr %#" HWADDR_PRIx "\n", __func__, addr);
     if (addr & 0xF) {
         return -1;
     }
@@ -819,7 +829,7 @@ static void openpic_cpu_write_internal(void *opaque, hwaddr addr,
     IRQDest *dst;
     int s_IRQ, n_IRQ;
 
-    DPRINTF("%s: cpu %d addr " TARGET_FMT_plx " <= %08x\n", __func__, idx,
+    DPRINTF("%s: cpu %d addr %#" HWADDR_PRIx " <= 0x%08x\n", __func__, idx,
             addr, val);
 
     if (idx < 0) {
@@ -890,7 +900,7 @@ static uint32_t openpic_cpu_read_internal(void *opaque, hwaddr addr,
     uint32_t retval;
     int n_IRQ;
 
-    DPRINTF("%s: cpu %d addr " TARGET_FMT_plx "\n", __func__, idx, addr);
+    DPRINTF("%s: cpu %d addr %#" HWADDR_PRIx "\n", __func__, idx, addr);
     retval = 0xFFFFFFFF;
 
     if (idx < 0) {
@@ -958,7 +968,7 @@ static uint32_t openpic_cpu_read_internal(void *opaque, hwaddr addr,
     default:
         break;
     }
-    DPRINTF("%s: => %08x\n", __func__, retval);
+    DPRINTF("%s: => 0x%08x\n", __func__, retval);
 
     return retval;
 }
Signature · 1 line
1.6.0.2
#12 lore raw

PATCH 12/31 openpic: lower interrupt when reading the MSI register

In reply to Alexander Graf

From: Scott Wood <[email protected]>

This will stop things from breaking once it's properly treated as a level-triggered interrupt. Note that it's the MPIC's MSI cascade interrupts that are level-triggered; the individual MSIs are edge-triggered.

---
 hw/openpic.c |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)
hw/openpic.c +1 -0
index 9243e70..f4df66d 100644
@@ -810,6 +810,7 @@ static uint64_t openpic_msi_read(void *opaque, hwaddr addr, unsigned size)
         r = opp->msi[srs].msir;
         /* Clear on read */
         opp->msi[srs].msir = 0;
+        openpic_set_irq(opp, opp->irq_msi + srs, 0);
         break;
     case 0x120: /* MSISR */
         for (i = 0; i < MAX_MSI; i++) {
Signature · 1 line
1.6.0.2
#13 lore raw

PATCH 13/31 ppc/booke: fix crit/mcheck/debug exceptions

In reply to Alexander Graf

From: Scott Wood <[email protected]>

Book E does not play games with certain bits of xSRR1 being MSR save bits and others being error status. xSRR1 is the old MSR, period. This was causing things like MSR[CE] to be lost, even in the saved version, as soon as you take an exception.

rfci/rfdi/rfmci are fixed to pass the actual xSRR1 register contents, rather than the register number.

Put FIXME comments on the hack that is "asrr0/1". The whole point of separate exception levels is so that you can, for example, take a machine check or debug interrupt without corrupting critical-level operations. The right xSRR0/1 set needs to be chosen based on CPU type flags.

---
 target-ppc/excp_helper.c |   31 ++++++++++++++++++++++---------
 1 files changed, 22 insertions(+), 9 deletions(-)
target-ppc/excp_helper.c +22 -9
index 5e34ad0..41037a7 100644
@@ -84,7 +84,11 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp)
                   " => %08x (%02x)\n", env->nip, excp, env->error_code);
 
     /* new srr1 value excluding must-be-zero bits */
-    msr = env->msr & ~0x783f0000ULL;
+    if (excp_model == POWERPC_EXCP_BOOKE) {
+        msr = env->msr;
+    } else {
+        msr = env->msr & ~0x783f0000ULL;
+    }
 
     /* new interrupt handler msr */
     new_msr = env->msr & ((target_ulong)1 << MSR_ME);
@@ -145,6 +149,7 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp)
             srr1 = SPR_40x_SRR3;
             break;
         case POWERPC_EXCP_BOOKE:
+            /* FIXME: choose one or the other based on CPU type */
             srr0 = SPR_BOOKE_MCSRR0;
             srr1 = SPR_BOOKE_MCSRR1;
             asrr0 = SPR_BOOKE_CSRR0;
@@ -275,6 +280,7 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp)
     case POWERPC_EXCP_DEBUG:     /* Debug interrupt                          */
         switch (excp_model) {
         case POWERPC_EXCP_BOOKE:
+            /* FIXME: choose one or the other based on CPU type */
             srr0 = SPR_BOOKE_DSRR0;
             srr1 = SPR_BOOKE_DSRR1;
             asrr0 = SPR_BOOKE_CSRR0;
@@ -836,8 +842,13 @@ static inline void do_rfi(CPUPPCState *env, target_ulong nip, target_ulong msr,
 
 void helper_rfi(CPUPPCState *env)
 {
-    do_rfi(env, env->spr[SPR_SRR0], env->spr[SPR_SRR1],
-           ~((target_ulong)0x783F0000), 1);
+    if (env->excp_model == POWERPC_EXCP_BOOKE) {
+        do_rfi(env, env->spr[SPR_SRR0], env->spr[SPR_SRR1],
+               ~((target_ulong)0), 0);
+    } else {
+        do_rfi(env, env->spr[SPR_SRR0], env->spr[SPR_SRR1],
+               ~((target_ulong)0x783F0000), 1);
+    }
 }
 
 #if defined(TARGET_PPC64)
@@ -864,20 +875,22 @@ void helper_40x_rfci(CPUPPCState *env)
 
 void helper_rfci(CPUPPCState *env)
 {
-    do_rfi(env, env->spr[SPR_BOOKE_CSRR0], SPR_BOOKE_CSRR1,
-           ~((target_ulong)0x3FFF0000), 0);
+    do_rfi(env, env->spr[SPR_BOOKE_CSRR0], env->spr[SPR_BOOKE_CSRR1],
+           ~((target_ulong)0), 0);
 }
 
 void helper_rfdi(CPUPPCState *env)
 {
-    do_rfi(env, env->spr[SPR_BOOKE_DSRR0], SPR_BOOKE_DSRR1,
-           ~((target_ulong)0x3FFF0000), 0);
+    /* FIXME: choose CSRR1 or DSRR1 based on cpu type */
+    do_rfi(env, env->spr[SPR_BOOKE_DSRR0], env->spr[SPR_BOOKE_DSRR1],
+           ~((target_ulong)0), 0);
 }
 
 void helper_rfmci(CPUPPCState *env)
 {
-    do_rfi(env, env->spr[SPR_BOOKE_MCSRR0], SPR_BOOKE_MCSRR1,
-           ~((target_ulong)0x3FFF0000), 0);
+    /* FIXME: choose CSRR1 or MCSRR1 based on cpu type */
+    do_rfi(env, env->spr[SPR_BOOKE_MCSRR0], env->spr[SPR_BOOKE_MCSRR1],
+           ~((target_ulong)0), 0);
 }
 #endif
 
Signature · 1 line
1.6.0.2
#14 lore raw

PATCH 14/31 openpic: make register names correspond better with hw docs

In reply to Alexander Graf

From: Scott Wood <[email protected]>

The base openpic specification doesn't provide abbreviated register names, so it's somewhat understandable that the QEMU code made up its own, except that most of the names that QEMU used didn't correspond to the terminology used by any implementation I could find.

In some cases, like PCTP, the phrase "processor current task priority" could be found in the openpic spec when describing the concept, but the register itself was labelled "current task priority register" and every implementation seems to use either CTPR or the full phrase.

In other cases, individual implementations disagree on what to call the register. The implementations I have documentation for are Freescale, Raven (MCP750), and IBM. The Raven docs tend to not use abbreviations at all. The IBM MPIC isn't implemented in QEMU. Thus, where there's disagreement I chose to use the Freescale abbreviations.

[agraf: rebase on current state of the code]
---
 hw/openpic.c |  356 +++++++++++++++++++++++++++++-----------------------------
 1 files changed, 178 insertions(+), 178 deletions(-)
hw/openpic.c +178 -178
index f4df66d..6362497 100644
@@ -63,7 +63,7 @@ static const int debug_openpic = 0;
 #define VID         0x03 /* MPIC version ID */
 
 /* OpenPIC capability flags */
-#define OPENPIC_FLAG_IDE_CRIT     (1 << 0)
+#define OPENPIC_FLAG_IDR_CRIT     (1 << 0)
 
 /* OpenPIC address map */
 #define OPENPIC_GLB_REG_START        0x0
@@ -120,19 +120,19 @@ static const int debug_openpic = 0;
 #define FSL_BRR1_IPMJ (0x00 << 8) /* 8 bit IP major number */
 #define FSL_BRR1_IPMN 0x00 /* 8 bit IP minor number */
 
-#define FREP_NIRQ_SHIFT   16
-#define FREP_NCPU_SHIFT    8
-#define FREP_VID_SHIFT     0
+#define FRR_NIRQ_SHIFT    16
+#define FRR_NCPU_SHIFT     8
+#define FRR_VID_SHIFT      0
 
 #define VID_REVISION_1_2   2
 #define VID_REVISION_1_3   3
 
-#define VENI_GENERIC      0x00000000 /* Generic Vendor ID */
+#define VIR_GENERIC      0x00000000 /* Generic Vendor ID */
 
-#define GLBC_RESET        0x80000000
+#define GCR_RESET        0x80000000
 
-#define TIBC_CI           0x80000000 /* count inhibit */
-#define TICC_TOG          0x80000000 /* toggles when decrement to zero */
+#define TBCR_CI           0x80000000 /* count inhibit */
+#define TCCR_TOG          0x80000000 /* toggles when decrement to zero */
 
 #define IDR_EP_SHIFT      31
 #define IDR_EP_MASK       (1 << IDR_EP_SHIFT)
@@ -187,33 +187,33 @@ typedef struct IRQQueue {
 } IRQQueue;
 
 typedef struct IRQSource {
-    uint32_t ipvp;  /* IRQ vector/priority register */
-    uint32_t ide;   /* IRQ destination register */
+    uint32_t ivpr;  /* IRQ vector/priority register */
+    uint32_t idr;   /* IRQ destination register */
     int last_cpu;
     int pending;    /* TRUE if IRQ is pending */
 } IRQSource;
 
-#define IPVP_MASK_SHIFT       31
-#define IPVP_MASK_MASK        (1 << IPVP_MASK_SHIFT)
-#define IPVP_ACTIVITY_SHIFT   30
-#define IPVP_ACTIVITY_MASK    (1 << IPVP_ACTIVITY_SHIFT)
-#define IPVP_MODE_SHIFT       29
-#define IPVP_MODE_MASK        (1 << IPVP_MODE_SHIFT)
-#define IPVP_POLARITY_SHIFT   23
-#define IPVP_POLARITY_MASK    (1 << IPVP_POLARITY_SHIFT)
-#define IPVP_SENSE_SHIFT      22
-#define IPVP_SENSE_MASK       (1 << IPVP_SENSE_SHIFT)
-
-#define IPVP_PRIORITY_MASK     (0xF << 16)
-#define IPVP_PRIORITY(_ipvpr_) ((int)(((_ipvpr_) & IPVP_PRIORITY_MASK) >> 16))
-#define IPVP_VECTOR(opp, _ipvpr_) ((_ipvpr_) & (opp)->vector_mask)
-
-/* IDE[EP/CI] are only for FSL MPIC prior to v4.0 */
-#define IDE_EP      0x80000000  /* external pin */
-#define IDE_CI      0x40000000  /* critical interrupt */
+#define IVPR_MASK_SHIFT       31
+#define IVPR_MASK_MASK        (1 << IVPR_MASK_SHIFT)
+#define IVPR_ACTIVITY_SHIFT   30
+#define IVPR_ACTIVITY_MASK    (1 << IVPR_ACTIVITY_SHIFT)
+#define IVPR_MODE_SHIFT       29
+#define IVPR_MODE_MASK        (1 << IVPR_MODE_SHIFT)
+#define IVPR_POLARITY_SHIFT   23
+#define IVPR_POLARITY_MASK    (1 << IVPR_POLARITY_SHIFT)
+#define IVPR_SENSE_SHIFT      22
+#define IVPR_SENSE_MASK       (1 << IVPR_SENSE_SHIFT)
+
+#define IVPR_PRIORITY_MASK     (0xF << 16)
+#define IVPR_PRIORITY(_ivprr_) ((int)(((_ivprr_) & IVPR_PRIORITY_MASK) >> 16))
+#define IVPR_VECTOR(opp, _ivprr_) ((_ivprr_) & (opp)->vector_mask)
+
+/* IDR[EP/CI] are only for FSL MPIC prior to v4.0 */
+#define IDR_EP      0x80000000  /* external pin */
+#define IDR_CI      0x40000000  /* critical interrupt */
 
 typedef struct IRQDest {
-    uint32_t pctp; /* CPU current task priority */
+    uint32_t ctpr; /* CPU current task priority */
     IRQQueue raised;
     IRQQueue servicing;
     qemu_irq *irqs;
@@ -228,22 +228,22 @@ typedef struct OpenPICState {
     uint32_t flags;
     uint32_t nb_irqs;
     uint32_t vid;
-    uint32_t veni; /* Vendor identification register */
+    uint32_t vir; /* Vendor identification register */
     uint32_t vector_mask;
-    uint32_t tifr_reset;
-    uint32_t ipvp_reset;
-    uint32_t ide_reset;
+    uint32_t tfrr_reset;
+    uint32_t ivpr_reset;
+    uint32_t idr_reset;
     uint32_t brr1;
 
     /* Sub-regions */
     MemoryRegion sub_io_mem[5];
 
     /* Global registers */
-    uint32_t frep; /* Feature reporting register */
-    uint32_t glbc; /* Global configuration register  */
-    uint32_t pint; /* Processor initialization register */
+    uint32_t frr; /* Feature reporting register */
+    uint32_t gcr; /* Global configuration register  */
+    uint32_t pir; /* Processor initialization register */
     uint32_t spve; /* Spurious vector register */
-    uint32_t tifr; /* Timer frequency reporting register */
+    uint32_t tfrr; /* Timer frequency reporting register */
     /* Source registers */
     IRQSource src[MAX_IRQ];
     /* Local registers per output pin */
@@ -251,8 +251,8 @@ typedef struct OpenPICState {
     uint32_t nb_cpus;
     /* Timer registers */
     struct {
-        uint32_t ticc;  /* Global timer current count register */
-        uint32_t tibc;  /* Global timer base count register */
+        uint32_t tccr;  /* Global timer current count register */
+        uint32_t tbcr;  /* Global timer base count register */
     } timers[MAX_TMR];
     /* Shared MSI registers */
     struct {
@@ -298,11 +298,11 @@ static void IRQ_check(OpenPICState *opp, IRQQueue *q)
 
     for (i = 0; i < opp->max_irq; i++) {
         if (IRQ_testbit(q, i)) {
-            DPRINTF("IRQ_check: irq %d set ipvp_pr=%d pr=%d\n",
-                    i, IPVP_PRIORITY(opp->src[i].ipvp), priority);
-            if (IPVP_PRIORITY(opp->src[i].ipvp) > priority) {
+            DPRINTF("IRQ_check: irq %d set ivpr_pr=%d pr=%d\n",
+                    i, IVPR_PRIORITY(opp->src[i].ivpr), priority);
+            if (IVPR_PRIORITY(opp->src[i].ivpr) > priority) {
                 next = i;
-                priority = IPVP_PRIORITY(opp->src[i].ipvp);
+                priority = IVPR_PRIORITY(opp->src[i].ivpr);
             }
         }
     }
@@ -330,8 +330,8 @@ static void IRQ_local_pipe(OpenPICState *opp, int n_CPU, int n_IRQ)
 
     dst = &opp->dst[n_CPU];
     src = &opp->src[n_IRQ];
-    priority = IPVP_PRIORITY(src->ipvp);
-    if (priority <= dst->pctp) {
+    priority = IVPR_PRIORITY(src->ivpr);
+    if (priority <= dst->ctpr) {
         /* Too low priority */
         DPRINTF("%s: IRQ %d has too low priority on CPU %d\n",
                 __func__, n_IRQ, n_CPU);
@@ -343,7 +343,7 @@ static void IRQ_local_pipe(OpenPICState *opp, int n_CPU, int n_IRQ)
                 __func__, n_IRQ, n_CPU);
         return;
     }
-    src->ipvp |= IPVP_ACTIVITY_MASK;
+    src->ivpr |= IVPR_ACTIVITY_MASK;
     IRQ_setbit(&dst->raised, n_IRQ);
     if (priority < dst->raised.priority) {
         /* An higher priority IRQ is already raised */
@@ -376,34 +376,34 @@ static void openpic_update_irq(OpenPICState *opp, int n_IRQ)
         DPRINTF("%s: IRQ %d is not pending\n", __func__, n_IRQ);
         return;
     }
-    if (src->ipvp & IPVP_MASK_MASK) {
+    if (src->ivpr & IVPR_MASK_MASK) {
         /* Interrupt source is disabled */
         DPRINTF("%s: IRQ %d is disabled\n", __func__, n_IRQ);
         return;
     }
-    if (IPVP_PRIORITY(src->ipvp) == 0) {
+    if (IVPR_PRIORITY(src->ivpr) == 0) {
         /* Priority set to zero */
         DPRINTF("%s: IRQ %d has 0 priority\n", __func__, n_IRQ);
         return;
     }
-    if (src->ipvp & IPVP_ACTIVITY_MASK) {
+    if (src->ivpr & IVPR_ACTIVITY_MASK) {
         /* IRQ already active */
         DPRINTF("%s: IRQ %d is already active\n", __func__, n_IRQ);
         return;
     }
-    if (src->ide == 0) {
+    if (src->idr == 0) {
         /* No target */
         DPRINTF("%s: IRQ %d has no target\n", __func__, n_IRQ);
         return;
     }
 
-    if (src->ide == (1 << src->last_cpu)) {
+    if (src->idr == (1 << src->last_cpu)) {
         /* Only one CPU is allowed to receive this IRQ */
         IRQ_local_pipe(opp, src->last_cpu, n_IRQ);
-    } else if (!(src->ipvp & IPVP_MODE_MASK)) {
+    } else if (!(src->ivpr & IVPR_MODE_MASK)) {
         /* Directed delivery mode */
         for (i = 0; i < opp->nb_cpus; i++) {
-            if (src->ide & (1 << i)) {
+            if (src->idr & (1 << i)) {
                 IRQ_local_pipe(opp, i, n_IRQ);
             }
         }
@@ -413,7 +413,7 @@ static void openpic_update_irq(OpenPICState *opp, int n_IRQ)
             if (i == opp->nb_cpus) {
                 i = 0;
             }
-            if (src->ide & (1 << i)) {
+            if (src->idr & (1 << i)) {
                 IRQ_local_pipe(opp, i, n_IRQ);
                 src->last_cpu = i;
                 break;
@@ -428,13 +428,13 @@ static void openpic_set_irq(void *opaque, int n_IRQ, int level)
     IRQSource *src;
 
     src = &opp->src[n_IRQ];
-    DPRINTF("openpic: set irq %d = %d ipvp=0x%08x\n",
-            n_IRQ, level, src->ipvp);
-    if (src->ipvp & IPVP_SENSE_MASK) {
+    DPRINTF("openpic: set irq %d = %d ivpr=0x%08x\n",
+            n_IRQ, level, src->ivpr);
+    if (src->ivpr & IVPR_SENSE_MASK) {
         /* level-sensitive irq */
         src->pending = level;
         if (!level) {
-            src->ipvp &= ~IPVP_ACTIVITY_MASK;
+            src->ivpr &= ~IVPR_ACTIVITY_MASK;
         }
     } else {
         /* edge-sensitive irq */
@@ -450,23 +450,23 @@ static void openpic_reset(DeviceState *d)
     OpenPICState *opp = FROM_SYSBUS(typeof (*opp), sysbus_from_qdev(d));
     int i;
 
-    opp->glbc = GLBC_RESET;
+    opp->gcr = GCR_RESET;
     /* Initialise controller registers */
-    opp->frep = ((opp->nb_irqs - 1) << FREP_NIRQ_SHIFT) |
-                ((opp->nb_cpus - 1) << FREP_NCPU_SHIFT) |
-                (opp->vid << FREP_VID_SHIFT);
+    opp->frr = ((opp->nb_irqs - 1) << FRR_NIRQ_SHIFT) |
+               ((opp->nb_cpus - 1) << FRR_NCPU_SHIFT) |
+               (opp->vid << FRR_VID_SHIFT);
 
-    opp->pint = 0;
+    opp->pir = 0;
     opp->spve = -1 & opp->vector_mask;
-    opp->tifr = opp->tifr_reset;
+    opp->tfrr = opp->tfrr_reset;
     /* Initialise IRQ sources */
     for (i = 0; i < opp->max_irq; i++) {
-        opp->src[i].ipvp = opp->ipvp_reset;
-        opp->src[i].ide  = opp->ide_reset;
+        opp->src[i].ivpr = opp->ivpr_reset;
+        opp->src[i].idr  = opp->idr_reset;
     }
     /* Initialise IRQ destinations */
     for (i = 0; i < MAX_CPU; i++) {
-        opp->dst[i].pctp      = 15;
+        opp->dst[i].ctpr      = 15;
         memset(&opp->dst[i].raised, 0, sizeof(IRQQueue));
         opp->dst[i].raised.next = -1;
         memset(&opp->dst[i].servicing, 0, sizeof(IRQQueue));
@@ -474,42 +474,42 @@ static void openpic_reset(DeviceState *d)
     }
     /* Initialise timers */
     for (i = 0; i < MAX_TMR; i++) {
-        opp->timers[i].ticc = 0;
-        opp->timers[i].tibc = TIBC_CI;
+        opp->timers[i].tccr = 0;
+        opp->timers[i].tbcr = TBCR_CI;
     }
     /* Go out of RESET state */
-    opp->glbc = 0;
+    opp->gcr = 0;
 }
 
-static inline uint32_t read_IRQreg_ide(OpenPICState *opp, int n_IRQ)
+static inline uint32_t read_IRQreg_idr(OpenPICState *opp, int n_IRQ)
 {
-    return opp->src[n_IRQ].ide;
+    return opp->src[n_IRQ].idr;
 }
 
-static inline uint32_t read_IRQreg_ipvp(OpenPICState *opp, int n_IRQ)
+static inline uint32_t read_IRQreg_ivpr(OpenPICState *opp, int n_IRQ)
 {
-    return opp->src[n_IRQ].ipvp;
+    return opp->src[n_IRQ].ivpr;
 }
 
-static inline void write_IRQreg_ide(OpenPICState *opp, int n_IRQ, uint32_t val)
+static inline void write_IRQreg_idr(OpenPICState *opp, int n_IRQ, uint32_t val)
 {
     uint32_t tmp;
 
-    tmp = val & (IDE_EP | IDE_CI);
+    tmp = val & (IDR_EP | IDR_CI);
     tmp |= val & ((1ULL << MAX_CPU) - 1);
-    opp->src[n_IRQ].ide = tmp;
-    DPRINTF("Set IDE %d to 0x%08x\n", n_IRQ, opp->src[n_IRQ].ide);
+    opp->src[n_IRQ].idr = tmp;
+    DPRINTF("Set IDR %d to 0x%08x\n", n_IRQ, opp->src[n_IRQ].idr);
 }
 
-static inline void write_IRQreg_ipvp(OpenPICState *opp, int n_IRQ, uint32_t val)
+static inline void write_IRQreg_ivpr(OpenPICState *opp, int n_IRQ, uint32_t val)
 {
     /* NOTE: not fully accurate for special IRQs, but simple and sufficient */
     /* ACTIVITY bit is read-only */
-    opp->src[n_IRQ].ipvp = (opp->src[n_IRQ].ipvp & IPVP_ACTIVITY_MASK) |
-        (val & (IPVP_MASK_MASK | IPVP_PRIORITY_MASK | opp->vector_mask));
+    opp->src[n_IRQ].ivpr = (opp->src[n_IRQ].ivpr & IVPR_ACTIVITY_MASK) |
+        (val & (IVPR_MASK_MASK | IVPR_PRIORITY_MASK | opp->vector_mask));
     openpic_update_irq(opp, n_IRQ);
-    DPRINTF("Set IPVP %d to 0x%08x -> 0x%08x\n", n_IRQ, val,
-            opp->src[n_IRQ].ipvp);
+    DPRINTF("Set IVPR %d to 0x%08x -> 0x%08x\n", n_IRQ, val,
+            opp->src[n_IRQ].ivpr);
 }
 
 static void openpic_gbl_write(void *opaque, hwaddr addr, uint64_t val,
@@ -537,37 +537,37 @@ static void openpic_gbl_write(void *opaque, hwaddr addr, uint64_t val,
     case 0xB0:
         openpic_cpu_write_internal(opp, addr, val, get_current_cpu());
         break;
-    case 0x1000: /* FREP */
+    case 0x1000: /* FRR */
         break;
-    case 0x1020: /* GLBC */
-        if (val & GLBC_RESET) {
+    case 0x1020: /* GCR */
+        if (val & GCR_RESET) {
             openpic_reset(&opp->busdev.qdev);
         }
         break;
-    case 0x1080: /* VENI */
+    case 0x1080: /* VIR */
         break;
-    case 0x1090: /* PINT */
+    case 0x1090: /* PIR */
         for (idx = 0; idx < opp->nb_cpus; idx++) {
-            if ((val & (1 << idx)) && !(opp->pint & (1 << idx))) {
+            if ((val & (1 << idx)) && !(opp->pir & (1 << idx))) {
                 DPRINTF("Raise OpenPIC RESET output for CPU %d\n", idx);
                 dst = &opp->dst[idx];
                 qemu_irq_raise(dst->irqs[OPENPIC_OUTPUT_RESET]);
-            } else if (!(val & (1 << idx)) && (opp->pint & (1 << idx))) {
+            } else if (!(val & (1 << idx)) && (opp->pir & (1 << idx))) {
                 DPRINTF("Lower OpenPIC RESET output for CPU %d\n", idx);
                 dst = &opp->dst[idx];
                 qemu_irq_lower(dst->irqs[OPENPIC_OUTPUT_RESET]);
             }
         }
-        opp->pint = val;
+        opp->pir = val;
         break;
-    case 0x10A0: /* IPI_IPVP */
+    case 0x10A0: /* IPI_IVPR */
     case 0x10B0:
     case 0x10C0:
     case 0x10D0:
         {
             int idx;
             idx = (addr - 0x10A0) >> 4;
-            write_IRQreg_ipvp(opp, opp->irq_ipi0 + idx, val);
+            write_IRQreg_ivpr(opp, opp->irq_ipi0 + idx, val);
         }
         break;
     case 0x10E0: /* SPVE */
@@ -589,16 +589,16 @@ static uint64_t openpic_gbl_read(void *opaque, hwaddr addr, unsigned len)
         return retval;
     }
     switch (addr) {
-    case 0x1000: /* FREP */
-        retval = opp->frep;
+    case 0x1000: /* FRR */
+        retval = opp->frr;
         break;
-    case 0x1020: /* GLBC */
-        retval = opp->glbc;
+    case 0x1020: /* GCR */
+        retval = opp->gcr;
         break;
-    case 0x1080: /* VENI */
-        retval = opp->veni;
+    case 0x1080: /* VIR */
+        retval = opp->vir;
         break;
-    case 0x1090: /* PINT */
+    case 0x1090: /* PIR */
         retval = 0x00000000;
         break;
     case 0x00: /* Block Revision Register1 (BRR1) */
@@ -614,14 +614,14 @@ static uint64_t openpic_gbl_read(void *opaque, hwaddr addr, unsigned len)
     case 0xB0:
         retval = openpic_cpu_read_internal(opp, addr, get_current_cpu());
         break;
-    case 0x10A0: /* IPI_IPVP */
+    case 0x10A0: /* IPI_IVPR */
     case 0x10B0:
     case 0x10C0:
     case 0x10D0:
         {
             int idx;
             idx = (addr - 0x10A0) >> 4;
-            retval = read_IRQreg_ipvp(opp, opp->irq_ipi0 + idx);
+            retval = read_IRQreg_ivpr(opp, opp->irq_ipi0 + idx);
         }
         break;
     case 0x10E0: /* SPVE */
@@ -650,26 +650,26 @@ static void openpic_tmr_write(void *opaque, hwaddr addr, uint64_t val,
     addr = addr & 0x30;
 
     if (addr == 0x0) {
-        /* TIFR (TFRR) */
-        opp->tifr = val;
+        /* TFRR */
+        opp->tfrr = val;
         return;
     }
     switch (addr & 0x30) {
-    case 0x00: /* TICC (GTCCR) */
+    case 0x00: /* TCCR */
         break;
-    case 0x10: /* TIBC (GTBCR) */
-        if ((opp->timers[idx].ticc & TICC_TOG) != 0 &&
-            (val & TIBC_CI) == 0 &&
-            (opp->timers[idx].tibc & TIBC_CI) != 0) {
-            opp->timers[idx].ticc &= ~TICC_TOG;
+    case 0x10: /* TBCR */
+        if ((opp->timers[idx].tccr & TCCR_TOG) != 0 &&
+            (val & TBCR_CI) == 0 &&
+            (opp->timers[idx].tbcr & TBCR_CI) != 0) {
+            opp->timers[idx].tccr &= ~TCCR_TOG;
         }
-        opp->timers[idx].tibc = val;
+        opp->timers[idx].tbcr = val;
         break;
-    case 0x20: /* TIVP (GTIVPR) */
-        write_IRQreg_ipvp(opp, opp->irq_tim0 + idx, val);
+    case 0x20: /* TVPR */
+        write_IRQreg_ivpr(opp, opp->irq_tim0 + idx, val);
         break;
-    case 0x30: /* TIDE (GTIDR) */
-        write_IRQreg_ide(opp, opp->irq_tim0 + idx, val);
+    case 0x30: /* TDR */
+        write_IRQreg_idr(opp, opp->irq_tim0 + idx, val);
         break;
     }
 }
@@ -686,22 +686,22 @@ static uint64_t openpic_tmr_read(void *opaque, hwaddr addr, unsigned len)
     }
     idx = (addr >> 6) & 0x3;
     if (addr == 0x0) {
-        /* TIFR (TFRR) */
-        retval = opp->tifr;
+        /* TFRR */
+        retval = opp->tfrr;
         goto out;
     }
     switch (addr & 0x30) {
-    case 0x00: /* TICC (GTCCR) */
-        retval = opp->timers[idx].ticc;
+    case 0x00: /* TCCR */
+        retval = opp->timers[idx].tccr;
         break;
-    case 0x10: /* TIBC (GTBCR) */
-        retval = opp->timers[idx].tibc;
+    case 0x10: /* TBCR */
+        retval = opp->timers[idx].tbcr;
         break;
-    case 0x20: /* TIPV (TIPV) */
-        retval = read_IRQreg_ipvp(opp, opp->irq_tim0 + idx);
+    case 0x20: /* TIPV */
+        retval = read_IRQreg_ivpr(opp, opp->irq_tim0 + idx);
         break;
     case 0x30: /* TIDE (TIDR) */
-        retval = read_IRQreg_ide(opp, opp->irq_tim0 + idx);
+        retval = read_IRQreg_idr(opp, opp->irq_tim0 + idx);
         break;
     }
 
@@ -726,10 +726,10 @@ static void openpic_src_write(void *opaque, hwaddr addr, uint64_t val,
     idx = addr >> 5;
     if (addr & 0x10) {
         /* EXDE / IFEDE / IEEDE */
-        write_IRQreg_ide(opp, idx, val);
+        write_IRQreg_idr(opp, idx, val);
     } else {
         /* EXVP / IFEVP / IEEVP */
-        write_IRQreg_ipvp(opp, idx, val);
+        write_IRQreg_ivpr(opp, idx, val);
     }
 }
 
@@ -748,10 +748,10 @@ static uint64_t openpic_src_read(void *opaque, uint64_t addr, unsigned len)
     idx = addr >> 5;
     if (addr & 0x10) {
         /* EXDE / IFEDE / IEEDE */
-        retval = read_IRQreg_ide(opp, idx);
+        retval = read_IRQreg_idr(opp, idx);
     } else {
         /* EXVP / IFEVP / IEEVP */
-        retval = read_IRQreg_ipvp(opp, idx);
+        retval = read_IRQreg_ivpr(opp, idx);
     }
     DPRINTF("%s: => 0x%08x\n", __func__, retval);
 
@@ -849,22 +849,22 @@ static void openpic_cpu_write_internal(void *opaque, hwaddr addr,
     case 0x70:
         idx = (addr - 0x40) >> 4;
         /* we use IDE as mask which CPUs to deliver the IPI to still. */
-        write_IRQreg_ide(opp, opp->irq_ipi0 + idx,
-                         opp->src[opp->irq_ipi0 + idx].ide | val);
+        write_IRQreg_idr(opp, opp->irq_ipi0 + idx,
+                         opp->src[opp->irq_ipi0 + idx].idr | val);
         openpic_set_irq(opp, opp->irq_ipi0 + idx, 1);
         openpic_set_irq(opp, opp->irq_ipi0 + idx, 0);
         break;
-    case 0x80: /* PCTP */
-        dst->pctp = val & 0x0000000F;
+    case 0x80: /* CTPR */
+        dst->ctpr = val & 0x0000000F;
         break;
     case 0x90: /* WHOAMI */
         /* Read-only register */
         break;
-    case 0xA0: /* PIAC */
+    case 0xA0: /* IACK */
         /* Read-only register */
         break;
-    case 0xB0: /* PEOI */
-        DPRINTF("PEOI\n");
+    case 0xB0: /* EOI */
+        DPRINTF("EOI\n");
         s_IRQ = IRQ_get_next(opp, &dst->servicing);
         IRQ_resetbit(&dst->servicing, s_IRQ);
         dst->servicing.next = -1;
@@ -875,7 +875,7 @@ static void openpic_cpu_write_internal(void *opaque, hwaddr addr,
         src = &opp->src[n_IRQ];
         if (n_IRQ != -1 &&
             (s_IRQ == -1 ||
-             IPVP_PRIORITY(src->ipvp) > dst->servicing.priority)) {
+             IVPR_PRIORITY(src->ivpr) > dst->servicing.priority)) {
             DPRINTF("Raise OpenPIC INT output cpu %d irq %d\n",
                     idx, n_IRQ);
             openpic_irq_raise(opp, idx, src);
@@ -914,56 +914,56 @@ static uint32_t openpic_cpu_read_internal(void *opaque, hwaddr addr,
     dst = &opp->dst[idx];
     addr &= 0xFF0;
     switch (addr) {
-    case 0x80: /* PCTP */
-        retval = dst->pctp;
+    case 0x80: /* CTPR */
+        retval = dst->ctpr;
         break;
     case 0x90: /* WHOAMI */
         retval = idx;
         break;
-    case 0xA0: /* PIAC */
+    case 0xA0: /* IACK */
         DPRINTF("Lower OpenPIC INT output\n");
         qemu_irq_lower(dst->irqs[OPENPIC_OUTPUT_INT]);
         n_IRQ = IRQ_get_next(opp, &dst->raised);
-        DPRINTF("PIAC: irq=%d\n", n_IRQ);
+        DPRINTF("IACK: irq=%d\n", n_IRQ);
         if (n_IRQ == -1) {
             /* No more interrupt pending */
             retval = opp->spve;
         } else {
             src = &opp->src[n_IRQ];
-            if (!(src->ipvp & IPVP_ACTIVITY_MASK) ||
-                !(IPVP_PRIORITY(src->ipvp) > dst->pctp)) {
+            if (!(src->ivpr & IVPR_ACTIVITY_MASK) ||
+                !(IVPR_PRIORITY(src->ivpr) > dst->ctpr)) {
                 /* - Spurious level-sensitive IRQ
                  * - Priorities has been changed
                  *   and the pending IRQ isn't allowed anymore
                  */
-                src->ipvp &= ~IPVP_ACTIVITY_MASK;
+                src->ivpr &= ~IVPR_ACTIVITY_MASK;
                 retval = opp->spve;
             } else {
                 /* IRQ enter servicing state */
                 IRQ_setbit(&dst->servicing, n_IRQ);
-                retval = IPVP_VECTOR(opp, src->ipvp);
+                retval = IVPR_VECTOR(opp, src->ivpr);
             }
             IRQ_resetbit(&dst->raised, n_IRQ);
             dst->raised.next = -1;
-            if (!(src->ipvp & IPVP_SENSE_MASK)) {
+            if (!(src->ivpr & IVPR_SENSE_MASK)) {
                 /* edge-sensitive IRQ */
-                src->ipvp &= ~IPVP_ACTIVITY_MASK;
+                src->ivpr &= ~IVPR_ACTIVITY_MASK;
                 src->pending = 0;
             }
 
             if ((n_IRQ >= opp->irq_ipi0) &&  (n_IRQ < (opp->irq_ipi0 + MAX_IPI))) {
-                src->ide &= ~(1 << idx);
-                if (src->ide && !(src->ipvp & IPVP_SENSE_MASK)) {
+                src->idr &= ~(1 << idx);
+                if (src->idr && !(src->ivpr & IVPR_SENSE_MASK)) {
                     /* trigger on CPUs that didn't know about it yet */
                     openpic_set_irq(opp, n_IRQ, 1);
                     openpic_set_irq(opp, n_IRQ, 0);
                     /* if all CPUs knew about it, set active bit again */
-                    src->ipvp |= IPVP_ACTIVITY_MASK;
+                    src->ivpr |= IVPR_ACTIVITY_MASK;
                 }
             }
         }
         break;
-    case 0xB0: /* PEOI */
+    case 0xB0: /* EOI */
         retval = 0;
         break;
     default:
@@ -1095,15 +1095,15 @@ static void openpic_save(QEMUFile* f, void *opaque)
     OpenPICState *opp = (OpenPICState *)opaque;
     unsigned int i;
 
-    qemu_put_be32s(f, &opp->glbc);
-    qemu_put_be32s(f, &opp->veni);
-    qemu_put_be32s(f, &opp->pint);
+    qemu_put_be32s(f, &opp->gcr);
+    qemu_put_be32s(f, &opp->vir);
+    qemu_put_be32s(f, &opp->pir);
     qemu_put_be32s(f, &opp->spve);
-    qemu_put_be32s(f, &opp->tifr);
+    qemu_put_be32s(f, &opp->tfrr);
 
     for (i = 0; i < opp->max_irq; i++) {
-        qemu_put_be32s(f, &opp->src[i].ipvp);
-        qemu_put_be32s(f, &opp->src[i].ide);
+        qemu_put_be32s(f, &opp->src[i].ivpr);
+        qemu_put_be32s(f, &opp->src[i].idr);
         qemu_put_sbe32s(f, &opp->src[i].last_cpu);
         qemu_put_sbe32s(f, &opp->src[i].pending);
     }
@@ -1111,14 +1111,14 @@ static void openpic_save(QEMUFile* f, void *opaque)
     qemu_put_be32s(f, &opp->nb_cpus);
 
     for (i = 0; i < opp->nb_cpus; i++) {
-        qemu_put_be32s(f, &opp->dst[i].pctp);
+        qemu_put_be32s(f, &opp->dst[i].ctpr);
         openpic_save_IRQ_queue(f, &opp->dst[i].raised);
         openpic_save_IRQ_queue(f, &opp->dst[i].servicing);
     }
 
     for (i = 0; i < MAX_TMR; i++) {
-        qemu_put_be32s(f, &opp->timers[i].ticc);
-        qemu_put_be32s(f, &opp->timers[i].tibc);
+        qemu_put_be32s(f, &opp->timers[i].tccr);
+        qemu_put_be32s(f, &opp->timers[i].tbcr);
     }
 }
 
@@ -1142,15 +1142,15 @@ static int openpic_load(QEMUFile* f, void *opaque, int version_id)
         return -EINVAL;
     }
 
-    qemu_get_be32s(f, &opp->glbc);
-    qemu_get_be32s(f, &opp->veni);
-    qemu_get_be32s(f, &opp->pint);
+    qemu_get_be32s(f, &opp->gcr);
+    qemu_get_be32s(f, &opp->vir);
+    qemu_get_be32s(f, &opp->pir);
     qemu_get_be32s(f, &opp->spve);
-    qemu_get_be32s(f, &opp->tifr);
+    qemu_get_be32s(f, &opp->tfrr);
 
     for (i = 0; i < opp->max_irq; i++) {
-        qemu_get_be32s(f, &opp->src[i].ipvp);
-        qemu_get_be32s(f, &opp->src[i].ide);
+        qemu_get_be32s(f, &opp->src[i].ivpr);
+        qemu_get_be32s(f, &opp->src[i].idr);
         qemu_get_sbe32s(f, &opp->src[i].last_cpu);
         qemu_get_sbe32s(f, &opp->src[i].pending);
     }
@@ -1158,14 +1158,14 @@ static int openpic_load(QEMUFile* f, void *opaque, int version_id)
     qemu_get_be32s(f, &opp->nb_cpus);
 
     for (i = 0; i < opp->nb_cpus; i++) {
-        qemu_get_be32s(f, &opp->dst[i].pctp);
+        qemu_get_be32s(f, &opp->dst[i].ctpr);
         openpic_load_IRQ_queue(f, &opp->dst[i].raised);
         openpic_load_IRQ_queue(f, &opp->dst[i].servicing);
     }
 
     for (i = 0; i < MAX_TMR; i++) {
-        qemu_get_be32s(f, &opp->timers[i].ticc);
-        qemu_get_be32s(f, &opp->timers[i].tibc);
+        qemu_get_be32s(f, &opp->timers[i].tccr);
+        qemu_get_be32s(f, &opp->timers[i].tbcr);
     }
 
     return 0;
@@ -1175,7 +1175,7 @@ static void openpic_irq_raise(OpenPICState *opp, int n_CPU, IRQSource *src)
 {
     int n_ci = IDR_CI0_SHIFT - n_CPU;
 
-    if ((opp->flags & OPENPIC_FLAG_IDE_CRIT) && (src->ide & (1 << n_ci))) {
+    if ((opp->flags & OPENPIC_FLAG_IDR_CRIT) && (src->idr & (1 << n_ci))) {
         qemu_irq_raise(opp->dst[n_CPU].irqs[OPENPIC_OUTPUT_CINT]);
     } else {
         qemu_irq_raise(opp->dst[n_CPU].irqs[OPENPIC_OUTPUT_INT]);
@@ -1223,14 +1223,14 @@ static int openpic_init(SysBusDevice *dev)
     switch (opp->model) {
     case OPENPIC_MODEL_FSL_MPIC_20:
     default:
-        opp->flags |= OPENPIC_FLAG_IDE_CRIT;
+        opp->flags |= OPENPIC_FLAG_IDR_CRIT;
         opp->nb_irqs = 80;
         opp->vid = VID_REVISION_1_2;
-        opp->veni = VENI_GENERIC;
+        opp->vir = VIR_GENERIC;
         opp->vector_mask = 0xFFFF;
-        opp->tifr_reset = 0;
-        opp->ipvp_reset = IPVP_MASK_MASK;
-        opp->ide_reset = 1 << 0;
+        opp->tfrr_reset = 0;
+        opp->ivpr_reset = IVPR_MASK_MASK;
+        opp->idr_reset = 1 << 0;
         opp->max_irq = FSL_MPIC_20_MAX_IRQ;
         opp->irq_ipi0 = FSL_MPIC_20_IPI_IRQ;
         opp->irq_tim0 = FSL_MPIC_20_TMR_IRQ;
@@ -1242,11 +1242,11 @@ static int openpic_init(SysBusDevice *dev)
     case OPENPIC_MODEL_RAVEN:
         opp->nb_irqs = RAVEN_MAX_EXT;
         opp->vid = VID_REVISION_1_3;
-        opp->veni = VENI_GENERIC;
+        opp->vir = VIR_GENERIC;
         opp->vector_mask = 0xFF;
-        opp->tifr_reset = 4160000;
-        opp->ipvp_reset = IPVP_MASK_MASK | IPVP_MODE_MASK;
-        opp->ide_reset = 0;
+        opp->tfrr_reset = 4160000;
+        opp->ivpr_reset = IVPR_MASK_MASK | IVPR_MODE_MASK;
+        opp->idr_reset = 0;
         opp->max_irq = RAVEN_MAX_IRQ;
         opp->irq_ipi0 = RAVEN_IPI_IRQ;
         opp->irq_tim0 = RAVEN_TMR_IRQ;
Signature · 1 line
1.6.0.2
#15 lore raw

PATCH 15/31 openpic: rework critical interrupt support

In reply to Alexander Graf

From: Scott Wood <[email protected]>

Critical interrupts on FSL MPIC are not supposed to pay attention to priority, IACK, EOI, etc. On the currently modeled version it's not supposed to pay attention to the mask bit either.

Also reorganize to make it easier to implement newer FSL MPIC models, which encode interrupt level information differently and support mcheck as well as crit, and to reduce problems for later patches in this set.

Still missing is the ability to lower the CINT signal to the core, as IACK/EOI is not used. This will come with general IRQ-source-driven lowering in the next patch.

New state is added which is not serialized, but instead is recomputed in openpic_load() by calling the appropriate write_IRQreg function. This should have the side effect of causing the IRQ outputs to be raised appropriately on load, which was missing.

The serialization format is altered by swapping ivpr and idr (we'd like IDR to be restored before we run the IVPR logic), and moving interrupts to the end (so that other state has been restored by the time we run the IDR/IVPR logic. Serialization for this driver is not yet in a state where backwards compatibility is reasonable (assuming it works at all), and the current serialization format was not built for extensibility.

[agraf: fix for current code state]
---
 hw/openpic.c |  110 ++++++++++++++++++++++++++++++++++++++++------------------
 1 files changed, 76 insertions(+), 34 deletions(-)
hw/openpic.c +76 -34
index 6362497..fe6cf67 100644
@@ -189,7 +189,9 @@ typedef struct IRQQueue {
 typedef struct IRQSource {
     uint32_t ivpr;  /* IRQ vector/priority register */
     uint32_t idr;   /* IRQ destination register */
+    uint32_t destmask; /* bitmap of CPU destinations */
     int last_cpu;
+    int output;     /* IRQ level, e.g. OPENPIC_OUTPUT_INT */
     int pending;    /* TRUE if IRQ is pending */
 } IRQSource;
 
@@ -264,8 +266,6 @@ typedef struct OpenPICState {
     uint32_t irq_msi;
 } OpenPICState;
 
-static void openpic_irq_raise(OpenPICState *opp, int n_CPU, IRQSource *src);
-
 static inline void IRQ_setbit(IRQQueue *q, int n_IRQ)
 {
     q->pending++;
@@ -330,6 +330,19 @@ static void IRQ_local_pipe(OpenPICState *opp, int n_CPU, int n_IRQ)
 
     dst = &opp->dst[n_CPU];
     src = &opp->src[n_IRQ];
+
+    if (src->output != OPENPIC_OUTPUT_INT) {
+        /* On Freescale MPIC, critical interrupts ignore priority,
+         * IACK, EOI, etc.  Before MPIC v4.1 they also ignore
+         * masking.
+         */
+        src->ivpr |= IVPR_ACTIVITY_MASK;
+        DPRINTF("%s: Raise OpenPIC output %d cpu %d irq %d\n",
+                __func__, src->output, n_CPU, n_IRQ);
+        qemu_irq_raise(opp->dst[n_CPU].irqs[src->output]);
+        return;
+    }
+
     priority = IVPR_PRIORITY(src->ivpr);
     if (priority <= dst->ctpr) {
         /* Too low priority */
@@ -360,7 +373,7 @@ static void IRQ_local_pipe(OpenPICState *opp, int n_CPU, int n_IRQ)
         return;
     }
     DPRINTF("Raise OpenPIC INT output cpu %d irq %d\n", n_CPU, n_IRQ);
-    openpic_irq_raise(opp, n_CPU, src);
+    qemu_irq_raise(opp->dst[n_CPU].irqs[OPENPIC_OUTPUT_INT]);
 }
 
 /* update pic state because registers for n_IRQ have changed value */
@@ -403,7 +416,7 @@ static void openpic_update_irq(OpenPICState *opp, int n_IRQ)
     } else if (!(src->ivpr & IVPR_MODE_MASK)) {
         /* Directed delivery mode */
         for (i = 0; i < opp->nb_cpus; i++) {
-            if (src->idr & (1 << i)) {
+            if (src->destmask & (1 << i)) {
                 IRQ_local_pipe(opp, i, n_IRQ);
             }
         }
@@ -413,7 +426,7 @@ static void openpic_update_irq(OpenPICState *opp, int n_IRQ)
             if (i == opp->nb_cpus) {
                 i = 0;
             }
-            if (src->idr & (1 << i)) {
+            if (src->destmask & (1 << i)) {
                 IRQ_local_pipe(opp, i, n_IRQ);
                 src->last_cpu = i;
                 break;
@@ -493,12 +506,45 @@ static inline uint32_t read_IRQreg_ivpr(OpenPICState *opp, int n_IRQ)
 
 static inline void write_IRQreg_idr(OpenPICState *opp, int n_IRQ, uint32_t val)
 {
-    uint32_t tmp;
+    IRQSource *src = &opp->src[n_IRQ];
+    uint32_t normal_mask = (1UL << opp->nb_cpus) - 1;
+    uint32_t crit_mask = 0;
+    uint32_t mask = normal_mask;
+    int crit_shift = IDR_EP_SHIFT - opp->nb_cpus;
+    int i;
+
+    if (opp->flags & OPENPIC_FLAG_IDR_CRIT) {
+        crit_mask = mask << crit_shift;
+        mask |= crit_mask | IDR_EP;
+    }
+
+    src->idr = val & mask;
+    DPRINTF("Set IDR %d to 0x%08x\n", n_IRQ, src->idr);
+
+    if (opp->flags & OPENPIC_FLAG_IDR_CRIT) {
+        if (src->idr & crit_mask) {
+            if (src->idr & normal_mask) {
+                DPRINTF("%s: IRQ configured for multiple output types, using "
+                        "critical\n", __func__);
+            }
+
+            src->output = OPENPIC_OUTPUT_CINT;
+            src->destmask = 0;
+
+            for (i = 0; i < opp->nb_cpus; i++) {
+                int n_ci = IDR_CI0_SHIFT - i;
 
-    tmp = val & (IDR_EP | IDR_CI);
-    tmp |= val & ((1ULL << MAX_CPU) - 1);
-    opp->src[n_IRQ].idr = tmp;
-    DPRINTF("Set IDR %d to 0x%08x\n", n_IRQ, opp->src[n_IRQ].idr);
+                if (src->idr & (1UL << n_ci)) {
+                    src->destmask |= 1UL << i;
+                }
+            }
+        } else {
+            src->output = OPENPIC_OUTPUT_INT;
+            src->destmask = src->idr & normal_mask;
+        }
+    } else {
+        src->destmask = src->idr;
+    }
 }
 
 static inline void write_IRQreg_ivpr(OpenPICState *opp, int n_IRQ, uint32_t val)
@@ -878,7 +924,7 @@ static void openpic_cpu_write_internal(void *opaque, hwaddr addr,
              IVPR_PRIORITY(src->ivpr) > dst->servicing.priority)) {
             DPRINTF("Raise OpenPIC INT output cpu %d irq %d\n",
                     idx, n_IRQ);
-            openpic_irq_raise(opp, idx, src);
+            qemu_irq_raise(opp->dst[idx].irqs[OPENPIC_OUTPUT_INT]);
         }
         break;
     default:
@@ -1101,13 +1147,6 @@ static void openpic_save(QEMUFile* f, void *opaque)
     qemu_put_be32s(f, &opp->spve);
     qemu_put_be32s(f, &opp->tfrr);
 
-    for (i = 0; i < opp->max_irq; i++) {
-        qemu_put_be32s(f, &opp->src[i].ivpr);
-        qemu_put_be32s(f, &opp->src[i].idr);
-        qemu_put_sbe32s(f, &opp->src[i].last_cpu);
-        qemu_put_sbe32s(f, &opp->src[i].pending);
-    }
-
     qemu_put_be32s(f, &opp->nb_cpus);
 
     for (i = 0; i < opp->nb_cpus; i++) {
@@ -1120,6 +1159,13 @@ static void openpic_save(QEMUFile* f, void *opaque)
         qemu_put_be32s(f, &opp->timers[i].tccr);
         qemu_put_be32s(f, &opp->timers[i].tbcr);
     }
+
+    for (i = 0; i < opp->max_irq; i++) {
+        qemu_put_be32s(f, &opp->src[i].ivpr);
+        qemu_put_be32s(f, &opp->src[i].idr);
+        qemu_put_sbe32s(f, &opp->src[i].last_cpu);
+        qemu_put_sbe32s(f, &opp->src[i].pending);
+    }
 }
 
 static void openpic_load_IRQ_queue(QEMUFile* f, IRQQueue *q)
@@ -1148,13 +1194,6 @@ static int openpic_load(QEMUFile* f, void *opaque, int version_id)
     qemu_get_be32s(f, &opp->spve);
     qemu_get_be32s(f, &opp->tfrr);
 
-    for (i = 0; i < opp->max_irq; i++) {
-        qemu_get_be32s(f, &opp->src[i].ivpr);
-        qemu_get_be32s(f, &opp->src[i].idr);
-        qemu_get_sbe32s(f, &opp->src[i].last_cpu);
-        qemu_get_sbe32s(f, &opp->src[i].pending);
-    }
-
     qemu_get_be32s(f, &opp->nb_cpus);
 
     for (i = 0; i < opp->nb_cpus; i++) {
@@ -1168,18 +1207,21 @@ static int openpic_load(QEMUFile* f, void *opaque, int version_id)
         qemu_get_be32s(f, &opp->timers[i].tbcr);
     }
 
-    return 0;
-}
+    for (i = 0; i < opp->max_irq; i++) {
+        uint32_t val;
 
-static void openpic_irq_raise(OpenPICState *opp, int n_CPU, IRQSource *src)
-{
-    int n_ci = IDR_CI0_SHIFT - n_CPU;
+        val = qemu_get_be32(f);
+        write_IRQreg_idr(opp, i, val);
+        val = qemu_get_be32(f);
+        write_IRQreg_ivpr(opp, i, val);
 
-    if ((opp->flags & OPENPIC_FLAG_IDR_CRIT) && (src->idr & (1 << n_ci))) {
-        qemu_irq_raise(opp->dst[n_CPU].irqs[OPENPIC_OUTPUT_CINT]);
-    } else {
-        qemu_irq_raise(opp->dst[n_CPU].irqs[OPENPIC_OUTPUT_INT]);
+        qemu_get_be32s(f, &opp->src[i].ivpr);
+        qemu_get_be32s(f, &opp->src[i].idr);
+        qemu_get_sbe32s(f, &opp->src[i].last_cpu);
+        qemu_get_sbe32s(f, &opp->src[i].pending);
     }
+
+    return 0;
 }
 
 typedef struct MemReg {
Signature · 1 line
1.6.0.2
#16 lore raw

PATCH 16/31 openpic: make ctpr signed

In reply to Alexander Graf

From: Scott Wood <[email protected]>

Other priorities are signed, so avoid comparisons between signed and unsigned.

---
 hw/openpic.c |    6 +++---
 1 files changed, 3 insertions(+), 3 deletions(-)
hw/openpic.c +3 -3
index fe6cf67..824b8fd 100644
@@ -215,7 +215,7 @@ typedef struct IRQSource {
 #define IDR_CI      0x40000000  /* critical interrupt */
 
 typedef struct IRQDest {
-    uint32_t ctpr; /* CPU current task priority */
+    int32_t ctpr; /* CPU current task priority */
     IRQQueue raised;
     IRQQueue servicing;
     qemu_irq *irqs;
@@ -1150,7 +1150,7 @@ static void openpic_save(QEMUFile* f, void *opaque)
     qemu_put_be32s(f, &opp->nb_cpus);
 
     for (i = 0; i < opp->nb_cpus; i++) {
-        qemu_put_be32s(f, &opp->dst[i].ctpr);
+        qemu_put_sbe32s(f, &opp->dst[i].ctpr);
         openpic_save_IRQ_queue(f, &opp->dst[i].raised);
         openpic_save_IRQ_queue(f, &opp->dst[i].servicing);
     }
@@ -1197,7 +1197,7 @@ static int openpic_load(QEMUFile* f, void *opaque, int version_id)
     qemu_get_be32s(f, &opp->nb_cpus);
 
     for (i = 0; i < opp->nb_cpus; i++) {
-        qemu_get_be32s(f, &opp->dst[i].ctpr);
+        qemu_get_sbe32s(f, &opp->dst[i].ctpr);
         openpic_load_IRQ_queue(f, &opp->dst[i].raised);
         openpic_load_IRQ_queue(f, &opp->dst[i].servicing);
     }
Signature · 1 line
1.6.0.2
#17 lore raw

PATCH 17/31 openpic/fsl: critical interrupts ignore mask before v4.1

In reply to Alexander Graf

From: Scott Wood <[email protected]>

[agraf: make bool :1]
---
 hw/openpic.c |    5 ++++-
 1 files changed, 4 insertions(+), 1 deletions(-)
hw/openpic.c +4 -1
index 824b8fd..ac5027a 100644
@@ -193,6 +193,7 @@ typedef struct IRQSource {
     int last_cpu;
     int output;     /* IRQ level, e.g. OPENPIC_OUTPUT_INT */
     int pending;    /* TRUE if IRQ is pending */
+    bool nomask:1;  /* critical interrupts ignore mask on some FSL MPICs */
 } IRQSource;
 
 #define IVPR_MASK_SHIFT       31
@@ -389,7 +390,7 @@ static void openpic_update_irq(OpenPICState *opp, int n_IRQ)
         DPRINTF("%s: IRQ %d is not pending\n", __func__, n_IRQ);
         return;
     }
-    if (src->ivpr & IVPR_MASK_MASK) {
+    if ((src->ivpr & IVPR_MASK_MASK) && !src->nomask) {
         /* Interrupt source is disabled */
         DPRINTF("%s: IRQ %d is disabled\n", __func__, n_IRQ);
         return;
@@ -529,6 +530,7 @@ static inline void write_IRQreg_idr(OpenPICState *opp, int n_IRQ, uint32_t val)
             }
 
             src->output = OPENPIC_OUTPUT_CINT;
+            src->nomask = true;
             src->destmask = 0;
 
             for (i = 0; i < opp->nb_cpus; i++) {
@@ -540,6 +542,7 @@ static inline void write_IRQreg_idr(OpenPICState *opp, int n_IRQ, uint32_t val)
             }
         } else {
             src->output = OPENPIC_OUTPUT_INT;
+            src->nomask = false;
             src->destmask = src->idr & normal_mask;
         }
     } else {
Signature · 1 line
1.6.0.2
#18 lore raw

PATCH 18/31 openpic: always call IRQ_check from IRQ_get_next

In reply to Alexander Graf

From: Scott Wood <[email protected]>

Previously the code relied on the queue's "next" field getting set to -1 sometime between an update to the bitmap, and the next call to IRQ_get_next. Sometimes this happened after the update. Sometimes it happened before the check. Sometimes it didn't happen at all.

---
 hw/openpic.c |   10 +++-------
 1 files changed, 3 insertions(+), 7 deletions(-)
hw/openpic.c +3 -7
index ac5027a..19e6280 100644
@@ -315,10 +315,8 @@ out:
 
 static int IRQ_get_next(OpenPICState *opp, IRQQueue *q)
 {
-    if (q->next == -1) {
-        /* XXX: optimize */
-        IRQ_check(opp, q);
-    }
+    /* XXX: optimize */
+    IRQ_check(opp, q);
 
     return q->next;
 }
@@ -365,7 +363,7 @@ static void IRQ_local_pipe(OpenPICState *opp, int n_CPU, int n_IRQ)
                 __func__, n_IRQ, dst->raised.next, n_CPU);
         return;
     }
-    IRQ_get_next(opp, &dst->raised);
+    IRQ_check(opp, &dst->raised);
     if (IRQ_get_next(opp, &dst->servicing) != -1 &&
         priority <= dst->servicing.priority) {
         DPRINTF("%s: IRQ %d is hidden by servicing IRQ %d on CPU %d\n",
@@ -916,7 +914,6 @@ static void openpic_cpu_write_internal(void *opaque, hwaddr addr,
         DPRINTF("EOI\n");
         s_IRQ = IRQ_get_next(opp, &dst->servicing);
         IRQ_resetbit(&dst->servicing, s_IRQ);
-        dst->servicing.next = -1;
         /* Set up next servicing IRQ */
         s_IRQ = IRQ_get_next(opp, &dst->servicing);
         /* Check queued interrupts. */
@@ -993,7 +990,6 @@ static uint32_t openpic_cpu_read_internal(void *opaque, hwaddr addr,
                 retval = IVPR_VECTOR(opp, src->ivpr);
             }
             IRQ_resetbit(&dst->raised, n_IRQ);
-            dst->raised.next = -1;
             if (!(src->ivpr & IVPR_SENSE_MASK)) {
                 /* edge-sensitive IRQ */
                 src->ivpr &= ~IVPR_ACTIVITY_MASK;
Signature · 1 line
1.6.0.2
#19 lore raw

PATCH 19/31 Revert "openpic: Accelerate pending irq search"

In reply to Alexander Graf

From: Scott Wood <[email protected]>

This reverts commit a9bd83f4c65de0058659ede009fa1a241f379edd.

This counting approach is not robust against setting a bit that was already set, or clearing a bit that was already clear. Perhaps that is considered a bug, but besides the lack of any documentation for that restriction, it's a pretty unpleasant way for the problem to manifest itself.

It could be made more robust by testing the current value of the bit before changing the count, but a later patch speeds up IRQ_check in all cases, not just when there's nothing pending. Hopefully that should be adequate to address performance concerns.

---
 hw/openpic.c |   11 -----------
 1 files changed, 0 insertions(+), 11 deletions(-)
hw/openpic.c +0 -11
index 19e6280..2c238fb 100644
@@ -183,7 +183,6 @@ typedef struct IRQQueue {
     uint32_t queue[BF_WIDTH(MAX_IRQ)];
     int next;
     int priority;
-    int pending;    /* nr of pending bits in queue */
 } IRQQueue;
 
 typedef struct IRQSource {
@@ -269,13 +268,11 @@ typedef struct OpenPICState {
 
 static inline void IRQ_setbit(IRQQueue *q, int n_IRQ)
 {
-    q->pending++;
     set_bit(q->queue, n_IRQ);
 }
 
 static inline void IRQ_resetbit(IRQQueue *q, int n_IRQ)
 {
-    q->pending--;
     reset_bit(q->queue, n_IRQ);
 }
 
@@ -291,12 +288,6 @@ static void IRQ_check(OpenPICState *opp, IRQQueue *q)
 
     next = -1;
     priority = -1;
-
-    if (!q->pending) {
-        /* IRQ bitmap is empty */
-        goto out;
-    }
-
     for (i = 0; i < opp->max_irq; i++) {
         if (IRQ_testbit(q, i)) {
             DPRINTF("IRQ_check: irq %d set ivpr_pr=%d pr=%d\n",
@@ -307,8 +298,6 @@ static void IRQ_check(OpenPICState *opp, IRQQueue *q)
             }
         }
     }
-
-out:
     q->next = next;
     q->priority = priority;
 }
Signature · 1 line
1.6.0.2
#20 lore raw

PATCH 20/31 openpic: use standard bitmap operations

In reply to Alexander Graf

From: Scott Wood <[email protected]>

Besides the private implementation being redundant, namespace collisions prevented the use of other things in bitops.h.

Serialization does get a bit more awkward, unfortunately, since the standard bitmap operations are "unsigned long" rather than "uint32_t", though in exchange we will get faster queue lookups on 64-bit hosts once we search a word at a time.

---
 hw/openpic.c |   55 +++++++++++++++++++++++++++++--------------------------
 1 files changed, 29 insertions(+), 26 deletions(-)
hw/openpic.c +29 -26
index 2c238fb..b54308d 100644
@@ -39,6 +39,7 @@
 #include "openpic.h"
 #include "sysbus.h"
 #include "pci/msi.h"
+#include "qemu/bitops.h"
 
 //#define DEBUG_OPENPIC
 
@@ -147,24 +148,6 @@ static const int debug_openpic = 0;
 #define MSIIR_IBS_SHIFT    24
 #define MSIIR_IBS_MASK     (0x1f << MSIIR_IBS_SHIFT)
 
-#define BF_WIDTH(_bits_) \
-(((_bits_) + (sizeof(uint32_t) * 8) - 1) / (sizeof(uint32_t) * 8))
-
-static inline void set_bit(uint32_t *field, int bit)
-{
-    field[bit >> 5] |= 1 << (bit & 0x1F);
-}
-
-static inline void reset_bit(uint32_t *field, int bit)
-{
-    field[bit >> 5] &= ~(1 << (bit & 0x1F));
-}
-
-static inline int test_bit(uint32_t *field, int bit)
-{
-    return (field[bit >> 5] & 1 << (bit & 0x1F)) != 0;
-}
-
 static int get_current_cpu(void)
 {
     if (!cpu_single_env) {
@@ -180,7 +163,10 @@ static void openpic_cpu_write_internal(void *opaque, hwaddr addr,
                                        uint32_t val, int idx);
 
 typedef struct IRQQueue {
-    uint32_t queue[BF_WIDTH(MAX_IRQ)];
+    /* Round up to the nearest 64 IRQs so that the queue length
+     * won't change when moving between 32 and 64 bit hosts.
+     */
+    unsigned long queue[BITS_TO_LONGS((MAX_IRQ + 63) & ~63)];
     int next;
     int priority;
 } IRQQueue;
@@ -268,17 +254,17 @@ typedef struct OpenPICState {
 
 static inline void IRQ_setbit(IRQQueue *q, int n_IRQ)
 {
-    set_bit(q->queue, n_IRQ);
+    set_bit(n_IRQ, q->queue);
 }
 
 static inline void IRQ_resetbit(IRQQueue *q, int n_IRQ)
 {
-    reset_bit(q->queue, n_IRQ);
+    clear_bit(n_IRQ, q->queue);
 }
 
 static inline int IRQ_testbit(IRQQueue *q, int n_IRQ)
 {
-    return test_bit(q->queue, n_IRQ);
+    return test_bit(n_IRQ, q->queue);
 }
 
 static void IRQ_check(OpenPICState *opp, IRQQueue *q)
@@ -1117,8 +1103,16 @@ static void openpic_save_IRQ_queue(QEMUFile* f, IRQQueue *q)
 {
     unsigned int i;
 
-    for (i = 0; i < BF_WIDTH(MAX_IRQ); i++)
-        qemu_put_be32s(f, &q->queue[i]);
+    for (i = 0; i < ARRAY_SIZE(q->queue); i++) {
+        /* Always put the lower half of a 64-bit long first, in case we
+         * restore on a 32-bit host.  The least significant bits correspond
+         * to lower IRQ numbers in the bitmap.
+         */
+        qemu_put_be32(f, (uint32_t)q->queue[i]);
+#if LONG_MAX > 0x7FFFFFFF
+        qemu_put_be32(f, (uint32_t)(q->queue[i] >> 32));
+#endif
+    }
 
     qemu_put_sbe32s(f, &q->next);
     qemu_put_sbe32s(f, &q->priority);
@@ -1160,8 +1154,17 @@ static void openpic_load_IRQ_queue(QEMUFile* f, IRQQueue *q)
 {
     unsigned int i;
 
-    for (i = 0; i < BF_WIDTH(MAX_IRQ); i++)
-        qemu_get_be32s(f, &q->queue[i]);
+    for (i = 0; i < ARRAY_SIZE(q->queue); i++) {
+        unsigned long val;
+
+        val = qemu_get_be32(f);
+#if LONG_MAX > 0x7FFFFFFF
+        val <<= 32;
+        val |= qemu_get_be32(f);
+#endif
+
+        q->queue[i] = val;
+    }
 
     qemu_get_sbe32s(f, &q->next);
     qemu_get_sbe32s(f, &q->priority);
Signature · 1 line
1.6.0.2
#21 lore raw

PATCH 21/31 openpic: add some bounds checking for IRQ numbers

In reply to Alexander Graf

From: Scott Wood <[email protected]>

The two checks with abort() guard against potential QEMU-internal problems, but the EOI check stops the guest from causing updates to queue position -1 and other havoc if it writes EOI with no interrupt in service.

[agraf: remove hunk in code that didn't get applied yet]
---
 hw/openpic.c |   11 +++++++++++
 1 files changed, 11 insertions(+), 0 deletions(-)
hw/openpic.c +11 -0
index b54308d..35a7fe3 100644
@@ -414,6 +414,11 @@ static void openpic_set_irq(void *opaque, int n_IRQ, int level)
     OpenPICState *opp = opaque;
     IRQSource *src;
 
+    if (n_IRQ >= MAX_IRQ) {
+        fprintf(stderr, "%s: IRQ %d out of range\n", __func__, n_IRQ);
+        abort();
+    }
+
     src = &opp->src[n_IRQ];
     DPRINTF("openpic: set irq %d = %d ivpr=0x%08x\n",
             n_IRQ, level, src->ivpr);
@@ -888,6 +893,12 @@ static void openpic_cpu_write_internal(void *opaque, hwaddr addr,
     case 0xB0: /* EOI */
         DPRINTF("EOI\n");
         s_IRQ = IRQ_get_next(opp, &dst->servicing);
+
+        if (s_IRQ < 0) {
+            DPRINTF("%s: EOI with no interrupt in service\n", __func__);
+            break;
+        }
+
         IRQ_resetbit(&dst->servicing, s_IRQ);
         /* Set up next servicing IRQ */
         s_IRQ = IRQ_get_next(opp, &dst->servicing);
Signature · 1 line
1.6.0.2
#22 lore raw

PATCH 22/31 openpic: fix sense and priority bits

In reply to Alexander Graf

From: Scott Wood <[email protected]>

Previously, the sense and priority bits were masked off when writing to IVPR, and all interrupts were treated as edge-triggered (despite the existence of code for handling level-triggered interrupts).

Polarity is implemented only as storage. We don't simulate the bad effects that you'd get on real hardware if you set this incorrectly, but at least the guest sees the right thing when it reads back the register.

Sense now controls level/edge on FSL external interrupts (and all interrupts on non-FSL MPIC). FSL internal interrupts do not have a sense bit (reads as zero), but are level. FSL timers and IPIs do not have sense or polarity bits (read as zero), and are edge-triggered. To accommodate FSL internal interrupts, QEMU's internal notion of whether an interrupt is level-triggered is separated from the IVPR bit.

---
 hw/openpic.c |   77 +++++++++++++++++++++++++++++++++++++++++++++++++++++----
 1 files changed, 71 insertions(+), 6 deletions(-)
hw/openpic.c +71 -6
index 35a7fe3..66179c2 100644
@@ -162,6 +162,12 @@ static uint32_t openpic_cpu_read_internal(void *opaque, hwaddr addr,
 static void openpic_cpu_write_internal(void *opaque, hwaddr addr,
                                        uint32_t val, int idx);
 
+typedef enum IRQType {
+    IRQ_TYPE_NORMAL = 0,
+    IRQ_TYPE_FSLINT,        /* FSL internal interrupt -- level only */
+    IRQ_TYPE_FSLSPECIAL,    /* FSL timer/IPI interrupt, edge, no polarity */
+} IRQType;
+
 typedef struct IRQQueue {
     /* Round up to the nearest 64 IRQs so that the queue length
      * won't change when moving between 32 and 64 bit hosts.
@@ -178,6 +184,8 @@ typedef struct IRQSource {
     int last_cpu;
     int output;     /* IRQ level, e.g. OPENPIC_OUTPUT_INT */
     int pending;    /* TRUE if IRQ is pending */
+    IRQType type;
+    bool level:1;   /* level-triggered */
     bool nomask:1;  /* critical interrupts ignore mask on some FSL MPICs */
 } IRQSource;
 
@@ -422,7 +430,7 @@ static void openpic_set_irq(void *opaque, int n_IRQ, int level)
     src = &opp->src[n_IRQ];
     DPRINTF("openpic: set irq %d = %d ivpr=0x%08x\n",
             n_IRQ, level, src->ivpr);
-    if (src->ivpr & IVPR_SENSE_MASK) {
+    if (src->level) {
         /* level-sensitive irq */
         src->pending = level;
         if (!level) {
@@ -455,6 +463,19 @@ static void openpic_reset(DeviceState *d)
     for (i = 0; i < opp->max_irq; i++) {
         opp->src[i].ivpr = opp->ivpr_reset;
         opp->src[i].idr  = opp->idr_reset;
+
+        switch (opp->src[i].type) {
+        case IRQ_TYPE_NORMAL:
+            opp->src[i].level = !!(opp->ivpr_reset & IVPR_SENSE_MASK);
+            break;
+
+        case IRQ_TYPE_FSLINT:
+            opp->src[i].ivpr |= IVPR_POLARITY_MASK;
+            break;
+
+        case IRQ_TYPE_FSLSPECIAL:
+            break;
+        }
     }
     /* Initialise IRQ destinations */
     for (i = 0; i < MAX_CPU; i++) {
@@ -530,10 +551,36 @@ static inline void write_IRQreg_idr(OpenPICState *opp, int n_IRQ, uint32_t val)
 
 static inline void write_IRQreg_ivpr(OpenPICState *opp, int n_IRQ, uint32_t val)
 {
-    /* NOTE: not fully accurate for special IRQs, but simple and sufficient */
+    uint32_t mask;
+
+    /* NOTE when implementing newer FSL MPIC models: starting with v4.0,
+     * the polarity bit is read-only on internal interrupts.
+     */
+    mask = IVPR_MASK_MASK | IVPR_PRIORITY_MASK | IVPR_SENSE_MASK |
+           IVPR_POLARITY_MASK | opp->vector_mask;
+
     /* ACTIVITY bit is read-only */
-    opp->src[n_IRQ].ivpr = (opp->src[n_IRQ].ivpr & IVPR_ACTIVITY_MASK) |
-        (val & (IVPR_MASK_MASK | IVPR_PRIORITY_MASK | opp->vector_mask));
+    opp->src[n_IRQ].ivpr =
+        (opp->src[n_IRQ].ivpr & IVPR_ACTIVITY_MASK) | (val & mask);
+
+    /* For FSL internal interrupts, The sense bit is reserved and zero,
+     * and the interrupt is always level-triggered.  Timers and IPIs
+     * have no sense or polarity bits, and are edge-triggered.
+     */
+    switch (opp->src[n_IRQ].type) {
+    case IRQ_TYPE_NORMAL:
+        opp->src[n_IRQ].level = !!(opp->src[n_IRQ].ivpr & IVPR_SENSE_MASK);
+        break;
+
+    case IRQ_TYPE_FSLINT:
+        opp->src[n_IRQ].ivpr &= ~IVPR_SENSE_MASK;
+        break;
+
+    case IRQ_TYPE_FSLSPECIAL:
+        opp->src[n_IRQ].ivpr &= ~(IVPR_POLARITY_MASK | IVPR_SENSE_MASK);
+        break;
+    }
+
     openpic_update_irq(opp, n_IRQ);
     DPRINTF("Set IVPR %d to 0x%08x -> 0x%08x\n", n_IRQ, val,
             opp->src[n_IRQ].ivpr);
@@ -976,7 +1023,7 @@ static uint32_t openpic_cpu_read_internal(void *opaque, hwaddr addr,
                 retval = IVPR_VECTOR(opp, src->ivpr);
             }
             IRQ_resetbit(&dst->raised, n_IRQ);
-            if (!(src->ivpr & IVPR_SENSE_MASK)) {
+            if (!src->level) {
                 /* edge-sensitive IRQ */
                 src->ivpr &= ~IVPR_ACTIVITY_MASK;
                 src->pending = 0;
@@ -984,7 +1031,7 @@ static uint32_t openpic_cpu_read_internal(void *opaque, hwaddr addr,
 
             if ((n_IRQ >= opp->irq_ipi0) &&  (n_IRQ < (opp->irq_ipi0 + MAX_IPI))) {
                 src->idr &= ~(1 << idx);
-                if (src->idr && !(src->ivpr & IVPR_SENSE_MASK)) {
+                if (src->idr && !src->level) {
                     /* trigger on CPUs that didn't know about it yet */
                     openpic_set_irq(opp, n_IRQ, 1);
                     openpic_set_irq(opp, n_IRQ, 0);
@@ -1282,7 +1329,25 @@ static int openpic_init(SysBusDevice *dev)
         opp->brr1 = FSL_BRR1_IPID | FSL_BRR1_IPMJ | FSL_BRR1_IPMN;
         msi_supported = true;
         list = list_be;
+
+        for (i = 0; i < FSL_MPIC_20_MAX_EXT; i++) {
+            opp->src[i].level = false;
+        }
+
+        /* Internal interrupts, including message and MSI */
+        for (i = 16; i < MAX_SRC; i++) {
+            opp->src[i].type = IRQ_TYPE_FSLINT;
+            opp->src[i].level = true;
+        }
+
+        /* timers and IPIs */
+        for (i = MAX_SRC; i < MAX_IRQ; i++) {
+            opp->src[i].type = IRQ_TYPE_FSLSPECIAL;
+            opp->src[i].level = false;
+        }
+
         break;
+
     case OPENPIC_MODEL_RAVEN:
         opp->nb_irqs = RAVEN_MAX_EXT;
         opp->vid = VID_REVISION_1_3;
Signature · 1 line
1.6.0.2
#23 lore raw

PATCH 23/31 openpic: IRQ_check: search the queue a word at a time

In reply to Alexander Graf

From: Scott Wood <[email protected]>

Search the queue more efficiently by first looking for a non-zero word, and then using the common bit-searching function to find the bit within the word. It would be even nicer if bitops_ffsl() could be hooked up to the compiler intrinsic so that bit-searching instructions could be used, but that's another matter.

---
 hw/openpic.c |   28 ++++++++++++++++------------
 1 files changed, 16 insertions(+), 12 deletions(-)
hw/openpic.c +16 -12
index 66179c2..7645d67 100644
@@ -277,21 +277,25 @@ static inline int IRQ_testbit(IRQQueue *q, int n_IRQ)
 
 static void IRQ_check(OpenPICState *opp, IRQQueue *q)
 {
-    int next, i;
-    int priority;
+    int irq = -1;
+    int next = -1;
+    int priority = -1;
 
-    next = -1;
-    priority = -1;
-    for (i = 0; i < opp->max_irq; i++) {
-        if (IRQ_testbit(q, i)) {
-            DPRINTF("IRQ_check: irq %d set ivpr_pr=%d pr=%d\n",
-                    i, IVPR_PRIORITY(opp->src[i].ivpr), priority);
-            if (IVPR_PRIORITY(opp->src[i].ivpr) > priority) {
-                next = i;
-                priority = IVPR_PRIORITY(opp->src[i].ivpr);
-            }
+    for (;;) {
+        irq = find_next_bit(q->queue, opp->max_irq, irq + 1);
+        if (irq == opp->max_irq) {
+            break;
+        }
+
+        DPRINTF("IRQ_check: irq %d set ivpr_pr=%d pr=%d\n",
+                irq, IVPR_PRIORITY(opp->src[irq].ivpr), priority);
+
+        if (IVPR_PRIORITY(opp->src[irq].ivpr) > priority) {
+            next = irq;
+            priority = IVPR_PRIORITY(opp->src[irq].ivpr);
         }
     }
+
     q->next = next;
     q->priority = priority;
 }
Signature · 1 line
1.6.0.2
#24 lore raw

PATCH 24/31 openpic: move IACK to its own function

In reply to Alexander Graf

From: Scott Wood <[email protected]>

Besides making the code cleaner, we will need a separate way to access IACK in order to implement EPR (external proxy) interrupt delivery.

---
 hw/openpic.c |   95 ++++++++++++++++++++++++++++++++-------------------------
 1 files changed, 53 insertions(+), 42 deletions(-)
hw/openpic.c +53 -42
index 7645d67..374f80e 100644
@@ -975,14 +975,64 @@ static void openpic_cpu_write(void *opaque, hwaddr addr, uint64_t val,
     openpic_cpu_write_internal(opaque, addr, val, (addr & 0x1f000) >> 12);
 }
 
+
+static uint32_t openpic_iack(OpenPICState *opp, IRQDest *dst, int cpu)
+{
+    IRQSource *src;
+    int retval, irq;
+
+    DPRINTF("Lower OpenPIC INT output\n");
+    qemu_irq_lower(dst->irqs[OPENPIC_OUTPUT_INT]);
+
+    irq = IRQ_get_next(opp, &dst->raised);
+    DPRINTF("IACK: irq=%d\n", irq);
+
+    if (irq == -1) {
+        /* No more interrupt pending */
+        return opp->spve;
+    }
+
+    src = &opp->src[irq];
+    if (!(src->ivpr & IVPR_ACTIVITY_MASK) ||
+            !(IVPR_PRIORITY(src->ivpr) > dst->ctpr)) {
+        /* - Spurious level-sensitive IRQ
+         * - Priorities has been changed
+         *   and the pending IRQ isn't allowed anymore
+         */
+        src->ivpr &= ~IVPR_ACTIVITY_MASK;
+        retval = opp->spve;
+    } else {
+        /* IRQ enter servicing state */
+        IRQ_setbit(&dst->servicing, irq);
+        retval = IVPR_VECTOR(opp, src->ivpr);
+    }
+    IRQ_resetbit(&dst->raised, irq);
+    if (!src->level) {
+        /* edge-sensitive IRQ */
+        src->ivpr &= ~IVPR_ACTIVITY_MASK;
+        src->pending = 0;
+    }
+
+    if ((irq >= opp->irq_ipi0) &&  (irq < (opp->irq_ipi0 + MAX_IPI))) {
+        src->idr &= ~(1 << cpu);
+        if (src->idr && !src->level) {
+            /* trigger on CPUs that didn't know about it yet */
+            openpic_set_irq(opp, irq, 1);
+            openpic_set_irq(opp, irq, 0);
+            /* if all CPUs knew about it, set active bit again */
+            src->ivpr |= IVPR_ACTIVITY_MASK;
+        }
+    }
+
+    return retval;
+}
+
 static uint32_t openpic_cpu_read_internal(void *opaque, hwaddr addr,
                                           int idx)
 {
     OpenPICState *opp = opaque;
-    IRQSource *src;
     IRQDest *dst;
     uint32_t retval;
-    int n_IRQ;
 
     DPRINTF("%s: cpu %d addr %#" HWADDR_PRIx "\n", __func__, idx, addr);
     retval = 0xFFFFFFFF;
@@ -1004,46 +1054,7 @@ static uint32_t openpic_cpu_read_internal(void *opaque, hwaddr addr,
         retval = idx;
         break;
     case 0xA0: /* IACK */
-        DPRINTF("Lower OpenPIC INT output\n");
-        qemu_irq_lower(dst->irqs[OPENPIC_OUTPUT_INT]);
-        n_IRQ = IRQ_get_next(opp, &dst->raised);
-        DPRINTF("IACK: irq=%d\n", n_IRQ);
-        if (n_IRQ == -1) {
-            /* No more interrupt pending */
-            retval = opp->spve;
-        } else {
-            src = &opp->src[n_IRQ];
-            if (!(src->ivpr & IVPR_ACTIVITY_MASK) ||
-                !(IVPR_PRIORITY(src->ivpr) > dst->ctpr)) {
-                /* - Spurious level-sensitive IRQ
-                 * - Priorities has been changed
-                 *   and the pending IRQ isn't allowed anymore
-                 */
-                src->ivpr &= ~IVPR_ACTIVITY_MASK;
-                retval = opp->spve;
-            } else {
-                /* IRQ enter servicing state */
-                IRQ_setbit(&dst->servicing, n_IRQ);
-                retval = IVPR_VECTOR(opp, src->ivpr);
-            }
-            IRQ_resetbit(&dst->raised, n_IRQ);
-            if (!src->level) {
-                /* edge-sensitive IRQ */
-                src->ivpr &= ~IVPR_ACTIVITY_MASK;
-                src->pending = 0;
-            }
-
-            if ((n_IRQ >= opp->irq_ipi0) &&  (n_IRQ < (opp->irq_ipi0 + MAX_IPI))) {
-                src->idr &= ~(1 << idx);
-                if (src->idr && !src->level) {
-                    /* trigger on CPUs that didn't know about it yet */
-                    openpic_set_irq(opp, n_IRQ, 1);
-                    openpic_set_irq(opp, n_IRQ, 0);
-                    /* if all CPUs knew about it, set active bit again */
-                    src->ivpr |= IVPR_ACTIVITY_MASK;
-                }
-            }
-        }
+        retval = openpic_iack(opp, dst, idx);
         break;
     case 0xB0: /* EOI */
         retval = 0;
Signature · 1 line
1.6.0.2
#25 lore raw

PATCH 25/31 openpic: fix CTPR and de-assertion of interrupts

In reply to Alexander Graf

From: Scott Wood <[email protected]>

Properly implement level-triggered interrupts by withdrawing an interrupt from the raised queue if the interrupt source de-asserts. Also withdraw from the raised queue if the interrupt becomes masked.

When CTPR is written, check whether we need to raise or lower the interrupt output.

---
 hw/openpic.c |  181 +++++++++++++++++++++++++++++++++++++++-------------------
 1 files changed, 123 insertions(+), 58 deletions(-)
hw/openpic.c +123 -58
index 374f80e..e773d68 100644
@@ -213,6 +213,9 @@ typedef struct IRQDest {
     IRQQueue raised;
     IRQQueue servicing;
     qemu_irq *irqs;
+
+    /* Count of IRQ sources asserting on non-INT outputs */
+    uint32_t outputs_active[OPENPIC_OUTPUT_NB];
 } IRQDest;
 
 typedef struct OpenPICState {
@@ -308,7 +311,8 @@ static int IRQ_get_next(OpenPICState *opp, IRQQueue *q)
     return q->next;
 }
 
-static void IRQ_local_pipe(OpenPICState *opp, int n_CPU, int n_IRQ)
+static void IRQ_local_pipe(OpenPICState *opp, int n_CPU, int n_IRQ,
+                           bool active, bool was_active)
 {
     IRQDest *dst;
     IRQSource *src;
@@ -317,79 +321,113 @@ static void IRQ_local_pipe(OpenPICState *opp, int n_CPU, int n_IRQ)
     dst = &opp->dst[n_CPU];
     src = &opp->src[n_IRQ];
 
+    DPRINTF("%s: IRQ %d active %d was %d\n",
+            __func__, n_IRQ, active, was_active);
+
     if (src->output != OPENPIC_OUTPUT_INT) {
+        DPRINTF("%s: output %d irq %d active %d was %d count %d\n",
+                __func__, src->output, n_IRQ, active, was_active,
+                dst->outputs_active[src->output]);
+
         /* On Freescale MPIC, critical interrupts ignore priority,
          * IACK, EOI, etc.  Before MPIC v4.1 they also ignore
          * masking.
          */
-        src->ivpr |= IVPR_ACTIVITY_MASK;
-        DPRINTF("%s: Raise OpenPIC output %d cpu %d irq %d\n",
-                __func__, src->output, n_CPU, n_IRQ);
-        qemu_irq_raise(opp->dst[n_CPU].irqs[src->output]);
+        if (active) {
+            if (!was_active && dst->outputs_active[src->output]++ == 0) {
+                DPRINTF("%s: Raise OpenPIC output %d cpu %d irq %d\n",
+                        __func__, src->output, n_CPU, n_IRQ);
+                qemu_irq_raise(dst->irqs[src->output]);
+            }
+        } else {
+            if (was_active && --dst->outputs_active[src->output] == 0) {
+                DPRINTF("%s: Lower OpenPIC output %d cpu %d irq %d\n",
+                        __func__, src->output, n_CPU, n_IRQ);
+                qemu_irq_lower(dst->irqs[src->output]);
+            }
+        }
+
         return;
     }
 
     priority = IVPR_PRIORITY(src->ivpr);
-    if (priority <= dst->ctpr) {
-        /* Too low priority */
-        DPRINTF("%s: IRQ %d has too low priority on CPU %d\n",
-                __func__, n_IRQ, n_CPU);
-        return;
-    }
-    if (IRQ_testbit(&dst->raised, n_IRQ)) {
-        /* Interrupt miss */
-        DPRINTF("%s: IRQ %d was missed on CPU %d\n",
-                __func__, n_IRQ, n_CPU);
-        return;
-    }
-    src->ivpr |= IVPR_ACTIVITY_MASK;
-    IRQ_setbit(&dst->raised, n_IRQ);
-    if (priority < dst->raised.priority) {
-        /* An higher priority IRQ is already raised */
-        DPRINTF("%s: IRQ %d is hidden by raised IRQ %d on CPU %d\n",
-                __func__, n_IRQ, dst->raised.next, n_CPU);
-        return;
+
+    /* Even if the interrupt doesn't have enough priority,
+     * it is still raised, in case ctpr is lowered later.
+     */
+    if (active) {
+        IRQ_setbit(&dst->raised, n_IRQ);
+    } else {
+        IRQ_resetbit(&dst->raised, n_IRQ);
     }
+
     IRQ_check(opp, &dst->raised);
-    if (IRQ_get_next(opp, &dst->servicing) != -1 &&
-        priority <= dst->servicing.priority) {
-        DPRINTF("%s: IRQ %d is hidden by servicing IRQ %d on CPU %d\n",
-                __func__, n_IRQ, dst->servicing.next, n_CPU);
-        /* Already servicing a higher priority IRQ */
-        return;
+
+    if (active && priority <= dst->ctpr) {
+        DPRINTF("%s: IRQ %d priority %d too low for ctpr %d on CPU %d\n",
+                __func__, n_IRQ, priority, dst->ctpr, n_CPU);
+        active = 0;
+    }
+
+    if (active) {
+        if (IRQ_get_next(opp, &dst->servicing) >= 0 &&
+                priority <= dst->servicing.priority) {
+            DPRINTF("%s: IRQ %d is hidden by servicing IRQ %d on CPU %d\n",
+                    __func__, n_IRQ, dst->servicing.next, n_CPU);
+        } else {
+            DPRINTF("%s: Raise OpenPIC INT output cpu %d irq %d/%d\n",
+                    __func__, n_CPU, n_IRQ, dst->raised.next);
+            qemu_irq_raise(opp->dst[n_CPU].irqs[OPENPIC_OUTPUT_INT]);
+        }
+    } else {
+        IRQ_get_next(opp, &dst->servicing);
+        if (dst->raised.priority > dst->ctpr &&
+                dst->raised.priority > dst->servicing.priority) {
+            DPRINTF("%s: IRQ %d inactive, IRQ %d prio %d above %d/%d, CPU %d\n",
+                    __func__, n_IRQ, dst->raised.next, dst->raised.priority,
+                    dst->ctpr, dst->servicing.priority, n_CPU);
+            /* IRQ line stays asserted */
+        } else {
+            DPRINTF("%s: IRQ %d inactive, current prio %d/%d, CPU %d\n",
+                    __func__, n_IRQ, dst->ctpr, dst->servicing.priority, n_CPU);
+            qemu_irq_lower(opp->dst[n_CPU].irqs[OPENPIC_OUTPUT_INT]);
+        }
     }
-    DPRINTF("Raise OpenPIC INT output cpu %d irq %d\n", n_CPU, n_IRQ);
-    qemu_irq_raise(opp->dst[n_CPU].irqs[OPENPIC_OUTPUT_INT]);
 }
 
 /* update pic state because registers for n_IRQ have changed value */
 static void openpic_update_irq(OpenPICState *opp, int n_IRQ)
 {
     IRQSource *src;
+    bool active, was_active;
     int i;
 
     src = &opp->src[n_IRQ];
+    active = src->pending;
 
-    if (!src->pending) {
-        /* no irq pending */
-        DPRINTF("%s: IRQ %d is not pending\n", __func__, n_IRQ);
-        return;
-    }
     if ((src->ivpr & IVPR_MASK_MASK) && !src->nomask) {
         /* Interrupt source is disabled */
         DPRINTF("%s: IRQ %d is disabled\n", __func__, n_IRQ);
-        return;
+        active = false;
     }
-    if (IVPR_PRIORITY(src->ivpr) == 0) {
-        /* Priority set to zero */
-        DPRINTF("%s: IRQ %d has 0 priority\n", __func__, n_IRQ);
+
+    was_active = !!(src->ivpr & IVPR_ACTIVITY_MASK);
+
+    /*
+     * We don't have a similar check for already-active because
+     * ctpr may have changed and we need to withdraw the interrupt.
+     */
+    if (!active && !was_active) {
+        DPRINTF("%s: IRQ %d is already inactive\n", __func__, n_IRQ);
         return;
     }
-    if (src->ivpr & IVPR_ACTIVITY_MASK) {
-        /* IRQ already active */
-        DPRINTF("%s: IRQ %d is already active\n", __func__, n_IRQ);
-        return;
+
+    if (active) {
+        src->ivpr |= IVPR_ACTIVITY_MASK;
+    } else {
+        src->ivpr &= ~IVPR_ACTIVITY_MASK;
     }
+
     if (src->idr == 0) {
         /* No target */
         DPRINTF("%s: IRQ %d has no target\n", __func__, n_IRQ);
@@ -398,12 +436,12 @@ static void openpic_update_irq(OpenPICState *opp, int n_IRQ)
 
     if (src->idr == (1 << src->last_cpu)) {
         /* Only one CPU is allowed to receive this IRQ */
-        IRQ_local_pipe(opp, src->last_cpu, n_IRQ);
+        IRQ_local_pipe(opp, src->last_cpu, n_IRQ, active, was_active);
     } else if (!(src->ivpr & IVPR_MODE_MASK)) {
         /* Directed delivery mode */
         for (i = 0; i < opp->nb_cpus; i++) {
             if (src->destmask & (1 << i)) {
-                IRQ_local_pipe(opp, i, n_IRQ);
+                IRQ_local_pipe(opp, i, n_IRQ, active, was_active);
             }
         }
     } else {
@@ -413,7 +451,7 @@ static void openpic_update_irq(OpenPICState *opp, int n_IRQ)
                 i = 0;
             }
             if (src->destmask & (1 << i)) {
-                IRQ_local_pipe(opp, i, n_IRQ);
+                IRQ_local_pipe(opp, i, n_IRQ, active, was_active);
                 src->last_cpu = i;
                 break;
             }
@@ -437,16 +475,25 @@ static void openpic_set_irq(void *opaque, int n_IRQ, int level)
     if (src->level) {
         /* level-sensitive irq */
         src->pending = level;
-        if (!level) {
-            src->ivpr &= ~IVPR_ACTIVITY_MASK;
-        }
+        openpic_update_irq(opp, n_IRQ);
     } else {
         /* edge-sensitive irq */
         if (level) {
             src->pending = 1;
+            openpic_update_irq(opp, n_IRQ);
+        }
+
+        if (src->output != OPENPIC_OUTPUT_INT) {
+            /* Edge-triggered interrupts shouldn't be used
+             * with non-INT delivery, but just in case,
+             * try to make it do something sane rather than
+             * cause an interrupt storm.  This is close to
+             * what you'd probably see happen in real hardware.
+             */
+            src->pending = 0;
+            openpic_update_irq(opp, n_IRQ);
         }
     }
-    openpic_update_irq(opp, n_IRQ);
 }
 
 static void openpic_reset(DeviceState *d)
@@ -934,6 +981,21 @@ static void openpic_cpu_write_internal(void *opaque, hwaddr addr,
         break;
     case 0x80: /* CTPR */
         dst->ctpr = val & 0x0000000F;
+
+        DPRINTF("%s: set CPU %d ctpr to %d, raised %d servicing %d\n",
+                __func__, idx, dst->ctpr, dst->raised.priority,
+                dst->servicing.priority);
+
+        if (dst->raised.priority <= dst->ctpr) {
+            DPRINTF("%s: Lower OpenPIC INT output cpu %d due to ctpr\n",
+                    __func__, idx);
+            qemu_irq_lower(dst->irqs[OPENPIC_OUTPUT_INT]);
+        } else if (dst->raised.priority > dst->servicing.priority) {
+            DPRINTF("%s: Raise OpenPIC INT output cpu %d irq %d\n",
+                    __func__, idx, dst->raised.next);
+            qemu_irq_raise(dst->irqs[OPENPIC_OUTPUT_INT]);
+        }
+
         break;
     case 0x90: /* WHOAMI */
         /* Read-only register */
@@ -995,22 +1057,21 @@ static uint32_t openpic_iack(OpenPICState *opp, IRQDest *dst, int cpu)
     src = &opp->src[irq];
     if (!(src->ivpr & IVPR_ACTIVITY_MASK) ||
             !(IVPR_PRIORITY(src->ivpr) > dst->ctpr)) {
-        /* - Spurious level-sensitive IRQ
-         * - Priorities has been changed
-         *   and the pending IRQ isn't allowed anymore
-         */
-        src->ivpr &= ~IVPR_ACTIVITY_MASK;
+        fprintf(stderr, "%s: bad raised IRQ %d ctpr %d ivpr 0x%08x\n",
+                __func__, irq, dst->ctpr, src->ivpr);
+        openpic_update_irq(opp, irq);
         retval = opp->spve;
     } else {
         /* IRQ enter servicing state */
         IRQ_setbit(&dst->servicing, irq);
         retval = IVPR_VECTOR(opp, src->ivpr);
     }
-    IRQ_resetbit(&dst->raised, irq);
+
     if (!src->level) {
         /* edge-sensitive IRQ */
         src->ivpr &= ~IVPR_ACTIVITY_MASK;
         src->pending = 0;
+        IRQ_resetbit(&dst->raised, irq);
     }
 
     if ((irq >= opp->irq_ipi0) &&  (irq < (opp->irq_ipi0 + MAX_IPI))) {
@@ -1208,6 +1269,8 @@ static void openpic_save(QEMUFile* f, void *opaque)
         qemu_put_sbe32s(f, &opp->dst[i].ctpr);
         openpic_save_IRQ_queue(f, &opp->dst[i].raised);
         openpic_save_IRQ_queue(f, &opp->dst[i].servicing);
+        qemu_put_buffer(f, (uint8_t *)&opp->dst[i].outputs_active,
+                        sizeof(opp->dst[i].outputs_active));
     }
 
     for (i = 0; i < MAX_TMR; i++) {
@@ -1264,6 +1327,8 @@ static int openpic_load(QEMUFile* f, void *opaque, int version_id)
         qemu_get_sbe32s(f, &opp->dst[i].ctpr);
         openpic_load_IRQ_queue(f, &opp->dst[i].raised);
         openpic_load_IRQ_queue(f, &opp->dst[i].servicing);
+        qemu_get_buffer(f, (uint8_t *)&opp->dst[i].outputs_active,
+                        sizeof(opp->dst[i].outputs_active));
     }
 
     for (i = 0; i < MAX_TMR; i++) {
Signature · 1 line
1.6.0.2
#26 lore raw

PATCH 26/31 kvm: Update kernel headers

In reply to Alexander Graf

Corresponding kvm.git hash: 18eb54cf4a

---
 linux-headers/asm-powerpc/epapr_hcalls.h |   98 ++++++++++++++++++++++++++++++
 linux-headers/asm-powerpc/kvm.h          |   86 ++++++++++++++++++++++++++
 linux-headers/asm-powerpc/kvm_para.h     |   13 ++--
 linux-headers/linux/kvm.h                |   21 +++++--
 linux-headers/linux/kvm_para.h           |    6 +-
 linux-headers/linux/vfio.h               |    6 +-
 linux-headers/linux/virtio_config.h      |    6 +-
 linux-headers/linux/virtio_ring.h        |    6 +-
 8 files changed, 219 insertions(+), 23 deletions(-)
 create mode 100644 linux-headers/asm-powerpc/epapr_hcalls.h
linux-headers/asm-powerpc/epapr_hcalls.h new file +98 -0
new file mode 100644
index 0000000..06f7247
@@ -0,0 +1,98 @@
+/*
+ * ePAPR hcall interface
+ *
+ * Copyright 2008-2011 Freescale Semiconductor, Inc.
+ *
+ * Author: Timur Tabi <[email protected]>
+ *
+ * This file is provided under a dual BSD/GPL license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Freescale Semiconductor nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _ASM_POWERPC_EPAPR_HCALLS_H
+#define _ASM_POWERPC_EPAPR_HCALLS_H
+
+#define EV_BYTE_CHANNEL_SEND		1
+#define EV_BYTE_CHANNEL_RECEIVE		2
+#define EV_BYTE_CHANNEL_POLL		3
+#define EV_INT_SET_CONFIG		4
+#define EV_INT_GET_CONFIG		5
+#define EV_INT_SET_MASK			6
+#define EV_INT_GET_MASK			7
+#define EV_INT_IACK			9
+#define EV_INT_EOI			10
+#define EV_INT_SEND_IPI			11
+#define EV_INT_SET_TASK_PRIORITY	12
+#define EV_INT_GET_TASK_PRIORITY	13
+#define EV_DOORBELL_SEND		14
+#define EV_MSGSND			15
+#define EV_IDLE				16
+
+/* vendor ID: epapr */
+#define EV_LOCAL_VENDOR_ID		0	/* for private use */
+#define EV_EPAPR_VENDOR_ID		1
+#define EV_FSL_VENDOR_ID		2	/* Freescale Semiconductor */
+#define EV_IBM_VENDOR_ID		3	/* IBM */
+#define EV_GHS_VENDOR_ID		4	/* Green Hills Software */
+#define EV_ENEA_VENDOR_ID		5	/* Enea */
+#define EV_WR_VENDOR_ID			6	/* Wind River Systems */
+#define EV_AMCC_VENDOR_ID		7	/* Applied Micro Circuits */
+#define EV_KVM_VENDOR_ID		42	/* KVM */
+
+/* The max number of bytes that a byte channel can send or receive per call */
+#define EV_BYTE_CHANNEL_MAX_BYTES	16
+
+
+#define _EV_HCALL_TOKEN(id, num) (((id) << 16) | (num))
+#define EV_HCALL_TOKEN(hcall_num) _EV_HCALL_TOKEN(EV_EPAPR_VENDOR_ID, hcall_num)
+
+/* epapr return codes */
+#define EV_SUCCESS		0
+#define EV_EPERM		1	/* Operation not permitted */
+#define EV_ENOENT		2	/*  Entry Not Found */
+#define EV_EIO			3	/* I/O error occured */
+#define EV_EAGAIN		4	/* The operation had insufficient
+					 * resources to complete and should be
+					 * retried
+					 */
+#define EV_ENOMEM		5	/* There was insufficient memory to
+					 * complete the operation */
+#define EV_EFAULT		6	/* Bad guest address */
+#define EV_ENODEV		7	/* No such device */
+#define EV_EINVAL		8	/* An argument supplied to the hcall
+					   was out of range or invalid */
+#define EV_INTERNAL		9	/* An internal error occured */
+#define EV_CONFIG		10	/* A configuration error was detected */
+#define EV_INVALID_STATE	11	/* The object is in an invalid state */
+#define EV_UNIMPLEMENTED	12	/* Unimplemented hypercall */
+#define EV_BUFFER_OVERFLOW	13	/* Caller-supplied buffer too small */
+
+#endif /* _ASM_POWERPC_EPAPR_HCALLS_H */
linux-headers/asm-powerpc/kvm.h +86 -0

98 lines not on this page · raw message

linux-headers/asm-powerpc/kvm_para.h +7 -6
index 5e04383..7e64f57 100644
@@ -17,8 +17,8 @@
  * Authors: Hollis Blanchard <[email protected]>
  */
 
-#ifndef _UAPI__POWERPC_KVM_PARA_H__
-#define _UAPI__POWERPC_KVM_PARA_H__
+#ifndef __POWERPC_KVM_PARA_H__
+#define __POWERPC_KVM_PARA_H__
 
 #include <linux/types.h>
 
@@ -75,9 +75,10 @@ struct kvm_vcpu_arch_shared {
 };
 
 #define KVM_SC_MAGIC_R0		0x4b564d21 /* "KVM!" */
-#define HC_VENDOR_KVM		(42 << 16)
-#define HC_EV_SUCCESS		0
-#define HC_EV_UNIMPLEMENTED	12
+
+#define KVM_HCALL_TOKEN(num)     _EV_HCALL_TOKEN(EV_KVM_VENDOR_ID, num)
+
+#include <asm/epapr_hcalls.h>
 
 #define KVM_FEATURE_MAGIC_PAGE	1
 
@@ -87,4 +88,4 @@ struct kvm_vcpu_arch_shared {
 #define KVM_MAGIC_FEAT_MAS0_TO_SPRG7	(1 << 1)
 
 
-#endif /* _UAPI__POWERPC_KVM_PARA_H__ */
+#endif /* __POWERPC_KVM_PARA_H__ */
linux-headers/linux/kvm.h +16 -5
index 81d2feb..bfdbf4d 100644
@@ -167,10 +167,15 @@ struct kvm_pit_config {
 #define KVM_EXIT_OSI              18
 #define KVM_EXIT_PAPR_HCALL	  19
 #define KVM_EXIT_S390_UCONTROL	  20
+#define KVM_EXIT_WATCHDOG         21
 
 /* For KVM_EXIT_INTERNAL_ERROR */
-#define KVM_INTERNAL_ERROR_EMULATION 1
-#define KVM_INTERNAL_ERROR_SIMUL_EX 2
+/* Emulate instruction failed. */
+#define KVM_INTERNAL_ERROR_EMULATION	1
+/* Encounter unexpected simultaneous exceptions. */
+#define KVM_INTERNAL_ERROR_SIMUL_EX	2
+/* Encounter unexpected vm-exit due to delivery event. */
+#define KVM_INTERNAL_ERROR_DELIVERY_EV	3
 
 /* for KVM_RUN, returned by mmap(vcpu_fd, offset=0) */
 struct kvm_run {
@@ -477,6 +482,8 @@ struct kvm_ppc_smmu_info {
 	struct kvm_ppc_one_seg_page_size sps[KVM_PPC_PAGE_SIZES_MAX_SZ];
 };
 
+#define KVM_PPC_PVINFO_FLAGS_EV_IDLE   (1<<0)
+
 #define KVMIO 0xAE
 
 /* machine type bits, to be used as argument to KVM_CREATE_VM */
@@ -626,6 +633,8 @@ struct kvm_ppc_smmu_info {
 #define KVM_CAP_READONLY_MEM 81
 #endif
 #define KVM_CAP_IRQFD_RESAMPLE 82
+#define KVM_CAP_PPC_BOOKE_WATCHDOG 83
+#define KVM_CAP_PPC_HTAB_FD 84
 
 #ifdef KVM_CAP_IRQ_ROUTING
 
@@ -848,6 +857,11 @@ struct kvm_s390_ucas_mapping {
 #define KVM_PPC_GET_SMMU_INFO	  _IOR(KVMIO,  0xa6, struct kvm_ppc_smmu_info)
 /* Available with KVM_CAP_PPC_ALLOC_HTAB */
 #define KVM_PPC_ALLOCATE_HTAB	  _IOWR(KVMIO, 0xa7, __u32)
+#define KVM_CREATE_SPAPR_TCE	  _IOW(KVMIO,  0xa8, struct kvm_create_spapr_tce)
+/* Available with KVM_CAP_RMA */
+#define KVM_ALLOCATE_RMA	  _IOR(KVMIO,  0xa9, struct kvm_allocate_rma)
+/* Available with KVM_CAP_PPC_HTAB_FD */
+#define KVM_PPC_GET_HTAB_FD	  _IOW(KVMIO,  0xaa, struct kvm_get_htab_fd)
 
 /*
  * ioctls for vcpu fds
@@ -911,9 +925,6 @@ struct kvm_s390_ucas_mapping {
 /* Available with KVM_CAP_XCRS */
 #define KVM_GET_XCRS		  _IOR(KVMIO,  0xa6, struct kvm_xcrs)
 #define KVM_SET_XCRS		  _IOW(KVMIO,  0xa7, struct kvm_xcrs)
-#define KVM_CREATE_SPAPR_TCE	  _IOW(KVMIO,  0xa8, struct kvm_create_spapr_tce)
-/* Available with KVM_CAP_RMA */
-#define KVM_ALLOCATE_RMA	  _IOR(KVMIO,  0xa9, struct kvm_allocate_rma)
 /* Available with KVM_CAP_SW_TLB */
 #define KVM_DIRTY_TLB		  _IOW(KVMIO,  0xaa, struct kvm_dirty_tlb)
 /* Available with KVM_CAP_ONE_REG */
linux-headers/linux/kvm_para.h +3 -3
index cea2c5c..7bdcf93 100644
@@ -1,5 +1,5 @@
-#ifndef _UAPI__LINUX_KVM_PARA_H
-#define _UAPI__LINUX_KVM_PARA_H
+#ifndef __LINUX_KVM_PARA_H
+#define __LINUX_KVM_PARA_H
 
 /*
  * This header file provides a method for making a hypercall to the host
@@ -25,4 +25,4 @@
  */
 #include <asm/kvm_para.h>
 
-#endif /* _UAPI__LINUX_KVM_PARA_H */
+#endif /* __LINUX_KVM_PARA_H */
linux-headers/linux/vfio.h +3 -3
index 4758d1b..f787b72 100644
@@ -8,8 +8,8 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
-#ifndef _UAPIVFIO_H
-#define _UAPIVFIO_H
+#ifndef VFIO_H
+#define VFIO_H
 
 #include <linux/types.h>
 #include <linux/ioctl.h>
@@ -365,4 +365,4 @@ struct vfio_iommu_type1_dma_unmap {
 
 #define VFIO_IOMMU_UNMAP_DMA _IO(VFIO_TYPE, VFIO_BASE + 14)
 
-#endif /* _UAPIVFIO_H */
+#endif /* VFIO_H */
linux-headers/linux/virtio_config.h +3 -3
index b7cda39..4f51d8f 100644
@@ -1,5 +1,5 @@
-#ifndef _UAPI_LINUX_VIRTIO_CONFIG_H
-#define _UAPI_LINUX_VIRTIO_CONFIG_H
+#ifndef _LINUX_VIRTIO_CONFIG_H
+#define _LINUX_VIRTIO_CONFIG_H
 /* This header, excluding the #ifdef __KERNEL__ part, is BSD licensed so
  * anyone can use the definitions to implement compatible drivers/servers.
  *
@@ -51,4 +51,4 @@
  * suppressed them? */
 #define VIRTIO_F_NOTIFY_ON_EMPTY	24
 
-#endif /* _UAPI_LINUX_VIRTIO_CONFIG_H */
+#endif /* _LINUX_VIRTIO_CONFIG_H */
linux-headers/linux/virtio_ring.h +3 -3
index 921694a..1b333e2 100644
@@ -1,5 +1,5 @@
-#ifndef _UAPI_LINUX_VIRTIO_RING_H
-#define _UAPI_LINUX_VIRTIO_RING_H
+#ifndef _LINUX_VIRTIO_RING_H
+#define _LINUX_VIRTIO_RING_H
 /* An interface for efficient virtio implementation, currently for use by KVM
  * and lguest, but hopefully others soon.  Do NOT change this since it will
  * break existing servers and clients.
@@ -160,4 +160,4 @@ static __inline__ int vring_need_event(__u16 event_idx, __u16 new_idx, __u16 old
 	return (__u16)(new_idx - event_idx - 1) < (__u16)(new_idx - old);
 }
 
-#endif /* _UAPI_LINUX_VIRTIO_RING_H */
+#endif /* _LINUX_VIRTIO_RING_H */
Signature · 1 line
1.6.0.2
#27 lore raw

PATCH 27/31 PPC: KVM: set has-idle in guest device tree

In reply to Alexander Graf

From: Stuart Yoder <[email protected]>

On e500mc, the platform doesn't provide a way for the CPU to go idle.

To still not uselessly burn CPU time, expose an idle hypercall to the guest if kvm supports it.

[agraf: adjust for current code base, add patch description]
---
 hw/ppc/e500.c        |    4 ++++
 target-ppc/kvm.c     |   32 ++++++++++++++++++++++++++------
 target-ppc/kvm_ppc.h |    1 +
 3 files changed, 31 insertions(+), 6 deletions(-)
hw/ppc/e500.c +4 -0
index b262f31..5d70618 100644
@@ -225,6 +225,10 @@ static int ppce500_load_device_tree(CPUPPCState *env,
         kvmppc_get_hypercall(env, hypercall, sizeof(hypercall));
         qemu_devtree_setprop(fdt, "/hypervisor", "hcall-instructions",
                              hypercall, sizeof(hypercall));
+        /* if KVM supports the idle hcall, set property indicating this */
+        if (kvmppc_get_hasidle(env)) {
+            qemu_devtree_setprop(fdt, "/hypervisor", "has-idle", NULL, 0);
+        }
     }
 
     /* Create CPU nodes */
target-ppc/kvm.c +26 -6
index 436ca47..9fe949f 100644
@@ -989,18 +989,38 @@ uint32_t kvmppc_get_dfp(void)
     return kvmppc_read_int_cpu_dt("ibm,dfp");
 }
 
+static int kvmppc_get_pvinfo(CPUPPCState *env, struct kvm_ppc_pvinfo *pvinfo)
+ {
+     PowerPCCPU *cpu = ppc_env_get_cpu(env);
+     CPUState *cs = CPU(cpu);
+
+    if (kvm_check_extension(cs->kvm_state, KVM_CAP_PPC_GET_PVINFO) &&
+        !kvm_vm_ioctl(cs->kvm_state, KVM_PPC_GET_PVINFO, pvinfo)) {
+        return 0;
+    }
+
+    return 1;
+}
+
+int kvmppc_get_hasidle(CPUPPCState *env)
+{
+    struct kvm_ppc_pvinfo pvinfo;
+
+    if (!kvmppc_get_pvinfo(env, &pvinfo) &&
+        (pvinfo.flags & KVM_PPC_PVINFO_FLAGS_EV_IDLE)) {
+        return 1;
+    }
+
+    return 0;
+}
+
 int kvmppc_get_hypercall(CPUPPCState *env, uint8_t *buf, int buf_len)
 {
-    PowerPCCPU *cpu = ppc_env_get_cpu(env);
-    CPUState *cs = CPU(cpu);
     uint32_t *hc = (uint32_t*)buf;
-
     struct kvm_ppc_pvinfo pvinfo;
 
-    if (kvm_check_extension(cs->kvm_state, KVM_CAP_PPC_GET_PVINFO) &&
-        !kvm_vm_ioctl(cs->kvm_state, KVM_PPC_GET_PVINFO, &pvinfo)) {
+    if (!kvmppc_get_pvinfo(env, &pvinfo)) {
         memcpy(buf, pvinfo.hcall, buf_len);
-
         return 0;
     }
 
target-ppc/kvm_ppc.h +1 -0
index 31eb9e6..dfb4ecf 100644
@@ -19,6 +19,7 @@ uint32_t kvmppc_get_tbfreq(void);
 uint64_t kvmppc_get_clockfreq(void);
 uint32_t kvmppc_get_vmx(void);
 uint32_t kvmppc_get_dfp(void);
+int kvmppc_get_hasidle(CPUPPCState *env);
 int kvmppc_get_hypercall(CPUPPCState *env, uint8_t *buf, int buf_len);
 int kvmppc_set_interrupt(PowerPCCPU *cpu, int irq, int level);
 void kvmppc_set_papr(PowerPCCPU *cpu);
Signature · 1 line
1.6.0.2
#28 lore raw

PATCH 28/31 PPC: Bring EPR support closer to reality

In reply to Alexander Graf

We already used to support the external proxy facility of FSL MPICs, but only implemented it halfway correctly.

This patch adds support for

* dynamic enablement of the EPR facility
* interrupt acknowledgement only when the interrupt is delivered

This way the implementation now is closer to real hardware.

---
 hw/openpic.c                |   21 +++++++++++++++++++++
 hw/ppc/e500.c               |    4 ++--
 target-ppc/Makefile.objs    |    1 -
 target-ppc/cpu.h            |    4 +++-
 target-ppc/excp_helper.c    |    4 ++++
 target-ppc/helper.h         |    1 -
 target-ppc/mpic_helper.c    |   35 -----------------------------------
 target-ppc/translate_init.c |    7 +------
 8 files changed, 31 insertions(+), 46 deletions(-)
 delete mode 100644 target-ppc/mpic_helper.c
hw/openpic.c +21 -0
index e773d68..3b20a39 100644
@@ -131,6 +131,9 @@ static const int debug_openpic = 0;
 #define VIR_GENERIC      0x00000000 /* Generic Vendor ID */
 
 #define GCR_RESET        0x80000000
+#define GCR_MODE_PASS    0x00000000
+#define GCR_MODE_MIXED   0x20000000
+#define GCR_MODE_PROXY   0x60000000
 
 #define TBCR_CI           0x80000000 /* count inhibit */
 #define TCCR_TOG          0x80000000 /* toggles when decrement to zero */
@@ -233,6 +236,7 @@ typedef struct OpenPICState {
     uint32_t ivpr_reset;
     uint32_t idr_reset;
     uint32_t brr1;
+    uint32_t mpic_mode_mask;
 
     /* Sub-regions */
     MemoryRegion sub_io_mem[5];
@@ -667,6 +671,20 @@ static void openpic_gbl_write(void *opaque, hwaddr addr, uint64_t val,
     case 0x1020: /* GCR */
         if (val & GCR_RESET) {
             openpic_reset(&opp->busdev.qdev);
+        } else if (opp->mpic_mode_mask) {
+            CPUArchState *env;
+            int mpic_proxy = 0;
+
+            opp->gcr &= ~opp->mpic_mode_mask;
+            opp->gcr |= val & opp->mpic_mode_mask;
+
+            /* Set external proxy mode */
+            if ((val & opp->mpic_mode_mask) == GCR_MODE_PROXY) {
+                mpic_proxy = 1;
+            }
+            for (env = first_cpu; env != NULL; env = env->next_cpu) {
+                env->mpic_proxy = mpic_proxy;
+            }
         }
         break;
     case 0x1080: /* VIR */
@@ -1407,6 +1425,9 @@ static int openpic_init(SysBusDevice *dev)
         opp->irq_tim0 = FSL_MPIC_20_TMR_IRQ;
         opp->irq_msi = FSL_MPIC_20_MSI_IRQ;
         opp->brr1 = FSL_BRR1_IPID | FSL_BRR1_IPMJ | FSL_BRR1_IPMN;
+        /* XXX really only available as of MPIC 4.0 */
+        opp->mpic_mode_mask = GCR_MODE_PROXY;
+
         msi_supported = true;
         list = list_be;
 
hw/ppc/e500.c +2 -2
index 5d70618..3a9e1c7 100644
@@ -497,8 +497,8 @@ void ppce500_init(PPCE500Params *params)
         irqs[i][OPENPIC_OUTPUT_INT] = input[PPCE500_INPUT_INT];
         irqs[i][OPENPIC_OUTPUT_CINT] = input[PPCE500_INPUT_CINT];
         env->spr[SPR_BOOKE_PIR] = env->cpu_index = i;
-        env->mpic_cpu_base = MPC8544_CCSRBAR_BASE +
-                              MPC8544_MPIC_REGS_OFFSET + 0x20000;
+        env->mpic_iack = MPC8544_CCSRBAR_BASE +
+                         MPC8544_MPIC_REGS_OFFSET + 0x200A0;
 
         ppc_booke_timers_init(cpu, 400000000, PPC_TIMER_E500);
 
target-ppc/Makefile.objs +0 -1
index 237a0ed..6c11ef8 100644
@@ -9,4 +9,3 @@ obj-y += mmu_helper.o
 obj-y += timebase_helper.o
 obj-y += misc_helper.o
 obj-y += mem_helper.o
-obj-y += mpic_helper.o
target-ppc/cpu.h +3 -1
index e88ebe0..dc5145b 100644
@@ -1067,7 +1067,9 @@ struct CPUPPCState {
     target_ulong ivor_mask;
     target_ulong ivpr_mask;
     target_ulong hreset_vector;
-    hwaddr mpic_cpu_base;
+    hwaddr mpic_iack;
+    /* true when the external proxy facility mode is enabled */
+    bool mpic_proxy;
 #endif
 
     /* Those resources are used only during code translation */
target-ppc/excp_helper.c +4 -0
index 41037a7..0a1ac86 100644
@@ -178,6 +178,10 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp)
         if (lpes0 == 1) {
             new_msr |= (target_ulong)MSR_HVB;
         }
+        if (env->mpic_proxy) {
+            /* IACK the IRQ on delivery */
+            env->spr[SPR_BOOKE_EPR] = ldl_phys(env->mpic_iack);
+        }
         goto store_next;
     case POWERPC_EXCP_ALIGN:     /* Alignment exception                      */
         if (lpes1 == 0) {
target-ppc/helper.h +0 -1
index d2e9a55..83139d5 100644
@@ -405,7 +405,6 @@ DEF_HELPER_2(store_40x_dbcr0, void, env, tl)
 DEF_HELPER_2(store_40x_sler, void, env, tl)
 DEF_HELPER_2(store_booke_tcr, void, env, tl)
 DEF_HELPER_2(store_booke_tsr, void, env, tl)
-DEF_HELPER_1(load_epr, tl, env)
 DEF_HELPER_3(store_ibatl, void, env, i32, tl)
 DEF_HELPER_3(store_ibatu, void, env, i32, tl)
 DEF_HELPER_3(store_dbatl, void, env, i32, tl)
target-ppc/mpic_helper.c deleted +0 -35
deleted file mode 100644
index 2c6a4d3..0000000
@@ -1,35 +0,0 @@
-/*
- *  PowerPC emulation helpers for QEMU.
- *
- *  Copyright (c) 2003-2007 Jocelyn Mayer
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, see <http://www.gnu.org/licenses/>.
- */
-#include "cpu.h"
-#include "helper.h"
-
-/*****************************************************************************/
-/* SPR accesses */
-
-#if !defined(CONFIG_USER_ONLY)
-/*
- * This is an ugly helper for EPR, which is basically the same as accessing
- * the IACK (PIAC) register on the MPIC. Because we model the MPIC as a device
- * that can only talk to the CPU through MMIO, let's access it that way!
- */
-target_ulong helper_load_epr(CPUPPCState *env)
-{
-    return ldl_phys(env->mpic_cpu_base + 0xA0);
-}
-#endif
target-ppc/translate_init.c +1 -6
index 42ed748..e2eeb87 100644
@@ -4493,11 +4493,6 @@ static void spr_read_mas73(void *opaque, int gprn, int sprn)
     tcg_temp_free(mas7);
 }
 
-static void spr_load_epr(void *opaque, int gprn, int sprn)
-{
-    gen_helper_load_epr(cpu_gpr[gprn], cpu_env);
-}
-
 #endif
 
 enum fsl_e500_version {
@@ -4656,7 +4651,7 @@ static void init_proc_e500 (CPUPPCState *env, int version)
                  0x00000000);
     spr_register(env, SPR_BOOKE_EPR, "EPR",
                  SPR_NOACCESS, SPR_NOACCESS,
-                 &spr_load_epr, SPR_NOACCESS,
+                 &spr_read_generic, SPR_NOACCESS,
                  0x00000000);
     /* XXX better abstract into Emb.xxx features */
     if (version == fsl_e5500) {
Signature · 1 line
1.6.0.2
#29 lore raw

PATCH 29/31 target-ppc: Slim conversion of model definitions to QOM subclasses

In reply to Alexander Graf

From: Andreas Färber <[email protected]>

Since the model list is highly macrofied, keep ppc_def_t for now and save a pointer to it in PowerPCCPUClass. This results in a flat list of subclasses including aliases, to be refined later.

Move cpu_ppc_init() to translate_init.c and drop helper.c. Long-term the idea is to turn translate_init.c into a standalone cpu.c.

Inline cpu_ppc_usable() into type registration.

Split cpu_ppc_register() in two by code movement into the initfn and by turning the remaining part into a realizefn.
Move qemu_init_vcpu() call into the new realizefn and adapt create_ppc_opcodes() to return an Error.

Change ppc_find_by_pvr() -> ppc_cpu_class_by_pvr(). Change ppc_find_by_name() -> ppc_cpu_class_by_name().

Turn -cpu host into its own subclass. This requires to move the kvm_enabled() check in ppc_cpu_class_by_name() to avoid the class being found via the normal name lookup in the !kvm_enabled() case. Turn kvmppc_host_cpu_def() into the class_init and add an initfn that asserts KVM is in fact enabled.

Implement -cpu ? and the QMP equivalent in terms of subclasses. This newly exposes -cpu host to the user, ordered last for -cpu ?.

---
 target-ppc/Makefile.objs    |    3 +-
 target-ppc/cpu-qom.h        |    5 +
 target-ppc/cpu.h            |    4 -
 target-ppc/helper.c         |   50 ------
 target-ppc/kvm.c            |   37 ++++-
 target-ppc/kvm_ppc.h        |    8 +-
 target-ppc/translate_init.c |  345 +++++++++++++++++++++++++++++-------------
 7 files changed, 276 insertions(+), 176 deletions(-)
 delete mode 100644 target-ppc/helper.c
target-ppc/Makefile.objs +1 -2
index 6c11ef8..a028dcd 100644
@@ -1,7 +1,6 @@
-obj-y += translate.o helper.o
+obj-y += translate.o
 obj-$(CONFIG_SOFTMMU) += machine.o
 obj-$(CONFIG_KVM) += kvm.o kvm_ppc.o
-obj-y += helper.o
 obj-y += excp_helper.o
 obj-y += fpu_helper.o
 obj-y += int_helper.o
target-ppc/cpu-qom.h +5 -0
index fb6b5a4..b338f8f 100644
@@ -50,6 +50,9 @@ typedef struct PowerPCCPUClass {
     /*< public >*/
 
     void (*parent_reset)(CPUState *cpu);
+
+    /* TODO inline fields here */
+    ppc_def_t *info;
 } PowerPCCPUClass;
 
 /**
@@ -73,5 +76,7 @@ static inline PowerPCCPU *ppc_env_get_cpu(CPUPPCState *env)
 
 #define ENV_GET_CPU(e) CPU(ppc_env_get_cpu(e))
 
+PowerPCCPUClass *ppc_cpu_class_by_pvr(uint32_t pvr);
+
 
 #endif
target-ppc/cpu.h +0 -4
index dc5145b..953146e 100644
@@ -1158,10 +1158,6 @@ void ppc_store_msr (CPUPPCState *env, target_ulong value);
 
 void ppc_cpu_list (FILE *f, fprintf_function cpu_fprintf);
 
-const ppc_def_t *ppc_find_by_pvr(uint32_t pvr);
-const ppc_def_t *cpu_ppc_find_by_name (const char *name);
-int cpu_ppc_register_internal (CPUPPCState *env, const ppc_def_t *def);
-
 /* Time-base and decrementer management */
 #ifndef NO_CPU_IO_DEFS
 uint64_t cpu_ppc_load_tbl (CPUPPCState *env);
target-ppc/helper.c deleted +0 -50

50 lines not on this page · raw message

target-ppc/kvm.c +30 -7
index 9fe949f..ce7d69b 100644
@@ -1230,18 +1230,29 @@ static void alter_insns(uint64_t *word, uint64_t flags, bool on)
     }
 }
 
-const ppc_def_t *kvmppc_host_cpu_def(void)
+static void kvmppc_host_cpu_initfn(Object *obj)
 {
+    assert(kvm_enabled());
+}
+
+static void kvmppc_host_cpu_class_init(ObjectClass *oc, void *data)
+{
+    PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
     uint32_t host_pvr = mfpvr();
-    const ppc_def_t *base_spec;
+    PowerPCCPUClass *pvr_pcc;
     ppc_def_t *spec;
     uint32_t vmx = kvmppc_get_vmx();
     uint32_t dfp = kvmppc_get_dfp();
 
-    base_spec = ppc_find_by_pvr(host_pvr);
-
     spec = g_malloc0(sizeof(*spec));
-    memcpy(spec, base_spec, sizeof(*spec));
+
+    pvr_pcc = ppc_cpu_class_by_pvr(host_pvr);
+    if (pvr_pcc != NULL) {
+        memcpy(spec, pvr_pcc->info, sizeof(*spec));
+    }
+    pcc->info = spec;
+    /* Override the display name for -cpu ? and QMP */
+    pcc->info->name = "host";
 
     /* Now fix up the spec with information we can query from the host */
 
@@ -1254,8 +1265,6 @@ const ppc_def_t *kvmppc_host_cpu_def(void)
         /* Only override when we know what the host supports */
         alter_insns(&spec->insns_flags2, PPC2_DFP, dfp);
     }
-
-    return spec;
 }
 
 int kvmppc_fixup_cpu(CPUPPCState *env)
@@ -1285,3 +1294,17 @@ int kvm_arch_on_sigbus(int code, void *addr)
 {
     return 1;
 }
+
+static const TypeInfo kvm_host_cpu_type_info = {
+    .name = TYPE_HOST_POWERPC_CPU,
+    .parent = TYPE_POWERPC_CPU,
+    .instance_init = kvmppc_host_cpu_initfn,
+    .class_init = kvmppc_host_cpu_class_init,
+};
+
+static void kvm_ppc_register_types(void)
+{
+    type_register_static(&kvm_host_cpu_type_info);
+}
+
+type_init(kvm_ppc_register_types)
target-ppc/kvm_ppc.h +2 -6
index dfb4ecf..a57ec6f 100644
@@ -11,6 +11,8 @@
 
 #include "exec/memory.h"
 
+#define TYPE_HOST_POWERPC_CPU "host-" TYPE_POWERPC_CPU
+
 void kvmppc_init(void);
 
 #ifdef CONFIG_KVM
@@ -31,7 +33,6 @@ int kvmppc_remove_spapr_tce(void *table, int pfd, uint32_t window_size);
 int kvmppc_reset_htab(int shift_hint);
 uint64_t kvmppc_rma_size(uint64_t current_size, unsigned int hash_shift);
 #endif /* !CONFIG_USER_ONLY */
-const ppc_def_t *kvmppc_host_cpu_def(void);
 int kvmppc_fixup_cpu(CPUPPCState *env);
 
 #else
@@ -116,11 +117,6 @@ static inline int kvmppc_update_sdr1(CPUPPCState *env)
 
 #endif /* !CONFIG_USER_ONLY */
 
-static inline const ppc_def_t *kvmppc_host_cpu_def(void)
-{
-    return NULL;
-}
-
 static inline int kvmppc_fixup_cpu(CPUPPCState *env)
 {
     return -1;
target-ppc/translate_init.c +238 -107

459 lines not on this page · raw message

Signature · 1 line
1.6.0.2
#30 lore raw

PATCH 30/31 target-ppc: Error out for -cpu host on unknown PVR

In reply to Alexander Graf

From: Andreas Färber <[email protected]>

Previously we silently exited, with subclasses we got an opcode warning. Instead, explicitly tell the user what's wrong.

An indication for this is -cpu ? showing "host" with an all-zero PVR.

---
 target-ppc/kvm.c |    8 ++++++++
 1 files changed, 8 insertions(+), 0 deletions(-)
target-ppc/kvm.c +8 -0
index ce7d69b..4846acf 100644
@@ -1232,7 +1232,15 @@ static void alter_insns(uint64_t *word, uint64_t flags, bool on)
 
 static void kvmppc_host_cpu_initfn(Object *obj)
 {
+    PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(obj);
+
     assert(kvm_enabled());
+
+    if (pcc->info->pvr != mfpvr()) {
+        fprintf(stderr, "Your host CPU is unsupported.\n"
+                "Please choose a supported model instead, see -cpu ?.\n");
+        exit(1);
+    }
 }
 
 static void kvmppc_host_cpu_class_init(ObjectClass *oc, void *data)
Signature · 1 line
1.6.0.2
#31 lore raw

PATCH 31/31 PPC: linux-user: Calculate context pointer explicitly

In reply to Alexander Graf

From: Samuel Seay <[email protected]>

Peter Maydell recommended the change to be more proper. The result was tested and shows coming up with the same proper value.

[agraf: change subject]
---
 linux-user/signal.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)
linux-user/signal.c +1 -1
index c43b8ac..bb08a93 100644
@@ -4614,7 +4614,7 @@ static void setup_frame(int sig, struct target_sigaction *ka,
     /* Set up registers for signal handler.  */
     env->gpr[1] = newsp;
     env->gpr[3] = signal;
-    env->gpr[4] = (target_ulong) h2g(sc);
+    env->gpr[4] = frame_addr + offsetof(struct target_sigframe, sctx);
     env->nip = (target_ulong) ka->_sa_handler;
     /* Signal handlers are entered in big-endian mode.  */
     env->msr &= ~MSR_LE;
Signature · 1 line
1.6.0.2
#32 lore raw
In reply to Alexander Graf

Am 07.01.2013 16:38, schrieb Alexander Graf:

Quoted 3 lines

Hi Blue / Aurelien,

This is my current patch queue for ppc. Please pull.

Breaks on x86_64:

CC ppc-softmmu/hw/ppc/e500.o
/home/andreas/QEMU/qemu-ppc/hw/ppc/e500.c: In function ‘ppce500_load_device_tree’:
/home/andreas/QEMU/qemu-ppc/hw/ppc/e500.c:229:9: error: implicit declaration of function ‘kvmppc_get_hasidle’ [-Werror=implicit-function-declaration] /home/andreas/QEMU/qemu-ppc/hw/ppc/e500.c:229:9: error: nested extern declaration of ‘kvmppc_get_hasidle’ [-Werror=nested-externs]
cc1: all warnings being treated as errors
make[1]: *** [hw/ppc/e500.o] Fehler 1
make: *** [subdir-ppc-softmmu] Fehler 2

Lacking a static inline version of kvmppc_get_hasidle() in kvm_ppc.h.

Andreas

Signature · 2 lines
SUSE LINUX Products GmbH, Maxfeldstr. 5, 90409 Nürnberg, Germany
GF: Jeff Hawn, Jennifer Guild, Felix Imendörffer; HRB 16746 AG Nürnberg
#33 lore raw
Quoted 19 lines · Andreas Färber

Am 07.01.2013 16:38, schrieb Alexander Graf:

Quoted 3 lines

Hi Blue / Aurelien,

This is my current patch queue for ppc. Please pull.

Breaks on x86_64:

CC ppc-softmmu/hw/ppc/e500.o
/home/andreas/QEMU/qemu-ppc/hw/ppc/e500.c: In function ‘ppce500_load_device_tree’:
/home/andreas/QEMU/qemu-ppc/hw/ppc/e500.c:229:9: error: implicit declaration of function ‘kvmppc_get_hasidle’ [-Werror=implicit-function-declaration] /home/andreas/QEMU/qemu-ppc/hw/ppc/e500.c:229:9: error: nested extern declaration of ‘kvmppc_get_hasidle’ [-Werror=nested-externs]
cc1: all warnings being treated as errors
make[1]: *** [hw/ppc/e500.o] Fehler 1
make: *** [subdir-ppc-softmmu] Fehler 2

Quoted 1 line

Lacking a static inline version of kvmppc_get_hasidle() in kvm_ppc.h.

Sigh. I wonder why our buildbots didn't fetch this one.

Fixed it up manually in both ppc-next and ppc-for-upstream, so the pull request is still valid.

Alex

#34 lore raw
Quoted 22 lines · Alexander Graf
Quoted 19 lines · Andreas Färber

Am 07.01.2013 16:38, schrieb Alexander Graf:

Quoted 3 lines

Hi Blue / Aurelien,

This is my current patch queue for ppc. Please pull.

Breaks on x86_64:

CC ppc-softmmu/hw/ppc/e500.o
/home/andreas/QEMU/qemu-ppc/hw/ppc/e500.c: In function ‘ppce500_load_device_tree’:
/home/andreas/QEMU/qemu-ppc/hw/ppc/e500.c:229:9: error: implicit declaration of function ‘kvmppc_get_hasidle’ [-Werror=implicit-function-declaration] /home/andreas/QEMU/qemu-ppc/hw/ppc/e500.c:229:9: error: nested extern declaration of ‘kvmppc_get_hasidle’ [-Werror=nested-externs]
cc1: all warnings being treated as errors
make[1]: *** [hw/ppc/e500.o] Fehler 1
make: *** [subdir-ppc-softmmu] Fehler 2

Quoted 5 lines
Quoted 1 line

Lacking a static inline version of kvmppc_get_hasidle() in kvm_ppc.h.

Sigh. I wonder why our buildbots didn't fetch this one.

Fixed it up manually in both ppc-next and ppc-for-upstream, so the pull request is still valid.

e500.o is only built when CONFIG_FDT is defined.

agraf: "zypper search libfdt" on qemu-ppc.opensuse.org turns up no packages. Any ideas where to get the packages from?

Stefan

#35 lore raw

Am 08.01.2013 um 09:54 schrieb Stefan Hajnoczi <[email protected]>:

Quoted 25 lines · Alexander Graf
Quoted 24 lines · Andreas Färber
Quoted 21 lines

Am 07.01.2013 16:38, schrieb Alexander Graf:

Quoted 3 lines

Hi Blue / Aurelien,

This is my current patch queue for ppc. Please pull.

Breaks on x86_64:

CC ppc-softmmu/hw/ppc/e500.o
/home/andreas/QEMU/qemu-ppc/hw/ppc/e500.c: In function ‘ppce500_load_device_tree’:
/home/andreas/QEMU/qemu-ppc/hw/ppc/e500.c:229:9: error: implicit declaration of function ‘kvmppc_get_hasidle’ [-Werror=implicit-function-declaration] /home/andreas/QEMU/qemu-ppc/hw/ppc/e500.c:229:9: error: nested extern declaration of ‘kvmppc_get_hasidle’ [-Werror=nested-externs]
cc1: all warnings being treated as errors
make[1]: *** [hw/ppc/e500.o] Fehler 1
make: *** [subdir-ppc-softmmu] Fehler 2

Lacking a static inline version of kvmppc_get_hasidle() in kvm_ppc.h.

Quoted 8 lines
Quoted 3 lines

Sigh. I wonder why our buildbots didn't fetch this one.

Fixed it up manually in both ppc-next and ppc-for-upstream, so the pull request is still valid.

e500.o is only built when CONFIG_FDT is defined.

agraf: "zypper search libfdt" on qemu-ppc.opensuse.org turns up no packages. Any ideas where to get the packages from?

I can install them on the ppc box, but the important build case would be against x86, no?

Alex

Quoted 2 lines

Stefan

#37 lore raw
In reply to Alexander Graf
Quoted 22 lines · Alexander Graf
Quoted 19 lines · Andreas Färber

Am 07.01.2013 16:38, schrieb Alexander Graf:

Quoted 3 lines

Hi Blue / Aurelien,

This is my current patch queue for ppc. Please pull.

Breaks on x86_64:

CC ppc-softmmu/hw/ppc/e500.o
/home/andreas/QEMU/qemu-ppc/hw/ppc/e500.c: In function ‘ppce500_load_device_tree’:
/home/andreas/QEMU/qemu-ppc/hw/ppc/e500.c:229:9: error: implicit declaration of function ‘kvmppc_get_hasidle’ [-Werror=implicit-function-declaration] /home/andreas/QEMU/qemu-ppc/hw/ppc/e500.c:229:9: error: nested extern declaration of ‘kvmppc_get_hasidle’ [-Werror=nested-externs]
cc1: all warnings being treated as errors
make[1]: *** [hw/ppc/e500.o] Fehler 1
make: *** [subdir-ppc-softmmu] Fehler 2

Quoted 5 lines
Quoted 1 line

Lacking a static inline version of kvmppc_get_hasidle() in kvm_ppc.h.

Sigh. I wonder why our buildbots didn't fetch this one.

Fixed it up manually in both ppc-next and ppc-for-upstream, so the pull request is still valid.

Thanks, pulled.

Quoted 4 lines

Alex