uaccess-asm.h 3.7 KB

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