| /* |
| * Code to help test the MTE gdbstubs in system mode. |
| * |
| * Copyright (c) 2024 Linaro Limited |
| * |
| * Author: Gustavo Romero <gustavo.romero@linaro.org> |
| * |
| * SPDX-License-Identifier: LGPL-2.1-or-later |
| */ |
| |
| #define addr x0 /* Ptr to the start of the MTE-enabled page. */ |
| #define tagged_addr x1 /* 'addr' ptr with a random-generated tag added. */ |
| #define tmp0 x2 /* Scratch register. */ |
| #define tmp1 x3 /* Scratch register. */ |
| #define tmp2 x4 /* Scratch register. */ |
| #define tmp3 x5 /* Sctatch register. */ |
| |
| .file "mte.S" |
| |
| .text |
| .align 4 |
| |
| .globl main |
| .type main, @function |
| |
| main: |
| /* |
| * Set MAIR_EL1 (Memory Attribute Index Register). In boot.S, the |
| * attribute index for .mte_page is set to point to MAILR_EL field Attr1 |
| * (AttrIndx=Attr1), so set Attr1 as Tagged Normal (MTE) to enable MTE |
| * on this page. |
| * |
| * Attr1 = 0xF0 => Tagged Normal (MTE) |
| */ |
| mrs tmp0, mair_el1 |
| orr tmp0, tmp0, (0xF0 << 8) |
| msr mair_el1, tmp0 |
| |
| /* |
| * Set TCR_EL1 (Translation Control Registers) to ignore the top byte |
| * in the translated addresses so it can be used to keep the tags. |
| * |
| * TBI0[37] = 0b1 => Top Byte ignored and used for tagged addresses |
| */ |
| mrs tmp1, tcr_el1 |
| orr tmp1, tmp1, (1 << 37) |
| msr tcr_el1, tmp1 |
| |
| /* |
| * Set SCTLR_EL1 (System Control Register) to enable the use of MTE |
| * insns., like stg & friends, and to enable synchronous exception in |
| * case of a tag mismatch, i.e., when the logical tag in 'tagged_addr' |
| * is different from the allocation tag related to 'addr' address. |
| * |
| * ATA[43] = 0b1 => Enable access to allocation tags at EL1 |
| * TCF[41:40] = 0b01 => Tag Check Faults cause a synchronous exception |
| * |
| */ |
| mrs tmp2, sctlr_el1 |
| mov tmp3, (1 << 43) | (1 << 40) |
| orr tmp2, tmp2, tmp3 |
| msr sctlr_el1, tmp2 |
| |
| isb |
| |
| /* |
| * MTE-enabled page resides at the 3rd 2MB chunk in the second 1GB |
| * block, i.e., at 0x40400000 address. See .mte_page section in boot.S |
| * and kernel.ld (where the address is effectively computed). |
| * |
| * Load .mte_page address into 'addr' register. |
| */ |
| adrp addr, mte_page |
| add addr, addr, :lo12:mte_page |
| |
| /* |
| * Set GCR for random tag generation. 0xA5 is just a random value to set |
| * GCR != 0 so the tag generated by 'irg' insn. is not zero, which is |
| * more interesting for the tests than when tag is zero. |
| */ |
| mov tmp0, 0xA5 |
| msr gcr_el1, tmp0 |
| |
| /* |
| * Generate a logical tag, add it to 'addr' address and put it into |
| * 'tagged_addr'. |
| */ |
| irg tagged_addr, addr |
| |
| /* |
| * Store the generated tag to memory region pointed to by 'addr', i.e. |
| * set the allocation tag for granule at 'addr'. The tag is extracted |
| * by stg from tagged_addr pointer. |
| */ |
| stg tagged_addr, [addr] |
| |
| /* |
| * Store a random value (0xdeadbeef) to tagged_addr address. This must |
| * not cause any Tag Check Fault since logical tag in tagged_addr and |
| * allocation tag associated with the memory pointed by tagged_addr are |
| * set the same, otherwise something is off and the test fails -- an |
| * exception is generated. |
| */ |
| ldr tmp1, =0xdeadbeef |
| str tmp1, [tagged_addr] |
| |
| /* This label is used by GDB Python script test-mte.py. */ |
| main_end: |
| ret |