134bfeea4SCatalin Marinas/* SPDX-License-Identifier: GPL-2.0-only */ 234bfeea4SCatalin Marinas/* 334bfeea4SCatalin Marinas * Copyright (C) 2020 ARM Ltd. 434bfeea4SCatalin Marinas */ 534bfeea4SCatalin Marinas#include <linux/linkage.h> 634bfeea4SCatalin Marinas 7e2a2190aSMark Rutland#include <asm/asm-uaccess.h> 834bfeea4SCatalin Marinas#include <asm/assembler.h> 918ddbaa0SCatalin Marinas#include <asm/mte.h> 102563776bSVincenzo Frascino#include <asm/page.h> 1134bfeea4SCatalin Marinas#include <asm/sysreg.h> 1234bfeea4SCatalin Marinas 1334bfeea4SCatalin Marinas .arch armv8.5-a+memtag 1434bfeea4SCatalin Marinas 1534bfeea4SCatalin Marinas/* 1634bfeea4SCatalin Marinas * multitag_transfer_size - set \reg to the block size that is accessed by the 1734bfeea4SCatalin Marinas * LDGM/STGM instructions. 1834bfeea4SCatalin Marinas */ 1934bfeea4SCatalin Marinas .macro multitag_transfer_size, reg, tmp 2034bfeea4SCatalin Marinas mrs_s \reg, SYS_GMID_EL1 21*acb3f4bcSWill Deacon ubfx \reg, \reg, #GMID_EL1_BS_SHIFT, #GMID_EL1_BS_WIDTH 2234bfeea4SCatalin Marinas mov \tmp, #4 2334bfeea4SCatalin Marinas lsl \reg, \tmp, \reg 2434bfeea4SCatalin Marinas .endm 2534bfeea4SCatalin Marinas 2634bfeea4SCatalin Marinas/* 2734bfeea4SCatalin Marinas * Clear the tags in a page 2834bfeea4SCatalin Marinas * x0 - address of the page to be cleared 2934bfeea4SCatalin Marinas */ 3034bfeea4SCatalin MarinasSYM_FUNC_START(mte_clear_page_tags) 3134bfeea4SCatalin Marinas multitag_transfer_size x1, x2 3234bfeea4SCatalin Marinas1: stgm xzr, [x0] 3334bfeea4SCatalin Marinas add x0, x0, x1 3434bfeea4SCatalin Marinas tst x0, #(PAGE_SIZE - 1) 3534bfeea4SCatalin Marinas b.ne 1b 3634bfeea4SCatalin Marinas ret 3734bfeea4SCatalin MarinasSYM_FUNC_END(mte_clear_page_tags) 382563776bSVincenzo Frascino 392563776bSVincenzo Frascino/* 40013bb59dSPeter Collingbourne * Zero the page and tags at the same time 41013bb59dSPeter Collingbourne * 42013bb59dSPeter Collingbourne * Parameters: 43013bb59dSPeter Collingbourne * x0 - address to the beginning of the page 44013bb59dSPeter Collingbourne */ 45013bb59dSPeter CollingbourneSYM_FUNC_START(mte_zero_clear_page_tags) 46685e2564SReiji Watanabe and x0, x0, #(1 << MTE_TAG_SHIFT) - 1 // clear the tag 47013bb59dSPeter Collingbourne mrs x1, dczid_el0 48685e2564SReiji Watanabe tbnz x1, #4, 2f // Branch if DC GZVA is prohibited 49013bb59dSPeter Collingbourne and w1, w1, #0xf 50013bb59dSPeter Collingbourne mov x2, #4 51013bb59dSPeter Collingbourne lsl x1, x2, x1 52013bb59dSPeter Collingbourne 53013bb59dSPeter Collingbourne1: dc gzva, x0 54013bb59dSPeter Collingbourne add x0, x0, x1 55013bb59dSPeter Collingbourne tst x0, #(PAGE_SIZE - 1) 56013bb59dSPeter Collingbourne b.ne 1b 57013bb59dSPeter Collingbourne ret 58685e2564SReiji Watanabe 59685e2564SReiji Watanabe2: stz2g x0, [x0], #(MTE_GRANULE_SIZE * 2) 60685e2564SReiji Watanabe tst x0, #(PAGE_SIZE - 1) 61685e2564SReiji Watanabe b.ne 2b 62685e2564SReiji Watanabe ret 63013bb59dSPeter CollingbourneSYM_FUNC_END(mte_zero_clear_page_tags) 64013bb59dSPeter Collingbourne 65013bb59dSPeter Collingbourne/* 662563776bSVincenzo Frascino * Copy the tags from the source page to the destination one 672563776bSVincenzo Frascino * x0 - address of the destination page 682563776bSVincenzo Frascino * x1 - address of the source page 692563776bSVincenzo Frascino */ 702563776bSVincenzo FrascinoSYM_FUNC_START(mte_copy_page_tags) 712563776bSVincenzo Frascino mov x2, x0 722563776bSVincenzo Frascino mov x3, x1 732563776bSVincenzo Frascino multitag_transfer_size x5, x6 742563776bSVincenzo Frascino1: ldgm x4, [x3] 752563776bSVincenzo Frascino stgm x4, [x2] 762563776bSVincenzo Frascino add x2, x2, x5 772563776bSVincenzo Frascino add x3, x3, x5 782563776bSVincenzo Frascino tst x2, #(PAGE_SIZE - 1) 792563776bSVincenzo Frascino b.ne 1b 802563776bSVincenzo Frascino ret 812563776bSVincenzo FrascinoSYM_FUNC_END(mte_copy_page_tags) 8218ddbaa0SCatalin Marinas 8318ddbaa0SCatalin Marinas/* 8418ddbaa0SCatalin Marinas * Read tags from a user buffer (one tag per byte) and set the corresponding 8518ddbaa0SCatalin Marinas * tags at the given kernel address. Used by PTRACE_POKEMTETAGS. 8618ddbaa0SCatalin Marinas * x0 - kernel address (to) 8718ddbaa0SCatalin Marinas * x1 - user buffer (from) 8818ddbaa0SCatalin Marinas * x2 - number of tags/bytes (n) 8918ddbaa0SCatalin Marinas * Returns: 9018ddbaa0SCatalin Marinas * x0 - number of tags read/set 9118ddbaa0SCatalin Marinas */ 9218ddbaa0SCatalin MarinasSYM_FUNC_START(mte_copy_tags_from_user) 9318ddbaa0SCatalin Marinas mov x3, x1 9418ddbaa0SCatalin Marinas cbz x2, 2f 9518ddbaa0SCatalin Marinas1: 96b4d6bb38SRobin MurphyUSER(2f, ldtrb w4, [x1]) 9718ddbaa0SCatalin Marinas lsl x4, x4, #MTE_TAG_SHIFT 9818ddbaa0SCatalin Marinas stg x4, [x0], #MTE_GRANULE_SIZE 9918ddbaa0SCatalin Marinas add x1, x1, #1 10018ddbaa0SCatalin Marinas subs x2, x2, #1 10118ddbaa0SCatalin Marinas b.ne 1b 10218ddbaa0SCatalin Marinas 10318ddbaa0SCatalin Marinas // exception handling and function return 10418ddbaa0SCatalin Marinas2: sub x0, x1, x3 // update the number of tags set 10518ddbaa0SCatalin Marinas ret 10618ddbaa0SCatalin MarinasSYM_FUNC_END(mte_copy_tags_from_user) 10718ddbaa0SCatalin Marinas 10818ddbaa0SCatalin Marinas/* 10918ddbaa0SCatalin Marinas * Get the tags from a kernel address range and write the tag values to the 11018ddbaa0SCatalin Marinas * given user buffer (one tag per byte). Used by PTRACE_PEEKMTETAGS. 11118ddbaa0SCatalin Marinas * x0 - user buffer (to) 11218ddbaa0SCatalin Marinas * x1 - kernel address (from) 11318ddbaa0SCatalin Marinas * x2 - number of tags/bytes (n) 11418ddbaa0SCatalin Marinas * Returns: 11518ddbaa0SCatalin Marinas * x0 - number of tags read/set 11618ddbaa0SCatalin Marinas */ 11718ddbaa0SCatalin MarinasSYM_FUNC_START(mte_copy_tags_to_user) 11818ddbaa0SCatalin Marinas mov x3, x0 11918ddbaa0SCatalin Marinas cbz x2, 2f 12018ddbaa0SCatalin Marinas1: 12118ddbaa0SCatalin Marinas ldg x4, [x1] 12218ddbaa0SCatalin Marinas ubfx x4, x4, #MTE_TAG_SHIFT, #MTE_TAG_SIZE 123b4d6bb38SRobin MurphyUSER(2f, sttrb w4, [x0]) 12418ddbaa0SCatalin Marinas add x0, x0, #1 12518ddbaa0SCatalin Marinas add x1, x1, #MTE_GRANULE_SIZE 12618ddbaa0SCatalin Marinas subs x2, x2, #1 12718ddbaa0SCatalin Marinas b.ne 1b 12818ddbaa0SCatalin Marinas 12918ddbaa0SCatalin Marinas // exception handling and function return 13018ddbaa0SCatalin Marinas2: sub x0, x0, x3 // update the number of tags copied 13118ddbaa0SCatalin Marinas ret 13218ddbaa0SCatalin MarinasSYM_FUNC_END(mte_copy_tags_to_user) 13336943abaSSteven Price 13436943abaSSteven Price/* 13536943abaSSteven Price * Save the tags in a page 13636943abaSSteven Price * x0 - page address 137ab1e435cSCatalin Marinas * x1 - tag storage, MTE_PAGE_TAG_STORAGE bytes 13836943abaSSteven Price */ 13936943abaSSteven PriceSYM_FUNC_START(mte_save_page_tags) 14036943abaSSteven Price multitag_transfer_size x7, x5 14136943abaSSteven Price1: 14236943abaSSteven Price mov x2, #0 14336943abaSSteven Price2: 14436943abaSSteven Price ldgm x5, [x0] 14536943abaSSteven Price orr x2, x2, x5 14636943abaSSteven Price add x0, x0, x7 14736943abaSSteven Price tst x0, #0xFF // 16 tag values fit in a register, 14836943abaSSteven Price b.ne 2b // which is 16*16=256 bytes 14936943abaSSteven Price 15036943abaSSteven Price str x2, [x1], #8 15136943abaSSteven Price 15236943abaSSteven Price tst x0, #(PAGE_SIZE - 1) 15336943abaSSteven Price b.ne 1b 15436943abaSSteven Price 15536943abaSSteven Price ret 15636943abaSSteven PriceSYM_FUNC_END(mte_save_page_tags) 15736943abaSSteven Price 15836943abaSSteven Price/* 15936943abaSSteven Price * Restore the tags in a page 16036943abaSSteven Price * x0 - page address 161ab1e435cSCatalin Marinas * x1 - tag storage, MTE_PAGE_TAG_STORAGE bytes 16236943abaSSteven Price */ 16336943abaSSteven PriceSYM_FUNC_START(mte_restore_page_tags) 16436943abaSSteven Price multitag_transfer_size x7, x5 16536943abaSSteven Price1: 16636943abaSSteven Price ldr x2, [x1], #8 16736943abaSSteven Price2: 16836943abaSSteven Price stgm x2, [x0] 16936943abaSSteven Price add x0, x0, x7 17036943abaSSteven Price tst x0, #0xFF 17136943abaSSteven Price b.ne 2b 17236943abaSSteven Price 17336943abaSSteven Price tst x0, #(PAGE_SIZE - 1) 17436943abaSSteven Price b.ne 1b 17536943abaSSteven Price 17636943abaSSteven Price ret 17736943abaSSteven PriceSYM_FUNC_END(mte_restore_page_tags) 178