summaryrefslogtreecommitdiffstats
path: root/hw/intc
diff options
context:
space:
mode:
authorPeter Maydell2017-01-27 17:59:17 +0100
committerPeter Maydell2017-01-27 17:59:17 +0100
commit3aca12f841fcd6f3a7477076dad0d564360500de (patch)
tree269f5bbbc7ab4601758ed53938fb334cd5e699b2 /hw/intc
parentMerge remote-tracking branch 'remotes/armbru/tags/pull-qapi-2017-01-27' into ... (diff)
parentdma: omap: check dma channel data_type (diff)
downloadqemu-3aca12f841fcd6f3a7477076dad0d564360500de.tar.gz
qemu-3aca12f841fcd6f3a7477076dad0d564360500de.tar.xz
qemu-3aca12f841fcd6f3a7477076dad0d564360500de.zip
Merge remote-tracking branch 'remotes/pmaydell/tags/pull-target-arm-20170127' into staging
target-arm queue: * various minor M profile bugfixes * aspeed/smc: handle dummy bytes when doing fast reads in command mode * pflash_cfi01: fix per-device sector length in CFI table * arm: stellaris: make MII accesses complete immediately * hw/char/exynos4210_uart: Drop unused local variable frame_size * arm_gicv3: Fix broken logic in ELRSR calculation * dma: omap: check dma channel data_type # gpg: Signature made Fri 27 Jan 2017 15:29:39 GMT # gpg: using RSA key 0x3C2525ED14360CDE # gpg: Good signature from "Peter Maydell <peter.maydell@linaro.org>" # gpg: aka "Peter Maydell <pmaydell@gmail.com>" # gpg: aka "Peter Maydell <pmaydell@chiark.greenend.org.uk>" # Primary key fingerprint: E1A5 C593 CD41 9DE2 8E83 15CF 3C25 25ED 1436 0CDE * remotes/pmaydell/tags/pull-target-arm-20170127: (22 commits) dma: omap: check dma channel data_type arm_gicv3: Fix broken logic in ELRSR calculation hw/char/exynos4210_uart: Drop unused local variable frame_size arm: stellaris: make MII accesses complete immediately armv7m: R14 should reset to 0xffffffff armv7m: FAULTMASK should be 0 on reset armv7m: Honour CCR.USERSETMPEND armv7m: Report no-coprocessor faults correctly armv7m: set CFSR.UNDEFINSTR on undefined instructions armv7m: honour CCR.STACKALIGN on exception entry armv7m: implement CCR, CFSR, HFSR, DFSR, BFAR, and MMFAR armv7m: add state for v7M CCR, CFSR, HFSR, DFSR, MMFAR, BFAR armv7m_nvic: keep a pointer to the CPU target/arm: Drop IS_M() macro pflash_cfi01: fix per-device sector length in CFI table armv7m: Clear FAULTMASK on return from non-NMI exceptions armv7m: Fix reads of CONTROL register bit 1 hw/registerfields.h: Pull FIELD etc macros out of hw/register.h armv7m: Explicit error for bad vector table armv7m: Replace armv7m.hack with unassigned_access handler ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'hw/intc')
-rw-r--r--hw/intc/arm_gicv3_cpuif.c2
-rw-r--r--hw/intc/armv7m_nvic.c58
2 files changed, 42 insertions, 18 deletions
diff --git a/hw/intc/arm_gicv3_cpuif.c b/hw/intc/arm_gicv3_cpuif.c
index a9ee7fddf9..c25ee03556 100644
--- a/hw/intc/arm_gicv3_cpuif.c
+++ b/hw/intc/arm_gicv3_cpuif.c
@@ -2430,7 +2430,7 @@ static uint64_t ich_elrsr_read(CPUARMState *env, const ARMCPRegInfo *ri)
uint64_t lr = cs->ich_lr_el2[i];
if ((lr & ICH_LR_EL2_STATE_MASK) == 0 &&
- ((lr & ICH_LR_EL2_HW) == 1 || (lr & ICH_LR_EL2_EOI) == 0)) {
+ ((lr & ICH_LR_EL2_HW) != 0 || (lr & ICH_LR_EL2_EOI) == 0)) {
value |= (1 << i);
}
}
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
index 06d8db6bd6..fe5c303de9 100644
--- a/hw/intc/armv7m_nvic.c
+++ b/hw/intc/armv7m_nvic.c
@@ -23,6 +23,7 @@
typedef struct {
GICState gic;
+ ARMCPU *cpu;
struct {
uint32_t control;
uint32_t reload;
@@ -155,7 +156,7 @@ void armv7m_nvic_complete_irq(void *opaque, int irq)
static uint32_t nvic_readl(nvic_state *s, uint32_t offset)
{
- ARMCPU *cpu;
+ ARMCPU *cpu = s->cpu;
uint32_t val;
int irq;
@@ -187,11 +188,9 @@ static uint32_t nvic_readl(nvic_state *s, uint32_t offset)
case 0x1c: /* SysTick Calibration Value. */
return 10000;
case 0xd00: /* CPUID Base. */
- cpu = ARM_CPU(qemu_get_cpu(0));
return cpu->midr;
case 0xd04: /* Interrupt Control State. */
/* VECTACTIVE */
- cpu = ARM_CPU(qemu_get_cpu(0));
val = cpu->env.v7m.exception;
if (val == 1023) {
val = 0;
@@ -222,7 +221,6 @@ static uint32_t nvic_readl(nvic_state *s, uint32_t offset)
val |= (1 << 31);
return val;
case 0xd08: /* Vector Table Offset. */
- cpu = ARM_CPU(qemu_get_cpu(0));
return cpu->env.v7m.vecbase;
case 0xd0c: /* Application Interrupt/Reset Control. */
return 0xfa050000;
@@ -230,8 +228,7 @@ static uint32_t nvic_readl(nvic_state *s, uint32_t offset)
/* TODO: Implement SLEEPONEXIT. */
return 0;
case 0xd14: /* Configuration Control. */
- /* TODO: Implement Configuration Control bits. */
- return 0;
+ return cpu->env.v7m.ccr;
case 0xd24: /* System Handler Status. */
val = 0;
if (s->gic.irq_state[ARMV7M_EXCP_MEM].active) val |= (1 << 0);
@@ -250,16 +247,19 @@ static uint32_t nvic_readl(nvic_state *s, uint32_t offset)
if (s->gic.irq_state[ARMV7M_EXCP_USAGE].enabled) val |= (1 << 18);
return val;
case 0xd28: /* Configurable Fault Status. */
- /* TODO: Implement Fault Status. */
- qemu_log_mask(LOG_UNIMP, "Configurable Fault Status unimplemented\n");
- return 0;
+ return cpu->env.v7m.cfsr;
case 0xd2c: /* Hard Fault Status. */
+ return cpu->env.v7m.hfsr;
case 0xd30: /* Debug Fault Status. */
- case 0xd34: /* Mem Manage Address. */
+ return cpu->env.v7m.dfsr;
+ case 0xd34: /* MMFAR MemManage Fault Address */
+ return cpu->env.v7m.mmfar;
case 0xd38: /* Bus Fault Address. */
+ return cpu->env.v7m.bfar;
case 0xd3c: /* Aux Fault Status. */
/* TODO: Implement fault status registers. */
- qemu_log_mask(LOG_UNIMP, "Fault status registers unimplemented\n");
+ qemu_log_mask(LOG_UNIMP,
+ "Aux Fault status registers unimplemented\n");
return 0;
case 0xd40: /* PFR0. */
return 0x00000030;
@@ -296,7 +296,7 @@ static uint32_t nvic_readl(nvic_state *s, uint32_t offset)
static void nvic_writel(nvic_state *s, uint32_t offset, uint32_t value)
{
- ARMCPU *cpu;
+ ARMCPU *cpu = s->cpu;
uint32_t oldval;
switch (offset) {
case 0x10: /* SysTick Control and Status. */
@@ -349,7 +349,6 @@ static void nvic_writel(nvic_state *s, uint32_t offset, uint32_t value)
}
break;
case 0xd08: /* Vector Table Offset. */
- cpu = ARM_CPU(qemu_get_cpu(0));
cpu->env.v7m.vecbase = value & 0xffffff80;
break;
case 0xd0c: /* Application Interrupt/Reset Control. */
@@ -369,9 +368,19 @@ static void nvic_writel(nvic_state *s, uint32_t offset, uint32_t value)
}
break;
case 0xd10: /* System Control. */
- case 0xd14: /* Configuration Control. */
/* TODO: Implement control registers. */
- qemu_log_mask(LOG_UNIMP, "NVIC: SCR and CCR unimplemented\n");
+ qemu_log_mask(LOG_UNIMP, "NVIC: SCR unimplemented\n");
+ break;
+ case 0xd14: /* Configuration Control. */
+ /* Enforce RAZ/WI on reserved and must-RAZ/WI bits */
+ value &= (R_V7M_CCR_STKALIGN_MASK |
+ R_V7M_CCR_BFHFNMIGN_MASK |
+ R_V7M_CCR_DIV_0_TRP_MASK |
+ R_V7M_CCR_UNALIGN_TRP_MASK |
+ R_V7M_CCR_USERSETMPEND_MASK |
+ R_V7M_CCR_NONBASETHRDENA_MASK);
+
+ cpu->env.v7m.ccr = value;
break;
case 0xd24: /* System Handler Control. */
/* TODO: Real hardware allows you to set/clear the active bits
@@ -381,16 +390,29 @@ static void nvic_writel(nvic_state *s, uint32_t offset, uint32_t value)
s->gic.irq_state[ARMV7M_EXCP_USAGE].enabled = (value & (1 << 18)) != 0;
break;
case 0xd28: /* Configurable Fault Status. */
+ cpu->env.v7m.cfsr &= ~value; /* W1C */
+ break;
case 0xd2c: /* Hard Fault Status. */
+ cpu->env.v7m.hfsr &= ~value; /* W1C */
+ break;
case 0xd30: /* Debug Fault Status. */
+ cpu->env.v7m.dfsr &= ~value; /* W1C */
+ break;
case 0xd34: /* Mem Manage Address. */
+ cpu->env.v7m.mmfar = value;
+ return;
case 0xd38: /* Bus Fault Address. */
+ cpu->env.v7m.bfar = value;
+ return;
case 0xd3c: /* Aux Fault Status. */
qemu_log_mask(LOG_UNIMP,
- "NVIC: fault status registers unimplemented\n");
+ "NVIC: Aux fault status registers unimplemented\n");
break;
case 0xf00: /* Software Triggered Interrupt Register */
- if ((value & 0x1ff) < s->num_irq) {
+ /* user mode can only write to STIR if CCR.USERSETMPEND permits it */
+ if ((value & 0x1ff) < s->num_irq &&
+ (arm_current_el(&cpu->env) ||
+ (cpu->env.v7m.ccr & R_V7M_CCR_USERSETMPEND_MASK))) {
gic_set_pending_private(&s->gic, 0, value & 0x1ff);
}
break;
@@ -495,6 +517,8 @@ static void armv7m_nvic_realize(DeviceState *dev, Error **errp)
NVICClass *nc = NVIC_GET_CLASS(s);
Error *local_err = NULL;
+ s->cpu = ARM_CPU(qemu_get_cpu(0));
+ assert(s->cpu);
/* The NVIC always has only one CPU */
s->gic.num_cpu = 1;
/* Tell the common code we're an NVIC */