root/arch/arm64/lib/kasan_sw_tags.S
/* SPDX-License-Identifier: GPL-2.0-only */
/*
 * Copyright (C) 2020 Google LLC
 */

#include <linux/linkage.h>
#include <asm/assembler.h>

/*
 * Report a tag mismatch detected by tag-based KASAN.
 *
 * A compiler-generated thunk calls this with a non-AAPCS calling
 * convention. Upon entry to this function, registers are as follows:
 *
 * x0:         fault address (see below for restore)
 * x1:         fault description (see below for restore)
 * x2 to x15:  callee-saved
 * x16 to x17: safe to clobber
 * x18 to x30: callee-saved
 * sp:         pre-decremented by 256 bytes (see below for restore)
 *
 * The caller has decremented the SP by 256 bytes, and created a
 * structure on the stack as follows:
 *
 * sp + 0..15:    x0 and x1 to be restored
 * sp + 16..231:  free for use
 * sp + 232..247: x29 and x30 (same as in GPRs)
 * sp + 248..255: free for use
 *
 * Note that this is not a struct pt_regs.
 *
 * To call a regular AAPCS function we must save x2 to x15 (which we can
 * store in the gaps), and create a frame record (for which we can use
 * x29 and x30 spilled by the caller as those match the GPRs).
 *
 * The caller expects x0 and x1 to be restored from the structure, and
 * for the structure to be removed from the stack (i.e. the SP must be
 * incremented by 256 prior to return).
 */
SYM_CODE_START(__hwasan_tag_mismatch)
        bti     c
        add     x29, sp, #232
        stp     x2, x3, [sp, #8 * 2]
        stp     x4, x5, [sp, #8 * 4]
        stp     x6, x7, [sp, #8 * 6]
        stp     x8, x9, [sp, #8 * 8]
        stp     x10, x11, [sp, #8 * 10]
        stp     x12, x13, [sp, #8 * 12]
        stp     x14, x15, [sp, #8 * 14]
#ifndef CONFIG_SHADOW_CALL_STACK
        str     x18, [sp, #8 * 18]
#endif

        mov     x2, x30
        bl      kasan_tag_mismatch

        ldp     x0, x1, [sp]
        ldp     x2, x3, [sp, #8 * 2]
        ldp     x4, x5, [sp, #8 * 4]
        ldp     x6, x7, [sp, #8 * 6]
        ldp     x8, x9, [sp, #8 * 8]
        ldp     x10, x11, [sp, #8 * 10]
        ldp     x12, x13, [sp, #8 * 12]
        ldp     x14, x15, [sp, #8 * 14]
#ifndef CONFIG_SHADOW_CALL_STACK
        ldr     x18, [sp, #8 * 18]
#endif
        ldp     x29, x30, [sp, #8 * 29]

        /* remove the structure from the stack */
        add     sp, sp, #256
        ret
SYM_CODE_END(__hwasan_tag_mismatch)
EXPORT_SYMBOL(__hwasan_tag_mismatch)