diff mbox

[v5,00/22] target/arm: Implement ARMv8.5-MemTag, system mode

Message ID 20191011134744.2477-1-richard.henderson@linaro.org
State New
Headers show

Commit Message

Richard Henderson Oct. 11, 2019, 1:47 p.m. UTC
This is an update of the v4 patch from March.

I believe I've fixed the address space issues that Peter noticed.
If the board model does not supply tag memory, then I downgrade
the cpu support to "instructions only" (id_aa64pfr1.mte == 1),
which does not allow tag memory access to be enabled in the cpu.

I did not update the arm_hcr_el2_eff comment re ARMv8.4, because
I have not done a complete audit of all of the v8.5 bits.

The hacky kernel testing patch has needed some updates since March.
The following applies to v5.4-rc2.


r~


Richard Henderson (22):
  target/arm: Add MTE_ACTIVE to tb_flags
  target/arm: Add regime_has_2_ranges
  target/arm: Add MTE system registers
  target/arm: Add helper_mte_check{1,2,3}
  target/arm: Suppress tag check for sp+offset
  target/arm: Implement the IRG instruction
  target/arm: Implement ADDG, SUBG instructions
  target/arm: Implement the GMI instruction
  target/arm: Implement the SUBP instruction
  target/arm: Define arm_cpu_do_unaligned_access for CONFIG_USER_ONLY
  target/arm: Implement LDG, STG, ST2G instructions
  target/arm: Implement the STGP instruction
  target/arm: Implement the LDGM and STGM instructions
  target/arm: Implement the access tag cache flushes
  target/arm: Clean address for DC ZVA
  target/arm: Implement data cache set allocation tags
  target/arm: Set PSTATE.TCO on exception entry
  target/arm: Enable MTE
  target/arm: Cache the Tagged bit for a page in MemTxAttrs
  target/arm: Create tagged ram when MTE is enabled
  target/arm: Add mmu indexes for tag memory
  target/arm: Add allocation tag storage for system mode

 target/arm/cpu-param.h     |   2 +-
 target/arm/cpu.h           |  37 ++-
 target/arm/helper-a64.h    |  17 ++
 target/arm/internals.h     |  45 +++
 target/arm/translate.h     |   2 +
 hw/arm/virt.c              |  54 ++++
 target/arm/cpu.c           |  63 +++-
 target/arm/cpu64.c         |   1 +
 target/arm/helper.c        | 277 ++++++++++++++---
 target/arm/mte_helper.c    | 601 +++++++++++++++++++++++++++++++++++++
 target/arm/tlb_helper.c    |   3 +-
 target/arm/translate-a64.c | 342 ++++++++++++++++++---
 target/arm/Makefile.objs   |   1 +
 13 files changed, 1345 insertions(+), 100 deletions(-)
 create mode 100644 target/arm/mte_helper.c

--- kernel patch


--- mte smoke test

/*
 * Memory tagging, basic pass cases.
 */

#include <stdio.h>
#include <assert.h>
#include <sys/mman.h>

asm(".arch armv8.5-a+memtag");

int data[16 / sizeof(int)] __attribute__((aligned(16)));

int main(int ac, char **av)
{
    int *p0 = data;
    int *p1, *p2;
    long c;

    if (mlock(data, sizeof(data)) < 0) {
        perror("mlock");
        return 1;
    }

    asm("irg %0,%1,%2" : "=r"(p1) : "r"(p0), "r"(1));
    assert(p1 != p0);
    asm("subp %0,%1,%2" : "=r"(c) : "r"(p0), "r"(p1));
    assert(c == 0);

    asm("stg %0, [%0]" : : "r"(p1));
    asm("ldg %0, [%1]" : "=r"(p2) : "r"(p0), "0"(p0));
    assert(p1 == p2);

    return 0;
}

Comments

