| .. | .. |
|---|
| 24 | 24 | #include <linux/seccomp.h> |
|---|
| 25 | 25 | #include <linux/compat.h> |
|---|
| 26 | 26 | #include <trace/syscall.h> |
|---|
| 27 | | -#include <asm/segment.h> |
|---|
| 28 | 27 | #include <asm/page.h> |
|---|
| 29 | | -#include <asm/pgtable.h> |
|---|
| 30 | | -#include <asm/pgalloc.h> |
|---|
| 31 | 28 | #include <linux/uaccess.h> |
|---|
| 32 | 29 | #include <asm/unistd.h> |
|---|
| 33 | 30 | #include <asm/switch_to.h> |
|---|
| .. | .. |
|---|
| 868 | 865 | asmlinkage long do_syscall_trace_enter(struct pt_regs *regs) |
|---|
| 869 | 866 | { |
|---|
| 870 | 867 | unsigned long mask = -1UL; |
|---|
| 868 | + long ret = -1; |
|---|
| 869 | + |
|---|
| 870 | + if (is_compat_task()) |
|---|
| 871 | + mask = 0xffffffff; |
|---|
| 871 | 872 | |
|---|
| 872 | 873 | /* |
|---|
| 873 | 874 | * The sysc_tracesys code in entry.S stored the system |
|---|
| 874 | 875 | * call number to gprs[2]. |
|---|
| 875 | 876 | */ |
|---|
| 876 | 877 | if (test_thread_flag(TIF_SYSCALL_TRACE) && |
|---|
| 877 | | - (tracehook_report_syscall_entry(regs) || |
|---|
| 878 | | - regs->gprs[2] >= NR_syscalls)) { |
|---|
| 878 | + tracehook_report_syscall_entry(regs)) { |
|---|
| 879 | 879 | /* |
|---|
| 880 | | - * Tracing decided this syscall should not happen or the |
|---|
| 881 | | - * debugger stored an invalid system call number. Skip |
|---|
| 880 | + * Tracing decided this syscall should not happen. Skip |
|---|
| 882 | 881 | * the system call and the system call restart handling. |
|---|
| 883 | 882 | */ |
|---|
| 884 | | - clear_pt_regs_flag(regs, PIF_SYSCALL); |
|---|
| 885 | | - return -1; |
|---|
| 883 | + goto skip; |
|---|
| 886 | 884 | } |
|---|
| 887 | 885 | |
|---|
| 886 | +#ifdef CONFIG_SECCOMP |
|---|
| 888 | 887 | /* Do the secure computing check after ptrace. */ |
|---|
| 889 | | - if (secure_computing(NULL)) { |
|---|
| 890 | | - /* seccomp failures shouldn't expose any additional code. */ |
|---|
| 891 | | - return -1; |
|---|
| 888 | + if (unlikely(test_thread_flag(TIF_SECCOMP))) { |
|---|
| 889 | + struct seccomp_data sd; |
|---|
| 890 | + |
|---|
| 891 | + if (is_compat_task()) { |
|---|
| 892 | + sd.instruction_pointer = regs->psw.addr & 0x7fffffff; |
|---|
| 893 | + sd.arch = AUDIT_ARCH_S390; |
|---|
| 894 | + } else { |
|---|
| 895 | + sd.instruction_pointer = regs->psw.addr; |
|---|
| 896 | + sd.arch = AUDIT_ARCH_S390X; |
|---|
| 897 | + } |
|---|
| 898 | + |
|---|
| 899 | + sd.nr = regs->int_code & 0xffff; |
|---|
| 900 | + sd.args[0] = regs->orig_gpr2 & mask; |
|---|
| 901 | + sd.args[1] = regs->gprs[3] & mask; |
|---|
| 902 | + sd.args[2] = regs->gprs[4] & mask; |
|---|
| 903 | + sd.args[3] = regs->gprs[5] & mask; |
|---|
| 904 | + sd.args[4] = regs->gprs[6] & mask; |
|---|
| 905 | + sd.args[5] = regs->gprs[7] & mask; |
|---|
| 906 | + |
|---|
| 907 | + if (__secure_computing(&sd) == -1) |
|---|
| 908 | + goto skip; |
|---|
| 892 | 909 | } |
|---|
| 910 | +#endif /* CONFIG_SECCOMP */ |
|---|
| 893 | 911 | |
|---|
| 894 | 912 | if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT))) |
|---|
| 895 | | - trace_sys_enter(regs, regs->gprs[2]); |
|---|
| 913 | + trace_sys_enter(regs, regs->int_code & 0xffff); |
|---|
| 896 | 914 | |
|---|
| 897 | | - if (is_compat_task()) |
|---|
| 898 | | - mask = 0xffffffff; |
|---|
| 899 | 915 | |
|---|
| 900 | | - audit_syscall_entry(regs->gprs[2], regs->orig_gpr2 & mask, |
|---|
| 916 | + audit_syscall_entry(regs->int_code & 0xffff, regs->orig_gpr2 & mask, |
|---|
| 901 | 917 | regs->gprs[3] &mask, regs->gprs[4] &mask, |
|---|
| 902 | 918 | regs->gprs[5] &mask); |
|---|
| 903 | 919 | |
|---|
| 920 | + if ((signed long)regs->gprs[2] >= NR_syscalls) { |
|---|
| 921 | + regs->gprs[2] = -ENOSYS; |
|---|
| 922 | + ret = -ENOSYS; |
|---|
| 923 | + } |
|---|
| 904 | 924 | return regs->gprs[2]; |
|---|
| 925 | +skip: |
|---|
| 926 | + clear_pt_regs_flag(regs, PIF_SYSCALL); |
|---|
| 927 | + return ret; |
|---|
| 905 | 928 | } |
|---|
| 906 | 929 | |
|---|
| 907 | 930 | asmlinkage void do_syscall_trace_exit(struct pt_regs *regs) |
|---|
| .. | .. |
|---|
| 921 | 944 | |
|---|
| 922 | 945 | static int s390_regs_get(struct task_struct *target, |
|---|
| 923 | 946 | const struct user_regset *regset, |
|---|
| 924 | | - unsigned int pos, unsigned int count, |
|---|
| 925 | | - void *kbuf, void __user *ubuf) |
|---|
| 947 | + struct membuf to) |
|---|
| 926 | 948 | { |
|---|
| 949 | + unsigned pos; |
|---|
| 927 | 950 | if (target == current) |
|---|
| 928 | 951 | save_access_regs(target->thread.acrs); |
|---|
| 929 | 952 | |
|---|
| 930 | | - if (kbuf) { |
|---|
| 931 | | - unsigned long *k = kbuf; |
|---|
| 932 | | - while (count > 0) { |
|---|
| 933 | | - *k++ = __peek_user(target, pos); |
|---|
| 934 | | - count -= sizeof(*k); |
|---|
| 935 | | - pos += sizeof(*k); |
|---|
| 936 | | - } |
|---|
| 937 | | - } else { |
|---|
| 938 | | - unsigned long __user *u = ubuf; |
|---|
| 939 | | - while (count > 0) { |
|---|
| 940 | | - if (__put_user(__peek_user(target, pos), u++)) |
|---|
| 941 | | - return -EFAULT; |
|---|
| 942 | | - count -= sizeof(*u); |
|---|
| 943 | | - pos += sizeof(*u); |
|---|
| 944 | | - } |
|---|
| 945 | | - } |
|---|
| 953 | + for (pos = 0; pos < sizeof(s390_regs); pos += sizeof(long)) |
|---|
| 954 | + membuf_store(&to, __peek_user(target, pos)); |
|---|
| 946 | 955 | return 0; |
|---|
| 947 | 956 | } |
|---|
| 948 | 957 | |
|---|
| .. | .. |
|---|
| 983 | 992 | } |
|---|
| 984 | 993 | |
|---|
| 985 | 994 | static int s390_fpregs_get(struct task_struct *target, |
|---|
| 986 | | - const struct user_regset *regset, unsigned int pos, |
|---|
| 987 | | - unsigned int count, void *kbuf, void __user *ubuf) |
|---|
| 995 | + const struct user_regset *regset, |
|---|
| 996 | + struct membuf to) |
|---|
| 988 | 997 | { |
|---|
| 989 | 998 | _s390_fp_regs fp_regs; |
|---|
| 990 | 999 | |
|---|
| .. | .. |
|---|
| 994 | 1003 | fp_regs.fpc = target->thread.fpu.fpc; |
|---|
| 995 | 1004 | fpregs_store(&fp_regs, &target->thread.fpu); |
|---|
| 996 | 1005 | |
|---|
| 997 | | - return user_regset_copyout(&pos, &count, &kbuf, &ubuf, |
|---|
| 998 | | - &fp_regs, 0, -1); |
|---|
| 1006 | + return membuf_write(&to, &fp_regs, sizeof(fp_regs)); |
|---|
| 999 | 1007 | } |
|---|
| 1000 | 1008 | |
|---|
| 1001 | 1009 | static int s390_fpregs_set(struct task_struct *target, |
|---|
| .. | .. |
|---|
| 1042 | 1050 | |
|---|
| 1043 | 1051 | static int s390_last_break_get(struct task_struct *target, |
|---|
| 1044 | 1052 | const struct user_regset *regset, |
|---|
| 1045 | | - unsigned int pos, unsigned int count, |
|---|
| 1046 | | - void *kbuf, void __user *ubuf) |
|---|
| 1053 | + struct membuf to) |
|---|
| 1047 | 1054 | { |
|---|
| 1048 | | - if (count > 0) { |
|---|
| 1049 | | - if (kbuf) { |
|---|
| 1050 | | - unsigned long *k = kbuf; |
|---|
| 1051 | | - *k = target->thread.last_break; |
|---|
| 1052 | | - } else { |
|---|
| 1053 | | - unsigned long __user *u = ubuf; |
|---|
| 1054 | | - if (__put_user(target->thread.last_break, u)) |
|---|
| 1055 | | - return -EFAULT; |
|---|
| 1056 | | - } |
|---|
| 1057 | | - } |
|---|
| 1058 | | - return 0; |
|---|
| 1055 | + return membuf_store(&to, target->thread.last_break); |
|---|
| 1059 | 1056 | } |
|---|
| 1060 | 1057 | |
|---|
| 1061 | 1058 | static int s390_last_break_set(struct task_struct *target, |
|---|
| .. | .. |
|---|
| 1068 | 1065 | |
|---|
| 1069 | 1066 | static int s390_tdb_get(struct task_struct *target, |
|---|
| 1070 | 1067 | const struct user_regset *regset, |
|---|
| 1071 | | - unsigned int pos, unsigned int count, |
|---|
| 1072 | | - void *kbuf, void __user *ubuf) |
|---|
| 1068 | + struct membuf to) |
|---|
| 1073 | 1069 | { |
|---|
| 1074 | 1070 | struct pt_regs *regs = task_pt_regs(target); |
|---|
| 1075 | | - unsigned char *data; |
|---|
| 1076 | 1071 | |
|---|
| 1077 | 1072 | if (!(regs->int_code & 0x200)) |
|---|
| 1078 | 1073 | return -ENODATA; |
|---|
| 1079 | | - data = target->thread.trap_tdb; |
|---|
| 1080 | | - return user_regset_copyout(&pos, &count, &kbuf, &ubuf, data, 0, 256); |
|---|
| 1074 | + return membuf_write(&to, target->thread.trap_tdb, 256); |
|---|
| 1081 | 1075 | } |
|---|
| 1082 | 1076 | |
|---|
| 1083 | 1077 | static int s390_tdb_set(struct task_struct *target, |
|---|
| .. | .. |
|---|
| 1090 | 1084 | |
|---|
| 1091 | 1085 | static int s390_vxrs_low_get(struct task_struct *target, |
|---|
| 1092 | 1086 | const struct user_regset *regset, |
|---|
| 1093 | | - unsigned int pos, unsigned int count, |
|---|
| 1094 | | - void *kbuf, void __user *ubuf) |
|---|
| 1087 | + struct membuf to) |
|---|
| 1095 | 1088 | { |
|---|
| 1096 | 1089 | __u64 vxrs[__NUM_VXRS_LOW]; |
|---|
| 1097 | 1090 | int i; |
|---|
| .. | .. |
|---|
| 1102 | 1095 | save_fpu_regs(); |
|---|
| 1103 | 1096 | for (i = 0; i < __NUM_VXRS_LOW; i++) |
|---|
| 1104 | 1097 | vxrs[i] = *((__u64 *)(target->thread.fpu.vxrs + i) + 1); |
|---|
| 1105 | | - return user_regset_copyout(&pos, &count, &kbuf, &ubuf, vxrs, 0, -1); |
|---|
| 1098 | + return membuf_write(&to, vxrs, sizeof(vxrs)); |
|---|
| 1106 | 1099 | } |
|---|
| 1107 | 1100 | |
|---|
| 1108 | 1101 | static int s390_vxrs_low_set(struct task_struct *target, |
|---|
| .. | .. |
|---|
| 1131 | 1124 | |
|---|
| 1132 | 1125 | static int s390_vxrs_high_get(struct task_struct *target, |
|---|
| 1133 | 1126 | const struct user_regset *regset, |
|---|
| 1134 | | - unsigned int pos, unsigned int count, |
|---|
| 1135 | | - void *kbuf, void __user *ubuf) |
|---|
| 1127 | + struct membuf to) |
|---|
| 1136 | 1128 | { |
|---|
| 1137 | | - __vector128 vxrs[__NUM_VXRS_HIGH]; |
|---|
| 1138 | | - |
|---|
| 1139 | 1129 | if (!MACHINE_HAS_VX) |
|---|
| 1140 | 1130 | return -ENODEV; |
|---|
| 1141 | 1131 | if (target == current) |
|---|
| 1142 | 1132 | save_fpu_regs(); |
|---|
| 1143 | | - memcpy(vxrs, target->thread.fpu.vxrs + __NUM_VXRS_LOW, sizeof(vxrs)); |
|---|
| 1144 | | - |
|---|
| 1145 | | - return user_regset_copyout(&pos, &count, &kbuf, &ubuf, vxrs, 0, -1); |
|---|
| 1133 | + return membuf_write(&to, target->thread.fpu.vxrs + __NUM_VXRS_LOW, |
|---|
| 1134 | + __NUM_VXRS_HIGH * sizeof(__vector128)); |
|---|
| 1146 | 1135 | } |
|---|
| 1147 | 1136 | |
|---|
| 1148 | 1137 | static int s390_vxrs_high_set(struct task_struct *target, |
|---|
| .. | .. |
|---|
| 1164 | 1153 | |
|---|
| 1165 | 1154 | static int s390_system_call_get(struct task_struct *target, |
|---|
| 1166 | 1155 | const struct user_regset *regset, |
|---|
| 1167 | | - unsigned int pos, unsigned int count, |
|---|
| 1168 | | - void *kbuf, void __user *ubuf) |
|---|
| 1156 | + struct membuf to) |
|---|
| 1169 | 1157 | { |
|---|
| 1170 | | - unsigned int *data = &target->thread.system_call; |
|---|
| 1171 | | - return user_regset_copyout(&pos, &count, &kbuf, &ubuf, |
|---|
| 1172 | | - data, 0, sizeof(unsigned int)); |
|---|
| 1158 | + return membuf_store(&to, target->thread.system_call); |
|---|
| 1173 | 1159 | } |
|---|
| 1174 | 1160 | |
|---|
| 1175 | 1161 | static int s390_system_call_set(struct task_struct *target, |
|---|
| .. | .. |
|---|
| 1184 | 1170 | |
|---|
| 1185 | 1171 | static int s390_gs_cb_get(struct task_struct *target, |
|---|
| 1186 | 1172 | const struct user_regset *regset, |
|---|
| 1187 | | - unsigned int pos, unsigned int count, |
|---|
| 1188 | | - void *kbuf, void __user *ubuf) |
|---|
| 1173 | + struct membuf to) |
|---|
| 1189 | 1174 | { |
|---|
| 1190 | 1175 | struct gs_cb *data = target->thread.gs_cb; |
|---|
| 1191 | 1176 | |
|---|
| .. | .. |
|---|
| 1195 | 1180 | return -ENODATA; |
|---|
| 1196 | 1181 | if (target == current) |
|---|
| 1197 | 1182 | save_gs_cb(data); |
|---|
| 1198 | | - return user_regset_copyout(&pos, &count, &kbuf, &ubuf, |
|---|
| 1199 | | - data, 0, sizeof(struct gs_cb)); |
|---|
| 1183 | + return membuf_write(&to, data, sizeof(struct gs_cb)); |
|---|
| 1200 | 1184 | } |
|---|
| 1201 | 1185 | |
|---|
| 1202 | 1186 | static int s390_gs_cb_set(struct task_struct *target, |
|---|
| .. | .. |
|---|
| 1240 | 1224 | |
|---|
| 1241 | 1225 | static int s390_gs_bc_get(struct task_struct *target, |
|---|
| 1242 | 1226 | const struct user_regset *regset, |
|---|
| 1243 | | - unsigned int pos, unsigned int count, |
|---|
| 1244 | | - void *kbuf, void __user *ubuf) |
|---|
| 1227 | + struct membuf to) |
|---|
| 1245 | 1228 | { |
|---|
| 1246 | 1229 | struct gs_cb *data = target->thread.gs_bc_cb; |
|---|
| 1247 | 1230 | |
|---|
| .. | .. |
|---|
| 1249 | 1232 | return -ENODEV; |
|---|
| 1250 | 1233 | if (!data) |
|---|
| 1251 | 1234 | return -ENODATA; |
|---|
| 1252 | | - return user_regset_copyout(&pos, &count, &kbuf, &ubuf, |
|---|
| 1253 | | - data, 0, sizeof(struct gs_cb)); |
|---|
| 1235 | + return membuf_write(&to, data, sizeof(struct gs_cb)); |
|---|
| 1254 | 1236 | } |
|---|
| 1255 | 1237 | |
|---|
| 1256 | 1238 | static int s390_gs_bc_set(struct task_struct *target, |
|---|
| .. | .. |
|---|
| 1300 | 1282 | |
|---|
| 1301 | 1283 | static int s390_runtime_instr_get(struct task_struct *target, |
|---|
| 1302 | 1284 | const struct user_regset *regset, |
|---|
| 1303 | | - unsigned int pos, unsigned int count, |
|---|
| 1304 | | - void *kbuf, void __user *ubuf) |
|---|
| 1285 | + struct membuf to) |
|---|
| 1305 | 1286 | { |
|---|
| 1306 | 1287 | struct runtime_instr_cb *data = target->thread.ri_cb; |
|---|
| 1307 | 1288 | |
|---|
| .. | .. |
|---|
| 1310 | 1291 | if (!data) |
|---|
| 1311 | 1292 | return -ENODATA; |
|---|
| 1312 | 1293 | |
|---|
| 1313 | | - return user_regset_copyout(&pos, &count, &kbuf, &ubuf, |
|---|
| 1314 | | - data, 0, sizeof(struct runtime_instr_cb)); |
|---|
| 1294 | + return membuf_write(&to, data, sizeof(struct runtime_instr_cb)); |
|---|
| 1315 | 1295 | } |
|---|
| 1316 | 1296 | |
|---|
| 1317 | 1297 | static int s390_runtime_instr_set(struct task_struct *target, |
|---|
| .. | .. |
|---|
| 1371 | 1351 | .n = sizeof(s390_regs) / sizeof(long), |
|---|
| 1372 | 1352 | .size = sizeof(long), |
|---|
| 1373 | 1353 | .align = sizeof(long), |
|---|
| 1374 | | - .get = s390_regs_get, |
|---|
| 1354 | + .regset_get = s390_regs_get, |
|---|
| 1375 | 1355 | .set = s390_regs_set, |
|---|
| 1376 | 1356 | }, |
|---|
| 1377 | 1357 | { |
|---|
| .. | .. |
|---|
| 1379 | 1359 | .n = sizeof(s390_fp_regs) / sizeof(long), |
|---|
| 1380 | 1360 | .size = sizeof(long), |
|---|
| 1381 | 1361 | .align = sizeof(long), |
|---|
| 1382 | | - .get = s390_fpregs_get, |
|---|
| 1362 | + .regset_get = s390_fpregs_get, |
|---|
| 1383 | 1363 | .set = s390_fpregs_set, |
|---|
| 1384 | 1364 | }, |
|---|
| 1385 | 1365 | { |
|---|
| .. | .. |
|---|
| 1387 | 1367 | .n = 1, |
|---|
| 1388 | 1368 | .size = sizeof(unsigned int), |
|---|
| 1389 | 1369 | .align = sizeof(unsigned int), |
|---|
| 1390 | | - .get = s390_system_call_get, |
|---|
| 1370 | + .regset_get = s390_system_call_get, |
|---|
| 1391 | 1371 | .set = s390_system_call_set, |
|---|
| 1392 | 1372 | }, |
|---|
| 1393 | 1373 | { |
|---|
| .. | .. |
|---|
| 1395 | 1375 | .n = 1, |
|---|
| 1396 | 1376 | .size = sizeof(long), |
|---|
| 1397 | 1377 | .align = sizeof(long), |
|---|
| 1398 | | - .get = s390_last_break_get, |
|---|
| 1378 | + .regset_get = s390_last_break_get, |
|---|
| 1399 | 1379 | .set = s390_last_break_set, |
|---|
| 1400 | 1380 | }, |
|---|
| 1401 | 1381 | { |
|---|
| .. | .. |
|---|
| 1403 | 1383 | .n = 1, |
|---|
| 1404 | 1384 | .size = 256, |
|---|
| 1405 | 1385 | .align = 1, |
|---|
| 1406 | | - .get = s390_tdb_get, |
|---|
| 1386 | + .regset_get = s390_tdb_get, |
|---|
| 1407 | 1387 | .set = s390_tdb_set, |
|---|
| 1408 | 1388 | }, |
|---|
| 1409 | 1389 | { |
|---|
| .. | .. |
|---|
| 1411 | 1391 | .n = __NUM_VXRS_LOW, |
|---|
| 1412 | 1392 | .size = sizeof(__u64), |
|---|
| 1413 | 1393 | .align = sizeof(__u64), |
|---|
| 1414 | | - .get = s390_vxrs_low_get, |
|---|
| 1394 | + .regset_get = s390_vxrs_low_get, |
|---|
| 1415 | 1395 | .set = s390_vxrs_low_set, |
|---|
| 1416 | 1396 | }, |
|---|
| 1417 | 1397 | { |
|---|
| .. | .. |
|---|
| 1419 | 1399 | .n = __NUM_VXRS_HIGH, |
|---|
| 1420 | 1400 | .size = sizeof(__vector128), |
|---|
| 1421 | 1401 | .align = sizeof(__vector128), |
|---|
| 1422 | | - .get = s390_vxrs_high_get, |
|---|
| 1402 | + .regset_get = s390_vxrs_high_get, |
|---|
| 1423 | 1403 | .set = s390_vxrs_high_set, |
|---|
| 1424 | 1404 | }, |
|---|
| 1425 | 1405 | { |
|---|
| .. | .. |
|---|
| 1427 | 1407 | .n = sizeof(struct gs_cb) / sizeof(__u64), |
|---|
| 1428 | 1408 | .size = sizeof(__u64), |
|---|
| 1429 | 1409 | .align = sizeof(__u64), |
|---|
| 1430 | | - .get = s390_gs_cb_get, |
|---|
| 1410 | + .regset_get = s390_gs_cb_get, |
|---|
| 1431 | 1411 | .set = s390_gs_cb_set, |
|---|
| 1432 | 1412 | }, |
|---|
| 1433 | 1413 | { |
|---|
| .. | .. |
|---|
| 1435 | 1415 | .n = sizeof(struct gs_cb) / sizeof(__u64), |
|---|
| 1436 | 1416 | .size = sizeof(__u64), |
|---|
| 1437 | 1417 | .align = sizeof(__u64), |
|---|
| 1438 | | - .get = s390_gs_bc_get, |
|---|
| 1418 | + .regset_get = s390_gs_bc_get, |
|---|
| 1439 | 1419 | .set = s390_gs_bc_set, |
|---|
| 1440 | 1420 | }, |
|---|
| 1441 | 1421 | { |
|---|
| .. | .. |
|---|
| 1443 | 1423 | .n = sizeof(struct runtime_instr_cb) / sizeof(__u64), |
|---|
| 1444 | 1424 | .size = sizeof(__u64), |
|---|
| 1445 | 1425 | .align = sizeof(__u64), |
|---|
| 1446 | | - .get = s390_runtime_instr_get, |
|---|
| 1426 | + .regset_get = s390_runtime_instr_get, |
|---|
| 1447 | 1427 | .set = s390_runtime_instr_set, |
|---|
| 1448 | 1428 | }, |
|---|
| 1449 | 1429 | }; |
|---|
| 1450 | 1430 | |
|---|
| 1451 | 1431 | static const struct user_regset_view user_s390_view = { |
|---|
| 1452 | | - .name = UTS_MACHINE, |
|---|
| 1432 | + .name = "s390x", |
|---|
| 1453 | 1433 | .e_machine = EM_S390, |
|---|
| 1454 | 1434 | .regsets = s390_regsets, |
|---|
| 1455 | 1435 | .n = ARRAY_SIZE(s390_regsets) |
|---|
| .. | .. |
|---|
| 1458 | 1438 | #ifdef CONFIG_COMPAT |
|---|
| 1459 | 1439 | static int s390_compat_regs_get(struct task_struct *target, |
|---|
| 1460 | 1440 | const struct user_regset *regset, |
|---|
| 1461 | | - unsigned int pos, unsigned int count, |
|---|
| 1462 | | - void *kbuf, void __user *ubuf) |
|---|
| 1441 | + struct membuf to) |
|---|
| 1463 | 1442 | { |
|---|
| 1443 | + unsigned n; |
|---|
| 1444 | + |
|---|
| 1464 | 1445 | if (target == current) |
|---|
| 1465 | 1446 | save_access_regs(target->thread.acrs); |
|---|
| 1466 | 1447 | |
|---|
| 1467 | | - if (kbuf) { |
|---|
| 1468 | | - compat_ulong_t *k = kbuf; |
|---|
| 1469 | | - while (count > 0) { |
|---|
| 1470 | | - *k++ = __peek_user_compat(target, pos); |
|---|
| 1471 | | - count -= sizeof(*k); |
|---|
| 1472 | | - pos += sizeof(*k); |
|---|
| 1473 | | - } |
|---|
| 1474 | | - } else { |
|---|
| 1475 | | - compat_ulong_t __user *u = ubuf; |
|---|
| 1476 | | - while (count > 0) { |
|---|
| 1477 | | - if (__put_user(__peek_user_compat(target, pos), u++)) |
|---|
| 1478 | | - return -EFAULT; |
|---|
| 1479 | | - count -= sizeof(*u); |
|---|
| 1480 | | - pos += sizeof(*u); |
|---|
| 1481 | | - } |
|---|
| 1482 | | - } |
|---|
| 1448 | + for (n = 0; n < sizeof(s390_compat_regs); n += sizeof(compat_ulong_t)) |
|---|
| 1449 | + membuf_store(&to, __peek_user_compat(target, n)); |
|---|
| 1483 | 1450 | return 0; |
|---|
| 1484 | 1451 | } |
|---|
| 1485 | 1452 | |
|---|
| .. | .. |
|---|
| 1521 | 1488 | |
|---|
| 1522 | 1489 | static int s390_compat_regs_high_get(struct task_struct *target, |
|---|
| 1523 | 1490 | const struct user_regset *regset, |
|---|
| 1524 | | - unsigned int pos, unsigned int count, |
|---|
| 1525 | | - void *kbuf, void __user *ubuf) |
|---|
| 1491 | + struct membuf to) |
|---|
| 1526 | 1492 | { |
|---|
| 1527 | 1493 | compat_ulong_t *gprs_high; |
|---|
| 1494 | + int i; |
|---|
| 1528 | 1495 | |
|---|
| 1529 | | - gprs_high = (compat_ulong_t *) |
|---|
| 1530 | | - &task_pt_regs(target)->gprs[pos / sizeof(compat_ulong_t)]; |
|---|
| 1531 | | - if (kbuf) { |
|---|
| 1532 | | - compat_ulong_t *k = kbuf; |
|---|
| 1533 | | - while (count > 0) { |
|---|
| 1534 | | - *k++ = *gprs_high; |
|---|
| 1535 | | - gprs_high += 2; |
|---|
| 1536 | | - count -= sizeof(*k); |
|---|
| 1537 | | - } |
|---|
| 1538 | | - } else { |
|---|
| 1539 | | - compat_ulong_t __user *u = ubuf; |
|---|
| 1540 | | - while (count > 0) { |
|---|
| 1541 | | - if (__put_user(*gprs_high, u++)) |
|---|
| 1542 | | - return -EFAULT; |
|---|
| 1543 | | - gprs_high += 2; |
|---|
| 1544 | | - count -= sizeof(*u); |
|---|
| 1545 | | - } |
|---|
| 1546 | | - } |
|---|
| 1496 | + gprs_high = (compat_ulong_t *)task_pt_regs(target)->gprs; |
|---|
| 1497 | + for (i = 0; i < NUM_GPRS; i++, gprs_high += 2) |
|---|
| 1498 | + membuf_store(&to, *gprs_high); |
|---|
| 1547 | 1499 | return 0; |
|---|
| 1548 | 1500 | } |
|---|
| 1549 | 1501 | |
|---|
| .. | .. |
|---|
| 1582 | 1534 | |
|---|
| 1583 | 1535 | static int s390_compat_last_break_get(struct task_struct *target, |
|---|
| 1584 | 1536 | const struct user_regset *regset, |
|---|
| 1585 | | - unsigned int pos, unsigned int count, |
|---|
| 1586 | | - void *kbuf, void __user *ubuf) |
|---|
| 1537 | + struct membuf to) |
|---|
| 1587 | 1538 | { |
|---|
| 1588 | | - compat_ulong_t last_break; |
|---|
| 1539 | + compat_ulong_t last_break = target->thread.last_break; |
|---|
| 1589 | 1540 | |
|---|
| 1590 | | - if (count > 0) { |
|---|
| 1591 | | - last_break = target->thread.last_break; |
|---|
| 1592 | | - if (kbuf) { |
|---|
| 1593 | | - unsigned long *k = kbuf; |
|---|
| 1594 | | - *k = last_break; |
|---|
| 1595 | | - } else { |
|---|
| 1596 | | - unsigned long __user *u = ubuf; |
|---|
| 1597 | | - if (__put_user(last_break, u)) |
|---|
| 1598 | | - return -EFAULT; |
|---|
| 1599 | | - } |
|---|
| 1600 | | - } |
|---|
| 1601 | | - return 0; |
|---|
| 1541 | + return membuf_store(&to, (unsigned long)last_break); |
|---|
| 1602 | 1542 | } |
|---|
| 1603 | 1543 | |
|---|
| 1604 | 1544 | static int s390_compat_last_break_set(struct task_struct *target, |
|---|
| .. | .. |
|---|
| 1615 | 1555 | .n = sizeof(s390_compat_regs) / sizeof(compat_long_t), |
|---|
| 1616 | 1556 | .size = sizeof(compat_long_t), |
|---|
| 1617 | 1557 | .align = sizeof(compat_long_t), |
|---|
| 1618 | | - .get = s390_compat_regs_get, |
|---|
| 1558 | + .regset_get = s390_compat_regs_get, |
|---|
| 1619 | 1559 | .set = s390_compat_regs_set, |
|---|
| 1620 | 1560 | }, |
|---|
| 1621 | 1561 | { |
|---|
| .. | .. |
|---|
| 1623 | 1563 | .n = sizeof(s390_fp_regs) / sizeof(compat_long_t), |
|---|
| 1624 | 1564 | .size = sizeof(compat_long_t), |
|---|
| 1625 | 1565 | .align = sizeof(compat_long_t), |
|---|
| 1626 | | - .get = s390_fpregs_get, |
|---|
| 1566 | + .regset_get = s390_fpregs_get, |
|---|
| 1627 | 1567 | .set = s390_fpregs_set, |
|---|
| 1628 | 1568 | }, |
|---|
| 1629 | 1569 | { |
|---|
| .. | .. |
|---|
| 1631 | 1571 | .n = 1, |
|---|
| 1632 | 1572 | .size = sizeof(compat_uint_t), |
|---|
| 1633 | 1573 | .align = sizeof(compat_uint_t), |
|---|
| 1634 | | - .get = s390_system_call_get, |
|---|
| 1574 | + .regset_get = s390_system_call_get, |
|---|
| 1635 | 1575 | .set = s390_system_call_set, |
|---|
| 1636 | 1576 | }, |
|---|
| 1637 | 1577 | { |
|---|
| .. | .. |
|---|
| 1639 | 1579 | .n = 1, |
|---|
| 1640 | 1580 | .size = sizeof(long), |
|---|
| 1641 | 1581 | .align = sizeof(long), |
|---|
| 1642 | | - .get = s390_compat_last_break_get, |
|---|
| 1582 | + .regset_get = s390_compat_last_break_get, |
|---|
| 1643 | 1583 | .set = s390_compat_last_break_set, |
|---|
| 1644 | 1584 | }, |
|---|
| 1645 | 1585 | { |
|---|
| .. | .. |
|---|
| 1647 | 1587 | .n = 1, |
|---|
| 1648 | 1588 | .size = 256, |
|---|
| 1649 | 1589 | .align = 1, |
|---|
| 1650 | | - .get = s390_tdb_get, |
|---|
| 1590 | + .regset_get = s390_tdb_get, |
|---|
| 1651 | 1591 | .set = s390_tdb_set, |
|---|
| 1652 | 1592 | }, |
|---|
| 1653 | 1593 | { |
|---|
| .. | .. |
|---|
| 1655 | 1595 | .n = __NUM_VXRS_LOW, |
|---|
| 1656 | 1596 | .size = sizeof(__u64), |
|---|
| 1657 | 1597 | .align = sizeof(__u64), |
|---|
| 1658 | | - .get = s390_vxrs_low_get, |
|---|
| 1598 | + .regset_get = s390_vxrs_low_get, |
|---|
| 1659 | 1599 | .set = s390_vxrs_low_set, |
|---|
| 1660 | 1600 | }, |
|---|
| 1661 | 1601 | { |
|---|
| .. | .. |
|---|
| 1663 | 1603 | .n = __NUM_VXRS_HIGH, |
|---|
| 1664 | 1604 | .size = sizeof(__vector128), |
|---|
| 1665 | 1605 | .align = sizeof(__vector128), |
|---|
| 1666 | | - .get = s390_vxrs_high_get, |
|---|
| 1606 | + .regset_get = s390_vxrs_high_get, |
|---|
| 1667 | 1607 | .set = s390_vxrs_high_set, |
|---|
| 1668 | 1608 | }, |
|---|
| 1669 | 1609 | { |
|---|
| .. | .. |
|---|
| 1671 | 1611 | .n = sizeof(s390_compat_regs_high) / sizeof(compat_long_t), |
|---|
| 1672 | 1612 | .size = sizeof(compat_long_t), |
|---|
| 1673 | 1613 | .align = sizeof(compat_long_t), |
|---|
| 1674 | | - .get = s390_compat_regs_high_get, |
|---|
| 1614 | + .regset_get = s390_compat_regs_high_get, |
|---|
| 1675 | 1615 | .set = s390_compat_regs_high_set, |
|---|
| 1676 | 1616 | }, |
|---|
| 1677 | 1617 | { |
|---|
| .. | .. |
|---|
| 1679 | 1619 | .n = sizeof(struct gs_cb) / sizeof(__u64), |
|---|
| 1680 | 1620 | .size = sizeof(__u64), |
|---|
| 1681 | 1621 | .align = sizeof(__u64), |
|---|
| 1682 | | - .get = s390_gs_cb_get, |
|---|
| 1622 | + .regset_get = s390_gs_cb_get, |
|---|
| 1683 | 1623 | .set = s390_gs_cb_set, |
|---|
| 1684 | 1624 | }, |
|---|
| 1685 | 1625 | { |
|---|
| .. | .. |
|---|
| 1687 | 1627 | .n = sizeof(struct gs_cb) / sizeof(__u64), |
|---|
| 1688 | 1628 | .size = sizeof(__u64), |
|---|
| 1689 | 1629 | .align = sizeof(__u64), |
|---|
| 1690 | | - .get = s390_gs_bc_get, |
|---|
| 1630 | + .regset_get = s390_gs_bc_get, |
|---|
| 1691 | 1631 | .set = s390_gs_bc_set, |
|---|
| 1692 | 1632 | }, |
|---|
| 1693 | 1633 | { |
|---|
| .. | .. |
|---|
| 1695 | 1635 | .n = sizeof(struct runtime_instr_cb) / sizeof(__u64), |
|---|
| 1696 | 1636 | .size = sizeof(__u64), |
|---|
| 1697 | 1637 | .align = sizeof(__u64), |
|---|
| 1698 | | - .get = s390_runtime_instr_get, |
|---|
| 1638 | + .regset_get = s390_runtime_instr_get, |
|---|
| 1699 | 1639 | .set = s390_runtime_instr_set, |
|---|
| 1700 | 1640 | }, |
|---|
| 1701 | 1641 | }; |
|---|