Re: [PATCH v4 17/18] target/arm: Provide cpu property for controling FEAT_LPA2

2022-03-04 Thread Peter Maydell
On Tue, 1 Mar 2022 at 22:00, Richard Henderson
 wrote:
>
> There is a Linux kernel bug present until v5.12 that prevents
> booting with FEAT_LPA2 enabled.  As a workaround for TCG, allow
> the feature to be disabled from -cpu max.
>
> Since this kernel bug is present in the Fedora 31 image that
> we test in avocado, disable lpa2 on the command-line.
>
> Signed-off-by: Richard Henderson 
> ---

Reviewed-by: Peter Maydell 

thanks
-- PMM



[PATCH v4 17/18] target/arm: Provide cpu property for controling FEAT_LPA2

2022-03-01 Thread Richard Henderson
There is a Linux kernel bug present until v5.12 that prevents
booting with FEAT_LPA2 enabled.  As a workaround for TCG, allow
the feature to be disabled from -cpu max.

Since this kernel bug is present in the Fedora 31 image that
we test in avocado, disable lpa2 on the command-line.

Signed-off-by: Richard Henderson 
---
 target/arm/cpu.h|  5 -
 target/arm/cpu.c|  6 ++
 target/arm/cpu64.c  | 24 
 tests/avocado/boot_linux.py |  2 ++
 4 files changed, 36 insertions(+), 1 deletion(-)

diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index 24d9fff170..4aa70ceca1 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -204,10 +204,12 @@ typedef struct {
 # define ARM_MAX_VQ16
 void arm_cpu_sve_finalize(ARMCPU *cpu, Error **errp);
 void arm_cpu_pauth_finalize(ARMCPU *cpu, Error **errp);
+void arm_cpu_lpa2_finalize(ARMCPU *cpu, Error **errp);
 #else
 # define ARM_MAX_VQ1
 static inline void arm_cpu_sve_finalize(ARMCPU *cpu, Error **errp) { }
 static inline void arm_cpu_pauth_finalize(ARMCPU *cpu, Error **errp) { }
+static inline void arm_cpu_lpa2_finalize(ARMCPU *cpu, Error **errp) { }
 #endif
 
 typedef struct ARMVectorReg {
@@ -975,10 +977,11 @@ struct ARMCPU {
 
 /*
  * Intermediate values used during property parsing.
- * Once finalized, the values should be read from ID_AA64ISAR1.
+ * Once finalized, the values should be read from ID_AA64*.
  */
 bool prop_pauth;
 bool prop_pauth_impdef;
+bool prop_lpa2;
 
 /* DCZ blocksize, in log_2(words), ie low 4 bits of DCZID_EL0 */
 uint32_t dcz_blocksize;
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
index e251f0df4b..e2747e7d86 100644
--- a/target/arm/cpu.c
+++ b/target/arm/cpu.c
@@ -1391,6 +1391,12 @@ void arm_cpu_finalize_features(ARMCPU *cpu, Error **errp)
 error_propagate(errp, local_err);
 return;
 }
+
+arm_cpu_lpa2_finalize(cpu, _err);
+if (local_err != NULL) {
+error_propagate(errp, local_err);
+return;
+}
 }
 
 if (kvm_enabled()) {
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
index 2fdc16bf18..eb44c05822 100644
--- a/target/arm/cpu64.c
+++ b/target/arm/cpu64.c
@@ -688,6 +688,29 @@ void aarch64_add_pauth_properties(Object *obj)
 }
 }
 
+static Property arm_cpu_lpa2_property =
+DEFINE_PROP_BOOL("lpa2", ARMCPU, prop_lpa2, true);
+
+void arm_cpu_lpa2_finalize(ARMCPU *cpu, Error **errp)
+{
+uint64_t t;
+
+/*
+ * We only install the property for tcg -cpu max; this is the
+ * only situation in which the cpu field can be true.
+ */
+if (!cpu->prop_lpa2) {
+return;
+}
+
+t = cpu->isar.id_aa64mmfr0;
+t = FIELD_DP64(t, ID_AA64MMFR0, TGRAN16, 2);   /* 16k pages w/ LPA2 */
+t = FIELD_DP64(t, ID_AA64MMFR0, TGRAN4, 1);/*  4k pages w/ LPA2 */
+t = FIELD_DP64(t, ID_AA64MMFR0, TGRAN16_2, 3); /* 16k stage2 w/ LPA2 */
+t = FIELD_DP64(t, ID_AA64MMFR0, TGRAN4_2, 3);  /*  4k stage2 w/ LPA2 */
+cpu->isar.id_aa64mmfr0 = t;
+}
+
 static void aarch64_host_initfn(Object *obj)
 {
 #if defined(CONFIG_KVM)
@@ -897,6 +920,7 @@ static void aarch64_max_initfn(Object *obj)
 aarch64_add_sve_properties(obj);
 object_property_add(obj, "sve-max-vq", "uint32", cpu_max_get_sve_max_vq,
 cpu_max_set_sve_max_vq, NULL, NULL);
+qdev_property_add_static(DEVICE(obj), _cpu_lpa2_property);
 }
 
 static void aarch64_a64fx_initfn(Object *obj)
diff --git a/tests/avocado/boot_linux.py b/tests/avocado/boot_linux.py
index ab19146d1e..ee584d2fdf 100644
--- a/tests/avocado/boot_linux.py
+++ b/tests/avocado/boot_linux.py
@@ -79,6 +79,7 @@ def test_virt_tcg_gicv2(self):
 """
 self.require_accelerator("tcg")
 self.vm.add_args("-accel", "tcg")
+self.vm.add_args("-cpu", "max,lpa2=off")
 self.vm.add_args("-machine", "virt,gic-version=2")
 self.add_common_args()
 self.launch_and_wait(set_up_ssh_connection=False)
@@ -91,6 +92,7 @@ def test_virt_tcg_gicv3(self):
 """
 self.require_accelerator("tcg")
 self.vm.add_args("-accel", "tcg")
+self.vm.add_args("-cpu", "max,lpa2=off")
 self.vm.add_args("-machine", "virt,gic-version=3")
 self.add_common_args()
 self.launch_and_wait(set_up_ssh_connection=False)
-- 
2.25.1