diff options
author | Peter Maydell <peter.maydell@linaro.org> | 2015-07-06 11:04:54 +0100 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2015-07-06 11:04:54 +0100 |
commit | 261ccf426a6df854ba398be92413476919dd67f9 (patch) | |
tree | e72d79039c7a01270f4869331f5aecd2840dc264 /hw | |
parent | f50a1640fb82708a5d528dee1ace42a224b95b15 (diff) | |
parent | 257621a9566054472d1d55a819880d0f9da02bda (diff) |
Merge remote-tracking branch 'remotes/pmaydell/tags/pull-target-arm-20150706' into staging
target-arm queue:
* TLBI ALLEI1IS should operate on all CPUs, not just this one
* Fix interval interrupt of cadence ttc in decrement mode
* Implement YIELD insn to yield in ARM and Thumb translators
* ARM GIC: reset all registers
* arm_mptimer: fix timer shutdown and mode change
* arm_mptimer: respect IT bit state
# gpg: Signature made Mon Jul 6 10:58:27 2015 BST using RSA key ID 14360CDE
# gpg: Good signature from "Peter Maydell <peter.maydell@linaro.org>"
* remotes/pmaydell/tags/pull-target-arm-20150706:
arm_mptimer: Respect IT bit state
arm_mptimer: Fix timer shutdown and mode change
hw/intc/arm_gic_common.c: Reset all registers
target-arm: Implement YIELD insn to yield in ARM and Thumb translators
target-arm: Split DISAS_YIELD from DISAS_WFE
Fix interval interrupt of cadence ttc when timer is in decrement mode
target-arm: fix write helper for TLBI ALLE1IS
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'hw')
-rw-r--r-- | hw/intc/arm_gic_common.c | 21 | ||||
-rw-r--r-- | hw/timer/arm_mptimer.c | 13 | ||||
-rw-r--r-- | hw/timer/cadence_ttc.c | 9 |
3 files changed, 32 insertions, 11 deletions
diff --git a/hw/intc/arm_gic_common.c b/hw/intc/arm_gic_common.c index 044ad66730..a64d0714ea 100644 --- a/hw/intc/arm_gic_common.c +++ b/hw/intc/arm_gic_common.c @@ -123,7 +123,7 @@ static void arm_gic_common_realize(DeviceState *dev, Error **errp) static void arm_gic_common_reset(DeviceState *dev) { GICState *s = ARM_GIC_COMMON(dev); - int i; + int i, j; memset(s->irq_state, 0, GIC_MAXIRQ * sizeof(gic_irq_state)); for (i = 0 ; i < s->num_cpu; i++) { if (s->revision == REV_11MPCORE) { @@ -135,15 +135,30 @@ static void arm_gic_common_reset(DeviceState *dev) s->running_irq[i] = 1023; s->running_priority[i] = 0x100; s->cpu_ctlr[i] = 0; + s->bpr[i] = GIC_MIN_BPR; + s->abpr[i] = GIC_MIN_ABPR; + for (j = 0; j < GIC_INTERNAL; j++) { + s->priority1[j][i] = 0; + } + for (j = 0; j < GIC_NR_SGIS; j++) { + s->sgi_pending[j][i] = 0; + } } for (i = 0; i < GIC_NR_SGIS; i++) { GIC_SET_ENABLED(i, ALL_CPU_MASK); GIC_SET_EDGE_TRIGGER(i); } - if (s->num_cpu == 1) { + + for (i = 0; i < ARRAY_SIZE(s->priority2); i++) { + s->priority2[i] = 0; + } + + for (i = 0; i < GIC_MAXIRQ; i++) { /* For uniprocessor GICs all interrupts always target the sole CPU */ - for (i = 0; i < GIC_MAXIRQ; i++) { + if (s->num_cpu == 1) { s->irq_target[i] = 1; + } else { + s->irq_target[i] = 0; } } s->ctlr = 0; diff --git a/hw/timer/arm_mptimer.c b/hw/timer/arm_mptimer.c index 8b93b3c1ae..3e59c2a288 100644 --- a/hw/timer/arm_mptimer.c +++ b/hw/timer/arm_mptimer.c @@ -38,7 +38,7 @@ static inline int get_current_cpu(ARMMPTimerState *s) static inline void timerblock_update_irq(TimerBlock *tb) { - qemu_set_irq(tb->irq, tb->status); + qemu_set_irq(tb->irq, tb->status && (tb->control & 4)); } /* Return conversion factor from mpcore timer ticks to qemu timer ticks. */ @@ -122,11 +122,18 @@ static void timerblock_write(void *opaque, hwaddr addr, case 8: /* Control. */ old = tb->control; tb->control = value; - if (((old & 1) == 0) && (value & 1)) { - if (tb->count == 0 && (tb->control & 2)) { + if (value & 1) { + if ((old & 1) && (tb->count != 0)) { + /* Do nothing if timer is ticking right now. */ + break; + } + if (tb->control & 2) { tb->count = tb->load; } timerblock_reload(tb, 1); + } else if (old & 1) { + /* Shutdown the timer. */ + timer_del(tb->timer); } break; case 12: /* Interrupt status. */ diff --git a/hw/timer/cadence_ttc.c b/hw/timer/cadence_ttc.c index d46db3c0e2..35bc88033e 100644 --- a/hw/timer/cadence_ttc.c +++ b/hw/timer/cadence_ttc.c @@ -208,15 +208,14 @@ static void cadence_timer_sync(CadenceTimerState *s) s->reg_intr |= (2 << i); } } + if ((x < 0) || (x >= interval)) { + s->reg_intr |= (s->reg_count & COUNTER_CTRL_INT) ? + COUNTER_INTR_IV : COUNTER_INTR_OV; + } while (x < 0) { x += interval; } s->reg_value = (uint32_t)(x % interval); - - if (s->reg_value != x) { - s->reg_intr |= (s->reg_count & COUNTER_CTRL_INT) ? - COUNTER_INTR_IV : COUNTER_INTR_OV; - } cadence_timer_update(s); } |