uaccess.c 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Standard user space access functions based on mvcp/mvcs and doing
  4. * interesting things in the secondary space mode.
  5. *
  6. * Copyright IBM Corp. 2006,2014
  7. * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com),
  8. * Gerald Schaefer (gerald.schaefer@de.ibm.com)
  9. */
  10. #include <linux/uaccess.h>
  11. #include <linux/export.h>
  12. #include <linux/mm.h>
  13. #include <asm/asm-extable.h>
  14. #include <asm/ctlreg.h>
  15. #ifdef CONFIG_DEBUG_ENTRY
  16. void debug_user_asce(int exit)
  17. {
  18. struct ctlreg cr1, cr7;
  19. local_ctl_store(1, &cr1);
  20. local_ctl_store(7, &cr7);
  21. if (cr1.val == get_lowcore()->kernel_asce.val && cr7.val == get_lowcore()->user_asce.val)
  22. return;
  23. panic("incorrect ASCE on kernel %s\n"
  24. "cr1: %016lx cr7: %016lx\n"
  25. "kernel: %016lx user: %016lx\n",
  26. exit ? "exit" : "entry", cr1.val, cr7.val,
  27. get_lowcore()->kernel_asce.val, get_lowcore()->user_asce.val);
  28. }
  29. #endif /*CONFIG_DEBUG_ENTRY */
  30. static unsigned long raw_copy_from_user_key(void *to, const void __user *from,
  31. unsigned long size, unsigned long key)
  32. {
  33. unsigned long rem;
  34. union oac spec = {
  35. .oac2.key = key,
  36. .oac2.as = PSW_BITS_AS_SECONDARY,
  37. .oac2.k = 1,
  38. .oac2.a = 1,
  39. };
  40. asm volatile(
  41. " lr 0,%[spec]\n"
  42. "0: mvcos 0(%[to]),0(%[from]),%[size]\n"
  43. "1: jz 5f\n"
  44. " algr %[size],%[val]\n"
  45. " slgr %[from],%[val]\n"
  46. " slgr %[to],%[val]\n"
  47. " j 0b\n"
  48. "2: la %[rem],4095(%[from])\n" /* rem = from + 4095 */
  49. " nr %[rem],%[val]\n" /* rem = (from + 4095) & -4096 */
  50. " slgr %[rem],%[from]\n"
  51. " clgr %[size],%[rem]\n" /* copy crosses next page boundary? */
  52. " jnh 6f\n"
  53. "3: mvcos 0(%[to]),0(%[from]),%[rem]\n"
  54. "4: slgr %[size],%[rem]\n"
  55. " j 6f\n"
  56. "5: slgr %[size],%[size]\n"
  57. "6:\n"
  58. EX_TABLE(0b, 2b)
  59. EX_TABLE(1b, 2b)
  60. EX_TABLE(3b, 6b)
  61. EX_TABLE(4b, 6b)
  62. : [size] "+&a" (size), [from] "+&a" (from), [to] "+&a" (to), [rem] "=&a" (rem)
  63. : [val] "a" (-4096UL), [spec] "d" (spec.val)
  64. : "cc", "memory", "0");
  65. return size;
  66. }
  67. unsigned long raw_copy_from_user(void *to, const void __user *from, unsigned long n)
  68. {
  69. return raw_copy_from_user_key(to, from, n, 0);
  70. }
  71. EXPORT_SYMBOL(raw_copy_from_user);
  72. unsigned long _copy_from_user_key(void *to, const void __user *from,
  73. unsigned long n, unsigned long key)
  74. {
  75. unsigned long res = n;
  76. might_fault();
  77. if (!should_fail_usercopy()) {
  78. instrument_copy_from_user_before(to, from, n);
  79. res = raw_copy_from_user_key(to, from, n, key);
  80. instrument_copy_from_user_after(to, from, n, res);
  81. }
  82. if (unlikely(res))
  83. memset(to + (n - res), 0, res);
  84. return res;
  85. }
  86. EXPORT_SYMBOL(_copy_from_user_key);
  87. static unsigned long raw_copy_to_user_key(void __user *to, const void *from,
  88. unsigned long size, unsigned long key)
  89. {
  90. unsigned long rem;
  91. union oac spec = {
  92. .oac1.key = key,
  93. .oac1.as = PSW_BITS_AS_SECONDARY,
  94. .oac1.k = 1,
  95. .oac1.a = 1,
  96. };
  97. asm volatile(
  98. " lr 0,%[spec]\n"
  99. "0: mvcos 0(%[to]),0(%[from]),%[size]\n"
  100. "1: jz 5f\n"
  101. " algr %[size],%[val]\n"
  102. " slgr %[to],%[val]\n"
  103. " slgr %[from],%[val]\n"
  104. " j 0b\n"
  105. "2: la %[rem],4095(%[to])\n" /* rem = to + 4095 */
  106. " nr %[rem],%[val]\n" /* rem = (to + 4095) & -4096 */
  107. " slgr %[rem],%[to]\n"
  108. " clgr %[size],%[rem]\n" /* copy crosses next page boundary? */
  109. " jnh 6f\n"
  110. "3: mvcos 0(%[to]),0(%[from]),%[rem]\n"
  111. "4: slgr %[size],%[rem]\n"
  112. " j 6f\n"
  113. "5: slgr %[size],%[size]\n"
  114. "6:\n"
  115. EX_TABLE(0b, 2b)
  116. EX_TABLE(1b, 2b)
  117. EX_TABLE(3b, 6b)
  118. EX_TABLE(4b, 6b)
  119. : [size] "+&a" (size), [to] "+&a" (to), [from] "+&a" (from), [rem] "=&a" (rem)
  120. : [val] "a" (-4096UL), [spec] "d" (spec.val)
  121. : "cc", "memory", "0");
  122. return size;
  123. }
  124. unsigned long raw_copy_to_user(void __user *to, const void *from, unsigned long n)
  125. {
  126. return raw_copy_to_user_key(to, from, n, 0);
  127. }
  128. EXPORT_SYMBOL(raw_copy_to_user);
  129. unsigned long _copy_to_user_key(void __user *to, const void *from,
  130. unsigned long n, unsigned long key)
  131. {
  132. might_fault();
  133. if (should_fail_usercopy())
  134. return n;
  135. instrument_copy_to_user(to, from, n);
  136. return raw_copy_to_user_key(to, from, n, key);
  137. }
  138. EXPORT_SYMBOL(_copy_to_user_key);
  139. unsigned long __clear_user(void __user *to, unsigned long size)
  140. {
  141. unsigned long rem;
  142. union oac spec = {
  143. .oac1.as = PSW_BITS_AS_SECONDARY,
  144. .oac1.a = 1,
  145. };
  146. asm volatile(
  147. " lr 0,%[spec]\n"
  148. "0: mvcos 0(%[to]),0(%[zeropg]),%[size]\n"
  149. "1: jz 5f\n"
  150. " algr %[size],%[val]\n"
  151. " slgr %[to],%[val]\n"
  152. " j 0b\n"
  153. "2: la %[rem],4095(%[to])\n" /* rem = to + 4095 */
  154. " nr %[rem],%[val]\n" /* rem = (to + 4095) & -4096 */
  155. " slgr %[rem],%[to]\n"
  156. " clgr %[size],%[rem]\n" /* copy crosses next page boundary? */
  157. " jnh 6f\n"
  158. "3: mvcos 0(%[to]),0(%[zeropg]),%[rem]\n"
  159. "4: slgr %[size],%[rem]\n"
  160. " j 6f\n"
  161. "5: slgr %[size],%[size]\n"
  162. "6:\n"
  163. EX_TABLE(0b, 2b)
  164. EX_TABLE(1b, 2b)
  165. EX_TABLE(3b, 6b)
  166. EX_TABLE(4b, 6b)
  167. : [size] "+&a" (size), [to] "+&a" (to), [rem] "=&a" (rem)
  168. : [val] "a" (-4096UL), [zeropg] "a" (empty_zero_page), [spec] "d" (spec.val)
  169. : "cc", "memory", "0");
  170. return size;
  171. }
  172. EXPORT_SYMBOL(__clear_user);