aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2018-11-13 10:52:32 +0000
committerPeter Maydell <peter.maydell@linaro.org>2018-11-13 10:52:32 +0000
commita8a1b163b7433fee312aa5896a7385ae328a684f (patch)
treef3a51e994dc3ec89ca973a331151e1e1ae1d54be
parent6db87aae61bc6ac0a8cd9bc2e05d7ebfbcfd3657 (diff)
parent436c0cbbeb38dd97c02fe921a7cb253a18afdd86 (diff)
Merge remote-tracking branch 'remotes/pmaydell/tags/pull-target-arm-20181113' into staging
target/arm queue: * Remove no-longer-needed workaround for small SAU regions for v8M * Remove antique TODO comment * MAINTAINERS: Add an entry for the 'collie' machine * hw/arm/sysbus-fdt: Only call match_fn callback if the type matches * Fix infinite recursion in tlbi_aa64_vmalle1_write() * ARM KVM: fix various bugs in handling of guest debugging * Correctly implement handling of HCR_EL2.{VI, VF} * Hyp mode R14 is shared with User and System * Give Cortex-A15 and -A7 the EL2 feature # gpg: Signature made Tue 13 Nov 2018 10:51:53 GMT # gpg: using RSA key 3C2525ED14360CDE # 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-20181113: target/arm/cpu: Give Cortex-A15 and -A7 the EL2 feature target/arm: Hyp mode R14 is shared with User and System target/arm: Correctly implement handling of HCR_EL2.{VI, VF} target/arm: Track the state of our irq lines from the GIC explicitly Revert "target/arm: Implement HCR.VI and VF" arm: fix aa64_generate_debug_exceptions to work with EL2 arm: use symbolic MDCR_TDE in arm_debug_target_el tests/guest-debug: fix scoping of failcount target/arm64: kvm debug set target_el when passing exception to guest target/arm64: hold BQL when calling do_interrupt() target/arm64: properly handle DBGVR RESS bits target/arm: Fix typo in tlbi_aa64_vmalle1_write hw/arm/sysbus-fdt: Only call match_fn callback if the type matches MAINTAINERS: Add an entry for the 'collie' machine target/arm: Remove antique TODO comment target/arm: Remove workaround for small SAU regions Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
-rw-r--r--MAINTAINERS7
-rw-r--r--hw/arm/sysbus-fdt.c12
-rw-r--r--target/arm/cpu.c67
-rw-r--r--target/arm/cpu.h44
-rw-r--r--target/arm/helper.c101
-rw-r--r--target/arm/internals.h34
-rw-r--r--target/arm/kvm32.c4
-rw-r--r--target/arm/kvm64.c20
-rw-r--r--target/arm/machine.c51
-rw-r--r--target/arm/op_helper.c4
-rw-r--r--tests/guest-debug/test-gdbstub.py1
11 files changed, 249 insertions, 96 deletions
diff --git a/MAINTAINERS b/MAINTAINERS
index c076758b3d..4b8db618f5 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -591,6 +591,13 @@ F: hw/*/pxa2xx*
F: hw/misc/mst_fpga.c
F: include/hw/arm/pxa.h
+Sharp SL-5500 (Collie) PDA
+M: Peter Maydell <peter.maydell@linaro.org>
+L: qemu-arm@nongnu.org
+S: Odd Fixes
+F: hw/arm/collie.c
+F: hw/arm/strongarm*
+
Stellaris
M: Peter Maydell <peter.maydell@linaro.org>
L: qemu-arm@nongnu.org
diff --git a/hw/arm/sysbus-fdt.c b/hw/arm/sysbus-fdt.c
index 0e24c803a1..ad698d4832 100644
--- a/hw/arm/sysbus-fdt.c
+++ b/hw/arm/sysbus-fdt.c
@@ -449,7 +449,7 @@ static bool type_match(SysBusDevice *sbdev, const BindingEntry *entry)
return !strcmp(object_get_typename(OBJECT(sbdev)), entry->typename);
}
-#define TYPE_BINDING(type, add_fn) {(type), NULL, (add_fn), type_match}
+#define TYPE_BINDING(type, add_fn) {(type), NULL, (add_fn), NULL}
/* list of supported dynamic sysbus bindings */
static const BindingEntry bindings[] = {
@@ -481,10 +481,12 @@ static void add_fdt_node(SysBusDevice *sbdev, void *opaque)
for (i = 0; i < ARRAY_SIZE(bindings); i++) {
const BindingEntry *iter = &bindings[i];
- if (iter->match_fn(sbdev, iter)) {
- ret = iter->add_fn(sbdev, opaque);
- assert(!ret);
- return;
+ if (type_match(sbdev, iter)) {
+ if (!iter->match_fn || iter->match_fn(sbdev, iter)) {
+ ret = iter->add_fn(sbdev, opaque);
+ assert(!ret);
+ return;
+ }
}
}
error_report("Device %s can not be dynamically instantiated",
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
index 784a4c2dfc..60411f6bfe 100644
--- a/target/arm/cpu.c
+++ b/target/arm/cpu.c
@@ -436,6 +436,48 @@ static bool arm_v7m_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
}
#endif
+void arm_cpu_update_virq(ARMCPU *cpu)
+{
+ /*
+ * Update the interrupt level for VIRQ, which is the logical OR of
+ * the HCR_EL2.VI bit and the input line level from the GIC.
+ */
+ CPUARMState *env = &cpu->env;
+ CPUState *cs = CPU(cpu);
+
+ bool new_state = (env->cp15.hcr_el2 & HCR_VI) ||
+ (env->irq_line_state & CPU_INTERRUPT_VIRQ);
+
+ if (new_state != ((cs->interrupt_request & CPU_INTERRUPT_VIRQ) != 0)) {
+ if (new_state) {
+ cpu_interrupt(cs, CPU_INTERRUPT_VIRQ);
+ } else {
+ cpu_reset_interrupt(cs, CPU_INTERRUPT_VIRQ);
+ }
+ }
+}
+
+void arm_cpu_update_vfiq(ARMCPU *cpu)
+{
+ /*
+ * Update the interrupt level for VFIQ, which is the logical OR of
+ * the HCR_EL2.VF bit and the input line level from the GIC.
+ */
+ CPUARMState *env = &cpu->env;
+ CPUState *cs = CPU(cpu);
+
+ bool new_state = (env->cp15.hcr_el2 & HCR_VF) ||
+ (env->irq_line_state & CPU_INTERRUPT_VFIQ);
+
+ if (new_state != ((cs->interrupt_request & CPU_INTERRUPT_VFIQ) != 0)) {
+ if (new_state) {
+ cpu_interrupt(cs, CPU_INTERRUPT_VFIQ);
+ } else {
+ cpu_reset_interrupt(cs, CPU_INTERRUPT_VFIQ);
+ }
+ }
+}
+
#ifndef CONFIG_USER_ONLY
static void arm_cpu_set_irq(void *opaque, int irq, int level)
{
@@ -449,11 +491,21 @@ static void arm_cpu_set_irq(void *opaque, int irq, int level)
[ARM_CPU_VFIQ] = CPU_INTERRUPT_VFIQ
};
+ if (level) {
+ env->irq_line_state |= mask[irq];
+ } else {
+ env->irq_line_state &= ~mask[irq];
+ }
+
switch (irq) {
case ARM_CPU_VIRQ:
+ assert(arm_feature(env, ARM_FEATURE_EL2));
+ arm_cpu_update_virq(cpu);
+ break;
case ARM_CPU_VFIQ:
assert(arm_feature(env, ARM_FEATURE_EL2));
- /* fall through */
+ arm_cpu_update_vfiq(cpu);
+ break;
case ARM_CPU_IRQ:
case ARM_CPU_FIQ:
if (level) {
@@ -471,19 +523,30 @@ static void arm_cpu_kvm_set_irq(void *opaque, int irq, int level)
{
#ifdef CONFIG_KVM
ARMCPU *cpu = opaque;
+ CPUARMState *env = &cpu->env;
CPUState *cs = CPU(cpu);
int kvm_irq = KVM_ARM_IRQ_TYPE_CPU << KVM_ARM_IRQ_TYPE_SHIFT;
+ uint32_t linestate_bit;
switch (irq) {
case ARM_CPU_IRQ:
kvm_irq |= KVM_ARM_IRQ_CPU_IRQ;
+ linestate_bit = CPU_INTERRUPT_HARD;
break;
case ARM_CPU_FIQ:
kvm_irq |= KVM_ARM_IRQ_CPU_FIQ;
+ linestate_bit = CPU_INTERRUPT_FIQ;
break;
default:
g_assert_not_reached();
}
+
+ if (level) {
+ env->irq_line_state |= linestate_bit;
+ } else {
+ env->irq_line_state &= ~linestate_bit;
+ }
+
kvm_irq |= cs->cpu_index << KVM_ARM_IRQ_VCPU_SHIFT;
kvm_set_irq(kvm_state, kvm_irq, level ? 1 : 0);
#endif
@@ -1587,6 +1650,7 @@ static void cortex_a7_initfn(Object *obj)
set_feature(&cpu->env, ARM_FEATURE_GENERIC_TIMER);
set_feature(&cpu->env, ARM_FEATURE_DUMMY_C15_REGS);
set_feature(&cpu->env, ARM_FEATURE_CBAR_RO);
+ set_feature(&cpu->env, ARM_FEATURE_EL2);
set_feature(&cpu->env, ARM_FEATURE_EL3);
cpu->kvm_target = QEMU_KVM_ARM_TARGET_CORTEX_A7;
cpu->midr = 0x410fc075;
@@ -1633,6 +1697,7 @@ static void cortex_a15_initfn(Object *obj)
set_feature(&cpu->env, ARM_FEATURE_GENERIC_TIMER);
set_feature(&cpu->env, ARM_FEATURE_DUMMY_C15_REGS);
set_feature(&cpu->env, ARM_FEATURE_CBAR_RO);
+ set_feature(&cpu->env, ARM_FEATURE_EL2);
set_feature(&cpu->env, ARM_FEATURE_EL3);
cpu->kvm_target = QEMU_KVM_ARM_TARGET_CORTEX_A15;
cpu->midr = 0x412fc0f1;
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index b5eff79f73..2a73fed9a0 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -538,6 +538,9 @@ typedef struct CPUARMState {
uint64_t esr;
} serror;
+ /* State of our input IRQ/FIQ/VIRQ/VFIQ lines */
+ uint32_t irq_line_state;
+
/* Thumb-2 EE state. */
uint32_t teecr;
uint32_t teehbr;
@@ -2743,7 +2746,7 @@ static inline int arm_debug_target_el(CPUARMState *env)
if (arm_feature(env, ARM_FEATURE_EL2) && !secure) {
route_to_el2 = env->cp15.hcr_el2 & HCR_TGE ||
- env->cp15.mdcr_el2 & (1 << 8);
+ env->cp15.mdcr_el2 & MDCR_TDE;
}
if (route_to_el2) {
@@ -2764,23 +2767,35 @@ static inline bool arm_v7m_csselr_razwi(ARMCPU *cpu)
return (cpu->clidr & R_V7M_CLIDR_CTYPE_ALL_MASK) != 0;
}
+/* See AArch64.GenerateDebugExceptionsFrom() in ARM ARM pseudocode */
static inline bool aa64_generate_debug_exceptions(CPUARMState *env)
{
- if (arm_is_secure(env)) {
- /* MDCR_EL3.SDD disables debug events from Secure state */
- if (extract32(env->cp15.mdcr_el3, 16, 1) != 0
- || arm_current_el(env) == 3) {
- return false;
- }
+ int cur_el = arm_current_el(env);
+ int debug_el;
+
+ if (cur_el == 3) {
+ return false;
}
- if (arm_current_el(env) == arm_debug_target_el(env)) {
- if ((extract32(env->cp15.mdscr_el1, 13, 1) == 0)
- || (env->daif & PSTATE_D)) {
- return false;
- }
+ /* MDCR_EL3.SDD disables debug events from Secure state */
+ if (arm_is_secure_below_el3(env)
+ && extract32(env->cp15.mdcr_el3, 16, 1)) {
+ return false;
}
- return true;
+
+ /*
+ * Same EL to same EL debug exceptions need MDSCR_KDE enabled
+ * while not masking the (D)ebug bit in DAIF.
+ */
+ debug_el = arm_debug_target_el(env);
+
+ if (cur_el == debug_el) {
+ return extract32(env->cp15.mdscr_el1, 13, 1)
+ && !(env->daif & PSTATE_D);
+ }
+
+ /* Otherwise the debug target needs to be a higher EL */
+ return debug_el > cur_el;
}
static inline bool aa32_generate_debug_exceptions(CPUARMState *env)
@@ -2833,9 +2848,6 @@ static inline bool aa32_generate_debug_exceptions(CPUARMState *env)
* since the pseudocode has it at all callsites except for the one in
* CheckSoftwareStep(), where it is elided because both branches would
* always return the same value.
- *
- * Parts of the pseudocode relating to EL2 and EL3 are omitted because we
- * don't yet implement those exception levels or their associated trap bits.
*/
static inline bool arm_generate_debug_exceptions(CPUARMState *env)
{
diff --git a/target/arm/helper.c b/target/arm/helper.c
index 96301930cc..0da1424f72 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -3155,7 +3155,7 @@ static void tlbi_aa64_vmalle1_write(CPUARMState *env, const ARMCPRegInfo *ri,
CPUState *cs = ENV_GET_CPU(env);
if (tlb_force_broadcast(env)) {
- tlbi_aa64_vmalle1_write(env, NULL, value);
+ tlbi_aa64_vmalle1is_write(env, NULL, value);
return;
}
@@ -3931,7 +3931,6 @@ static const ARMCPRegInfo el3_no_el2_v8_cp_reginfo[] = {
static void hcr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
{
ARMCPU *cpu = arm_env_get_cpu(env);
- CPUState *cs = ENV_GET_CPU(env);
uint64_t valid_mask = HCR_MASK;
if (arm_feature(env, ARM_FEATURE_EL3)) {
@@ -3950,28 +3949,6 @@ static void hcr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
/* Clear RES0 bits. */
value &= valid_mask;
- /*
- * VI and VF are kept in cs->interrupt_request. Modifying that
- * requires that we have the iothread lock, which is done by
- * marking the reginfo structs as ARM_CP_IO.
- * Note that if a write to HCR pends a VIRQ or VFIQ it is never
- * possible for it to be taken immediately, because VIRQ and
- * VFIQ are masked unless running at EL0 or EL1, and HCR
- * can only be written at EL2.
- */
- g_assert(qemu_mutex_iothread_locked());
- if (value & HCR_VI) {
- cs->interrupt_request |= CPU_INTERRUPT_VIRQ;
- } else {
- cs->interrupt_request &= ~CPU_INTERRUPT_VIRQ;
- }
- if (value & HCR_VF) {
- cs->interrupt_request |= CPU_INTERRUPT_VFIQ;
- } else {
- cs->interrupt_request &= ~CPU_INTERRUPT_VFIQ;
- }
- value &= ~(HCR_VI | HCR_VF);
-
/* These bits change the MMU setup:
* HCR_VM enables stage 2 translation
* HCR_PTW forbids certain page-table setups
@@ -3981,6 +3958,21 @@ static void hcr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
tlb_flush(CPU(cpu));
}
env->cp15.hcr_el2 = value;
+
+ /*
+ * Updates to VI and VF require us to update the status of
+ * virtual interrupts, which are the logical OR of these bits
+ * and the state of the input lines from the GIC. (This requires
+ * that we have the iothread lock, which is done by marking the
+ * reginfo structs as ARM_CP_IO.)
+ * Note that if a write to HCR pends a VIRQ or VFIQ it is never
+ * possible for it to be taken immediately, because VIRQ and
+ * VFIQ are masked unless running at EL0 or EL1, and HCR
+ * can only be written at EL2.
+ */
+ g_assert(qemu_mutex_iothread_locked());
+ arm_cpu_update_virq(cpu);
+ arm_cpu_update_vfiq(cpu);
}
static void hcr_writehigh(CPUARMState *env, const ARMCPRegInfo *ri,
@@ -3999,32 +3991,17 @@ static void hcr_writelow(CPUARMState *env, const ARMCPRegInfo *ri,
hcr_write(env, NULL, value);
}
-static uint64_t hcr_read(CPUARMState *env, const ARMCPRegInfo *ri)
-{
- /* The VI and VF bits live in cs->interrupt_request */
- uint64_t ret = env->cp15.hcr_el2 & ~(HCR_VI | HCR_VF);
- CPUState *cs = ENV_GET_CPU(env);
-
- if (cs->interrupt_request & CPU_INTERRUPT_VIRQ) {
- ret |= HCR_VI;
- }
- if (cs->interrupt_request & CPU_INTERRUPT_VFIQ) {
- ret |= HCR_VF;
- }
- return ret;
-}
-
static const ARMCPRegInfo el2_cp_reginfo[] = {
{ .name = "HCR_EL2", .state = ARM_CP_STATE_AA64,
.type = ARM_CP_IO,
.opc0 = 3, .opc1 = 4, .crn = 1, .crm = 1, .opc2 = 0,
.access = PL2_RW, .fieldoffset = offsetof(CPUARMState, cp15.hcr_el2),
- .writefn = hcr_write, .readfn = hcr_read },
+ .writefn = hcr_write },
{ .name = "HCR", .state = ARM_CP_STATE_AA32,
.type = ARM_CP_ALIAS | ARM_CP_IO,
.cp = 15, .opc1 = 4, .crn = 1, .crm = 1, .opc2 = 0,
.access = PL2_RW, .fieldoffset = offsetof(CPUARMState, cp15.hcr_el2),
- .writefn = hcr_writelow, .readfn = hcr_read },
+ .writefn = hcr_writelow },
{ .name = "ELR_EL2", .state = ARM_CP_STATE_AA64,
.type = ARM_CP_ALIAS,
.opc0 = 3, .opc1 = 4, .crn = 4, .crm = 0, .opc2 = 1,
@@ -6455,13 +6432,14 @@ static void switch_mode(CPUARMState *env, int mode)
i = bank_number(old_mode);
env->banked_r13[i] = env->regs[13];
- env->banked_r14[i] = env->regs[14];
env->banked_spsr[i] = env->spsr;
i = bank_number(mode);
env->regs[13] = env->banked_r13[i];
- env->regs[14] = env->banked_r14[i];
env->spsr = env->banked_spsr[i];
+
+ env->banked_r14[r14_bank_number(old_mode)] = env->regs[14];
+ env->regs[14] = env->banked_r14[r14_bank_number(mode)];
}
/* Physical Interrupt Target EL Lookup Table
@@ -8040,7 +8018,7 @@ void aarch64_sync_32_to_64(CPUARMState *env)
if (mode == ARM_CPU_MODE_HYP) {
env->xregs[14] = env->regs[14];
} else {
- env->xregs[14] = env->banked_r14[bank_number(ARM_CPU_MODE_USR)];
+ env->xregs[14] = env->banked_r14[r14_bank_number(ARM_CPU_MODE_USR)];
}
}
@@ -8054,7 +8032,7 @@ void aarch64_sync_32_to_64(CPUARMState *env)
env->xregs[16] = env->regs[14];
env->xregs[17] = env->regs[13];
} else {
- env->xregs[16] = env->banked_r14[bank_number(ARM_CPU_MODE_IRQ)];
+ env->xregs[16] = env->banked_r14[r14_bank_number(ARM_CPU_MODE_IRQ)];
env->xregs[17] = env->banked_r13[bank_number(ARM_CPU_MODE_IRQ)];
}
@@ -8062,7 +8040,7 @@ void aarch64_sync_32_to_64(CPUARMState *env)
env->xregs[18] = env->regs[14];
env->xregs[19] = env->regs[13];
} else {
- env->xregs[18] = env->banked_r14[bank_number(ARM_CPU_MODE_SVC)];
+ env->xregs[18] = env->banked_r14[r14_bank_number(ARM_CPU_MODE_SVC)];
env->xregs[19] = env->banked_r13[bank_number(ARM_CPU_MODE_SVC)];
}
@@ -8070,7 +8048,7 @@ void aarch64_sync_32_to_64(CPUARMState *env)
env->xregs[20] = env->regs[14];
env->xregs[21] = env->regs[13];
} else {
- env->xregs[20] = env->banked_r14[bank_number(ARM_CPU_MODE_ABT)];
+ env->xregs[20] = env->banked_r14[r14_bank_number(ARM_CPU_MODE_ABT)];
env->xregs[21] = env->banked_r13[bank_number(ARM_CPU_MODE_ABT)];
}
@@ -8078,7 +8056,7 @@ void aarch64_sync_32_to_64(CPUARMState *env)
env->xregs[22] = env->regs[14];
env->xregs[23] = env->regs[13];
} else {
- env->xregs[22] = env->banked_r14[bank_number(ARM_CPU_MODE_UND)];
+ env->xregs[22] = env->banked_r14[r14_bank_number(ARM_CPU_MODE_UND)];
env->xregs[23] = env->banked_r13[bank_number(ARM_CPU_MODE_UND)];
}
@@ -8095,7 +8073,7 @@ void aarch64_sync_32_to_64(CPUARMState *env)
env->xregs[i] = env->fiq_regs[i - 24];
}
env->xregs[29] = env->banked_r13[bank_number(ARM_CPU_MODE_FIQ)];
- env->xregs[30] = env->banked_r14[bank_number(ARM_CPU_MODE_FIQ)];
+ env->xregs[30] = env->banked_r14[r14_bank_number(ARM_CPU_MODE_FIQ)];
}
env->pc = env->regs[15];
@@ -8145,7 +8123,7 @@ void aarch64_sync_64_to_32(CPUARMState *env)
if (mode == ARM_CPU_MODE_HYP) {
env->regs[14] = env->xregs[14];
} else {
- env->banked_r14[bank_number(ARM_CPU_MODE_USR)] = env->xregs[14];
+ env->banked_r14[r14_bank_number(ARM_CPU_MODE_USR)] = env->xregs[14];
}
}
@@ -8159,7 +8137,7 @@ void aarch64_sync_64_to_32(CPUARMState *env)
env->regs[14] = env->xregs[16];
env->regs[13] = env->xregs[17];
} else {
- env->banked_r14[bank_number(ARM_CPU_MODE_IRQ)] = env->xregs[16];
+ env->banked_r14[r14_bank_number(ARM_CPU_MODE_IRQ)] = env->xregs[16];
env->banked_r13[bank_number(ARM_CPU_MODE_IRQ)] = env->xregs[17];
}
@@ -8167,7 +8145,7 @@ void aarch64_sync_64_to_32(CPUARMState *env)
env->regs[14] = env->xregs[18];
env->regs[13] = env->xregs[19];
} else {
- env->banked_r14[bank_number(ARM_CPU_MODE_SVC)] = env->xregs[18];
+ env->banked_r14[r14_bank_number(ARM_CPU_MODE_SVC)] = env->xregs[18];
env->banked_r13[bank_number(ARM_CPU_MODE_SVC)] = env->xregs[19];
}
@@ -8175,7 +8153,7 @@ void aarch64_sync_64_to_32(CPUARMState *env)
env->regs[14] = env->xregs[20];
env->regs[13] = env->xregs[21];
} else {
- env->banked_r14[bank_number(ARM_CPU_MODE_ABT)] = env->xregs[20];
+ env->banked_r14[r14_bank_number(ARM_CPU_MODE_ABT)] = env->xregs[20];
env->banked_r13[bank_number(ARM_CPU_MODE_ABT)] = env->xregs[21];
}
@@ -8183,7 +8161,7 @@ void aarch64_sync_64_to_32(CPUARMState *env)
env->regs[14] = env->xregs[22];
env->regs[13] = env->xregs[23];
} else {
- env->banked_r14[bank_number(ARM_CPU_MODE_UND)] = env->xregs[22];
+ env->banked_r14[r14_bank_number(ARM_CPU_MODE_UND)] = env->xregs[22];
env->banked_r13[bank_number(ARM_CPU_MODE_UND)] = env->xregs[23];
}
@@ -8200,7 +8178,7 @@ void aarch64_sync_64_to_32(CPUARMState *env)
env->fiq_regs[i - 24] = env->xregs[i];
}
env->banked_r13[bank_number(ARM_CPU_MODE_FIQ)] = env->xregs[29];
- env->banked_r14[bank_number(ARM_CPU_MODE_FIQ)] = env->xregs[30];
+ env->banked_r14[r14_bank_number(ARM_CPU_MODE_FIQ)] = env->xregs[30];
}
env->regs[15] = env->pc;
@@ -8378,7 +8356,6 @@ static void arm_cpu_do_interrupt_aarch32(CPUState *cs)
return;
}
- /* TODO: Vectored interrupt controller. */
switch (cs->exception_index) {
case EXCP_UDEF:
new_mode = ARM_CPU_MODE_UND;
@@ -10560,18 +10537,6 @@ static bool get_phys_addr_pmsav8(CPUARMState *env, uint32_t address,
ret = pmsav8_mpu_lookup(env, address, access_type, mmu_idx, phys_ptr,
txattrs, prot, &mpu_is_subpage, fi, NULL);
- /*
- * TODO: this is a temporary hack to ignore the fact that the SAU region
- * is smaller than a page if this is an executable region. We never
- * supported small MPU regions, but we did (accidentally) allow small
- * SAU regions, and if we now made small SAU regions not be executable
- * then this would break previously working guest code. We can't
- * remove this until/unless we implement support for execution from
- * small regions.
- */
- if (*prot & PAGE_EXEC) {
- sattrs.subpage = false;
- }
*page_size = sattrs.subpage || mpu_is_subpage ? 1 : TARGET_PAGE_SIZE;
return ret;
}
diff --git a/target/arm/internals.h b/target/arm/internals.h
index 6c2bb2deeb..d208b70a64 100644
--- a/target/arm/internals.h
+++ b/target/arm/internals.h
@@ -145,6 +145,22 @@ static inline int bank_number(int mode)
g_assert_not_reached();
}
+/**
+ * r14_bank_number: Map CPU mode onto register bank for r14
+ *
+ * Given an AArch32 CPU mode, return the index into the saved register
+ * banks to use for the R14 (LR) in that mode. This is the same as
+ * bank_number(), except for the special case of Hyp mode, where
+ * R14 is shared with USR and SYS, unlike its R13 and SPSR.
+ * This should be used as the index into env->banked_r14[], and
+ * bank_number() used for the index into env->banked_r13[] and
+ * env->banked_spsr[].
+ */
+static inline int r14_bank_number(int mode)
+{
+ return (mode == ARM_CPU_MODE_HYP) ? BANK_USRSYS : bank_number(mode);
+}
+
void arm_cpu_register_gdb_regs_for_features(ARMCPU *cpu);
void arm_translate_init(void);
@@ -871,4 +887,22 @@ static inline const char *aarch32_mode_name(uint32_t psr)
return cpu_mode_names[psr & 0xf];
}
+/**
+ * arm_cpu_update_virq: Update CPU_INTERRUPT_VIRQ bit in cs->interrupt_request
+ *
+ * Update the CPU_INTERRUPT_VIRQ bit in cs->interrupt_request, following
+ * a change to either the input VIRQ line from the GIC or the HCR_EL2.VI bit.
+ * Must be called with the iothread lock held.
+ */
+void arm_cpu_update_virq(ARMCPU *cpu);
+
+/**
+ * arm_cpu_update_vfiq: Update CPU_INTERRUPT_VFIQ bit in cs->interrupt_request
+ *
+ * Update the CPU_INTERRUPT_VFIQ bit in cs->interrupt_request, following
+ * a change to either the input VFIQ line from the GIC or the HCR_EL2.VF bit.
+ * Must be called with the iothread lock held.
+ */
+void arm_cpu_update_vfiq(ARMCPU *cpu);
+
#endif
diff --git a/target/arm/kvm32.c b/target/arm/kvm32.c
index 0f1e94c7b5..cb3fb73a96 100644
--- a/target/arm/kvm32.c
+++ b/target/arm/kvm32.c
@@ -318,8 +318,8 @@ int kvm_arch_put_registers(CPUState *cs, int level)
memcpy(env->usr_regs, env->regs + 8, 5 * sizeof(uint32_t));
}
env->banked_r13[bn] = env->regs[13];
- env->banked_r14[bn] = env->regs[14];
env->banked_spsr[bn] = env->spsr;
+ env->banked_r14[r14_bank_number(mode)] = env->regs[14];
/* Now we can safely copy stuff down to the kernel */
for (i = 0; i < ARRAY_SIZE(regs); i++) {
@@ -430,8 +430,8 @@ int kvm_arch_get_registers(CPUState *cs)
memcpy(env->regs + 8, env->usr_regs, 5 * sizeof(uint32_t));
}
env->regs[13] = env->banked_r13[bn];
- env->regs[14] = env->banked_r14[bn];
env->spsr = env->banked_spsr[bn];
+ env->regs[14] = env->banked_r14[r14_bank_number(mode)];
/* VFP registers */
r.id = KVM_REG_ARM | KVM_REG_SIZE_U64 | KVM_REG_ARM_VFP;
diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c
index 5de8ff0ac5..46fbe6d8ff 100644
--- a/target/arm/kvm64.c
+++ b/target/arm/kvm64.c
@@ -103,7 +103,7 @@ static void kvm_arm_init_debug(CPUState *cs)
* capable of fancier matching but that will require exposing that
* fanciness to GDB's interface
*
- * D7.3.2 DBGBCR<n>_EL1, Debug Breakpoint Control Registers
+ * DBGBCR<n>_EL1, Debug Breakpoint Control Registers
*
* 31 24 23 20 19 16 15 14 13 12 9 8 5 4 3 2 1 0
* +------+------+-------+-----+----+------+-----+------+-----+---+
@@ -115,12 +115,25 @@ static void kvm_arm_init_debug(CPUState *cs)
* SSC/HMC/PMC: Security, Higher and Priv access control (Table D-12)
* BAS: Byte Address Select (RES1 for AArch64)
* E: Enable bit
+ *
+ * DBGBVR<n>_EL1, Debug Breakpoint Value Registers
+ *
+ * 63 53 52 49 48 2 1 0
+ * +------+-----------+----------+-----+
+ * | RESS | VA[52:49] | VA[48:2] | 0 0 |
+ * +------+-----------+----------+-----+
+ *
+ * Depending on the addressing mode bits the top bits of the register
+ * are a sign extension of the highest applicable VA bit. Some
+ * versions of GDB don't do it correctly so we ensure they are correct
+ * here so future PC comparisons will work properly.
*/
+
static int insert_hw_breakpoint(target_ulong addr)
{
HWBreakpoint brk = {
.bcr = 0x1, /* BCR E=1, enable */
- .bvr = addr
+ .bvr = sextract64(addr, 0, 53)
};
if (cur_hw_bps >= max_hw_bps) {
@@ -987,7 +1000,10 @@ bool kvm_arm_handle_debug(CPUState *cs, struct kvm_debug_exit_arch *debug_exit)
cs->exception_index = EXCP_BKPT;
env->exception.syndrome = debug_exit->hsr;
env->exception.vaddress = debug_exit->far;
+ env->exception.target_el = 1;
+ qemu_mutex_lock_iothread();
cc->do_interrupt(cs);
+ qemu_mutex_unlock_iothread();
return false;
}
diff --git a/target/arm/machine.c b/target/arm/machine.c
index 239fe4e84d..2033816a64 100644
--- a/target/arm/machine.c
+++ b/target/arm/machine.c
@@ -192,6 +192,22 @@ static const VMStateDescription vmstate_serror = {
}
};
+static bool irq_line_state_needed(void *opaque)
+{
+ return true;
+}
+
+static const VMStateDescription vmstate_irq_line_state = {
+ .name = "cpu/irq-line-state",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .needed = irq_line_state_needed,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT32(env.irq_line_state, ARMCPU),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
static bool m_needed(void *opaque)
{
ARMCPU *cpu = opaque;
@@ -625,11 +641,44 @@ static int cpu_pre_save(void *opaque)
return 0;
}
+static int cpu_pre_load(void *opaque)
+{
+ ARMCPU *cpu = opaque;
+ CPUARMState *env = &cpu->env;
+
+ /*
+ * Pre-initialize irq_line_state to a value that's never valid as
+ * real data, so cpu_post_load() can tell whether we've seen the
+ * irq-line-state subsection in the incoming migration state.
+ */
+ env->irq_line_state = UINT32_MAX;
+
+ return 0;
+}
+
static int cpu_post_load(void *opaque, int version_id)
{
ARMCPU *cpu = opaque;
+ CPUARMState *env = &cpu->env;
int i, v;
+ /*
+ * Handle migration compatibility from old QEMU which didn't
+ * send the irq-line-state subsection. A QEMU without it did not
+ * implement the HCR_EL2.{VI,VF} bits as generating interrupts,
+ * so for TCG the line state matches the bits set in cs->interrupt_request.
+ * For KVM the line state is not stored in cs->interrupt_request
+ * and so this will leave irq_line_state as 0, but this is OK because
+ * we only need to care about it for TCG.
+ */
+ if (env->irq_line_state == UINT32_MAX) {
+ CPUState *cs = CPU(cpu);
+
+ env->irq_line_state = cs->interrupt_request &
+ (CPU_INTERRUPT_HARD | CPU_INTERRUPT_FIQ |
+ CPU_INTERRUPT_VIRQ | CPU_INTERRUPT_VFIQ);
+ }
+
/* Update the values list from the incoming migration data.
* Anything in the incoming data which we don't know about is
* a migration failure; anything we know about but the incoming
@@ -680,6 +729,7 @@ const VMStateDescription vmstate_arm_cpu = {
.version_id = 22,
.minimum_version_id = 22,
.pre_save = cpu_pre_save,
+ .pre_load = cpu_pre_load,
.post_load = cpu_post_load,
.fields = (VMStateField[]) {
VMSTATE_UINT32_ARRAY(env.regs, ARMCPU, 16),
@@ -747,6 +797,7 @@ const VMStateDescription vmstate_arm_cpu = {
&vmstate_sve,
#endif
&vmstate_serror,
+ &vmstate_irq_line_state,
NULL
}
};
diff --git a/target/arm/op_helper.c b/target/arm/op_helper.c
index 90741f6331..eb6fb82fb8 100644
--- a/target/arm/op_helper.c
+++ b/target/arm/op_helper.c
@@ -694,7 +694,7 @@ void HELPER(msr_banked)(CPUARMState *env, uint32_t value, uint32_t tgtmode,
env->banked_r13[bank_number(tgtmode)] = value;
break;
case 14:
- env->banked_r14[bank_number(tgtmode)] = value;
+ env->banked_r14[r14_bank_number(tgtmode)] = value;
break;
case 8 ... 12:
switch (tgtmode) {
@@ -725,7 +725,7 @@ uint32_t HELPER(mrs_banked)(CPUARMState *env, uint32_t tgtmode, uint32_t regno)
case 13:
return env->banked_r13[bank_number(tgtmode)];
case 14:
- return env->banked_r14[bank_number(tgtmode)];
+ return env->banked_r14[r14_bank_number(tgtmode)];
case 8 ... 12:
switch (tgtmode) {
case ARM_CPU_MODE_USR:
diff --git a/tests/guest-debug/test-gdbstub.py b/tests/guest-debug/test-gdbstub.py
index 0e4ac01426..c7e3986a24 100644
--- a/tests/guest-debug/test-gdbstub.py
+++ b/tests/guest-debug/test-gdbstub.py
@@ -16,6 +16,7 @@ def report(cond, msg):
print ("PASS: %s" % (msg))
else:
print ("FAIL: %s" % (msg))
+ global failcount
failcount += 1