no-reply@patchew.org Oct. 11, 2019, 7:32 p.m. UTC | #1
Patchew URL: https://patchew.org/QEMU/20191011134744.2477-1-richard.henderson@linaro.org/



Hi,

This series seems to have some coding style problems. See output below for
more information:

Subject: [PATCH v5 00/22] target/arm: Implement ARMv8.5-MemTag, system mode
Type: series
Message-id: 20191011134744.2477-1-richard.henderson@linaro.org

=== TEST SCRIPT BEGIN ===
#!/bin/bash
git rev-parse base > /dev/null || exit 0
git config --local diff.renamelimit 0
git config --local diff.renames True
git config --local diff.algorithm histogram
./scripts/checkpatch.pl --mailback base..
=== TEST SCRIPT END ===

Switched to a new branch 'test'
2cb4ac6 target/arm: Add allocation tag storage for system mode
04c91b4 target/arm: Add mmu indexes for tag memory
1e0ff9d target/arm: Create tagged ram when MTE is enabled
b751fc4 target/arm: Cache the Tagged bit for a page in MemTxAttrs
9ac60fd target/arm: Enable MTE
513b429 target/arm: Set PSTATE.TCO on exception entry
b34fae3 target/arm: Implement data cache set allocation tags
e821379 target/arm: Clean address for DC ZVA
aff90e1 target/arm: Implement the access tag cache flushes
0caee2b target/arm: Implement the LDGM and STGM instructions
2b4a576 target/arm: Implement the STGP instruction
8dc4ae2 target/arm: Implement LDG, STG, ST2G instructions
2f4a984 target/arm: Define arm_cpu_do_unaligned_access for CONFIG_USER_ONLY
3af0a57 target/arm: Implement the SUBP instruction
b26b9b0 target/arm: Implement the GMI instruction
83744f3 target/arm: Implement ADDG, SUBG instructions
454811d target/arm: Implement the IRG instruction
3570a15 target/arm: Suppress tag check for sp+offset
1409fa4 target/arm: Add helper_mte_check{1,2,3}
bbbd12d target/arm: Add MTE system registers
bac1b74 target/arm: Add regime_has_2_ranges
498eda0 target/arm: Add MTE_ACTIVE to tb_flags

=== OUTPUT BEGIN ===
1/22 Checking commit 498eda06038b (target/arm: Add MTE_ACTIVE to tb_flags)
ERROR: spaces prohibited around that ':' (ctx:WxW)
#214: FILE: target/arm/internals.h:986:
+    bool tcma       : 1;
                     ^

total: 1 errors, 0 warnings, 213 lines checked

Patch 1/22 has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.

2/22 Checking commit bac1b74f8ee9 (target/arm: Add regime_has_2_ranges)
3/22 Checking commit bbbd12d06479 (target/arm: Add MTE system registers)
4/22 Checking commit 1409fa4954ca (target/arm: Add helper_mte_check{1,2,3})
WARNING: added, moved or deleted file(s), does MAINTAINERS need updating?
#39: 
new file mode 100644

total: 0 errors, 1 warnings, 199 lines checked

