uaccess.c 4.6 KB

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