* [Qemu-devel] [PATCH 01/31] openpic: symbolicize some magic numbers
2013-01-07 15:38 [Qemu-devel] [PULL 00/31] ppc patch queue 2013-01-07 Alexander Graf
@ 2013-01-07 15:38 ` Alexander Graf
2013-01-07 15:38 ` [Qemu-devel] [PATCH 02/31] openpic: remove pcsr (CPU sensitivity register) Alexander Graf
` (30 subsequent siblings)
31 siblings, 0 replies; 38+ messages in thread
From: Alexander Graf @ 2013-01-07 15:38 UTC (permalink / raw)
To: qemu-devel; +Cc: Blue Swirl, Scott Wood, qemu-ppc, Aurelien Jarno
From: Scott Wood <scottwood@freescale.com>
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.
Signed-off-by: Scott Wood <scottwood@freescale.com>
Signed-off-by: Alexander Graf <agraf@suse.de>
---
hw/openpic.c | 54 ++++++++++++++++++++++++++++++++----------------------
1 files changed, 32 insertions(+), 22 deletions(-)
diff --git a/hw/openpic.c b/hw/openpic.c
index 9c956b9..eff1eee 100644
--- a/hw/openpic.c
+++ b/hw/openpic.c
@@ -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;
--
1.6.0.2
^ permalink raw reply related [flat|nested] 38+ messages in thread
* [Qemu-devel] [PATCH 02/31] openpic: remove pcsr (CPU sensitivity register)
2013-01-07 15:38 [Qemu-devel] [PULL 00/31] ppc patch queue 2013-01-07 Alexander Graf
2013-01-07 15:38 ` [Qemu-devel] [PATCH 01/31] openpic: symbolicize some magic numbers Alexander Graf
@ 2013-01-07 15:38 ` Alexander Graf
2013-01-07 15:38 ` [Qemu-devel] [PATCH 03/31] openpic: support large vectors on FSL mpic Alexander Graf
` (29 subsequent siblings)
31 siblings, 0 replies; 38+ messages in thread
From: Alexander Graf @ 2013-01-07 15:38 UTC (permalink / raw)
To: qemu-devel; +Cc: Blue Swirl, Scott Wood, qemu-ppc, Aurelien Jarno
From: Scott Wood <scottwood@freescale.com>
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.
Signed-off-by: Scott Wood <scottwood@freescale.com>
Signed-off-by: Alexander Graf <agraf@suse.de>
---
hw/openpic.c | 4 ----
1 files changed, 0 insertions(+), 4 deletions(-)
diff --git a/hw/openpic.c b/hw/openpic.c
index eff1eee..44f7cc4 100644
--- a/hw/openpic.c
+++ b/hw/openpic.c
@@ -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);
}
--
1.6.0.2
^ permalink raw reply related [flat|nested] 38+ messages in thread
* [Qemu-devel] [PATCH 03/31] openpic: support large vectors on FSL mpic
2013-01-07 15:38 [Qemu-devel] [PULL 00/31] ppc patch queue 2013-01-07 Alexander Graf
2013-01-07 15:38 ` [Qemu-devel] [PATCH 01/31] openpic: symbolicize some magic numbers Alexander Graf
2013-01-07 15:38 ` [Qemu-devel] [PATCH 02/31] openpic: remove pcsr (CPU sensitivity register) Alexander Graf
@ 2013-01-07 15:38 ` Alexander Graf
2013-01-07 15:38 ` [Qemu-devel] [PATCH 04/31] openpic: BRR1 is not a CPU-specific register Alexander Graf
` (28 subsequent siblings)
31 siblings, 0 replies; 38+ messages in thread
From: Alexander Graf @ 2013-01-07 15:38 UTC (permalink / raw)
To: qemu-devel; +Cc: Blue Swirl, Scott Wood, qemu-ppc, Aurelien Jarno
From: Scott Wood <scottwood@freescale.com>
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.
Signed-off-by: Scott Wood <scottwood@freescale.com>
Signed-off-by: Alexander Graf <agraf@suse.de>
---
hw/openpic.c | 22 ++++++++++------------
1 files changed, 10 insertions(+), 12 deletions(-)
diff --git a/hw/openpic.c b/hw/openpic.c
index 44f7cc4..f0877fa 100644
--- a/hw/openpic.c
+++ b/hw/openpic.c
@@ -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;
--
1.6.0.2
^ permalink raw reply related [flat|nested] 38+ messages in thread
* [Qemu-devel] [PATCH 04/31] openpic: BRR1 is not a CPU-specific register.
2013-01-07 15:38 [Qemu-devel] [PULL 00/31] ppc patch queue 2013-01-07 Alexander Graf
` (2 preceding siblings ...)
2013-01-07 15:38 ` [Qemu-devel] [PATCH 03/31] openpic: support large vectors on FSL mpic Alexander Graf
@ 2013-01-07 15:38 ` Alexander Graf
2013-01-07 15:38 ` [Qemu-devel] [PATCH 05/31] openpic: s/opp->nb_irqs -1/opp->nb_cpus - 1/ Alexander Graf
` (27 subsequent siblings)
31 siblings, 0 replies; 38+ messages in thread
From: Alexander Graf @ 2013-01-07 15:38 UTC (permalink / raw)
To: qemu-devel; +Cc: Blue Swirl, Scott Wood, qemu-ppc, Aurelien Jarno
From: Scott Wood <scottwood@freescale.com>
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".
Signed-off-by: Scott Wood <scottwood@freescale.com>
Signed-off-by: Alexander Graf <agraf@suse.de>
---
hw/openpic.c | 5 ++---
1 files changed, 2 insertions(+), 3 deletions(-)
diff --git a/hw/openpic.c b/hw/openpic.c
index f0877fa..337dbf5 100644
--- a/hw/openpic.c
+++ b/hw/openpic.c
@@ -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;
--
1.6.0.2
^ permalink raw reply related [flat|nested] 38+ messages in thread
* [Qemu-devel] [PATCH 05/31] openpic: s/opp->nb_irqs -1/opp->nb_cpus - 1/
2013-01-07 15:38 [Qemu-devel] [PULL 00/31] ppc patch queue 2013-01-07 Alexander Graf
` (3 preceding siblings ...)
2013-01-07 15:38 ` [Qemu-devel] [PATCH 04/31] openpic: BRR1 is not a CPU-specific register Alexander Graf
@ 2013-01-07 15:38 ` Alexander Graf
2013-01-07 15:38 ` [Qemu-devel] [PATCH 06/31] openpic: don't crash on a register access without a CPU context Alexander Graf
` (26 subsequent siblings)
31 siblings, 0 replies; 38+ messages in thread
From: Alexander Graf @ 2013-01-07 15:38 UTC (permalink / raw)
To: qemu-devel; +Cc: Blue Swirl, Scott Wood, qemu-ppc, Aurelien Jarno
From: Scott Wood <scottwood@freescale.com>
"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".
Signed-off-by: Scott Wood <scottwood@freescale.com>
Signed-off-by: Alexander Graf <agraf@suse.de>
---
hw/openpic.c | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/hw/openpic.c b/hw/openpic.c
index 337dbf5..10dbdf7 100644
--- a/hw/openpic.c
+++ b/hw/openpic.c
@@ -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;
--
1.6.0.2
^ permalink raw reply related [flat|nested] 38+ messages in thread
* [Qemu-devel] [PATCH 06/31] openpic: don't crash on a register access without a CPU context
2013-01-07 15:38 [Qemu-devel] [PULL 00/31] ppc patch queue 2013-01-07 Alexander Graf
` (4 preceding siblings ...)
2013-01-07 15:38 ` [Qemu-devel] [PATCH 05/31] openpic: s/opp->nb_irqs -1/opp->nb_cpus - 1/ Alexander Graf
@ 2013-01-07 15:38 ` Alexander Graf
2013-01-07 15:38 ` [Qemu-devel] [PATCH 07/31] powerpc: linux header sync script includes epapr_hcalls.h Alexander Graf
` (25 subsequent siblings)
31 siblings, 0 replies; 38+ messages in thread
From: Alexander Graf @ 2013-01-07 15:38 UTC (permalink / raw)
To: qemu-devel; +Cc: Blue Swirl, Scott Wood, qemu-ppc, Aurelien Jarno
From: Scott Wood <scottwood@freescale.com>
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.
Signed-off-by: Scott Wood <scottwood@freescale.com>
Signed-off-by: Alexander Graf <agraf@suse.de>
---
hw/openpic.c | 16 +++++++++++++++-
1 files changed, 15 insertions(+), 1 deletions(-)
diff --git a/hw/openpic.c b/hw/openpic.c
index 10dbdf7..93e8208 100644
--- a/hw/openpic.c
+++ b/hw/openpic.c
@@ -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];
--
1.6.0.2
^ permalink raw reply related [flat|nested] 38+ messages in thread
* [Qemu-devel] [PATCH 07/31] powerpc: linux header sync script includes epapr_hcalls.h
2013-01-07 15:38 [Qemu-devel] [PULL 00/31] ppc patch queue 2013-01-07 Alexander Graf
` (5 preceding siblings ...)
2013-01-07 15:38 ` [Qemu-devel] [PATCH 06/31] openpic: don't crash on a register access without a CPU context Alexander Graf
@ 2013-01-07 15:38 ` Alexander Graf
2013-01-07 15:38 ` [Qemu-devel] [PATCH 08/31] openpic: fix coding style issues Alexander Graf
` (24 subsequent siblings)
31 siblings, 0 replies; 38+ messages in thread
From: Alexander Graf @ 2013-01-07 15:38 UTC (permalink / raw)
To: qemu-devel
Cc: Blue Swirl, Bharat Bhushan, qemu-ppc, Aurelien Jarno,
Bharat Bhushan
From: Bharat Bhushan <r65777@freescale.com>
epapr_hcalls.h is now referenced by kvm_para.h. so this is needed for
QEMU to get compiled on powerpc.
Signed-off-by: Bharat Bhushan <bharat.bhushan@freescale.com>
Signed-off-by: Alexander Graf <agraf@suse.de>
---
| 3 +++
1 files changed, 3 insertions(+), 0 deletions(-)
--git a/scripts/update-linux-headers.sh b/scripts/update-linux-headers.sh
index 4c7b566..120a694 100755
--- a/scripts/update-linux-headers.sh
+++ b/scripts/update-linux-headers.sh
@@ -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"
--
1.6.0.2
^ permalink raw reply related [flat|nested] 38+ messages in thread
* [Qemu-devel] [PATCH 08/31] openpic: fix coding style issues
2013-01-07 15:38 [Qemu-devel] [PULL 00/31] ppc patch queue 2013-01-07 Alexander Graf
` (6 preceding siblings ...)
2013-01-07 15:38 ` [Qemu-devel] [PATCH 07/31] powerpc: linux header sync script includes epapr_hcalls.h Alexander Graf
@ 2013-01-07 15:38 ` Alexander Graf
2013-01-07 15:38 ` [Qemu-devel] [PATCH 09/31] PPC: Reset qemu timers when guest reset Alexander Graf
` (23 subsequent siblings)
31 siblings, 0 replies; 38+ messages in thread
From: Alexander Graf @ 2013-01-07 15:38 UTC (permalink / raw)
To: qemu-devel; +Cc: Blue Swirl, qemu-ppc, Aurelien Jarno
This patch fixes the following coding style violations:
- structs have to be typedef and be CamelCase
- if()s are always surrounded by curly braces
Signed-off-by: Alexander Graf <agraf@suse.de>
---
hw/openpic.c | 100 ++++++++++++++++++++++++++++++++--------------------------
1 files changed, 55 insertions(+), 45 deletions(-)
diff --git a/hw/openpic.c b/hw/openpic.c
index 93e8208..55e96d1 100644
--- a/hw/openpic.c
+++ b/hw/openpic.c
@@ -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:
--
1.6.0.2
^ permalink raw reply related [flat|nested] 38+ messages in thread
* [Qemu-devel] [PATCH 09/31] PPC: Reset qemu timers when guest reset
2013-01-07 15:38 [Qemu-devel] [PULL 00/31] ppc patch queue 2013-01-07 Alexander Graf
` (7 preceding siblings ...)
2013-01-07 15:38 ` [Qemu-devel] [PATCH 08/31] openpic: fix coding style issues Alexander Graf
@ 2013-01-07 15:38 ` Alexander Graf
2013-01-07 15:38 ` [Qemu-devel] [PATCH 10/31] PPC: fix segfault in signal handling code Alexander Graf
` (22 subsequent siblings)
31 siblings, 0 replies; 38+ messages in thread
From: Alexander Graf @ 2013-01-07 15:38 UTC (permalink / raw)
To: qemu-devel
Cc: Blue Swirl, Bharat Bhushan, qemu-ppc, Aurelien Jarno,
Bharat Bhushan
From: Bharat Bhushan <r65777@freescale.com>
This patch install the timer reset handler. This will be called when
the guest is reset.
Signed-off-by: Bharat Bhushan <bharat.bhushan@freescale.com>
[agraf: adjust for QOM'ification]
Signed-off-by: Alexander Graf <agraf@suse.de>
---
hw/ppc_booke.c | 13 +++++++++++++
1 files changed, 13 insertions(+), 0 deletions(-)
diff --git a/hw/ppc_booke.c b/hw/ppc_booke.c
index 4483b8d..25a4e91 100644
--- a/hw/ppc_booke.c
+++ b/hw/ppc_booke.c
@@ -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);
}
--
1.6.0.2
^ permalink raw reply related [flat|nested] 38+ messages in thread
* [Qemu-devel] [PATCH 10/31] PPC: fix segfault in signal handling code
2013-01-07 15:38 [Qemu-devel] [PULL 00/31] ppc patch queue 2013-01-07 Alexander Graf
` (8 preceding siblings ...)
2013-01-07 15:38 ` [Qemu-devel] [PATCH 09/31] PPC: Reset qemu timers when guest reset Alexander Graf
@ 2013-01-07 15:38 ` Alexander Graf
2013-01-07 15:38 ` [Qemu-devel] [PATCH 11/31] openpic: fix debug prints Alexander Graf
` (21 subsequent siblings)
31 siblings, 0 replies; 38+ messages in thread
From: Alexander Graf @ 2013-01-07 15:38 UTC (permalink / raw)
To: qemu-devel; +Cc: Blue Swirl, Samuel Seay, qemu-ppc, Aurelien Jarno
From: Samuel Seay <lightningth@gmail.com>
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.
Signed-off-by: Samuel Seay <LightningTH@GMail.com>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
[agraf: change subject line, reformat commit message]
Signed-off-by: Alexander Graf <agraf@suse.de>
---
linux-user/signal.c | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/linux-user/signal.c b/linux-user/signal.c
index 95e2ffa..c43b8ac 100644
--- a/linux-user/signal.c
+++ b/linux-user/signal.c
@@ -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;
--
1.6.0.2
^ permalink raw reply related [flat|nested] 38+ messages in thread
* [Qemu-devel] [PATCH 11/31] openpic: fix debug prints
2013-01-07 15:38 [Qemu-devel] [PULL 00/31] ppc patch queue 2013-01-07 Alexander Graf
` (9 preceding siblings ...)
2013-01-07 15:38 ` [Qemu-devel] [PATCH 10/31] PPC: fix segfault in signal handling code Alexander Graf
@ 2013-01-07 15:38 ` Alexander Graf
2013-01-07 15:38 ` [Qemu-devel] [PATCH 12/31] openpic: lower interrupt when reading the MSI register Alexander Graf
` (20 subsequent siblings)
31 siblings, 0 replies; 38+ messages in thread
From: Alexander Graf @ 2013-01-07 15:38 UTC (permalink / raw)
To: qemu-devel; +Cc: Blue Swirl, Scott Wood, qemu-ppc, Aurelien Jarno
From: Scott Wood <scottwood@freescale.com>
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.
Signed-off-by: Scott Wood <scottwood@freescale.com>
[agraf: adjust for more recent code base, prettify DPRINTF macro]
Signed-off-by: Alexander Graf <agraf@suse.de>
---
hw/openpic.c | 44 +++++++++++++++++++++++++++-----------------
1 files changed, 27 insertions(+), 17 deletions(-)
diff --git a/hw/openpic.c b/hw/openpic.c
index 55e96d1..9243e70 100644
--- a/hw/openpic.c
+++ b/hw/openpic.c
@@ -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;
}
--
1.6.0.2
^ permalink raw reply related [flat|nested] 38+ messages in thread
* [Qemu-devel] [PATCH 12/31] openpic: lower interrupt when reading the MSI register
2013-01-07 15:38 [Qemu-devel] [PULL 00/31] ppc patch queue 2013-01-07 Alexander Graf
` (10 preceding siblings ...)
2013-01-07 15:38 ` [Qemu-devel] [PATCH 11/31] openpic: fix debug prints Alexander Graf
@ 2013-01-07 15:38 ` Alexander Graf
2013-01-07 15:38 ` [Qemu-devel] [PATCH 13/31] ppc/booke: fix crit/mcheck/debug exceptions Alexander Graf
` (19 subsequent siblings)
31 siblings, 0 replies; 38+ messages in thread
From: Alexander Graf @ 2013-01-07 15:38 UTC (permalink / raw)
To: qemu-devel; +Cc: Blue Swirl, Scott Wood, qemu-ppc, Aurelien Jarno
From: Scott Wood <scottwood@freescale.com>
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.
Signed-off-by: Scott Wood <scottwood@freescale.com>
Signed-off-by: Alexander Graf <agraf@suse.de>
---
hw/openpic.c | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
diff --git a/hw/openpic.c b/hw/openpic.c
index 9243e70..f4df66d 100644
--- a/hw/openpic.c
+++ b/hw/openpic.c
@@ -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++) {
--
1.6.0.2
^ permalink raw reply related [flat|nested] 38+ messages in thread
* [Qemu-devel] [PATCH 13/31] ppc/booke: fix crit/mcheck/debug exceptions
2013-01-07 15:38 [Qemu-devel] [PULL 00/31] ppc patch queue 2013-01-07 Alexander Graf
` (11 preceding siblings ...)
2013-01-07 15:38 ` [Qemu-devel] [PATCH 12/31] openpic: lower interrupt when reading the MSI register Alexander Graf
@ 2013-01-07 15:38 ` Alexander Graf
2013-01-07 15:38 ` [Qemu-devel] [PATCH 14/31] openpic: make register names correspond better with hw docs Alexander Graf
` (18 subsequent siblings)
31 siblings, 0 replies; 38+ messages in thread
From: Alexander Graf @ 2013-01-07 15:38 UTC (permalink / raw)
To: qemu-devel; +Cc: Blue Swirl, Scott Wood, qemu-ppc, Aurelien Jarno
From: Scott Wood <scottwood@freescale.com>
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.
Signed-off-by: Scott Wood <scottwood@freescale.com>
Signed-off-by: Alexander Graf <agraf@suse.de>
---
target-ppc/excp_helper.c | 31 ++++++++++++++++++++++---------
1 files changed, 22 insertions(+), 9 deletions(-)
diff --git a/target-ppc/excp_helper.c b/target-ppc/excp_helper.c
index 5e34ad0..41037a7 100644
--- a/target-ppc/excp_helper.c
+++ b/target-ppc/excp_helper.c
@@ -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
--
1.6.0.2
^ permalink raw reply related [flat|nested] 38+ messages in thread
* [Qemu-devel] [PATCH 14/31] openpic: make register names correspond better with hw docs
2013-01-07 15:38 [Qemu-devel] [PULL 00/31] ppc patch queue 2013-01-07 Alexander Graf
` (12 preceding siblings ...)
2013-01-07 15:38 ` [Qemu-devel] [PATCH 13/31] ppc/booke: fix crit/mcheck/debug exceptions Alexander Graf
@ 2013-01-07 15:38 ` Alexander Graf
2013-01-07 15:38 ` [Qemu-devel] [PATCH 15/31] openpic: rework critical interrupt support Alexander Graf
` (17 subsequent siblings)
31 siblings, 0 replies; 38+ messages in thread
From: Alexander Graf @ 2013-01-07 15:38 UTC (permalink / raw)
To: qemu-devel; +Cc: Blue Swirl, Scott Wood, qemu-ppc, Aurelien Jarno
From: Scott Wood <scottwood@freescale.com>
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.
Signed-off-by: Scott Wood <scottwood@freescale.com>
[agraf: rebase on current state of the code]
Signed-off-by: Alexander Graf <agraf@suse.de>
---
hw/openpic.c | 356 +++++++++++++++++++++++++++++-----------------------------
1 files changed, 178 insertions(+), 178 deletions(-)
diff --git a/hw/openpic.c b/hw/openpic.c
index f4df66d..6362497 100644
--- a/hw/openpic.c
+++ b/hw/openpic.c
@@ -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;
--
1.6.0.2
^ permalink raw reply related [flat|nested] 38+ messages in thread
* [Qemu-devel] [PATCH 15/31] openpic: rework critical interrupt support
2013-01-07 15:38 [Qemu-devel] [PULL 00/31] ppc patch queue 2013-01-07 Alexander Graf
` (13 preceding siblings ...)
2013-01-07 15:38 ` [Qemu-devel] [PATCH 14/31] openpic: make register names correspond better with hw docs Alexander Graf
@ 2013-01-07 15:38 ` Alexander Graf
2013-01-07 15:38 ` [Qemu-devel] [PATCH 16/31] openpic: make ctpr signed Alexander Graf
` (16 subsequent siblings)
31 siblings, 0 replies; 38+ messages in thread
From: Alexander Graf @ 2013-01-07 15:38 UTC (permalink / raw)
To: qemu-devel; +Cc: Blue Swirl, Scott Wood, qemu-ppc, Aurelien Jarno
From: Scott Wood <scottwood@freescale.com>
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.
Signed-off-by: Scott Wood <scottwood@freescale.com>
[agraf: fix for current code state]
Signed-off-by: Alexander Graf <agraf@suse.de>
---
hw/openpic.c | 110 ++++++++++++++++++++++++++++++++++++++++------------------
1 files changed, 76 insertions(+), 34 deletions(-)
diff --git a/hw/openpic.c b/hw/openpic.c
index 6362497..fe6cf67 100644
--- a/hw/openpic.c
+++ b/hw/openpic.c
@@ -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 {
--
1.6.0.2
^ permalink raw reply related [flat|nested] 38+ messages in thread
* [Qemu-devel] [PATCH 16/31] openpic: make ctpr signed
2013-01-07 15:38 [Qemu-devel] [PULL 00/31] ppc patch queue 2013-01-07 Alexander Graf
` (14 preceding siblings ...)
2013-01-07 15:38 ` [Qemu-devel] [PATCH 15/31] openpic: rework critical interrupt support Alexander Graf
@ 2013-01-07 15:38 ` Alexander Graf
2013-01-07 15:38 ` [Qemu-devel] [PATCH 17/31] openpic/fsl: critical interrupts ignore mask before v4.1 Alexander Graf
` (15 subsequent siblings)
31 siblings, 0 replies; 38+ messages in thread
From: Alexander Graf @ 2013-01-07 15:38 UTC (permalink / raw)
To: qemu-devel; +Cc: Blue Swirl, Scott Wood, qemu-ppc, Aurelien Jarno
From: Scott Wood <scottwood@freescale.com>
Other priorities are signed, so avoid comparisons between
signed and unsigned.
Signed-off-by: Scott Wood <scottwood@freescale.com>
Signed-off-by: Alexander Graf <agraf@suse.de>
---
hw/openpic.c | 6 +++---
1 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/hw/openpic.c b/hw/openpic.c
index fe6cf67..824b8fd 100644
--- a/hw/openpic.c
+++ b/hw/openpic.c
@@ -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);
}
--
1.6.0.2
^ permalink raw reply related [flat|nested] 38+ messages in thread
* [Qemu-devel] [PATCH 17/31] openpic/fsl: critical interrupts ignore mask before v4.1
2013-01-07 15:38 [Qemu-devel] [PULL 00/31] ppc patch queue 2013-01-07 Alexander Graf
` (15 preceding siblings ...)
2013-01-07 15:38 ` [Qemu-devel] [PATCH 16/31] openpic: make ctpr signed Alexander Graf
@ 2013-01-07 15:38 ` Alexander Graf
2013-01-07 15:38 ` [Qemu-devel] [PATCH 18/31] openpic: always call IRQ_check from IRQ_get_next Alexander Graf
` (14 subsequent siblings)
31 siblings, 0 replies; 38+ messages in thread
From: Alexander Graf @ 2013-01-07 15:38 UTC (permalink / raw)
To: qemu-devel; +Cc: Blue Swirl, Scott Wood, qemu-ppc, Aurelien Jarno
From: Scott Wood <scottwood@freescale.com>
Signed-off-by: Scott Wood <scottwood@freescale.com>
[agraf: make bool :1]
Signed-off-by: Alexander Graf <agraf@suse.de>
---
hw/openpic.c | 5 ++++-
1 files changed, 4 insertions(+), 1 deletions(-)
diff --git a/hw/openpic.c b/hw/openpic.c
index 824b8fd..ac5027a 100644
--- a/hw/openpic.c
+++ b/hw/openpic.c
@@ -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 {
--
1.6.0.2
^ permalink raw reply related [flat|nested] 38+ messages in thread
* [Qemu-devel] [PATCH 18/31] openpic: always call IRQ_check from IRQ_get_next
2013-01-07 15:38 [Qemu-devel] [PULL 00/31] ppc patch queue 2013-01-07 Alexander Graf
` (16 preceding siblings ...)
2013-01-07 15:38 ` [Qemu-devel] [PATCH 17/31] openpic/fsl: critical interrupts ignore mask before v4.1 Alexander Graf
@ 2013-01-07 15:38 ` Alexander Graf
2013-01-07 15:38 ` [Qemu-devel] [PATCH 19/31] Revert "openpic: Accelerate pending irq search" Alexander Graf
` (13 subsequent siblings)
31 siblings, 0 replies; 38+ messages in thread
From: Alexander Graf @ 2013-01-07 15:38 UTC (permalink / raw)
To: qemu-devel; +Cc: Blue Swirl, Scott Wood, qemu-ppc, Aurelien Jarno
From: Scott Wood <scottwood@freescale.com>
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.
Signed-off-by: Scott Wood <scottwood@freescale.com>
Signed-off-by: Alexander Graf <agraf@suse.de>
---
hw/openpic.c | 10 +++-------
1 files changed, 3 insertions(+), 7 deletions(-)
diff --git a/hw/openpic.c b/hw/openpic.c
index ac5027a..19e6280 100644
--- a/hw/openpic.c
+++ b/hw/openpic.c
@@ -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;
--
1.6.0.2
^ permalink raw reply related [flat|nested] 38+ messages in thread
* [Qemu-devel] [PATCH 19/31] Revert "openpic: Accelerate pending irq search"
2013-01-07 15:38 [Qemu-devel] [PULL 00/31] ppc patch queue 2013-01-07 Alexander Graf
` (17 preceding siblings ...)
2013-01-07 15:38 ` [Qemu-devel] [PATCH 18/31] openpic: always call IRQ_check from IRQ_get_next Alexander Graf
@ 2013-01-07 15:38 ` Alexander Graf
2013-01-07 15:38 ` [Qemu-devel] [PATCH 20/31] openpic: use standard bitmap operations Alexander Graf
` (12 subsequent siblings)
31 siblings, 0 replies; 38+ messages in thread
From: Alexander Graf @ 2013-01-07 15:38 UTC (permalink / raw)
To: qemu-devel; +Cc: Blue Swirl, Scott Wood, qemu-ppc, Aurelien Jarno
From: Scott Wood <scottwood@freescale.com>
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.
Signed-off-by: Scott Wood <scottwood@freescale.com>
Signed-off-by: Alexander Graf <agraf@suse.de>
---
hw/openpic.c | 11 -----------
1 files changed, 0 insertions(+), 11 deletions(-)
diff --git a/hw/openpic.c b/hw/openpic.c
index 19e6280..2c238fb 100644
--- a/hw/openpic.c
+++ b/hw/openpic.c
@@ -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;
}
--
1.6.0.2
^ permalink raw reply related [flat|nested] 38+ messages in thread
* [Qemu-devel] [PATCH 20/31] openpic: use standard bitmap operations
2013-01-07 15:38 [Qemu-devel] [PULL 00/31] ppc patch queue 2013-01-07 Alexander Graf
` (18 preceding siblings ...)
2013-01-07 15:38 ` [Qemu-devel] [PATCH 19/31] Revert "openpic: Accelerate pending irq search" Alexander Graf
@ 2013-01-07 15:38 ` Alexander Graf
2013-01-07 15:38 ` [Qemu-devel] [PATCH 21/31] openpic: add some bounds checking for IRQ numbers Alexander Graf
` (11 subsequent siblings)
31 siblings, 0 replies; 38+ messages in thread
From: Alexander Graf @ 2013-01-07 15:38 UTC (permalink / raw)
To: qemu-devel; +Cc: Blue Swirl, Scott Wood, qemu-ppc, Aurelien Jarno
From: Scott Wood <scottwood@freescale.com>
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.
Signed-off-by: Scott Wood <scottwood@freescale.com>
Signed-off-by: Alexander Graf <agraf@suse.de>
---
hw/openpic.c | 55 +++++++++++++++++++++++++++++--------------------------
1 files changed, 29 insertions(+), 26 deletions(-)
diff --git a/hw/openpic.c b/hw/openpic.c
index 2c238fb..b54308d 100644
--- a/hw/openpic.c
+++ b/hw/openpic.c
@@ -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);
--
1.6.0.2
^ permalink raw reply related [flat|nested] 38+ messages in thread
* [Qemu-devel] [PATCH 21/31] openpic: add some bounds checking for IRQ numbers
2013-01-07 15:38 [Qemu-devel] [PULL 00/31] ppc patch queue 2013-01-07 Alexander Graf
` (19 preceding siblings ...)
2013-01-07 15:38 ` [Qemu-devel] [PATCH 20/31] openpic: use standard bitmap operations Alexander Graf
@ 2013-01-07 15:38 ` Alexander Graf
2013-01-07 15:38 ` [Qemu-devel] [PATCH 22/31] openpic: fix sense and priority bits Alexander Graf
` (10 subsequent siblings)
31 siblings, 0 replies; 38+ messages in thread
From: Alexander Graf @ 2013-01-07 15:38 UTC (permalink / raw)
To: qemu-devel; +Cc: Blue Swirl, Scott Wood, qemu-ppc, Aurelien Jarno
From: Scott Wood <scottwood@freescale.com>
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.
Signed-off-by: Scott Wood <scottwood@freescale.com>
[agraf: remove hunk in code that didn't get applied yet]
Signed-off-by: Alexander Graf <agraf@suse.de>
---
hw/openpic.c | 11 +++++++++++
1 files changed, 11 insertions(+), 0 deletions(-)
diff --git a/hw/openpic.c b/hw/openpic.c
index b54308d..35a7fe3 100644
--- a/hw/openpic.c
+++ b/hw/openpic.c
@@ -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);
--
1.6.0.2
^ permalink raw reply related [flat|nested] 38+ messages in thread
* [Qemu-devel] [PATCH 22/31] openpic: fix sense and priority bits
2013-01-07 15:38 [Qemu-devel] [PULL 00/31] ppc patch queue 2013-01-07 Alexander Graf
` (20 preceding siblings ...)
2013-01-07 15:38 ` [Qemu-devel] [PATCH 21/31] openpic: add some bounds checking for IRQ numbers Alexander Graf
@ 2013-01-07 15:38 ` Alexander Graf
2013-01-07 15:38 ` [Qemu-devel] [PATCH 23/31] openpic: IRQ_check: search the queue a word at a time Alexander Graf
` (9 subsequent siblings)
31 siblings, 0 replies; 38+ messages in thread
From: Alexander Graf @ 2013-01-07 15:38 UTC (permalink / raw)
To: qemu-devel; +Cc: Blue Swirl, Scott Wood, qemu-ppc, Aurelien Jarno
From: Scott Wood <scottwood@freescale.com>
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.
Signed-off-by: Scott Wood <scottwood@freescale.com>
Signed-off-by: Alexander Graf <agraf@suse.de>
---
hw/openpic.c | 77 +++++++++++++++++++++++++++++++++++++++++++++++++++++----
1 files changed, 71 insertions(+), 6 deletions(-)
diff --git a/hw/openpic.c b/hw/openpic.c
index 35a7fe3..66179c2 100644
--- a/hw/openpic.c
+++ b/hw/openpic.c
@@ -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;
--
1.6.0.2
^ permalink raw reply related [flat|nested] 38+ messages in thread
* [Qemu-devel] [PATCH 23/31] openpic: IRQ_check: search the queue a word at a time
2013-01-07 15:38 [Qemu-devel] [PULL 00/31] ppc patch queue 2013-01-07 Alexander Graf
` (21 preceding siblings ...)
2013-01-07 15:38 ` [Qemu-devel] [PATCH 22/31] openpic: fix sense and priority bits Alexander Graf
@ 2013-01-07 15:38 ` Alexander Graf
2013-01-07 15:38 ` [Qemu-devel] [PATCH 24/31] openpic: move IACK to its own function Alexander Graf
` (8 subsequent siblings)
31 siblings, 0 replies; 38+ messages in thread
From: Alexander Graf @ 2013-01-07 15:38 UTC (permalink / raw)
To: qemu-devel; +Cc: Blue Swirl, Scott Wood, qemu-ppc, Aurelien Jarno
From: Scott Wood <scottwood@freescale.com>
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.
Signed-off-by: Scott Wood <scottwood@freescale.com>
Signed-off-by: Alexander Graf <agraf@suse.de>
---
hw/openpic.c | 28 ++++++++++++++++------------
1 files changed, 16 insertions(+), 12 deletions(-)
diff --git a/hw/openpic.c b/hw/openpic.c
index 66179c2..7645d67 100644
--- a/hw/openpic.c
+++ b/hw/openpic.c
@@ -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;
}
--
1.6.0.2
^ permalink raw reply related [flat|nested] 38+ messages in thread
* [Qemu-devel] [PATCH 24/31] openpic: move IACK to its own function
2013-01-07 15:38 [Qemu-devel] [PULL 00/31] ppc patch queue 2013-01-07 Alexander Graf
` (22 preceding siblings ...)
2013-01-07 15:38 ` [Qemu-devel] [PATCH 23/31] openpic: IRQ_check: search the queue a word at a time Alexander Graf
@ 2013-01-07 15:38 ` Alexander Graf
2013-01-07 15:38 ` [Qemu-devel] [PATCH 25/31] openpic: fix CTPR and de-assertion of interrupts Alexander Graf
` (7 subsequent siblings)
31 siblings, 0 replies; 38+ messages in thread
From: Alexander Graf @ 2013-01-07 15:38 UTC (permalink / raw)
To: qemu-devel; +Cc: Blue Swirl, Scott Wood, qemu-ppc, Aurelien Jarno
From: Scott Wood <scottwood@freescale.com>
Besides making the code cleaner, we will need a separate way to access
IACK in order to implement EPR (external proxy) interrupt delivery.
Signed-off-by: Scott Wood <scottwood@freescale.com>
Signed-off-by: Alexander Graf <agraf@suse.de>
---
hw/openpic.c | 95 ++++++++++++++++++++++++++++++++-------------------------
1 files changed, 53 insertions(+), 42 deletions(-)
diff --git a/hw/openpic.c b/hw/openpic.c
index 7645d67..374f80e 100644
--- a/hw/openpic.c
+++ b/hw/openpic.c
@@ -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;
--
1.6.0.2
^ permalink raw reply related [flat|nested] 38+ messages in thread
* [Qemu-devel] [PATCH 25/31] openpic: fix CTPR and de-assertion of interrupts
2013-01-07 15:38 [Qemu-devel] [PULL 00/31] ppc patch queue 2013-01-07 Alexander Graf
` (23 preceding siblings ...)
2013-01-07 15:38 ` [Qemu-devel] [PATCH 24/31] openpic: move IACK to its own function Alexander Graf
@ 2013-01-07 15:38 ` Alexander Graf
2013-01-07 15:38 ` [Qemu-devel] [PATCH 26/31] kvm: Update kernel headers Alexander Graf
` (6 subsequent siblings)
31 siblings, 0 replies; 38+ messages in thread
From: Alexander Graf @ 2013-01-07 15:38 UTC (permalink / raw)
To: qemu-devel; +Cc: Blue Swirl, Scott Wood, qemu-ppc, Aurelien Jarno
From: Scott Wood <scottwood@freescale.com>
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.
Signed-off-by: Scott Wood <scottwood@freescale.com>
Signed-off-by: Alexander Graf <agraf@suse.de>
---
hw/openpic.c | 181 +++++++++++++++++++++++++++++++++++++++-------------------
1 files changed, 123 insertions(+), 58 deletions(-)
diff --git a/hw/openpic.c b/hw/openpic.c
index 374f80e..e773d68 100644
--- a/hw/openpic.c
+++ b/hw/openpic.c
@@ -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++) {
--
1.6.0.2
^ permalink raw reply related [flat|nested] 38+ messages in thread
* [Qemu-devel] [PATCH 26/31] kvm: Update kernel headers
2013-01-07 15:38 [Qemu-devel] [PULL 00/31] ppc patch queue 2013-01-07 Alexander Graf
` (24 preceding siblings ...)
2013-01-07 15:38 ` [Qemu-devel] [PATCH 25/31] openpic: fix CTPR and de-assertion of interrupts Alexander Graf
@ 2013-01-07 15:38 ` Alexander Graf
2013-01-07 15:38 ` [Qemu-devel] [PATCH 27/31] PPC: KVM: set has-idle in guest device tree Alexander Graf
` (5 subsequent siblings)
31 siblings, 0 replies; 38+ messages in thread
From: Alexander Graf @ 2013-01-07 15:38 UTC (permalink / raw)
To: qemu-devel; +Cc: Blue Swirl, qemu-ppc, Aurelien Jarno
Corresponding kvm.git hash: 18eb54cf4a
Signed-off-by: Alexander Graf <agraf@suse.de>
---
| 98 ++++++++++++++++++++++++++++++
| 86 ++++++++++++++++++++++++++
| 13 ++--
| 21 +++++--
| 6 +-
| 6 +-
| 6 +-
| 6 +-
8 files changed, 219 insertions(+), 23 deletions(-)
create mode 100644 linux-headers/asm-powerpc/epapr_hcalls.h
--git a/linux-headers/asm-powerpc/epapr_hcalls.h b/linux-headers/asm-powerpc/epapr_hcalls.h
new file mode 100644
index 0000000..06f7247
--- /dev/null
+++ b/linux-headers/asm-powerpc/epapr_hcalls.h
@@ -0,0 +1,98 @@
+/*
+ * ePAPR hcall interface
+ *
+ * Copyright 2008-2011 Freescale Semiconductor, Inc.
+ *
+ * Author: Timur Tabi <timur@freescale.com>
+ *
+ * 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 */
--git a/linux-headers/asm-powerpc/kvm.h b/linux-headers/asm-powerpc/kvm.h
index 1bea4d8..2fba8a6 100644
--- a/linux-headers/asm-powerpc/kvm.h
+++ b/linux-headers/asm-powerpc/kvm.h
@@ -221,6 +221,12 @@ struct kvm_sregs {
__u32 dbsr; /* KVM_SREGS_E_UPDATE_DBSR */
__u32 dbcr[3];
+ /*
+ * iac/dac registers are 64bit wide, while this API
+ * interface provides only lower 32 bits on 64 bit
+ * processors. ONE_REG interface is added for 64bit
+ * iac/dac registers.
+ */
__u32 iac[4];
__u32 dac[2];
__u32 dvc[2];
@@ -325,6 +331,86 @@ struct kvm_book3e_206_tlb_params {
__u32 reserved[8];
};
+/* For KVM_PPC_GET_HTAB_FD */
+struct kvm_get_htab_fd {
+ __u64 flags;
+ __u64 start_index;
+ __u64 reserved[2];
+};
+
+/* Values for kvm_get_htab_fd.flags */
+#define KVM_GET_HTAB_BOLTED_ONLY ((__u64)0x1)
+#define KVM_GET_HTAB_WRITE ((__u64)0x2)
+
+/*
+ * Data read on the file descriptor is formatted as a series of
+ * records, each consisting of a header followed by a series of
+ * `n_valid' HPTEs (16 bytes each), which are all valid. Following
+ * those valid HPTEs there are `n_invalid' invalid HPTEs, which
+ * are not represented explicitly in the stream. The same format
+ * is used for writing.
+ */
+struct kvm_get_htab_header {
+ __u32 index;
+ __u16 n_valid;
+ __u16 n_invalid;
+};
+
#define KVM_REG_PPC_HIOR (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x1)
+#define KVM_REG_PPC_IAC1 (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x2)
+#define KVM_REG_PPC_IAC2 (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x3)
+#define KVM_REG_PPC_IAC3 (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x4)
+#define KVM_REG_PPC_IAC4 (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x5)
+#define KVM_REG_PPC_DAC1 (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x6)
+#define KVM_REG_PPC_DAC2 (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x7)
+#define KVM_REG_PPC_DABR (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x8)
+#define KVM_REG_PPC_DSCR (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x9)
+#define KVM_REG_PPC_PURR (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xa)
+#define KVM_REG_PPC_SPURR (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xb)
+#define KVM_REG_PPC_DAR (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xc)
+#define KVM_REG_PPC_DSISR (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0xd)
+#define KVM_REG_PPC_AMR (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xe)
+#define KVM_REG_PPC_UAMOR (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xf)
+
+#define KVM_REG_PPC_MMCR0 (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x10)
+#define KVM_REG_PPC_MMCR1 (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x11)
+#define KVM_REG_PPC_MMCRA (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x12)
+
+#define KVM_REG_PPC_PMC1 (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x18)
+#define KVM_REG_PPC_PMC2 (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x19)
+#define KVM_REG_PPC_PMC3 (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x1a)
+#define KVM_REG_PPC_PMC4 (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x1b)
+#define KVM_REG_PPC_PMC5 (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x1c)
+#define KVM_REG_PPC_PMC6 (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x1d)
+#define KVM_REG_PPC_PMC7 (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x1e)
+#define KVM_REG_PPC_PMC8 (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x1f)
+
+/* 32 floating-point registers */
+#define KVM_REG_PPC_FPR0 (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x20)
+#define KVM_REG_PPC_FPR(n) (KVM_REG_PPC_FPR0 + (n))
+#define KVM_REG_PPC_FPR31 (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x3f)
+
+/* 32 VMX/Altivec vector registers */
+#define KVM_REG_PPC_VR0 (KVM_REG_PPC | KVM_REG_SIZE_U128 | 0x40)
+#define KVM_REG_PPC_VR(n) (KVM_REG_PPC_VR0 + (n))
+#define KVM_REG_PPC_VR31 (KVM_REG_PPC | KVM_REG_SIZE_U128 | 0x5f)
+
+/* 32 double-width FP registers for VSX */
+/* High-order halves overlap with FP regs */
+#define KVM_REG_PPC_VSR0 (KVM_REG_PPC | KVM_REG_SIZE_U128 | 0x60)
+#define KVM_REG_PPC_VSR(n) (KVM_REG_PPC_VSR0 + (n))
+#define KVM_REG_PPC_VSR31 (KVM_REG_PPC | KVM_REG_SIZE_U128 | 0x7f)
+
+/* FP and vector status/control registers */
+#define KVM_REG_PPC_FPSCR (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x80)
+#define KVM_REG_PPC_VSCR (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x81)
+
+/* Virtual processor areas */
+/* For SLB & DTL, address in high (first) half, length in low half */
+#define KVM_REG_PPC_VPA_ADDR (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x82)
+#define KVM_REG_PPC_VPA_SLB (KVM_REG_PPC | KVM_REG_SIZE_U128 | 0x83)
+#define KVM_REG_PPC_VPA_DTL (KVM_REG_PPC | KVM_REG_SIZE_U128 | 0x84)
+
+#define KVM_REG_PPC_EPCR (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x85)
#endif /* __LINUX_KVM_POWERPC_H */
--git a/linux-headers/asm-powerpc/kvm_para.h b/linux-headers/asm-powerpc/kvm_para.h
index 5e04383..7e64f57 100644
--- a/linux-headers/asm-powerpc/kvm_para.h
+++ b/linux-headers/asm-powerpc/kvm_para.h
@@ -17,8 +17,8 @@
* Authors: Hollis Blanchard <hollisb@us.ibm.com>
*/
-#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__ */
--git a/linux-headers/linux/kvm.h b/linux-headers/linux/kvm.h
index 81d2feb..bfdbf4d 100644
--- a/linux-headers/linux/kvm.h
+++ b/linux-headers/linux/kvm.h
@@ -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 */
--git a/linux-headers/linux/kvm_para.h b/linux-headers/linux/kvm_para.h
index cea2c5c..7bdcf93 100644
--- a/linux-headers/linux/kvm_para.h
+++ b/linux-headers/linux/kvm_para.h
@@ -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 */
--git a/linux-headers/linux/vfio.h b/linux-headers/linux/vfio.h
index 4758d1b..f787b72 100644
--- a/linux-headers/linux/vfio.h
+++ b/linux-headers/linux/vfio.h
@@ -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 */
--git a/linux-headers/linux/virtio_config.h b/linux-headers/linux/virtio_config.h
index b7cda39..4f51d8f 100644
--- a/linux-headers/linux/virtio_config.h
+++ b/linux-headers/linux/virtio_config.h
@@ -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 */
--git a/linux-headers/linux/virtio_ring.h b/linux-headers/linux/virtio_ring.h
index 921694a..1b333e2 100644
--- a/linux-headers/linux/virtio_ring.h
+++ b/linux-headers/linux/virtio_ring.h
@@ -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 */
--
1.6.0.2
^ permalink raw reply related [flat|nested] 38+ messages in thread
* [Qemu-devel] [PATCH 27/31] PPC: KVM: set has-idle in guest device tree
2013-01-07 15:38 [Qemu-devel] [PULL 00/31] ppc patch queue 2013-01-07 Alexander Graf
` (25 preceding siblings ...)
2013-01-07 15:38 ` [Qemu-devel] [PATCH 26/31] kvm: Update kernel headers Alexander Graf
@ 2013-01-07 15:38 ` Alexander Graf
2013-01-07 15:38 ` [Qemu-devel] [PATCH 28/31] PPC: Bring EPR support closer to reality Alexander Graf
` (4 subsequent siblings)
31 siblings, 0 replies; 38+ messages in thread
From: Alexander Graf @ 2013-01-07 15:38 UTC (permalink / raw)
To: qemu-devel; +Cc: Blue Swirl, qemu-ppc, Stuart Yoder, Aurelien Jarno
From: Stuart Yoder <stuart.yoder@freescale.com>
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.
Signed-off-by: Stuart Yoder <stuart.yoder@freescale.com>
[agraf: adjust for current code base, add patch description]
Signed-off-by: Alexander Graf <agraf@suse.de>
---
hw/ppc/e500.c | 4 ++++
target-ppc/kvm.c | 32 ++++++++++++++++++++++++++------
target-ppc/kvm_ppc.h | 1 +
3 files changed, 31 insertions(+), 6 deletions(-)
diff --git a/hw/ppc/e500.c b/hw/ppc/e500.c
index b262f31..5d70618 100644
--- a/hw/ppc/e500.c
+++ b/hw/ppc/e500.c
@@ -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 */
diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c
index 436ca47..9fe949f 100644
--- a/target-ppc/kvm.c
+++ b/target-ppc/kvm.c
@@ -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;
}
diff --git a/target-ppc/kvm_ppc.h b/target-ppc/kvm_ppc.h
index 31eb9e6..dfb4ecf 100644
--- a/target-ppc/kvm_ppc.h
+++ b/target-ppc/kvm_ppc.h
@@ -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);
--
1.6.0.2
^ permalink raw reply related [flat|nested] 38+ messages in thread
* [Qemu-devel] [PATCH 28/31] PPC: Bring EPR support closer to reality
2013-01-07 15:38 [Qemu-devel] [PULL 00/31] ppc patch queue 2013-01-07 Alexander Graf
` (26 preceding siblings ...)
2013-01-07 15:38 ` [Qemu-devel] [PATCH 27/31] PPC: KVM: set has-idle in guest device tree Alexander Graf
@ 2013-01-07 15:38 ` Alexander Graf
2013-01-07 15:38 ` [Qemu-devel] [PATCH 29/31] target-ppc: Slim conversion of model definitions to QOM subclasses Alexander Graf
` (3 subsequent siblings)
31 siblings, 0 replies; 38+ messages in thread
From: Alexander Graf @ 2013-01-07 15:38 UTC (permalink / raw)
To: qemu-devel; +Cc: Blue Swirl, qemu-ppc, Aurelien Jarno
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.
Signed-off-by: Alexander Graf <agraf@suse.de>
---
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
diff --git a/hw/openpic.c b/hw/openpic.c
index e773d68..3b20a39 100644
--- a/hw/openpic.c
+++ b/hw/openpic.c
@@ -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;
diff --git a/hw/ppc/e500.c b/hw/ppc/e500.c
index 5d70618..3a9e1c7 100644
--- a/hw/ppc/e500.c
+++ b/hw/ppc/e500.c
@@ -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);
diff --git a/target-ppc/Makefile.objs b/target-ppc/Makefile.objs
index 237a0ed..6c11ef8 100644
--- a/target-ppc/Makefile.objs
+++ b/target-ppc/Makefile.objs
@@ -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
diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h
index e88ebe0..dc5145b 100644
--- a/target-ppc/cpu.h
+++ b/target-ppc/cpu.h
@@ -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 */
diff --git a/target-ppc/excp_helper.c b/target-ppc/excp_helper.c
index 41037a7..0a1ac86 100644
--- a/target-ppc/excp_helper.c
+++ b/target-ppc/excp_helper.c
@@ -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) {
diff --git a/target-ppc/helper.h b/target-ppc/helper.h
index d2e9a55..83139d5 100644
--- a/target-ppc/helper.h
+++ b/target-ppc/helper.h
@@ -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)
diff --git a/target-ppc/mpic_helper.c b/target-ppc/mpic_helper.c
deleted file mode 100644
index 2c6a4d3..0000000
--- a/target-ppc/mpic_helper.c
+++ /dev/null
@@ -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
diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
index 42ed748..e2eeb87 100644
--- a/target-ppc/translate_init.c
+++ b/target-ppc/translate_init.c
@@ -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) {
--
1.6.0.2
^ permalink raw reply related [flat|nested] 38+ messages in thread
* [Qemu-devel] [PATCH 29/31] target-ppc: Slim conversion of model definitions to QOM subclasses
2013-01-07 15:38 [Qemu-devel] [PULL 00/31] ppc patch queue 2013-01-07 Alexander Graf
` (27 preceding siblings ...)
2013-01-07 15:38 ` [Qemu-devel] [PATCH 28/31] PPC: Bring EPR support closer to reality Alexander Graf
@ 2013-01-07 15:38 ` Alexander Graf
2013-01-07 15:38 ` [Qemu-devel] [PATCH 30/31] target-ppc: Error out for -cpu host on unknown PVR Alexander Graf
` (2 subsequent siblings)
31 siblings, 0 replies; 38+ messages in thread
From: Alexander Graf @ 2013-01-07 15:38 UTC (permalink / raw)
To: qemu-devel; +Cc: Blue Swirl, qemu-ppc, Andreas Färber, Aurelien Jarno
From: Andreas Färber <afaerber@suse.de>
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 ?.
Signed-off-by: Andreas Färber <afaerber@suse.de>
Signed-off-by: Alexander Graf <agraf@suse.de>
---
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
diff --git a/target-ppc/Makefile.objs b/target-ppc/Makefile.objs
index 6c11ef8..a028dcd 100644
--- a/target-ppc/Makefile.objs
+++ b/target-ppc/Makefile.objs
@@ -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
diff --git a/target-ppc/cpu-qom.h b/target-ppc/cpu-qom.h
index fb6b5a4..b338f8f 100644
--- a/target-ppc/cpu-qom.h
+++ b/target-ppc/cpu-qom.h
@@ -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
diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h
index dc5145b..953146e 100644
--- a/target-ppc/cpu.h
+++ b/target-ppc/cpu.h
@@ -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);
diff --git a/target-ppc/helper.c b/target-ppc/helper.c
deleted file mode 100644
index 103855a..0000000
--- a/target-ppc/helper.c
+++ /dev/null
@@ -1,50 +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_regs.h"
-#include "sysemu/kvm.h"
-#include "kvm_ppc.h"
-#include "sysemu/cpus.h"
-
-PowerPCCPU *cpu_ppc_init(const char *cpu_model)
-{
- PowerPCCPU *cpu;
- CPUPPCState *env;
- const ppc_def_t *def;
-
- def = cpu_ppc_find_by_name(cpu_model);
- if (!def) {
- return NULL;
- }
-
- cpu = POWERPC_CPU(object_new(TYPE_POWERPC_CPU));
- env = &cpu->env;
-
- if (tcg_enabled()) {
- ppc_translate_init();
- }
-
- env->cpu_model_str = cpu_model;
- cpu_ppc_register_internal(env, def);
-
- qemu_init_vcpu(env);
-
- return cpu;
-}
diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c
index 9fe949f..ce7d69b 100644
--- a/target-ppc/kvm.c
+++ b/target-ppc/kvm.c
@@ -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)
diff --git a/target-ppc/kvm_ppc.h b/target-ppc/kvm_ppc.h
index dfb4ecf..a57ec6f 100644
--- a/target-ppc/kvm_ppc.h
+++ b/target-ppc/kvm_ppc.h
@@ -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;
diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
index e2eeb87..2b03756 100644
--- a/target-ppc/translate_init.c
+++ b/target-ppc/translate_init.c
@@ -9792,8 +9792,11 @@ static void fix_opcode_tables (opc_handler_t **ppc_opcodes)
}
/*****************************************************************************/
-static int create_ppc_opcodes (CPUPPCState *env, const ppc_def_t *def)
+static void create_ppc_opcodes(PowerPCCPU *cpu, Error **errp)
{
+ PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu);
+ CPUPPCState *env = &cpu->env;
+ const ppc_def_t *def = pcc->info;
opcode_t *opc;
fill_new_table(env->opcodes, 0x40);
@@ -9801,18 +9804,16 @@ static int create_ppc_opcodes (CPUPPCState *env, const ppc_def_t *def)
if (((opc->handler.type & def->insns_flags) != 0) ||
((opc->handler.type2 & def->insns_flags2) != 0)) {
if (register_insn(env->opcodes, opc) < 0) {
- printf("*** ERROR initializing PowerPC instruction "
- "0x%02x 0x%02x 0x%02x\n", opc->opc1, opc->opc2,
- opc->opc3);
- return -1;
+ error_setg(errp, "ERROR initializing PowerPC instruction "
+ "0x%02x 0x%02x 0x%02x\n", opc->opc1, opc->opc2,
+ opc->opc3);
+ return;
}
}
}
fix_opcode_tables(env->opcodes);
fflush(stdout);
fflush(stderr);
-
- return 0;
}
#if defined(PPC_DUMP_CPU)
@@ -10026,53 +10027,31 @@ static int ppc_fixup_cpu(CPUPPCState *env)
return 0;
}
-int cpu_ppc_register_internal (CPUPPCState *env, const ppc_def_t *def)
+static void ppc_cpu_realize(Object *obj, Error **errp)
{
- env->msr_mask = def->msr_mask;
- env->mmu_model = def->mmu_model;
- env->excp_model = def->excp_model;
- env->bus_model = def->bus_model;
- env->insns_flags = def->insns_flags;
- env->insns_flags2 = def->insns_flags2;
- env->flags = def->flags;
- env->bfd_mach = def->bfd_mach;
- env->check_pow = def->check_pow;
-
-#if defined(TARGET_PPC64)
- if (def->sps)
- env->sps = *def->sps;
- else if (env->mmu_model & POWERPC_MMU_64) {
- /* Use default sets of page sizes */
- static const struct ppc_segment_page_sizes defsps = {
- .sps = {
- { .page_shift = 12, /* 4K */
- .slb_enc = 0,
- .enc = { { .page_shift = 12, .pte_enc = 0 } }
- },
- { .page_shift = 24, /* 16M */
- .slb_enc = 0x100,
- .enc = { { .page_shift = 24, .pte_enc = 0 } }
- },
- },
- };
- env->sps = defsps;
- }
-#endif /* defined(TARGET_PPC64) */
+ PowerPCCPU *cpu = POWERPC_CPU(obj);
+ CPUPPCState *env = &cpu->env;
+ PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu);
+ ppc_def_t *def = pcc->info;
+ Error *local_err = NULL;
if (kvm_enabled()) {
if (kvmppc_fixup_cpu(env) != 0) {
- fprintf(stderr, "Unable to virtualize selected CPU with KVM\n");
- exit(1);
+ error_setg(errp, "Unable to virtualize selected CPU with KVM");
+ return;
}
} else {
if (ppc_fixup_cpu(env) != 0) {
- fprintf(stderr, "Unable to emulate selected CPU with TCG\n");
- exit(1);
+ error_setg(errp, "Unable to emulate selected CPU with TCG");
+ return;
}
}
- if (create_ppc_opcodes(env, def) < 0)
- return -1;
+ create_ppc_opcodes(cpu, &local_err);
+ if (local_err != NULL) {
+ error_propagate(errp, local_err);
+ return;
+ }
init_ppc_proc(env, def);
if (def->insns_flags & PPC_FLOAT) {
@@ -10088,6 +10067,8 @@ int cpu_ppc_register_internal (CPUPPCState *env, const ppc_def_t *def)
34, "power-spe.xml", 0);
}
+ qemu_init_vcpu(env);
+
#if defined(PPC_DUMP_CPU)
{
const char *mmu_model, *excp_model, *bus_model;
@@ -10249,50 +10230,65 @@ int cpu_ppc_register_internal (CPUPPCState *env, const ppc_def_t *def)
dump_ppc_sprs(env);
fflush(stdout);
#endif
-
- return 0;
}
-static bool ppc_cpu_usable(const ppc_def_t *def)
+static gint ppc_cpu_compare_class_pvr(gconstpointer a, gconstpointer b)
{
-#if defined(TARGET_PPCEMB)
- /* When using the ppcemb target, we only support 440 style cores */
- if (def->mmu_model != POWERPC_MMU_BOOKE) {
- return false;
+ ObjectClass *oc = (ObjectClass *)a;
+ uint32_t pvr = *(uint32_t *)b;
+ PowerPCCPUClass *pcc = (PowerPCCPUClass *)a;
+
+ /* -cpu host does a PVR lookup during construction */
+ if (unlikely(strcmp(object_class_get_name(oc),
+ TYPE_HOST_POWERPC_CPU) == 0)) {
+ return -1;
}
-#endif
- return true;
+ return pcc->info->pvr == pvr ? 0 : -1;
}
-const ppc_def_t *ppc_find_by_pvr(uint32_t pvr)
+PowerPCCPUClass *ppc_cpu_class_by_pvr(uint32_t pvr)
{
- int i;
+ GSList *list, *item;
+ PowerPCCPUClass *pcc = NULL;
- for (i = 0; i < ARRAY_SIZE(ppc_defs); i++) {
- if (!ppc_cpu_usable(&ppc_defs[i])) {
- continue;
- }
-
- /* If we have an exact match, we're done */
- if (pvr == ppc_defs[i].pvr) {
- return &ppc_defs[i];
- }
+ list = object_class_get_list(TYPE_POWERPC_CPU, false);
+ item = g_slist_find_custom(list, &pvr, ppc_cpu_compare_class_pvr);
+ if (item != NULL) {
+ pcc = POWERPC_CPU_CLASS(item->data);
}
+ g_slist_free(list);
+
+ return pcc;
+}
+
+static gint ppc_cpu_compare_class_name(gconstpointer a, gconstpointer b)
+{
+ ObjectClass *oc = (ObjectClass *)a;
+ const char *name = b;
- return NULL;
+ if (strncasecmp(name, object_class_get_name(oc), strlen(name)) == 0 &&
+ strcmp(object_class_get_name(oc) + strlen(name),
+ "-" TYPE_POWERPC_CPU) == 0) {
+ return 0;
+ }
+ return -1;
}
#include <ctype.h>
-const ppc_def_t *cpu_ppc_find_by_name (const char *name)
+static ObjectClass *ppc_cpu_class_by_name(const char *name)
{
- const ppc_def_t *ret;
+ GSList *list, *item;
+ ObjectClass *ret = NULL;
const char *p;
- int i, max, len;
+ int i, len;
- if (kvm_enabled() && (strcasecmp(name, "host") == 0)) {
- return kvmppc_host_cpu_def();
+ if (strcasecmp(name, "host") == 0) {
+ if (kvm_enabled()) {
+ ret = object_class_by_name(TYPE_HOST_POWERPC_CPU);
+ }
+ return ret;
}
/* Check if the given name is a PVR */
@@ -10307,63 +10303,152 @@ const ppc_def_t *cpu_ppc_find_by_name (const char *name)
if (!qemu_isxdigit(*p++))
break;
}
- if (i == 8)
- return ppc_find_by_pvr(strtoul(name, NULL, 16));
- }
- ret = NULL;
- max = ARRAY_SIZE(ppc_defs);
- for (i = 0; i < max; i++) {
- if (!ppc_cpu_usable(&ppc_defs[i])) {
- continue;
+ if (i == 8) {
+ ret = OBJECT_CLASS(ppc_cpu_class_by_pvr(strtoul(name, NULL, 16)));
+ return ret;
}
+ }
- if (strcasecmp(name, ppc_defs[i].name) == 0) {
- ret = &ppc_defs[i];
- break;
- }
+ list = object_class_get_list(TYPE_POWERPC_CPU, false);
+ item = g_slist_find_custom(list, name, ppc_cpu_compare_class_name);
+ if (item != NULL) {
+ ret = OBJECT_CLASS(item->data);
}
+ g_slist_free(list);
return ret;
}
-void ppc_cpu_list (FILE *f, fprintf_function cpu_fprintf)
+PowerPCCPU *cpu_ppc_init(const char *cpu_model)
{
- int i, max;
+ PowerPCCPU *cpu;
+ CPUPPCState *env;
+ ObjectClass *oc;
+ Error *err = NULL;
- max = ARRAY_SIZE(ppc_defs);
- for (i = 0; i < max; i++) {
- if (!ppc_cpu_usable(&ppc_defs[i])) {
- continue;
- }
+ oc = ppc_cpu_class_by_name(cpu_model);
+ if (oc == NULL) {
+ return NULL;
+ }
- (*cpu_fprintf)(f, "PowerPC %-16s PVR %08x\n",
- ppc_defs[i].name, ppc_defs[i].pvr);
+ cpu = POWERPC_CPU(object_new(object_class_get_name(oc)));
+ env = &cpu->env;
+
+ if (tcg_enabled()) {
+ ppc_translate_init();
}
+
+ env->cpu_model_str = cpu_model;
+
+ ppc_cpu_realize(OBJECT(cpu), &err);
+ if (err != NULL) {
+ fprintf(stderr, "%s\n", error_get_pretty(err));
+ error_free(err);
+ object_delete(OBJECT(cpu));
+ return NULL;
+ }
+
+ return cpu;
+}
+
+/* Sort by PVR, ordering special case "host" last. */
+static gint ppc_cpu_list_compare(gconstpointer a, gconstpointer b)
+{
+ ObjectClass *oc_a = (ObjectClass *)a;
+ ObjectClass *oc_b = (ObjectClass *)b;
+ PowerPCCPUClass *pcc_a = POWERPC_CPU_CLASS(oc_a);
+ PowerPCCPUClass *pcc_b = POWERPC_CPU_CLASS(oc_b);
+ const char *name_a = object_class_get_name(oc_a);
+ const char *name_b = object_class_get_name(oc_b);
+
+ if (strcmp(name_a, TYPE_HOST_POWERPC_CPU) == 0) {
+ return 1;
+ } else if (strcmp(name_b, TYPE_HOST_POWERPC_CPU) == 0) {
+ return -1;
+ } else {
+ /* Avoid an integer overflow during subtraction */
+ if (pcc_a->info->pvr < pcc_b->info->pvr) {
+ return -1;
+ } else if (pcc_a->info->pvr > pcc_b->info->pvr) {
+ return 1;
+ } else {
+ return 0;
+ }
+ }
+}
+
+static void ppc_cpu_list_entry(gpointer data, gpointer user_data)
+{
+ ObjectClass *oc = data;
+ CPUListState *s = user_data;
+ PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
+
+ (*s->cpu_fprintf)(s->file, "PowerPC %-16s PVR %08x\n",
+ pcc->info->name, pcc->info->pvr);
+}
+
+void ppc_cpu_list(FILE *f, fprintf_function cpu_fprintf)
+{
+ CPUListState s = {
+ .file = f,
+ .cpu_fprintf = cpu_fprintf,
+ };
+ GSList *list;
+
+ list = object_class_get_list(TYPE_POWERPC_CPU, false);
+ list = g_slist_sort(list, ppc_cpu_list_compare);
+ g_slist_foreach(list, ppc_cpu_list_entry, &s);
+ g_slist_free(list);
+}
+
+static void ppc_cpu_defs_entry(gpointer data, gpointer user_data)
+{
+ ObjectClass *oc = data;
+ CpuDefinitionInfoList **first = user_data;
+ PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
+ CpuDefinitionInfoList *entry;
+ CpuDefinitionInfo *info;
+
+ info = g_malloc0(sizeof(*info));
+ info->name = g_strdup(pcc->info->name);
+
+ entry = g_malloc0(sizeof(*entry));
+ entry->value = info;
+ entry->next = *first;
+ *first = entry;
}
CpuDefinitionInfoList *arch_query_cpu_definitions(Error **errp)
{
CpuDefinitionInfoList *cpu_list = NULL;
- int i;
+ GSList *list;
- for (i = 0; i < ARRAY_SIZE(ppc_defs); i++) {
- CpuDefinitionInfoList *entry;
- CpuDefinitionInfo *info;
+ list = object_class_get_list(TYPE_POWERPC_CPU, false);
+ g_slist_foreach(list, ppc_cpu_defs_entry, &cpu_list);
+ g_slist_free(list);
- if (!ppc_cpu_usable(&ppc_defs[i])) {
- continue;
- }
+ return cpu_list;
+}
- info = g_malloc0(sizeof(*info));
- info->name = g_strdup(ppc_defs[i].name);
+static void ppc_cpu_def_class_init(ObjectClass *oc, void *data)
+{
+ PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
+ ppc_def_t *info = data;
- entry = g_malloc0(sizeof(*entry));
- entry->value = info;
- entry->next = cpu_list;
- cpu_list = entry;
- }
+ pcc->info = info;
+}
- return cpu_list;
+static void ppc_cpu_register_model(const ppc_def_t *def)
+{
+ TypeInfo type_info = {
+ .parent = TYPE_POWERPC_CPU,
+ .class_init = ppc_cpu_def_class_init,
+ .class_data = (void *)def,
+ };
+
+ type_info.name = g_strdup_printf("%s-" TYPE_POWERPC_CPU, def->name),
+ type_register(&type_info);
+ g_free((gpointer)type_info.name);
}
/* CPUClass::reset() */
@@ -10434,9 +10519,42 @@ static void ppc_cpu_reset(CPUState *s)
static void ppc_cpu_initfn(Object *obj)
{
PowerPCCPU *cpu = POWERPC_CPU(obj);
+ PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu);
CPUPPCState *env = &cpu->env;
+ ppc_def_t *def = pcc->info;
cpu_exec_init(env);
+
+ env->msr_mask = def->msr_mask;
+ env->mmu_model = def->mmu_model;
+ env->excp_model = def->excp_model;
+ env->bus_model = def->bus_model;
+ env->insns_flags = def->insns_flags;
+ env->insns_flags2 = def->insns_flags2;
+ env->flags = def->flags;
+ env->bfd_mach = def->bfd_mach;
+ env->check_pow = def->check_pow;
+
+#if defined(TARGET_PPC64)
+ if (def->sps) {
+ env->sps = *def->sps;
+ } else if (env->mmu_model & POWERPC_MMU_64) {
+ /* Use default sets of page sizes */
+ static const struct ppc_segment_page_sizes defsps = {
+ .sps = {
+ { .page_shift = 12, /* 4K */
+ .slb_enc = 0,
+ .enc = { { .page_shift = 12, .pte_enc = 0 } }
+ },
+ { .page_shift = 24, /* 16M */
+ .slb_enc = 0x100,
+ .enc = { { .page_shift = 24, .pte_enc = 0 } }
+ },
+ },
+ };
+ env->sps = defsps;
+ }
+#endif /* defined(TARGET_PPC64) */
}
static void ppc_cpu_class_init(ObjectClass *oc, void *data)
@@ -10453,14 +10571,27 @@ static const TypeInfo ppc_cpu_type_info = {
.parent = TYPE_CPU,
.instance_size = sizeof(PowerPCCPU),
.instance_init = ppc_cpu_initfn,
- .abstract = false,
+ .abstract = true,
.class_size = sizeof(PowerPCCPUClass),
.class_init = ppc_cpu_class_init,
};
static void ppc_cpu_register_types(void)
{
+ int i;
+
type_register_static(&ppc_cpu_type_info);
+
+ for (i = 0; i < ARRAY_SIZE(ppc_defs); i++) {
+ const ppc_def_t *def = &ppc_defs[i];
+#if defined(TARGET_PPCEMB)
+ /* When using the ppcemb target, we only support 440 style cores */
+ if (def->mmu_model != POWERPC_MMU_BOOKE) {
+ continue;
+ }
+#endif
+ ppc_cpu_register_model(def);
+ }
}
type_init(ppc_cpu_register_types)
--
1.6.0.2
^ permalink raw reply related [flat|nested] 38+ messages in thread
* [Qemu-devel] [PATCH 30/31] target-ppc: Error out for -cpu host on unknown PVR
2013-01-07 15:38 [Qemu-devel] [PULL 00/31] ppc patch queue 2013-01-07 Alexander Graf
` (28 preceding siblings ...)
2013-01-07 15:38 ` [Qemu-devel] [PATCH 29/31] target-ppc: Slim conversion of model definitions to QOM subclasses Alexander Graf
@ 2013-01-07 15:38 ` Alexander Graf
2013-01-07 15:39 ` [Qemu-devel] [PATCH 31/31] PPC: linux-user: Calculate context pointer explicitly Alexander Graf
2013-01-07 16:21 ` [Qemu-devel] [PULL 00/31] ppc patch queue 2013-01-07 Andreas Färber
31 siblings, 0 replies; 38+ messages in thread
From: Alexander Graf @ 2013-01-07 15:38 UTC (permalink / raw)
To: qemu-devel; +Cc: Blue Swirl, qemu-ppc, Andreas Färber, Aurelien Jarno
From: Andreas Färber <afaerber@suse.de>
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.
Signed-off-by: Andreas Färber <afaerber@suse.de>
Signed-off-by: Alexander Graf <agraf@suse.de>
---
target-ppc/kvm.c | 8 ++++++++
1 files changed, 8 insertions(+), 0 deletions(-)
diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c
index ce7d69b..4846acf 100644
--- a/target-ppc/kvm.c
+++ b/target-ppc/kvm.c
@@ -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)
--
1.6.0.2
^ permalink raw reply related [flat|nested] 38+ messages in thread
* [Qemu-devel] [PATCH 31/31] PPC: linux-user: Calculate context pointer explicitly
2013-01-07 15:38 [Qemu-devel] [PULL 00/31] ppc patch queue 2013-01-07 Alexander Graf
` (29 preceding siblings ...)
2013-01-07 15:38 ` [Qemu-devel] [PATCH 30/31] target-ppc: Error out for -cpu host on unknown PVR Alexander Graf
@ 2013-01-07 15:39 ` Alexander Graf
2013-01-07 16:21 ` [Qemu-devel] [PULL 00/31] ppc patch queue 2013-01-07 Andreas Färber
31 siblings, 0 replies; 38+ messages in thread
From: Alexander Graf @ 2013-01-07 15:39 UTC (permalink / raw)
To: qemu-devel; +Cc: Blue Swirl, Samuel Seay, qemu-ppc, Aurelien Jarno
From: Samuel Seay <lightningth@gmail.com>
Peter Maydell recommended the change to be more proper. The result was tested
and shows coming up with the same proper value.
Signed-off-by: Samuel Seay <LightningTH@GMail.com>
[agraf: change subject]
Signed-off-by: Alexander Graf <agraf@suse.de>
---
linux-user/signal.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/linux-user/signal.c b/linux-user/signal.c
index c43b8ac..bb08a93 100644
--- a/linux-user/signal.c
+++ b/linux-user/signal.c
@@ -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;
--
1.6.0.2
^ permalink raw reply related [flat|nested] 38+ messages in thread
* Re: [Qemu-devel] [PULL 00/31] ppc patch queue 2013-01-07
2013-01-07 15:38 [Qemu-devel] [PULL 00/31] ppc patch queue 2013-01-07 Alexander Graf
` (30 preceding siblings ...)
2013-01-07 15:39 ` [Qemu-devel] [PATCH 31/31] PPC: linux-user: Calculate context pointer explicitly Alexander Graf
@ 2013-01-07 16:21 ` Andreas Färber
2013-01-07 16:40 ` Alexander Graf
31 siblings, 1 reply; 38+ messages in thread
From: Andreas Färber @ 2013-01-07 16:21 UTC (permalink / raw)
To: Alexander Graf; +Cc: Blue Swirl, qemu-ppc, qemu-devel, Aurelien Jarno
Am 07.01.2013 16:38, schrieb Alexander Graf:
> 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
--
SUSE LINUX Products GmbH, Maxfeldstr. 5, 90409 Nürnberg, Germany
GF: Jeff Hawn, Jennifer Guild, Felix Imendörffer; HRB 16746 AG Nürnberg
^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [Qemu-devel] [PULL 00/31] ppc patch queue 2013-01-07
2013-01-07 16:21 ` [Qemu-devel] [PULL 00/31] ppc patch queue 2013-01-07 Andreas Färber
@ 2013-01-07 16:40 ` Alexander Graf
2013-01-08 8:54 ` Stefan Hajnoczi
2013-01-12 16:13 ` Blue Swirl
0 siblings, 2 replies; 38+ messages in thread
From: Alexander Graf @ 2013-01-07 16:40 UTC (permalink / raw)
To: Andreas Färber
Cc: Blue Swirl, Stefan Hajnoczi,
<qemu-ppc@nongnu.org> list:PowerPC,
qemu-devel@nongnu.org qemu-devel, Aurelien Jarno
On 07.01.2013, at 17:21, Andreas Färber wrote:
> Am 07.01.2013 16:38, schrieb Alexander Graf:
>> 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.
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
^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [Qemu-devel] [PULL 00/31] ppc patch queue 2013-01-07
2013-01-07 16:40 ` Alexander Graf
@ 2013-01-08 8:54 ` Stefan Hajnoczi
2013-01-08 9:12 ` Alexander Graf
2013-01-08 15:49 ` Richard Henderson
2013-01-12 16:13 ` Blue Swirl
1 sibling, 2 replies; 38+ messages in thread
From: Stefan Hajnoczi @ 2013-01-08 8:54 UTC (permalink / raw)
To: Alexander Graf
Cc: Blue Swirl, <qemu-ppc@nongnu.org> list:PowerPC,
Andreas Färber, Aurelien Jarno,
qemu-devel@nongnu.org qemu-devel
On Mon, Jan 07, 2013 at 05:40:24PM +0100, Alexander Graf wrote:
>
> On 07.01.2013, at 17:21, Andreas Färber wrote:
>
> > Am 07.01.2013 16:38, schrieb Alexander Graf:
> >> 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.
>
> 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
^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [Qemu-devel] [PULL 00/31] ppc patch queue 2013-01-07
2013-01-08 8:54 ` Stefan Hajnoczi
@ 2013-01-08 9:12 ` Alexander Graf
2013-01-08 15:49 ` Richard Henderson
1 sibling, 0 replies; 38+ messages in thread
From: Alexander Graf @ 2013-01-08 9:12 UTC (permalink / raw)
To: Stefan Hajnoczi
Cc: Blue Swirl, <qemu-ppc@nongnu.org> list:PowerPC,
Andreas Färber, Aurelien Jarno,
qemu-devel@nongnu.org qemu-devel
Am 08.01.2013 um 09:54 schrieb Stefan Hajnoczi <stefanha@redhat.com>:
> On Mon, Jan 07, 2013 at 05:40:24PM +0100, Alexander Graf wrote:
>>
>> On 07.01.2013, at 17:21, Andreas Färber wrote:
>>
>>> Am 07.01.2013 16:38, schrieb Alexander Graf:
>>>> 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.
>>
>> 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
>
> Stefan
^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [Qemu-devel] [PULL 00/31] ppc patch queue 2013-01-07
2013-01-08 8:54 ` Stefan Hajnoczi
2013-01-08 9:12 ` Alexander Graf
@ 2013-01-08 15:49 ` Richard Henderson
1 sibling, 0 replies; 38+ messages in thread
From: Richard Henderson @ 2013-01-08 15:49 UTC (permalink / raw)
To: Stefan Hajnoczi
Cc: qemu-devel@nongnu.org qemu-devel, Alexander Graf, Blue Swirl,
<qemu-ppc@nongnu.org> list:PowerPC, Andreas Färber,
Aurelien Jarno
On 01/08/2013 12:54 AM, Stefan Hajnoczi wrote:
> agraf: "zypper search libfdt" on qemu-ppc.opensuse.org turns up no
> packages. Any ideas where to get the packages from?
Fedora 17 ships them. Either grab the packages from there, or
the rpm info points to
URL : http://git.jdl.com/gitweb/?p=dtc.git;a=summary
as the upstream source.
r~
^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [Qemu-devel] [PULL 00/31] ppc patch queue 2013-01-07
2013-01-07 16:40 ` Alexander Graf
2013-01-08 8:54 ` Stefan Hajnoczi
@ 2013-01-12 16:13 ` Blue Swirl
1 sibling, 0 replies; 38+ messages in thread
From: Blue Swirl @ 2013-01-12 16:13 UTC (permalink / raw)
To: Alexander Graf
Cc: Stefan Hajnoczi, <qemu-ppc@nongnu.org> list:PowerPC,
Andreas Färber, Aurelien Jarno,
qemu-devel@nongnu.org qemu-devel
On Mon, Jan 7, 2013 at 4:40 PM, Alexander Graf <agraf@suse.de> wrote:
>
> On 07.01.2013, at 17:21, Andreas Färber wrote:
>
>> Am 07.01.2013 16:38, schrieb Alexander Graf:
>>> 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.
>
> 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.
>
>
> Alex
>
^ permalink raw reply [flat|nested] 38+ messages in thread