1 // SPDX-License-Identifier: GPL-2.0 << 2 /* 1 /* 3 * Standard user space access functions based !! 2 * This file is subject to the terms and conditions of the GNU General Public 4 * interesting things in the secondary space !! 3 * License. See the file COPYING in the main directory of this archive 5 * !! 4 * for more details. 6 * Copyright IBM Corp. 2006,2014 << 7 * Author(s): Martin Schwidefsky (schwidefs << 8 * Gerald Schaefer (gerald.schae << 9 */ 5 */ 10 6 >> 7 #include <linux/module.h> 11 #include <linux/uaccess.h> 8 #include <linux/uaccess.h> 12 #include <linux/export.h> << 13 #include <linux/mm.h> << 14 #include <asm/asm-extable.h> << 15 #include <asm/ctlreg.h> << 16 9 17 #ifdef CONFIG_DEBUG_ENTRY !! 10 unsigned long __generic_copy_from_user(void *to, const void __user *from, 18 void debug_user_asce(int exit) !! 11 unsigned long n) 19 { 12 { 20 struct ctlreg cr1, cr7; !! 13 unsigned long tmp, res; 21 14 22 local_ctl_store(1, &cr1); !! 15 asm volatile ("\n" 23 local_ctl_store(7, &cr7); !! 16 " tst.l %0\n" 24 if (cr1.val == get_lowcore()->kernel_a !! 17 " jeq 2f\n" 25 return; !! 18 "1: "MOVES".l (%1)+,%3\n" 26 panic("incorrect ASCE on kernel %s\n" !! 19 " move.l %3,(%2)+\n" 27 "cr1: %016lx cr7: %016lx\n" !! 20 " subq.l #1,%0\n" 28 "kernel: %016lx user: %016lx\n", !! 21 " jne 1b\n" 29 exit ? "exit" : "entry", cr1.val !! 22 "2: btst #1,%5\n" 30 get_lowcore()->kernel_asce.val, !! 23 " jeq 4f\n" 31 } !! 24 "3: "MOVES".w (%1)+,%3\n" 32 #endif /*CONFIG_DEBUG_ENTRY */ !! 25 " move.w %3,(%2)+\n" 33 !! 26 "4: btst #0,%5\n" 34 static unsigned long raw_copy_from_user_key(vo !! 27 " jeq 6f\n" 35 un !! 28 "5: "MOVES".b (%1)+,%3\n" 36 { !! 29 " move.b %3,(%2)+\n" 37 unsigned long rem; << 38 union oac spec = { << 39 .oac2.key = key, << 40 .oac2.as = PSW_BITS_AS_SECONDA << 41 .oac2.k = 1, << 42 .oac2.a = 1, << 43 }; << 44 << 45 asm volatile( << 46 " lr 0,%[spec]\n" << 47 "0: mvcos 0(%[to]),0(%[f << 48 "1: jz 5f\n" << 49 " algr %[size],%[val] << 50 " slgr %[from],%[val] << 51 " slgr %[to],%[val]\n << 52 " j 0b\n" << 53 "2: la %[rem],4095(%[ << 54 " nr %[rem],%[val]\ << 55 " slgr %[rem],%[from] << 56 " clgr %[size],%[rem] << 57 " jnh 6f\n" << 58 "3: mvcos 0(%[to]),0(%[f << 59 "4: slgr %[size],%[rem] << 60 " j 6f\n" << 61 "5: slgr %[size],%[size << 62 "6:\n" 30 "6:\n" 63 EX_TABLE(0b, 2b) !! 31 " .section .fixup,\"ax\"\n" 64 EX_TABLE(1b, 2b) !! 32 " .even\n" 65 EX_TABLE(3b, 6b) !! 33 "10: lsl.l #2,%0\n" 66 EX_TABLE(4b, 6b) !! 34 " btst #1,%5\n" 67 : [size] "+&a" (size), [from] !! 35 " jeq 8f\n" 68 : [val] "a" (-4096UL), [spec] !! 36 "30: addq.l #2,%0\n" 69 : "cc", "memory", ""); !! 37 "8: btst #0,%5\n" 70 return size; !! 38 " jeq 6b\n" 71 } !! 39 "50: addq.l #1,%0\n" >> 40 " jra 6b\n" >> 41 " .previous\n" >> 42 "\n" >> 43 " .section __ex_table,\"a\"\n" >> 44 " .align 4\n" >> 45 " .long 1b,10b\n" >> 46 " .long 3b,30b\n" >> 47 " .long 5b,50b\n" >> 48 " .previous" >> 49 : "=d" (res), "+a" (from), "+a" (to), "=&d" (tmp) >> 50 : "" (n / 4), "d" (n & 3)); 72 51 73 unsigned long raw_copy_from_user(void *to, con !! 52 return res; 74 { << 75 return raw_copy_from_user_key(to, from << 76 } 53 } 77 EXPORT_SYMBOL(raw_copy_from_user); !! 54 EXPORT_SYMBOL(__generic_copy_from_user); 78 55 79 unsigned long _copy_from_user_key(void *to, co !! 56 unsigned long __generic_copy_to_user(void __user *to, const void *from, 80 unsigned lon !! 57 unsigned long n) 81 { 58 { 82 unsigned long res = n; !! 59 unsigned long tmp, res; >> 60 >> 61 asm volatile ("\n" >> 62 " tst.l %0\n" >> 63 " jeq 4f\n" >> 64 "1: move.l (%1)+,%3\n" >> 65 "2: "MOVES".l %3,(%2)+\n" >> 66 "3: subq.l #1,%0\n" >> 67 " jne 1b\n" >> 68 "4: btst #1,%5\n" >> 69 " jeq 6f\n" >> 70 " move.w (%1)+,%3\n" >> 71 "5: "MOVES".w %3,(%2)+\n" >> 72 "6: btst #0,%5\n" >> 73 " jeq 8f\n" >> 74 " move.b (%1)+,%3\n" >> 75 "7: "MOVES".b %3,(%2)+\n" >> 76 "8:\n" >> 77 " .section .fixup,\"ax\"\n" >> 78 " .even\n" >> 79 "20: lsl.l #2,%0\n" >> 80 "50: add.l %5,%0\n" >> 81 " jra 8b\n" >> 82 " .previous\n" >> 83 "\n" >> 84 " .section __ex_table,\"a\"\n" >> 85 " .align 4\n" >> 86 " .long 2b,20b\n" >> 87 " .long 3b,20b\n" >> 88 " .long 5b,50b\n" >> 89 " .long 6b,50b\n" >> 90 " .long 7b,50b\n" >> 91 " .long 8b,50b\n" >> 92 " .previous" >> 93 : "=d" (res), "+a" (from), "+a" (to), "=&d" (tmp) >> 94 : "" (n / 4), "d" (n & 3)); 83 95 84 might_fault(); << 85 if (!should_fail_usercopy()) { << 86 instrument_copy_from_user_befo << 87 res = raw_copy_from_user_key(t << 88 instrument_copy_from_user_afte << 89 } << 90 if (unlikely(res)) << 91 memset(to + (n - res), 0, res) << 92 return res; 96 return res; 93 } 97 } 94 EXPORT_SYMBOL(_copy_from_user_key); !! 98 EXPORT_SYMBOL(__generic_copy_to_user); 95 99 96 static unsigned long raw_copy_to_user_key(void !! 100 /* 97 unsi !! 101 * Zero Userspace 98 { !! 102 */ 99 unsigned long rem; << 100 union oac spec = { << 101 .oac1.key = key, << 102 .oac1.as = PSW_BITS_AS_SECONDA << 103 .oac1.k = 1, << 104 .oac1.a = 1, << 105 }; << 106 << 107 asm volatile( << 108 " lr 0,%[spec]\n" << 109 "0: mvcos 0(%[to]),0(%[f << 110 "1: jz 5f\n" << 111 " algr %[size],%[val] << 112 " slgr %[to],%[val]\n << 113 " slgr %[from],%[val] << 114 " j 0b\n" << 115 "2: la %[rem],4095(%[ << 116 " nr %[rem],%[val]\ << 117 " slgr %[rem],%[to]\n << 118 " clgr %[size],%[rem] << 119 " jnh 6f\n" << 120 "3: mvcos 0(%[to]),0(%[f << 121 "4: slgr %[size],%[rem] << 122 " j 6f\n" << 123 "5: slgr %[size],%[size << 124 "6:\n" << 125 EX_TABLE(0b, 2b) << 126 EX_TABLE(1b, 2b) << 127 EX_TABLE(3b, 6b) << 128 EX_TABLE(4b, 6b) << 129 : [size] "+&a" (size), [to] "+ << 130 : [val] "a" (-4096UL), [spec] << 131 : "cc", "memory", ""); << 132 return size; << 133 } << 134 103 135 unsigned long raw_copy_to_user(void __user *to !! 104 unsigned long __clear_user(void __user *to, unsigned long n) 136 { 105 { 137 return raw_copy_to_user_key(to, from, !! 106 unsigned long res; 138 } << 139 EXPORT_SYMBOL(raw_copy_to_user); << 140 107 141 unsigned long _copy_to_user_key(void __user *t !! 108 asm volatile ("\n" 142 unsigned long !! 109 " tst.l %0\n" 143 { !! 110 " jeq 3f\n" 144 might_fault(); !! 111 "1: "MOVES".l %2,(%1)+\n" 145 if (should_fail_usercopy()) !! 112 "2: subq.l #1,%0\n" 146 return n; !! 113 " jne 1b\n" 147 instrument_copy_to_user(to, from, n); !! 114 "3: btst #1,%4\n" 148 return raw_copy_to_user_key(to, from, !! 115 " jeq 5f\n" 149 } !! 116 "4: "MOVES".w %2,(%1)+\n" 150 EXPORT_SYMBOL(_copy_to_user_key); !! 117 "5: btst #0,%4\n" >> 118 " jeq 7f\n" >> 119 "6: "MOVES".b %2,(%1)\n" >> 120 "7:\n" >> 121 " .section .fixup,\"ax\"\n" >> 122 " .even\n" >> 123 "10: lsl.l #2,%0\n" >> 124 "40: add.l %4,%0\n" >> 125 " jra 7b\n" >> 126 " .previous\n" >> 127 "\n" >> 128 " .section __ex_table,\"a\"\n" >> 129 " .align 4\n" >> 130 " .long 1b,10b\n" >> 131 " .long 2b,10b\n" >> 132 " .long 4b,40b\n" >> 133 " .long 5b,40b\n" >> 134 " .long 6b,40b\n" >> 135 " .long 7b,40b\n" >> 136 " .previous" >> 137 : "=d" (res), "+a" (to) >> 138 : "d" (0), "" (n / 4), "d" (n & 3)); 151 139 152 unsigned long __clear_user(void __user *to, un !! 140 return res; 153 { << 154 unsigned long rem; << 155 union oac spec = { << 156 .oac1.as = PSW_BITS_AS_SECONDA << 157 .oac1.a = 1, << 158 }; << 159 << 160 asm volatile( << 161 " lr 0,%[spec]\n" << 162 "0: mvcos 0(%[to]),0(%[z << 163 "1: jz 5f\n" << 164 " algr %[size],%[val] << 165 " slgr %[to],%[val]\n << 166 " j 0b\n" << 167 "2: la %[rem],4095(%[ << 168 " nr %[rem],%[val]\ << 169 " slgr %[rem],%[to]\n << 170 " clgr %[size],%[rem] << 171 " jnh 6f\n" << 172 "3: mvcos 0(%[to]),0(%[z << 173 "4: slgr %[size],%[rem] << 174 " j 6f\n" << 175 "5: slgr %[size],%[size << 176 "6:\n" << 177 EX_TABLE(0b, 2b) << 178 EX_TABLE(1b, 2b) << 179 EX_TABLE(3b, 6b) << 180 EX_TABLE(4b, 6b) << 181 : [size] "+&a" (size), [to] "+ << 182 : [val] "a" (-4096UL), [zeropg << 183 : "cc", "memory", ""); << 184 return size; << 185 } 141 } 186 EXPORT_SYMBOL(__clear_user); 142 EXPORT_SYMBOL(__clear_user); 187 143
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.