@@ -1848,6 +1848,45 @@ static inline bool check_p2m(bool is_data, paddr_t gpa)
return false;
}
+static int do_mmio_trap_stage2_abort_guest(struct cpu_user_regs *regs,
+ const union hsr hsr,
+ mmio_info_t *info,
+ vaddr_t gva, paddr_t gpa)
+{
+ enum io_state state;
+
+ state = try_handle_mmio(regs, info);
+ switch ( state )
+ {
+ case IO_ABORT:
+ goto inject_abt;
+ case IO_HANDLED:
+ /*
+ * If the instruction was decoded and has executed successfully
+ * on the MMIO region, then Xen should execute the next part of
+ * the instruction. (for eg increment the rn if it is a
+ * post-indexing instruction.
+ */
+ finalize_instr_emulation(&info->dabt_instr);
+ advance_pc(regs, hsr);
+ return 0;
+ case IO_RETRY:
+ /* finish later */
+ return 0;
+ case IO_UNHANDLED:
+ /* IO unhandled, try another way to handle it. */
+ return -EFAULT;
+ }
+
+inject_abt:
+ gdprintk(XENLOG_DEBUG,
+ "HSR=%#"PRIregister" pc=%#"PRIregister" gva=%#"PRIvaddr" gpa=%#"PRIpaddr"\n",
+ hsr.bits, regs->pc, gva, gpa);
+ inject_dabt_exception(regs, gva, hsr.len);
+
+ return 0;
+}
+
static void do_trap_stage2_abort_guest(struct cpu_user_regs *regs,
const union hsr hsr)
{
@@ -1862,7 +1901,6 @@ static void do_trap_stage2_abort_guest(struct cpu_user_regs *regs,
uint8_t fsc = xabt.fsc & ~FSC_LL_MASK;
bool is_data = (hsr.ec == HSR_EC_DATA_ABORT_LOWER_EL);
mmio_info_t info;
- enum io_state state;
/*
* If this bit has been set, it means that this stage-2 abort is caused
@@ -1896,6 +1934,8 @@ static void do_trap_stage2_abort_guest(struct cpu_user_regs *regs,
return; /* Try again */
}
+ info.gpa = gpa;
+ info.dabt = hsr.dabt;
switch ( fsc )
{
case FSC_FLT_PERM:
@@ -1909,6 +1949,17 @@ static void do_trap_stage2_abort_guest(struct cpu_user_regs *regs,
};
p2m_mem_access_check(gpa, gva, npfec);
+
+#ifdef CONFIG_HAS_MPU
+ /*
+ * MMIO region traps, generating from insufficient access permissions,
+ * will lead to data abort with Permission fault.
+ */
+ if ( is_data &&
+ (do_mmio_trap_stage2_abort_guest(regs, hsr, &info, gva, gpa) == 0) )
+ return;
+#endif
+
/*
* The only way to get here right now is because of mem_access,
* thus reinjecting the exception to the guest is never required.
@@ -1917,9 +1968,6 @@ static void do_trap_stage2_abort_guest(struct cpu_user_regs *regs,
}
case FSC_FLT_TRANS:
{
- info.gpa = gpa;
- info.dabt = hsr.dabt;
-
/*
* Assumption :- Most of the times when we get a data abort and the ISS
* is invalid or an instruction abort, the underlying cause is that the
@@ -1948,29 +1996,8 @@ static void do_trap_stage2_abort_guest(struct cpu_user_regs *regs,
if ( info.dabt_instr.state == INSTR_ERROR )
goto inject_abt;
- state = try_handle_mmio(regs, &info);
-
- switch ( state )
- {
- case IO_ABORT:
- goto inject_abt;
- case IO_HANDLED:
- /*
- * If the instruction was decoded and has executed successfully
- * on the MMIO region, then Xen should execute the next part of
- * the instruction. (for eg increment the rn if it is a
- * post-indexing instruction.
- */
- finalize_instr_emulation(&info.dabt_instr);
- advance_pc(regs, hsr);
- return;
- case IO_RETRY:
- /* finish later */
- return;
- case IO_UNHANDLED:
- /* IO unhandled, try another way to handle it. */
- break;
- }
+ if ( do_mmio_trap_stage2_abort_guest(regs, hsr, &info, gva, gpa) == 0 )
+ return;
/*
* If the instruction syndrome was invalid, then we already checked if