Patch 4/22 has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
5/22 Checking commit 3570a158fe8a (target/arm: Suppress tag check for sp+offset)
6/22 Checking commit 454811d5fbee (target/arm: Implement the IRG instruction)
7/22 Checking commit 83744f3effbf (target/arm: Implement ADDG, SUBG instructions)
8/22 Checking commit b26b9b0ff90d (target/arm: Implement the GMI instruction)
9/22 Checking commit 3af0a5757328 (target/arm: Implement the SUBP instruction)
10/22 Checking commit 2f4a98446331 (target/arm: Define arm_cpu_do_unaligned_access for CONFIG_USER_ONLY)
11/22 Checking commit 8dc4ae2e080d (target/arm: Implement LDG, STG, ST2G instructions)
12/22 Checking commit 2b4a576928a6 (target/arm: Implement the STGP instruction)
13/22 Checking commit 0caee2b19728 (target/arm: Implement the LDGM and STGM instructions)
14/22 Checking commit aff90e1ac887 (target/arm: Implement the access tag cache flushes)
15/22 Checking commit e82137999567 (target/arm: Clean address for DC ZVA)
16/22 Checking commit b34fae36a523 (target/arm: Implement data cache set allocation tags)
17/22 Checking commit 513b42914b4f (target/arm: Set PSTATE.TCO on exception entry)
18/22 Checking commit 9ac60fd7222d (target/arm: Enable MTE)
19/22 Checking commit b751fc4415fe (target/arm: Cache the Tagged bit for a page in MemTxAttrs)
20/22 Checking commit 1e0ff9daa24d (target/arm: Create tagged ram when MTE is enabled)
21/22 Checking commit 04c91b4cfe18 (target/arm: Add mmu indexes for tag memory)
22/22 Checking commit 2cb4ac638a77 (target/arm: Add allocation tag storage for system mode)
=== OUTPUT END ===

Test command exited with code: 1


The full log is available at
http://patchew.org/logs/20191011134744.2477-1-richard.henderson@linaro.org/testing.checkpatch/?type=message.
---
Email generated automatically by Patchew [https://patchew.org/].
Please send your feedback to patchew-devel@redhat.com
Evgenii Stepanov Oct. 15, 2019, 8:39 p.m. UTC | #2
Hi,

please find attached three random fixes for instruction translation
and one for syscall emulation.

On Fri, Oct 11, 2019 at 6:48 AM Richard Henderson
<richard.henderson@linaro.org> wrote:
>

> This is an update of the v4 patch from March.

>

> I believe I've fixed the address space issues that Peter noticed.

> If the board model does not supply tag memory, then I downgrade

> the cpu support to "instructions only" (id_aa64pfr1.mte == 1),

> which does not allow tag memory access to be enabled in the cpu.

>

> I did not update the arm_hcr_el2_eff comment re ARMv8.4, because

> I have not done a complete audit of all of the v8.5 bits.

>

> The hacky kernel testing patch has needed some updates since March.

> The following applies to v5.4-rc2.

>

>

> r~

>

>

> Richard Henderson (22):

>   target/arm: Add MTE_ACTIVE to tb_flags

>   target/arm: Add regime_has_2_ranges

>   target/arm: Add MTE system registers

>   target/arm: Add helper_mte_check{1,2,3}

>   target/arm: Suppress tag check for sp+offset

>   target/arm: Implement the IRG instruction

>   target/arm: Implement ADDG, SUBG instructions

>   target/arm: Implement the GMI instruction

>   target/arm: Implement the SUBP instruction

>   target/arm: Define arm_cpu_do_unaligned_access for CONFIG_USER_ONLY

>   target/arm: Implement LDG, STG, ST2G instructions

>   target/arm: Implement the STGP instruction

>   target/arm: Implement the LDGM and STGM instructions

>   target/arm: Implement the access tag cache flushes

>   target/arm: Clean address for DC ZVA

>   target/arm: Implement data cache set allocation tags

>   target/arm: Set PSTATE.TCO on exception entry

>   target/arm: Enable MTE

>   target/arm: Cache the Tagged bit for a page in MemTxAttrs

>   target/arm: Create tagged ram when MTE is enabled

>   target/arm: Add mmu indexes for tag memory

>   target/arm: Add allocation tag storage for system mode

>

>  target/arm/cpu-param.h     |   2 +-

>  target/arm/cpu.h           |  37 ++-

>  target/arm/helper-a64.h    |  17 ++

>  target/arm/internals.h     |  45 +++

>  target/arm/translate.h     |   2 +

>  hw/arm/virt.c              |  54 ++++

>  target/arm/cpu.c           |  63 +++-

>  target/arm/cpu64.c         |   1 +

>  target/arm/helper.c        | 277 ++++++++++++++---

>  target/arm/mte_helper.c    | 601 +++++++++++++++++++++++++++++++++++++

>  target/arm/tlb_helper.c    |   3 +-

>  target/arm/translate-a64.c | 342 ++++++++++++++++++---

>  target/arm/Makefile.objs   |   1 +

>  13 files changed, 1345 insertions(+), 100 deletions(-)

>  create mode 100644 target/arm/mte_helper.c

>

> --- kernel patch

>

> diff --git a/arch/arm64/include/asm/cpucaps.h b/arch/arm64/include/asm/cpucaps.h

> index f19fe4b9acc4..ee6b7f387a9a 100644

> --- a/arch/arm64/include/asm/cpucaps.h

> +++ b/arch/arm64/include/asm/cpucaps.h

> @@ -52,7 +52,8 @@

>  #define ARM64_HAS_IRQ_PRIO_MASKING             42

>  #define ARM64_HAS_DCPODP                       43

>  #define ARM64_WORKAROUND_1463225               44

> +#define ARM64_HAS_MTE                          45

>

> -#define ARM64_NCAPS                            45

> +#define ARM64_NCAPS                            46

>

>  #endif /* __ASM_CPUCAPS_H */

> diff --git a/arch/arm64/include/asm/kvm_arm.h b/arch/arm64/include/asm/kvm_arm.h

> index ddf9d762ac62..5825130bd8eb 100644

> --- a/arch/arm64/include/asm/kvm_arm.h

> +++ b/arch/arm64/include/asm/kvm_arm.h

> @@ -12,6 +12,7 @@

>  #include <asm/types.h>

>

>  /* Hyp Configuration Register (HCR) bits */

> +#define HCR_ATA                (UL(1) << 56)

>  #define HCR_FWB                (UL(1) << 46)

>  #define HCR_API                (UL(1) << 41)

>  #define HCR_APK                (UL(1) << 40)

> @@ -78,8 +79,8 @@

>                          HCR_AMO | HCR_SWIO | HCR_TIDCP | HCR_RW | HCR_TLOR | \

>                          HCR_FMO | HCR_IMO)

