[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[RFC PATCH v1 19/26] xen/arm: io: add register-backed MMIO emulation helpers


  • To: xen-devel@xxxxxxxxxxxxxxxxxxxx
  • From: Koichiro Den <den@xxxxxxxxxxxxx>
  • Date: Fri, 15 May 2026 13:08:05 +0900
  • Arc-authentication-results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=valinux.co.jp; dmarc=pass action=none header.from=valinux.co.jp; dkim=pass header.d=valinux.co.jp; arc=none
  • Arc-message-signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=0GEQq9mUrsUO2xmFWtA16fpenonSWpgtrYzSVQj3dvs=; b=Q5s2yI/O1dtr+dmoLh13LvNx5cH63OY4ijrIl6nw7vFPLyLa9c8ToSyyeL+uoQdFPwU6sDj+hC+FjWppeNX+mErOPTrtkJPbRSQW76a2b+bG9guohPOsxjRR99TERYSucUp1zlDgUitCgmsMegTD2gy+CCQnhSiCYzRoq0f5O38mQ6R+t5Q5aFr0W157+GgmDOAYMPzVI/B8xn6QyilAOfKoXAbA5F20Wb5V94bZ1I8DIz4W2iAc9TQ0BV1EVzmMAlm9p0hA/RmRuly402F20go1Bzrh65IY4ikDTsODxuy28xVGxCh6KohNVn2k+cVybBNqQV4yQB4oo8sJBlWthg==
  • Arc-seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=I+Mwv9doEpL2dG4jZioqU2Kknggnd98GpjjzPGosMa2iRRSIp6O/nfW0SyX1YVmZ5bVDOxQrL6auDQDck15aeaymVVih2OZH0UpegmKXsSo1Q16LjKwR8nMg3vNTMkH/62VALPW4e6tpbkqzDRWEGckPJr36d9WiIbus+TZ34z1wsztEUBKMv0+z9WGAxikikzD+WFC7odBPh9wT7Kc+kep3K8aXT7rFVaP1dKLo2E6zNmBjwEqxusqN1FBTCOzUNfPQ9DdLTtNOL6cN5hJTnG6CXdj1o1hOQ0DmR0b96e2K2smWXb9UfsQ9xK6HYPCYQWucLaUISw3ExLj6CTQQ6g==
  • Authentication-results: eu.smtp.expurgate.cloud; dkim=pass header.s=selector1 header.d=valinux.co.jp header.i="@valinux.co.jp" header.h="From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck"
  • Authentication-results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=valinux.co.jp;
  • Cc: Andrew Cooper <andrew.cooper3@xxxxxxxxxx>, Anthony PERARD <anthony.perard@xxxxxxxxxx>, Michal Orzel <michal.orzel@xxxxxxx>, Jan Beulich <jbeulich@xxxxxxxx>, Julien Grall <julien@xxxxxxx>, Roger Pau Monné <roger.pau@xxxxxxxxxx>, Stefano Stabellini <sstabellini@xxxxxxxxxx>, "Daniel P. Smith" <dpsmith@xxxxxxxxxxxxxxxxxxxx>, Juergen Gross <jgross@xxxxxxxx>, Bertrand Marquis <bertrand.marquis@xxxxxxx>, Volodymyr Babchuk <Volodymyr_Babchuk@xxxxxxxx>
  • Delivery-date: Fri, 15 May 2026 04:11:45 +0000
  • List-id: Xen developer discussion <xen-devel.lists.xenproject.org>

Allow the Arm MMIO emulator to use a caller-provided register backend.
Realm exits carry GPR state in RecRun, not in guest_cpu_user_regs().

Signed-off-by: Koichiro Den <den@xxxxxxxxxxxxx>
---
 xen/arch/arm/include/asm/mmio.h | 11 ++++
 xen/arch/arm/io.c               | 99 +++++++++++++++++++++++++--------
 2 files changed, 88 insertions(+), 22 deletions(-)

diff --git a/xen/arch/arm/include/asm/mmio.h b/xen/arch/arm/include/asm/mmio.h
index b22cfdac5be9..b8a640dc6ee7 100644
--- a/xen/arch/arm/include/asm/mmio.h
+++ b/xen/arch/arm/include/asm/mmio.h
@@ -62,6 +62,14 @@ typedef int (*mmio_read_t)(struct vcpu *v, mmio_info_t *info,
 typedef int (*mmio_write_t)(struct vcpu *v, mmio_info_t *info,
                             register_t r, void *priv);
 
+typedef register_t (*mmio_reg_read_t)(void *ctxt, int reg);
+typedef void (*mmio_reg_write_t)(void *ctxt, int reg, register_t value);
+
+struct mmio_regops {
+    mmio_reg_read_t read;
+    mmio_reg_write_t write;
+};
+
 struct mmio_handler_ops {
     mmio_read_t read;
     mmio_write_t write;
@@ -83,6 +91,9 @@ struct vmmio {
 
 enum io_state try_handle_mmio(struct cpu_user_regs *regs,
                               mmio_info_t *info);
+enum io_state try_handle_mmio_regops(struct vcpu *v, mmio_info_t *info,
+                                     const struct mmio_regops *regops,
+                                     void *ctxt);
 void register_mmio_handler(struct domain *d,
                            const struct mmio_handler_ops *ops,
                            paddr_t addr, paddr_t size, void *priv);
diff --git a/xen/arch/arm/io.c b/xen/arch/arm/io.c
index 9707cadcf80e..9ce9fe1c1528 100644
--- a/xen/arch/arm/io.c
+++ b/xen/arch/arm/io.c
@@ -47,12 +47,36 @@ static const struct mmio_handler unmapped_handler = {
     .ops = &unmapped_ops
 };
 
+struct mmio_guest_regs {
+    struct cpu_user_regs *regs;
+};
+
+static register_t mmio_guest_read_reg(void *ctxt, int reg)
+{
+    struct mmio_guest_regs *guest = ctxt;
+
+    return get_user_reg(guest->regs, reg);
+}
+
+static void mmio_guest_write_reg(void *ctxt, int reg, register_t value)
+{
+    struct mmio_guest_regs *guest = ctxt;
+
+    set_user_reg(guest->regs, reg, value);
+}
+
+static const struct mmio_regops mmio_guest_regops = {
+    .read = mmio_guest_read_reg,
+    .write = mmio_guest_write_reg,
+};
+
 static enum io_state handle_read(const struct mmio_handler *handler,
                                  struct vcpu *v,
-                                 mmio_info_t *info)
+                                 mmio_info_t *info,
+                                 const struct mmio_regops *regops,
+                                 void *ctxt)
 {
     const struct hsr_dabt dabt = info->dabt;
-    struct cpu_user_regs *regs = guest_cpu_user_regs();
     /*
      * Initialize to zero to avoid leaking data if there is an
      * implementation error in the emulation (such as not correctly
@@ -66,22 +90,24 @@ static enum io_state handle_read(const struct mmio_handler 
*handler,
     ASSERT((r & ~GENMASK((1U << info->dabt.size) * 8 - 1, 0)) == 0);
 
     r = sign_extend(dabt, r);
-
-    set_user_reg(regs, dabt.reg, r);
+    regops->write(ctxt, dabt.reg, r);
 
     return IO_HANDLED;
 }
 
 static enum io_state handle_write(const struct mmio_handler *handler,
                                   struct vcpu *v,
-                                  mmio_info_t *info)
+                                  mmio_info_t *info,
+                                  const struct mmio_regops *regops,
+                                  void *ctxt)
 {
     const struct hsr_dabt dabt = info->dabt;
-    struct cpu_user_regs *regs = guest_cpu_user_regs();
+    register_t value;
     int ret;
 
-    ret = handler->ops->write(v, info, get_user_reg(regs, dabt.reg),
-                              handler->priv);
+    value = regops->read(ctxt, dabt.reg);
+    ret = handler->ops->write(v, info, value, handler->priv);
+
     return ret ? IO_HANDLED : IO_ABORT;
 }
 
@@ -183,10 +209,13 @@ void try_decode_instruction(const struct cpu_user_regs 
*regs,
     }
 }
 
-enum io_state try_handle_mmio(struct cpu_user_regs *regs,
-                              mmio_info_t *info)
+static enum io_state __try_handle_mmio(struct vcpu *v,
+                                       struct cpu_user_regs *regs,
+                                       mmio_info_t *info,
+                                       const struct mmio_regops *regops,
+                                       void *ctxt,
+                                       bool allow_ioreq)
 {
-    struct vcpu *v = current;
     const struct mmio_handler *handler = NULL;
     int rc;
 
@@ -202,17 +231,22 @@ enum io_state try_handle_mmio(struct cpu_user_regs *regs,
     if ( !handler )
     {
         bool trap_unmapped = v->domain->options &
-                                         XEN_DOMCTL_CDF_trap_unmapped_accesses;
-        rc = try_fwd_ioserv(regs, v, info);
-        if ( rc == IO_HANDLED )
-            return handle_ioserv(regs, v);
-        else if ( rc == IO_UNHANDLED && !trap_unmapped )
+                             XEN_DOMCTL_CDF_trap_unmapped_accesses;
+
+        if ( allow_ioreq )
         {
-            /* Fallback to the unmapped handler. */
-            handler = &unmapped_handler;
-        } else {
-            return rc;
+            rc = try_fwd_ioserv(regs, v, info);
+            if ( rc == IO_HANDLED )
+                return handle_ioserv(regs, v);
+            else if ( rc != IO_UNHANDLED )
+                return rc;
         }
+
+        if ( trap_unmapped )
+            return IO_UNHANDLED;
+
+        /* Fallback to the unmapped handler. */
+        handler = &unmapped_handler;
     }
 
     /*
@@ -228,9 +262,30 @@ enum io_state try_handle_mmio(struct cpu_user_regs *regs,
      * instruction on the emulated MMIO region.
      */
     if ( info->dabt.write )
-        return handle_write(handler, v, info);
+        return handle_write(handler, v, info, regops, ctxt);
     else
-        return handle_read(handler, v, info);
+        return handle_read(handler, v, info, regops, ctxt);
+}
+
+enum io_state try_handle_mmio(struct cpu_user_regs *regs,
+                              mmio_info_t *info)
+{
+    struct mmio_guest_regs guest = { .regs = regs };
+
+    return __try_handle_mmio(current, regs, info, &mmio_guest_regops,
+                             &guest, true);
+}
+
+enum io_state try_handle_mmio_regops(struct vcpu *v, mmio_info_t *info,
+                                     const struct mmio_regops *regops,
+                                     void *ctxt)
+{
+    ASSERT(v != NULL);
+    ASSERT(regops != NULL);
+    ASSERT(regops->read != NULL);
+    ASSERT(regops->write != NULL);
+
+    return __try_handle_mmio(v, NULL, info, regops, ctxt, false);
 }
 
 void register_mmio_handler(struct domain *d,
-- 
2.51.0




 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.