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

Merge master.kernel.org:/pub/scm/linux/kernel/git/davem/sparc-2.6

+376 -724
-2
arch/sparc/kernel/setup.c
··· 249 249 250 250 struct pt_regs fake_swapper_regs; 251 251 252 - extern void paging_init(void); 253 - 254 252 void __init setup_arch(char **cmdline_p) 255 253 { 256 254 int i;
+5 -2
arch/sparc64/kernel/head.S
··· 540 540 prom_tba: .xword 0 541 541 tlb_type: .word 0 /* Must NOT end up in BSS */ 542 542 .section ".fixup",#alloc,#execinstr 543 - .globl __ret_efault 543 + 544 + .globl __ret_efault, __retl_efault 544 545 __ret_efault: 545 546 ret 546 547 restore %g0, -EFAULT, %o0 547 - 548 + __retl_efault: 549 + retl 550 + mov -EFAULT, %o0
+11 -3
arch/sparc64/kernel/ptrace.c
··· 31 31 #include <asm/visasm.h> 32 32 #include <asm/spitfire.h> 33 33 #include <asm/page.h> 34 + #include <asm/cpudata.h> 34 35 35 36 /* Returning from ptrace is a bit tricky because the syscall return 36 37 * low level code assumes any value returned which is negative and ··· 133 132 if ((uaddr ^ (unsigned long) kaddr) & (1UL << 13)) { 134 133 unsigned long start = __pa(kaddr); 135 134 unsigned long end = start + len; 135 + unsigned long dcache_line_size; 136 + 137 + dcache_line_size = local_cpu_data().dcache_line_size; 136 138 137 139 if (tlb_type == spitfire) { 138 - for (; start < end; start += 32) 140 + for (; start < end; start += dcache_line_size) 139 141 spitfire_put_dcache_tag(start & 0x3fe0, 0x0); 140 142 } else { 141 - for (; start < end; start += 32) 143 + start &= ~(dcache_line_size - 1); 144 + for (; start < end; start += dcache_line_size) 142 145 __asm__ __volatile__( 143 146 "stxa %%g0, [%0] %1\n\t" 144 147 "membar #Sync" ··· 155 150 if (write && tlb_type == spitfire) { 156 151 unsigned long start = (unsigned long) kaddr; 157 152 unsigned long end = start + len; 153 + unsigned long icache_line_size; 158 154 159 - for (; start < end; start += 32) 155 + icache_line_size = local_cpu_data().icache_line_size; 156 + 157 + for (; start < end; start += icache_line_size) 160 158 flushi(start); 161 159 } 162 160 }
-21
arch/sparc64/kernel/setup.c
··· 464 464 } 465 465 } 466 466 467 - extern int prom_probe_memory(void); 468 - extern unsigned long start, end; 469 467 extern void panic_setup(char *, int *); 470 468 471 469 extern unsigned short root_flags; ··· 490 492 "' linux-.soft2 to .soft2"); 491 493 } 492 494 493 - extern void paging_init(void); 494 - 495 495 void __init setup_arch(char **cmdline_p) 496 496 { 497 - int i; 498 - 499 497 /* Initialize PROM console and command line. */ 500 498 *cmdline_p = prom_getbootargs(); 501 499 strcpy(saved_command_line, *cmdline_p); ··· 510 516 boot_flags_init(*cmdline_p); 511 517 512 518 idprom_init(); 513 - (void) prom_probe_memory(); 514 - 515 - phys_base = 0xffffffffffffffffUL; 516 - for (i = 0; sp_banks[i].num_bytes != 0; i++) { 517 - unsigned long top; 518 - 519 - if (sp_banks[i].base_addr < phys_base) 520 - phys_base = sp_banks[i].base_addr; 521 - top = sp_banks[i].base_addr + 522 - sp_banks[i].num_bytes; 523 - } 524 - pfn_base = phys_base >> PAGE_SHIFT; 525 - 526 - kern_base = (prom_boot_mapping_phys_low >> 22UL) << 22UL; 527 - kern_size = (unsigned long)&_end - (unsigned long)KERNBASE; 528 519 529 520 if (!root_flags) 530 521 root_mountflags &= ~MS_RDONLY;
+98 -72
arch/sparc64/kernel/sys32.S
··· 157 157 or %g2, %lo(__socketcall_table_begin), %g2 158 158 jmpl %g2 + %o0, %g0 159 159 nop 160 + do_einval: 161 + retl 162 + mov -EINVAL, %o0 160 163 161 - /* Each entry is exactly 32 bytes. */ 162 164 .align 32 163 165 __socketcall_table_begin: 166 + 167 + /* Each entry is exactly 32 bytes. */ 164 168 do_sys_socket: /* sys_socket(int, int, int) */ 165 - ldswa [%o1 + 0x0] %asi, %o0 169 + 1: ldswa [%o1 + 0x0] %asi, %o0 166 170 sethi %hi(sys_socket), %g1 167 - ldswa [%o1 + 0x8] %asi, %o2 171 + 2: ldswa [%o1 + 0x8] %asi, %o2 168 172 jmpl %g1 + %lo(sys_socket), %g0 169 - ldswa [%o1 + 0x4] %asi, %o1 173 + 3: ldswa [%o1 + 0x4] %asi, %o1 170 174 nop 171 175 nop 172 176 nop 173 177 do_sys_bind: /* sys_bind(int fd, struct sockaddr *, int) */ 174 - ldswa [%o1 + 0x0] %asi, %o0 178 + 4: ldswa [%o1 + 0x0] %asi, %o0 175 179 sethi %hi(sys_bind), %g1 176 - ldswa [%o1 + 0x8] %asi, %o2 180 + 5: ldswa [%o1 + 0x8] %asi, %o2 177 181 jmpl %g1 + %lo(sys_bind), %g0 178 - lduwa [%o1 + 0x4] %asi, %o1 182 + 6: lduwa [%o1 + 0x4] %asi, %o1 179 183 nop 180 184 nop 181 185 nop 182 186 do_sys_connect: /* sys_connect(int, struct sockaddr *, int) */ 183 - ldswa [%o1 + 0x0] %asi, %o0 187 + 7: ldswa [%o1 + 0x0] %asi, %o0 184 188 sethi %hi(sys_connect), %g1 185 - ldswa [%o1 + 0x8] %asi, %o2 189 + 8: ldswa [%o1 + 0x8] %asi, %o2 186 190 jmpl %g1 + %lo(sys_connect), %g0 187 - lduwa [%o1 + 0x4] %asi, %o1 191 + 9: lduwa [%o1 + 0x4] %asi, %o1 188 192 nop 189 193 nop 190 194 nop 191 195 do_sys_listen: /* sys_listen(int, int) */ 192 - ldswa [%o1 + 0x0] %asi, %o0 196 + 10: ldswa [%o1 + 0x0] %asi, %o0 193 197 sethi %hi(sys_listen), %g1 194 198 jmpl %g1 + %lo(sys_listen), %g0 195 - ldswa [%o1 + 0x4] %asi, %o1 199 + 11: ldswa [%o1 + 0x4] %asi, %o1 196 200 nop 197 201 nop 198 202 nop 199 203 nop 200 204 do_sys_accept: /* sys_accept(int, struct sockaddr *, int *) */ 201 - ldswa [%o1 + 0x0] %asi, %o0 205 + 12: ldswa [%o1 + 0x0] %asi, %o0 202 206 sethi %hi(sys_accept), %g1 203 - lduwa [%o1 + 0x8] %asi, %o2 207 + 13: lduwa [%o1 + 0x8] %asi, %o2 204 208 jmpl %g1 + %lo(sys_accept), %g0 205 - lduwa [%o1 + 0x4] %asi, %o1 209 + 14: lduwa [%o1 + 0x4] %asi, %o1 206 210 nop 207 211 nop 208 212 nop 209 213 do_sys_getsockname: /* sys_getsockname(int, struct sockaddr *, int *) */ 210 - ldswa [%o1 + 0x0] %asi, %o0 214 + 15: ldswa [%o1 + 0x0] %asi, %o0 211 215 sethi %hi(sys_getsockname), %g1 212 - lduwa [%o1 + 0x8] %asi, %o2 216 + 16: lduwa [%o1 + 0x8] %asi, %o2 213 217 jmpl %g1 + %lo(sys_getsockname), %g0 214 - lduwa [%o1 + 0x4] %asi, %o1 218 + 17: lduwa [%o1 + 0x4] %asi, %o1 215 219 nop 216 220 nop 217 221 nop 218 222 do_sys_getpeername: /* sys_getpeername(int, struct sockaddr *, int *) */ 219 - ldswa [%o1 + 0x0] %asi, %o0 223 + 18: ldswa [%o1 + 0x0] %asi, %o0 220 224 sethi %hi(sys_getpeername), %g1 221 - lduwa [%o1 + 0x8] %asi, %o2 225 + 19: lduwa [%o1 + 0x8] %asi, %o2 222 226 jmpl %g1 + %lo(sys_getpeername), %g0 223 - lduwa [%o1 + 0x4] %asi, %o1 227 + 20: lduwa [%o1 + 0x4] %asi, %o1 224 228 nop 225 229 nop 226 230 nop 227 231 do_sys_socketpair: /* sys_socketpair(int, int, int, int *) */ 228 - ldswa [%o1 + 0x0] %asi, %o0 232 + 21: ldswa [%o1 + 0x0] %asi, %o0 229 233 sethi %hi(sys_socketpair), %g1 230 - ldswa [%o1 + 0x8] %asi, %o2 231 - lduwa [%o1 + 0xc] %asi, %o3 234 + 22: ldswa [%o1 + 0x8] %asi, %o2 235 + 23: lduwa [%o1 + 0xc] %asi, %o3 232 236 jmpl %g1 + %lo(sys_socketpair), %g0 233 - ldswa [%o1 + 0x4] %asi, %o1 237 + 24: ldswa [%o1 + 0x4] %asi, %o1 234 238 nop 235 239 nop 236 240 do_sys_send: /* sys_send(int, void *, size_t, unsigned int) */ 237 - ldswa [%o1 + 0x0] %asi, %o0 241 + 25: ldswa [%o1 + 0x0] %asi, %o0 238 242 sethi %hi(sys_send), %g1 239 - lduwa [%o1 + 0x8] %asi, %o2 240 - lduwa [%o1 + 0xc] %asi, %o3 243 + 26: lduwa [%o1 + 0x8] %asi, %o2 244 + 27: lduwa [%o1 + 0xc] %asi, %o3 241 245 jmpl %g1 + %lo(sys_send), %g0 242 - lduwa [%o1 + 0x4] %asi, %o1 246 + 28: lduwa [%o1 + 0x4] %asi, %o1 243 247 nop 244 248 nop 245 249 do_sys_recv: /* sys_recv(int, void *, size_t, unsigned int) */ 246 - ldswa [%o1 + 0x0] %asi, %o0 250 + 29: ldswa [%o1 + 0x0] %asi, %o0 247 251 sethi %hi(sys_recv), %g1 248 - lduwa [%o1 + 0x8] %asi, %o2 249 - lduwa [%o1 + 0xc] %asi, %o3 252 + 30: lduwa [%o1 + 0x8] %asi, %o2 253 + 31: lduwa [%o1 + 0xc] %asi, %o3 250 254 jmpl %g1 + %lo(sys_recv), %g0 251 - lduwa [%o1 + 0x4] %asi, %o1 255 + 32: lduwa [%o1 + 0x4] %asi, %o1 252 256 nop 253 257 nop 254 258 do_sys_sendto: /* sys_sendto(int, u32, compat_size_t, unsigned int, u32, int) */ 255 - ldswa [%o1 + 0x0] %asi, %o0 259 + 33: ldswa [%o1 + 0x0] %asi, %o0 256 260 sethi %hi(sys_sendto), %g1 257 - lduwa [%o1 + 0x8] %asi, %o2 258 - lduwa [%o1 + 0xc] %asi, %o3 259 - lduwa [%o1 + 0x10] %asi, %o4 260 - ldswa [%o1 + 0x14] %asi, %o5 261 + 34: lduwa [%o1 + 0x8] %asi, %o2 262 + 35: lduwa [%o1 + 0xc] %asi, %o3 263 + 36: lduwa [%o1 + 0x10] %asi, %o4 264 + 37: ldswa [%o1 + 0x14] %asi, %o5 261 265 jmpl %g1 + %lo(sys_sendto), %g0 262 - lduwa [%o1 + 0x4] %asi, %o1 266 + 38: lduwa [%o1 + 0x4] %asi, %o1 263 267 do_sys_recvfrom: /* sys_recvfrom(int, u32, compat_size_t, unsigned int, u32, u32) */ 264 - ldswa [%o1 + 0x0] %asi, %o0 268 + 39: ldswa [%o1 + 0x0] %asi, %o0 265 269 sethi %hi(sys_recvfrom), %g1 266 - lduwa [%o1 + 0x8] %asi, %o2 267 - lduwa [%o1 + 0xc] %asi, %o3 268 - lduwa [%o1 + 0x10] %asi, %o4 269 - lduwa [%o1 + 0x14] %asi, %o5 270 + 40: lduwa [%o1 + 0x8] %asi, %o2 271 + 41: lduwa [%o1 + 0xc] %asi, %o3 272 + 42: lduwa [%o1 + 0x10] %asi, %o4 273 + 43: lduwa [%o1 + 0x14] %asi, %o5 270 274 jmpl %g1 + %lo(sys_recvfrom), %g0 271 - lduwa [%o1 + 0x4] %asi, %o1 275 + 44: lduwa [%o1 + 0x4] %asi, %o1 272 276 do_sys_shutdown: /* sys_shutdown(int, int) */ 273 - ldswa [%o1 + 0x0] %asi, %o0 277 + 45: ldswa [%o1 + 0x0] %asi, %o0 274 278 sethi %hi(sys_shutdown), %g1 275 279 jmpl %g1 + %lo(sys_shutdown), %g0 276 - ldswa [%o1 + 0x4] %asi, %o1 280 + 46: ldswa [%o1 + 0x4] %asi, %o1 277 281 nop 278 282 nop 279 283 nop 280 284 nop 281 285 do_sys_setsockopt: /* compat_sys_setsockopt(int, int, int, char *, int) */ 282 - ldswa [%o1 + 0x0] %asi, %o0 286 + 47: ldswa [%o1 + 0x0] %asi, %o0 283 287 sethi %hi(compat_sys_setsockopt), %g1 284 - ldswa [%o1 + 0x8] %asi, %o2 285 - lduwa [%o1 + 0xc] %asi, %o3 286 - ldswa [%o1 + 0x10] %asi, %o4 288 + 48: ldswa [%o1 + 0x8] %asi, %o2 289 + 49: lduwa [%o1 + 0xc] %asi, %o3 290 + 50: ldswa [%o1 + 0x10] %asi, %o4 287 291 jmpl %g1 + %lo(compat_sys_setsockopt), %g0 288 - ldswa [%o1 + 0x4] %asi, %o1 292 + 51: ldswa [%o1 + 0x4] %asi, %o1 289 293 nop 290 294 do_sys_getsockopt: /* compat_sys_getsockopt(int, int, int, u32, u32) */ 291 - ldswa [%o1 + 0x0] %asi, %o0 295 + 52: ldswa [%o1 + 0x0] %asi, %o0 292 296 sethi %hi(compat_sys_getsockopt), %g1 293 - ldswa [%o1 + 0x8] %asi, %o2 294 - lduwa [%o1 + 0xc] %asi, %o3 295 - lduwa [%o1 + 0x10] %asi, %o4 297 + 53: ldswa [%o1 + 0x8] %asi, %o2 298 + 54: lduwa [%o1 + 0xc] %asi, %o3 299 + 55: lduwa [%o1 + 0x10] %asi, %o4 296 300 jmpl %g1 + %lo(compat_sys_getsockopt), %g0 297 - ldswa [%o1 + 0x4] %asi, %o1 301 + 56: ldswa [%o1 + 0x4] %asi, %o1 298 302 nop 299 303 do_sys_sendmsg: /* compat_sys_sendmsg(int, struct compat_msghdr *, unsigned int) */ 300 - ldswa [%o1 + 0x0] %asi, %o0 304 + 57: ldswa [%o1 + 0x0] %asi, %o0 301 305 sethi %hi(compat_sys_sendmsg), %g1 302 - lduwa [%o1 + 0x8] %asi, %o2 306 + 58: lduwa [%o1 + 0x8] %asi, %o2 303 307 jmpl %g1 + %lo(compat_sys_sendmsg), %g0 304 - lduwa [%o1 + 0x4] %asi, %o1 308 + 59: lduwa [%o1 + 0x4] %asi, %o1 305 309 nop 306 310 nop 307 311 nop 308 312 do_sys_recvmsg: /* compat_sys_recvmsg(int, struct compat_msghdr *, unsigned int) */ 309 - ldswa [%o1 + 0x0] %asi, %o0 313 + 60: ldswa [%o1 + 0x0] %asi, %o0 310 314 sethi %hi(compat_sys_recvmsg), %g1 311 - lduwa [%o1 + 0x8] %asi, %o2 315 + 61: lduwa [%o1 + 0x8] %asi, %o2 312 316 jmpl %g1 + %lo(compat_sys_recvmsg), %g0 313 - lduwa [%o1 + 0x4] %asi, %o1 317 + 62: lduwa [%o1 + 0x4] %asi, %o1 314 318 nop 315 319 nop 316 320 nop 317 - __socketcall_table_end: 318 - 319 - do_einval: 320 - retl 321 - mov -EINVAL, %o0 322 - do_efault: 323 - retl 324 - mov -EFAULT, %o0 325 321 326 322 .section __ex_table 327 323 .align 4 328 - .word __socketcall_table_begin, 0, __socketcall_table_end, do_efault 324 + .word 1b, __retl_efault, 2b, __retl_efault 325 + .word 3b, __retl_efault, 4b, __retl_efault 326 + .word 5b, __retl_efault, 6b, __retl_efault 327 + .word 7b, __retl_efault, 8b, __retl_efault 328 + .word 9b, __retl_efault, 10b, __retl_efault 329 + .word 11b, __retl_efault, 12b, __retl_efault 330 + .word 13b, __retl_efault, 14b, __retl_efault 331 + .word 15b, __retl_efault, 16b, __retl_efault 332 + .word 17b, __retl_efault, 18b, __retl_efault 333 + .word 19b, __retl_efault, 20b, __retl_efault 334 + .word 21b, __retl_efault, 22b, __retl_efault 335 + .word 23b, __retl_efault, 24b, __retl_efault 336 + .word 25b, __retl_efault, 26b, __retl_efault 337 + .word 27b, __retl_efault, 28b, __retl_efault 338 + .word 29b, __retl_efault, 30b, __retl_efault 339 + .word 31b, __retl_efault, 32b, __retl_efault 340 + .word 33b, __retl_efault, 34b, __retl_efault 341 + .word 35b, __retl_efault, 36b, __retl_efault 342 + .word 37b, __retl_efault, 38b, __retl_efault 343 + .word 39b, __retl_efault, 40b, __retl_efault 344 + .word 41b, __retl_efault, 42b, __retl_efault 345 + .word 43b, __retl_efault, 44b, __retl_efault 346 + .word 45b, __retl_efault, 46b, __retl_efault 347 + .word 47b, __retl_efault, 48b, __retl_efault 348 + .word 49b, __retl_efault, 50b, __retl_efault 349 + .word 51b, __retl_efault, 52b, __retl_efault 350 + .word 53b, __retl_efault, 54b, __retl_efault 351 + .word 55b, __retl_efault, 56b, __retl_efault 352 + .word 57b, __retl_efault, 58b, __retl_efault 353 + .word 59b, __retl_efault, 60b, __retl_efault 354 + .word 61b, __retl_efault, 62b, __retl_efault 329 355 .previous
+20 -40
arch/sparc64/kernel/traps.c
··· 189 189 190 190 if (regs->tstate & TSTATE_PRIV) { 191 191 /* Test if this comes from uaccess places. */ 192 - unsigned long fixup; 193 - unsigned long g2 = regs->u_regs[UREG_G2]; 192 + const struct exception_table_entry *entry; 194 193 195 - if ((fixup = search_extables_range(regs->tpc, &g2))) { 196 - /* Ouch, somebody is trying ugly VM hole tricks on us... */ 194 + entry = search_exception_tables(regs->tpc); 195 + if (entry) { 196 + /* Ouch, somebody is trying VM hole tricks on us... */ 197 197 #ifdef DEBUG_EXCEPTIONS 198 198 printk("Exception: PC<%016lx> faddr<UNKNOWN>\n", regs->tpc); 199 - printk("EX_TABLE: insn<%016lx> fixup<%016lx> " 200 - "g2<%016lx>\n", regs->tpc, fixup, g2); 199 + printk("EX_TABLE: insn<%016lx> fixup<%016lx>\n", 200 + regs->tpc, entry->fixup); 201 201 #endif 202 - regs->tpc = fixup; 202 + regs->tpc = entry->fixup; 203 203 regs->tnpc = regs->tpc + 4; 204 - regs->u_regs[UREG_G2] = g2; 205 204 return; 206 205 } 207 206 /* Shit... */ ··· 757 758 ecache_flush_size = (2 * largest_size); 758 759 ecache_flush_linesize = smallest_linesize; 759 760 760 - /* Discover a physically contiguous chunk of physical 761 - * memory in 'sp_banks' of size ecache_flush_size calculated 762 - * above. Store the physical base of this area at 763 - * ecache_flush_physbase. 764 - */ 765 - for (node = 0; ; node++) { 766 - if (sp_banks[node].num_bytes == 0) 767 - break; 768 - if (sp_banks[node].num_bytes >= ecache_flush_size) { 769 - ecache_flush_physbase = sp_banks[node].base_addr; 770 - break; 771 - } 772 - } 761 + ecache_flush_physbase = find_ecache_flush_span(ecache_flush_size); 773 762 774 - /* Note: Zero would be a valid value of ecache_flush_physbase so 775 - * don't use that as the success test. :-) 776 - */ 777 - if (sp_banks[node].num_bytes == 0) { 763 + if (ecache_flush_physbase == ~0UL) { 778 764 prom_printf("cheetah_ecache_flush_init: Cannot find %d byte " 779 - "contiguous physical memory.\n", ecache_flush_size); 765 + "contiguous physical memory.\n", 766 + ecache_flush_size); 780 767 prom_halt(); 781 768 } 782 769 ··· 1331 1346 /* Return non-zero if PADDR is a valid physical memory address. */ 1332 1347 static int cheetah_check_main_memory(unsigned long paddr) 1333 1348 { 1334 - int i; 1349 + unsigned long vaddr = PAGE_OFFSET + paddr; 1335 1350 1336 - for (i = 0; ; i++) { 1337 - if (sp_banks[i].num_bytes == 0) 1338 - break; 1339 - if (paddr >= sp_banks[i].base_addr && 1340 - paddr < (sp_banks[i].base_addr + sp_banks[i].num_bytes)) 1341 - return 1; 1342 - } 1343 - return 0; 1351 + if (vaddr > (unsigned long) high_memory) 1352 + return 0; 1353 + 1354 + return kern_addr_valid(vaddr); 1344 1355 } 1345 1356 1346 1357 void cheetah_cee_handler(struct pt_regs *regs, unsigned long afsr, unsigned long afar) ··· 1591 1610 /* OK, usermode access. */ 1592 1611 recoverable = 1; 1593 1612 } else { 1594 - unsigned long g2 = regs->u_regs[UREG_G2]; 1595 - unsigned long fixup = search_extables_range(regs->tpc, &g2); 1613 + const struct exception_table_entry *entry; 1596 1614 1597 - if (fixup != 0UL) { 1615 + entry = search_exception_tables(regs->tpc); 1616 + if (entry) { 1598 1617 /* OK, kernel access to userspace. */ 1599 1618 recoverable = 1; 1600 1619 ··· 1613 1632 * recoverable condition. 1614 1633 */ 1615 1634 if (recoverable) { 1616 - regs->tpc = fixup; 1635 + regs->tpc = entry->fixup; 1617 1636 regs->tnpc = regs->tpc + 4; 1618 - regs->u_regs[UREG_G2] = g2; 1619 1637 } 1620 1638 } 1621 1639 }
+29 -36
arch/sparc64/kernel/una_asm.S
··· 6 6 7 7 .text 8 8 9 - kernel_unaligned_trap_fault: 10 - call kernel_mna_trap_fault 11 - nop 12 - retl 13 - nop 14 - .size kern_unaligned_trap_fault, .-kern_unaligned_trap_fault 15 - 16 9 .globl __do_int_store 17 10 __do_int_store: 18 11 rd %asi, %o4 ··· 44 51 0: 45 52 wr %o4, 0x0, %asi 46 53 retl 47 - nop 54 + mov 0, %o0 48 55 .size __do_int_store, .-__do_int_store 49 56 50 57 .section __ex_table 51 - .word 4b, kernel_unaligned_trap_fault 52 - .word 5b, kernel_unaligned_trap_fault 53 - .word 6b, kernel_unaligned_trap_fault 54 - .word 7b, kernel_unaligned_trap_fault 55 - .word 8b, kernel_unaligned_trap_fault 56 - .word 9b, kernel_unaligned_trap_fault 57 - .word 10b, kernel_unaligned_trap_fault 58 - .word 11b, kernel_unaligned_trap_fault 59 - .word 12b, kernel_unaligned_trap_fault 60 - .word 13b, kernel_unaligned_trap_fault 61 - .word 14b, kernel_unaligned_trap_fault 62 - .word 15b, kernel_unaligned_trap_fault 63 - .word 16b, kernel_unaligned_trap_fault 64 - .word 17b, kernel_unaligned_trap_fault 58 + .word 4b, __retl_efault 59 + .word 5b, __retl_efault 60 + .word 6b, __retl_efault 61 + .word 7b, __retl_efault 62 + .word 8b, __retl_efault 63 + .word 9b, __retl_efault 64 + .word 10b, __retl_efault 65 + .word 11b, __retl_efault 66 + .word 12b, __retl_efault 67 + .word 13b, __retl_efault 68 + .word 14b, __retl_efault 69 + .word 15b, __retl_efault 70 + .word 16b, __retl_efault 71 + .word 17b, __retl_efault 65 72 .previous 66 73 67 74 .globl do_int_load ··· 126 133 0: 127 134 wr %o5, 0x0, %asi 128 135 retl 129 - nop 136 + mov 0, %o0 130 137 .size __do_int_load, .-__do_int_load 131 138 132 139 .section __ex_table 133 - .word 4b, kernel_unaligned_trap_fault 134 - .word 5b, kernel_unaligned_trap_fault 135 - .word 6b, kernel_unaligned_trap_fault 136 - .word 7b, kernel_unaligned_trap_fault 137 - .word 8b, kernel_unaligned_trap_fault 138 - .word 9b, kernel_unaligned_trap_fault 139 - .word 10b, kernel_unaligned_trap_fault 140 - .word 11b, kernel_unaligned_trap_fault 141 - .word 12b, kernel_unaligned_trap_fault 142 - .word 13b, kernel_unaligned_trap_fault 143 - .word 14b, kernel_unaligned_trap_fault 144 - .word 15b, kernel_unaligned_trap_fault 145 - .word 16b, kernel_unaligned_trap_fault 140 + .word 4b, __retl_efault 141 + .word 5b, __retl_efault 142 + .word 6b, __retl_efault 143 + .word 7b, __retl_efault 144 + .word 8b, __retl_efault 145 + .word 9b, __retl_efault 146 + .word 10b, __retl_efault 147 + .word 11b, __retl_efault 148 + .word 12b, __retl_efault 149 + .word 13b, __retl_efault 150 + .word 14b, __retl_efault 151 + .word 15b, __retl_efault 152 + .word 16b, __retl_efault 146 153 .previous
+24 -21
arch/sparc64/kernel/unaligned.c
··· 180 180 die_if_kernel(str, regs); 181 181 } 182 182 183 - extern void do_int_load(unsigned long *dest_reg, int size, 184 - unsigned long *saddr, int is_signed, int asi); 183 + extern int do_int_load(unsigned long *dest_reg, int size, 184 + unsigned long *saddr, int is_signed, int asi); 185 185 186 - extern void __do_int_store(unsigned long *dst_addr, int size, 187 - unsigned long src_val, int asi); 186 + extern int __do_int_store(unsigned long *dst_addr, int size, 187 + unsigned long src_val, int asi); 188 188 189 - static inline void do_int_store(int reg_num, int size, unsigned long *dst_addr, 190 - struct pt_regs *regs, int asi, int orig_asi) 189 + static inline int do_int_store(int reg_num, int size, unsigned long *dst_addr, 190 + struct pt_regs *regs, int asi, int orig_asi) 191 191 { 192 192 unsigned long zero = 0; 193 193 unsigned long *src_val_p = &zero; ··· 219 219 break; 220 220 }; 221 221 } 222 - __do_int_store(dst_addr, size, src_val, asi); 222 + return __do_int_store(dst_addr, size, src_val, asi); 223 223 } 224 224 225 225 static inline void advance(struct pt_regs *regs) ··· 242 242 return !floating_point_load_or_store_p(insn); 243 243 } 244 244 245 - void kernel_mna_trap_fault(void) 245 + static void kernel_mna_trap_fault(void) 246 246 { 247 247 struct pt_regs *regs = current_thread_info()->kern_una_regs; 248 248 unsigned int insn = current_thread_info()->kern_una_insn; 249 - unsigned long g2 = regs->u_regs[UREG_G2]; 250 - unsigned long fixup = search_extables_range(regs->tpc, &g2); 249 + const struct exception_table_entry *entry; 251 250 252 - if (!fixup) { 251 + entry = search_exception_tables(regs->tpc); 252 + if (!entry) { 253 253 unsigned long address; 254 254 255 255 address = compute_effective_address(regs, insn, ··· 270 270 die_if_kernel("Oops", regs); 271 271 /* Not reached */ 272 272 } 273 - regs->tpc = fixup; 273 + regs->tpc = entry->fixup; 274 274 regs->tnpc = regs->tpc + 4; 275 - regs->u_regs [UREG_G2] = g2; 276 275 277 276 regs->tstate &= ~TSTATE_ASI; 278 277 regs->tstate |= (ASI_AIUS << 24UL); ··· 294 295 kernel_mna_trap_fault(); 295 296 } else { 296 297 unsigned long addr, *reg_addr; 297 - int orig_asi, asi; 298 + int orig_asi, asi, err; 298 299 299 300 addr = compute_effective_address(regs, insn, 300 301 ((insn >> 25) & 0x1f)); ··· 319 320 switch (dir) { 320 321 case load: 321 322 reg_addr = fetch_reg_addr(((insn>>25)&0x1f), regs); 322 - do_int_load(reg_addr, size, (unsigned long *) addr, 323 - decode_signedness(insn), asi); 324 - if (unlikely(asi != orig_asi)) { 323 + err = do_int_load(reg_addr, size, 324 + (unsigned long *) addr, 325 + decode_signedness(insn), asi); 326 + if (likely(!err) && unlikely(asi != orig_asi)) { 325 327 unsigned long val_in = *reg_addr; 326 328 switch (size) { 327 329 case 2: ··· 344 344 break; 345 345 346 346 case store: 347 - do_int_store(((insn>>25)&0x1f), size, 348 - (unsigned long *) addr, regs, 349 - asi, orig_asi); 347 + err = do_int_store(((insn>>25)&0x1f), size, 348 + (unsigned long *) addr, regs, 349 + asi, orig_asi); 350 350 break; 351 351 352 352 default: 353 353 panic("Impossible kernel unaligned trap."); 354 354 /* Not reached... */ 355 355 } 356 - advance(regs); 356 + if (unlikely(err)) 357 + kernel_mna_trap_fault(); 358 + else 359 + advance(regs); 357 360 } 358 361 } 359 362
+6 -10
arch/sparc64/lib/strncpy_from_user.S
··· 125 125 add %o2, %o3, %o0 126 126 .size __strncpy_from_user, .-__strncpy_from_user 127 127 128 - .section .fixup,#alloc,#execinstr 129 - .align 4 130 - 4: retl 131 - mov -EFAULT, %o0 132 - 133 128 .section __ex_table,#alloc 134 129 .align 4 135 - .word 60b, 4b 136 - .word 61b, 4b 137 - .word 62b, 4b 138 - .word 63b, 4b 139 - .word 64b, 4b 130 + .word 60b, __retl_efault 131 + .word 61b, __retl_efault 132 + .word 62b, __retl_efault 133 + .word 63b, __retl_efault 134 + .word 64b, __retl_efault 135 + .previous
+30 -35
arch/sparc64/lib/user_fixup.c
··· 11 11 12 12 /* Calculating the exact fault address when using 13 13 * block loads and stores can be very complicated. 14 + * 14 15 * Instead of trying to be clever and handling all 15 16 * of the cases, just fix things up simply here. 16 17 */ 17 18 19 + static unsigned long compute_size(unsigned long start, unsigned long size, unsigned long *offset) 20 + { 21 + unsigned long fault_addr = current_thread_info()->fault_address; 22 + unsigned long end = start + size; 23 + 24 + if (fault_addr < start || fault_addr >= end) { 25 + *offset = 0; 26 + } else { 27 + *offset = start - fault_addr; 28 + size = end - fault_addr; 29 + } 30 + return size; 31 + } 32 + 18 33 unsigned long copy_from_user_fixup(void *to, const void __user *from, unsigned long size) 19 34 { 20 - char *dst = to; 21 - const char __user *src = from; 35 + unsigned long offset; 22 36 23 - while (size) { 24 - if (__get_user(*dst, src)) 25 - break; 26 - dst++; 27 - src++; 28 - size--; 29 - } 30 - 31 - if (size) 32 - memset(dst, 0, size); 37 + size = compute_size((unsigned long) from, size, &offset); 38 + if (likely(size)) 39 + memset(to + offset, 0, size); 33 40 34 41 return size; 35 42 } 36 43 37 44 unsigned long copy_to_user_fixup(void __user *to, const void *from, unsigned long size) 38 45 { 39 - char __user *dst = to; 40 - const char *src = from; 46 + unsigned long offset; 41 47 42 - while (size) { 43 - if (__put_user(*src, dst)) 44 - break; 45 - dst++; 46 - src++; 47 - size--; 48 - } 49 - 50 - return size; 48 + return compute_size((unsigned long) to, size, &offset); 51 49 } 52 50 53 51 unsigned long copy_in_user_fixup(void __user *to, void __user *from, unsigned long size) 54 52 { 55 - char __user *dst = to; 56 - char __user *src = from; 53 + unsigned long fault_addr = current_thread_info()->fault_address; 54 + unsigned long start = (unsigned long) to; 55 + unsigned long end = start + size; 57 56 58 - while (size) { 59 - char tmp; 57 + if (fault_addr >= start && fault_addr < end) 58 + return end - fault_addr; 60 59 61 - if (__get_user(tmp, src)) 62 - break; 63 - if (__put_user(tmp, dst)) 64 - break; 65 - dst++; 66 - src++; 67 - size--; 68 - } 60 + start = (unsigned long) from; 61 + end = start + size; 62 + if (fault_addr >= start && fault_addr < end) 63 + return end - fault_addr; 69 64 70 65 return size; 71 66 }
+1 -1
arch/sparc64/mm/Makefile
··· 5 5 EXTRA_AFLAGS := -ansi 6 6 EXTRA_CFLAGS := -Werror 7 7 8 - obj-y := ultra.o tlb.o fault.o init.o generic.o extable.o 8 + obj-y := ultra.o tlb.o fault.o init.o generic.o 9 9 10 10 obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o
-80
arch/sparc64/mm/extable.c
··· 1 - /* 2 - * linux/arch/sparc64/mm/extable.c 3 - */ 4 - 5 - #include <linux/config.h> 6 - #include <linux/module.h> 7 - #include <asm/uaccess.h> 8 - 9 - extern const struct exception_table_entry __start___ex_table[]; 10 - extern const struct exception_table_entry __stop___ex_table[]; 11 - 12 - void sort_extable(struct exception_table_entry *start, 13 - struct exception_table_entry *finish) 14 - { 15 - } 16 - 17 - /* Caller knows they are in a range if ret->fixup == 0 */ 18 - const struct exception_table_entry * 19 - search_extable(const struct exception_table_entry *start, 20 - const struct exception_table_entry *last, 21 - unsigned long value) 22 - { 23 - const struct exception_table_entry *walk; 24 - 25 - /* Single insn entries are encoded as: 26 - * word 1: insn address 27 - * word 2: fixup code address 28 - * 29 - * Range entries are encoded as: 30 - * word 1: first insn address 31 - * word 2: 0 32 - * word 3: last insn address + 4 bytes 33 - * word 4: fixup code address 34 - * 35 - * See asm/uaccess.h for more details. 36 - */ 37 - 38 - /* 1. Try to find an exact match. */ 39 - for (walk = start; walk <= last; walk++) { 40 - if (walk->fixup == 0) { 41 - /* A range entry, skip both parts. */ 42 - walk++; 43 - continue; 44 - } 45 - 46 - if (walk->insn == value) 47 - return walk; 48 - } 49 - 50 - /* 2. Try to find a range match. */ 51 - for (walk = start; walk <= (last - 1); walk++) { 52 - if (walk->fixup) 53 - continue; 54 - 55 - if (walk[0].insn <= value && walk[1].insn > value) 56 - return walk; 57 - 58 - walk++; 59 - } 60 - 61 - return NULL; 62 - } 63 - 64 - /* Special extable search, which handles ranges. Returns fixup */ 65 - unsigned long search_extables_range(unsigned long addr, unsigned long *g2) 66 - { 67 - const struct exception_table_entry *entry; 68 - 69 - entry = search_exception_tables(addr); 70 - if (!entry) 71 - return 0; 72 - 73 - /* Inside range? Fix g2 and return correct fixup */ 74 - if (!entry->fixup) { 75 - *g2 = (addr - entry->insn) / 4; 76 - return (entry + 1)->fixup; 77 - } 78 - 79 - return entry->fixup; 80 - }
+5 -64
arch/sparc64/mm/fault.c
··· 32 32 33 33 #define ELEMENTS(arr) (sizeof (arr)/sizeof (arr[0])) 34 34 35 - extern struct sparc_phys_banks sp_banks[SPARC_PHYS_BANKS]; 36 - 37 35 /* 38 36 * To debug kernel to catch accesses to certain virtual/physical addresses. 39 37 * Mode = 0 selects physical watchpoints, mode = 1 selects virtual watchpoints. ··· 67 69 : /* no outputs */ 68 70 : "r" (lsubits), "i" (ASI_LSU_CONTROL) 69 71 : "memory"); 70 - } 71 - 72 - /* Nice, simple, prom library does all the sweating for us. ;) */ 73 - unsigned long __init prom_probe_memory (void) 74 - { 75 - register struct linux_mlist_p1275 *mlist; 76 - register unsigned long bytes, base_paddr, tally; 77 - register int i; 78 - 79 - i = 0; 80 - mlist = *prom_meminfo()->p1275_available; 81 - bytes = tally = mlist->num_bytes; 82 - base_paddr = mlist->start_adr; 83 - 84 - sp_banks[0].base_addr = base_paddr; 85 - sp_banks[0].num_bytes = bytes; 86 - 87 - while (mlist->theres_more != (void *) 0) { 88 - i++; 89 - mlist = mlist->theres_more; 90 - bytes = mlist->num_bytes; 91 - tally += bytes; 92 - if (i >= SPARC_PHYS_BANKS-1) { 93 - printk ("The machine has more banks than " 94 - "this kernel can support\n" 95 - "Increase the SPARC_PHYS_BANKS " 96 - "setting (currently %d)\n", 97 - SPARC_PHYS_BANKS); 98 - i = SPARC_PHYS_BANKS-1; 99 - break; 100 - } 101 - 102 - sp_banks[i].base_addr = mlist->start_adr; 103 - sp_banks[i].num_bytes = mlist->num_bytes; 104 - } 105 - 106 - i++; 107 - sp_banks[i].base_addr = 0xdeadbeefbeefdeadUL; 108 - sp_banks[i].num_bytes = 0; 109 - 110 - /* Now mask all bank sizes on a page boundary, it is all we can 111 - * use anyways. 112 - */ 113 - for (i = 0; sp_banks[i].num_bytes != 0; i++) 114 - sp_banks[i].num_bytes &= PAGE_MASK; 115 - 116 - return tally; 117 72 } 118 73 119 74 static void __kprobes unhandled_fault(unsigned long address, ··· 193 242 static void do_kernel_fault(struct pt_regs *regs, int si_code, int fault_code, 194 243 unsigned int insn, unsigned long address) 195 244 { 196 - unsigned long g2; 197 245 unsigned char asi = ASI_P; 198 246 199 247 if ((!insn) && (regs->tstate & TSTATE_PRIV)) ··· 223 273 } 224 274 } 225 275 226 - g2 = regs->u_regs[UREG_G2]; 227 - 228 276 /* Is this in ex_table? */ 229 277 if (regs->tstate & TSTATE_PRIV) { 230 - unsigned long fixup; 278 + const struct exception_table_entry *entry; 231 279 232 280 if (asi == ASI_P && (insn & 0xc0800000) == 0xc0800000) { 233 281 if (insn & 0x2000) ··· 236 288 237 289 /* Look in asi.h: All _S asis have LS bit set */ 238 290 if ((asi & 0x1) && 239 - (fixup = search_extables_range(regs->tpc, &g2))) { 240 - regs->tpc = fixup; 291 + (entry = search_exception_tables(regs->tpc))) { 292 + regs->tpc = entry->fixup; 241 293 regs->tnpc = regs->tpc + 4; 242 - regs->u_regs[UREG_G2] = g2; 243 294 return; 244 295 } 245 296 } else { ··· 408 461 } 409 462 410 463 up_read(&mm->mmap_sem); 411 - goto fault_done; 464 + return; 412 465 413 466 /* 414 467 * Something tried to access memory that isn't in our memory map.. ··· 420 473 421 474 handle_kernel_fault: 422 475 do_kernel_fault(regs, si_code, fault_code, insn, address); 423 - 424 - goto fault_done; 476 + return; 425 477 426 478 /* 427 479 * We ran out of memory, or some other thing happened to us that made ··· 451 505 /* Kernel mode? Handle exceptions or die */ 452 506 if (regs->tstate & TSTATE_PRIV) 453 507 goto handle_kernel_fault; 454 - 455 - fault_done: 456 - /* These values are no longer needed, clear them. */ 457 - set_thread_fault_code(0); 458 - current_thread_info()->fault_address = 0; 459 508 }
+130 -129
arch/sparc64/mm/init.c
··· 21 21 #include <linux/seq_file.h> 22 22 #include <linux/kprobes.h> 23 23 #include <linux/cache.h> 24 + #include <linux/sort.h> 24 25 25 26 #include <asm/head.h> 26 27 #include <asm/system.h> ··· 42 41 43 42 extern void device_scan(void); 44 43 45 - struct sparc_phys_banks sp_banks[SPARC_PHYS_BANKS]; 44 + #define MAX_BANKS 32 45 + 46 + static struct linux_prom64_registers pavail[MAX_BANKS] __initdata; 47 + static struct linux_prom64_registers pavail_rescan[MAX_BANKS] __initdata; 48 + static int pavail_ents __initdata; 49 + static int pavail_rescan_ents __initdata; 50 + 51 + static int cmp_p64(const void *a, const void *b) 52 + { 53 + const struct linux_prom64_registers *x = a, *y = b; 54 + 55 + if (x->phys_addr > y->phys_addr) 56 + return 1; 57 + if (x->phys_addr < y->phys_addr) 58 + return -1; 59 + return 0; 60 + } 61 + 62 + static void __init read_obp_memory(const char *property, 63 + struct linux_prom64_registers *regs, 64 + int *num_ents) 65 + { 66 + int node = prom_finddevice("/memory"); 67 + int prop_size = prom_getproplen(node, property); 68 + int ents, ret, i; 69 + 70 + ents = prop_size / sizeof(struct linux_prom64_registers); 71 + if (ents > MAX_BANKS) { 72 + prom_printf("The machine has more %s property entries than " 73 + "this kernel can support (%d).\n", 74 + property, MAX_BANKS); 75 + prom_halt(); 76 + } 77 + 78 + ret = prom_getproperty(node, property, (char *) regs, prop_size); 79 + if (ret == -1) { 80 + prom_printf("Couldn't get %s property from /memory.\n"); 81 + prom_halt(); 82 + } 83 + 84 + *num_ents = ents; 85 + 86 + /* Sanitize what we got from the firmware, by page aligning 87 + * everything. 88 + */ 89 + for (i = 0; i < ents; i++) { 90 + unsigned long base, size; 91 + 92 + base = regs[i].phys_addr; 93 + size = regs[i].reg_size; 94 + 95 + size &= PAGE_MASK; 96 + if (base & ~PAGE_MASK) { 97 + unsigned long new_base = PAGE_ALIGN(base); 98 + 99 + size -= new_base - base; 100 + if ((long) size < 0L) 101 + size = 0UL; 102 + base = new_base; 103 + } 104 + regs[i].phys_addr = base; 105 + regs[i].reg_size = size; 106 + } 107 + sort(regs, ents, sizeof(struct linux_prom64_registers), 108 + cmp_p64, NULL); 109 + } 46 110 47 111 unsigned long *sparc64_valid_addr_bitmap __read_mostly; 48 112 ··· 1272 1206 int i; 1273 1207 1274 1208 #ifdef CONFIG_DEBUG_BOOTMEM 1275 - prom_printf("bootmem_init: Scan sp_banks, "); 1209 + prom_printf("bootmem_init: Scan pavail, "); 1276 1210 #endif 1277 1211 1278 1212 bytes_avail = 0UL; 1279 - for (i = 0; sp_banks[i].num_bytes != 0; i++) { 1280 - end_of_phys_memory = sp_banks[i].base_addr + 1281 - sp_banks[i].num_bytes; 1282 - bytes_avail += sp_banks[i].num_bytes; 1213 + for (i = 0; i < pavail_ents; i++) { 1214 + end_of_phys_memory = pavail[i].phys_addr + 1215 + pavail[i].reg_size; 1216 + bytes_avail += pavail[i].reg_size; 1283 1217 if (cmdline_memory_size) { 1284 1218 if (bytes_avail > cmdline_memory_size) { 1285 1219 unsigned long slack = bytes_avail - cmdline_memory_size; ··· 1287 1221 bytes_avail -= slack; 1288 1222 end_of_phys_memory -= slack; 1289 1223 1290 - sp_banks[i].num_bytes -= slack; 1291 - if (sp_banks[i].num_bytes == 0) { 1292 - sp_banks[i].base_addr = 0xdeadbeef; 1224 + pavail[i].reg_size -= slack; 1225 + if ((long)pavail[i].reg_size <= 0L) { 1226 + pavail[i].phys_addr = 0xdeadbeefUL; 1227 + pavail[i].reg_size = 0UL; 1228 + pavail_ents = i; 1293 1229 } else { 1294 - sp_banks[i+1].num_bytes = 0; 1295 - sp_banks[i+1].base_addr = 0xdeadbeef; 1230 + pavail[i+1].reg_size = 0Ul; 1231 + pavail[i+1].phys_addr = 0xdeadbeefUL; 1232 + pavail_ents = i + 1; 1296 1233 } 1297 1234 break; 1298 1235 } ··· 1349 1280 /* Now register the available physical memory with the 1350 1281 * allocator. 1351 1282 */ 1352 - for (i = 0; sp_banks[i].num_bytes != 0; i++) { 1283 + for (i = 0; i < pavail_ents; i++) { 1353 1284 #ifdef CONFIG_DEBUG_BOOTMEM 1354 - prom_printf("free_bootmem(sp_banks:%d): base[%lx] size[%lx]\n", 1355 - i, sp_banks[i].base_addr, sp_banks[i].num_bytes); 1285 + prom_printf("free_bootmem(pavail:%d): base[%lx] size[%lx]\n", 1286 + i, pavail[i].phys_addr, pavail[i].reg_size); 1356 1287 #endif 1357 - free_bootmem(sp_banks[i].base_addr, sp_banks[i].num_bytes); 1288 + free_bootmem(pavail[i].phys_addr, pavail[i].reg_size); 1358 1289 } 1359 1290 1360 1291 #ifdef CONFIG_BLK_DEV_INITRD ··· 1403 1334 unsigned long alloc_bytes = 0UL; 1404 1335 1405 1336 if ((vstart & ~PAGE_MASK) || (vend & ~PAGE_MASK)) { 1406 - prom_printf("kernel_map: Unaligned sp_banks[%lx:%lx]\n", 1337 + prom_printf("kernel_map: Unaligned physmem[%lx:%lx]\n", 1407 1338 vstart, vend); 1408 1339 prom_halt(); 1409 1340 } ··· 1450 1381 return alloc_bytes; 1451 1382 } 1452 1383 1453 - extern struct linux_mlist_p1275 *prom_ptot_ptr; 1384 + static struct linux_prom64_registers pall[MAX_BANKS] __initdata; 1385 + static int pall_ents __initdata; 1386 + 1454 1387 extern unsigned int kvmap_linear_patch[1]; 1455 1388 1456 1389 static void __init kernel_physical_mapping_init(void) 1457 1390 { 1458 - struct linux_mlist_p1275 *p = prom_ptot_ptr; 1459 - unsigned long mem_alloced = 0UL; 1391 + unsigned long i, mem_alloced = 0UL; 1460 1392 1461 - while (p) { 1393 + read_obp_memory("reg", &pall[0], &pall_ents); 1394 + 1395 + for (i = 0; i < pall_ents; i++) { 1462 1396 unsigned long phys_start, phys_end; 1463 1397 1464 - phys_start = p->start_adr; 1465 - phys_end = phys_start + p->num_bytes; 1398 + phys_start = pall[i].phys_addr; 1399 + phys_end = phys_start + pall[i].reg_size; 1466 1400 mem_alloced += kernel_map_range(phys_start, phys_end, 1467 1401 PAGE_KERNEL); 1468 - 1469 - p = p->theres_more; 1470 1402 } 1471 1403 1472 1404 printk("Allocated %ld bytes for kernel page tables.\n", ··· 1495 1425 } 1496 1426 #endif 1497 1427 1428 + unsigned long __init find_ecache_flush_span(unsigned long size) 1429 + { 1430 + int i; 1431 + 1432 + for (i = 0; i < pavail_ents; i++) { 1433 + if (pavail[i].reg_size >= size) 1434 + return pavail[i].phys_addr; 1435 + } 1436 + 1437 + return ~0UL; 1438 + } 1439 + 1498 1440 /* paging_init() sets up the page tables */ 1499 1441 1500 1442 extern void cheetah_ecache_flush_init(void); ··· 1517 1435 void __init paging_init(void) 1518 1436 { 1519 1437 unsigned long end_pfn, pages_avail, shift; 1520 - unsigned long real_end; 1438 + unsigned long real_end, i; 1439 + 1440 + /* Find available physical memory... */ 1441 + read_obp_memory("available", &pavail[0], &pavail_ents); 1442 + 1443 + phys_base = 0xffffffffffffffffUL; 1444 + for (i = 0; i < pavail_ents; i++) 1445 + phys_base = min(phys_base, pavail[i].phys_addr); 1446 + 1447 + pfn_base = phys_base >> PAGE_SHIFT; 1448 + 1449 + kern_base = (prom_boot_mapping_phys_low >> 22UL) << 22UL; 1450 + kern_size = (unsigned long)&_end - (unsigned long)KERNBASE; 1521 1451 1522 1452 set_bit(0, mmu_context_bmap); 1523 1453 ··· 1601 1507 device_scan(); 1602 1508 } 1603 1509 1604 - /* Ok, it seems that the prom can allocate some more memory chunks 1605 - * as a side effect of some prom calls we perform during the 1606 - * boot sequence. My most likely theory is that it is from the 1607 - * prom_set_traptable() call, and OBP is allocating a scratchpad 1608 - * for saving client program register state etc. 1609 - */ 1610 - static void __init sort_memlist(struct linux_mlist_p1275 *thislist) 1611 - { 1612 - int swapi = 0; 1613 - int i, mitr; 1614 - unsigned long tmpaddr, tmpsize; 1615 - unsigned long lowest; 1616 - 1617 - for (i = 0; thislist[i].theres_more != 0; i++) { 1618 - lowest = thislist[i].start_adr; 1619 - for (mitr = i+1; thislist[mitr-1].theres_more != 0; mitr++) 1620 - if (thislist[mitr].start_adr < lowest) { 1621 - lowest = thislist[mitr].start_adr; 1622 - swapi = mitr; 1623 - } 1624 - if (lowest == thislist[i].start_adr) 1625 - continue; 1626 - tmpaddr = thislist[swapi].start_adr; 1627 - tmpsize = thislist[swapi].num_bytes; 1628 - for (mitr = swapi; mitr > i; mitr--) { 1629 - thislist[mitr].start_adr = thislist[mitr-1].start_adr; 1630 - thislist[mitr].num_bytes = thislist[mitr-1].num_bytes; 1631 - } 1632 - thislist[i].start_adr = tmpaddr; 1633 - thislist[i].num_bytes = tmpsize; 1634 - } 1635 - } 1636 - 1637 - void __init rescan_sp_banks(void) 1638 - { 1639 - struct linux_prom64_registers memlist[64]; 1640 - struct linux_mlist_p1275 avail[64], *mlist; 1641 - unsigned long bytes, base_paddr; 1642 - int num_regs, node = prom_finddevice("/memory"); 1643 - int i; 1644 - 1645 - num_regs = prom_getproperty(node, "available", 1646 - (char *) memlist, sizeof(memlist)); 1647 - num_regs = (num_regs / sizeof(struct linux_prom64_registers)); 1648 - for (i = 0; i < num_regs; i++) { 1649 - avail[i].start_adr = memlist[i].phys_addr; 1650 - avail[i].num_bytes = memlist[i].reg_size; 1651 - avail[i].theres_more = &avail[i + 1]; 1652 - } 1653 - avail[i - 1].theres_more = NULL; 1654 - sort_memlist(avail); 1655 - 1656 - mlist = &avail[0]; 1657 - i = 0; 1658 - bytes = mlist->num_bytes; 1659 - base_paddr = mlist->start_adr; 1660 - 1661 - sp_banks[0].base_addr = base_paddr; 1662 - sp_banks[0].num_bytes = bytes; 1663 - 1664 - while (mlist->theres_more != NULL){ 1665 - i++; 1666 - mlist = mlist->theres_more; 1667 - bytes = mlist->num_bytes; 1668 - if (i >= SPARC_PHYS_BANKS-1) { 1669 - printk ("The machine has more banks than " 1670 - "this kernel can support\n" 1671 - "Increase the SPARC_PHYS_BANKS " 1672 - "setting (currently %d)\n", 1673 - SPARC_PHYS_BANKS); 1674 - i = SPARC_PHYS_BANKS-1; 1675 - break; 1676 - } 1677 - 1678 - sp_banks[i].base_addr = mlist->start_adr; 1679 - sp_banks[i].num_bytes = mlist->num_bytes; 1680 - } 1681 - 1682 - i++; 1683 - sp_banks[i].base_addr = 0xdeadbeefbeefdeadUL; 1684 - sp_banks[i].num_bytes = 0; 1685 - 1686 - for (i = 0; sp_banks[i].num_bytes != 0; i++) 1687 - sp_banks[i].num_bytes &= PAGE_MASK; 1688 - } 1689 - 1690 1510 static void __init taint_real_pages(void) 1691 1511 { 1692 - struct sparc_phys_banks saved_sp_banks[SPARC_PHYS_BANKS]; 1693 1512 int i; 1694 1513 1695 - for (i = 0; i < SPARC_PHYS_BANKS; i++) { 1696 - saved_sp_banks[i].base_addr = 1697 - sp_banks[i].base_addr; 1698 - saved_sp_banks[i].num_bytes = 1699 - sp_banks[i].num_bytes; 1700 - } 1514 + read_obp_memory("available", &pavail_rescan[0], &pavail_rescan_ents); 1701 1515 1702 - rescan_sp_banks(); 1703 - 1704 - /* Find changes discovered in the sp_bank rescan and 1516 + /* Find changes discovered in the physmem available rescan and 1705 1517 * reserve the lost portions in the bootmem maps. 1706 1518 */ 1707 - for (i = 0; saved_sp_banks[i].num_bytes; i++) { 1519 + for (i = 0; i < pavail_ents; i++) { 1708 1520 unsigned long old_start, old_end; 1709 1521 1710 - old_start = saved_sp_banks[i].base_addr; 1522 + old_start = pavail[i].phys_addr; 1711 1523 old_end = old_start + 1712 - saved_sp_banks[i].num_bytes; 1524 + pavail[i].reg_size; 1713 1525 while (old_start < old_end) { 1714 1526 int n; 1715 1527 1716 - for (n = 0; sp_banks[n].num_bytes; n++) { 1528 + for (n = 0; pavail_rescan_ents; n++) { 1717 1529 unsigned long new_start, new_end; 1718 1530 1719 - new_start = sp_banks[n].base_addr; 1720 - new_end = new_start + sp_banks[n].num_bytes; 1531 + new_start = pavail_rescan[n].phys_addr; 1532 + new_end = new_start + 1533 + pavail_rescan[n].reg_size; 1721 1534 1722 1535 if (new_start <= old_start && 1723 1536 new_end >= (old_start + PAGE_SIZE)) { 1724 - set_bit (old_start >> 22, 1725 - sparc64_valid_addr_bitmap); 1537 + set_bit(old_start >> 22, 1538 + sparc64_valid_addr_bitmap); 1726 1539 goto do_next_page; 1727 1540 } 1728 1541 }
+1 -1
arch/sparc64/prom/Makefile
··· 6 6 EXTRA_AFLAGS := -ansi 7 7 EXTRA_CFLAGS := -Werror 8 8 9 - lib-y := bootstr.o devops.o init.o memory.o misc.o \ 9 + lib-y := bootstr.o devops.o init.o misc.o \ 10 10 tree.o console.o printf.o p1275.o cif.o
-3
arch/sparc64/prom/init.c
··· 27 27 * failure. It gets passed the pointer to the PROM vector. 28 28 */ 29 29 30 - extern void prom_meminit(void); 31 30 extern void prom_cif_init(void *, void *); 32 31 33 32 void __init prom_init(void *cif_handler, void *cif_stack) ··· 88 89 prom_prev = (ints[0] << 16) | (ints[1] << 8) | ints[2]; 89 90 90 91 printk ("PROMLIB: Sun IEEE Boot Prom %s\n", buffer + bufadjust); 91 - 92 - prom_meminit(); 93 92 94 93 /* Initialization successful. */ 95 94 return;
-152
arch/sparc64/prom/memory.c
··· 1 - /* $Id: memory.c,v 1.5 1999/08/31 06:55:04 davem Exp $ 2 - * memory.c: Prom routine for acquiring various bits of information 3 - * about RAM on the machine, both virtual and physical. 4 - * 5 - * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) 6 - * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz) 7 - */ 8 - 9 - #include <linux/kernel.h> 10 - #include <linux/init.h> 11 - 12 - #include <asm/openprom.h> 13 - #include <asm/oplib.h> 14 - 15 - /* This routine, for consistency, returns the ram parameters in the 16 - * V0 prom memory descriptor format. I choose this format because I 17 - * think it was the easiest to work with. I feel the religious 18 - * arguments now... ;) Also, I return the linked lists sorted to 19 - * prevent paging_init() upset stomach as I have not yet written 20 - * the pepto-bismol kernel module yet. 21 - */ 22 - 23 - struct linux_prom64_registers prom_reg_memlist[64]; 24 - struct linux_prom64_registers prom_reg_tmp[64]; 25 - 26 - struct linux_mlist_p1275 prom_phys_total[64]; 27 - struct linux_mlist_p1275 prom_prom_taken[64]; 28 - struct linux_mlist_p1275 prom_phys_avail[64]; 29 - 30 - struct linux_mlist_p1275 *prom_ptot_ptr = prom_phys_total; 31 - struct linux_mlist_p1275 *prom_ptak_ptr = prom_prom_taken; 32 - struct linux_mlist_p1275 *prom_pavl_ptr = prom_phys_avail; 33 - 34 - struct linux_mem_p1275 prom_memlist; 35 - 36 - 37 - /* Internal Prom library routine to sort a linux_mlist_p1275 memory 38 - * list. Used below in initialization. 39 - */ 40 - static void __init 41 - prom_sortmemlist(struct linux_mlist_p1275 *thislist) 42 - { 43 - int swapi = 0; 44 - int i, mitr; 45 - unsigned long tmpaddr, tmpsize; 46 - unsigned long lowest; 47 - 48 - for(i=0; thislist[i].theres_more; i++) { 49 - lowest = thislist[i].start_adr; 50 - for(mitr = i+1; thislist[mitr-1].theres_more; mitr++) 51 - if(thislist[mitr].start_adr < lowest) { 52 - lowest = thislist[mitr].start_adr; 53 - swapi = mitr; 54 - } 55 - if(lowest == thislist[i].start_adr) continue; 56 - tmpaddr = thislist[swapi].start_adr; 57 - tmpsize = thislist[swapi].num_bytes; 58 - for(mitr = swapi; mitr > i; mitr--) { 59 - thislist[mitr].start_adr = thislist[mitr-1].start_adr; 60 - thislist[mitr].num_bytes = thislist[mitr-1].num_bytes; 61 - } 62 - thislist[i].start_adr = tmpaddr; 63 - thislist[i].num_bytes = tmpsize; 64 - } 65 - } 66 - 67 - /* Initialize the memory lists based upon the prom version. */ 68 - void __init prom_meminit(void) 69 - { 70 - int node = 0; 71 - unsigned int iter, num_regs; 72 - 73 - node = prom_finddevice("/memory"); 74 - num_regs = prom_getproperty(node, "available", 75 - (char *) prom_reg_memlist, 76 - sizeof(prom_reg_memlist)); 77 - num_regs = (num_regs/sizeof(struct linux_prom64_registers)); 78 - for(iter=0; iter<num_regs; iter++) { 79 - prom_phys_avail[iter].start_adr = 80 - prom_reg_memlist[iter].phys_addr; 81 - prom_phys_avail[iter].num_bytes = 82 - prom_reg_memlist[iter].reg_size; 83 - prom_phys_avail[iter].theres_more = 84 - &prom_phys_avail[iter+1]; 85 - } 86 - prom_phys_avail[iter-1].theres_more = NULL; 87 - 88 - num_regs = prom_getproperty(node, "reg", 89 - (char *) prom_reg_memlist, 90 - sizeof(prom_reg_memlist)); 91 - num_regs = (num_regs/sizeof(struct linux_prom64_registers)); 92 - for(iter=0; iter<num_regs; iter++) { 93 - prom_phys_total[iter].start_adr = 94 - prom_reg_memlist[iter].phys_addr; 95 - prom_phys_total[iter].num_bytes = 96 - prom_reg_memlist[iter].reg_size; 97 - prom_phys_total[iter].theres_more = 98 - &prom_phys_total[iter+1]; 99 - } 100 - prom_phys_total[iter-1].theres_more = NULL; 101 - 102 - node = prom_finddevice("/virtual-memory"); 103 - num_regs = prom_getproperty(node, "available", 104 - (char *) prom_reg_memlist, 105 - sizeof(prom_reg_memlist)); 106 - num_regs = (num_regs/sizeof(struct linux_prom64_registers)); 107 - 108 - /* Convert available virtual areas to taken virtual 109 - * areas. First sort, then convert. 110 - */ 111 - for(iter=0; iter<num_regs; iter++) { 112 - prom_prom_taken[iter].start_adr = 113 - prom_reg_memlist[iter].phys_addr; 114 - prom_prom_taken[iter].num_bytes = 115 - prom_reg_memlist[iter].reg_size; 116 - prom_prom_taken[iter].theres_more = 117 - &prom_prom_taken[iter+1]; 118 - } 119 - prom_prom_taken[iter-1].theres_more = NULL; 120 - 121 - prom_sortmemlist(prom_prom_taken); 122 - 123 - /* Finally, convert. */ 124 - for(iter=0; iter<num_regs; iter++) { 125 - prom_prom_taken[iter].start_adr = 126 - prom_prom_taken[iter].start_adr + 127 - prom_prom_taken[iter].num_bytes; 128 - prom_prom_taken[iter].num_bytes = 129 - prom_prom_taken[iter+1].start_adr - 130 - prom_prom_taken[iter].start_adr; 131 - } 132 - prom_prom_taken[iter-1].num_bytes = 133 - -1UL - prom_prom_taken[iter-1].start_adr; 134 - 135 - /* Sort the other two lists. */ 136 - prom_sortmemlist(prom_phys_total); 137 - prom_sortmemlist(prom_phys_avail); 138 - 139 - /* Link all the lists into the top-level descriptor. */ 140 - prom_memlist.p1275_totphys=&prom_ptot_ptr; 141 - prom_memlist.p1275_prommap=&prom_ptak_ptr; 142 - prom_memlist.p1275_available=&prom_pavl_ptr; 143 - } 144 - 145 - /* This returns a pointer to our libraries internal p1275 format 146 - * memory descriptor. 147 - */ 148 - struct linux_mem_p1275 * 149 - prom_meminfo(void) 150 - { 151 - return &prom_memlist; 152 - }
+1 -1
drivers/video/aty/radeon_base.c
··· 475 475 */ 476 476 477 477 /* Flush PCI buffers ? */ 478 - tmp = INREG(DEVICE_ID); 478 + tmp = INREG16(DEVICE_ID); 479 479 480 480 local_irq_disable(); 481 481
+2
drivers/video/aty/radeonfb.h
··· 395 395 396 396 #define INREG8(addr) readb((rinfo->mmio_base)+addr) 397 397 #define OUTREG8(addr,val) writeb(val, (rinfo->mmio_base)+addr) 398 + #define INREG16(addr) readw((rinfo->mmio_base)+addr) 399 + #define OUTREG16(addr,val) writew(val, (rinfo->mmio_base)+addr) 398 400 #define INREG(addr) readl((rinfo->mmio_base)+addr) 399 401 #define OUTREG(addr,val) writel(val, (rinfo->mmio_base)+addr) 400 402
+2
include/asm-sparc/pgtable.h
··· 82 82 /* Top-level page directory */ 83 83 extern pgd_t swapper_pg_dir[1024]; 84 84 85 + extern void paging_init(void); 86 + 85 87 /* Page table for 0-4MB for everybody, on the Sparc this 86 88 * holds the same as on the i386. 87 89 */
+2 -2
include/asm-sparc64/openprom.h
··· 186 186 }; 187 187 188 188 struct linux_prom64_registers { 189 - long phys_addr; 190 - long reg_size; 189 + unsigned long phys_addr; 190 + unsigned long reg_size; 191 191 }; 192 192 193 193 struct linux_prom_irqs {
-14
include/asm-sparc64/oplib.h
··· 95 95 extern void prom_seek(int device_handle, unsigned int seek_hival, 96 96 unsigned int seek_lowval); 97 97 98 - /* Machine memory configuration routine. */ 99 - 100 - /* This function returns a V0 format memory descriptor table, it has three 101 - * entries. One for the total amount of physical ram on the machine, one 102 - * for the amount of physical ram available, and one describing the virtual 103 - * areas which are allocated by the prom. So, in a sense the physical 104 - * available is a calculation of the total physical minus the physical mapped 105 - * by the prom with virtual mappings. 106 - * 107 - * These lists are returned pre-sorted, this should make your life easier 108 - * since the prom itself is way too lazy to do such nice things. 109 - */ 110 - extern struct linux_mem_p1275 *prom_meminfo(void); 111 - 112 98 /* Miscellaneous routines, don't really fit in any category per se. */ 113 99 114 100 /* Reboot the machine with the command line passed. */
-17
include/asm-sparc64/page.h
··· 140 140 #define virt_to_phys __pa 141 141 #define phys_to_virt __va 142 142 143 - /* The following structure is used to hold the physical 144 - * memory configuration of the machine. This is filled in 145 - * probe_memory() and is later used by mem_init() to set up 146 - * mem_map[]. We statically allocate SPARC_PHYS_BANKS of 147 - * these structs, this is arbitrary. The entry after the 148 - * last valid one has num_bytes==0. 149 - */ 150 - 151 - struct sparc_phys_banks { 152 - unsigned long base_addr; 153 - unsigned long num_bytes; 154 - }; 155 - 156 - #define SPARC_PHYS_BANKS 32 157 - 158 - extern struct sparc_phys_banks sp_banks[SPARC_PHYS_BANKS]; 159 - 160 143 #endif /* !(__ASSEMBLY__) */ 161 144 162 145 #define VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | VM_EXEC | \
+3
include/asm-sparc64/pgtable.h
··· 341 341 extern pgd_t swapper_pg_dir[2048]; 342 342 extern pmd_t swapper_low_pmd_dir[2048]; 343 343 344 + extern void paging_init(void); 345 + extern unsigned long find_ecache_flush_span(unsigned long size); 346 + 344 347 /* These do nothing with the way I have things setup. */ 345 348 #define mmu_lockarea(vaddr, len) (vaddr) 346 349 #define mmu_unlockarea(vaddr, len) do { } while(0)
+6 -18
include/asm-sparc64/uaccess.h
··· 70 70 * with the main instruction path. This means when everything is well, 71 71 * we don't even have to jump over them. Further, they do not intrude 72 72 * on our cache or tlb entries. 73 - * 74 - * There is a special way how to put a range of potentially faulting 75 - * insns (like twenty ldd/std's with now intervening other instructions) 76 - * You specify address of first in insn and 0 in fixup and in the next 77 - * exception_table_entry you specify last potentially faulting insn + 1 78 - * and in fixup the routine which should handle the fault. 79 - * That fixup code will get 80 - * (faulting_insn_address - first_insn_in_the_range_address)/4 81 - * in %g2 (ie. index of the faulting instruction in the range). 82 73 */ 83 74 84 - struct exception_table_entry 85 - { 86 - unsigned insn, fixup; 75 + struct exception_table_entry { 76 + unsigned int insn, fixup; 87 77 }; 88 78 89 - /* Special exable search, which handles ranges. Returns fixup */ 90 - unsigned long search_extables_range(unsigned long addr, unsigned long *g2); 91 - 92 79 extern void __ret_efault(void); 80 + extern void __retl_efault(void); 93 81 94 82 /* Uh, these should become the main single-value transfer routines.. 95 83 * They automatically use the right size if we just have the right ··· 251 263 { 252 264 unsigned long ret = ___copy_from_user(to, from, size); 253 265 254 - if (ret) 266 + if (unlikely(ret)) 255 267 ret = copy_from_user_fixup(to, from, size); 256 268 return ret; 257 269 } ··· 267 279 { 268 280 unsigned long ret = ___copy_to_user(to, from, size); 269 281 270 - if (ret) 282 + if (unlikely(ret)) 271 283 ret = copy_to_user_fixup(to, from, size); 272 284 return ret; 273 285 } ··· 283 295 { 284 296 unsigned long ret = ___copy_in_user(to, from, size); 285 297 286 - if (ret) 298 + if (unlikely(ret)) 287 299 ret = copy_in_user_fixup(to, from, size); 288 300 return ret; 289 301 }