mirror of
https://github.com/xemu-project/xemu.git
synced 2024-11-28 14:00:44 +00:00
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:
commit
261ccf426a
@ -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;
|
||||
|
@ -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. */
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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.
|
||||
|
@ -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));
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user