[PATCH v2 5/9] arm64: Allow the idreg override to deal with variable field width

Marc Zyngier maz at kernel.org
Thu Jun 30 09:04:56 PDT 2022


Currently, the override mechanism can only deal with 4bit fields,
which is the most common case. However, we now have a bunch of
ID registers that have more diverse field widths, such as
ID_AA64SMFR0_EL1, which has fields that are a single bit wide.

Add the support for variable width, and a macro that encodes
a feature width of 4 for all existing override.

No functional change.

Signed-off-by: Marc Zyngier <maz at kernel.org>
---
 arch/arm64/kernel/idreg-override.c | 28 ++++++++++++++++------------
 1 file changed, 16 insertions(+), 12 deletions(-)

diff --git a/arch/arm64/kernel/idreg-override.c b/arch/arm64/kernel/idreg-override.c
index 03185bc46d69..1e5f3dba3f01 100644
--- a/arch/arm64/kernel/idreg-override.c
+++ b/arch/arm64/kernel/idreg-override.c
@@ -27,10 +27,13 @@ struct ftr_set_desc {
 	struct {
 		char			name[FTR_DESC_FIELD_LEN];
 		u8			shift;
+		u8			width;
 		bool			(*filter)(u64 val);
 	} 				fields[];
 };
 
+#define FIELD(n, s, f)	{ .name = n, .shift = s, .width = 4, .filter = f }
+
 static bool __init mmfr1_vh_filter(u64 val)
 {
 	/*
@@ -47,7 +50,7 @@ static const struct ftr_set_desc mmfr1 __initconst = {
 	.name		= "id_aa64mmfr1",
 	.override	= &id_aa64mmfr1_override,
 	.fields		= {
-		{ "vh", ID_AA64MMFR1_VHE_SHIFT, mmfr1_vh_filter },
+		FIELD("vh", ID_AA64MMFR1_VHE_SHIFT, mmfr1_vh_filter),
 		{}
 	},
 };
@@ -56,8 +59,8 @@ static const struct ftr_set_desc pfr1 __initconst = {
 	.name		= "id_aa64pfr1",
 	.override	= &id_aa64pfr1_override,
 	.fields		= {
-	        { "bt", ID_AA64PFR1_BT_SHIFT },
-		{ "mte", ID_AA64PFR1_MTE_SHIFT},
+	        FIELD("bt", ID_AA64PFR1_BT_SHIFT, NULL),
+		FIELD("mte", ID_AA64PFR1_MTE_SHIFT, NULL),
 		{}
 	},
 };
@@ -66,10 +69,10 @@ static const struct ftr_set_desc isar1 __initconst = {
 	.name		= "id_aa64isar1",
 	.override	= &id_aa64isar1_override,
 	.fields		= {
-	        { "gpi", ID_AA64ISAR1_GPI_SHIFT },
-	        { "gpa", ID_AA64ISAR1_GPA_SHIFT },
-	        { "api", ID_AA64ISAR1_API_SHIFT },
-	        { "apa", ID_AA64ISAR1_APA_SHIFT },
+	        FIELD("gpi", ID_AA64ISAR1_GPI_SHIFT, NULL),
+	        FIELD("gpa", ID_AA64ISAR1_GPA_SHIFT, NULL),
+	        FIELD("api", ID_AA64ISAR1_API_SHIFT, NULL),
+	        FIELD("apa", ID_AA64ISAR1_APA_SHIFT, NULL),
 		{}
 	},
 };
@@ -78,8 +81,8 @@ static const struct ftr_set_desc isar2 __initconst = {
 	.name		= "id_aa64isar2",
 	.override	= &id_aa64isar2_override,
 	.fields		= {
-	        { "gpa3", ID_AA64ISAR2_GPA3_SHIFT },
-	        { "apa3", ID_AA64ISAR2_APA3_SHIFT },
+	        FIELD("gpa3", ID_AA64ISAR2_GPA3_SHIFT, NULL),
+	        FIELD("apa3", ID_AA64ISAR2_APA3_SHIFT, NULL),
 		{}
 	},
 };
@@ -92,7 +95,7 @@ static const struct ftr_set_desc kaslr __initconst = {
 	.override	= &kaslr_feature_override,
 #endif
 	.fields		= {
-		{ "disabled", 0 },
+		FIELD("disabled", 0, NULL),
 		{}
 	},
 };
@@ -147,7 +150,8 @@ static void __init match_options(const char *cmdline)
 
 		for (f = 0; strlen(regs[i]->fields[f].name); f++) {
 			u64 shift = regs[i]->fields[f].shift;
-			u64 mask = 0xfUL << shift;
+			u64 width = regs[i]->fields[f].width ?: 4;
+			u64 mask = GENMASK_ULL(shift + width - 1, shift);
 			u64 v;
 
 			if (find_field(cmdline, regs[i], f, &v))
@@ -155,7 +159,7 @@ static void __init match_options(const char *cmdline)
 
 			/*
 			 * If an override gets filtered out, advertise
-			 * it by setting the value to 0xf, but
+			 * it by setting the value to the all-ones while
 			 * clearing the mask... Yes, this is fragile.
 			 */
 			if (regs[i]->fields[f].filter &&
-- 
2.34.1




More information about the linux-arm-kernel mailing list