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
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1
 
 iQIcBAABCAAGBQJVmlFDAAoJEDwlJe0UNgze9y8P/1dOW0fITZo9Ld3fIVqJL4lK
 9Ihkq9FzCrui0XYoXoP7VBD3qGJE6KdICP1IMvvyEEbgbnMMRa0yXL3pwODRxV0Q
 8qNlH4HZyzxYUuT+lHTs7YLgPOOi+UFE/i7ekQBlmdLwBdYvohQAJzjRTMrfLtnv
 SmB/I+Q5dIp/5FMe2hk1sUZslejMhr/ErDtiFa4w5jEYqHzsPiXlUytVhFIQ7UQI
 4OZpQ6SHG65AsnehUp79HPhBSrBpT18j61w3aUYmkn0ENIo1JQdsdoGx09dK6HHF
 tvQG2sKus0VJmiBJxFN8Rth+pFGyJTeZztTGodU+DlqXl09AykBXMZ6FG4VZLMo5
 zw2nK22dBIfMO8suRdYZ6Fk3V4MUoiASrItQp/QuflW2oKHc/gF0/RFX6KkFYdqG
 UJhQA0Kx/rQzMeNcMwQVZh4jLQtdh9dbRFmY0Lf23BY5+mDfRx1+Z/wSXEc3eSH7
 Y7KnjETfkJ21Xf5E+69Aud8yt5puiMywu0/EP03ihl/THMyKiSiVLzRh0sKNTp2j
 O5neBiypDusqG3dvUYXDWg5y7BO3IoTUtBPkTgKpEe3LaN8g7WkglMmfHeEQeLp2
 cXXrhfZ/mbnW4x6Jd+xJIjUEBcS3prr1Exa9p9+9lvV7fJSoS7MVBD4bRWMe5FvX
 BGktZFm/DGdUSkxL3gne
 =bBka
 -----END PGP SIGNATURE-----

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>
This commit is contained in:
Peter Maydell 2015-07-06 11:04:54 +01:00
commit 261ccf426a
9 changed files with 63 additions and 15 deletions

View file

@ -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;

View file

@ -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. */

View file

@ -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);
}

View file

@ -2441,7 +2441,7 @@ static const ARMCPRegInfo v8_cp_reginfo[] = {
{ .name = "TLBI_ALLE1IS", .state = ARM_CP_STATE_AA64,
.opc0 = 1, .opc1 = 4, .crn = 8, .crm = 3, .opc2 = 4,
.access = PL2_W, .type = ARM_CP_NO_RAW,
.writefn = tlbiall_write },
.writefn = tlbiall_is_write },
{ .name = "TLBI_VMALLE1IS", .state = ARM_CP_STATE_AA64,
.opc0 = 1, .opc1 = 0, .crn = 8, .crm = 3, .opc2 = 0,
.access = PL1_W, .type = ARM_CP_NO_RAW,

View file

@ -50,6 +50,7 @@ DEF_HELPER_2(exception_internal, void, env, i32)
DEF_HELPER_4(exception_with_syndrome, void, env, i32, i32, i32)
DEF_HELPER_1(wfi, void, env)
DEF_HELPER_1(wfe, void, env)
DEF_HELPER_1(yield, void, env)
DEF_HELPER_1(pre_hvc, void, env)
DEF_HELPER_2(pre_smc, void, env, i32)

View file

@ -323,13 +323,25 @@ void HELPER(wfi)(CPUARMState *env)
void HELPER(wfe)(CPUARMState *env)
{
CPUState *cs = CPU(arm_env_get_cpu(env));
/* Don't actually halt the CPU, just yield back to top
/* This is a hint instruction that is semantically different
* from YIELD even though we currently implement it identically.
* Don't actually halt the CPU, just yield back to top
* level loop. This is not going into a "low power state"
* (ie halting until some event occurs), so we never take
* a configurable trap to a different exception level.
*/
HELPER(yield)(env);
}
void HELPER(yield)(CPUARMState *env)
{
ARMCPU *cpu = arm_env_get_cpu(env);
CPUState *cs = CPU(cpu);
/* This is a non-trappable hint instruction that generally indicates
* that the guest is currently busy-looping. Yield control back to the
* top level loop so that a more deserving VCPU has a chance to run.
*/
cs->exception_index = EXCP_YIELD;
cpu_loop_exit(cs);
}

View file

@ -1199,6 +1199,8 @@ static void handle_hint(DisasContext *s, uint32_t insn,
s->is_jmp = DISAS_WFI;
return;
case 1: /* YIELD */
s->is_jmp = DISAS_YIELD;
return;
case 2: /* WFE */
s->is_jmp = DISAS_WFE;
return;
@ -11107,6 +11109,10 @@ void gen_intermediate_code_internal_a64(ARMCPU *cpu,
gen_a64_set_pc_im(dc->pc);
gen_helper_wfe(cpu_env);
break;
case DISAS_YIELD:
gen_a64_set_pc_im(dc->pc);
gen_helper_yield(cpu_env);
break;
case DISAS_WFI:
/* This is a special case because we don't want to just halt the CPU
* if trying to debug across a WFI.

View file

@ -4080,6 +4080,10 @@ static void gen_rfe(DisasContext *s, TCGv_i32 pc, TCGv_i32 cpsr)
static void gen_nop_hint(DisasContext *s, int val)
{
switch (val) {
case 1: /* yield */
gen_set_pc_im(s, s->pc);
s->is_jmp = DISAS_YIELD;
break;
case 3: /* wfi */
gen_set_pc_im(s, s->pc);
s->is_jmp = DISAS_WFI;
@ -11459,6 +11463,9 @@ static inline void gen_intermediate_code_internal(ARMCPU *cpu,
case DISAS_WFE:
gen_helper_wfe(cpu_env);
break;
case DISAS_YIELD:
gen_helper_yield(cpu_env);
break;
case DISAS_SWI:
gen_exception(EXCP_SWI, syn_aa32_svc(dc->svc_imm, dc->thumb),
default_exception_el(dc));

View file

@ -103,6 +103,7 @@ static inline int default_exception_el(DisasContext *s)
#define DISAS_WFE 7
#define DISAS_HVC 8
#define DISAS_SMC 9
#define DISAS_YIELD 10
#ifdef TARGET_AARCH64
void a64_translate_init(void);