lsphinx.addnodesdocument)}( rawsourcechildren]( translations LanguagesNode)}(hhh](h pending_xref)}(hhh]docutils.nodesTextChinese (Simplified)}parenthsba attributes}(ids]classes]names]dupnames]backrefs] refdomainstdreftypedoc reftarget7/translations/zh_CN/arch/arm64/memory-tagging-extensionmodnameN classnameN refexplicitutagnamehhh ubh)}(hhh]hChinese (Traditional)}hh2sbah}(h]h ]h"]h$]h&] refdomainh)reftypeh+ reftarget7/translations/zh_TW/arch/arm64/memory-tagging-extensionmodnameN classnameN refexplicituh1hhh ubh)}(hhh]hItalian}hhFsbah}(h]h ]h"]h$]h&] refdomainh)reftypeh+ reftarget7/translations/it_IT/arch/arm64/memory-tagging-extensionmodnameN classnameN refexplicituh1hhh ubh)}(hhh]hJapanese}hhZsbah}(h]h ]h"]h$]h&] refdomainh)reftypeh+ reftarget7/translations/ja_JP/arch/arm64/memory-tagging-extensionmodnameN classnameN refexplicituh1hhh ubh)}(hhh]hKorean}hhnsbah}(h]h ]h"]h$]h&] refdomainh)reftypeh+ reftarget7/translations/ko_KR/arch/arm64/memory-tagging-extensionmodnameN classnameN refexplicituh1hhh ubh)}(hhh]hSpanish}hhsbah}(h]h ]h"]h$]h&] refdomainh)reftypeh+ reftarget7/translations/sp_SP/arch/arm64/memory-tagging-extensionmodnameN classnameN refexplicituh1hhh ubeh}(h]h ]h"]h$]h&]current_languageEnglishuh1h hh _documenthsourceNlineNubhsection)}(hhh](htitle)}(h/Memory Tagging Extension (MTE) in AArch64 Linuxh]h/Memory Tagging Extension (MTE) in AArch64 Linux}(hhhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhhhQ/var/lib/git/docbuild/linux/Documentation/arch/arm64/memory-tagging-extension.rsthKubhdefinition_list)}(hhh]hdefinition_list_item)}(haAuthors: Vincenzo Frascino Catalin Marinas h](hterm)}(h6Authors: Vincenzo Frascino h](hAuthors: Vincenzo Frascino <}(hhhhhNhNubh reference)}(hvincenzo.frascino@arm.comh]hvincenzo.frascino@arm.com}(hhhhhNhNubah}(h]h ]h"]h$]h&]refuri mailto:vincenzo.frascino@arm.comuh1hhhubh>}(hhhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKhhubh definition)}(hhh]h paragraph)}(h)Catalin Marinas h](hCatalin Marinas <}(hhhhhNhNubh)}(hcatalin.marinas@arm.comh]hcatalin.marinas@arm.com}(hhhhhNhNubah}(h]h ]h"]h$]h&]refurimailto:catalin.marinas@arm.comuh1hhhubh>}(hhhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKhhubah}(h]h ]h"]h$]h&]uh1hhhubeh}(h]h ]h"]h$]h&]uh1hhhhKhhubah}(h]h ]h"]h$]h&]uh1hhhhhhhhNubh)}(hDate: 2020-02-25h]hDate: 2020-02-25}(hj#hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhhhhubh)}(heThis document describes the provision of the Memory Tagging Extension functionality in AArch64 Linux.h]heThis document describes the provision of the Memory Tagging Extension functionality in AArch64 Linux.}(hj1hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK hhhhubh)}(hhh](h)}(h Introductionh]h Introduction}(hjBhhhNhNubah}(h]h ]h"]h$]h&]uh1hhj?hhhhhKubh)}(hXdARMv8.5 based processors introduce the Memory Tagging Extension (MTE) feature. MTE is built on top of the ARMv8.0 virtual address tagging TBI (Top Byte Ignore) feature and allows software to access a 4-bit allocation tag for each 16-byte granule in the physical address space. Such memory range must be mapped with the Normal-Tagged memory attribute. A logical tag is derived from bits 59-56 of the virtual address used for the memory access. A CPU with MTE enabled will compare the logical tag against the allocation tag and potentially raise an exception on mismatch, subject to system registers configuration.h]hXdARMv8.5 based processors introduce the Memory Tagging Extension (MTE) feature. MTE is built on top of the ARMv8.0 virtual address tagging TBI (Top Byte Ignore) feature and allows software to access a 4-bit allocation tag for each 16-byte granule in the physical address space. Such memory range must be mapped with the Normal-Tagged memory attribute. A logical tag is derived from bits 59-56 of the virtual address used for the memory access. A CPU with MTE enabled will compare the logical tag against the allocation tag and potentially raise an exception on mismatch, subject to system registers configuration.}(hjPhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhj?hhubeh}(h] introductionah ]h"] introductionah$]h&]uh1hhhhhhhhKubh)}(hhh](h)}(hUserspace Supporth]hUserspace Support}(hjihhhNhNubah}(h]h ]h"]h$]h&]uh1hhjfhhhhhKubh)}(hWhen ``CONFIG_ARM64_MTE`` is selected and Memory Tagging Extension is supported by the hardware, the kernel advertises the feature to userspace via ``HWCAP2_MTE``.h](hWhen }(hjwhhhNhNubhliteral)}(h``CONFIG_ARM64_MTE``h]hCONFIG_ARM64_MTE}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjwubh{ is selected and Memory Tagging Extension is supported by the hardware, the kernel advertises the feature to userspace via }(hjwhhhNhNubj)}(h``HWCAP2_MTE``h]h HWCAP2_MTE}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjwubh.}(hjwhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKhjfhhubh)}(hhh](h)}(hPROT_MTEh]hPROT_MTE}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhjhhhhhK"ubh)}(hTo access the allocation tags, a user process must enable the Tagged memory attribute on an address range using a new ``prot`` flag for ``mmap()`` and ``mprotect()``:h](hvTo access the allocation tags, a user process must enable the Tagged memory attribute on an address range using a new }(hjhhhNhNubj)}(h``prot``h]hprot}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubh flag for }(hjhhhNhNubj)}(h ``mmap()``h]hmmap()}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubh and }(hjhhhNhNubj)}(h``mprotect()``h]h mprotect()}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubh:}(hjhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhK$hjhhubh)}(h=``PROT_MTE`` - Pages allow access to the MTE allocation tags.h](j)}(h ``PROT_MTE``h]hPROT_MTE}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubh1 - Pages allow access to the MTE allocation tags.}(hjhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhK(hjhhubh)}(hThe allocation tag is set to 0 when such pages are first mapped in the user address space and preserved on copy-on-write. ``MAP_SHARED`` is supported and the allocation tags can be shared between processes.h](hzThe allocation tag is set to 0 when such pages are first mapped in the user address space and preserved on copy-on-write. }(hjhhhNhNubj)}(h``MAP_SHARED``h]h MAP_SHARED}(hj$hhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubhF is supported and the allocation tags can be shared between processes.}(hjhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhK*hjhhubh)}(h**Note**: ``PROT_MTE`` is only supported on ``MAP_ANONYMOUS`` and RAM-based file mappings (``tmpfs``, ``memfd``). Passing it to other types of mapping will result in ``-EINVAL`` returned by these system calls.h](hstrong)}(h**Note**h]hNote}(hjBhhhNhNubah}(h]h ]h"]h$]h&]uh1j@hj<ubh: }(hj<hhhNhNubj)}(h ``PROT_MTE``h]hPROT_MTE}(hjThhhNhNubah}(h]h ]h"]h$]h&]uh1jhj<ubh is only supported on }(hj<hhhNhNubj)}(h``MAP_ANONYMOUS``h]h MAP_ANONYMOUS}(hjfhhhNhNubah}(h]h ]h"]h$]h&]uh1jhj<ubh and RAM-based file mappings (}(hj<hhhNhNubj)}(h ``tmpfs``h]htmpfs}(hjxhhhNhNubah}(h]h ]h"]h$]h&]uh1jhj<ubh, }(hj<hhhNhNubj)}(h ``memfd``h]hmemfd}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhj<ubh7). Passing it to other types of mapping will result in }(hj<hhhNhNubj)}(h ``-EINVAL``h]h-EINVAL}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhj<ubh returned by these system calls.}(hj<hhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhK.hjhhubh)}(hd**Note**: The ``PROT_MTE`` flag (and corresponding memory type) cannot be cleared by ``mprotect()``.h](jA)}(h**Note**h]hNote}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1j@hjubh: The }(hjhhhNhNubj)}(h ``PROT_MTE``h]hPROT_MTE}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubh; flag (and corresponding memory type) cannot be cleared by }(hjhhhNhNubj)}(h``mprotect()``h]h mprotect()}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubh.}(hjhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhK3hjhhubh)}(h**Note**: ``madvise()`` memory ranges with ``MADV_DONTNEED`` and ``MADV_FREE`` may have the allocation tags cleared (set to 0) at any point after the system call.h](jA)}(h**Note**h]hNote}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1j@hjubh: }(hjhhhNhNubj)}(h ``madvise()``h]h madvise()}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubh memory ranges with }(hjhhhNhNubj)}(h``MADV_DONTNEED``h]h MADV_DONTNEED}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubh and }(hjhhhNhNubj)}(h ``MADV_FREE``h]h MADV_FREE}(hj.hhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubhT may have the allocation tags cleared (set to 0) at any point after the system call.}(hjhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhK6hjhhubeh}(h]prot-mteah ]h"]prot_mteah$]h&]uh1hhjfhhhhhK"ubh)}(hhh](h)}(hTag Check Faultsh]hTag Check Faults}(hjQhhhNhNubah}(h]h ]h"]h$]h&]uh1hhjNhhhhhK;ubh)}(hWhen ``PROT_MTE`` is enabled on an address range and a mismatch between the logical and allocation tags occurs on access, there are three configurable behaviours:h](hWhen }(hj_hhhNhNubj)}(h ``PROT_MTE``h]hPROT_MTE}(hjghhhNhNubah}(h]h ]h"]h$]h&]uh1jhj_ubh is enabled on an address range and a mismatch between the logical and allocation tags occurs on access, there are three configurable behaviours:}(hj_hhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhK=hjNhhubh bullet_list)}(hhh](h list_item)}(hW*Ignore* - This is the default mode. The CPU (and kernel) ignores the tag check fault. h]h)}(hV*Ignore* - This is the default mode. The CPU (and kernel) ignores the tag check fault.h](hemphasis)}(h*Ignore*h]hIgnore}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubhN - This is the default mode. The CPU (and kernel) ignores the tag check fault.}(hjhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKAhjubah}(h]h ]h"]h$]h&]uh1jhjhhhhhNubj)}(hX *Synchronous* - The kernel raises a ``SIGSEGV`` synchronously, with ``.si_code = SEGV_MTESERR`` and ``.si_addr = ``. The memory access is not performed. If ``SIGSEGV`` is ignored or blocked by the offending thread, the containing process is terminated with a ``coredump``. h]h)}(hX*Synchronous* - The kernel raises a ``SIGSEGV`` synchronously, with ``.si_code = SEGV_MTESERR`` and ``.si_addr = ``. The memory access is not performed. If ``SIGSEGV`` is ignored or blocked by the offending thread, the containing process is terminated with a ``coredump``.h](j)}(h *Synchronous*h]h Synchronous}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubh - The kernel raises a }(hjhhhNhNubj)}(h ``SIGSEGV``h]hSIGSEGV}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubh synchronously, with }(hjhhhNhNubj)}(h``.si_code = SEGV_MTESERR``h]h.si_code = SEGV_MTESERR}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubh and }(hjhhhNhNubj)}(h``.si_addr = ``h]h.si_addr = }(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubh). The memory access is not performed. If }(hjhhhNhNubj)}(h ``SIGSEGV``h]hSIGSEGV}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubh\ is ignored or blocked by the offending thread, the containing process is terminated with a }(hjhhhNhNubj)}(h ``coredump``h]hcoredump}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubh.}(hjhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKDhjubah}(h]h ]h"]h$]h&]uh1jhjhhhhhNubj)}(h*Asynchronous* - The kernel raises a ``SIGSEGV``, in the offending thread, asynchronously following one or multiple tag check faults, with ``.si_code = SEGV_MTEAERR`` and ``.si_addr = 0`` (the faulting address is unknown). h]h)}(h*Asynchronous* - The kernel raises a ``SIGSEGV``, in the offending thread, asynchronously following one or multiple tag check faults, with ``.si_code = SEGV_MTEAERR`` and ``.si_addr = 0`` (the faulting address is unknown).h](j)}(h*Asynchronous*h]h Asynchronous}(hj6hhhNhNubah}(h]h ]h"]h$]h&]uh1jhj2ubh - The kernel raises a }(hj2hhhNhNubj)}(h ``SIGSEGV``h]hSIGSEGV}(hjHhhhNhNubah}(h]h ]h"]h$]h&]uh1jhj2ubh[, in the offending thread, asynchronously following one or multiple tag check faults, with }(hj2hhhNhNubj)}(h``.si_code = SEGV_MTEAERR``h]h.si_code = SEGV_MTEAERR}(hjZhhhNhNubah}(h]h ]h"]h$]h&]uh1jhj2ubh and }(hj2hhhNhNubj)}(h``.si_addr = 0``h]h .si_addr = 0}(hjlhhhNhNubah}(h]h ]h"]h$]h&]uh1jhj2ubh# (the faulting address is unknown).}(hj2hhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKJhj.ubah}(h]h ]h"]h$]h&]uh1jhjhhhhhNubj)}(hl*Asymmetric* - Reads are handled as for synchronous mode while writes are handled as for asynchronous mode. h]h)}(hk*Asymmetric* - Reads are handled as for synchronous mode while writes are handled as for asynchronous mode.h](j)}(h *Asymmetric*h]h Asymmetric}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubh_ - Reads are handled as for synchronous mode while writes are handled as for asynchronous mode.}(hjhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKOhjubah}(h]h ]h"]h$]h&]uh1jhjhhhhhNubeh}(h]h ]h"]h$]h&]bullet-uh1jhhhKAhjNhhubh)}(hThe user can select the above modes, per thread, using the ``prctl(PR_SET_TAGGED_ADDR_CTRL, flags, 0, 0, 0)`` system call where ``flags`` contains any number of the following values in the ``PR_MTE_TCF_MASK`` bit-field:h](h;The user can select the above modes, per thread, using the }(hjhhhNhNubj)}(h2``prctl(PR_SET_TAGGED_ADDR_CTRL, flags, 0, 0, 0)``h]h.prctl(PR_SET_TAGGED_ADDR_CTRL, flags, 0, 0, 0)}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubh system call where }(hjhhhNhNubj)}(h ``flags``h]hflags}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubh4 contains any number of the following values in the }(hjhhhNhNubj)}(h``PR_MTE_TCF_MASK``h]hPR_MTE_TCF_MASK}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubh bit-field:}(hjhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKRhjNhhubj)}(hhh](j)}(hq``PR_MTE_TCF_NONE``  - *Ignore* tag check faults (ignored if combined with other options)h]h)}(hhh]h)}(hZ``PR_MTE_TCF_NONE``  - *Ignore* tag check faults (ignored if combined with other options)h](h)}(h1``PR_MTE_TCF_NONE``  - *Ignore* tag check faultsh](j)}(h``PR_MTE_TCF_NONE``h]hPR_MTE_TCF_NONE}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhj ubh  - }(hj hhhNhNubj)}(h*Ignore*h]hIgnore}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1jhj ubh tag check faults}(hj hhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKWhjubh)}(hhh]h)}(h((ignored if combined with other options)h]h((ignored if combined with other options)}(hj;hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKXhj8ubah}(h]h ]h"]h$]h&]uh1hhjubeh}(h]h ]h"]h$]h&]uh1hhhhKWhjubah}(h]h ]h"]h$]h&]uh1hhjubah}(h]h ]h"]h$]h&]uh1jhjhhhNhNubj)}(h9``PR_MTE_TCF_SYNC`` - *Synchronous* tag check fault modeh]h)}(hjch](j)}(h``PR_MTE_TCF_SYNC``h]hPR_MTE_TCF_SYNC}(hjhhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjeubh - }(hjehhhNhNubj)}(h *Synchronous*h]h Synchronous}(hjzhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjeubh tag check fault mode}(hjehhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKYhjaubah}(h]h ]h"]h$]h&]uh1jhjhhhhhNubj)}(h;``PR_MTE_TCF_ASYNC`` - *Asynchronous* tag check fault mode h]h)}(h:``PR_MTE_TCF_ASYNC`` - *Asynchronous* tag check fault modeh](j)}(h``PR_MTE_TCF_ASYNC``h]hPR_MTE_TCF_ASYNC}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubh - }(hjhhhNhNubj)}(h*Asynchronous*h]h Asynchronous}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubh tag check fault mode}(hjhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKZhjubah}(h]h ]h"]h$]h&]uh1jhjhhhhhNubeh}(h]h ]h"]h$]h&]jjuh1jhhhKWhjNhhubh)}(hIf no modes are specified, tag check faults are ignored. If a single mode is specified, the program will run in that mode. If multiple modes are specified, the mode is selected as described in the "Per-CPU preferred tag checking modes" section below.h]hIf no modes are specified, tag check faults are ignored. If a single mode is specified, the program will run in that mode. If multiple modes are specified, the mode is selected as described in the “Per-CPU preferred tag checking modes” section below.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK\hjNhhubh)}(hThe current tag check fault configuration can be read using the ``prctl(PR_GET_TAGGED_ADDR_CTRL, 0, 0, 0, 0)`` system call. If multiple modes were requested then all will be reported.h](h@The current tag check fault configuration can be read using the }(hjhhhNhNubj)}(h.``prctl(PR_GET_TAGGED_ADDR_CTRL, 0, 0, 0, 0)``h]h*prctl(PR_GET_TAGGED_ADDR_CTRL, 0, 0, 0, 0)}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubhI system call. If multiple modes were requested then all will be reported.}(hjhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKahjNhhubh)}(hkTag checking can also be disabled for a user thread by setting the ``PSTATE.TCO`` bit with ``MSR TCO, #1``.h](hCTag checking can also be disabled for a user thread by setting the }(hjhhhNhNubj)}(h``PSTATE.TCO``h]h PSTATE.TCO}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubh bit with }(hjhhhNhNubj)}(h``MSR TCO, #1``h]h MSR TCO, #1}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubh.}(hjhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKehjNhhubh)}(h**Note**: Signal handlers are always invoked with ``PSTATE.TCO = 0``, irrespective of the interrupted context. ``PSTATE.TCO`` is restored on ``sigreturn()``.h](jA)}(h**Note**h]hNote}(hj:hhhNhNubah}(h]h ]h"]h$]h&]uh1j@hj6ubh*: Signal handlers are always invoked with }(hj6hhhNhNubj)}(h``PSTATE.TCO = 0``h]hPSTATE.TCO = 0}(hjLhhhNhNubah}(h]h ]h"]h$]h&]uh1jhj6ubh+, irrespective of the interrupted context. }(hj6hhhNhNubj)}(h``PSTATE.TCO``h]h PSTATE.TCO}(hj^hhhNhNubah}(h]h ]h"]h$]h&]uh1jhj6ubh is restored on }(hj6hhhNhNubj)}(h``sigreturn()``h]h sigreturn()}(hjphhhNhNubah}(h]h ]h"]h$]h&]uh1jhj6ubh.}(hj6hhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKhhjNhhubh)}(hP**Note**: There are no *match-all* logical tags available for user applications.h](jA)}(h**Note**h]hNote}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1j@hjubh: There are no }(hjhhhNhNubj)}(h *match-all*h]h match-all}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubh. logical tags available for user applications.}(hjhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKlhjNhhubh)}(hX**Note**: Kernel accesses to the user address space (e.g. ``read()`` system call) are not checked if the user thread tag checking mode is ``PR_MTE_TCF_NONE`` or ``PR_MTE_TCF_ASYNC``. If the tag checking mode is ``PR_MTE_TCF_SYNC``, the kernel makes a best effort to check its user address accesses, however it cannot always guarantee it. Kernel accesses to user addresses are always performed with an effective ``PSTATE.TCO`` value of zero, regardless of the user configuration.h](jA)}(h**Note**h]hNote}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1j@hjubh2: Kernel accesses to the user address space (e.g. }(hjhhhNhNubj)}(h ``read()``h]hread()}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubhF system call) are not checked if the user thread tag checking mode is }(hjhhhNhNubj)}(h``PR_MTE_TCF_NONE``h]hPR_MTE_TCF_NONE}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubh or }(hjhhhNhNubj)}(h``PR_MTE_TCF_ASYNC``h]hPR_MTE_TCF_ASYNC}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubh. If the tag checking mode is }(hjhhhNhNubj)}(h``PR_MTE_TCF_SYNC``h]hPR_MTE_TCF_SYNC}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubh, the kernel makes a best effort to check its user address accesses, however it cannot always guarantee it. Kernel accesses to user addresses are always performed with an effective }(hjhhhNhNubj)}(h``PSTATE.TCO``h]h PSTATE.TCO}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubh5 value of zero, regardless of the user configuration.}(hjhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKohjNhhubeh}(h]tag-check-faultsah ]h"]tag check faultsah$]h&]uh1hhjfhhhhhK;ubh)}(hhh](h)}(hAExcluding Tags in the ``IRG``, ``ADDG`` and ``SUBG`` instructionsh](hExcluding Tags in the }(hj7hhhNhNubj)}(h``IRG``h]hIRG}(hj?hhhNhNubah}(h]h ]h"]h$]h&]uh1jhj7ubh, }(hj7hhhNhNubj)}(h``ADDG``h]hADDG}(hjQhhhNhNubah}(h]h ]h"]h$]h&]uh1jhj7ubh and }(hj7hhhNhNubj)}(h``SUBG``h]hSUBG}(hjchhhNhNubah}(h]h ]h"]h$]h&]uh1jhj7ubh instructions}(hj7hhhNhNubeh}(h]h ]h"]h$]h&]uh1hhj4hhhhhKxubh)}(hXThe architecture allows excluding certain tags to be randomly generated via the ``GCR_EL1.Exclude`` register bit-field. By default, Linux excludes all tags other than 0. A user thread can enable specific tags in the randomly generated set using the ``prctl(PR_SET_TAGGED_ADDR_CTRL, flags, 0, 0, 0)`` system call where ``flags`` contains the tags bitmap in the ``PR_MTE_TAG_MASK`` bit-field.h](hPThe architecture allows excluding certain tags to be randomly generated via the }(hj{hhhNhNubj)}(h``GCR_EL1.Exclude``h]hGCR_EL1.Exclude}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhj{ubh register bit-field. By default, Linux excludes all tags other than 0. A user thread can enable specific tags in the randomly generated set using the }(hj{hhhNhNubj)}(h2``prctl(PR_SET_TAGGED_ADDR_CTRL, flags, 0, 0, 0)``h]h.prctl(PR_SET_TAGGED_ADDR_CTRL, flags, 0, 0, 0)}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhj{ubh system call where }(hj{hhhNhNubj)}(h ``flags``h]hflags}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhj{ubh! contains the tags bitmap in the }(hj{hhhNhNubj)}(h``PR_MTE_TAG_MASK``h]hPR_MTE_TAG_MASK}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhj{ubh bit-field.}(hj{hhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKzhj4hhubh)}(h**Note**: The hardware uses an exclude mask but the ``prctl()`` interface provides an include mask. An include mask of ``0`` (exclusion mask ``0xffff``) results in the CPU always generating tag ``0``.h](jA)}(h**Note**h]hNote}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1j@hjubh,: The hardware uses an exclude mask but the }(hjhhhNhNubj)}(h ``prctl()``h]hprctl()}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubh8 interface provides an include mask. An include mask of }(hjhhhNhNubj)}(h``0``h]h0}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubh (exclusion mask }(hjhhhNhNubj)}(h ``0xffff``h]h0xffff}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubh+) results in the CPU always generating tag }(hjhhhNhNubj)}(h``0``h]h0}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubh.}(hjhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKhj4hhubeh}(h]4excluding-tags-in-the-irg-addg-and-subg-instructionsah ]h"]5excluding tags in the irg, addg and subg instructionsah$]h&]uh1hhjfhhhhhKxubh)}(hhh](h)}(h#Per-CPU preferred tag checking modeh]h#Per-CPU preferred tag checking mode}(hj@hhhNhNubah}(h]h ]h"]h$]h&]uh1hhj=hhhhhKubh)}(hXOn some CPUs the performance of MTE in stricter tag checking modes is similar to that of less strict tag checking modes. This makes it worthwhile to enable stricter checks on those CPUs when a less strict checking mode is requested, in order to gain the error detection benefits of the stricter checks without the performance downsides. To support this scenario, a privileged user may configure a stricter tag checking mode as the CPU's preferred tag checking mode.h]hXOn some CPUs the performance of MTE in stricter tag checking modes is similar to that of less strict tag checking modes. This makes it worthwhile to enable stricter checks on those CPUs when a less strict checking mode is requested, in order to gain the error detection benefits of the stricter checks without the performance downsides. To support this scenario, a privileged user may configure a stricter tag checking mode as the CPU’s preferred tag checking mode.}(hjNhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhj=hhubh)}(hThe preferred tag checking mode for each CPU is controlled by ``/sys/devices/system/cpu/cpu/mte_tcf_preferred``, to which a privileged user may write the value ``async``, ``sync`` or ``asymm``. The default preferred mode for each CPU is ``async``.h](h>The preferred tag checking mode for each CPU is controlled by }(hj\hhhNhNubj)}(h4``/sys/devices/system/cpu/cpu/mte_tcf_preferred``h]h0/sys/devices/system/cpu/cpu/mte_tcf_preferred}(hjdhhhNhNubah}(h]h ]h"]h$]h&]uh1jhj\ubh1, to which a privileged user may write the value }(hj\hhhNhNubj)}(h ``async``h]hasync}(hjvhhhNhNubah}(h]h ]h"]h$]h&]uh1jhj\ubh, }(hj\hhhNhNubj)}(h``sync``h]hsync}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhj\ubh or }(hj\hhhNhNubj)}(h ``asymm``h]hasymm}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhj\ubh.. The default preferred mode for each CPU is }(hj\hhhNhNubj)}(h ``async``h]hasync}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhj\ubh.}(hj\hhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKhj=hhubh)}(hX[To allow a program to potentially run in the CPU's preferred tag checking mode, the user program may set multiple tag check fault mode bits in the ``flags`` argument to the ``prctl(PR_SET_TAGGED_ADDR_CTRL, flags, 0, 0, 0)`` system call. If both synchronous and asynchronous modes are requested then asymmetric mode may also be selected by the kernel. If the CPU's preferred tag checking mode is in the task's set of provided tag checking modes, that mode will be selected. Otherwise, one of the modes in the task's mode will be selected by the kernel from the task's mode set using the preference order:h](hTo allow a program to potentially run in the CPU’s preferred tag checking mode, the user program may set multiple tag check fault mode bits in the }(hjhhhNhNubj)}(h ``flags``h]hflags}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubh argument to the }(hjhhhNhNubj)}(h2``prctl(PR_SET_TAGGED_ADDR_CTRL, flags, 0, 0, 0)``h]h.prctl(PR_SET_TAGGED_ADDR_CTRL, flags, 0, 0, 0)}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubhX system call. If both synchronous and asynchronous modes are requested then asymmetric mode may also be selected by the kernel. If the CPU’s preferred tag checking mode is in the task’s set of provided tag checking modes, that mode will be selected. Otherwise, one of the modes in the task’s mode will be selected by the kernel from the task’s mode set using the preference order:}(hjhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKhj=hhubh block_quote)}(h-1. Asynchronous 2. Asymmetric 3. Synchronous h]henumerated_list)}(hhh](j)}(h Asynchronoush]h)}(hj h]h Asynchronous}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhj ubah}(h]h ]h"]h$]h&]uh1jhjubj)}(h Asymmetrich]h)}(hj h]h Asymmetric}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhj ubah}(h]h ]h"]h$]h&]uh1jhjubj)}(h Synchronous h]h)}(h Synchronoush]h Synchronous}(hj3 hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhj/ ubah}(h]h ]h"]h$]h&]uh1jhjubeh}(h]h ]h"]h$]h&]enumtypearabicprefixhsuffix.uh1jhjubah}(h]h ]h"]h$]h&]uh1jhhhKhj=hhubh)}(hcNote that there is no way for userspace to request multiple modes and also disable asymmetric mode.h]hcNote that there is no way for userspace to request multiple modes and also disable asymmetric mode.}(hjX hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhj=hhubeh}(h]#per-cpu-preferred-tag-checking-modeah ]h"]#per-cpu preferred tag checking modeah$]h&]uh1hhjfhhhhhKubh)}(hhh](h)}(hInitial process stateh]hInitial process state}(hjq hhhNhNubah}(h]h ]h"]h$]h&]uh1hhjn hhhhhKubh)}(hAOn ``execve()``, the new process has the following configuration:h](hOn }(hj hhhNhNubj)}(h ``execve()``h]hexecve()}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1jhj ubh2, the new process has the following configuration:}(hj hhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKhjn hhubj)}(hhh](j)}(h-``PR_TAGGED_ADDR_ENABLE`` set to 0 (disabled)h]h)}(hj h](j)}(h``PR_TAGGED_ADDR_ENABLE``h]hPR_TAGGED_ADDR_ENABLE}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1jhj ubh set to 0 (disabled)}(hj hhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKhj ubah}(h]h ]h"]h$]h&]uh1jhj hhhhhNubj)}(h=No tag checking modes are selected (tag check faults ignored)h]h)}(hj h]h=No tag checking modes are selected (tag check faults ignored)}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhj ubah}(h]h ]h"]h$]h&]uh1jhj hhhhhNubj)}(h0``PR_MTE_TAG_MASK`` set to 0 (all tags excluded)h]h)}(hj h](j)}(h``PR_MTE_TAG_MASK``h]hPR_MTE_TAG_MASK}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1jhj ubh set to 0 (all tags excluded)}(hj hhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKhj ubah}(h]h ]h"]h$]h&]uh1jhj hhhhhNubj)}(h``PSTATE.TCO`` set to 0h]h)}(hj h](j)}(h``PSTATE.TCO``h]h PSTATE.TCO}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1jhj ubh set to 0}(hj hhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKhj ubah}(h]h ]h"]h$]h&]uh1jhj hhhhhNubj)}(h7``PROT_MTE`` not set on any of the initial memory maps h]h)}(h6``PROT_MTE`` not set on any of the initial memory mapsh](j)}(h ``PROT_MTE``h]hPROT_MTE}(hj0 hhhNhNubah}(h]h ]h"]h$]h&]uh1jhj, ubh* not set on any of the initial memory maps}(hj, hhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKhj( ubah}(h]h ]h"]h$]h&]uh1jhj hhhhhNubeh}(h]h ]h"]h$]h&]jjuh1jhhhKhjn hhubh)}(hOn ``fork()``, the new process inherits the parent's configuration and memory map attributes with the exception of the ``madvise()`` ranges with ``MADV_WIPEONFORK`` which will have the data and tags cleared (set to 0).h](hOn }(hjT hhhNhNubj)}(h ``fork()``h]hfork()}(hj\ hhhNhNubah}(h]h ]h"]h$]h&]uh1jhjT ubhl, the new process inherits the parent’s configuration and memory map attributes with the exception of the }(hjT hhhNhNubj)}(h ``madvise()``h]h madvise()}(hjn hhhNhNubah}(h]h ]h"]h$]h&]uh1jhjT ubh ranges with }(hjT hhhNhNubj)}(h``MADV_WIPEONFORK``h]hMADV_WIPEONFORK}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1jhjT ubh6 which will have the data and tags cleared (set to 0).}(hjT hhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKhjn hhubeh}(h]initial-process-stateah ]h"]initial process stateah$]h&]uh1hhjfhhhhhKubh)}(hhh](h)}(hThe ``ptrace()`` interfaceh](hThe }(hj hhhNhNubj)}(h ``ptrace()``h]hptrace()}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1jhj ubh interface}(hj hhhNhNubeh}(h]h ]h"]h$]h&]uh1hhj hhhhhKubh)}(h``PTRACE_PEEKMTETAGS`` and ``PTRACE_POKEMTETAGS`` allow a tracer to read the tags from or set the tags to a tracee's address space. The ``ptrace()`` system call is invoked as ``ptrace(request, pid, addr, data)`` where:h](j)}(h``PTRACE_PEEKMTETAGS``h]hPTRACE_PEEKMTETAGS}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1jhj ubh and }(hj hhhNhNubj)}(h``PTRACE_POKEMTETAGS``h]hPTRACE_POKEMTETAGS}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1jhj ubhY allow a tracer to read the tags from or set the tags to a tracee’s address space. The }(hj hhhNhNubj)}(h ``ptrace()``h]hptrace()}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1jhj ubh system call is invoked as }(hj hhhNhNubj)}(h$``ptrace(request, pid, addr, data)``h]h ptrace(request, pid, addr, data)}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1jhj ubh where:}(hj hhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKhj hhubj)}(hhh](j)}(hF``request`` - one of ``PTRACE_PEEKMTETAGS`` or ``PTRACE_POKEMTETAGS``.h]h)}(hj h](j)}(h ``request``h]hrequest}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1jhj ubh - one of }(hj hhhNhNubj)}(h``PTRACE_PEEKMTETAGS``h]hPTRACE_PEEKMTETAGS}(hj1 hhhNhNubah}(h]h ]h"]h$]h&]uh1jhj ubh or }(hj hhhNhNubj)}(h``PTRACE_POKEMTETAGS``h]hPTRACE_POKEMTETAGS}(hjC hhhNhNubah}(h]h ]h"]h$]h&]uh1jhj ubh.}(hj hhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKhj ubah}(h]h ]h"]h$]h&]uh1jhj hhhhhNubj)}(h``pid`` - the tracee's PID.h]h)}(hjc h](j)}(h``pid``h]hpid}(hjh hhhNhNubah}(h]h ]h"]h$]h&]uh1jhje ubh - the tracee’s PID.}(hje hhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKhja ubah}(h]h ]h"]h$]h&]uh1jhj hhhhhNubj)}(h1``addr`` - address in the tracee's address space.h]h)}(hj h](j)}(h``addr``h]haddr}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1jhj ubh+ - address in the tracee’s address space.}(hj hhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKhj ubah}(h]h ]h"]h$]h&]uh1jhj hhhhhNubj)}(h``data`` - pointer to a ``struct iovec`` where ``iov_base`` points to a buffer of ``iov_len`` length in the tracer's address space. h]h)}(h``data`` - pointer to a ``struct iovec`` where ``iov_base`` points to a buffer of ``iov_len`` length in the tracer's address space.h](j)}(h``data``h]hdata}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1jhj ubh - pointer to a }(hj hhhNhNubj)}(h``struct iovec``h]h struct iovec}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1jhj ubh where }(hj hhhNhNubj)}(h ``iov_base``h]hiov_base}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1jhj ubh points to a buffer of }(hj hhhNhNubj)}(h ``iov_len``h]hiov_len}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1jhj ubh( length in the tracer’s address space.}(hj hhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKhj ubah}(h]h ]h"]h$]h&]uh1jhj hhhhhNubeh}(h]h ]h"]h$]h&]jjuh1jhhhKhj hhubh)}(hThe tags in the tracer's ``iov_base`` buffer are represented as one 4-bit tag per byte and correspond to a 16-byte MTE tag granule in the tracee's address space.h](hThe tags in the tracer’s }(hj hhhNhNubj)}(h ``iov_base``h]hiov_base}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1jhj ubh~ buffer are represented as one 4-bit tag per byte and correspond to a 16-byte MTE tag granule in the tracee’s address space.}(hj hhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKhj hhubh)}(hq**Note**: If ``addr`` is not aligned to a 16-byte granule, the kernel will use the corresponding aligned address.h](jA)}(h**Note**h]hNote}(hj1 hhhNhNubah}(h]h ]h"]h$]h&]uh1j@hj- ubh: If }(hj- hhhNhNubj)}(h``addr``h]haddr}(hjC hhhNhNubah}(h]h ]h"]h$]h&]uh1jhj- ubh\ is not aligned to a 16-byte granule, the kernel will use the corresponding aligned address.}(hj- hhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKhj hhubh)}(h``ptrace()`` return value:h](j)}(h ``ptrace()``h]hptrace()}(hj_ hhhNhNubah}(h]h ]h"]h$]h&]uh1jhj[ ubh return value:}(hj[ hhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKhj hhubj)}(hhh](j)}(hX0 - tags were copied, the tracer's ``iov_len`` was updated to the number of tags transferred. This may be smaller than the requested ``iov_len`` if the requested address range in the tracee's or the tracer's space cannot be accessed or does not have valid tags.h]h)}(hX0 - tags were copied, the tracer's ``iov_len`` was updated to the number of tags transferred. This may be smaller than the requested ``iov_len`` if the requested address range in the tracee's or the tracer's space cannot be accessed or does not have valid tags.h](h%0 - tags were copied, the tracer’s }(hj~ hhhNhNubj)}(h ``iov_len``h]hiov_len}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1jhj~ ubhW was updated to the number of tags transferred. This may be smaller than the requested }(hj~ hhhNhNubj)}(h ``iov_len``h]hiov_len}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1jhj~ ubhy if the requested address range in the tracee’s or the tracer’s space cannot be accessed or does not have valid tags.}(hj~ hhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKhjz ubah}(h]h ]h"]h$]h&]uh1jhjw hhhhhNubj)}(h4``-EPERM`` - the specified process cannot be traced.h]h)}(hj h](j)}(h ``-EPERM``h]h-EPERM}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1jhj ubh* - the specified process cannot be traced.}(hj hhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKhj ubah}(h]h ]h"]h$]h&]uh1jhjw hhhhhNubj)}(h|``-EIO`` - the tracee's address range cannot be accessed (e.g. invalid address) and no tags copied. ``iov_len`` not updated.h]h)}(h|``-EIO`` - the tracee's address range cannot be accessed (e.g. invalid address) and no tags copied. ``iov_len`` not updated.h](j)}(h``-EIO``h]h-EIO}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1jhj ubh^ - the tracee’s address range cannot be accessed (e.g. invalid address) and no tags copied. }(hj hhhNhNubj)}(h ``iov_len``h]hiov_len}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1jhj ubh not updated.}(hj hhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKhj ubah}(h]h ]h"]h$]h&]uh1jhjw hhhhhNubj)}(h``-EFAULT`` - fault on accessing the tracer's memory (``struct iovec`` or ``iov_base`` buffer) and no tags copied. ``iov_len`` not updated.h]h)}(h``-EFAULT`` - fault on accessing the tracer's memory (``struct iovec`` or ``iov_base`` buffer) and no tags copied. ``iov_len`` not updated.h](j)}(h ``-EFAULT``h]h-EFAULT}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1jhj ubh- - fault on accessing the tracer’s memory (}(hj hhhNhNubj)}(h``struct iovec``h]h struct iovec}(hj- hhhNhNubah}(h]h ]h"]h$]h&]uh1jhj ubh or }(hj hhhNhNubj)}(h ``iov_base``h]hiov_base}(hj? hhhNhNubah}(h]h ]h"]h$]h&]uh1jhj ubh buffer) and no tags copied. }(hj hhhNhNubj)}(h ``iov_len``h]hiov_len}(hjQ hhhNhNubah}(h]h ]h"]h$]h&]uh1jhj ubh not updated.}(hj hhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKhj ubah}(h]h ]h"]h$]h&]uh1jhjw hhhhhNubj)}(h``-EOPNOTSUPP`` - the tracee's address does not have valid tags (never mapped with the ``PROT_MTE`` flag). ``iov_len`` not updated. h]h)}(h``-EOPNOTSUPP`` - the tracee's address does not have valid tags (never mapped with the ``PROT_MTE`` flag). ``iov_len`` not updated.h](j)}(h``-EOPNOTSUPP``h]h -EOPNOTSUPP}(hjw hhhNhNubah}(h]h ]h"]h$]h&]uh1jhjs ubhJ - the tracee’s address does not have valid tags (never mapped with the }(hjs hhhNhNubj)}(h ``PROT_MTE``h]hPROT_MTE}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1jhjs ubh flag). }(hjs hhhNhNubj)}(h ``iov_len``h]hiov_len}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1jhjs ubh not updated.}(hjs hhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKhjo ubah}(h]h ]h"]h$]h&]uh1jhjw hhhhhNubeh}(h]h ]h"]h$]h&]jjuh1jhhhKhj hhubh)}(h**Note**: There are no transient errors for the requests above, so user programs should not retry in case of a non-zero system call return.h](jA)}(h**Note**h]hNote}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1j@hj ubh: There are no transient errors for the requests above, so user programs should not retry in case of a non-zero system call return.}(hj hhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKhj hhubh)}(hXh``PTRACE_GETREGSET`` and ``PTRACE_SETREGSET`` with ``addr == ``NT_ARM_TAGGED_ADDR_CTRL`` allow ``ptrace()`` access to the tagged address ABI control and MTE configuration of a process as per the ``prctl()`` options described in Documentation/arch/arm64/tagged-address-abi.rst and above. The corresponding ``regset`` is 1 element of 8 bytes (``sizeof(long))``).h](j)}(h``PTRACE_GETREGSET``h]hPTRACE_GETREGSET}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1jhj ubh and }(hj hhhNhNubj)}(h``PTRACE_SETREGSET``h]hPTRACE_SETREGSET}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1jhj ubh with }(hj hhhNhNubj)}(h%``addr == ``NT_ARM_TAGGED_ADDR_CTRL``h]h!addr == ``NT_ARM_TAGGED_ADDR_CTRL}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhj ubh allow }(hj hhhNhNubj)}(h ``ptrace()``h]hptrace()}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhj ubhX access to the tagged address ABI control and MTE configuration of a process as per the }(hj hhhNhNubj)}(h ``prctl()``h]hprctl()}(hj'hhhNhNubah}(h]h ]h"]h$]h&]uh1jhj ubhc options described in Documentation/arch/arm64/tagged-address-abi.rst and above. The corresponding }(hj hhhNhNubj)}(h ``regset``h]hregset}(hj9hhhNhNubah}(h]h ]h"]h$]h&]uh1jhj ubh is 1 element of 8 bytes (}(hj hhhNhNubj)}(h``sizeof(long))``h]h sizeof(long))}(hjKhhhNhNubah}(h]h ]h"]h$]h&]uh1jhj ubh).}(hj hhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKhj hhubeh}(h]the-ptrace-interfaceah ]h"]the ptrace() interfaceah$]h&]uh1hhjfhhhhhKubh)}(hhh](h)}(hCore dump supporth]hCore dump support}(hjnhhhNhNubah}(h]h ]h"]h$]h&]uh1hhjkhhhhhKubh)}(hThe allocation tags for user memory mapped with ``PROT_MTE`` are dumped in the core file as additional ``PT_AARCH64_MEMTAG_MTE`` segments. The program header for such segment is defined as:h](h0The allocation tags for user memory mapped with }(hj|hhhNhNubj)}(h ``PROT_MTE``h]hPROT_MTE}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhj|ubh+ are dumped in the core file as additional }(hj|hhhNhNubj)}(h``PT_AARCH64_MEMTAG_MTE``h]hPT_AARCH64_MEMTAG_MTE}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhj|ubh= segments. The program header for such segment is defined as:}(hj|hhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKhjkhhubh field_list)}(hhh](hfield)}(hhh](h field_name)}(h ``p_type``h]j)}(hjh]hp_type}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubah}(h]h ]h"]h$]h&]uh1jhjhhhKubh field_body)}(h``PT_AARCH64_MEMTAG_MTE``h]h)}(hjh]j)}(hjh]hPT_AARCH64_MEMTAG_MTE}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubah}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1jhjubeh}(h]h ]h"]h$]h&]uh1jhhhKhjhhubj)}(hhh](j)}(h ``p_flags``h]j)}(hjh]hp_flags}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubah}(h]h ]h"]h$]h&]uh1jhjhhhKubj)}(h0h]h)}(hjh]h0}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1jhjubeh}(h]h ]h"]h$]h&]uh1jhhhKhjhhubj)}(hhh](j)}(h ``p_offset``h]j)}(hj5h]hp_offset}(hj7hhhNhNubah}(h]h ]h"]h$]h&]uh1jhj3ubah}(h]h ]h"]h$]h&]uh1jhj0hhhKubj)}(hsegment file offseth]h)}(hjLh]hsegment file offset}(hjNhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjJubah}(h]h ]h"]h$]h&]uh1jhj0ubeh}(h]h ]h"]h$]h&]uh1jhhhKhjhhubj)}(hhh](j)}(h ``p_vaddr``h]j)}(hjlh]hp_vaddr}(hjnhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjjubah}(h]h ]h"]h$]h&]uh1jhjghhhKubj)}(hFsegment virtual address, same as the corresponding ``PT_LOAD`` segmenth]h)}(hFsegment virtual address, same as the corresponding ``PT_LOAD`` segmenth](h3segment virtual address, same as the corresponding }(hjhhhNhNubj)}(h ``PT_LOAD``h]hPT_LOAD}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubh segment}(hjhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1jhjgubeh}(h]h ]h"]h$]h&]uh1jhhhKhjhhubj)}(hhh](j)}(h ``p_paddr``h]j)}(hjh]hp_paddr}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubah}(h]h ]h"]h$]h&]uh1jhjhhhKubj)}(hjh]h)}(hjh]h0}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1jhjubeh}(h]h ]h"]h$]h&]uh1jhhhKhjhhubj)}(hhh](j)}(h ``p_filesz``h]j)}(hjh]hp_filesz}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubah}(h]h ]h"]h$]h&]uh1jhjhhhKubj)}(h_segment size in file, calculated as ``p_mem_sz / 32`` (two 4-bit tags cover 32 bytes of memory)h]h)}(h_segment size in file, calculated as ``p_mem_sz / 32`` (two 4-bit tags cover 32 bytes of memory)h](h$segment size in file, calculated as }(hjhhhNhNubj)}(h``p_mem_sz / 32``h]h p_mem_sz / 32}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubh* (two 4-bit tags cover 32 bytes of memory)}(hjhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1jhjubeh}(h]h ]h"]h$]h&]uh1jhhhKhjhhubj)}(hhh](j)}(h ``p_memsz``h]j)}(hj6h]hp_memsz}(hj8hhhNhNubah}(h]h ]h"]h$]h&]uh1jhj4ubah}(h]h ]h"]h$]h&]uh1jhj1hhhKubj)}(hEsegment size in memory, same as the corresponding ``PT_LOAD`` segmenth]h)}(hEsegment size in memory, same as the corresponding ``PT_LOAD`` segmenth](h2segment size in memory, same as the corresponding }(hjOhhhNhNubj)}(h ``PT_LOAD``h]hPT_LOAD}(hjWhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjOubh segment}(hjOhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKhjKubah}(h]h ]h"]h$]h&]uh1jhj1ubeh}(h]h ]h"]h$]h&]uh1jhhhKhjhhubj)}(hhh](j)}(h ``p_align``h]j)}(hjh]hp_align}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhj~ubah}(h]h ]h"]h$]h&]uh1jhj{hhhKubj)}(h0 h]h)}(hjh]h0}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1jhj{ubeh}(h]h ]h"]h$]h&]uh1jhhhKhjhhubeh}(h]h ]h"]h$]h&]uh1jhjkhhhhhKubh)}(hThe tags are stored in the core file at ``p_offset`` as two 4-bit tags in a byte. With the tag granule of 16 bytes, a 4K page requires 128 bytes in the core file.h](h(The tags are stored in the core file at }(hjhhhNhNubj)}(h ``p_offset``h]hp_offset}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubhn as two 4-bit tags in a byte. With the tag granule of 16 bytes, a 4K page requires 128 bytes in the core file.}(hjhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKhjkhhubeh}(h]core-dump-supportah ]h"]core dump supportah$]h&]uh1hhjfhhhhhKubeh}(h]userspace-supportah ]h"]userspace supportah$]h&]uh1hhhhhhhhKubh)}(hhh](h)}(hExample of correct usageh]hExample of correct usage}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhjhhhhhKubh)}(h*MTE Example code*h]j)}(hjh]hMTE Example code}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubah}(h]h ]h"]h$]h&]uh1hhhhKhjhhubh literal_block)}(hX /* * To be compiled with -march=armv8.5-a+memtag */ #include #include #include #include #include #include #include #include /* * From arch/arm64/include/uapi/asm/hwcap.h */ #define HWCAP2_MTE (1 << 18) /* * From arch/arm64/include/uapi/asm/mman.h */ #define PROT_MTE 0x20 /* * From include/uapi/linux/prctl.h */ #define PR_SET_TAGGED_ADDR_CTRL 55 #define PR_GET_TAGGED_ADDR_CTRL 56 # define PR_TAGGED_ADDR_ENABLE (1UL << 0) # define PR_MTE_TCF_SHIFT 1 # define PR_MTE_TCF_NONE (0UL << PR_MTE_TCF_SHIFT) # define PR_MTE_TCF_SYNC (1UL << PR_MTE_TCF_SHIFT) # define PR_MTE_TCF_ASYNC (2UL << PR_MTE_TCF_SHIFT) # define PR_MTE_TCF_MASK (3UL << PR_MTE_TCF_SHIFT) # define PR_MTE_TAG_SHIFT 3 # define PR_MTE_TAG_MASK (0xffffUL << PR_MTE_TAG_SHIFT) /* * Insert a random logical tag into the given pointer. */ #define insert_random_tag(ptr) ({ \ uint64_t __val; \ asm("irg %0, %1" : "=r" (__val) : "r" (ptr)); \ __val; \ }) /* * Set the allocation tag on the destination address. */ #define set_tag(tagged_addr) do { \ asm volatile("stg %0, [%0]" : : "r" (tagged_addr) : "memory"); \ } while (0) int main() { unsigned char *a; unsigned long page_sz = sysconf(_SC_PAGESIZE); unsigned long hwcap2 = getauxval(AT_HWCAP2); /* check if MTE is present */ if (!(hwcap2 & HWCAP2_MTE)) return EXIT_FAILURE; /* * Enable the tagged address ABI, synchronous or asynchronous MTE * tag check faults (based on per-CPU preference) and allow all * non-zero tags in the randomly generated set. */ if (prctl(PR_SET_TAGGED_ADDR_CTRL, PR_TAGGED_ADDR_ENABLE | PR_MTE_TCF_SYNC | PR_MTE_TCF_ASYNC | (0xfffe << PR_MTE_TAG_SHIFT), 0, 0, 0)) { perror("prctl() failed"); return EXIT_FAILURE; } a = mmap(0, page_sz, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); if (a == MAP_FAILED) { perror("mmap() failed"); return EXIT_FAILURE; } /* * Enable MTE on the above anonymous mmap. The flag could be passed * directly to mmap() and skip this step. */ if (mprotect(a, page_sz, PROT_READ | PROT_WRITE | PROT_MTE)) { perror("mprotect() failed"); return EXIT_FAILURE; } /* access with the default tag (0) */ a[0] = 1; a[1] = 2; printf("a[0] = %hhu a[1] = %hhu\n", a[0], a[1]); /* set the logical and allocation tags */ a = (unsigned char *)insert_random_tag(a); set_tag(a); printf("%p\n", a); /* non-zero tag access */ a[0] = 3; printf("a[0] = %hhu a[1] = %hhu\n", a[0], a[1]); /* * If MTE is enabled correctly the next instruction will generate an * exception. */ printf("Expecting SIGSEGV...\n"); a[16] = 0xdd; /* this should not be printed in the PR_MTE_TCF_SYNC mode */ printf("...haven't got one\n"); return EXIT_FAILURE; }h]hX /* * To be compiled with -march=armv8.5-a+memtag */ #include #include #include #include #include #include #include #include /* * From arch/arm64/include/uapi/asm/hwcap.h */ #define HWCAP2_MTE (1 << 18) /* * From arch/arm64/include/uapi/asm/mman.h */ #define PROT_MTE 0x20 /* * From include/uapi/linux/prctl.h */ #define PR_SET_TAGGED_ADDR_CTRL 55 #define PR_GET_TAGGED_ADDR_CTRL 56 # define PR_TAGGED_ADDR_ENABLE (1UL << 0) # define PR_MTE_TCF_SHIFT 1 # define PR_MTE_TCF_NONE (0UL << PR_MTE_TCF_SHIFT) # define PR_MTE_TCF_SYNC (1UL << PR_MTE_TCF_SHIFT) # define PR_MTE_TCF_ASYNC (2UL << PR_MTE_TCF_SHIFT) # define PR_MTE_TCF_MASK (3UL << PR_MTE_TCF_SHIFT) # define PR_MTE_TAG_SHIFT 3 # define PR_MTE_TAG_MASK (0xffffUL << PR_MTE_TAG_SHIFT) /* * Insert a random logical tag into the given pointer. */ #define insert_random_tag(ptr) ({ \ uint64_t __val; \ asm("irg %0, %1" : "=r" (__val) : "r" (ptr)); \ __val; \ }) /* * Set the allocation tag on the destination address. */ #define set_tag(tagged_addr) do { \ asm volatile("stg %0, [%0]" : : "r" (tagged_addr) : "memory"); \ } while (0) int main() { unsigned char *a; unsigned long page_sz = sysconf(_SC_PAGESIZE); unsigned long hwcap2 = getauxval(AT_HWCAP2); /* check if MTE is present */ if (!(hwcap2 & HWCAP2_MTE)) return EXIT_FAILURE; /* * Enable the tagged address ABI, synchronous or asynchronous MTE * tag check faults (based on per-CPU preference) and allow all * non-zero tags in the randomly generated set. */ if (prctl(PR_SET_TAGGED_ADDR_CTRL, PR_TAGGED_ADDR_ENABLE | PR_MTE_TCF_SYNC | PR_MTE_TCF_ASYNC | (0xfffe << PR_MTE_TAG_SHIFT), 0, 0, 0)) { perror("prctl() failed"); return EXIT_FAILURE; } a = mmap(0, page_sz, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); if (a == MAP_FAILED) { perror("mmap() failed"); return EXIT_FAILURE; } /* * Enable MTE on the above anonymous mmap. The flag could be passed * directly to mmap() and skip this step. */ if (mprotect(a, page_sz, PROT_READ | PROT_WRITE | PROT_MTE)) { perror("mprotect() failed"); return EXIT_FAILURE; } /* access with the default tag (0) */ a[0] = 1; a[1] = 2; printf("a[0] = %hhu a[1] = %hhu\n", a[0], a[1]); /* set the logical and allocation tags */ a = (unsigned char *)insert_random_tag(a); set_tag(a); printf("%p\n", a); /* non-zero tag access */ a[0] = 3; printf("a[0] = %hhu a[1] = %hhu\n", a[0], a[1]); /* * If MTE is enabled correctly the next instruction will generate an * exception. */ printf("Expecting SIGSEGV...\n"); a[16] = 0xdd; /* this should not be printed in the PR_MTE_TCF_SYNC mode */ printf("...haven't got one\n"); return EXIT_FAILURE; }}hjsbah}(h]h ]h"]h$]h&] xml:spacepreserveforcelanguagechighlight_args}uh1jhhhKhjhhubeh}(h]example-of-correct-usageah ]h"]example of correct usageah$]h&]uh1hhhhhhhhKubeh}(h]-memory-tagging-extension-mte-in-aarch64-linuxah ]h"]/memory tagging extension (mte) in aarch64 linuxah$]h&]uh1hhhhhhhhKubeh}(h]h ]h"]h$]h&]sourcehuh1hcurrent_sourceN current_lineNsettingsdocutils.frontendValues)}(hN generatorN datestampN source_linkN source_urlN toc_backlinksentryfootnote_backlinksK sectnum_xformKstrip_commentsNstrip_elements_with_classesN strip_classesN report_levelK halt_levelKexit_status_levelKdebugNwarning_streamN tracebackinput_encoding utf-8-siginput_encoding_error_handlerstrictoutput_encodingutf-8output_encoding_error_handlerjZerror_encodingutf-8error_encoding_error_handlerbackslashreplace language_codeenrecord_dependenciesNconfigN id_prefixhauto_id_prefixid dump_settingsNdump_internalsNdump_transformsNdump_pseudo_xmlNexpose_internalsNstrict_visitorN_disable_configN_sourceh _destinationN _config_files]7/var/lib/git/docbuild/linux/Documentation/docutils.confafile_insertion_enabled raw_enabledKline_length_limitM'pep_referencesN pep_base_urlhttps://peps.python.org/pep_file_url_templatepep-%04drfc_referencesN rfc_base_url&https://datatracker.ietf.org/doc/html/ tab_widthKtrim_footnote_reference_spacesyntax_highlightlong smart_quotessmartquotes_locales]character_level_inline_markupdoctitle_xform docinfo_xformKsectsubtitle_xform image_loadinglinkembed_stylesheetcloak_email_addressessection_self_linkenvNubreporterNindirect_targets]substitution_defs}substitution_names}refnames}refids}nameids}(j4j1jcj`jjjKjHj1j.j:j7jk jh j j jhjejjj,j)u nametypes}(j4jcjjKj1j:jk j jhjj,uh}(j1hj`j?jjfjHjj.jNj7j4jh j=j jn jej jjkj)ju footnote_refs} citation_refs} autofootnotes]autofootnote_refs]symbol_footnotes]symbol_footnote_refs] footnotes] citations]autofootnote_startKsymbol_footnote_startK id_counter collectionsCounter}Rparse_messages]transform_messages] transformerN include_log] decorationNhhub.