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

[PATCH v2 1/2] arch: arm64: always set IL=1 when injecting undefined exception


  • To: "xen-devel@xxxxxxxxxxxxxxxxxxxx" <xen-devel@xxxxxxxxxxxxxxxxxxxx>
  • From: Volodymyr Babchuk <Volodymyr_Babchuk@xxxxxxxx>
  • Date: Thu, 13 Feb 2025 15:37:54 +0000
  • Accept-language: en-US
  • Arc-authentication-results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=epam.com; dmarc=pass action=none header.from=epam.com; dkim=pass header.d=epam.com; 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=5lUWhDpk9z4EobijUnTQ7RN6XrcUJy+kCom73IXEI2I=; b=sEJfZL+ygAgiR6OUfcNsFhPyUM0LIrBZmwjgtMeriyQOfr3cd73TfmLxSHHypeC4Tj4FNTtmQclC4Wq+4z+1/rTaTqad+jrGXZu2vXbloUo7gZOaGFOyBKfCKyAf9c33dIorcDwjGWstsKjVU5h56+F5QjJ++MMiDiBJdN/XChEFR9ziYN3EF3C2ZVKK0DAuP7CVWZzjQjAjlgh8gF9wA/L6rXcQ7ub4nOP8qxLgIzGtV249nQ5hV4rSvaxsbWkzPOs8srbuSHx1rzO9R4VpB8vX3Za7u6whM4EuNFOMQpMVsFukRpOa8ofAXNuEqsIKytYHOTf24m7m7HVTWFYEgw==
  • Arc-seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=Bl5ebXVtgIhkPMEwNgHsOof++VfPRAA2ThrYaEK8VBybKn3hR/Ea93U9qHuX+tJ3hkgXNNMeJNeA8SkV6h4ts0+BrBgtoh/eeJNFP3gnAJaQf7TKYylaGhdvYbJoLY7jxR/KKfb7QAgTiVPxFS3RjnkBtvXHCPLxNoEwsTjcQ0T9N1J9+ddkXRLrcatgMlfkWmlqOQzfxu7L3PM6mcKHkJre2o7bHFUvFo1STViwf6vTItruxl56rL17G7ndl99xMv/E+LhQexe6KcL+t8SSwTBE3qRh8Pq+fjDk/F7Az5rOA8/kyw8tZ+Ao+XPiWRzueZnbezx2U7gpKRzFKp5tgA==
  • Authentication-results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=epam.com;
  • Cc: Volodymyr Babchuk <Volodymyr_Babchuk@xxxxxxxx>, Stefano Stabellini <sstabellini@xxxxxxxxxx>, Julien Grall <julien@xxxxxxx>, Bertrand Marquis <bertrand.marquis@xxxxxxx>, Michal Orzel <michal.orzel@xxxxxxx>, Volodymyr Babchuk <Volodymyr_Babchuk@xxxxxxxx>
  • Delivery-date: Thu, 13 Feb 2025 15:38:11 +0000
  • List-id: Xen developer discussion <xen-devel.lists.xenproject.org>
  • Thread-index: AQHbfi0/n6EK9tAEc02lOS/WV8Illg==
  • Thread-topic: [PATCH v2 1/2] arch: arm64: always set IL=1 when injecting undefined exception

ARM Architecture Reference Manual states that IL field of ESR_EL1
register should be 1 when EC is 0b000000 aka HSR_EC_UNKNOWN.

Section D24.2.40, page D24-7337 of ARM DDI 0487L:

  IL, bit [25]
  Instruction Length for synchronous exceptions. Possible values of this bit 
are:

  [...]

  0b1 - 32-bit instruction trapped.
  This value is also used when the exception is one of the following:
  [...]
   - An exception reported using EC value 0b000000.

To align code with the specification, set .len field to 1 in
inject_undef64_exception() and remove unneeded second parameter.

Signed-off-by: Volodymyr Babchuk <volodymyr_babchuk@xxxxxxxx>

---

Changes in v2:
 - Removed unused parameter from p2m_set_way_flush()
---
 xen/arch/arm/arm64/vsysreg.c           | 10 +++++-----
 xen/arch/arm/include/asm/arm64/traps.h |  2 +-
 xen/arch/arm/include/asm/p2m.h         |  3 +--
 xen/arch/arm/include/asm/traps.h       |  2 +-
 xen/arch/arm/p2m.c                     |  5 ++---
 xen/arch/arm/traps.c                   | 24 ++++++++++++------------
 xen/arch/arm/vcpreg.c                  | 26 +++++++++++++-------------
 xen/arch/arm/vsmc.c                    |  6 ++----
 8 files changed, 37 insertions(+), 41 deletions(-)