>  #define HCR_VIRT_EXCP_MASK (HCR_VSE | HCR_VI | HCR_VF)

> -#define HCR_HOST_NVHE_FLAGS (HCR_RW | HCR_API | HCR_APK)

> -#define HCR_HOST_VHE_FLAGS (HCR_RW | HCR_TGE | HCR_E2H)

> +#define HCR_HOST_NVHE_FLAGS (HCR_RW | HCR_API | HCR_APK | HCR_ATA)

> +#define HCR_HOST_VHE_FLAGS (HCR_RW | HCR_TGE | HCR_E2H | HCR_ATA)

>

>  /* TCR_EL2 Registers bits */

>  #define TCR_EL2_RES1           ((1 << 31) | (1 << 23))

> diff --git a/arch/arm64/include/asm/sysreg.h b/arch/arm64/include/asm/sysreg.h

> index 972d196c7714..2a65831f6e0f 100644

> --- a/arch/arm64/include/asm/sysreg.h

> +++ b/arch/arm64/include/asm/sysreg.h

> @@ -482,6 +482,7 @@

>

>  /* Common SCTLR_ELx flags. */

>  #define SCTLR_ELx_DSSBS        (BIT(44))

> +#define SCTLR_ELx_ATA  (BIT(43))

>  #define SCTLR_ELx_ENIA (BIT(31))

>  #define SCTLR_ELx_ENIB (BIT(30))

>  #define SCTLR_ELx_ENDA (BIT(27))

> @@ -510,6 +511,7 @@

>  #endif

>

>  /* SCTLR_EL1 specific flags. */

> +#define SCTLR_EL1_ATA0         (BIT(42))

>  #define SCTLR_EL1_UCI          (BIT(26))

>  #define SCTLR_EL1_E0E          (BIT(24))

