FEAT_MTE_TAGGED_FAR is a feature required for MTE4. The feature guarantees that the full address (including tag bits) is reported after a SEGV_MTESERR, and advertises itself in the ID_AA64PFR2_EL1 system register. QEMU was already reporting the full address, so this commit simply advertises the feature by setting that register, and unsets the register if MTE is disabled.
Signed-off-by: Gabriel Brookman <[email protected]> --- This patch is the first step toward implementing ARM's Enhanced Memory Tagging Extension (MTE4). MTE4 guarantees the presence of several subfeatures: FEAT_MTE_CANONICAL_TAGS, FEAT_MTE_TAGGED_FAR, FEAT_MTE_STORE_ONLY, FEAT_MTE_NO_ADDRESS_TAGS, and FEAT_MTE_PERM, none of which are currently implemented in QEMU. According to the ARM ARM, the presence of any of these features (except FEAT_MTE_PERM) implies the presence of all the others. For simplicity and ease of review, I plan to introduce them one at a time. This first patch focuses on FEAT_MTE_TAGGED_FAR. FEAT_MTE_TAGGED_FAR guarantees that the full fault address (including tag bits) is reported after a SEGV_MTESERR, and exposes itself in the ID_AA64PFR2_EL1 register. QEMU already reports the full address in this case, so this change only advertises the feature by setting the appropriate field in ID_AA64PFR2_EL1. The field is cleared when MTE support is disabled or rolled back to instruction-only. Testing: - Verified in system mode that the MTEFAR field in ID_AA64PFR2_EL1 is set to 1 when running with mte=on and cleared with mte=off. - Verified in user mode test that SEGV_MTESERR faults report the full tagged address as expected. I didn’t include these checks as formal tests since the functionality is simple, but I can add them in follow-up versions if reviewers prefer. Follow-up patches will implement the remaining MTE4 subfeatures listed above. Thanks, Gabriel Brookman --- target/arm/cpu.c | 4 +++- target/arm/tcg/cpu64.c | 4 ++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/target/arm/cpu.c b/target/arm/cpu.c index 39292fb9bc..804e70b235 100644 --- a/target/arm/cpu.c +++ b/target/arm/cpu.c @@ -2020,6 +2020,7 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp) */ if (tcg_enabled() && cpu->tag_memory == NULL) { FIELD_DP64_IDREG(isar, ID_AA64PFR1, MTE, 1); + FIELD_DP64_IDREG(isar, ID_AA64PFR2, MTEFAR, 0); } /* @@ -2027,7 +2028,8 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp) * enabled on the guest (i.e mte=off), clear guest's MTE bits." */ if (kvm_enabled() && !cpu->kvm_mte) { - FIELD_DP64_IDREG(isar, ID_AA64PFR1, MTE, 0); + FIELD_DP64_IDREG(isar, ID_AA64PFR1, MTE, 0); + FIELD_DP64_IDREG(isar, ID_AA64PFR2, MTEFAR, 0); } #endif } diff --git a/target/arm/tcg/cpu64.c b/target/arm/tcg/cpu64.c index 6871956382..27f0b43256 100644 --- a/target/arm/tcg/cpu64.c +++ b/target/arm/tcg/cpu64.c @@ -1283,6 +1283,10 @@ void aarch64_max_tcg_initfn(Object *obj) t = FIELD_DP64(t, ID_AA64PFR1, GCS, 1); /* FEAT_GCS */ SET_IDREG(isar, ID_AA64PFR1, t); + t = GET_IDREG(isar, ID_AA64PFR2); + t = FIELD_DP64(t, ID_AA64PFR2, MTEFAR, 1); /* FEAT_MTE_TAGGED_FAR */ + SET_IDREG(isar, ID_AA64PFR2, t); + t = GET_IDREG(isar, ID_AA64MMFR0); t = FIELD_DP64(t, ID_AA64MMFR0, PARANGE, 6); /* FEAT_LPA: 52 bits */ t = FIELD_DP64(t, ID_AA64MMFR0, TGRAN16, 1); /* 16k pages supported */ --- base-commit: e9c692eabbbb7f395347605a6ef33a32d398ea25 change-id: 20251104-feat-mte-tagged-far-c8d302a888ad Best regards, -- Gabriel Brookman <[email protected]>
