Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ia64: remove CONFIG_SET_FS support

ia64 only uses set_fs() in one file to handle unaligned access for
both user space and kernel instructions. Rewrite this to explicitly
pass around a flag about which one it is and drop the feature from
the architecture.

Signed-off-by: Arnd Bergmann <arnd@arndb.de>

+45 -43
-1
arch/ia64/Kconfig
··· 61 61 select NEED_SG_DMA_LENGTH 62 62 select NUMA if !FLATMEM 63 63 select PCI_MSI_ARCH_FALLBACKS if PCI_MSI 64 - select SET_FS 65 64 select ZONE_DMA32 66 65 default y 67 66 help
-4
arch/ia64/include/asm/processor.h
··· 243 243 244 244 extern void print_cpu_info (struct cpuinfo_ia64 *); 245 245 246 - typedef struct { 247 - unsigned long seg; 248 - } mm_segment_t; 249 - 250 246 #define SET_UNALIGN_CTL(task,value) \ 251 247 ({ \ 252 248 (task)->thread.flags = (((task)->thread.flags & ~IA64_THREAD_UAC_MASK) \
-2
arch/ia64/include/asm/thread_info.h
··· 27 27 __u32 cpu; /* current CPU */ 28 28 __u32 last_cpu; /* Last CPU thread ran on */ 29 29 __u32 status; /* Thread synchronous flags */ 30 - mm_segment_t addr_limit; /* user-level address space limit */ 31 30 int preempt_count; /* 0=premptable, <0=BUG; will also serve as bh-counter */ 32 31 #ifdef CONFIG_VIRT_CPU_ACCOUNTING_NATIVE 33 32 __u64 utime; ··· 47 48 .task = &tsk, \ 48 49 .flags = 0, \ 49 50 .cpu = 0, \ 50 - .addr_limit = KERNEL_DS, \ 51 51 .preempt_count = INIT_PREEMPT_COUNT, \ 52 52 } 53 53
+6 -15
arch/ia64/include/asm/uaccess.h
··· 42 42 #include <asm/extable.h> 43 43 44 44 /* 45 - * For historical reasons, the following macros are grossly misnamed: 46 - */ 47 - #define KERNEL_DS ((mm_segment_t) { ~0UL }) /* cf. access_ok() */ 48 - #define USER_DS ((mm_segment_t) { TASK_SIZE-1 }) /* cf. access_ok() */ 49 - 50 - #define get_fs() (current_thread_info()->addr_limit) 51 - #define set_fs(x) (current_thread_info()->addr_limit = (x)) 52 - 53 - /* 54 - * When accessing user memory, we need to make sure the entire area really is in 55 - * user-level space. In order to do this efficiently, we make sure that the page at 56 - * address TASK_SIZE is never valid. We also need to make sure that the address doesn't 45 + * When accessing user memory, we need to make sure the entire area really is 46 + * in user-level space. We also need to make sure that the address doesn't 57 47 * point inside the virtually mapped linear page table. 58 48 */ 59 49 static inline int __access_ok(const void __user *p, unsigned long size) 60 50 { 51 + unsigned long limit = TASK_SIZE; 61 52 unsigned long addr = (unsigned long)p; 62 - unsigned long seg = get_fs().seg; 63 - return likely(addr <= seg) && 64 - (seg == KERNEL_DS.seg || likely(REGION_OFFSET(addr) < RGN_MAP_LIMIT)); 53 + 54 + return likely((size <= limit) && (addr <= (limit - size)) && 55 + likely(REGION_OFFSET(addr) < RGN_MAP_LIMIT)); 65 56 } 66 57 #define __access_ok __access_ok 67 58 #include <asm-generic/access_ok.h>
+39 -21
arch/ia64/kernel/unaligned.c
··· 749 749 } 750 750 } 751 751 752 + static int emulate_store(unsigned long ifa, void *val, int len, bool kernel_mode) 753 + { 754 + if (kernel_mode) 755 + return copy_to_kernel_nofault((void *)ifa, val, len); 756 + 757 + return copy_to_user((void __user *)ifa, val, len); 758 + } 759 + 760 + static int emulate_load(void *val, unsigned long ifa, int len, bool kernel_mode) 761 + { 762 + if (kernel_mode) 763 + return copy_from_kernel_nofault(val, (void *)ifa, len); 764 + 765 + return copy_from_user(val, (void __user *)ifa, len); 766 + } 752 767 753 768 static int 754 - emulate_load_int (unsigned long ifa, load_store_t ld, struct pt_regs *regs) 769 + emulate_load_int (unsigned long ifa, load_store_t ld, struct pt_regs *regs, 770 + bool kernel_mode) 755 771 { 756 772 unsigned int len = 1 << ld.x6_sz; 757 773 unsigned long val = 0; ··· 790 774 return -1; 791 775 } 792 776 /* this assumes little-endian byte-order: */ 793 - if (copy_from_user(&val, (void __user *) ifa, len)) 777 + if (emulate_load(&val, ifa, len, kernel_mode)) 794 778 return -1; 795 779 setreg(ld.r1, val, 0, regs); 796 780 ··· 888 872 } 889 873 890 874 static int 891 - emulate_store_int (unsigned long ifa, load_store_t ld, struct pt_regs *regs) 875 + emulate_store_int (unsigned long ifa, load_store_t ld, struct pt_regs *regs, 876 + bool kernel_mode) 892 877 { 893 878 unsigned long r2; 894 879 unsigned int len = 1 << ld.x6_sz; ··· 918 901 } 919 902 920 903 /* this assumes little-endian byte-order: */ 921 - if (copy_to_user((void __user *) ifa, &r2, len)) 904 + if (emulate_store(ifa, &r2, len, kernel_mode)) 922 905 return -1; 923 906 924 907 /* ··· 1038 1021 } 1039 1022 1040 1023 static int 1041 - emulate_load_floatpair (unsigned long ifa, load_store_t ld, struct pt_regs *regs) 1024 + emulate_load_floatpair (unsigned long ifa, load_store_t ld, struct pt_regs *regs, bool kernel_mode) 1042 1025 { 1043 1026 struct ia64_fpreg fpr_init[2]; 1044 1027 struct ia64_fpreg fpr_final[2]; ··· 1067 1050 * This assumes little-endian byte-order. Note that there is no "ldfpe" 1068 1051 * instruction: 1069 1052 */ 1070 - if (copy_from_user(&fpr_init[0], (void __user *) ifa, len) 1071 - || copy_from_user(&fpr_init[1], (void __user *) (ifa + len), len)) 1053 + if (emulate_load(&fpr_init[0], ifa, len, kernel_mode) 1054 + || emulate_load(&fpr_init[1], (ifa + len), len, kernel_mode)) 1072 1055 return -1; 1073 1056 1074 1057 DPRINT("ld.r1=%d ld.imm=%d x6_sz=%d\n", ld.r1, ld.imm, ld.x6_sz); ··· 1143 1126 1144 1127 1145 1128 static int 1146 - emulate_load_float (unsigned long ifa, load_store_t ld, struct pt_regs *regs) 1129 + emulate_load_float (unsigned long ifa, load_store_t ld, struct pt_regs *regs, 1130 + bool kernel_mode) 1147 1131 { 1148 1132 struct ia64_fpreg fpr_init; 1149 1133 struct ia64_fpreg fpr_final; ··· 1170 1152 * See comments in ldX for descriptions on how the various loads are handled. 1171 1153 */ 1172 1154 if (ld.x6_op != 0x2) { 1173 - if (copy_from_user(&fpr_init, (void __user *) ifa, len)) 1155 + if (emulate_load(&fpr_init, ifa, len, kernel_mode)) 1174 1156 return -1; 1175 1157 1176 1158 DPRINT("ld.r1=%d x6_sz=%d\n", ld.r1, ld.x6_sz); ··· 1220 1202 1221 1203 1222 1204 static int 1223 - emulate_store_float (unsigned long ifa, load_store_t ld, struct pt_regs *regs) 1205 + emulate_store_float (unsigned long ifa, load_store_t ld, struct pt_regs *regs, 1206 + bool kernel_mode) 1224 1207 { 1225 1208 struct ia64_fpreg fpr_init; 1226 1209 struct ia64_fpreg fpr_final; ··· 1263 1244 DDUMP("fpr_init =", &fpr_init, len); 1264 1245 DDUMP("fpr_final =", &fpr_final, len); 1265 1246 1266 - if (copy_to_user((void __user *) ifa, &fpr_final, len)) 1247 + if (emulate_store(ifa, &fpr_final, len, kernel_mode)) 1267 1248 return -1; 1268 1249 1269 1250 /* ··· 1314 1295 ia64_handle_unaligned (unsigned long ifa, struct pt_regs *regs) 1315 1296 { 1316 1297 struct ia64_psr *ipsr = ia64_psr(regs); 1317 - mm_segment_t old_fs = get_fs(); 1318 1298 unsigned long bundle[2]; 1319 1299 unsigned long opcode; 1320 1300 const struct exception_table_entry *eh = NULL; ··· 1322 1304 load_store_t insn; 1323 1305 } u; 1324 1306 int ret = -1; 1307 + bool kernel_mode = false; 1325 1308 1326 1309 if (ia64_psr(regs)->be) { 1327 1310 /* we don't support big-endian accesses */ ··· 1386 1367 if (unaligned_dump_stack) 1387 1368 dump_stack(); 1388 1369 } 1389 - set_fs(KERNEL_DS); 1370 + kernel_mode = true; 1390 1371 } 1391 1372 1392 1373 DPRINT("iip=%lx ifa=%lx isr=%lx (ei=%d, sp=%d)\n", 1393 1374 regs->cr_iip, ifa, regs->cr_ipsr, ipsr->ri, ipsr->it); 1394 1375 1395 - if (__copy_from_user(bundle, (void __user *) regs->cr_iip, 16)) 1376 + if (emulate_load(bundle, regs->cr_iip, 16, kernel_mode)) 1396 1377 goto failure; 1397 1378 1398 1379 /* ··· 1486 1467 case LDCCLR_IMM_OP: 1487 1468 case LDCNC_IMM_OP: 1488 1469 case LDCCLRACQ_IMM_OP: 1489 - ret = emulate_load_int(ifa, u.insn, regs); 1470 + ret = emulate_load_int(ifa, u.insn, regs, kernel_mode); 1490 1471 break; 1491 1472 1492 1473 case ST_OP: ··· 1497 1478 fallthrough; 1498 1479 case ST_IMM_OP: 1499 1480 case STREL_IMM_OP: 1500 - ret = emulate_store_int(ifa, u.insn, regs); 1481 + ret = emulate_store_int(ifa, u.insn, regs, kernel_mode); 1501 1482 break; 1502 1483 1503 1484 case LDF_OP: ··· 1505 1486 case LDFCCLR_OP: 1506 1487 case LDFCNC_OP: 1507 1488 if (u.insn.x) 1508 - ret = emulate_load_floatpair(ifa, u.insn, regs); 1489 + ret = emulate_load_floatpair(ifa, u.insn, regs, kernel_mode); 1509 1490 else 1510 - ret = emulate_load_float(ifa, u.insn, regs); 1491 + ret = emulate_load_float(ifa, u.insn, regs, kernel_mode); 1511 1492 break; 1512 1493 1513 1494 case LDF_IMM_OP: 1514 1495 case LDFA_IMM_OP: 1515 1496 case LDFCCLR_IMM_OP: 1516 1497 case LDFCNC_IMM_OP: 1517 - ret = emulate_load_float(ifa, u.insn, regs); 1498 + ret = emulate_load_float(ifa, u.insn, regs, kernel_mode); 1518 1499 break; 1519 1500 1520 1501 case STF_OP: 1521 1502 case STF_IMM_OP: 1522 - ret = emulate_store_float(ifa, u.insn, regs); 1503 + ret = emulate_store_float(ifa, u.insn, regs, kernel_mode); 1523 1504 break; 1524 1505 1525 1506 default: ··· 1540 1521 1541 1522 DPRINT("ipsr->ri=%d iip=%lx\n", ipsr->ri, regs->cr_iip); 1542 1523 done: 1543 - set_fs(old_fs); /* restore original address limit */ 1544 1524 return; 1545 1525 1546 1526 failure: