|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [XEN][RESEND][PATCH 3/3] xen/arm32: use IPA-based TLBI when supported with FEAT_nTLBPA
From: Haseeb Ashraf <haseeb.ashraf@xxxxxxxxxxx>
Arm32 provides TLBI-by-IPA instructions on CPUs that implement the
relevant stage-2 invalidation support. Detect this as a CPU capability
and use it to perform IPA-based invalidation in the p2m range flush
helper.
On Arm32, however, IPA-based stage-2 invalidation is only useful when
FEAT_nTLBPA is also present. Without FEAT_nTLBPA, a stage-2 invalidation
may still require discarding associated stage-1 side effects, and Arm32
does not provide a separate stage-1 guest TLBI that Xen can use here.
In that case, falling back to the existing full guest flush remains the
correct approach.
Therefore, enable Arm32 IPA-based invalidation only when both:
- TLBI-by-IPA is supported, and
- FEAT_nTLBPA is present.
As on Arm64, the helper bounds the per-page invalidation loop with a
256MB cutoff and falls back to a full guest flush for larger ranges.
For Arm32 this threshold is used as a conservative practical limit,
reusing the Arm64 cutoff, rather than as an Arm32-specific tuned value.
Suggested-by: Julien Grall <julien@xxxxxxx>
Signed-off-by: Haseeb Ashraf <haseeb.ashraf@xxxxxxxxxxx>
Changes in v4:
- Clarified that Arm32 IPA-based TLBI is only enabled when both
TLBI-by-IPA support and FEAT_nTLBPA are present.
- Clarified that the 256MB threshold is reused as a conservative
practical cutoff and is not based on Arm32-specific measurements.
- Refined comments and commit message wording.
Changes in v3:
- There are no functional changes in this version. There are minor
code updates and comment updates as per the feedback on v2.
- The cpregs are defined in order as per Coprocessor-> CRn-> Opcode 1
-> CRm-> Opcode 2.
- Added comment to explain why IPA-based TLBI is added only in
presence of FEAT_nTLBPA.
- Replaced `goto default_tlbi` with if...else.
- Removed extra definitions of MM32_UNITLB_* macros which were not
being used.
Changes in v2:
- This commit is implemented in v2 as per the feedback to implement
IPA-based TLBI for Arm32 in addition to Arm64.
---
xen/arch/arm/cpufeature.c | 12 ++++++
xen/arch/arm/include/asm/arm32/flushtlb.h | 47 ++++++++++++++++++++---
xen/arch/arm/include/asm/cpregs.h | 1 +
xen/arch/arm/include/asm/cpufeature.h | 15 +++++---
xen/arch/arm/include/asm/processor.h | 3 ++
5 files changed, 67 insertions(+), 11 deletions(-)
diff --git a/xen/arch/arm/cpufeature.c b/xen/arch/arm/cpufeature.c
index 86720c10a3..9ca449a551 100644
--- a/xen/arch/arm/cpufeature.c
+++ b/xen/arch/arm/cpufeature.c
@@ -18,6 +18,11 @@ DECLARE_BITMAP(cpu_hwcaps, ARM_NCAPS);
struct cpuinfo_arm __read_mostly domain_cpuinfo;
#ifdef CONFIG_ARM_32
+static bool has_tlb_ipa_instruction(const struct arm_cpu_capabilities *entry)
+{
+ return system_cpuinfo.mm32.unitlb == MM32_UNITLB_BY_IPA;
+}
+
static bool has_ntlbpa(const struct arm_cpu_capabilities *entry)
{
return system_cpuinfo.mm32.ntlbpa == MM32_NTLBPA_SUPPORT_IMP;
@@ -37,6 +42,13 @@ static bool has_sb_instruction(const struct
arm_cpu_capabilities *entry)
#endif
static const struct arm_cpu_capabilities arm_features[] = {
+#ifdef CONFIG_ARM_32
+ {
+ .desc = "IPA-based TLB Invalidation",
+ .capability = ARM32_HAS_TLB_IPA,
+ .matches = has_tlb_ipa_instruction,
+ },
+#endif
#if defined(CONFIG_ARM_32) || defined(CONFIG_ARM_64)
{
.desc = "Intermediate caching of translation table walks (nTLBPA)",
diff --git a/xen/arch/arm/include/asm/arm32/flushtlb.h
b/xen/arch/arm/include/asm/arm32/flushtlb.h
index 30df161323..1db6b8410e 100644
--- a/xen/arch/arm/include/asm/arm32/flushtlb.h
+++ b/xen/arch/arm/include/asm/arm32/flushtlb.h
@@ -1,6 +1,8 @@
#ifndef __ASM_ARM_ARM32_FLUSHTLB_H__
#define __ASM_ARM_ARM32_FLUSHTLB_H__
+#include <xen/sizes.h> /* For SZ_* macros. */
+
/*
* Every invalidation operation use the following patterns:
*
@@ -107,12 +109,47 @@ static inline void flush_guest_tlb_range_ipa(paddr_t ipa,
unsigned long size)
{
/*
- * Following can invalidate both stage-1 and stage-2 TLBs depending upon
- * the execution mode.
- *
- * See ARMv8 (DDI 0487L.b): G5-11698 Table G5-23.
+ * IPA-based stage-2 invalidation is only useful when FEAT_nTLBPA is
+ * present. Without FEAT_nTLBPA, invalidating stage-2 alone may still
+ * require discarding associated stage-1 side effects, and Arm32 does not
+ * provide a separate guest stage-1 TLBI for that case.
*/
- flush_guest_tlb();
+ if ( cpus_have_const_cap(ARM_HAS_NTLBPA) &&
+ cpus_have_const_cap(ARM32_HAS_TLB_IPA) )
+ {
+ /*
+ * If the IPA range is too large, fall back to a full guest flush
+ * rather than issuing a long per-page TLBI sequence. Reuse the same
+ * practical cutoff as Arm64.
+ */
+ if ( size > SZ_256M )
+ flush_guest_tlb();
+ else
+ {
+ paddr_t end = ipa + size;
+
+ dsb(ishst); /* Ensure prior page-tables updates have completed */
+ while ( ipa < end )
+ {
+ /* Flush stage-2 TLBs for this IPA. */
+ asm volatile ( STORE_CP32(0, TLBIIPAS2IS)
+ : : "r" (ipa >> PAGE_SHIFT) : "memory" );
+ ipa += PAGE_SIZE;
+ }
+ dsb(ish);
+ isb();
+ }
+ }
+ else
+ {
+ /*
+ * Following can invalidate both stage-1 and stage-2 TLBs depending
+ * upon the execution mode.
+ *
+ * See ARMv8 (DDI 0487L.b): G5-11698 Table G5-23.
+ */
+ flush_guest_tlb();
+ }
}
#endif /* __ASM_ARM_ARM32_FLUSHTLB_H__ */
diff --git a/xen/arch/arm/include/asm/cpregs.h
b/xen/arch/arm/include/asm/cpregs.h
index a7503a190f..26b5c08d0e 100644
--- a/xen/arch/arm/include/asm/cpregs.h
+++ b/xen/arch/arm/include/asm/cpregs.h
@@ -223,6 +223,7 @@
#define TLBIMVA p15,0,c8,c7,1 /* invalidate unified TLB entry by MVA
*/
#define TLBIASID p15,0,c8,c7,2 /* invalid unified TLB by ASID match */
#define TLBIMVAA p15,0,c8,c7,3 /* invalidate unified TLB entries by
MVA all ASID */
+#define TLBIIPAS2IS p15,4,c8,c0,1 /* Invalidate unified TLB entry for
stage 2 by IPA inner shareable */
#define TLBIALLHIS p15,4,c8,c3,0 /* Invalidate Entire Hyp. Unified TLB
inner shareable */
#define TLBIMVAHIS p15,4,c8,c3,1 /* Invalidate Unified Hyp. TLB by MVA
inner shareable */
#define TLBIALLNSNHIS p15,4,c8,c3,4 /* Invalidate Entire Non-Secure
Non-Hyp. Unified TLB inner shareable */
diff --git a/xen/arch/arm/include/asm/cpufeature.h
b/xen/arch/arm/include/asm/cpufeature.h
index 3e56dd27ef..09a516fe49 100644
--- a/xen/arch/arm/include/asm/cpufeature.h
+++ b/xen/arch/arm/include/asm/cpufeature.h
@@ -77,8 +77,9 @@
#define ARM_HAS_SB 16
#define ARM64_WORKAROUND_1508412 17
#define ARM_HAS_NTLBPA 18
+#define ARM32_HAS_TLB_IPA 19
-#define ARM_NCAPS 19
+#define ARM_NCAPS 20
#ifndef __ASSEMBLER__
@@ -447,15 +448,17 @@ struct cpuinfo_arm {
/* MMFR1 */
unsigned long __res1:32;
/* MMFR2 */
- unsigned long __res2:32;
+ unsigned long __res2:16;
+ unsigned long unitlb:4;
+ unsigned long __res3:12;
/* MMFR3 */
- unsigned long __res3:32;
- /* MMFR4 */
unsigned long __res4:32;
+ /* MMFR4 */
+ unsigned long __res5:32;
/* MMFR5 */
- unsigned long __res5:4;
+ unsigned long __res6:4;
unsigned long ntlbpa:4;
- unsigned long __res6:24;
+ unsigned long __res7:24;
};
} mm32;
diff --git a/xen/arch/arm/include/asm/processor.h
b/xen/arch/arm/include/asm/processor.h
index dbf9471a7a..0c47225de0 100644
--- a/xen/arch/arm/include/asm/processor.h
+++ b/xen/arch/arm/include/asm/processor.h
@@ -485,6 +485,9 @@
#define FSRL_STATUS_DEBUG (_AC(0x22,UL)<<0)
#ifdef CONFIG_ARM_32
+#define MM32_UNITLB_NI 0x0
+#define MM32_UNITLB_BY_IPA 0x6
+
#define MM32_NTLBPA_SUPPORT_NI 0x0
#define MM32_NTLBPA_SUPPORT_IMP 0x1
#endif
--
2.43.0
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |