aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid S. Miller <davem@sunset.davemloft.net>2007-09-16 14:51:15 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2007-09-16 14:51:15 -0400
commit301feb652441a7168b59256fc44918075dcab0d5 (patch)
tree68721bebf1375659be165c4810bb439785d6e96f
parent58ea1aa07e3cb4674ab0261b45aa1ba68282a79d (diff)
[SPARC64]: Fix lockdep, particularly on SMP.
As noted by Al Viro, when we try to call prom_set_trap_table() in the SMP trampoline code we try to take the PROM call spinlock which doesn't work because the current thread pointer isn't valid yet and lockdep depends upon that being correct. Furthermore, we cannot set the current thread pointer register because it can't be properly dereferenced until we return from prom_set_trap_table(). Kernel TLB misses only work after that call. So do the PROM call to set the trap table directly instead of going through the OBP library C code, and thus avoid the lock altogether. These calls are guarenteed to be serialized fully. Since there are now no calls to the prom_set_trap_table{_sun4v}() library functions, they can be deleted. Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--arch/sparc64/kernel/head.S35
-rw-r--r--arch/sparc64/kernel/trampoline.S33
-rw-r--r--arch/sparc64/prom/misc.c16
-rw-r--r--include/asm-sparc64/oplib.h4
4 files changed, 58 insertions, 30 deletions
diff --git a/arch/sparc64/kernel/head.S b/arch/sparc64/kernel/head.S
index 63144ad476f6..c4147ad8677b 100644
--- a/arch/sparc64/kernel/head.S
+++ b/arch/sparc64/kernel/head.S
@@ -98,7 +98,7 @@ sparc64_boot:
98 .globl prom_boot_mapped_pc, prom_boot_mapping_mode 98 .globl prom_boot_mapped_pc, prom_boot_mapping_mode
99 .globl prom_boot_mapping_phys_high, prom_boot_mapping_phys_low 99 .globl prom_boot_mapping_phys_high, prom_boot_mapping_phys_low
100 .globl prom_compatible_name, prom_cpu_path, prom_cpu_compatible 100 .globl prom_compatible_name, prom_cpu_path, prom_cpu_compatible
101 .globl is_sun4v, sun4v_chip_type 101 .globl is_sun4v, sun4v_chip_type, prom_set_trap_table_name
102prom_peer_name: 102prom_peer_name:
103 .asciz "peer" 103 .asciz "peer"
104prom_compatible_name: 104prom_compatible_name:
@@ -121,6 +121,8 @@ prom_map_name:
121 .asciz "map" 121 .asciz "map"
122prom_unmap_name: 122prom_unmap_name:
123 .asciz "unmap" 123 .asciz "unmap"
124prom_set_trap_table_name:
125 .asciz "SUNW,set-trap-table"
124prom_sun4v_name: 126prom_sun4v_name:
125 .asciz "sun4v" 127 .asciz "sun4v"
126prom_niagara_prefix: 128prom_niagara_prefix:
@@ -691,15 +693,38 @@ setup_trap_table:
691 sethi %hi(kern_base), %g3 693 sethi %hi(kern_base), %g3
692 ldx [%g3 + %lo(kern_base)], %g3 694 ldx [%g3 + %lo(kern_base)], %g3
693 add %g2, %g3, %o1 695 add %g2, %g3, %o1
696 sethi %hi(sparc64_ttable_tl0), %o0
694 697
695 call prom_set_trap_table_sun4v 698 set prom_set_trap_table_name, %g2
696 sethi %hi(sparc64_ttable_tl0), %o0 699 stx %g2, [%sp + 2047 + 128 + 0x00]
700 mov 2, %g2
701 stx %g2, [%sp + 2047 + 128 + 0x08]
702 mov 0, %g2
703 stx %g2, [%sp + 2047 + 128 + 0x10]
704 stx %o0, [%sp + 2047 + 128 + 0x18]
705 stx %o1, [%sp + 2047 + 128 + 0x20]
706 sethi %hi(p1275buf), %g2
707 or %g2, %lo(p1275buf), %g2
708 ldx [%g2 + 0x08], %o1
709 call %o1
710 add %sp, (2047 + 128), %o0
697 711
698 ba,pt %xcc, 2f 712 ba,pt %xcc, 2f
699 nop 713 nop
700 714
7011: call prom_set_trap_table 7151: sethi %hi(sparc64_ttable_tl0), %o0
702 sethi %hi(sparc64_ttable_tl0), %o0 716 set prom_set_trap_table_name, %g2
717 stx %g2, [%sp + 2047 + 128 + 0x00]
718 mov 1, %g2
719 stx %g2, [%sp + 2047 + 128 + 0x08]
720 mov 0, %g2
721 stx %g2, [%sp + 2047 + 128 + 0x10]
722 stx %o0, [%sp + 2047 + 128 + 0x18]
723 sethi %hi(p1275buf), %g2
724 or %g2, %lo(p1275buf), %g2
725 ldx [%g2 + 0x08], %o1
726 call %o1
727 add %sp, (2047 + 128), %o0
703 728
704 /* Start using proper page size encodings in ctx register. */ 729 /* Start using proper page size encodings in ctx register. */
7052: sethi %hi(sparc64_kern_pri_context), %g3 7302: sethi %hi(sparc64_kern_pri_context), %g3
diff --git a/arch/sparc64/kernel/trampoline.S b/arch/sparc64/kernel/trampoline.S
index 9533a25ce5d2..04e81dda13d0 100644
--- a/arch/sparc64/kernel/trampoline.S
+++ b/arch/sparc64/kernel/trampoline.S
@@ -345,7 +345,7 @@ after_lock_tlb:
345 sethi %hi(tramp_stack), %g1 345 sethi %hi(tramp_stack), %g1
346 or %g1, %lo(tramp_stack), %g1 346 or %g1, %lo(tramp_stack), %g1
347 add %g1, TRAMP_STACK_SIZE, %g1 347 add %g1, TRAMP_STACK_SIZE, %g1
348 sub %g1, STACKFRAME_SZ + STACK_BIAS, %sp 348 sub %g1, STACKFRAME_SZ + STACK_BIAS + 256, %sp
349 mov 0, %fp 349 mov 0, %fp
350 350
351 /* Put garbage in these registers to trap any access to them. */ 351 /* Put garbage in these registers to trap any access to them. */
@@ -411,15 +411,38 @@ after_lock_tlb:
411 sethi %hi(kern_base), %g3 411 sethi %hi(kern_base), %g3
412 ldx [%g3 + %lo(kern_base)], %g3 412 ldx [%g3 + %lo(kern_base)], %g3
413 add %g2, %g3, %o1 413 add %g2, %g3, %o1
414 sethi %hi(sparc64_ttable_tl0), %o0
414 415
415 call prom_set_trap_table_sun4v 416 set prom_set_trap_table_name, %g2
416 sethi %hi(sparc64_ttable_tl0), %o0 417 stx %g2, [%sp + 2047 + 128 + 0x00]
418 mov 2, %g2
419 stx %g2, [%sp + 2047 + 128 + 0x08]
420 mov 0, %g2
421 stx %g2, [%sp + 2047 + 128 + 0x10]
422 stx %o0, [%sp + 2047 + 128 + 0x18]
423 stx %o1, [%sp + 2047 + 128 + 0x20]
424 sethi %hi(p1275buf), %g2
425 or %g2, %lo(p1275buf), %g2
426 ldx [%g2 + 0x08], %o1
427 call %o1
428 add %sp, (2047 + 128), %o0
417 429
418 ba,pt %xcc, 2f 430 ba,pt %xcc, 2f
419 nop 431 nop
420 432
4211: call prom_set_trap_table 4331: sethi %hi(sparc64_ttable_tl0), %o0
422 sethi %hi(sparc64_ttable_tl0), %o0 434 set prom_set_trap_table_name, %g2
435 stx %g2, [%sp + 2047 + 128 + 0x00]
436 mov 1, %g2
437 stx %g2, [%sp + 2047 + 128 + 0x08]
438 mov 0, %g2
439 stx %g2, [%sp + 2047 + 128 + 0x10]
440 stx %o0, [%sp + 2047 + 128 + 0x18]
441 sethi %hi(p1275buf), %g2
442 or %g2, %lo(p1275buf), %g2
443 ldx [%g2 + 0x08], %o1
444 call %o1
445 add %sp, (2047 + 128), %o0
423 446
4242: ldx [%l0], %g6 4472: ldx [%l0], %g6
425 ldx [%g6 + TI_TASK], %g4 448 ldx [%g6 + TI_TASK], %g4
diff --git a/arch/sparc64/prom/misc.c b/arch/sparc64/prom/misc.c
index 68c83ad04ad9..bbec7522826c 100644
--- a/arch/sparc64/prom/misc.c
+++ b/arch/sparc64/prom/misc.c
@@ -143,22 +143,6 @@ unsigned char prom_get_idprom(char *idbuf, int num_bytes)
143 return 0xff; 143 return 0xff;
144} 144}
145 145
146/* Install Linux trap table so PROM uses that instead of its own. */
147void prom_set_trap_table(unsigned long tba)
148{
149 p1275_cmd("SUNW,set-trap-table",
150 (P1275_ARG(0, P1275_ARG_IN_64B) |
151 P1275_INOUT(1, 0)), tba);
152}
153
154void prom_set_trap_table_sun4v(unsigned long tba, unsigned long mmfsa)
155{
156 p1275_cmd("SUNW,set-trap-table",
157 (P1275_ARG(0, P1275_ARG_IN_64B) |
158 P1275_ARG(1, P1275_ARG_IN_64B) |
159 P1275_INOUT(2, 0)), tba, mmfsa);
160}
161
162int prom_get_mmu_ihandle(void) 146int prom_get_mmu_ihandle(void)
163{ 147{
164 int node, ret; 148 int node, ret;
diff --git a/include/asm-sparc64/oplib.h b/include/asm-sparc64/oplib.h
index 86dc5c018a19..55c5bb27e4da 100644
--- a/include/asm-sparc64/oplib.h
+++ b/include/asm-sparc64/oplib.h
@@ -297,11 +297,7 @@ extern void prom_sun4v_guest_soft_state(void);
297extern int prom_ihandle2path(int handle, char *buffer, int bufsize); 297extern int prom_ihandle2path(int handle, char *buffer, int bufsize);
298 298
299/* Client interface level routines. */ 299/* Client interface level routines. */
300extern void prom_set_trap_table(unsigned long tba);
301extern void prom_set_trap_table_sun4v(unsigned long tba, unsigned long mmfsa);
302
303extern long p1275_cmd(const char *, long, ...); 300extern long p1275_cmd(const char *, long, ...);
304
305 301
306#if 0 302#if 0
307#define P1275_SIZE(x) ((((long)((x) / 32)) << 32) | (x)) 303#define P1275_SIZE(x) ((((long)((x) / 32)) << 32) | (x))