diff options
Diffstat (limited to 'arch/parisc')
-rw-r--r-- | arch/parisc/kernel/cache.c | 28 | ||||
-rw-r--r-- | arch/parisc/kernel/entry.S | 6 | ||||
-rw-r--r-- | arch/parisc/kernel/firmware.c | 46 | ||||
-rw-r--r-- | arch/parisc/kernel/module.c | 63 | ||||
-rw-r--r-- | arch/parisc/kernel/pdc_chassis.c | 109 | ||||
-rw-r--r-- | arch/parisc/kernel/ptrace.c | 8 | ||||
-rw-r--r-- | arch/parisc/kernel/real2.S | 9 | ||||
-rw-r--r-- | arch/parisc/kernel/setup.c | 5 | ||||
-rw-r--r-- | arch/parisc/kernel/signal.c | 20 | ||||
-rw-r--r-- | arch/parisc/kernel/syscall.S | 14 | ||||
-rw-r--r-- | arch/parisc/kernel/time.c | 18 | ||||
-rw-r--r-- | arch/parisc/kernel/traps.c | 84 | ||||
-rw-r--r-- | arch/parisc/kernel/unaligned.c | 18 |
13 files changed, 281 insertions, 147 deletions
diff --git a/arch/parisc/kernel/cache.c b/arch/parisc/kernel/cache.c index c057ad7605ba..bc7c4a4e26a1 100644 --- a/arch/parisc/kernel/cache.c +++ b/arch/parisc/kernel/cache.c | |||
@@ -97,15 +97,17 @@ update_mmu_cache(struct vm_area_struct *vma, unsigned long address, pte_t pte) | |||
97 | void | 97 | void |
98 | show_cache_info(struct seq_file *m) | 98 | show_cache_info(struct seq_file *m) |
99 | { | 99 | { |
100 | char buf[32]; | ||
101 | |||
100 | seq_printf(m, "I-cache\t\t: %ld KB\n", | 102 | seq_printf(m, "I-cache\t\t: %ld KB\n", |
101 | cache_info.ic_size/1024 ); | 103 | cache_info.ic_size/1024 ); |
102 | seq_printf(m, "D-cache\t\t: %ld KB (%s%s, %d-way associative)\n", | 104 | if (cache_info.dc_loop == 1) |
105 | snprintf(buf, 32, "%lu-way associative", cache_info.dc_loop); | ||
106 | seq_printf(m, "D-cache\t\t: %ld KB (%s%s, %s)\n", | ||
103 | cache_info.dc_size/1024, | 107 | cache_info.dc_size/1024, |
104 | (cache_info.dc_conf.cc_wt ? "WT":"WB"), | 108 | (cache_info.dc_conf.cc_wt ? "WT":"WB"), |
105 | (cache_info.dc_conf.cc_sh ? ", shared I/D":""), | 109 | (cache_info.dc_conf.cc_sh ? ", shared I/D":""), |
106 | (cache_info.dc_conf.cc_assoc) | 110 | ((cache_info.dc_loop == 1) ? "direct mapped" : buf)); |
107 | ); | ||
108 | |||
109 | seq_printf(m, "ITLB entries\t: %ld\n" "DTLB entries\t: %ld%s\n", | 111 | seq_printf(m, "ITLB entries\t: %ld\n" "DTLB entries\t: %ld%s\n", |
110 | cache_info.it_size, | 112 | cache_info.it_size, |
111 | cache_info.dt_size, | 113 | cache_info.dt_size, |
@@ -158,11 +160,11 @@ parisc_cache_init(void) | |||
158 | cache_info.dc_conf.cc_block, | 160 | cache_info.dc_conf.cc_block, |
159 | cache_info.dc_conf.cc_line, | 161 | cache_info.dc_conf.cc_line, |
160 | cache_info.dc_conf.cc_shift); | 162 | cache_info.dc_conf.cc_shift); |
161 | printk(" wt %d sh %d cst %d assoc %d\n", | 163 | printk(" wt %d sh %d cst %d hv %d\n", |
162 | cache_info.dc_conf.cc_wt, | 164 | cache_info.dc_conf.cc_wt, |
163 | cache_info.dc_conf.cc_sh, | 165 | cache_info.dc_conf.cc_sh, |
164 | cache_info.dc_conf.cc_cst, | 166 | cache_info.dc_conf.cc_cst, |
165 | cache_info.dc_conf.cc_assoc); | 167 | cache_info.dc_conf.cc_hv); |
166 | 168 | ||
167 | printk("IC base 0x%lx stride 0x%lx count 0x%lx loop 0x%lx\n", | 169 | printk("IC base 0x%lx stride 0x%lx count 0x%lx loop 0x%lx\n", |
168 | cache_info.ic_base, | 170 | cache_info.ic_base, |
@@ -176,11 +178,11 @@ parisc_cache_init(void) | |||
176 | cache_info.ic_conf.cc_block, | 178 | cache_info.ic_conf.cc_block, |
177 | cache_info.ic_conf.cc_line, | 179 | cache_info.ic_conf.cc_line, |
178 | cache_info.ic_conf.cc_shift); | 180 | cache_info.ic_conf.cc_shift); |
179 | printk(" wt %d sh %d cst %d assoc %d\n", | 181 | printk(" wt %d sh %d cst %d hv %d\n", |
180 | cache_info.ic_conf.cc_wt, | 182 | cache_info.ic_conf.cc_wt, |
181 | cache_info.ic_conf.cc_sh, | 183 | cache_info.ic_conf.cc_sh, |
182 | cache_info.ic_conf.cc_cst, | 184 | cache_info.ic_conf.cc_cst, |
183 | cache_info.ic_conf.cc_assoc); | 185 | cache_info.ic_conf.cc_hv); |
184 | 186 | ||
185 | printk("D-TLB conf: sh %d page %d cst %d aid %d pad1 %d \n", | 187 | printk("D-TLB conf: sh %d page %d cst %d aid %d pad1 %d \n", |
186 | cache_info.dt_conf.tc_sh, | 188 | cache_info.dt_conf.tc_sh, |
@@ -234,7 +236,8 @@ parisc_cache_init(void) | |||
234 | 236 | ||
235 | void disable_sr_hashing(void) | 237 | void disable_sr_hashing(void) |
236 | { | 238 | { |
237 | int srhash_type; | 239 | int srhash_type, retval; |
240 | unsigned long space_bits; | ||
238 | 241 | ||
239 | switch (boot_cpu_data.cpu_type) { | 242 | switch (boot_cpu_data.cpu_type) { |
240 | case pcx: /* We shouldn't get this far. setup.c should prevent it. */ | 243 | case pcx: /* We shouldn't get this far. setup.c should prevent it. */ |
@@ -260,6 +263,13 @@ void disable_sr_hashing(void) | |||
260 | } | 263 | } |
261 | 264 | ||
262 | disable_sr_hashing_asm(srhash_type); | 265 | disable_sr_hashing_asm(srhash_type); |
266 | |||
267 | retval = pdc_spaceid_bits(&space_bits); | ||
268 | /* If this procedure isn't implemented, don't panic. */ | ||
269 | if (retval < 0 && retval != PDC_BAD_OPTION) | ||
270 | panic("pdc_spaceid_bits call failed.\n"); | ||
271 | if (space_bits != 0) | ||
272 | panic("SpaceID hashing is still on!\n"); | ||
263 | } | 273 | } |
264 | 274 | ||
265 | void flush_dcache_page(struct page *page) | 275 | void flush_dcache_page(struct page *page) |
diff --git a/arch/parisc/kernel/entry.S b/arch/parisc/kernel/entry.S index d9e53cf0372b..630730c32a5a 100644 --- a/arch/parisc/kernel/entry.S +++ b/arch/parisc/kernel/entry.S | |||
@@ -1638,7 +1638,7 @@ dbit_trap_20w: | |||
1638 | load32 PA(pa_dbit_lock),t0 | 1638 | load32 PA(pa_dbit_lock),t0 |
1639 | 1639 | ||
1640 | dbit_spin_20w: | 1640 | dbit_spin_20w: |
1641 | ldcw 0(t0),t1 | 1641 | LDCW 0(t0),t1 |
1642 | cmpib,= 0,t1,dbit_spin_20w | 1642 | cmpib,= 0,t1,dbit_spin_20w |
1643 | nop | 1643 | nop |
1644 | 1644 | ||
@@ -1674,7 +1674,7 @@ dbit_trap_11: | |||
1674 | load32 PA(pa_dbit_lock),t0 | 1674 | load32 PA(pa_dbit_lock),t0 |
1675 | 1675 | ||
1676 | dbit_spin_11: | 1676 | dbit_spin_11: |
1677 | ldcw 0(t0),t1 | 1677 | LDCW 0(t0),t1 |
1678 | cmpib,= 0,t1,dbit_spin_11 | 1678 | cmpib,= 0,t1,dbit_spin_11 |
1679 | nop | 1679 | nop |
1680 | 1680 | ||
@@ -1714,7 +1714,7 @@ dbit_trap_20: | |||
1714 | load32 PA(pa_dbit_lock),t0 | 1714 | load32 PA(pa_dbit_lock),t0 |
1715 | 1715 | ||
1716 | dbit_spin_20: | 1716 | dbit_spin_20: |
1717 | ldcw 0(t0),t1 | 1717 | LDCW 0(t0),t1 |
1718 | cmpib,= 0,t1,dbit_spin_20 | 1718 | cmpib,= 0,t1,dbit_spin_20 |
1719 | nop | 1719 | nop |
1720 | 1720 | ||
diff --git a/arch/parisc/kernel/firmware.c b/arch/parisc/kernel/firmware.c index 2dc06b8e1817..4398d2a95789 100644 --- a/arch/parisc/kernel/firmware.c +++ b/arch/parisc/kernel/firmware.c | |||
@@ -11,7 +11,7 @@ | |||
11 | * Copyright 1999 The Puffin Group, (Alex deVries, David Kennedy) | 11 | * Copyright 1999 The Puffin Group, (Alex deVries, David Kennedy) |
12 | * Copyright 2003 Grant Grundler <grundler parisc-linux org> | 12 | * Copyright 2003 Grant Grundler <grundler parisc-linux org> |
13 | * Copyright 2003,2004 Ryan Bradetich <rbrad@parisc-linux.org> | 13 | * Copyright 2003,2004 Ryan Bradetich <rbrad@parisc-linux.org> |
14 | * Copyright 2004 Thibaut VARENE <varenet@parisc-linux.org> | 14 | * Copyright 2004,2006 Thibaut VARENE <varenet@parisc-linux.org> |
15 | * | 15 | * |
16 | * This program is free software; you can redistribute it and/or modify | 16 | * This program is free software; you can redistribute it and/or modify |
17 | * it under the terms of the GNU General Public License as published by | 17 | * it under the terms of the GNU General Public License as published by |
@@ -252,10 +252,8 @@ int pdc_pat_chassis_send_log(unsigned long state, unsigned long data) | |||
252 | #endif | 252 | #endif |
253 | 253 | ||
254 | /** | 254 | /** |
255 | * pdc_chassis_disp - Updates display | 255 | * pdc_chassis_disp - Updates chassis code |
256 | * @retval: -1 on error, 0 on success | 256 | * @retval: -1 on error, 0 on success |
257 | * | ||
258 | * Works on old PDC only (E class, others?) | ||
259 | */ | 257 | */ |
260 | int pdc_chassis_disp(unsigned long disp) | 258 | int pdc_chassis_disp(unsigned long disp) |
261 | { | 259 | { |
@@ -269,6 +267,22 @@ int pdc_chassis_disp(unsigned long disp) | |||
269 | } | 267 | } |
270 | 268 | ||
271 | /** | 269 | /** |
270 | * pdc_chassis_warn - Fetches chassis warnings | ||
271 | * @retval: -1 on error, 0 on success | ||
272 | */ | ||
273 | int pdc_chassis_warn(unsigned long *warn) | ||
274 | { | ||
275 | int retval = 0; | ||
276 | |||
277 | spin_lock_irq(&pdc_lock); | ||
278 | retval = mem_pdc_call(PDC_CHASSIS, PDC_CHASSIS_WARN, __pa(pdc_result)); | ||
279 | *warn = pdc_result[0]; | ||
280 | spin_unlock_irq(&pdc_lock); | ||
281 | |||
282 | return retval; | ||
283 | } | ||
284 | |||
285 | /** | ||
272 | * pdc_coproc_cfg - To identify coprocessors attached to the processor. | 286 | * pdc_coproc_cfg - To identify coprocessors attached to the processor. |
273 | * @pdc_coproc_info: Return buffer address. | 287 | * @pdc_coproc_info: Return buffer address. |
274 | * | 288 | * |
@@ -393,7 +407,9 @@ int pdc_model_info(struct pdc_model *model) | |||
393 | * pdc_model_sysmodel - Get the system model name. | 407 | * pdc_model_sysmodel - Get the system model name. |
394 | * @name: A char array of at least 81 characters. | 408 | * @name: A char array of at least 81 characters. |
395 | * | 409 | * |
396 | * Get system model name from PDC ROM (e.g. 9000/715 or 9000/778/B160L) | 410 | * Get system model name from PDC ROM (e.g. 9000/715 or 9000/778/B160L). |
411 | * Using OS_ID_HPUX will return the equivalent of the 'modelname' command | ||
412 | * on HP/UX. | ||
397 | */ | 413 | */ |
398 | int pdc_model_sysmodel(char *name) | 414 | int pdc_model_sysmodel(char *name) |
399 | { | 415 | { |
@@ -498,6 +514,26 @@ int pdc_cache_info(struct pdc_cache_info *cache_info) | |||
498 | return retval; | 514 | return retval; |
499 | } | 515 | } |
500 | 516 | ||
517 | /** | ||
518 | * pdc_spaceid_bits - Return whether Space ID hashing is turned on. | ||
519 | * @space_bits: Should be 0, if not, bad mojo! | ||
520 | * | ||
521 | * Returns information about Space ID hashing. | ||
522 | */ | ||
523 | int pdc_spaceid_bits(unsigned long *space_bits) | ||
524 | { | ||
525 | int retval; | ||
526 | |||
527 | spin_lock_irq(&pdc_lock); | ||
528 | pdc_result[0] = 0; | ||
529 | retval = mem_pdc_call(PDC_CACHE, PDC_CACHE_RET_SPID, __pa(pdc_result), 0); | ||
530 | convert_to_wide(pdc_result); | ||
531 | *space_bits = pdc_result[0]; | ||
532 | spin_unlock_irq(&pdc_lock); | ||
533 | |||
534 | return retval; | ||
535 | } | ||
536 | |||
501 | #ifndef CONFIG_PA20 | 537 | #ifndef CONFIG_PA20 |
502 | /** | 538 | /** |
503 | * pdc_btlb_info - Return block TLB information. | 539 | * pdc_btlb_info - Return block TLB information. |
diff --git a/arch/parisc/kernel/module.c b/arch/parisc/kernel/module.c index f27cfe4771b8..aee311884f3f 100644 --- a/arch/parisc/kernel/module.c +++ b/arch/parisc/kernel/module.c | |||
@@ -89,6 +89,12 @@ static inline int is_local(struct module *me, void *loc) | |||
89 | return is_init(me, loc) || is_core(me, loc); | 89 | return is_init(me, loc) || is_core(me, loc); |
90 | } | 90 | } |
91 | 91 | ||
92 | static inline int is_local_section(struct module *me, void *loc, void *dot) | ||
93 | { | ||
94 | return (is_init(me, loc) && is_init(me, dot)) || | ||
95 | (is_core(me, loc) && is_core(me, dot)); | ||
96 | } | ||
97 | |||
92 | 98 | ||
93 | #ifndef __LP64__ | 99 | #ifndef __LP64__ |
94 | struct got_entry { | 100 | struct got_entry { |
@@ -364,8 +370,14 @@ static Elf_Addr get_fdesc(struct module *me, unsigned long value) | |||
364 | } | 370 | } |
365 | #endif /* __LP64__ */ | 371 | #endif /* __LP64__ */ |
366 | 372 | ||
373 | enum elf_stub_type { | ||
374 | ELF_STUB_GOT, | ||
375 | ELF_STUB_MILLI, | ||
376 | ELF_STUB_DIRECT, | ||
377 | }; | ||
378 | |||
367 | static Elf_Addr get_stub(struct module *me, unsigned long value, long addend, | 379 | static Elf_Addr get_stub(struct module *me, unsigned long value, long addend, |
368 | int millicode, int init_section) | 380 | enum elf_stub_type stub_type, int init_section) |
369 | { | 381 | { |
370 | unsigned long i; | 382 | unsigned long i; |
371 | struct stub_entry *stub; | 383 | struct stub_entry *stub; |
@@ -396,7 +408,7 @@ static Elf_Addr get_stub(struct module *me, unsigned long value, long addend, | |||
396 | stub->insns[1] |= reassemble_17(rrsel(value, addend) / 4); | 408 | stub->insns[1] |= reassemble_17(rrsel(value, addend) / 4); |
397 | 409 | ||
398 | #else | 410 | #else |
399 | /* for 64-bit we have two kinds of stubs: | 411 | /* for 64-bit we have three kinds of stubs: |
400 | * for normal function calls: | 412 | * for normal function calls: |
401 | * ldd 0(%dp),%dp | 413 | * ldd 0(%dp),%dp |
402 | * ldd 10(%dp), %r1 | 414 | * ldd 10(%dp), %r1 |
@@ -408,18 +420,23 @@ static Elf_Addr get_stub(struct module *me, unsigned long value, long addend, | |||
408 | * ldo 0(%r1), %r1 | 420 | * ldo 0(%r1), %r1 |
409 | * ldd 10(%r1), %r1 | 421 | * ldd 10(%r1), %r1 |
410 | * bve,n (%r1) | 422 | * bve,n (%r1) |
423 | * | ||
424 | * for direct branches (jumps between different section of the | ||
425 | * same module): | ||
426 | * ldil 0, %r1 | ||
427 | * ldo 0(%r1), %r1 | ||
428 | * bve,n (%r1) | ||
411 | */ | 429 | */ |
412 | if (!millicode) | 430 | switch (stub_type) { |
413 | { | 431 | case ELF_STUB_GOT: |
414 | stub->insns[0] = 0x537b0000; /* ldd 0(%dp),%dp */ | 432 | stub->insns[0] = 0x537b0000; /* ldd 0(%dp),%dp */ |
415 | stub->insns[1] = 0x53610020; /* ldd 10(%dp),%r1 */ | 433 | stub->insns[1] = 0x53610020; /* ldd 10(%dp),%r1 */ |
416 | stub->insns[2] = 0xe820d000; /* bve (%r1) */ | 434 | stub->insns[2] = 0xe820d000; /* bve (%r1) */ |
417 | stub->insns[3] = 0x537b0030; /* ldd 18(%dp),%dp */ | 435 | stub->insns[3] = 0x537b0030; /* ldd 18(%dp),%dp */ |
418 | 436 | ||
419 | stub->insns[0] |= reassemble_14(get_got(me, value, addend) & 0x3fff); | 437 | stub->insns[0] |= reassemble_14(get_got(me, value, addend) & 0x3fff); |
420 | } | 438 | break; |
421 | else | 439 | case ELF_STUB_MILLI: |
422 | { | ||
423 | stub->insns[0] = 0x20200000; /* ldil 0,%r1 */ | 440 | stub->insns[0] = 0x20200000; /* ldil 0,%r1 */ |
424 | stub->insns[1] = 0x34210000; /* ldo 0(%r1), %r1 */ | 441 | stub->insns[1] = 0x34210000; /* ldo 0(%r1), %r1 */ |
425 | stub->insns[2] = 0x50210020; /* ldd 10(%r1),%r1 */ | 442 | stub->insns[2] = 0x50210020; /* ldd 10(%r1),%r1 */ |
@@ -427,7 +444,17 @@ static Elf_Addr get_stub(struct module *me, unsigned long value, long addend, | |||
427 | 444 | ||
428 | stub->insns[0] |= reassemble_21(lrsel(value, addend)); | 445 | stub->insns[0] |= reassemble_21(lrsel(value, addend)); |
429 | stub->insns[1] |= reassemble_14(rrsel(value, addend)); | 446 | stub->insns[1] |= reassemble_14(rrsel(value, addend)); |
447 | break; | ||
448 | case ELF_STUB_DIRECT: | ||
449 | stub->insns[0] = 0x20200000; /* ldil 0,%r1 */ | ||
450 | stub->insns[1] = 0x34210000; /* ldo 0(%r1), %r1 */ | ||
451 | stub->insns[2] = 0xe820d002; /* bve,n (%r1) */ | ||
452 | |||
453 | stub->insns[0] |= reassemble_21(lrsel(value, addend)); | ||
454 | stub->insns[1] |= reassemble_14(rrsel(value, addend)); | ||
455 | break; | ||
430 | } | 456 | } |
457 | |||
431 | #endif | 458 | #endif |
432 | 459 | ||
433 | return (Elf_Addr)stub; | 460 | return (Elf_Addr)stub; |
@@ -539,14 +566,14 @@ int apply_relocate_add(Elf_Shdr *sechdrs, | |||
539 | break; | 566 | break; |
540 | case R_PARISC_PCREL17F: | 567 | case R_PARISC_PCREL17F: |
541 | /* 17-bit PC relative address */ | 568 | /* 17-bit PC relative address */ |
542 | val = get_stub(me, val, addend, 0, is_init(me, loc)); | 569 | val = get_stub(me, val, addend, ELF_STUB_GOT, is_init(me, loc)); |
543 | val = (val - dot - 8)/4; | 570 | val = (val - dot - 8)/4; |
544 | CHECK_RELOC(val, 17) | 571 | CHECK_RELOC(val, 17) |
545 | *loc = (*loc & ~0x1f1ffd) | reassemble_17(val); | 572 | *loc = (*loc & ~0x1f1ffd) | reassemble_17(val); |
546 | break; | 573 | break; |
547 | case R_PARISC_PCREL22F: | 574 | case R_PARISC_PCREL22F: |
548 | /* 22-bit PC relative address; only defined for pa20 */ | 575 | /* 22-bit PC relative address; only defined for pa20 */ |
549 | val = get_stub(me, val, addend, 0, is_init(me, loc)); | 576 | val = get_stub(me, val, addend, ELF_STUB_GOT, is_init(me, loc)); |
550 | DEBUGP("STUB FOR %s loc %lx+%lx at %lx\n", | 577 | DEBUGP("STUB FOR %s loc %lx+%lx at %lx\n", |
551 | strtab + sym->st_name, (unsigned long)loc, addend, | 578 | strtab + sym->st_name, (unsigned long)loc, addend, |
552 | val) | 579 | val) |
@@ -643,13 +670,23 @@ int apply_relocate_add(Elf_Shdr *sechdrs, | |||
643 | strtab + sym->st_name, | 670 | strtab + sym->st_name, |
644 | loc, val); | 671 | loc, val); |
645 | /* can we reach it locally? */ | 672 | /* can we reach it locally? */ |
646 | if(!is_local(me, (void *)val)) { | 673 | if(!is_local_section(me, (void *)val, (void *)dot)) { |
647 | if (strncmp(strtab + sym->st_name, "$$", 2) | 674 | |
675 | if (is_local(me, (void *)val)) | ||
676 | /* this is the case where the | ||
677 | * symbol is local to the | ||
678 | * module, but in a different | ||
679 | * section, so stub the jump | ||
680 | * in case it's more than 22 | ||
681 | * bits away */ | ||
682 | val = get_stub(me, val, addend, ELF_STUB_DIRECT, | ||
683 | is_init(me, loc)); | ||
684 | else if (strncmp(strtab + sym->st_name, "$$", 2) | ||
648 | == 0) | 685 | == 0) |
649 | val = get_stub(me, val, addend, 1, | 686 | val = get_stub(me, val, addend, ELF_STUB_MILLI, |
650 | is_init(me, loc)); | 687 | is_init(me, loc)); |
651 | else | 688 | else |
652 | val = get_stub(me, val, addend, 0, | 689 | val = get_stub(me, val, addend, ELF_STUB_GOT, |
653 | is_init(me, loc)); | 690 | is_init(me, loc)); |
654 | } | 691 | } |
655 | DEBUGP("STUB FOR %s loc %lx, val %lx+%lx at %lx\n", | 692 | DEBUGP("STUB FOR %s loc %lx, val %lx+%lx at %lx\n", |
diff --git a/arch/parisc/kernel/pdc_chassis.c b/arch/parisc/kernel/pdc_chassis.c index a45e2e2ffd9f..d47ba1aa8253 100644 --- a/arch/parisc/kernel/pdc_chassis.c +++ b/arch/parisc/kernel/pdc_chassis.c | |||
@@ -1,8 +1,8 @@ | |||
1 | /* | 1 | /* |
2 | * interfaces to log Chassis Codes via PDC (firmware) | 2 | * interfaces to Chassis Codes via PDC (firmware) |
3 | * | 3 | * |
4 | * Copyright (C) 2002 Laurent Canet <canetl@esiee.fr> | 4 | * Copyright (C) 2002 Laurent Canet <canetl@esiee.fr> |
5 | * Copyright (C) 2002-2004 Thibaut VARENE <varenet@parisc-linux.org> | 5 | * Copyright (C) 2002-2006 Thibaut VARENE <varenet@parisc-linux.org> |
6 | * | 6 | * |
7 | * This program is free software; you can redistribute it and/or modify | 7 | * This program is free software; you can redistribute it and/or modify |
8 | * it under the terms of the GNU General Public License, version 2, as | 8 | * it under the terms of the GNU General Public License, version 2, as |
@@ -16,6 +16,10 @@ | |||
16 | * You should have received a copy of the GNU General Public License | 16 | * You should have received a copy of the GNU General Public License |
17 | * along with this program; if not, write to the Free Software | 17 | * along with this program; if not, write to the Free Software |
18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
19 | * | ||
20 | * TODO: poll chassis warns, trigger (configurable) machine shutdown when | ||
21 | * needed. | ||
22 | * Find out how to get Chassis warnings out of PAT boxes? | ||
19 | */ | 23 | */ |
20 | 24 | ||
21 | #undef PDC_CHASSIS_DEBUG | 25 | #undef PDC_CHASSIS_DEBUG |
@@ -30,15 +34,16 @@ | |||
30 | #include <linux/reboot.h> | 34 | #include <linux/reboot.h> |
31 | #include <linux/notifier.h> | 35 | #include <linux/notifier.h> |
32 | #include <linux/cache.h> | 36 | #include <linux/cache.h> |
37 | #include <linux/proc_fs.h> | ||
33 | 38 | ||
34 | #include <asm/pdc_chassis.h> | 39 | #include <asm/pdc_chassis.h> |
35 | #include <asm/processor.h> | 40 | #include <asm/processor.h> |
36 | #include <asm/pdc.h> | 41 | #include <asm/pdc.h> |
37 | #include <asm/pdcpat.h> | 42 | #include <asm/pdcpat.h> |
38 | 43 | ||
44 | #define PDC_CHASSIS_VER "0.05" | ||
39 | 45 | ||
40 | #ifdef CONFIG_PDC_CHASSIS | 46 | #ifdef CONFIG_PDC_CHASSIS |
41 | static int pdc_chassis_old __read_mostly = 0; | ||
42 | static unsigned int pdc_chassis_enabled __read_mostly = 1; | 47 | static unsigned int pdc_chassis_enabled __read_mostly = 1; |
43 | 48 | ||
44 | 49 | ||
@@ -64,7 +69,7 @@ __setup("pdcchassis=", pdc_chassis_setup); | |||
64 | * Currently, only E class and A180 are known to work with this. | 69 | * Currently, only E class and A180 are known to work with this. |
65 | * Inspired by Christoph Plattner | 70 | * Inspired by Christoph Plattner |
66 | */ | 71 | */ |
67 | 72 | #if 0 | |
68 | static void __init pdc_chassis_checkold(void) | 73 | static void __init pdc_chassis_checkold(void) |
69 | { | 74 | { |
70 | switch(CPU_HVERSION) { | 75 | switch(CPU_HVERSION) { |
@@ -73,7 +78,6 @@ static void __init pdc_chassis_checkold(void) | |||
73 | case 0x482: /* E45 */ | 78 | case 0x482: /* E45 */ |
74 | case 0x483: /* E55 */ | 79 | case 0x483: /* E55 */ |
75 | case 0x516: /* A180 */ | 80 | case 0x516: /* A180 */ |
76 | pdc_chassis_old = 1; | ||
77 | break; | 81 | break; |
78 | 82 | ||
79 | default: | 83 | default: |
@@ -81,7 +85,7 @@ static void __init pdc_chassis_checkold(void) | |||
81 | } | 85 | } |
82 | DPRINTK(KERN_DEBUG "%s: pdc_chassis_checkold(); pdc_chassis_old = %d\n", __FILE__, pdc_chassis_old); | 86 | DPRINTK(KERN_DEBUG "%s: pdc_chassis_checkold(); pdc_chassis_old = %d\n", __FILE__, pdc_chassis_old); |
83 | } | 87 | } |
84 | 88 | #endif | |
85 | 89 | ||
86 | /** | 90 | /** |
87 | * pdc_chassis_panic_event() - Called by the panic handler. | 91 | * pdc_chassis_panic_event() - Called by the panic handler. |
@@ -131,30 +135,20 @@ static struct notifier_block pdc_chassis_reboot_block = { | |||
131 | void __init parisc_pdc_chassis_init(void) | 135 | void __init parisc_pdc_chassis_init(void) |
132 | { | 136 | { |
133 | #ifdef CONFIG_PDC_CHASSIS | 137 | #ifdef CONFIG_PDC_CHASSIS |
134 | int handle = 0; | ||
135 | if (likely(pdc_chassis_enabled)) { | 138 | if (likely(pdc_chassis_enabled)) { |
136 | DPRINTK(KERN_DEBUG "%s: parisc_pdc_chassis_init()\n", __FILE__); | 139 | DPRINTK(KERN_DEBUG "%s: parisc_pdc_chassis_init()\n", __FILE__); |
137 | 140 | ||
138 | /* Let see if we have something to handle... */ | 141 | /* Let see if we have something to handle... */ |
139 | /* Check for PDC_PAT or old LED Panel */ | 142 | printk(KERN_INFO "Enabling %s chassis codes support v%s\n", |
140 | pdc_chassis_checkold(); | 143 | is_pdc_pat() ? "PDC_PAT" : "regular", |
141 | if (is_pdc_pat()) { | 144 | PDC_CHASSIS_VER); |
142 | printk(KERN_INFO "Enabling PDC_PAT chassis codes support.\n"); | 145 | |
143 | handle = 1; | 146 | /* initialize panic notifier chain */ |
144 | } | 147 | atomic_notifier_chain_register(&panic_notifier_list, |
145 | else if (unlikely(pdc_chassis_old)) { | 148 | &pdc_chassis_panic_block); |
146 | printk(KERN_INFO "Enabling old style chassis LED panel support.\n"); | 149 | |
147 | handle = 1; | 150 | /* initialize reboot notifier chain */ |
148 | } | 151 | register_reboot_notifier(&pdc_chassis_reboot_block); |
149 | |||
150 | if (handle) { | ||
151 | /* initialize panic notifier chain */ | ||
152 | atomic_notifier_chain_register(&panic_notifier_list, | ||
153 | &pdc_chassis_panic_block); | ||
154 | |||
155 | /* initialize reboot notifier chain */ | ||
156 | register_reboot_notifier(&pdc_chassis_reboot_block); | ||
157 | } | ||
158 | } | 152 | } |
159 | #endif /* CONFIG_PDC_CHASSIS */ | 153 | #endif /* CONFIG_PDC_CHASSIS */ |
160 | } | 154 | } |
@@ -215,9 +209,12 @@ int pdc_chassis_send_status(int message) | |||
215 | } | 209 | } |
216 | } else retval = -1; | 210 | } else retval = -1; |
217 | #else | 211 | #else |
218 | if (unlikely(pdc_chassis_old)) { | 212 | if (1) { |
219 | switch (message) { | 213 | switch (message) { |
220 | case PDC_CHASSIS_DIRECT_BSTART: | 214 | case PDC_CHASSIS_DIRECT_BSTART: |
215 | retval = pdc_chassis_disp(PDC_CHASSIS_DISP_DATA(OSTAT_INIT)); | ||
216 | break; | ||
217 | |||
221 | case PDC_CHASSIS_DIRECT_BCOMPLETE: | 218 | case PDC_CHASSIS_DIRECT_BCOMPLETE: |
222 | retval = pdc_chassis_disp(PDC_CHASSIS_DISP_DATA(OSTAT_RUN)); | 219 | retval = pdc_chassis_disp(PDC_CHASSIS_DISP_DATA(OSTAT_RUN)); |
223 | break; | 220 | break; |
@@ -244,3 +241,61 @@ int pdc_chassis_send_status(int message) | |||
244 | #endif /* CONFIG_PDC_CHASSIS */ | 241 | #endif /* CONFIG_PDC_CHASSIS */ |
245 | return retval; | 242 | return retval; |
246 | } | 243 | } |
244 | |||
245 | #ifdef CONFIG_PDC_CHASSIS_WARN | ||
246 | #ifdef CONFIG_PROC_FS | ||
247 | static int pdc_chassis_warn_pread(char *page, char **start, off_t off, | ||
248 | int count, int *eof, void *data) | ||
249 | { | ||
250 | char *out = page; | ||
251 | int len, ret; | ||
252 | unsigned long warn; | ||
253 | u32 warnreg; | ||
254 | |||
255 | ret = pdc_chassis_warn(&warn); | ||
256 | if (ret != PDC_OK) | ||
257 | return -EIO; | ||
258 | |||
259 | warnreg = (warn & 0xFFFFFFFF); | ||
260 | |||
261 | if ((warnreg >> 24) & 0xFF) | ||
262 | out += sprintf(out, "Chassis component failure! (eg fan or PSU): 0x%.2x\n", ((warnreg >> 24) & 0xFF)); | ||
263 | |||
264 | out += sprintf(out, "Battery: %s\n", (warnreg & 0x04) ? "Low!" : "OK"); | ||
265 | out += sprintf(out, "Temp low: %s\n", (warnreg & 0x02) ? "Exceeded!" : "OK"); | ||
266 | out += sprintf(out, "Temp mid: %s\n", (warnreg & 0x01) ? "Exceeded!" : "OK"); | ||
267 | |||
268 | len = out - page - off; | ||
269 | if (len < count) { | ||
270 | *eof = 1; | ||
271 | if (len <= 0) return 0; | ||
272 | } else { | ||
273 | len = count; | ||
274 | } | ||
275 | *start = page + off; | ||
276 | return len; | ||
277 | } | ||
278 | |||
279 | static int __init pdc_chassis_create_procfs(void) | ||
280 | { | ||
281 | unsigned long test; | ||
282 | int ret; | ||
283 | |||
284 | ret = pdc_chassis_warn(&test); | ||
285 | if ((ret == PDC_BAD_PROC) || (ret == PDC_BAD_OPTION)) { | ||
286 | /* seems that some boxes (eg L1000) do not implement this */ | ||
287 | printk(KERN_INFO "Chassis warnings not supported.\n"); | ||
288 | return 0; | ||
289 | } | ||
290 | |||
291 | printk(KERN_INFO "Enabling PDC chassis warnings support v%s\n", | ||
292 | PDC_CHASSIS_VER); | ||
293 | create_proc_read_entry("chassis", 0400, NULL, pdc_chassis_warn_pread, | ||
294 | NULL); | ||
295 | return 0; | ||
296 | } | ||
297 | |||
298 | __initcall(pdc_chassis_create_procfs); | ||
299 | |||
300 | #endif /* CONFIG_PROC_FS */ | ||
301 | #endif /* CONFIG_PDC_CHASSIS_WARN */ | ||
diff --git a/arch/parisc/kernel/ptrace.c b/arch/parisc/kernel/ptrace.c index 413292f1a4a3..3f28de974556 100644 --- a/arch/parisc/kernel/ptrace.c +++ b/arch/parisc/kernel/ptrace.c | |||
@@ -91,7 +91,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
91 | int copied; | 91 | int copied; |
92 | 92 | ||
93 | #ifdef __LP64__ | 93 | #ifdef __LP64__ |
94 | if (personality(child->personality) == PER_LINUX32) { | 94 | if (__is_compat_task(child)) { |
95 | unsigned int tmp; | 95 | unsigned int tmp; |
96 | 96 | ||
97 | addr &= 0xffffffffL; | 97 | addr &= 0xffffffffL; |
@@ -123,7 +123,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
123 | case PTRACE_POKEDATA: | 123 | case PTRACE_POKEDATA: |
124 | ret = 0; | 124 | ret = 0; |
125 | #ifdef __LP64__ | 125 | #ifdef __LP64__ |
126 | if (personality(child->personality) == PER_LINUX32) { | 126 | if (__is_compat_task(child)) { |
127 | unsigned int tmp = (unsigned int)data; | 127 | unsigned int tmp = (unsigned int)data; |
128 | DBG("sys_ptrace(POKE%s, %d, %lx, %lx)\n", | 128 | DBG("sys_ptrace(POKE%s, %d, %lx, %lx)\n", |
129 | request == PTRACE_POKETEXT ? "TEXT" : "DATA", | 129 | request == PTRACE_POKETEXT ? "TEXT" : "DATA", |
@@ -146,7 +146,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
146 | case PTRACE_PEEKUSR: { | 146 | case PTRACE_PEEKUSR: { |
147 | ret = -EIO; | 147 | ret = -EIO; |
148 | #ifdef __LP64__ | 148 | #ifdef __LP64__ |
149 | if (personality(child->personality) == PER_LINUX32) { | 149 | if (__is_compat_task(child)) { |
150 | unsigned int tmp; | 150 | unsigned int tmp; |
151 | 151 | ||
152 | if (addr & (sizeof(int)-1)) | 152 | if (addr & (sizeof(int)-1)) |
@@ -205,7 +205,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
205 | goto out_tsk; | 205 | goto out_tsk; |
206 | } | 206 | } |
207 | #ifdef __LP64__ | 207 | #ifdef __LP64__ |
208 | if (personality(child->personality) == PER_LINUX32) { | 208 | if (__is_compat_task(child)) { |
209 | if (addr & (sizeof(int)-1)) | 209 | if (addr & (sizeof(int)-1)) |
210 | goto out_tsk; | 210 | goto out_tsk; |
211 | if ((addr = translate_usr_offset(addr)) < 0) | 211 | if ((addr = translate_usr_offset(addr)) < 0) |
diff --git a/arch/parisc/kernel/real2.S b/arch/parisc/kernel/real2.S index 8c2859cca77e..453d01a9f971 100644 --- a/arch/parisc/kernel/real2.S +++ b/arch/parisc/kernel/real2.S | |||
@@ -276,15 +276,6 @@ r64_ret: | |||
276 | 276 | ||
277 | #endif | 277 | #endif |
278 | 278 | ||
279 | .export pc_in_user_space | ||
280 | .text | ||
281 | /* Doesn't belong here but I couldn't find a nicer spot. */ | ||
282 | /* Should never get called, only used by profile stuff in time.c */ | ||
283 | pc_in_user_space: | ||
284 | bv,n 0(%rp) | ||
285 | nop | ||
286 | |||
287 | |||
288 | .export __canonicalize_funcptr_for_compare | 279 | .export __canonicalize_funcptr_for_compare |
289 | .text | 280 | .text |
290 | /* http://lists.parisc-linux.org/hypermail/parisc-linux/10916.html | 281 | /* http://lists.parisc-linux.org/hypermail/parisc-linux/10916.html |
diff --git a/arch/parisc/kernel/setup.c b/arch/parisc/kernel/setup.c index 4a36ec3f6ac1..278f4b9f6a38 100644 --- a/arch/parisc/kernel/setup.c +++ b/arch/parisc/kernel/setup.c | |||
@@ -303,6 +303,8 @@ extern void eisa_init(void); | |||
303 | 303 | ||
304 | static int __init parisc_init(void) | 304 | static int __init parisc_init(void) |
305 | { | 305 | { |
306 | u32 osid = (OS_ID_LINUX << 16); | ||
307 | |||
306 | parisc_proc_mkdir(); | 308 | parisc_proc_mkdir(); |
307 | parisc_init_resources(); | 309 | parisc_init_resources(); |
308 | do_device_inventory(); /* probe for hardware */ | 310 | do_device_inventory(); /* probe for hardware */ |
@@ -311,6 +313,9 @@ static int __init parisc_init(void) | |||
311 | 313 | ||
312 | /* set up a new led state on systems shipped LED State panel */ | 314 | /* set up a new led state on systems shipped LED State panel */ |
313 | pdc_chassis_send_status(PDC_CHASSIS_DIRECT_BSTART); | 315 | pdc_chassis_send_status(PDC_CHASSIS_DIRECT_BSTART); |
316 | |||
317 | /* tell PDC we're Linux. Nevermind failure. */ | ||
318 | pdc_stable_write(0x40, &osid, sizeof(osid)); | ||
314 | 319 | ||
315 | processor_init(); | 320 | processor_init(); |
316 | printk(KERN_INFO "CPU(s): %d x %s at %d.%06d MHz\n", | 321 | printk(KERN_INFO "CPU(s): %d x %s at %d.%06d MHz\n", |
diff --git a/arch/parisc/kernel/signal.c b/arch/parisc/kernel/signal.c index cc38edfd90c5..bb83880c5ee3 100644 --- a/arch/parisc/kernel/signal.c +++ b/arch/parisc/kernel/signal.c | |||
@@ -76,7 +76,7 @@ sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize, struct pt_regs *r | |||
76 | #ifdef __LP64__ | 76 | #ifdef __LP64__ |
77 | compat_sigset_t newset32; | 77 | compat_sigset_t newset32; |
78 | 78 | ||
79 | if(personality(current->personality) == PER_LINUX32){ | 79 | if (is_compat_task()) { |
80 | /* XXX: Don't preclude handling different sized sigset_t's. */ | 80 | /* XXX: Don't preclude handling different sized sigset_t's. */ |
81 | if (sigsetsize != sizeof(compat_sigset_t)) | 81 | if (sigsetsize != sizeof(compat_sigset_t)) |
82 | return -EINVAL; | 82 | return -EINVAL; |
@@ -153,7 +153,7 @@ sys_rt_sigreturn(struct pt_regs *regs, int in_syscall) | |||
153 | compat_sigset_t compat_set; | 153 | compat_sigset_t compat_set; |
154 | struct compat_rt_sigframe __user * compat_frame; | 154 | struct compat_rt_sigframe __user * compat_frame; |
155 | 155 | ||
156 | if(personality(current->personality) == PER_LINUX32) | 156 | if (is_compat_task()) |
157 | sigframe_size = PARISC_RT_SIGFRAME_SIZE32; | 157 | sigframe_size = PARISC_RT_SIGFRAME_SIZE32; |
158 | #endif | 158 | #endif |
159 | 159 | ||
@@ -166,7 +166,7 @@ sys_rt_sigreturn(struct pt_regs *regs, int in_syscall) | |||
166 | #ifdef __LP64__ | 166 | #ifdef __LP64__ |
167 | compat_frame = (struct compat_rt_sigframe __user *)frame; | 167 | compat_frame = (struct compat_rt_sigframe __user *)frame; |
168 | 168 | ||
169 | if(personality(current->personality) == PER_LINUX32){ | 169 | if (is_compat_task()) { |
170 | DBG(2,"sys_rt_sigreturn: ELF32 process.\n"); | 170 | DBG(2,"sys_rt_sigreturn: ELF32 process.\n"); |
171 | if (__copy_from_user(&compat_set, &compat_frame->uc.uc_sigmask, sizeof(compat_set))) | 171 | if (__copy_from_user(&compat_set, &compat_frame->uc.uc_sigmask, sizeof(compat_set))) |
172 | goto give_sigsegv; | 172 | goto give_sigsegv; |
@@ -186,7 +186,7 @@ sys_rt_sigreturn(struct pt_regs *regs, int in_syscall) | |||
186 | 186 | ||
187 | /* Good thing we saved the old gr[30], eh? */ | 187 | /* Good thing we saved the old gr[30], eh? */ |
188 | #ifdef __LP64__ | 188 | #ifdef __LP64__ |
189 | if(personality(current->personality) == PER_LINUX32){ | 189 | if (is_compat_task()) { |
190 | DBG(1,"sys_rt_sigreturn: compat_frame->uc.uc_mcontext 0x%p\n", | 190 | DBG(1,"sys_rt_sigreturn: compat_frame->uc.uc_mcontext 0x%p\n", |
191 | &compat_frame->uc.uc_mcontext); | 191 | &compat_frame->uc.uc_mcontext); |
192 | // FIXME: Load upper half from register file | 192 | // FIXME: Load upper half from register file |
@@ -315,7 +315,7 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | |||
315 | 315 | ||
316 | compat_frame = (struct compat_rt_sigframe __user *)frame; | 316 | compat_frame = (struct compat_rt_sigframe __user *)frame; |
317 | 317 | ||
318 | if(personality(current->personality) == PER_LINUX32) { | 318 | if (is_compat_task()) { |
319 | DBG(1,"setup_rt_frame: frame->info = 0x%p\n", &compat_frame->info); | 319 | DBG(1,"setup_rt_frame: frame->info = 0x%p\n", &compat_frame->info); |
320 | err |= copy_siginfo_to_user32(&compat_frame->info, info); | 320 | err |= copy_siginfo_to_user32(&compat_frame->info, info); |
321 | DBG(1,"SETUP_RT_FRAME: 1\n"); | 321 | DBG(1,"SETUP_RT_FRAME: 1\n"); |
@@ -392,7 +392,7 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | |||
392 | haddr = A(ka->sa.sa_handler); | 392 | haddr = A(ka->sa.sa_handler); |
393 | /* The sa_handler may be a pointer to a function descriptor */ | 393 | /* The sa_handler may be a pointer to a function descriptor */ |
394 | #ifdef __LP64__ | 394 | #ifdef __LP64__ |
395 | if(personality(current->personality) == PER_LINUX32) { | 395 | if (is_compat_task()) { |
396 | #endif | 396 | #endif |
397 | if (haddr & PA_PLABEL_FDESC) { | 397 | if (haddr & PA_PLABEL_FDESC) { |
398 | Elf32_Fdesc fdesc; | 398 | Elf32_Fdesc fdesc; |
@@ -427,19 +427,19 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | |||
427 | */ | 427 | */ |
428 | sigframe_size = PARISC_RT_SIGFRAME_SIZE; | 428 | sigframe_size = PARISC_RT_SIGFRAME_SIZE; |
429 | #ifdef __LP64__ | 429 | #ifdef __LP64__ |
430 | if(personality(current->personality) == PER_LINUX32) | 430 | if (is_compat_task()) |
431 | sigframe_size = PARISC_RT_SIGFRAME_SIZE32; | 431 | sigframe_size = PARISC_RT_SIGFRAME_SIZE32; |
432 | #endif | 432 | #endif |
433 | if (in_syscall) { | 433 | if (in_syscall) { |
434 | regs->gr[31] = haddr; | 434 | regs->gr[31] = haddr; |
435 | #ifdef __LP64__ | 435 | #ifdef __LP64__ |
436 | if(personality(current->personality) == PER_LINUX) | 436 | if (personality(current->personality) == PER_LINUX) |
437 | sigframe_size |= 1; | 437 | sigframe_size |= 1; |
438 | #endif | 438 | #endif |
439 | } else { | 439 | } else { |
440 | unsigned long psw = USER_PSW; | 440 | unsigned long psw = USER_PSW; |
441 | #ifdef __LP64__ | 441 | #ifdef __LP64__ |
442 | if(personality(current->personality) == PER_LINUX) | 442 | if (personality(current->personality) == PER_LINUX) |
443 | psw |= PSW_W; | 443 | psw |= PSW_W; |
444 | #endif | 444 | #endif |
445 | 445 | ||
@@ -464,7 +464,7 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | |||
464 | regs->gr[26] = sig; /* signal number */ | 464 | regs->gr[26] = sig; /* signal number */ |
465 | 465 | ||
466 | #ifdef __LP64__ | 466 | #ifdef __LP64__ |
467 | if(personality(current->personality) == PER_LINUX32){ | 467 | if (is_compat_task()) { |
468 | regs->gr[25] = A(&compat_frame->info); /* siginfo pointer */ | 468 | regs->gr[25] = A(&compat_frame->info); /* siginfo pointer */ |
469 | regs->gr[24] = A(&compat_frame->uc); /* ucontext pointer */ | 469 | regs->gr[24] = A(&compat_frame->uc); /* ucontext pointer */ |
470 | } else | 470 | } else |
diff --git a/arch/parisc/kernel/syscall.S b/arch/parisc/kernel/syscall.S index 479d9a017cd1..9670a89c77fe 100644 --- a/arch/parisc/kernel/syscall.S +++ b/arch/parisc/kernel/syscall.S | |||
@@ -29,18 +29,6 @@ | |||
29 | .level 1.1 | 29 | .level 1.1 |
30 | #endif | 30 | #endif |
31 | 31 | ||
32 | #ifndef CONFIG_64BIT | ||
33 | .macro fixup_branch,lbl | ||
34 | b \lbl | ||
35 | .endm | ||
36 | #else | ||
37 | .macro fixup_branch,lbl | ||
38 | ldil L%\lbl, %r1 | ||
39 | ldo R%\lbl(%r1), %r1 | ||
40 | bv,n %r0(%r1) | ||
41 | .endm | ||
42 | #endif | ||
43 | |||
44 | .text | 32 | .text |
45 | 33 | ||
46 | .import syscall_exit,code | 34 | .import syscall_exit,code |
@@ -541,7 +529,7 @@ cas_nocontend: | |||
541 | # endif | 529 | # endif |
542 | /* ENABLE_LWS_DEBUG */ | 530 | /* ENABLE_LWS_DEBUG */ |
543 | 531 | ||
544 | ldcw 0(%sr2,%r20), %r28 /* Try to acquire the lock */ | 532 | LDCW 0(%sr2,%r20), %r28 /* Try to acquire the lock */ |
545 | cmpb,<>,n %r0, %r28, cas_action /* Did we get it? */ | 533 | cmpb,<>,n %r0, %r28, cas_action /* Did we get it? */ |
546 | cas_wouldblock: | 534 | cas_wouldblock: |
547 | ldo 2(%r0), %r28 /* 2nd case */ | 535 | ldo 2(%r0), %r28 /* 2nd case */ |
diff --git a/arch/parisc/kernel/time.c b/arch/parisc/kernel/time.c index 594930bc4bcf..eb35e1c0bb53 100644 --- a/arch/parisc/kernel/time.c +++ b/arch/parisc/kernel/time.c | |||
@@ -157,8 +157,22 @@ do_gettimeofday (struct timeval *tv) | |||
157 | usec += (xtime.tv_nsec / 1000); | 157 | usec += (xtime.tv_nsec / 1000); |
158 | } while (read_seqretry_irqrestore(&xtime_lock, seq, flags)); | 158 | } while (read_seqretry_irqrestore(&xtime_lock, seq, flags)); |
159 | 159 | ||
160 | while (usec >= 1000000) { | 160 | if (unlikely(usec > LONG_MAX)) { |
161 | usec -= 1000000; | 161 | /* This can happen if the gettimeoffset adjustment is |
162 | * negative and xtime.tv_nsec is smaller than the | ||
163 | * adjustment */ | ||
164 | printk(KERN_ERR "do_gettimeofday() spurious xtime.tv_nsec of %ld\n", usec); | ||
165 | usec += USEC_PER_SEC; | ||
166 | --sec; | ||
167 | /* This should never happen, it means the negative | ||
168 | * time adjustment was more than a second, so there's | ||
169 | * something seriously wrong */ | ||
170 | BUG_ON(usec > LONG_MAX); | ||
171 | } | ||
172 | |||
173 | |||
174 | while (usec >= USEC_PER_SEC) { | ||
175 | usec -= USEC_PER_SEC; | ||
162 | ++sec; | 176 | ++sec; |
163 | } | 177 | } |
164 | 178 | ||
diff --git a/arch/parisc/kernel/traps.c b/arch/parisc/kernel/traps.c index ff200608c851..348344a84bf7 100644 --- a/arch/parisc/kernel/traps.c +++ b/arch/parisc/kernel/traps.c | |||
@@ -66,57 +66,42 @@ int printbinary(char *buf, unsigned long x, int nbits) | |||
66 | #else | 66 | #else |
67 | #define RFMT "%08lx" | 67 | #define RFMT "%08lx" |
68 | #endif | 68 | #endif |
69 | #define FFMT "%016llx" /* fpregs are 64-bit always */ | ||
69 | 70 | ||
70 | void show_regs(struct pt_regs *regs) | 71 | #define PRINTREGS(lvl,r,f,fmt,x) \ |
72 | printk("%s%s%02d-%02d " fmt " " fmt " " fmt " " fmt "\n", \ | ||
73 | lvl, f, (x), (x+3), (r)[(x)+0], (r)[(x)+1], \ | ||
74 | (r)[(x)+2], (r)[(x)+3]) | ||
75 | |||
76 | static void print_gr(char *level, struct pt_regs *regs) | ||
71 | { | 77 | { |
72 | int i; | 78 | int i; |
73 | char buf[128], *p; | 79 | char buf[64]; |
74 | char *level; | ||
75 | unsigned long cr30; | ||
76 | unsigned long cr31; | ||
77 | /* carlos says that gcc understands better memory in a struct, | ||
78 | * and it makes our life easier with fpregs -- T-Bone */ | ||
79 | struct { u32 sw[2]; } s; | ||
80 | |||
81 | level = user_mode(regs) ? KERN_DEBUG : KERN_CRIT; | ||
82 | |||
83 | printk("%s\n", level); /* don't want to have that pretty register dump messed up */ | ||
84 | 80 | ||
81 | printk("%s\n", level); | ||
85 | printk("%s YZrvWESTHLNXBCVMcbcbcbcbOGFRQPDI\n", level); | 82 | printk("%s YZrvWESTHLNXBCVMcbcbcbcbOGFRQPDI\n", level); |
86 | printbinary(buf, regs->gr[0], 32); | 83 | printbinary(buf, regs->gr[0], 32); |
87 | printk("%sPSW: %s %s\n", level, buf, print_tainted()); | 84 | printk("%sPSW: %s %s\n", level, buf, print_tainted()); |
88 | 85 | ||
89 | for (i = 0; i < 32; i += 4) { | 86 | for (i = 0; i < 32; i += 4) |
90 | int j; | 87 | PRINTREGS(level, regs->gr, "r", RFMT, i); |
91 | p = buf; | 88 | } |
92 | p += sprintf(p, "%sr%02d-%02d ", level, i, i + 3); | ||
93 | for (j = 0; j < 4; j++) { | ||
94 | p += sprintf(p, " " RFMT, (i+j) == 0 ? 0 : regs->gr[i + j]); | ||
95 | } | ||
96 | printk("%s\n", buf); | ||
97 | } | ||
98 | 89 | ||
99 | for (i = 0; i < 8; i += 4) { | 90 | static void print_fr(char *level, struct pt_regs *regs) |
100 | int j; | 91 | { |
101 | p = buf; | 92 | int i; |
102 | p += sprintf(p, "%ssr%d-%d ", level, i, i + 3); | 93 | char buf[64]; |
103 | for (j = 0; j < 4; j++) { | 94 | struct { u32 sw[2]; } s; |
104 | p += sprintf(p, " " RFMT, regs->sr[i + j]); | ||
105 | } | ||
106 | printk("%s\n", buf); | ||
107 | } | ||
108 | 95 | ||
109 | /* FR are 64bit everywhere. Need to use asm to get the content | 96 | /* FR are 64bit everywhere. Need to use asm to get the content |
110 | * of fpsr/fper1, and we assume that we won't have a FP Identify | 97 | * of fpsr/fper1, and we assume that we won't have a FP Identify |
111 | * in our way, otherwise we're screwed. | 98 | * in our way, otherwise we're screwed. |
112 | * The fldd is used to restore the T-bit if there was one, as the | 99 | * The fldd is used to restore the T-bit if there was one, as the |
113 | * store clears it anyway. | 100 | * store clears it anyway. |
114 | * BTW, PA2.0 book says "thou shall not use fstw on FPSR/FPERs". */ | 101 | * PA2.0 book says "thou shall not use fstw on FPSR/FPERs" - T-Bone */ |
115 | __asm__ ( | 102 | asm volatile ("fstd %%fr0,0(%1) \n\t" |
116 | "fstd %%fr0,0(%1) \n\t" | 103 | "fldd 0(%1),%%fr0 \n\t" |
117 | "fldd 0(%1),%%fr0 \n\t" | 104 | : "=m" (s) : "r" (&s) : "r0"); |
118 | : "=m" (s) : "r" (&s) : "%r0" | ||
119 | ); | ||
120 | 105 | ||
121 | printk("%s\n", level); | 106 | printk("%s\n", level); |
122 | printk("%s VZOUICununcqcqcqcqcqcrmunTDVZOUI\n", level); | 107 | printk("%s VZOUICununcqcqcqcqcqcrmunTDVZOUI\n", level); |
@@ -125,14 +110,25 @@ void show_regs(struct pt_regs *regs) | |||
125 | printk("%sFPER1: %08x\n", level, s.sw[1]); | 110 | printk("%sFPER1: %08x\n", level, s.sw[1]); |
126 | 111 | ||
127 | /* here we'll print fr0 again, tho it'll be meaningless */ | 112 | /* here we'll print fr0 again, tho it'll be meaningless */ |
128 | for (i = 0; i < 32; i += 4) { | 113 | for (i = 0; i < 32; i += 4) |
129 | int j; | 114 | PRINTREGS(level, regs->fr, "fr", FFMT, i); |
130 | p = buf; | 115 | } |
131 | p += sprintf(p, "%sfr%02d-%02d ", level, i, i + 3); | 116 | |
132 | for (j = 0; j < 4; j++) | 117 | void show_regs(struct pt_regs *regs) |
133 | p += sprintf(p, " %016llx", (i+j) == 0 ? 0 : regs->fr[i+j]); | 118 | { |
134 | printk("%s\n", buf); | 119 | int i; |
135 | } | 120 | char *level; |
121 | unsigned long cr30, cr31; | ||
122 | |||
123 | level = user_mode(regs) ? KERN_DEBUG : KERN_CRIT; | ||
124 | |||
125 | print_gr(level, regs); | ||
126 | |||
127 | for (i = 0; i < 8; i += 4) | ||
128 | PRINTREGS(level, regs->sr, "sr", RFMT, i); | ||
129 | |||
130 | if (user_mode(regs)) | ||
131 | print_fr(level, regs); | ||
136 | 132 | ||
137 | cr30 = mfctl(30); | 133 | cr30 = mfctl(30); |
138 | cr31 = mfctl(31); | 134 | cr31 = mfctl(31); |
diff --git a/arch/parisc/kernel/unaligned.c b/arch/parisc/kernel/unaligned.c index de0a1b21cb40..92328fbddb3e 100644 --- a/arch/parisc/kernel/unaligned.c +++ b/arch/parisc/kernel/unaligned.c | |||
@@ -43,6 +43,8 @@ | |||
43 | "\tldil L%%" #lbl ", %%r1\n" \ | 43 | "\tldil L%%" #lbl ", %%r1\n" \ |
44 | "\tldo R%%" #lbl "(%%r1), %%r1\n" \ | 44 | "\tldo R%%" #lbl "(%%r1), %%r1\n" \ |
45 | "\tbv,n %%r0(%%r1)\n" | 45 | "\tbv,n %%r0(%%r1)\n" |
46 | /* If you use FIXUP_BRANCH, then you must list this clobber */ | ||
47 | #define FIXUP_BRANCH_CLOBBER "r1" | ||
46 | 48 | ||
47 | /* 1111 1100 0000 0000 0001 0011 1100 0000 */ | 49 | /* 1111 1100 0000 0000 0001 0011 1100 0000 */ |
48 | #define OPCODE1(a,b,c) ((a)<<26|(b)<<12|(c)<<6) | 50 | #define OPCODE1(a,b,c) ((a)<<26|(b)<<12|(c)<<6) |
@@ -157,7 +159,7 @@ static int emulate_ldh(struct pt_regs *regs, int toreg) | |||
157 | " .previous\n" | 159 | " .previous\n" |
158 | : "=r" (val), "=r" (ret) | 160 | : "=r" (val), "=r" (ret) |
159 | : "0" (val), "r" (saddr), "r" (regs->isr) | 161 | : "0" (val), "r" (saddr), "r" (regs->isr) |
160 | : "r20" ); | 162 | : "r20", FIXUP_BRANCH_CLOBBER ); |
161 | 163 | ||
162 | DPRINTF("val = 0x" RFMT "\n", val); | 164 | DPRINTF("val = 0x" RFMT "\n", val); |
163 | 165 | ||
@@ -202,7 +204,7 @@ static int emulate_ldw(struct pt_regs *regs, int toreg, int flop) | |||
202 | " .previous\n" | 204 | " .previous\n" |
203 | : "=r" (val), "=r" (ret) | 205 | : "=r" (val), "=r" (ret) |
204 | : "0" (val), "r" (saddr), "r" (regs->isr) | 206 | : "0" (val), "r" (saddr), "r" (regs->isr) |
205 | : "r19", "r20" ); | 207 | : "r19", "r20", FIXUP_BRANCH_CLOBBER ); |
206 | 208 | ||
207 | DPRINTF("val = 0x" RFMT "\n", val); | 209 | DPRINTF("val = 0x" RFMT "\n", val); |
208 | 210 | ||
@@ -253,7 +255,7 @@ static int emulate_ldd(struct pt_regs *regs, int toreg, int flop) | |||
253 | " .previous\n" | 255 | " .previous\n" |
254 | : "=r" (val), "=r" (ret) | 256 | : "=r" (val), "=r" (ret) |
255 | : "0" (val), "r" (saddr), "r" (regs->isr) | 257 | : "0" (val), "r" (saddr), "r" (regs->isr) |
256 | : "r19", "r20" ); | 258 | : "r19", "r20", FIXUP_BRANCH_CLOBBER ); |
257 | #else | 259 | #else |
258 | { | 260 | { |
259 | unsigned long valh=0,vall=0; | 261 | unsigned long valh=0,vall=0; |
@@ -287,7 +289,7 @@ static int emulate_ldd(struct pt_regs *regs, int toreg, int flop) | |||
287 | " .previous\n" | 289 | " .previous\n" |
288 | : "=r" (valh), "=r" (vall), "=r" (ret) | 290 | : "=r" (valh), "=r" (vall), "=r" (ret) |
289 | : "0" (valh), "1" (vall), "r" (saddr), "r" (regs->isr) | 291 | : "0" (valh), "1" (vall), "r" (saddr), "r" (regs->isr) |
290 | : "r19", "r20" ); | 292 | : "r19", "r20", FIXUP_BRANCH_CLOBBER ); |
291 | val=((__u64)valh<<32)|(__u64)vall; | 293 | val=((__u64)valh<<32)|(__u64)vall; |
292 | } | 294 | } |
293 | #endif | 295 | #endif |
@@ -335,7 +337,7 @@ static int emulate_sth(struct pt_regs *regs, int frreg) | |||
335 | " .previous\n" | 337 | " .previous\n" |
336 | : "=r" (ret) | 338 | : "=r" (ret) |
337 | : "r" (val), "r" (regs->ior), "r" (regs->isr) | 339 | : "r" (val), "r" (regs->ior), "r" (regs->isr) |
338 | : "r19" ); | 340 | : "r19", FIXUP_BRANCH_CLOBBER ); |
339 | 341 | ||
340 | return ret; | 342 | return ret; |
341 | } | 343 | } |
@@ -389,7 +391,7 @@ static int emulate_stw(struct pt_regs *regs, int frreg, int flop) | |||
389 | " .previous\n" | 391 | " .previous\n" |
390 | : "=r" (ret) | 392 | : "=r" (ret) |
391 | : "r" (val), "r" (regs->ior), "r" (regs->isr) | 393 | : "r" (val), "r" (regs->ior), "r" (regs->isr) |
392 | : "r19", "r20", "r21", "r22", "r1" ); | 394 | : "r19", "r20", "r21", "r22", "r1", FIXUP_BRANCH_CLOBBER ); |
393 | 395 | ||
394 | return 0; | 396 | return 0; |
395 | } | 397 | } |
@@ -450,7 +452,7 @@ static int emulate_std(struct pt_regs *regs, int frreg, int flop) | |||
450 | " .previous\n" | 452 | " .previous\n" |
451 | : "=r" (ret) | 453 | : "=r" (ret) |
452 | : "r" (val), "r" (regs->ior), "r" (regs->isr) | 454 | : "r" (val), "r" (regs->ior), "r" (regs->isr) |
453 | : "r19", "r20", "r21", "r22", "r1" ); | 455 | : "r19", "r20", "r21", "r22", "r1", FIXUP_BRANCH_CLOBBER ); |
454 | #else | 456 | #else |
455 | { | 457 | { |
456 | unsigned long valh=(val>>32),vall=(val&0xffffffffl); | 458 | unsigned long valh=(val>>32),vall=(val&0xffffffffl); |
@@ -495,7 +497,7 @@ static int emulate_std(struct pt_regs *regs, int frreg, int flop) | |||
495 | " .previous\n" | 497 | " .previous\n" |
496 | : "=r" (ret) | 498 | : "=r" (ret) |
497 | : "r" (valh), "r" (vall), "r" (regs->ior), "r" (regs->isr) | 499 | : "r" (valh), "r" (vall), "r" (regs->ior), "r" (regs->isr) |
498 | : "r19", "r20", "r21", "r1" ); | 500 | : "r19", "r20", "r21", "r1", FIXUP_BRANCH_CLOBBER ); |
499 | } | 501 | } |
500 | #endif | 502 | #endif |
501 | 503 | ||