diff --git a/target/arm/hvf/hvf.c b/target/arm/hvf/hvf.c index de1e8fb8a0..8288b60529 100644 --- a/target/arm/hvf/hvf.c +++ b/target/arm/hvf/hvf.c @@ -1935,13 +1935,14 @@ static int hvf_handle_exception(CPUState *cpu, hv_vcpu_exit_exception_t *excp) break; case EC_AA64_HVC: cpu_synchronize_state(cpu); - if (arm_is_psci_call(arm_cpu, EXCP_HVC)) { + if (arm_cpu->psci_conduit == QEMU_PSCI_CONDUIT_HVC) { /* Do NOT advance $pc for HVC */ if (!hvf_handle_psci_call(cpu)) { trace_hvf_unknown_hvc(env->pc, env->xregs[0]); /* SMCCC 1.3 section 5.2 says every unknown SMCCC call returns -1 */ env->xregs[0] = -1; } + cpu->vcpu_dirty = true; } else { trace_hvf_unknown_hvc(env->pc, env->xregs[0]); hvf_raise_exception(cpu, EXCP_UDEF, syn_uncategorized(), 1); @@ -1949,7 +1950,7 @@ static int hvf_handle_exception(CPUState *cpu, hv_vcpu_exit_exception_t *excp) break; case EC_AA64_SMC: cpu_synchronize_state(cpu); - if (arm_is_psci_call(arm_cpu, EXCP_SMC)) { + if (arm_cpu->psci_conduit == QEMU_PSCI_CONDUIT_SMC) { /* Secure Monitor Call exception, we need to advance $pc */ advance_pc = true; @@ -1958,6 +1959,7 @@ static int hvf_handle_exception(CPUState *cpu, hv_vcpu_exit_exception_t *excp) /* SMCCC 1.3 section 5.2 says every unknown SMCCC call returns -1 */ env->xregs[0] = -1; } + cpu->vcpu_dirty = true; } else { trace_hvf_unknown_smc(env->xregs[0]); hvf_raise_exception(cpu, EXCP_UDEF, syn_uncategorized(), 1); @@ -1980,10 +1982,12 @@ static int hvf_handle_exception(CPUState *cpu, hv_vcpu_exit_exception_t *excp) error_report("0x%llx: unhandled exception ec=0x%x", env->pc, ec); } + /* flush any changed cpu state back to HVF */ + flush_cpu_state(cpu); + if (advance_pc) { uint64_t pc; - flush_cpu_state(cpu); r = hv_vcpu_get_reg(cpu->accel->fd, HV_REG_PC, &pc); assert_hvf_ok(r); @@ -2016,6 +2020,7 @@ static int hvf_handle_vmexit(CPUState *cpu, hv_vcpu_exit_t *exit) break; case HV_EXIT_REASON_CANCELED: /* we got kicked, no exit to process */ + ret = -1; break; default: g_assert_not_reached(); diff --git a/target/arm/tcg/tlb_helper.c b/target/arm/tcg/tlb_helper.c index f1983a5732..5c689d3b69 100644 --- a/target/arm/tcg/tlb_helper.c +++ b/target/arm/tcg/tlb_helper.c @@ -250,7 +250,11 @@ void arm_deliver_fault(ARMCPU *cpu, vaddr addr, fsr = compute_fsr_fsc(env, fi, target_el, mmu_idx, &fsc); if (access_type == MMU_INST_FETCH) { - syn = syn_insn_abort(same_el, fi->ea, fi->s1ptw, fsc); + if (fi->type == ARMFault_Alignment) { + syn = syn_pcalignment(); + } else { + syn = syn_insn_abort(same_el, fi->ea, fi->s1ptw, fsc); + } exc = EXCP_PREFETCH_ABORT; } else { bool gcs = regime_is_gcs(core_to_arm_mmu_idx(env, mmu_idx)); @@ -346,11 +350,18 @@ bool arm_cpu_tlb_fill_align(CPUState *cs, CPUTLBEntryFull *out, vaddr address, } /* - * Per R_XCHFJ, alignment fault not due to memory type has - * highest precedence. Otherwise, walk the page table and - * and collect the page description. + * PC alignment faults should be dealt with at translation time + * but we also need to catch them while being probed. + * + * Then per R_XCHFJ, alignment fault not due to memory type take + * precedence. Otherwise, walk the page table and and collect the + * page description. + * */ - if (address & ((1 << memop_alignment_bits(memop)) - 1)) { + if (access_type == MMU_INST_FETCH && !cpu->env.thumb && + (address & 3)) { + fi->type = ARMFault_Alignment; + } else if (address & ((1 << memop_alignment_bits(memop)) - 1)) { fi->type = ARMFault_Alignment; } else if (!get_phys_addr(&cpu->env, address, access_type, memop, core_to_arm_mmu_idx(&cpu->env, mmu_idx),