>  #define SCTLR_EL1_SPAN         (BIT(23))

> @@ -598,6 +600,7 @@

>  #define ID_AA64PFR0_EL0_32BIT_64BIT    0x2

>

>  /* id_aa64pfr1 */

> +#define ID_AA64PFR1_MTE_SHIFT          8

>  #define ID_AA64PFR1_SSBS_SHIFT         4

>

>  #define ID_AA64PFR1_SSBS_PSTATE_NI     0

> diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c

> index cabebf1a7976..6a122ed7f76b 100644

> --- a/arch/arm64/kernel/cpufeature.c

> +++ b/arch/arm64/kernel/cpufeature.c

> @@ -171,6 +171,7 @@ static const struct arm64_ftr_bits ftr_id_aa64pfr0[] = {

>  };

>

>  static const struct arm64_ftr_bits ftr_id_aa64pfr1[] = {

> +       ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64PFR1_MTE_SHIFT, 4, 0),

>         ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64PFR1_SSBS_SHIFT, 4, ID_AA64PFR1_SSBS_PSTATE_NI),

>         ARM64_FTR_END,

>  };

> @@ -1261,6 +1262,11 @@ static bool can_use_gic_priorities(const struct arm64_cpu_capabilities *entry,

>  }

>  #endif

>

> +static void cpu_enable_mte(struct arm64_cpu_capabilities const *cap)

> +{

> +       sysreg_clear_set(sctlr_el1, 0, SCTLR_ELx_ATA | SCTLR_EL1_ATA0);

> +}

> +

>  static const struct arm64_cpu_capabilities arm64_features[] = {

>         {

>                 .desc = "GIC system register CPU interface",

> @@ -1561,6 +1567,17 @@ static const struct arm64_cpu_capabilities arm64_features[] = {

>                 .min_field_value = 1,

>         },

>  #endif

> +       {

> +               .desc = "Memory Tagging",

> +               .capability = ARM64_HAS_MTE,

> +               .type = ARM64_CPUCAP_SYSTEM_FEATURE,

> +               .matches = has_cpuid_feature,

> +               .sys_reg = SYS_ID_AA64PFR1_EL1,

> +               .field_pos = ID_AA64PFR1_MTE_SHIFT,

> +               .sign = FTR_UNSIGNED,

> +               .min_field_value = 2,

> +               .cpu_enable = cpu_enable_mte,

> +       },

>         {},

>  };

>

> diff --git a/arch/arm64/mm/proc.S b/arch/arm64/mm/proc.S

> index a1e0592d1fbc..32cfa35195ae 100644

> --- a/arch/arm64/mm/proc.S

> +++ b/arch/arm64/mm/proc.S

> @@ -424,14 +424,14 @@ ENTRY(__cpu_setup)

>          *   DEVICE_nGnRE       001     00000100

>          *   DEVICE_GRE         010     00001100

>          *   NORMAL_NC          011     01000100

> -        *   NORMAL             100     11111111

> +        *   NORMAL             100     11110000 (Tag)

>          *   NORMAL_WT          101     10111011

>          */

>         ldr     x5, =MAIR(0x00, MT_DEVICE_nGnRnE) | \

>                      MAIR(0x04, MT_DEVICE_nGnRE) | \

>                      MAIR(0x0c, MT_DEVICE_GRE) | \

>                      MAIR(0x44, MT_NORMAL_NC) | \

> -                    MAIR(0xff, MT_NORMAL) | \

> +                    MAIR(0xf0, MT_NORMAL) | \

>                      MAIR(0xbb, MT_NORMAL_WT)

>         msr     mair_el1, x5

>         /*

>

> --- mte smoke test

>

> /*

>  * Memory tagging, basic pass cases.

>  */

>

> #include <stdio.h>

> #include <assert.h>

> #include <sys/mman.h>

>

> asm(".arch armv8.5-a+memtag");

>

> int data[16 / sizeof(int)] __attribute__((aligned(16)));

>

> int main(int ac, char **av)

> {

>     int *p0 = data;

>     int *p1, *p2;

>     long c;

>

>     if (mlock(data, sizeof(data)) < 0) {

>         perror("mlock");

>         return 1;

>     }

>

>     asm("irg %0,%1,%2" : "=r"(p1) : "r"(p0), "r"(1));

>     assert(p1 != p0);

>     asm("subp %0,%1,%2" : "=r"(c) : "r"(p0), "r"(p1));

>     assert(c == 0);

>

>     asm("stg %0, [%0]" : : "r"(p1));

>     asm("ldg %0, [%1]" : "=r"(p2) : "r"(p0), "0"(p0));

>     assert(p1 == p2);

>

>     return 0;

> }

>

>
From 7dfe3f53bc606d2c5bb81e5828e6cf32225f6b72 Mon Sep 17 00:00:00 2001
From: Evgenii Stepanov <eugenis@google.com>
Date: Tue, 27 Aug 2019 16:14:37 -0700
Subject: [PATCH 4/4] Fix pre/post-index confusion in disas_ldst_tag.

---
 target/arm/translate-a64.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
index a85bae1f27..5728b68ccc 100644
--- a/target/arm/translate-a64.c
+++ b/target/arm/translate-a64.c
@@ -3679,7 +3679,7 @@ static void disas_ldst_tag(DisasContext *s, uint32_t insn)
     }
 
     dirty_addr = read_cpu_reg_sp(s, rn, true);
