* [RFC PATCH 0/3] KVM: arm64: Don't claim MTE_ASYNC if not supported
@ 2025-04-14 12:40 Ben Horgan
2025-04-14 12:40 ` [RFC PATCH 1/3] arm64/sysreg: Expose MTE_frac so that it is visible to KVM Ben Horgan
` (2 more replies)
0 siblings, 3 replies; 6+ messages in thread
From: Ben Horgan @ 2025-04-14 12:40 UTC (permalink / raw)
To: linux-arm-kernel, kvmarm, linux-kselftest
Cc: maz, oliver.upton, joey.gouly, suzuki.poulose, yuzenghui, shuah,
Ben Horgan
The ID_AA64PFR1_EL1.MTE_frac field is currently hidden from KVM.
However, when ID_AA64PFR1_EL1.MTE==2, ID_AA64PFR1_EL1.MTE_frac==0
indicates that MTE_ASYNC is supported. On a host with
ID_AA64PFR1_EL1.MTE==2 but without MTE_ASYNC support a guest with the
MTE capability enabled will incorrectly see MTE_ASYNC advertised as
supported. This series fixes that.
This was found by inspection and the current behaviour is not known to
break anything. Linux doesn't check MTE_frac, and wrongly, assumes
MTE async faults can be generated whenever MTE is supported. This is
a separate problem and not addressed here.
I am looking for feedback on whether this change is valuable or
otherwise.
Ben Horgan (3):
arm64/sysreg: Expose MTE_frac so that it is visible to KVM
KVM: arm64: Make MTE_frac masking conditional on MTE capability
KVM: selftests: Confirm exposing MTE_frac does not break migration
arch/arm64/kernel/cpufeature.c | 1 +
arch/arm64/kvm/sys_regs.c | 26 ++++++-
.../testing/selftests/kvm/arm64/set_id_regs.c | 77 ++++++++++++++++++-
3 files changed, 101 insertions(+), 3 deletions(-)
base-commit: 8ffd015db85fea3e15a77027fda6c02ced4d2444
--
2.43.0
^ permalink raw reply [flat|nested] 6+ messages in thread
* [RFC PATCH 1/3] arm64/sysreg: Expose MTE_frac so that it is visible to KVM
2025-04-14 12:40 [RFC PATCH 0/3] KVM: arm64: Don't claim MTE_ASYNC if not supported Ben Horgan
@ 2025-04-14 12:40 ` Ben Horgan
2025-04-14 12:40 ` [RFC PATCH 2/3] KVM: arm64: Make MTE_frac masking conditional on MTE capability Ben Horgan
2025-04-14 12:40 ` [RFC PATCH 3/3] KVM: selftests: Confirm exposing MTE_frac does not break migration Ben Horgan
2 siblings, 0 replies; 6+ messages in thread
From: Ben Horgan @ 2025-04-14 12:40 UTC (permalink / raw)
To: linux-arm-kernel, kvmarm, linux-kselftest
Cc: maz, oliver.upton, joey.gouly, suzuki.poulose, yuzenghui, shuah,
Ben Horgan
KVM exposes the sanitised ID registers to guests. Currently these ignore
the ID_AA64PFR1_EL1.MTE_frac field, meaning guests always see a value of
zero.
This is a problem for platforms without the MTE_ASYNC feature where
ID_AA64PFR1_EL1.MTE==0x2 and ID_AA64PFR1_EL1.MTE_frac==0xf. KVM forces
MTE_frac to zero, meaning the guest believes MTE_ASYNC is supported, when
no async fault will ever occur.
Before KVM can fix this, the architecture needs to sanitise the ID
register field for MTE_frac.
Linux itself does not use MTE_frac field and just assumes MTE async faults
can be generated if MTE is supported.
Signed-off-by: Ben Horgan <ben.horgan@arm.com>
---
arch/arm64/kernel/cpufeature.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
index 9c4d6d552b25..e952f4b07ce1 100644
--- a/arch/arm64/kernel/cpufeature.c
+++ b/arch/arm64/kernel/cpufeature.c
@@ -298,6 +298,7 @@ static const struct arm64_ftr_bits ftr_id_aa64pfr0[] = {
static const struct arm64_ftr_bits ftr_id_aa64pfr1[] = {
ARM64_FTR_BITS(FTR_VISIBLE_IF_IS_ENABLED(CONFIG_ARM64_GCS),
FTR_STRICT, FTR_LOWER_SAFE, ID_AA64PFR1_EL1_GCS_SHIFT, 4, 0),
+ S_ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64PFR1_EL1_MTE_frac_SHIFT, 4, 0),
ARM64_FTR_BITS(FTR_VISIBLE_IF_IS_ENABLED(CONFIG_ARM64_SME),
FTR_STRICT, FTR_LOWER_SAFE, ID_AA64PFR1_EL1_SME_SHIFT, 4, 0),
ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64PFR1_EL1_MPAM_frac_SHIFT, 4, 0),
--
2.43.0
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [RFC PATCH 2/3] KVM: arm64: Make MTE_frac masking conditional on MTE capability
2025-04-14 12:40 [RFC PATCH 0/3] KVM: arm64: Don't claim MTE_ASYNC if not supported Ben Horgan
2025-04-14 12:40 ` [RFC PATCH 1/3] arm64/sysreg: Expose MTE_frac so that it is visible to KVM Ben Horgan
@ 2025-04-14 12:40 ` Ben Horgan
2025-04-27 17:24 ` Marc Zyngier
2025-04-14 12:40 ` [RFC PATCH 3/3] KVM: selftests: Confirm exposing MTE_frac does not break migration Ben Horgan
2 siblings, 1 reply; 6+ messages in thread
From: Ben Horgan @ 2025-04-14 12:40 UTC (permalink / raw)
To: linux-arm-kernel, kvmarm, linux-kselftest
Cc: maz, oliver.upton, joey.gouly, suzuki.poulose, yuzenghui, shuah,
Ben Horgan
If MTE_frac is masked out unconditionally then the guest will always
see ID_AA64PFR1_EL1_MTE_frac as 0. However, a value of 0 when
ID_AA64PFR1_EL1_MTE is 2 indicates that MTE_ASYNC is supported. Hence, for
a host with ID_AA64PFR1_EL1_MTE==2 and ID_AA64PFR1_EL1_MTE_frac==0xf
(MTE_ASYNC unsupported) the guest would see MTE_ASYNC advertised as
supported whilst the host does not support it. Hence, expose the sanitised
value of MTE_frac to the guest and user-space.
As MTE_frac was previously hidden, always 0, and KVM must accept values
from KVM provided by user-space, when ID_AA64PFR1_EL1.MTE is 2 allow
user-space to set ID_AA64PFR1_EL1.MTE_frac to 0. However, ignore it to
avoid incorrectly claiming hardware support for MTE_ASYNC in the guest.
Note that linux does not check the value of ID_AA64PFR1_EL1_MTE_frac and
wrongly assumes that MTE async faults can be generated even on hardware
that does nto support them. This issue is not addressed here.
Signed-off-by: Ben Horgan <ben.horgan@arm.com>
---
arch/arm64/kvm/sys_regs.c | 26 ++++++++++++++++++++++++--
1 file changed, 24 insertions(+), 2 deletions(-)
diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
index 005ad28f7306..9ae647082684 100644
--- a/arch/arm64/kvm/sys_regs.c
+++ b/arch/arm64/kvm/sys_regs.c
@@ -1600,13 +1600,14 @@ static u64 __kvm_read_sanitised_id_reg(const struct kvm_vcpu *vcpu,
val = sanitise_id_aa64pfr0_el1(vcpu, val);
break;
case SYS_ID_AA64PFR1_EL1:
- if (!kvm_has_mte(vcpu->kvm))
+ if (!kvm_has_mte(vcpu->kvm)) {
val &= ~ARM64_FEATURE_MASK(ID_AA64PFR1_EL1_MTE);
+ val &= ~ARM64_FEATURE_MASK(ID_AA64PFR1_EL1_MTE_frac);
+ }
val &= ~ARM64_FEATURE_MASK(ID_AA64PFR1_EL1_SME);
val &= ~ARM64_FEATURE_MASK(ID_AA64PFR1_EL1_RNDR_trap);
val &= ~ARM64_FEATURE_MASK(ID_AA64PFR1_EL1_NMI);
- val &= ~ARM64_FEATURE_MASK(ID_AA64PFR1_EL1_MTE_frac);
val &= ~ARM64_FEATURE_MASK(ID_AA64PFR1_EL1_GCS);
val &= ~ARM64_FEATURE_MASK(ID_AA64PFR1_EL1_THE);
val &= ~ARM64_FEATURE_MASK(ID_AA64PFR1_EL1_MTEX);
@@ -1953,11 +1954,32 @@ static int set_id_aa64pfr1_el1(struct kvm_vcpu *vcpu,
{
u64 hw_val = read_sanitised_ftr_reg(SYS_ID_AA64PFR1_EL1);
u64 mpam_mask = ID_AA64PFR1_EL1_MPAM_frac_MASK;
+ u8 mte = SYS_FIELD_GET(ID_AA64PFR1_EL1, MTE, hw_val);
+ u8 user_mte_frac = SYS_FIELD_GET(ID_AA64PFR1_EL1, MTE_frac, user_val);
/* See set_id_aa64pfr0_el1 for comment about MPAM */
if ((hw_val & mpam_mask) == (user_val & mpam_mask))
user_val &= ~ID_AA64PFR1_EL1_MPAM_frac_MASK;
+ /*
+ * Previously MTE_frac was hidden from guest. However, if the
+ * hardware supports MTE2 but not MTE_ASYM_FAULT then a value
+ * of 0 for this field indicates that the hardware supports
+ * MTE_ASYNC. Whereas, 0xf indicates MTE_ASYNC is not supported.
+ *
+ * As KVM must accept values from KVM provided by user-space,
+ * when ID_AA64PFR1_EL1.MTE is 2 allow user-space to set
+ * ID_AA64PFR1_EL1.MTE_frac to 0. However, ignore it to avoid
+ * incorrectly claiming hardware support for MTE_ASYNC in the
+ * guest.
+ */
+
+ if (mte == ID_AA64PFR1_EL1_MTE_MTE2 &&
+ user_mte_frac == ID_AA64PFR1_EL1_MTE_frac_ASYNC) {
+ user_val &= ~ID_AA64PFR1_EL1_MTE_frac_MASK;
+ user_val |= hw_val & ID_AA64PFR1_EL1_MTE_frac_MASK;
+ }
+
return set_id_reg(vcpu, rd, user_val);
}
--
2.43.0
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [RFC PATCH 3/3] KVM: selftests: Confirm exposing MTE_frac does not break migration
2025-04-14 12:40 [RFC PATCH 0/3] KVM: arm64: Don't claim MTE_ASYNC if not supported Ben Horgan
2025-04-14 12:40 ` [RFC PATCH 1/3] arm64/sysreg: Expose MTE_frac so that it is visible to KVM Ben Horgan
2025-04-14 12:40 ` [RFC PATCH 2/3] KVM: arm64: Make MTE_frac masking conditional on MTE capability Ben Horgan
@ 2025-04-14 12:40 ` Ben Horgan
2 siblings, 0 replies; 6+ messages in thread
From: Ben Horgan @ 2025-04-14 12:40 UTC (permalink / raw)
To: linux-arm-kernel, kvmarm, linux-kselftest
Cc: maz, oliver.upton, joey.gouly, suzuki.poulose, yuzenghui, shuah,
Ben Horgan
When MTE is supported but MTE_ASYMM is not (ID_AA64PFR1_EL1.MTE == 2)
ID_AA64PFR1_EL1.MTE_frac == 0xF indicates MTE_ASYNC is unsupported
and MTE_frac == 0 indicates it is supported.
As MTE_frac was previously unconditionally read as 0 from the guest
and user-space, check that using SET_ONE_REG to set it to 0 succeeds
but does not change MTE_frac from unsupported (0xF) to supported (0).
This is required as values originating from KVM from user-space must
be accepted to avoid breaking migration.
Also, to allow this MTE field to be tested, enable KVM_ARM_CAP_MTE
for the set_id_regs test. No effect on existing tests is expected.
Signed-off-by: Ben Horgan <ben.horgan@arm.com>
---
.../testing/selftests/kvm/arm64/set_id_regs.c | 77 ++++++++++++++++++-
1 file changed, 76 insertions(+), 1 deletion(-)
diff --git a/tools/testing/selftests/kvm/arm64/set_id_regs.c b/tools/testing/selftests/kvm/arm64/set_id_regs.c
index 322b9d3b0125..34f4174e7285 100644
--- a/tools/testing/selftests/kvm/arm64/set_id_regs.c
+++ b/tools/testing/selftests/kvm/arm64/set_id_regs.c
@@ -15,6 +15,8 @@
#include "test_util.h"
#include <linux/bitfield.h>
+bool have_cap_arm_mte;
+
enum ftr_type {
FTR_EXACT, /* Use a predefined safe value */
FTR_LOWER_SAFE, /* Smaller value is safe */
@@ -543,6 +545,70 @@ static void test_user_set_mpam_reg(struct kvm_vcpu *vcpu)
ksft_test_result_fail("ID_AA64PFR1_EL1.MPAM_frac value should not be ignored\n");
}
+#define MTE_IDREG_TEST 1
+static void test_user_set_mte_reg(struct kvm_vcpu *vcpu)
+{
+ uint64_t masks[KVM_ARM_FEATURE_ID_RANGE_SIZE];
+ struct reg_mask_range range = {
+ .addr = (__u64)masks,
+ };
+ uint64_t val;
+ uint64_t mte;
+ uint64_t mte_frac;
+ int idx, err;
+
+ if (!have_cap_arm_mte) {
+ ksft_test_result_skip("MTE capability not supported, nothing to test\n");
+ return;
+ }
+
+ /* Get writable masks for feature ID registers */
+ memset(range.reserved, 0, sizeof(range.reserved));
+ vm_ioctl(vcpu->vm, KVM_ARM_GET_REG_WRITABLE_MASKS, &range);
+
+ idx = encoding_to_range_idx(SYS_ID_AA64PFR1_EL1);
+ if ((masks[idx] & ID_AA64PFR1_EL1_MTE_frac_MASK) == ID_AA64PFR1_EL1_MTE_frac_MASK) {
+ ksft_test_result_skip("ID_AA64PFR1_EL1.MTE_frac is officially writable, nothing to test\n");
+ return;
+ }
+
+ /*
+ * When MTE is supported but MTE_ASYMM is not (ID_AA64PFR1_EL1.MTE == 2)
+ * ID_AA64PFR1_EL1.MTE_frac == 0xF indicates MTE_ASYNC is unsupported
+ * and MTE_frac == 0 indicates it is supported.
+ *
+ * As MTE_frac was previously unconditionally read as 0, check
+ * that the set to 0 succeeds but does not change MTE_frac
+ * from unsupported (0xF) to supported (0).
+ *
+ */
+ val = vcpu_get_reg(vcpu, KVM_ARM64_SYS_REG(SYS_ID_AA64PFR1_EL1));
+
+ mte = FIELD_GET(ARM64_FEATURE_MASK(ID_AA64PFR1_EL1_MTE), val);
+ mte_frac = FIELD_GET(ARM64_FEATURE_MASK(ID_AA64PFR1_EL1_MTE_frac), val);
+ if (mte != ID_AA64PFR1_EL1_MTE_MTE2 ||
+ mte_frac != ID_AA64PFR1_EL1_MTE_frac_NI) {
+ ksft_test_result_skip("MTE_ASYNC or MTE_ASYMM are supported, nothing to test\n");
+ return;
+ }
+
+ /* Try to set MTE_frac=0. */
+ val &= ~ID_AA64PFR1_EL1_MTE_frac_MASK;
+ val |= FIELD_PREP(ID_AA64PFR1_EL1_MTE_frac_MASK, 0);
+ err = __vcpu_set_reg(vcpu, KVM_ARM64_SYS_REG(SYS_ID_AA64PFR1_EL1), val);
+ if (err) {
+ ksft_test_result_fail("ID_AA64PFR1_EL1.MTE_frac=0 was not accepted\n");
+ return;
+ }
+
+ val = vcpu_get_reg(vcpu, KVM_ARM64_SYS_REG(SYS_ID_AA64PFR1_EL1));
+ mte_frac = FIELD_GET(ARM64_FEATURE_MASK(ID_AA64PFR1_EL1_MTE_frac), val);
+ if (mte_frac == ID_AA64PFR1_EL1_MTE_frac_NI)
+ ksft_test_result_pass("ID_AA64PFR1_EL1.MTE_frac=0 accepted and still 0xF\n");
+ else
+ ksft_test_result_pass("ID_AA64PFR1_EL1.MTE_frac no longer 0xF\n");
+}
+
static void test_guest_reg_read(struct kvm_vcpu *vcpu)
{
bool done = false;
@@ -673,6 +739,14 @@ static void test_reset_preserves_id_regs(struct kvm_vcpu *vcpu)
ksft_test_result_pass("%s\n", __func__);
}
+void kvm_arch_vm_post_create(struct kvm_vm *vm)
+{
+ if (vm_check_cap(vm, KVM_CAP_ARM_MTE)) {
+ vm_enable_cap(vm, KVM_CAP_ARM_MTE, 0);
+ have_cap_arm_mte = true;
+ }
+}
+
int main(void)
{
struct kvm_vcpu *vcpu;
@@ -701,7 +775,7 @@ int main(void)
ARRAY_SIZE(ftr_id_aa64pfr1_el1) + ARRAY_SIZE(ftr_id_aa64mmfr0_el1) +
ARRAY_SIZE(ftr_id_aa64mmfr1_el1) + ARRAY_SIZE(ftr_id_aa64mmfr2_el1) +
ARRAY_SIZE(ftr_id_aa64zfr0_el1) - ARRAY_SIZE(test_regs) + 3 +
- MPAM_IDREG_TEST;
+ MPAM_IDREG_TEST + MTE_IDREG_TEST;
ksft_set_plan(test_cnt);
@@ -709,6 +783,7 @@ int main(void)
test_vcpu_ftr_id_regs(vcpu);
test_vcpu_non_ftr_id_regs(vcpu);
test_user_set_mpam_reg(vcpu);
+ test_user_set_mte_reg(vcpu);
test_guest_reg_read(vcpu);
--
2.43.0
^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [RFC PATCH 2/3] KVM: arm64: Make MTE_frac masking conditional on MTE capability
2025-04-14 12:40 ` [RFC PATCH 2/3] KVM: arm64: Make MTE_frac masking conditional on MTE capability Ben Horgan
@ 2025-04-27 17:24 ` Marc Zyngier
2025-04-28 11:26 ` Ben Horgan
0 siblings, 1 reply; 6+ messages in thread
From: Marc Zyngier @ 2025-04-27 17:24 UTC (permalink / raw)
To: Ben Horgan
Cc: linux-arm-kernel, kvmarm, linux-kselftest, oliver.upton,
joey.gouly, suzuki.poulose, yuzenghui, shuah
On Mon, 14 Apr 2025 13:40:58 +0100,
Ben Horgan <ben.horgan@arm.com> wrote:
>
> If MTE_frac is masked out unconditionally then the guest will always
> see ID_AA64PFR1_EL1_MTE_frac as 0. However, a value of 0 when
> ID_AA64PFR1_EL1_MTE is 2 indicates that MTE_ASYNC is supported. Hence, for
> a host with ID_AA64PFR1_EL1_MTE==2 and ID_AA64PFR1_EL1_MTE_frac==0xf
> (MTE_ASYNC unsupported) the guest would see MTE_ASYNC advertised as
> supported whilst the host does not support it. Hence, expose the sanitised
> value of MTE_frac to the guest and user-space.
>
> As MTE_frac was previously hidden, always 0, and KVM must accept values
> from KVM provided by user-space, when ID_AA64PFR1_EL1.MTE is 2 allow
> user-space to set ID_AA64PFR1_EL1.MTE_frac to 0. However, ignore it to
> avoid incorrectly claiming hardware support for MTE_ASYNC in the guest.
>
> Note that linux does not check the value of ID_AA64PFR1_EL1_MTE_frac and
> wrongly assumes that MTE async faults can be generated even on hardware
> that does nto support them. This issue is not addressed here.
>
> Signed-off-by: Ben Horgan <ben.horgan@arm.com>
> ---
> arch/arm64/kvm/sys_regs.c | 26 ++++++++++++++++++++++++--
> 1 file changed, 24 insertions(+), 2 deletions(-)
>
> diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
> index 005ad28f7306..9ae647082684 100644
> --- a/arch/arm64/kvm/sys_regs.c
> +++ b/arch/arm64/kvm/sys_regs.c
> @@ -1600,13 +1600,14 @@ static u64 __kvm_read_sanitised_id_reg(const struct kvm_vcpu *vcpu,
> val = sanitise_id_aa64pfr0_el1(vcpu, val);
> break;
> case SYS_ID_AA64PFR1_EL1:
> - if (!kvm_has_mte(vcpu->kvm))
> + if (!kvm_has_mte(vcpu->kvm)) {
> val &= ~ARM64_FEATURE_MASK(ID_AA64PFR1_EL1_MTE);
> + val &= ~ARM64_FEATURE_MASK(ID_AA64PFR1_EL1_MTE_frac);
> + }
>
> val &= ~ARM64_FEATURE_MASK(ID_AA64PFR1_EL1_SME);
> val &= ~ARM64_FEATURE_MASK(ID_AA64PFR1_EL1_RNDR_trap);
> val &= ~ARM64_FEATURE_MASK(ID_AA64PFR1_EL1_NMI);
> - val &= ~ARM64_FEATURE_MASK(ID_AA64PFR1_EL1_MTE_frac);
> val &= ~ARM64_FEATURE_MASK(ID_AA64PFR1_EL1_GCS);
> val &= ~ARM64_FEATURE_MASK(ID_AA64PFR1_EL1_THE);
> val &= ~ARM64_FEATURE_MASK(ID_AA64PFR1_EL1_MTEX);
> @@ -1953,11 +1954,32 @@ static int set_id_aa64pfr1_el1(struct kvm_vcpu *vcpu,
> {
> u64 hw_val = read_sanitised_ftr_reg(SYS_ID_AA64PFR1_EL1);
> u64 mpam_mask = ID_AA64PFR1_EL1_MPAM_frac_MASK;
> + u8 mte = SYS_FIELD_GET(ID_AA64PFR1_EL1, MTE, hw_val);
> + u8 user_mte_frac = SYS_FIELD_GET(ID_AA64PFR1_EL1, MTE_frac, user_val);
>
> /* See set_id_aa64pfr0_el1 for comment about MPAM */
> if ((hw_val & mpam_mask) == (user_val & mpam_mask))
> user_val &= ~ID_AA64PFR1_EL1_MPAM_frac_MASK;
>
> + /*
> + * Previously MTE_frac was hidden from guest. However, if the
> + * hardware supports MTE2 but not MTE_ASYM_FAULT then a value
> + * of 0 for this field indicates that the hardware supports
> + * MTE_ASYNC. Whereas, 0xf indicates MTE_ASYNC is not supported.
> + *
> + * As KVM must accept values from KVM provided by user-space,
> + * when ID_AA64PFR1_EL1.MTE is 2 allow user-space to set
> + * ID_AA64PFR1_EL1.MTE_frac to 0. However, ignore it to avoid
> + * incorrectly claiming hardware support for MTE_ASYNC in the
> + * guest.
> + */
> +
> + if (mte == ID_AA64PFR1_EL1_MTE_MTE2 &&
The spec says that MTE_frac is valid if ID_AA64PFR1_EL1.MTE >= 0b0010.
Not strictly equal to 0b0010 (which represents MTE2). Crucially, MTE3
should receive the same treatment.
> + user_mte_frac == ID_AA64PFR1_EL1_MTE_frac_ASYNC) {
> + user_val &= ~ID_AA64PFR1_EL1_MTE_frac_MASK;
> + user_val |= hw_val & ID_AA64PFR1_EL1_MTE_frac_MASK;
This means you are unconditionally propagating what the HW supports,
which feels dodgy, specially considering that we don't know how
MTE_frac is going to evolve in the future.
I think you should limit the fix to the exact case we're mitigating
here, not blindly overwrite the guest's view with the HW's capability.
Thanks,
M.
--
Without deviation from the norm, progress is not possible.
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [RFC PATCH 2/3] KVM: arm64: Make MTE_frac masking conditional on MTE capability
2025-04-27 17:24 ` Marc Zyngier
@ 2025-04-28 11:26 ` Ben Horgan
0 siblings, 0 replies; 6+ messages in thread
From: Ben Horgan @ 2025-04-28 11:26 UTC (permalink / raw)
To: Marc Zyngier
Cc: linux-arm-kernel, kvmarm, linux-kselftest, oliver.upton,
joey.gouly, suzuki.poulose, yuzenghui, shuah
Hi Marc,
On 4/27/25 18:24, Marc Zyngier wrote:
> On Mon, 14 Apr 2025 13:40:58 +0100,
> Ben Horgan <ben.horgan@arm.com> wrote:
>> [...]
>> + /*
>> + * Previously MTE_frac was hidden from guest. However, if the
>> + * hardware supports MTE2 but not MTE_ASYM_FAULT then a value
>> + * of 0 for this field indicates that the hardware supports
>> + * MTE_ASYNC. Whereas, 0xf indicates MTE_ASYNC is not supported.
>> + *
>> + * As KVM must accept values from KVM provided by user-space,
>> + * when ID_AA64PFR1_EL1.MTE is 2 allow user-space to set
>> + * ID_AA64PFR1_EL1.MTE_frac to 0. However, ignore it to avoid
>> + * incorrectly claiming hardware support for MTE_ASYNC in the
>> + * guest.
>> + */
>> +
>> + if (mte == ID_AA64PFR1_EL1_MTE_MTE2 &&
>
> The spec says that MTE_frac is valid if ID_AA64PFR1_EL1.MTE >= 0b0010.
> Not strictly equal to 0b0010 (which represents MTE2). Crucially, MTE3
> should receive the same treatment.
This is specific to MTE2 as when MTE3 is supported MTE_ASYM_FAULT is
also supported and when MTE_ASYM_FAULT is supported the spec says
MTE_frac is 0.
>
>> + user_mte_frac == ID_AA64PFR1_EL1_MTE_frac_ASYNC) {
>> + user_val &= ~ID_AA64PFR1_EL1_MTE_frac_MASK;
>> + user_val |= hw_val & ID_AA64PFR1_EL1_MTE_frac_MASK;
>
> This means you are unconditionally propagating what the HW supports,
> which feels dodgy, specially considering that we don't know how
> MTE_frac is going to evolve in the future.
>
> I think you should limit the fix to the exact case we're mitigating
> here, not blindly overwrite the guest's view with the HW's capability.
Sure, better safe than sorry. I can update the if condition to the below.
u8 hw_mte_frac = SYS_FIELD_GET(ID_AA64PFR1_EL1, MTE_frac, hw_val);
...
if (mte == ID_AA64PFR1_EL1_MTE_MTE2 &&
hw_mte_frac == ID_AA64PFR1_EL1_MTE_frac_NI &&
user_mte_frac == ID_AA64PFR1_EL1_MTE_frac_ASYNC)
>
> Thanks,
>
> M.
>
Thanks,
Ben
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2025-04-28 11:57 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-04-14 12:40 [RFC PATCH 0/3] KVM: arm64: Don't claim MTE_ASYNC if not supported Ben Horgan
2025-04-14 12:40 ` [RFC PATCH 1/3] arm64/sysreg: Expose MTE_frac so that it is visible to KVM Ben Horgan
2025-04-14 12:40 ` [RFC PATCH 2/3] KVM: arm64: Make MTE_frac masking conditional on MTE capability Ben Horgan
2025-04-27 17:24 ` Marc Zyngier
2025-04-28 11:26 ` Ben Horgan
2025-04-14 12:40 ` [RFC PATCH 3/3] KVM: selftests: Confirm exposing MTE_frac does not break migration Ben Horgan
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).