diff mbox series

[v3,48/52] xen/mpu: enable MMIO region trap in MPU system

Message ID 20230626033443.2943270-49-Penny.Zheng@arm.com (mailing list archive)
State New, archived
Headers show
Series xen/arm: Add Armv8-R64 MPU support to Xen - Part#1 | expand

Commit Message

Penny Zheng June 26, 2023, 3:34 a.m. UTC
MMIO region traps, generating from insufficient access permissions,
will lead to data abort with Permission Fault in MPU system.
It is different with MMU system, which generates Translation Fault instead.

We extract common codes for dealing with MMIO trap into a new helper
do_mmio_trap_stage2_abort_guest().

Signed-off-by: Penny Zheng <penny.zheng@arm.com>
Signed-off-by: Wei Chen <wei.chen@arm.com>
---
v3:
- new commit
---
 xen/arch/arm/traps.c | 81 +++++++++++++++++++++++++++++---------------
 1 file changed, 54 insertions(+), 27 deletions(-)
diff mbox series

Patch

diff --git a/xen/arch/arm/traps.c b/xen/arch/arm/traps.c
index ef5c6a8195..bffa147c36 100644
--- a/xen/arch/arm/traps.c
+++ b/xen/arch/arm/traps.c
@@ -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