| 1 | /* |
| 2 | * Code to help test the MTE gdbstubs in system mode. |
| 3 | * |
| 4 | * Copyright (c) 2024 Linaro Limited |
| 5 | * |
| 6 | * Author: Gustavo Romero <gustavo.romero@linaro.org> |
| 7 | * |
| 8 | * SPDX-License-Identifier: LGPL-2.1-or-later |
| 9 | */ |
| 10 | |
| 11 | #define addr x0 /* Ptr to the start of the MTE-enabled page. */ |
| 12 | #define tagged_addr x1 /* 'addr' ptr with a random-generated tag added. */ |
| 13 | #define tmp0 x2 /* Scratch register. */ |
| 14 | #define tmp1 x3 /* Scratch register. */ |
| 15 | #define tmp2 x4 /* Scratch register. */ |
| 16 | #define tmp3 x5 /* Sctatch register. */ |
| 17 | |
| 18 | .file "mte.S" |
| 19 | |
| 20 | .text |
| 21 | .align 4 |
| 22 | |
| 23 | .globl main |
| 24 | .type main, @function |
| 25 | |
| 26 | main: |
| 27 | /* |
| 28 | * Set MAIR_EL1 (Memory Attribute Index Register). In boot.S, the |
| 29 | * attribute index for .mte_page is set to point to MAILR_EL field Attr1 |
| 30 | * (AttrIndx=Attr1), so set Attr1 as Tagged Normal (MTE) to enable MTE |
| 31 | * on this page. |
| 32 | * |
| 33 | * Attr1 = 0xF0 => Tagged Normal (MTE) |
| 34 | */ |
| 35 | mrs tmp0, mair_el1 |
| 36 | orr tmp0, tmp0, (0xF0 << 8) |
| 37 | msr mair_el1, tmp0 |
| 38 | |
| 39 | /* |
| 40 | * Set TCR_EL1 (Translation Control Registers) to ignore the top byte |
| 41 | * in the translated addresses so it can be used to keep the tags. |
| 42 | * |
| 43 | * TBI0[37] = 0b1 => Top Byte ignored and used for tagged addresses |
| 44 | */ |
| 45 | mrs tmp1, tcr_el1 |
| 46 | orr tmp1, tmp1, (1 << 37) |
| 47 | msr tcr_el1, tmp1 |
| 48 | |
| 49 | /* |
| 50 | * Set SCTLR_EL1 (System Control Register) to enable the use of MTE |
| 51 | * insns., like stg & friends, and to enable synchronous exception in |
| 52 | * case of a tag mismatch, i.e., when the logical tag in 'tagged_addr' |
| 53 | * is different from the allocation tag related to 'addr' address. |
| 54 | * |
| 55 | * ATA[43] = 0b1 => Enable access to allocation tags at EL1 |
| 56 | * TCF[41:40] = 0b01 => Tag Check Faults cause a synchronous exception |
| 57 | * |
| 58 | */ |
| 59 | mrs tmp2, sctlr_el1 |
| 60 | mov tmp3, (1 << 43) | (1 << 40) |
| 61 | orr tmp2, tmp2, tmp3 |
| 62 | msr sctlr_el1, tmp2 |
| 63 | |
| 64 | isb |
| 65 | |
| 66 | /* |
| 67 | * MTE-enabled page resides at the 3rd 2MB chunk in the second 1GB |
| 68 | * block, i.e., at 0x40400000 address. See .mte_page section in boot.S |
| 69 | * and kernel.ld (where the address is effectively computed). |
| 70 | * |
| 71 | * Load .mte_page address into 'addr' register. |
| 72 | */ |
| 73 | adrp addr, mte_page |
| 74 | add addr, addr, :lo12:mte_page |
| 75 | |
| 76 | /* |
| 77 | * Set GCR for random tag generation. 0xA5 is just a random value to set |
| 78 | * GCR != 0 so the tag generated by 'irg' insn. is not zero, which is |
| 79 | * more interesting for the tests than when tag is zero. |
| 80 | */ |
| 81 | mov tmp0, 0xA5 |
| 82 | msr gcr_el1, tmp0 |
| 83 | |
| 84 | /* |
| 85 | * Generate a logical tag, add it to 'addr' address and put it into |
| 86 | * 'tagged_addr'. |
| 87 | */ |
| 88 | irg tagged_addr, addr |
| 89 | |
| 90 | /* |
| 91 | * Store the generated tag to memory region pointed to by 'addr', i.e. |
| 92 | * set the allocation tag for granule at 'addr'. The tag is extracted |
| 93 | * by stg from tagged_addr pointer. |
| 94 | */ |
| 95 | stg tagged_addr, [addr] |
| 96 | |
| 97 | /* |
| 98 | * Store a random value (0xdeadbeef) to tagged_addr address. This must |
| 99 | * not cause any Tag Check Fault since logical tag in tagged_addr and |
| 100 | * allocation tag associated with the memory pointed by tagged_addr are |
| 101 | * set the same, otherwise something is off and the test fails -- an |
| 102 | * exception is generated. |
| 103 | */ |
| 104 | ldr tmp1, =0xdeadbeef |
| 105 | str tmp1, [tagged_addr] |
| 106 | |
| 107 | /* This label is used by GDB Python script test-mte.py. */ |
| 108 | main_end: |
| 109 | ret |