diff --git a/xen/arch/arm/arm64/vsysreg.c b/xen/arch/arm/arm64/vsysreg.c
index c73b2c95ce..d14258290f 100644
--- a/xen/arch/arm/arm64/vsysreg.c
+++ b/xen/arch/arm/arm64/vsysreg.c
@@ -95,7 +95,7 @@ void do_sysreg(struct cpu_user_regs *regs,
      */
     case HSR_SYSREG_ACTLR_EL1:
         if ( regs_mode_is_user(regs) )
-            return inject_undef_exception(regs, hsr);
+            return inject_undef_exception(regs);
         if ( hsr.sysreg.read )
             set_user_reg(regs, regidx, v->arch.actlr);
         break;
@@ -109,7 +109,7 @@ void do_sysreg(struct cpu_user_regs *regs,
     case HSR_SYSREG_DCCSW:
     case HSR_SYSREG_DCCISW:
         if ( !hsr.sysreg.read )
-            p2m_set_way_flush(current, regs, hsr);
+            p2m_set_way_flush(current, regs);
         break;
 
     /*
@@ -267,7 +267,7 @@ void do_sysreg(struct cpu_user_regs *regs,
     case HSR_SYSREG_CNTP_TVAL_EL0:
     case HSR_SYSREG_CNTP_CVAL_EL0:
         if ( !vtimer_emulate(regs, hsr) )
-            return inject_undef_exception(regs, hsr);
+            return inject_undef_exception(regs);
         break;
 
     /*
@@ -280,7 +280,7 @@ void do_sysreg(struct cpu_user_regs *regs,
     case HSR_SYSREG_ICC_SGI0R_EL1:
 
         if ( !vgic_emulate(regs, hsr) )
-            return inject_undef64_exception(regs, hsr.len);
+            return inject_undef64_exception(regs);
         break;
 
     /*
@@ -440,7 +440,7 @@ void do_sysreg(struct cpu_user_regs *regs,
     gdprintk(XENLOG_ERR,
              "unhandled 64-bit sysreg access %#"PRIregister"\n",
              hsr.bits & HSR_SYSREG_REGS_MASK);
-    inject_undef_exception(regs, hsr);
+    inject_undef_exception(regs);
 }
 
 /*
diff --git a/xen/arch/arm/include/asm/arm64/traps.h 
b/xen/arch/arm/include/asm/arm64/traps.h
index a347cb13d6..3be2fa69ee 100644
--- a/xen/arch/arm/include/asm/arm64/traps.h
+++ b/xen/arch/arm/include/asm/arm64/traps.h
@@ -1,7 +1,7 @@
 #ifndef __ASM_ARM64_TRAPS__
 #define __ASM_ARM64_TRAPS__
 
-void inject_undef64_exception(struct cpu_user_regs *regs, int instr_len);
+void inject_undef64_exception(struct cpu_user_regs *regs);
 
 void do_sysreg(struct cpu_user_regs *regs,
                const union hsr hsr);
diff --git a/xen/arch/arm/include/asm/p2m.h b/xen/arch/arm/include/asm/p2m.h
index 4818dd4b6a..594dc40041 100644
--- a/xen/arch/arm/include/asm/p2m.h
+++ b/xen/arch/arm/include/asm/p2m.h
@@ -298,8 +298,7 @@ void p2m_domain_creation_finished(struct domain *d);
  */
 int p2m_cache_flush_range(struct domain *d, gfn_t *pstart, gfn_t end);
 
-void p2m_set_way_flush(struct vcpu *v, struct cpu_user_regs *regs,
-                       const union hsr hsr);
+void p2m_set_way_flush(struct vcpu *v, struct cpu_user_regs *regs);
 
 void p2m_toggle_cache(struct vcpu *v, bool was_enabled);
 
diff --git a/xen/arch/arm/include/asm/traps.h b/xen/arch/arm/include/asm/traps.h
index 9a60dbf70e..3b40afe262 100644
--- a/xen/arch/arm/include/asm/traps.h
+++ b/xen/arch/arm/include/asm/traps.h
@@ -44,7 +44,7 @@ int check_conditional_instr(struct cpu_user_regs *regs, const 
union hsr hsr);
 
 void advance_pc(struct cpu_user_regs *regs, const union hsr hsr);
 
-void inject_undef_exception(struct cpu_user_regs *regs, const union hsr hsr);
+void inject_undef_exception(struct cpu_user_regs *regs);
 
 /* read as zero and write ignore */
 void handle_raz_wi(struct cpu_user_regs *regs, int regidx, bool read,
diff --git a/xen/arch/arm/p2m.c b/xen/arch/arm/p2m.c
index 65b70955e3..ef8bd4b6ab 100644
--- a/xen/arch/arm/p2m.c
+++ b/xen/arch/arm/p2m.c
@@ -428,8 +428,7 @@ int p2m_cache_flush_range(struct domain *d, gfn_t *pstart, 
gfn_t end)
  *
  *  - Once the caches are enabled, we stop trapping VM ops.
  */
-void p2m_set_way_flush(struct vcpu *v, struct cpu_user_regs *regs,
-                       const union hsr hsr)
+void p2m_set_way_flush(struct vcpu *v, struct cpu_user_regs *regs)
 {
     /* This function can only work with the current vCPU. */
     ASSERT(v == current);
@@ -438,7 +437,7 @@ void p2m_set_way_flush(struct vcpu *v, struct cpu_user_regs 
*regs,
     {
         gprintk(XENLOG_ERR,
                 "The cache should be flushed by VA rather than by set/way.\n");
-        inject_undef_exception(regs, hsr);
+        inject_undef_exception(regs);
         return;
     }
 
diff --git a/xen/arch/arm/traps.c b/xen/arch/arm/traps.c
index 737f4d65e3..5338d5c033 100644
--- a/xen/arch/arm/traps.c
+++ b/xen/arch/arm/traps.c
@@ -533,12 +533,12 @@ static vaddr_t exception_handler64(struct cpu_user_regs 
*regs, vaddr_t offset)
 }
 
 /* Inject an undefined exception into a 64 bit guest */
-void inject_undef64_exception(struct cpu_user_regs *regs, int instr_len)
+void inject_undef64_exception(struct cpu_user_regs *regs)
 {
     vaddr_t handler;
     const union hsr esr = {
         .iss = 0,
-        .len = instr_len,
+        .len = 1,
         .ec = HSR_EC_UNKNOWN,
     };
 
@@ -606,13 +606,13 @@ static void inject_iabt64_exception(struct cpu_user_regs 
*regs,
 
 #endif
 
-void inject_undef_exception(struct cpu_user_regs *regs, const union hsr hsr)
+void inject_undef_exception(struct cpu_user_regs *regs)
 {
         if ( is_32bit_domain(current->domain) )
             inject_undef32_exception(regs);
 #ifdef CONFIG_ARM_64
         else
-            inject_undef64_exception(regs, hsr.len);
+            inject_undef64_exception(regs);
 #endif
 }
 
@@ -1418,7 +1418,7 @@ static void do_trap_hypercall(struct cpu_user_regs *regs, 
register_t *nr,
     if ( hsr.iss != XEN_HYPERCALL_TAG )
     {
         gprintk(XENLOG_WARNING, "Invalid HVC imm 0x%x\n", hsr.iss);
-        return inject_undef_exception(regs, hsr);
+        return inject_undef_exception(regs);
     }
 
     curr->hcall_preempted = false;
@@ -1655,7 +1655,7 @@ void handle_raz_wi(struct cpu_user_regs *regs,
     ASSERT((min_el == 0) || (min_el == 1));
 
     if ( min_el > 0 && regs_mode_is_user(regs) )
-        return inject_undef_exception(regs, hsr);
+        return inject_undef_exception(regs);
 
     if ( read )
         set_user_reg(regs, regidx, 0);
@@ -1674,10 +1674,10 @@ void handle_wo_wi(struct cpu_user_regs *regs,
     ASSERT((min_el == 0) || (min_el == 1));
 
     if ( min_el > 0 && regs_mode_is_user(regs) )
-        return inject_undef_exception(regs, hsr);
+        return inject_undef_exception(regs);
 
     if ( read )
-        return inject_undef_exception(regs, hsr);
+        return inject_undef_exception(regs);
     /* else: ignore */
 
     advance_pc(regs, hsr);
@@ -1694,10 +1694,10 @@ void handle_ro_read_val(struct cpu_user_regs *regs,
     ASSERT((min_el == 0) || (min_el == 1));
 
     if ( min_el > 0 && regs_mode_is_user(regs) )
-        return inject_undef_exception(regs, hsr);
+        return inject_undef_exception(regs);
 
     if ( !read )
-        return inject_undef_exception(regs, hsr);
+        return inject_undef_exception(regs);
 
     set_user_reg(regs, regidx, val);
 
@@ -2147,7 +2147,7 @@ void asmlinkage do_trap_guest_sync(struct cpu_user_regs 
*regs)
     case HSR_EC_SVE:
         GUEST_BUG_ON(regs_mode_is_32bit(regs));
         gprintk(XENLOG_WARNING, "Domain tried to use SVE while not allowed\n");
-        inject_undef_exception(regs, hsr);
+        inject_undef_exception(regs);
         break;
 #endif
 
@@ -2164,7 +2164,7 @@ void asmlinkage do_trap_guest_sync(struct cpu_user_regs 
*regs)
         gprintk(XENLOG_WARNING,
                 "Unknown Guest Trap. HSR=%#"PRIregister" EC=0x%x IL=%x 
Syndrome=0x%"PRIx32"\n",
                 hsr.bits, hsr.ec, hsr.len, hsr.iss);
-        inject_undef_exception(regs, hsr);
+        inject_undef_exception(regs);
         break;
     }
 }
diff --git a/xen/arch/arm/vcpreg.c b/xen/arch/arm/vcpreg.c
index 0b336875a4..e7c484f2c1 100644
--- a/xen/arch/arm/vcpreg.c
+++ b/xen/arch/arm/vcpreg.c
@@ -206,7 +206,7 @@ void do_cp15_32(struct cpu_user_regs *regs, const union hsr 
hsr)
     case HSR_CPREG32(CNTP_CTL):
     case HSR_CPREG32(CNTP_TVAL):
         if ( !vtimer_emulate(regs, hsr) )
-            return inject_undef_exception(regs, hsr);
+            return inject_undef_exception(regs);
         break;
 
     /*
@@ -217,7 +217,7 @@ void do_cp15_32(struct cpu_user_regs *regs, const union hsr 
hsr)
      */
     case HSR_CPREG32(ACTLR):
         if ( regs_mode_is_user(regs) )
-            return inject_undef_exception(regs, hsr);
+            return inject_undef_exception(regs);
         if ( cp32.read )
             set_user_reg(regs, regidx, v->arch.actlr);
         break;
@@ -232,7 +232,7 @@ void do_cp15_32(struct cpu_user_regs *regs, const union hsr 
hsr)
     case HSR_CPREG32(DCCSW):
     case HSR_CPREG32(DCCISW):
         if ( !cp32.read )
-            p2m_set_way_flush(current, regs, hsr);
+            p2m_set_way_flush(current, regs);
         break;
 
     /*
@@ -397,7 +397,7 @@ void do_cp15_32(struct cpu_user_regs *regs, const union hsr 
hsr)
                  cp32.op1, cp32.reg, cp32.crn, cp32.crm, cp32.op2, regs->pc);
         gdprintk(XENLOG_ERR, "unhandled 32-bit CP15 access %#"PRIregister"\n",
                  hsr.bits & HSR_CP32_REGS_MASK);
-        inject_undef_exception(regs, hsr);
+        inject_undef_exception(regs);
         return;
     }
     advance_pc(regs, hsr);
@@ -421,7 +421,7 @@ void do_cp15_64(struct cpu_user_regs *regs, const union hsr 
hsr)
      */
     case HSR_CPREG64(CNTP_CVAL):
         if ( !vtimer_emulate(regs, hsr) )
-            return inject_undef_exception(regs, hsr);
+            return inject_undef_exception(regs);
         break;
 
     /*
@@ -433,7 +433,7 @@ void do_cp15_64(struct cpu_user_regs *regs, const union hsr 
hsr)
     case HSR_CPREG64(ICC_ASGI1R):
     case HSR_CPREG64(ICC_SGI0R):
         if ( !vgic_emulate(regs, hsr) )
-            return inject_undef_exception(regs, hsr);
+            return inject_undef_exception(regs);
         break;
 
     GENERATE_CASE(TTBR0, 64)
@@ -467,7 +467,7 @@ void do_cp15_64(struct cpu_user_regs *regs, const union hsr 
hsr)
             gdprintk(XENLOG_ERR,
                      "unhandled 64-bit CP15 access %#"PRIregister"\n",
                      hsr.bits & HSR_CP64_REGS_MASK);
-            inject_undef_exception(regs, hsr);
+            inject_undef_exception(regs);
             return;
         }
     }
@@ -532,7 +532,7 @@ void do_cp14_32(struct cpu_user_regs *regs, const union hsr 
hsr)
          * is set to 0, which we emulated below.
          */
         if ( !cp32.read )
-            return inject_undef_exception(regs, hsr);
+            return inject_undef_exception(regs);
 
         /* Implement the minimum requirements:
          *  - Number of watchpoints: 1
@@ -631,7 +631,7 @@ void do_cp14_32(struct cpu_user_regs *regs, const union hsr 
hsr)
              cp32.op1, cp32.reg, cp32.crn, cp32.crm, cp32.op2, regs->pc);
     gdprintk(XENLOG_ERR, "unhandled 32-bit cp14 access %#"PRIregister"\n",
              hsr.bits & HSR_CP32_REGS_MASK);
-    inject_undef_exception(regs, hsr);
+    inject_undef_exception(regs);
 }
 
 void do_cp14_64(struct cpu_user_regs *regs, const union hsr hsr)
@@ -669,7 +669,7 @@ void do_cp14_64(struct cpu_user_regs *regs, const union hsr 
hsr)
              cp64.op1, cp64.reg1, cp64.reg2, cp64.crm, regs->pc);
     gdprintk(XENLOG_ERR, "unhandled 64-bit CP14 access %#"PRIregister"\n",
              hsr.bits & HSR_CP64_REGS_MASK);
-    inject_undef_exception(regs, hsr);
+    inject_undef_exception(regs);
 }
 
 void do_cp14_dbg(struct cpu_user_regs *regs, const union hsr hsr)
@@ -698,7 +698,7 @@ void do_cp14_dbg(struct cpu_user_regs *regs, const union 
hsr hsr)
     gdprintk(XENLOG_ERR, "unhandled 64-bit CP14 DBG access %#"PRIregister"\n",
              hsr.bits & HSR_CP64_REGS_MASK);
 
-    inject_undef_exception(regs, hsr);
+    inject_undef_exception(regs);
 }
 
 void do_cp10(struct cpu_user_regs *regs, const union hsr hsr)
@@ -731,7 +731,7 @@ void do_cp10(struct cpu_user_regs *regs, const union hsr 
hsr)
                  cp32.op1, cp32.reg, cp32.crn, cp32.crm, cp32.op2, regs->pc);
         gdprintk(XENLOG_ERR, "unhandled 32-bit CP10 access %#"PRIregister"\n",
                  hsr.bits & HSR_CP32_REGS_MASK);
-        inject_undef_exception(regs, hsr);
+        inject_undef_exception(regs);
         return;
     }
     
@@ -756,7 +756,7 @@ void do_cp(struct cpu_user_regs *regs, const union hsr hsr)
 
     ASSERT(!cp.tas); /* We don't trap SIMD instruction */
     gdprintk(XENLOG_ERR, "unhandled CP%d access\n", cp.coproc);
-    inject_undef_exception(regs, hsr);
+    inject_undef_exception(regs);
 }
 
 /*
diff --git a/xen/arch/arm/vsmc.c b/xen/arch/arm/vsmc.c
index 62d8117a12..e253865b6c 100644
--- a/xen/arch/arm/vsmc.c
+++ b/xen/arch/arm/vsmc.c
@@ -346,13 +346,11 @@ void do_trap_smc(struct cpu_user_regs *regs, const union 
hsr hsr)
     if ( vsmccc_handle_call(regs) )
         advance_pc(regs, hsr);
     else
-        inject_undef_exception(regs, hsr);
+        inject_undef_exception(regs);
 }
 
 void do_trap_hvc_smccc(struct cpu_user_regs *regs)
 {
-    const union hsr hsr = { .bits = regs->hsr };
-
     /*
      * vsmccc_handle_call() will return false if this call is not
      * SMCCC compatible (e.g. immediate value != 0). As it is not
@@ -360,7 +358,7 @@ void do_trap_hvc_smccc(struct cpu_user_regs *regs)
      * ARM_SMCCC_ERR_UNKNOWN_FUNCTION.
      */
     if ( !vsmccc_handle_call(regs) )
-        inject_undef_exception(regs, hsr);
+        inject_undef_exception(regs);
 }
 
 /*
-- 
2.47.1



 


Rackspace

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