0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #include <linux/uaccess.h>
0012 #include <linux/export.h>
0013 #include <linux/mm.h>
0014 #include <asm/asm-extable.h>
0015
0016 #ifdef CONFIG_DEBUG_ENTRY
0017 void debug_user_asce(int exit)
0018 {
0019 unsigned long cr1, cr7;
0020
0021 __ctl_store(cr1, 1, 1);
0022 __ctl_store(cr7, 7, 7);
0023 if (cr1 == S390_lowcore.kernel_asce && cr7 == S390_lowcore.user_asce)
0024 return;
0025 panic("incorrect ASCE on kernel %s\n"
0026 "cr1: %016lx cr7: %016lx\n"
0027 "kernel: %016llx user: %016llx\n",
0028 exit ? "exit" : "entry", cr1, cr7,
0029 S390_lowcore.kernel_asce, S390_lowcore.user_asce);
0030
0031 }
0032 #endif
0033
0034 static unsigned long raw_copy_from_user_key(void *to, const void __user *from,
0035 unsigned long size, unsigned long key)
0036 {
0037 unsigned long tmp1, tmp2;
0038 union oac spec = {
0039 .oac2.key = key,
0040 .oac2.as = PSW_BITS_AS_SECONDARY,
0041 .oac2.k = 1,
0042 .oac2.a = 1,
0043 };
0044
0045 tmp1 = -4096UL;
0046 asm volatile(
0047 " lr 0,%[spec]\n"
0048 "0: mvcos 0(%2),0(%1),%0\n"
0049 "6: jz 4f\n"
0050 "1: algr %0,%3\n"
0051 " slgr %1,%3\n"
0052 " slgr %2,%3\n"
0053 " j 0b\n"
0054 "2: la %4,4095(%1)\n"
0055 " nr %4,%3\n"
0056 " slgr %4,%1\n"
0057 " clgr %0,%4\n"
0058 " jnh 5f\n"
0059 "3: mvcos 0(%2),0(%1),%4\n"
0060 "7: slgr %0,%4\n"
0061 " j 5f\n"
0062 "4: slgr %0,%0\n"
0063 "5:\n"
0064 EX_TABLE(0b,2b) EX_TABLE(3b,5b) EX_TABLE(6b,2b) EX_TABLE(7b,5b)
0065 : "+a" (size), "+a" (from), "+a" (to), "+a" (tmp1), "=a" (tmp2)
0066 : [spec] "d" (spec.val)
0067 : "cc", "memory", "0");
0068 return size;
0069 }
0070
0071 unsigned long raw_copy_from_user(void *to, const void __user *from, unsigned long n)
0072 {
0073 return raw_copy_from_user_key(to, from, n, 0);
0074 }
0075 EXPORT_SYMBOL(raw_copy_from_user);
0076
0077 unsigned long _copy_from_user_key(void *to, const void __user *from,
0078 unsigned long n, unsigned long key)
0079 {
0080 unsigned long res = n;
0081
0082 might_fault();
0083 if (!should_fail_usercopy()) {
0084 instrument_copy_from_user(to, from, n);
0085 res = raw_copy_from_user_key(to, from, n, key);
0086 }
0087 if (unlikely(res))
0088 memset(to + (n - res), 0, res);
0089 return res;
0090 }
0091 EXPORT_SYMBOL(_copy_from_user_key);
0092
0093 static unsigned long raw_copy_to_user_key(void __user *to, const void *from,
0094 unsigned long size, unsigned long key)
0095 {
0096 unsigned long tmp1, tmp2;
0097 union oac spec = {
0098 .oac1.key = key,
0099 .oac1.as = PSW_BITS_AS_SECONDARY,
0100 .oac1.k = 1,
0101 .oac1.a = 1,
0102 };
0103
0104 tmp1 = -4096UL;
0105 asm volatile(
0106 " lr 0,%[spec]\n"
0107 "0: mvcos 0(%1),0(%2),%0\n"
0108 "6: jz 4f\n"
0109 "1: algr %0,%3\n"
0110 " slgr %1,%3\n"
0111 " slgr %2,%3\n"
0112 " j 0b\n"
0113 "2: la %4,4095(%1)\n"
0114 " nr %4,%3\n"
0115 " slgr %4,%1\n"
0116 " clgr %0,%4\n"
0117 " jnh 5f\n"
0118 "3: mvcos 0(%1),0(%2),%4\n"
0119 "7: slgr %0,%4\n"
0120 " j 5f\n"
0121 "4: slgr %0,%0\n"
0122 "5:\n"
0123 EX_TABLE(0b,2b) EX_TABLE(3b,5b) EX_TABLE(6b,2b) EX_TABLE(7b,5b)
0124 : "+a" (size), "+a" (to), "+a" (from), "+a" (tmp1), "=a" (tmp2)
0125 : [spec] "d" (spec.val)
0126 : "cc", "memory", "0");
0127 return size;
0128 }
0129
0130 unsigned long raw_copy_to_user(void __user *to, const void *from, unsigned long n)
0131 {
0132 return raw_copy_to_user_key(to, from, n, 0);
0133 }
0134 EXPORT_SYMBOL(raw_copy_to_user);
0135
0136 unsigned long _copy_to_user_key(void __user *to, const void *from,
0137 unsigned long n, unsigned long key)
0138 {
0139 might_fault();
0140 if (should_fail_usercopy())
0141 return n;
0142 instrument_copy_to_user(to, from, n);
0143 return raw_copy_to_user_key(to, from, n, key);
0144 }
0145 EXPORT_SYMBOL(_copy_to_user_key);
0146
0147 unsigned long __clear_user(void __user *to, unsigned long size)
0148 {
0149 unsigned long tmp1, tmp2;
0150 union oac spec = {
0151 .oac1.as = PSW_BITS_AS_SECONDARY,
0152 .oac1.a = 1,
0153 };
0154
0155 tmp1 = -4096UL;
0156 asm volatile(
0157 " lr 0,%[spec]\n"
0158 "0: mvcos 0(%1),0(%4),%0\n"
0159 " jz 4f\n"
0160 "1: algr %0,%2\n"
0161 " slgr %1,%2\n"
0162 " j 0b\n"
0163 "2: la %3,4095(%1)\n"
0164 " nr %3,%2\n"
0165 " slgr %3,%1\n"
0166 " clgr %0,%3\n"
0167 " jnh 5f\n"
0168 "3: mvcos 0(%1),0(%4),%3\n"
0169 " slgr %0,%3\n"
0170 " j 5f\n"
0171 "4: slgr %0,%0\n"
0172 "5:\n"
0173 EX_TABLE(0b,2b) EX_TABLE(3b,5b)
0174 : "+a" (size), "+a" (to), "+a" (tmp1), "=a" (tmp2)
0175 : "a" (empty_zero_page), [spec] "d" (spec.val)
0176 : "cc", "memory", "0");
0177 return size;
0178 }
0179 EXPORT_SYMBOL(__clear_user);