-    if (index <= 0) {
+    if (index >= 0) {
         /* pre-index or signed offset */
         tcg_gen_addi_i64(dirty_addr, dirty_addr, offset);
     }
@@ -3726,7 +3726,7 @@ static void disas_ldst_tag(DisasContext *s, uint32_t insn)
 
     if (index != 0) {
         /* pre-index or post-index */
-        if (index > 0) {
+        if (index < 0) {
             /* post-index */
             tcg_gen_addi_i64(dirty_addr, dirty_addr, offset);
         }
Richard Henderson Oct. 15, 2019, 10:04 p.m. UTC | #3
On 10/15/19 1:39 PM, Evgenii Stepanov wrote:
> Hi,

> 

> please find attached three random fixes for instruction translation

> and one for syscall emulation.


Thanks for the patches.

> @@ -2763,7 +2763,8 @@ static void disas_ldst_pair

>          return;

>      }

>  

> -    offset <<= size;

> +    // STGP offset is 16-scaled.

> +    offset <<= (size + set_tag);


Right.  I'll fix this with

    offset <<= (set_tag ? LOG2_TAG_GRANULE : size);

which I think is a bit clearer.

> @@ -3611,7 +3611,7 @@ static void disas_ldst_tag

>      int rt = extract32(insn, 0, 5);

>      int rn = extract32(insn, 5, 5);

>      uint64_t offset = sextract64(insn, 12, 9) << LOG2_TAG_GRANULE;

> -    int op2 = extract32(insn, 10, 3);

> +    int op2 = extract32(insn, 10, 2);


Yep.

> @@ -3679,7 +3679,7 @@ static void disas_ldst_tag(DisasContext *s, uint32_t insn)

>      }

>  

>      dirty_addr = read_cpu_reg_sp(s, rn, true);

> -    if (index <= 0) {

> +    if (index >= 0) {

>          /* pre-index or signed offset */

>          tcg_gen_addi_i64(dirty_addr, dirty_addr, offset);

>      }

> @@ -3726,7 +3726,7 @@ static void disas_ldst_tag(DisasContext *s, uint32_t insn)

>  

>      if (index != 0) {

>          /* pre-index or post-index */

> -        if (index > 0) {

> +        if (index < 0) {

>              /* post-index */

>              tcg_gen_addi_i64(dirty_addr, dirty_addr, offset);

>          }


Yep.

Ideally there'd be a kernel patch for MTE that works well enough to run RISU on
the fast model, and I'd be able to compare results.  I suppose in the meantime
more unit testing will have to do.

> +++ b/linux-user/qemu.h

> @@ -456,8 +456,16 @@ extern unsigned long guest_stack_size;

>  #define VERIFY_READ 0

>  #define VERIFY_WRITE 1 /* implies read access */

>  

> +static inline abi_ulong untagged_addr(abi_ulong addr) {

> +#if TARGET_ABI_BITS == 64

> +    addr &= (((abi_ulong)-1) >> 8);

> +#endif

> +    return addr;

> +}


At minimum this needs TARGET_AARCH64, because this kernel feature doesn't apply
to other targets.  But I'll see if I can do this such that it doesn't put
target-specific stuff in linux-user/qemu.h.


r~
diff mbox

Patch

diff --git a/arch/arm64/include/asm/cpucaps.h b/arch/arm64/include/asm/cpucaps.h
index f19fe4b9acc4..ee6b7f387a9a 100644
--- a/arch/arm64/include/asm/cpucaps.h
+++ b/arch/arm64/include/asm/cpucaps.h
@@ -52,7 +52,8 @@ 
 #define ARM64_HAS_IRQ_PRIO_MASKING		42
 #define ARM64_HAS_DCPODP			43
 #define ARM64_WORKAROUND_1463225		44
+#define ARM64_HAS_MTE				45
 
-#define ARM64_NCAPS				45
+#define ARM64_NCAPS				46
 
 #endif /* __ASM_CPUCAPS_H */
diff --git a/arch/arm64/include/asm/kvm_arm.h b/arch/arm64/include/asm/kvm_arm.h
index ddf9d762ac62..5825130bd8eb 100644
--- a/arch/arm64/include/asm/kvm_arm.h
+++ b/arch/arm64/include/asm/kvm_arm.h
@@ -12,6 +12,7 @@ 
 #include <asm/types.h>
 
 /* Hyp Configuration Register (HCR) bits */
+#define HCR_ATA		(UL(1) << 56)
 #define HCR_FWB		(UL(1) << 46)
 #define HCR_API		(UL(1) << 41)
 #define HCR_APK		(UL(1) << 40)
@@ -78,8 +79,8 @@ 
 			 HCR_AMO | HCR_SWIO | HCR_TIDCP | HCR_RW | HCR_TLOR | \
 			 HCR_FMO | HCR_IMO)
 #define HCR_VIRT_EXCP_MASK (HCR_VSE | HCR_VI | HCR_VF)
-#define HCR_HOST_NVHE_FLAGS (HCR_RW | HCR_API | HCR_APK)
-#define HCR_HOST_VHE_FLAGS (HCR_RW | HCR_TGE | HCR_E2H)
+#define HCR_HOST_NVHE_FLAGS (HCR_RW | HCR_API | HCR_APK | HCR_ATA)
+#define HCR_HOST_VHE_FLAGS (HCR_RW | HCR_TGE | HCR_E2H | HCR_ATA)
 
 /* TCR_EL2 Registers bits */
 #define TCR_EL2_RES1		((1 << 31) | (1 << 23))
diff --git a/arch/arm64/include/asm/sysreg.h b/arch/arm64/include/asm/sysreg.h
index 972d196c7714..2a65831f6e0f 100644
--- a/arch/arm64/include/asm/sysreg.h
+++ b/arch/arm64/include/asm/sysreg.h
@@ -482,6 +482,7 @@ 
 
 /* Common SCTLR_ELx flags. */
 #define SCTLR_ELx_DSSBS	(BIT(44))
+#define SCTLR_ELx_ATA	(BIT(43))
 #define SCTLR_ELx_ENIA	(BIT(31))
 #define SCTLR_ELx_ENIB	(BIT(30))
 #define SCTLR_ELx_ENDA	(BIT(27))
@@ -510,6 +511,7 @@ 
 #endif
 
 /* SCTLR_EL1 specific flags. */
+#define SCTLR_EL1_ATA0		(BIT(42))
 #define SCTLR_EL1_UCI		(BIT(26))
 #define SCTLR_EL1_E0E		(BIT(24))
 #define SCTLR_EL1_SPAN		(BIT(23))
@@ -598,6 +600,7 @@ 
 #define ID_AA64PFR0_EL0_32BIT_64BIT	0x2
 
 /* id_aa64pfr1 */
+#define ID_AA64PFR1_MTE_SHIFT		8
 #define ID_AA64PFR1_SSBS_SHIFT		4
 
 #define ID_AA64PFR1_SSBS_PSTATE_NI	0
diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
index cabebf1a7976..6a122ed7f76b 100644
--- a/arch/arm64/kernel/cpufeature.c
+++ b/arch/arm64/kernel/cpufeature.c
@@ -171,6 +171,7 @@  static const struct arm64_ftr_bits ftr_id_aa64pfr0[] = {
 };
 
 static const struct arm64_ftr_bits ftr_id_aa64pfr1[] = {
+	ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64PFR1_MTE_SHIFT, 4, 0),
 	ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64PFR1_SSBS_SHIFT, 4, ID_AA64PFR1_SSBS_PSTATE_NI),
 	ARM64_FTR_END,
 };
@@ -1261,6 +1262,11 @@  static bool can_use_gic_priorities(const struct arm64_cpu_capabilities *entry,
 }
 #endif
 
+static void cpu_enable_mte(struct arm64_cpu_capabilities const *cap)
+{
+	sysreg_clear_set(sctlr_el1, 0, SCTLR_ELx_ATA | SCTLR_EL1_ATA0);
+}
+
 static const struct arm64_cpu_capabilities arm64_features[] = {
 	{
 		.desc = "GIC system register CPU interface",
@@ -1561,6 +1567,17 @@  static const struct arm64_cpu_capabilities arm64_features[] = {
 		.min_field_value = 1,
 	},
 #endif
+	{
+		.desc = "Memory Tagging",
+		.capability = ARM64_HAS_MTE,
+		.type = ARM64_CPUCAP_SYSTEM_FEATURE,
+		.matches = has_cpuid_feature,
+		.sys_reg = SYS_ID_AA64PFR1_EL1,
+		.field_pos = ID_AA64PFR1_MTE_SHIFT,
+		.sign = FTR_UNSIGNED,
+		.min_field_value = 2,
+		.cpu_enable = cpu_enable_mte,
+	},
 	{},
 };
 
diff --git a/arch/arm64/mm/proc.S b/arch/arm64/mm/proc.S
index a1e0592d1fbc..32cfa35195ae 100644
--- a/arch/arm64/mm/proc.S
+++ b/arch/arm64/mm/proc.S
@@ -424,14 +424,14 @@  ENTRY(__cpu_setup)
 	 *   DEVICE_nGnRE	001	00000100
 	 *   DEVICE_GRE		010	00001100
 	 *   NORMAL_NC		011	01000100
-	 *   NORMAL		100	11111111
+	 *   NORMAL		100	11110000 (Tag)
 	 *   NORMAL_WT		101	10111011
 	 */
 	ldr	x5, =MAIR(0x00, MT_DEVICE_nGnRnE) | \
 		     MAIR(0x04, MT_DEVICE_nGnRE) | \
 		     MAIR(0x0c, MT_DEVICE_GRE) | \
 		     MAIR(0x44, MT_NORMAL_NC) | \
-		     MAIR(0xff, MT_NORMAL) | \
+		     MAIR(0xf0, MT_NORMAL) | \
 		     MAIR(0xbb, MT_NORMAL_WT)
 	msr	mair_el1, x5
 	/*