linux/arch/arm/include/asm/uaccess-asm.h
<<
>>
Prefs
   1/* SPDX-License-Identifier: GPL-2.0-only */
   2
   3#ifndef __ASM_UACCESS_ASM_H__
   4#define __ASM_UACCESS_ASM_H__
   5
   6#include <asm/asm-offsets.h>
   7#include <asm/domain.h>
   8#include <asm/memory.h>
   9#include <asm/thread_info.h>
  10
  11        .macro  csdb
  12#ifdef CONFIG_THUMB2_KERNEL
  13        .inst.w 0xf3af8014
  14#else
  15        .inst   0xe320f014
  16#endif
  17        .endm
  18
  19        .macro check_uaccess, addr:req, size:req, limit:req, tmp:req, bad:req
  20#ifndef CONFIG_CPU_USE_DOMAINS
  21        adds    \tmp, \addr, #\size - 1
  22        sbcscc  \tmp, \tmp, \limit
  23        bcs     \bad
  24#ifdef CONFIG_CPU_SPECTRE
  25        movcs   \addr, #0
  26        csdb
  27#endif
  28#endif
  29        .endm
  30
  31        .macro uaccess_mask_range_ptr, addr:req, size:req, limit:req, tmp:req
  32#ifdef CONFIG_CPU_SPECTRE
  33        sub     \tmp, \limit, #1
  34        subs    \tmp, \tmp, \addr       @ tmp = limit - 1 - addr
  35        addhs   \tmp, \tmp, #1          @ if (tmp >= 0) {
  36        subshs  \tmp, \tmp, \size       @ tmp = limit - (addr + size) }
  37        movlo   \addr, #0               @ if (tmp < 0) addr = NULL
  38        csdb
  39#endif
  40        .endm
  41
  42        .macro  uaccess_disable, tmp, isb=1
  43#ifdef CONFIG_CPU_SW_DOMAIN_PAN
  44        /*
  45         * Whenever we re-enter userspace, the domains should always be
  46         * set appropriately.
  47         */
  48        mov     \tmp, #DACR_UACCESS_DISABLE
  49        mcr     p15, 0, \tmp, c3, c0, 0         @ Set domain register
  50        .if     \isb
  51        instr_sync
  52        .endif
  53#endif
  54        .endm
  55
  56        .macro  uaccess_enable, tmp, isb=1
  57#ifdef CONFIG_CPU_SW_DOMAIN_PAN
  58        /*
  59         * Whenever we re-enter userspace, the domains should always be
  60         * set appropriately.
  61         */
  62        mov     \tmp, #DACR_UACCESS_ENABLE
  63        mcr     p15, 0, \tmp, c3, c0, 0
  64        .if     \isb
  65        instr_sync
  66        .endif
  67#endif
  68        .endm
  69
  70#if defined(CONFIG_CPU_SW_DOMAIN_PAN) || defined(CONFIG_CPU_USE_DOMAINS)
  71#define DACR(x...)      x
  72#else
  73#define DACR(x...)
  74#endif
  75
  76        /*
  77         * Save the address limit on entry to a privileged exception.
  78         *
  79         * If we are using the DACR for kernel access by the user accessors
  80         * (CONFIG_CPU_USE_DOMAINS=y), always reset the DACR kernel domain
  81         * back to client mode, whether or not \disable is set.
  82         *
  83         * If we are using SW PAN, set the DACR user domain to no access
  84         * if \disable is set.
  85         */
  86        .macro  uaccess_entry, tsk, tmp0, tmp1, tmp2, disable
  87 DACR(  mrc     p15, 0, \tmp0, c3, c0, 0)
  88 DACR(  str     \tmp0, [sp, #SVC_DACR])
  89        .if \disable && IS_ENABLED(CONFIG_CPU_SW_DOMAIN_PAN)
  90        /* kernel=client, user=no access */
  91        mov     \tmp2, #DACR_UACCESS_DISABLE
  92        mcr     p15, 0, \tmp2, c3, c0, 0
  93        instr_sync
  94        .elseif IS_ENABLED(CONFIG_CPU_USE_DOMAINS)
  95        /* kernel=client */
  96        bic     \tmp2, \tmp0, #domain_mask(DOMAIN_KERNEL)
  97        orr     \tmp2, \tmp2, #domain_val(DOMAIN_KERNEL, DOMAIN_CLIENT)
  98        mcr     p15, 0, \tmp2, c3, c0, 0
  99        instr_sync
 100        .endif
 101        .endm
 102
 103        /* Restore the user access state previously saved by uaccess_entry */
 104        .macro  uaccess_exit, tsk, tmp0, tmp1
 105 DACR(  ldr     \tmp0, [sp, #SVC_DACR])
 106 DACR(  mcr     p15, 0, \tmp0, c3, c0, 0)
 107        .endm
 108
 109#undef DACR
 110
 111#endif /* __ASM_UACCESS_ASM_H__ */
 112