diff --git a/hw/arm/bcm2836.c b/hw/arm/bcm2836.c index 3e7e8ca791..3c4b44a53e 100644 --- a/hw/arm/bcm2836.c +++ b/hw/arm/bcm2836.c @@ -32,7 +32,7 @@ struct BCM283XInfo { static const BCM283XInfo bcm283x_socs[] = { { .name = TYPE_BCM2836, - .cpu_type = ARM_CPU_TYPE_NAME("cortex-a15"), + .cpu_type = ARM_CPU_TYPE_NAME("cortex-a7"), .clusterid = 0xf, }, #ifdef TARGET_AARCH64 diff --git a/hw/arm/raspi.c b/hw/arm/raspi.c index 06f1e08ca9..955a7c4e80 100644 --- a/hw/arm/raspi.c +++ b/hw/arm/raspi.c @@ -226,7 +226,7 @@ static void raspi2_machine_init(MachineClass *mc) mc->no_parallel = 1; mc->no_floppy = 1; mc->no_cdrom = 1; - mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-a15"); + mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-a7"); mc->max_cpus = BCM283X_NCPUS; mc->min_cpus = BCM283X_NCPUS; mc->default_cpus = BCM283X_NCPUS; diff --git a/hw/arm/virt.c b/hw/arm/virt.c index 2c07245047..94dcb125d3 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c @@ -1132,6 +1132,8 @@ static void *machvirt_dtb(const struct arm_boot_info *binfo, int *fdt_size) static void virt_build_smbios(VirtMachineState *vms) { + MachineClass *mc = MACHINE_GET_CLASS(vms); + VirtMachineClass *vmc = VIRT_MACHINE_GET_CLASS(vms); uint8_t *smbios_tables, *smbios_anchor; size_t smbios_tables_len, smbios_anchor_len; const char *product = "QEMU Virtual Machine"; @@ -1145,7 +1147,8 @@ static void virt_build_smbios(VirtMachineState *vms) } smbios_set_defaults("QEMU", product, - "1.0", false, true, SMBIOS_ENTRY_POINT_30); + vmc->smbios_old_sys_ver ? "1.0" : mc->name, false, + true, SMBIOS_ENTRY_POINT_30); smbios_get_tables(NULL, 0, &smbios_tables, &smbios_tables_len, &smbios_anchor, &smbios_anchor_len); @@ -1646,8 +1649,11 @@ static void virt_2_11_instance_init(Object *obj) static void virt_machine_2_11_options(MachineClass *mc) { + VirtMachineClass *vmc = VIRT_MACHINE_CLASS(OBJECT_CLASS(mc)); + virt_machine_2_12_options(mc); SET_MACHINE_COMPAT(mc, VIRT_COMPAT_2_11); + vmc->smbios_old_sys_ver = true; } DEFINE_VIRT_MACHINE(2, 11) diff --git a/hw/char/imx_serial.c b/hw/char/imx_serial.c index 1e5540472b..0747db9f2b 100644 --- a/hw/char/imx_serial.c +++ b/hw/char/imx_serial.c @@ -308,6 +308,9 @@ static void imx_put_data(void *opaque, uint32_t value) s->usr2 |= USR2_RDR; s->uts1 &= ~UTS1_RXEMPTY; s->readbuff = value; + if (value & URXD_BRK) { + s->usr2 |= USR2_BRCD; + } imx_update(s); } @@ -319,7 +322,7 @@ static void imx_receive(void *opaque, const uint8_t *buf, int size) static void imx_event(void *opaque, int event) { if (event == CHR_EVENT_BREAK) { - imx_put_data(opaque, URXD_BRK); + imx_put_data(opaque, URXD_BRK | URXD_FRMERR | URXD_ERR); } } diff --git a/hw/intc/arm_gicv3_cpuif.c b/hw/intc/arm_gicv3_cpuif.c index 5cbafaf497..26f5eeda94 100644 --- a/hw/intc/arm_gicv3_cpuif.c +++ b/hw/intc/arm_gicv3_cpuif.c @@ -836,7 +836,7 @@ static uint64_t icc_pmr_read(CPUARMState *env, const ARMCPRegInfo *ri) /* NS access and Group 0 is inaccessible to NS: return the * NS view of the current priority */ - if (value & 0x80) { + if ((value & 0x80) == 0) { /* Secure priorities not visible to NS */ value = 0; } else if (value != 0xff) { @@ -871,7 +871,7 @@ static void icc_pmr_write(CPUARMState *env, const ARMCPRegInfo *ri, /* Current PMR in the secure range, don't allow NS to change it */ return; } - value = (value >> 1) & 0x80; + value = (value >> 1) | 0x80; } cs->icc_pmr_el1 = value; gicv3_cpuif_update(cs); @@ -1609,7 +1609,7 @@ static uint64_t icc_rpr_read(CPUARMState *env, const ARMCPRegInfo *ri) if (arm_feature(env, ARM_FEATURE_EL3) && !arm_is_secure(env) && (env->cp15.scr_el3 & SCR_FIQ)) { /* NS GIC access and Group 0 is inaccessible to NS */ - if (prio & 0x80) { + if ((prio & 0x80) == 0) { /* NS mustn't see priorities in the Secure half of the range */ prio = 0; } else if (prio != 0xff) { diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c index 1b828b104d..63c44a4ee8 100644 --- a/hw/sd/sdhci.c +++ b/hw/sd/sdhci.c @@ -1474,7 +1474,7 @@ static void sdhci_pci_realize(PCIDevice *dev, Error **errp) Error *local_err = NULL; sdhci_initfn(s); - sdhci_common_realize(s, errp); + sdhci_common_realize(s, &local_err); if (local_err) { error_propagate(errp, local_err); return; @@ -1556,7 +1556,7 @@ static void sdhci_sysbus_realize(DeviceState *dev, Error ** errp) SysBusDevice *sbd = SYS_BUS_DEVICE(dev); Error *local_err = NULL; - sdhci_common_realize(s, errp); + sdhci_common_realize(s, &local_err); if (local_err) { error_propagate(errp, local_err); return; diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h index 33b0ff3892..ba0c1a4faa 100644 --- a/include/hw/arm/virt.h +++ b/include/hw/arm/virt.h @@ -85,6 +85,7 @@ typedef struct { bool no_its; bool no_pmu; bool claim_edge_triggered_timers; + bool smbios_old_sys_ver; } VirtMachineClass; typedef struct { diff --git a/include/hw/char/imx_serial.h b/include/hw/char/imx_serial.h index 5b99cee7cf..ee80da12e6 100644 --- a/include/hw/char/imx_serial.h +++ b/include/hw/char/imx_serial.h @@ -26,6 +26,7 @@ #define URXD_CHARRDY (1<<15) /* character read is valid */ #define URXD_ERR (1<<14) /* Character has error */ +#define URXD_FRMERR (1<<12) /* Character has frame error */ #define URXD_BRK (1<<11) /* Break received */ #define USR1_PARTYER (1<<15) /* Parity Error */ diff --git a/target/arm/helper.c b/target/arm/helper.c index 09893e3f72..dcb8476d9e 100644 --- a/target/arm/helper.c +++ b/target/arm/helper.c @@ -7910,7 +7910,6 @@ static void arm_cpu_do_interrupt_aarch32(CPUState *cs) offset = 0; break; case EXCP_BKPT: - env->exception.fsr = 2; /* Fall through to prefetch abort. */ case EXCP_PREFETCH_ABORT: A32_BANKED_CURRENT_REG_SET(env, ifsr, env->exception.fsr); diff --git a/target/arm/helper.h b/target/arm/helper.h index 0d2094f2be..34e8cc8904 100644 --- a/target/arm/helper.h +++ b/target/arm/helper.h @@ -47,6 +47,7 @@ DEF_HELPER_FLAGS_3(sel_flags, TCG_CALL_NO_RWG_SE, i32, i32, i32, i32) DEF_HELPER_2(exception_internal, void, env, i32) DEF_HELPER_4(exception_with_syndrome, void, env, i32, i32, i32) +DEF_HELPER_2(exception_bkpt_insn, void, env, i32) DEF_HELPER_1(setend, void, env) DEF_HELPER_2(wfi, void, env, i32) DEF_HELPER_1(wfe, void, env) diff --git a/target/arm/internals.h b/target/arm/internals.h index 47cc224a46..8ce944b7a0 100644 --- a/target/arm/internals.h +++ b/target/arm/internals.h @@ -763,4 +763,29 @@ static inline bool regime_is_secure(CPUARMState *env, ARMMMUIdx mmu_idx) } } +/* Return the FSR value for a debug exception (watchpoint, hardware + * breakpoint or BKPT insn) targeting the specified exception level. + */ +static inline uint32_t arm_debug_exception_fsr(CPUARMState *env) +{ + ARMMMUFaultInfo fi = { .type = ARMFault_Debug }; + int target_el = arm_debug_target_el(env); + bool using_lpae = false; + + if (target_el == 2 || arm_el_is_aa64(env, target_el)) { + using_lpae = true; + } else { + if (arm_feature(env, ARM_FEATURE_LPAE) && + (env->cp15.tcr_el[target_el].raw_tcr & TTBCR_EAE)) { + using_lpae = true; + } + } + + if (using_lpae) { + return arm_fi_to_lfsc(&fi); + } else { + return arm_fi_to_sfsc(&fi); + } +} + #endif diff --git a/target/arm/op_helper.c b/target/arm/op_helper.c index 7a88fd2c92..a266cc0116 100644 --- a/target/arm/op_helper.c +++ b/target/arm/op_helper.c @@ -483,6 +483,21 @@ void HELPER(exception_with_syndrome)(CPUARMState *env, uint32_t excp, raise_exception(env, excp, syndrome, target_el); } +/* Raise an EXCP_BKPT with the specified syndrome register value, + * targeting the correct exception level for debug exceptions. + */ +void HELPER(exception_bkpt_insn)(CPUARMState *env, uint32_t syndrome) +{ + /* FSR will only be used if the debug target EL is AArch32. */ + env->exception.fsr = arm_debug_exception_fsr(env); + /* FAR is UNKNOWN: clear vaddress to avoid potentially exposing + * values to the guest that it shouldn't be able to see at its + * exception/security level. + */ + env->exception.vaddress = 0; + raise_exception(env, EXCP_BKPT, syndrome, arm_debug_target_el(env)); +} + uint32_t HELPER(cpsr_read)(CPUARMState *env) { return cpsr_read(env) & ~(CPSR_EXEC | CPSR_RESERVED); @@ -1322,11 +1337,7 @@ void arm_debug_excp_handler(CPUState *cs) cs->watchpoint_hit = NULL; - if (extended_addresses_enabled(env)) { - env->exception.fsr = (1 << 9) | 0x22; - } else { - env->exception.fsr = 0x2; - } + env->exception.fsr = arm_debug_exception_fsr(env); env->exception.vaddress = wp_hit->hitaddr; raise_exception(env, EXCP_DATA_ABORT, syn_watchpoint(same_el, 0, wnr), @@ -1346,12 +1357,12 @@ void arm_debug_excp_handler(CPUState *cs) 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 */ + env->exception.fsr = arm_debug_exception_fsr(env); + /* FAR is UNKNOWN: clear vaddress to avoid potentially exposing + * values to the guest that it shouldn't be able to see at its + * exception/security level. + */ + env->exception.vaddress = 0; 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 31ff0479e6..c91329249d 100644 --- a/target/arm/translate-a64.c +++ b/target/arm/translate-a64.c @@ -321,6 +321,18 @@ static void gen_exception_insn(DisasContext *s, int offset, int excp, s->base.is_jmp = DISAS_NORETURN; } +static void gen_exception_bkpt_insn(DisasContext *s, int offset, + uint32_t syndrome) +{ + TCGv_i32 tcg_syn; + + gen_a64_set_pc_im(s->pc - offset); + tcg_syn = tcg_const_i32(syndrome); + gen_helper_exception_bkpt_insn(cpu_env, tcg_syn); + tcg_temp_free_i32(tcg_syn); + s->base.is_jmp = DISAS_NORETURN; +} + static void gen_ss_advance(DisasContext *s) { /* If the singlestep state is Active-not-pending, advance to @@ -1839,8 +1851,7 @@ static void disas_exc(DisasContext *s, uint32_t insn) break; } /* BRK */ - gen_exception_insn(s, 4, EXCP_BKPT, syn_aa64_bkpt(imm16), - default_exception_el(s)); + gen_exception_bkpt_insn(s, 4, syn_aa64_bkpt(imm16)); break; case 2: if (op2_ll != 0) { @@ -13378,12 +13389,12 @@ static void aarch64_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu) case DISAS_UPDATE: gen_a64_set_pc_im(dc->pc); /* fall through */ - case DISAS_JUMP: - tcg_gen_lookup_and_goto_ptr(); - break; case DISAS_EXIT: tcg_gen_exit_tb(0); break; + case DISAS_JUMP: + tcg_gen_lookup_and_goto_ptr(); + break; case DISAS_NORETURN: case DISAS_SWI: break; diff --git a/target/arm/translate.c b/target/arm/translate.c index ba6ab7d287..fc03b5b8c8 100644 --- a/target/arm/translate.c +++ b/target/arm/translate.c @@ -1248,6 +1248,18 @@ static void gen_exception_insn(DisasContext *s, int offset, int excp, s->base.is_jmp = DISAS_NORETURN; } +static void gen_exception_bkpt_insn(DisasContext *s, int offset, uint32_t syn) +{ + TCGv_i32 tcg_syn; + + gen_set_condexec(s); + gen_set_pc_im(s, s->pc - offset); + tcg_syn = tcg_const_i32(syn); + gen_helper_exception_bkpt_insn(cpu_env, tcg_syn); + tcg_temp_free_i32(tcg_syn); + s->base.is_jmp = DISAS_NORETURN; +} + /* Force a TB lookup after an instruction that changes the CPU state. */ static inline void gen_lookup_tb(DisasContext *s) { @@ -8774,9 +8786,7 @@ static void disas_arm_insn(DisasContext *s, unsigned int insn) case 1: /* bkpt */ ARCH(5); - gen_exception_insn(s, 4, EXCP_BKPT, - syn_aa32_bkpt(imm16, false), - default_exception_el(s)); + gen_exception_bkpt_insn(s, 4, syn_aa32_bkpt(imm16, false)); break; case 2: /* Hypervisor call (v7) */ @@ -11983,8 +11993,7 @@ static void disas_thumb_insn(DisasContext *s, uint32_t insn) { int imm8 = extract32(insn, 0, 8); ARCH(5); - gen_exception_insn(s, 2, EXCP_BKPT, syn_aa32_bkpt(imm8, true), - default_exception_el(s)); + gen_exception_bkpt_insn(s, 2, syn_aa32_bkpt(imm8, true)); break; }