summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--hw/arm/collie.c2
-rw-r--r--hw/arm/imx25_pdk.c2
-rw-r--r--hw/arm/spitz.c8
-rw-r--r--hw/arm/tosa.c2
-rw-r--r--hw/arm/virt.c8
-rw-r--r--hw/misc/zynq_slcr.c8
-rw-r--r--target-arm/cpu.h30
-rw-r--r--target-arm/helper.c60
-rw-r--r--target-arm/helper.h2
-rw-r--r--target-arm/op_helper.c35
-rw-r--r--target-arm/translate-a64.c25
-rw-r--r--target-arm/translate.c36
-rw-r--r--tests/ds1338-test.c2
13 files changed, 173 insertions, 47 deletions
diff --git a/hw/arm/collie.c b/hw/arm/collie.c
index 4e6541e4e1..9991c0c4a0 100644
--- a/hw/arm/collie.c
+++ b/hw/arm/collie.c
@@ -60,7 +60,7 @@ static void collie_init(MachineState *machine)
static void collie_machine_init(MachineClass *mc)
{
- mc->desc = "Collie PDA (SA-1110)";
+ mc->desc = "Sharp SL-5500 (Collie) PDA (SA-1110)";
mc->init = collie_init;
}
diff --git a/hw/arm/imx25_pdk.c b/hw/arm/imx25_pdk.c
index 425011475a..59a4c11277 100644
--- a/hw/arm/imx25_pdk.c
+++ b/hw/arm/imx25_pdk.c
@@ -151,4 +151,4 @@ static void imx25_pdk_machine_init(MachineClass *mc)
mc->init = imx25_pdk_init;
}
-DEFINE_MACHINE("imx25_pdk", imx25_pdk_machine_init)
+DEFINE_MACHINE("imx25-pdk", imx25_pdk_machine_init)
diff --git a/hw/arm/spitz.c b/hw/arm/spitz.c
index 2af03be622..8d3cc0b6b2 100644
--- a/hw/arm/spitz.c
+++ b/hw/arm/spitz.c
@@ -976,7 +976,7 @@ static void akitapda_class_init(ObjectClass *oc, void *data)
{
MachineClass *mc = MACHINE_CLASS(oc);
- mc->desc = "Akita PDA (PXA270)";
+ mc->desc = "Sharp SL-C1000 (Akita) PDA (PXA270)";
mc->init = akita_init;
}
@@ -990,7 +990,7 @@ static void spitzpda_class_init(ObjectClass *oc, void *data)
{
MachineClass *mc = MACHINE_CLASS(oc);
- mc->desc = "Spitz PDA (PXA270)";
+ mc->desc = "Sharp SL-C3000 (Spitz) PDA (PXA270)";
mc->init = spitz_init;
}
@@ -1004,7 +1004,7 @@ static void borzoipda_class_init(ObjectClass *oc, void *data)
{
MachineClass *mc = MACHINE_CLASS(oc);
- mc->desc = "Borzoi PDA (PXA270)";
+ mc->desc = "Sharp SL-C3100 (Borzoi) PDA (PXA270)";
mc->init = borzoi_init;
}
@@ -1018,7 +1018,7 @@ static void terrierpda_class_init(ObjectClass *oc, void *data)
{
MachineClass *mc = MACHINE_CLASS(oc);
- mc->desc = "Terrier PDA (PXA270)";
+ mc->desc = "Sharp SL-C3200 (Terrier) PDA (PXA270)";
mc->init = terrier_init;
}
diff --git a/hw/arm/tosa.c b/hw/arm/tosa.c
index 51d0b89687..02814d7aba 100644
--- a/hw/arm/tosa.c
+++ b/hw/arm/tosa.c
@@ -254,7 +254,7 @@ static void tosa_init(MachineState *machine)
static void tosapda_machine_init(MachineClass *mc)
{
- mc->desc = "Tosa PDA (PXA255)";
+ mc->desc = "Sharp SL-6000 (Tosa) PDA (PXA255)";
mc->init = tosa_init;
}
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index d25d6cfce7..4e7160ce96 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -884,12 +884,17 @@ static void virt_build_smbios(VirtGuestInfo *guest_info)
FWCfgState *fw_cfg = guest_info->fw_cfg;
uint8_t *smbios_tables, *smbios_anchor;
size_t smbios_tables_len, smbios_anchor_len;
+ const char *product = "QEMU Virtual Machine";
if (!fw_cfg) {
return;
}
- smbios_set_defaults("QEMU", "QEMU Virtual Machine",
+ if (kvm_enabled()) {
+ product = "KVM Virtual Machine";
+ }
+
+ smbios_set_defaults("QEMU", product,
"1.0", false, true, SMBIOS_ENTRY_POINT_30);
smbios_get_tables(NULL, 0, &smbios_tables, &smbios_tables_len,
@@ -1157,6 +1162,7 @@ static void virt_class_init(ObjectClass *oc, void *data)
mc->has_dynamic_sysbus = true;
mc->block_default_type = IF_VIRTIO;
mc->no_cdrom = 1;
+ mc->pci_allow_0_address = true;
}
static const TypeInfo machvirt_info = {
diff --git a/hw/misc/zynq_slcr.c b/hw/misc/zynq_slcr.c
index 964f2532ff..3d7870850b 100644
--- a/hw/misc/zynq_slcr.c
+++ b/hw/misc/zynq_slcr.c
@@ -393,12 +393,12 @@ static void zynq_slcr_write(void *opaque, hwaddr offset,
return;
}
- if (!s->regs[LOCKSTA]) {
- s->regs[offset / 4] = val;
- } else {
- DB_PRINT("SCLR registers are locked. Unlock them first\n");
+ if (s->regs[LOCKSTA]) {
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "SCLR registers are locked. Unlock them first\n");
return;
}
+ s->regs[offset] = val;
switch (offset) {
case PSS_RST_CTRL:
diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index 493f9d02a9..3daa7f58f9 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -379,6 +379,8 @@ typedef struct CPUARMState {
uint64_t dbgwvr[16]; /* watchpoint value registers */
uint64_t dbgwcr[16]; /* watchpoint control registers */
uint64_t mdscr_el1;
+ uint64_t oslsr_el1; /* OS Lock Status */
+ uint64_t mdcr_el2;
/* If the counter is enabled, this stores the last time the counter
* was reset. Otherwise it stores the counter value
*/
@@ -1016,11 +1018,11 @@ static inline bool access_secure_reg(CPUARMState *env)
*/
#define A32_BANKED_CURRENT_REG_GET(_env, _regname) \
A32_BANKED_REG_GET((_env), _regname, \
- ((!arm_el_is_aa64((_env), 3) && arm_is_secure(_env))))
+ (arm_is_secure(_env) && !arm_el_is_aa64((_env), 3)))
#define A32_BANKED_CURRENT_REG_SET(_env, _regname, _val) \
A32_BANKED_REG_SET((_env), _regname, \
- ((!arm_el_is_aa64((_env), 3) && arm_is_secure(_env))), \
+ (arm_is_secure(_env) && !arm_el_is_aa64((_env), 3)), \
(_val))
void arm_cpu_list(FILE *f, fprintf_function cpu_fprintf);
@@ -1587,7 +1589,12 @@ static inline bool arm_excp_unmasked(CPUState *cs, unsigned int excp_idx,
* interrupt.
*/
if ((target_el > cur_el) && (target_el != 1)) {
- if (arm_el_is_aa64(env, 3) || ((scr || hcr) && (!secure))) {
+ /* ARM_FEATURE_AARCH64 enabled means the highest EL is AArch64.
+ * This code currently assumes that EL2 is not implemented
+ * (and so that highest EL will be 3 and the target_el also 3).
+ */
+ if (arm_feature(env, ARM_FEATURE_AARCH64) ||
+ ((scr || hcr) && (!secure))) {
unmasked = 1;
}
}
@@ -1695,7 +1702,22 @@ static inline int cpu_mmu_index(CPUARMState *env, bool ifetch)
*/
static inline int arm_debug_target_el(CPUARMState *env)
{
- return 1;
+ bool secure = arm_is_secure(env);
+ bool route_to_el2 = false;
+
+ if (arm_feature(env, ARM_FEATURE_EL2) && !secure) {
+ route_to_el2 = env->cp15.hcr_el2 & HCR_TGE ||
+ env->cp15.mdcr_el2 & (1 << 8);
+ }
+
+ if (route_to_el2) {
+ return 2;
+ } else if (arm_feature(env, ARM_FEATURE_EL3) &&
+ !arm_el_is_aa64(env, 3) && secure) {
+ return 3;
+ } else {
+ return 1;
+ }
}
static inline bool aa64_generate_debug_exceptions(CPUARMState *env)
diff --git a/target-arm/helper.c b/target-arm/helper.c
index 83679970b4..e7fda37466 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -657,8 +657,12 @@ static const ARMCPRegInfo v6_cp_reginfo[] = {
{ .name = "MVA_prefetch",
.cp = 15, .crn = 7, .crm = 13, .opc1 = 0, .opc2 = 1,
.access = PL1_W, .type = ARM_CP_NOP },
+ /* We need to break the TB after ISB to execute self-modifying code
+ * correctly and also to take any pending interrupts immediately.
+ * So use arm_cp_write_ignore() function instead of ARM_CP_NOP flag.
+ */
{ .name = "ISB", .cp = 15, .crn = 7, .crm = 5, .opc1 = 0, .opc2 = 4,
- .access = PL0_W, .type = ARM_CP_NOP },
+ .access = PL0_W, .type = ARM_CP_NO_RAW, .writefn = arm_cp_write_ignore },
{ .name = "DSB", .cp = 15, .crn = 7, .crm = 10, .opc1 = 0, .opc2 = 4,
.access = PL0_W, .type = ARM_CP_NOP },
{ .name = "DMB", .cp = 15, .crn = 7, .crm = 10, .opc1 = 0, .opc2 = 5,
@@ -3223,6 +3227,9 @@ static const ARMCPRegInfo el3_no_el2_cp_reginfo[] = {
{ .name = "CNTHP_CTL_EL2", .state = ARM_CP_STATE_BOTH,
.opc0 = 3, .opc1 = 4, .crn = 14, .crm = 2, .opc2 = 1,
.access = PL2_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
+ { .name = "MDCR_EL2", .state = ARM_CP_STATE_BOTH,
+ .opc0 = 3, .opc1 = 4, .crn = 1, .crm = 1, .opc2 = 1,
+ .access = PL2_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
REGINFO_SENTINEL
};
@@ -3444,6 +3451,15 @@ static const ARMCPRegInfo el2_cp_reginfo[] = {
.resetvalue = 0,
.writefn = gt_hyp_ctl_write, .raw_writefn = raw_write },
#endif
+ /* The only field of MDCR_EL2 that has a defined architectural reset value
+ * is MDCR_EL2.HPMN which should reset to the value of PMCR_EL0.N; but we
+ * don't impelment any PMU event counters, so using zero as a reset
+ * value for MDCR_EL2 is okay
+ */
+ { .name = "MDCR_EL2", .state = ARM_CP_STATE_BOTH,
+ .opc0 = 3, .opc1 = 4, .crn = 1, .crm = 1, .opc2 = 1,
+ .access = PL2_RW, .resetvalue = 0,
+ .fieldoffset = offsetof(CPUARMState, cp15.mdcr_el2), },
REGINFO_SENTINEL
};
@@ -3564,6 +3580,23 @@ static CPAccessResult ctr_el0_access(CPUARMState *env, const ARMCPRegInfo *ri)
return CP_ACCESS_OK;
}
+static void oslar_write(CPUARMState *env, const ARMCPRegInfo *ri,
+ uint64_t value)
+{
+ /* Writes to OSLAR_EL1 may update the OS lock status, which can be
+ * read via a bit in OSLSR_EL1.
+ */
+ int oslock;
+
+ if (ri->state == ARM_CP_STATE_AA32) {
+ oslock = (value == 0xC5ACCE55);
+ } else {
+ oslock = value & 1;
+ }
+
+ env->cp15.oslsr_el1 = deposit32(env->cp15.oslsr_el1, 1, 1, oslock);
+}
+
static const ARMCPRegInfo debug_cp_reginfo[] = {
/* DBGDRAR, DBGDSAR: always RAZ since we don't implement memory mapped
* debug components. The AArch64 version of DBGDRAR is named MDRAR_EL1;
@@ -3592,10 +3625,14 @@ static const ARMCPRegInfo debug_cp_reginfo[] = {
.type = ARM_CP_ALIAS,
.access = PL1_R,
.fieldoffset = offsetof(CPUARMState, cp15.mdscr_el1), },
- /* We define a dummy WI OSLAR_EL1, because Linux writes to it. */
{ .name = "OSLAR_EL1", .state = ARM_CP_STATE_BOTH,
.cp = 14, .opc0 = 2, .opc1 = 0, .crn = 1, .crm = 0, .opc2 = 4,
- .access = PL1_W, .type = ARM_CP_NOP },
+ .access = PL1_W, .type = ARM_CP_NO_RAW,
+ .writefn = oslar_write },
+ { .name = "OSLSR_EL1", .state = ARM_CP_STATE_BOTH,
+ .cp = 14, .opc0 = 2, .opc1 = 0, .crn = 1, .crm = 1, .opc2 = 4,
+ .access = PL1_R, .resetvalue = 10,
+ .fieldoffset = offsetof(CPUARMState, cp15.oslsr_el1) },
/* Dummy OSDLR_EL1: 32-bit Linux will read this */
{ .name = "OSDLR_EL1", .state = ARM_CP_STATE_BOTH,
.cp = 14, .opc0 = 2, .opc1 = 0, .crn = 1, .crm = 3, .opc2 = 4,
@@ -5194,7 +5231,7 @@ void switch_mode(CPUARMState *env, int mode)
* BIT IRQ IMO Non-secure Secure
* EL3 FIQ RW FMO EL0 EL1 EL2 EL3 EL0 EL1 EL2 EL3
*/
-const int8_t target_el_table[2][2][2][2][2][4] = {
+static const int8_t target_el_table[2][2][2][2][2][4] = {
{{{{/* 0 0 0 0 */{ 1, 1, 2, -1 },{ 3, -1, -1, 3 },},
{/* 0 0 0 1 */{ 2, 2, 2, -1 },{ 3, -1, -1, 3 },},},
{{/* 0 0 1 0 */{ 1, 1, 2, -1 },{ 3, -1, -1, 3 },},
@@ -5220,11 +5257,22 @@ uint32_t arm_phys_excp_target_el(CPUState *cs, uint32_t excp_idx,
uint32_t cur_el, bool secure)
{
CPUARMState *env = cs->env_ptr;
- int rw = ((env->cp15.scr_el3 & SCR_RW) == SCR_RW);
+ int rw;
int scr;
int hcr;
int target_el;
- int is64 = arm_el_is_aa64(env, 3);
+ /* Is the highest EL AArch64? */
+ int is64 = arm_feature(env, ARM_FEATURE_AARCH64);
+
+ if (arm_feature(env, ARM_FEATURE_EL3)) {
+ rw = ((env->cp15.scr_el3 & SCR_RW) == SCR_RW);
+ } else {
+ /* Either EL2 is the highest EL (and so the EL2 register width
+ * is given by is64); or there is no EL2 or EL3, in which case
+ * the value of 'rw' does not affect the table lookup anyway.
+ */
+ rw = is64;
+ }
switch (excp_idx) {
case EXCP_IRQ:
diff --git a/target-arm/helper.h b/target-arm/helper.h
index 827b33dfec..c2a85c722a 100644
--- a/target-arm/helper.h
+++ b/target-arm/helper.h
@@ -54,6 +54,8 @@ DEF_HELPER_1(yield, void, env)
DEF_HELPER_1(pre_hvc, void, env)
DEF_HELPER_2(pre_smc, void, env, i32)
+DEF_HELPER_1(check_breakpoints, void, env)
+
DEF_HELPER_3(cpsr_write, void, env, i32, i32)
DEF_HELPER_1(cpsr_read, i32, env)
diff --git a/target-arm/op_helper.c b/target-arm/op_helper.c
index 1425a1d4bb..7929c71b43 100644
--- a/target-arm/op_helper.c
+++ b/target-arm/op_helper.c
@@ -867,6 +867,15 @@ static bool check_breakpoints(ARMCPU *cpu)
return false;
}
+void HELPER(check_breakpoints)(CPUARMState *env)
+{
+ ARMCPU *cpu = arm_env_get_cpu(env);
+
+ if (check_breakpoints(cpu)) {
+ HELPER(exception_internal(env, EXCP_DEBUG));
+ }
+}
+
void arm_debug_excp_handler(CPUState *cs)
{
/* Called by core code when a watchpoint or breakpoint fires;
@@ -897,18 +906,22 @@ void arm_debug_excp_handler(CPUState *cs)
}
}
} else {
- if (check_breakpoints(cpu)) {
- bool same_el = (arm_debug_target_el(env) == arm_current_el(env));
- if (extended_addresses_enabled(env)) {
- env->exception.fsr = (1 << 9) | 0x22;
- } else {
- env->exception.fsr = 0x2;
- }
- /* FAR is UNKNOWN, so doesn't need setting */
- raise_exception(env, EXCP_PREFETCH_ABORT,
- syn_breakpoint(same_el),
- arm_debug_target_el(env));
+ uint64_t pc = is_a64(env) ? env->pc : env->regs[15];
+ bool same_el = (arm_debug_target_el(env) == arm_current_el(env));
+
+ if (cpu_breakpoint_test(cs, pc, BP_GDB)) {
+ return;
+ }
+
+ if (extended_addresses_enabled(env)) {
+ env->exception.fsr = (1 << 9) | 0x22;
+ } else {
+ env->exception.fsr = 0x2;
}
+ /* FAR is UNKNOWN, so doesn't need setting */
+ raise_exception(env, EXCP_PREFETCH_ABORT,
+ syn_breakpoint(same_el),
+ arm_debug_target_el(env));
}
}
diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c
index e65e309535..19f9d8d2c8 100644
--- a/target-arm/translate-a64.c
+++ b/target-arm/translate-a64.c
@@ -1230,9 +1230,15 @@ static void handle_sync(DisasContext *s, uint32_t insn,
return;
case 4: /* DSB */
case 5: /* DMB */
- case 6: /* ISB */
/* We don't emulate caches so barriers are no-ops */
return;
+ case 6: /* ISB */
+ /* We need to break the TB after this insn to execute
+ * a self-modified code correctly and also to take
+ * any pending interrupts immediately.
+ */
+ s->is_jmp = DISAS_UPDATE;
+ return;
default:
unallocated_encoding(s);
return;
@@ -11084,11 +11090,18 @@ void gen_intermediate_code_a64(ARMCPU *cpu, TranslationBlock *tb)
CPUBreakpoint *bp;
QTAILQ_FOREACH(bp, &cs->breakpoints, entry) {
if (bp->pc == dc->pc) {
- gen_exception_internal_insn(dc, 0, EXCP_DEBUG);
- /* Advance PC so that clearing the breakpoint will
- invalidate this TB. */
- dc->pc += 2;
- goto done_generating;
+ if (bp->flags & BP_CPU) {
+ gen_helper_check_breakpoints(cpu_env);
+ /* End the TB early; it likely won't be executed */
+ dc->is_jmp = DISAS_UPDATE;
+ } else {
+ gen_exception_internal_insn(dc, 0, EXCP_DEBUG);
+ /* Advance PC so that clearing the breakpoint will
+ invalidate this TB. */
+ dc->pc += 4;
+ goto done_generating;
+ }
+ break;
}
}
}
diff --git a/target-arm/translate.c b/target-arm/translate.c
index 22c35877e5..9f1d740b4e 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -7720,10 +7720,16 @@ static void disas_arm_insn(DisasContext *s, unsigned int insn)
return;
case 4: /* dsb */
case 5: /* dmb */
- case 6: /* isb */
ARCH(7);
/* We don't emulate caches so these are a no-op. */
return;
+ case 6: /* isb */
+ /* We need to break the TB after this insn to execute
+ * self-modifying code correctly and also to take
+ * any pending interrupts immediately.
+ */
+ gen_lookup_tb(s);
+ return;
default:
goto illegal_op;
}
@@ -10030,9 +10036,16 @@ static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw
break;
case 4: /* dsb */
case 5: /* dmb */
- case 6: /* isb */
/* These execute as NOPs. */
break;
+ case 6: /* isb */
+ /* We need to break the TB after this insn
+ * to execute self-modifying code correctly
+ * and also to take any pending interrupts
+ * immediately.
+ */
+ gen_lookup_tb(s);
+ break;
default:
goto illegal_op;
}
@@ -11329,11 +11342,20 @@ void gen_intermediate_code(CPUARMState *env, TranslationBlock *tb)
CPUBreakpoint *bp;
QTAILQ_FOREACH(bp, &cs->breakpoints, entry) {
if (bp->pc == dc->pc) {
- gen_exception_internal_insn(dc, 0, EXCP_DEBUG);
- /* Advance PC so that clearing the breakpoint will
- invalidate this TB. */
- dc->pc += 2;
- goto done_generating;
+ if (bp->flags & BP_CPU) {
+ gen_helper_check_breakpoints(cpu_env);
+ /* End the TB early; it's likely not going to be executed */
+ dc->is_jmp = DISAS_UPDATE;
+ } else {
+ gen_exception_internal_insn(dc, 0, EXCP_DEBUG);
+ /* Advance PC so that clearing the breakpoint will
+ invalidate this TB. */
+ /* TODO: Advance PC by correct instruction length to
+ * avoid disassembler error messages */
+ dc->pc += 2;
+ goto done_generating;
+ }
+ break;
}
}
}
diff --git a/tests/ds1338-test.c b/tests/ds1338-test.c
index a7fb415353..7d513d8972 100644
--- a/tests/ds1338-test.c
+++ b/tests/ds1338-test.c
@@ -61,7 +61,7 @@ int main(int argc, char **argv)
g_test_init(&argc, &argv, NULL);
- s = qtest_start("-display none -machine imx25_pdk");
+ s = qtest_start("-display none -machine imx25-pdk");
i2c = imx_i2c_create(IMX25_I2C_0_BASE);
addr = DS1338_ADDR;