Skip to content

Commit

Permalink
[SPARC64]: Sanitize %pstate writes for sun4v.
Browse files Browse the repository at this point in the history
If we're just switching between different alternate global
sets, nop it out on sun4v.  Also, get rid of all of the
alternate global save/restore in the OBP CIF trampoline code.

Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed Mar 20, 2006
1 parent 314981a commit 45fec05
Show file tree
Hide file tree
Showing 7 changed files with 88 additions and 206 deletions.
18 changes: 16 additions & 2 deletions arch/sparc64/kernel/ktlb.S
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,15 @@ kvmap_itlb_load:
retry

kvmap_itlb_longpath:
rdpr %pstate, %g5

661: rdpr %pstate, %g5
wrpr %g5, PSTATE_AG | PSTATE_MG, %pstate
.section .gl_2insn_patch, "ax"
.word 661b
nop
nop
.previous

rdpr %tpc, %g5
ba,pt %xcc, sparc64_realfault_common
mov FAULT_CODE_ITLB, %g4
Expand Down Expand Up @@ -161,8 +168,15 @@ kvmap_check_obp:
nop

kvmap_dtlb_longpath:
rdpr %pstate, %g5

661: rdpr %pstate, %g5
wrpr %g5, PSTATE_AG | PSTATE_MG, %pstate
.section .gl_2insn_patch, "ax"
.word 661b
nop
nop
.previous

rdpr %tl, %g4
cmp %g4, 1
mov TLB_TAG_ACCESS, %g4
Expand Down
26 changes: 20 additions & 6 deletions arch/sparc64/kernel/setup.c
Original file line number Diff line number Diff line change
Expand Up @@ -547,19 +547,33 @@ static void __init per_cpu_patch(void)

static void __init gl_patch(void)
{
struct gl_1insn_patch_entry *p;
struct gl_1insn_patch_entry *p1;
struct gl_2insn_patch_entry *p2;

if (tlb_type != hypervisor)
return;

p = &__gl_1insn_patch;
while (p < &__gl_1insn_patch_end) {
unsigned long addr = p->addr;
p1 = &__gl_1insn_patch;
while (p1 < &__gl_1insn_patch_end) {
unsigned long addr = p1->addr;

*(unsigned int *) (addr + 0) = p->insn;
*(unsigned int *) (addr + 0) = p1->insn;
__asm__ __volatile__("flush %0" : : "r" (addr + 0));

p++;
p1++;
}

p2 = &__gl_2insn_patch;
while (p2 < &__gl_2insn_patch_end) {
unsigned long addr = p2->addr;

*(unsigned int *) (addr + 0) = p2->insns[0];
__asm__ __volatile__("flush %0" : : "r" (addr + 0));

*(unsigned int *) (addr + 3) = p2->insns[1];
__asm__ __volatile__("flush %0" : : "r" (addr + 4));

p2++;
}
}

Expand Down
12 changes: 10 additions & 2 deletions arch/sparc64/kernel/tsb.S
Original file line number Diff line number Diff line change
Expand Up @@ -82,9 +82,17 @@ tsb_itlb_load:
.globl tsb_do_fault
tsb_do_fault:
cmp %g3, FAULT_CODE_DTLB
rdpr %pstate, %g5

661: rdpr %pstate, %g5
wrpr %g5, PSTATE_AG | PSTATE_MG, %pstate
.section .gl_2insn_patch, "ax"
.word 661b
nop
nop
.previous

bne,pn %xcc, tsb_do_itlb_fault
wrpr %g5, PSTATE_AG | PSTATE_MG, %pstate
nop

tsb_do_dtlb_fault:
rdpr %tl, %g4
Expand Down
3 changes: 3 additions & 0 deletions arch/sparc64/kernel/vmlinux.lds.S
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,9 @@ SECTIONS
__gl_1insn_patch = .;
.gl_1insn_patch : { *(.gl_1insn_patch) }
__gl_1insn_patch_end = .;
__gl_2insn_patch = .;
.gl_2insn_patch : { *(.gl_2insn_patch) }
__gl_2insn_patch_end = .;
. = ALIGN(8192);
__initramfs_start = .;
.init.ramfs : { *(.init.ramfs) }
Expand Down
18 changes: 16 additions & 2 deletions arch/sparc64/mm/ultra.S
Original file line number Diff line number Diff line change
Expand Up @@ -444,8 +444,15 @@ xcall_flush_tlb_kernel_range: /* 22 insns */
*/
.globl xcall_sync_tick
xcall_sync_tick:
rdpr %pstate, %g2

661: rdpr %pstate, %g2
wrpr %g2, PSTATE_IG | PSTATE_AG, %pstate
.section .gl_2insn_patch, "ax"
.word 661b
nop
nop
.previous

rdpr %pil, %g2
wrpr %g0, 15, %pil
sethi %hi(109f), %g7
Expand All @@ -468,8 +475,15 @@ xcall_sync_tick:
*/
.globl xcall_report_regs
xcall_report_regs:
rdpr %pstate, %g2

661: rdpr %pstate, %g2
wrpr %g2, PSTATE_IG | PSTATE_AG, %pstate
.section .gl_2insn_patch, "ax"
.word 661b
nop
nop
.previous

rdpr %pil, %g2
wrpr %g0, 15, %pil
sethi %hi(109f), %g7
Expand Down
211 changes: 17 additions & 194 deletions arch/sparc64/prom/cif.S
Original file line number Diff line number Diff line change
@@ -1,225 +1,48 @@
/* cif.S: PROM entry/exit assembler trampolines.
*
* Copyright (C) 1996,1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
* Copyright (C) 2005 David S. Miller <davem@davemloft.net>
* Copyright (C) 1996, 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
* Copyright (C) 2005, 2006 David S. Miller <davem@davemloft.net>
*/

#include <asm/pstate.h>
#include <asm/cpudata.h>
#include <asm/thread_info.h>

.text
.globl prom_cif_interface
prom_cif_interface:
sethi %hi(p1275buf), %o0
or %o0, %lo(p1275buf), %o0
ldx [%o0 + 0x010], %o1 ! prom_cif_stack
save %o1, -0x190, %sp
save %o1, -192, %sp
ldx [%i0 + 0x008], %l2 ! prom_cif_handler
rdpr %pstate, %l4
wrpr %g0, 0x15, %pstate ! save alternate globals
stx %g1, [%sp + 2047 + 0x0b0]
stx %g2, [%sp + 2047 + 0x0b8]
stx %g3, [%sp + 2047 + 0x0c0]
stx %g4, [%sp + 2047 + 0x0c8]
stx %g5, [%sp + 2047 + 0x0d0]
stx %g6, [%sp + 2047 + 0x0d8]
stx %g7, [%sp + 2047 + 0x0e0]
wrpr %g0, 0x814, %pstate ! save interrupt globals
stx %g1, [%sp + 2047 + 0x0e8]
stx %g2, [%sp + 2047 + 0x0f0]
stx %g3, [%sp + 2047 + 0x0f8]
stx %g4, [%sp + 2047 + 0x100]
stx %g5, [%sp + 2047 + 0x108]
stx %g6, [%sp + 2047 + 0x110]
stx %g7, [%sp + 2047 + 0x118]
wrpr %g0, 0x14, %pstate ! save normal globals
stx %g1, [%sp + 2047 + 0x120]
stx %g2, [%sp + 2047 + 0x128]
stx %g3, [%sp + 2047 + 0x130]
stx %g4, [%sp + 2047 + 0x138]
stx %g5, [%sp + 2047 + 0x140]
stx %g6, [%sp + 2047 + 0x148]
stx %g7, [%sp + 2047 + 0x150]
wrpr %g0, 0x414, %pstate ! save mmu globals
stx %g1, [%sp + 2047 + 0x158]
stx %g2, [%sp + 2047 + 0x160]
stx %g3, [%sp + 2047 + 0x168]
stx %g4, [%sp + 2047 + 0x170]
stx %g5, [%sp + 2047 + 0x178]
stx %g6, [%sp + 2047 + 0x180]
stx %g7, [%sp + 2047 + 0x188]
mov %g1, %l0 ! also save to locals, so we can handle
mov %g2, %l1 ! tlb faults later on, when accessing
mov %g3, %l3 ! the stack.
mov %g7, %l5
wrpr %l4, PSTATE_IE, %pstate ! turn off interrupts
mov %g4, %l0
mov %g5, %l1
mov %g6, %l3
call %l2
add %i0, 0x018, %o0 ! prom_args
wrpr %g0, 0x414, %pstate ! restore mmu globals
mov %l0, %g1
mov %l1, %g2
mov %l3, %g3
mov %l5, %g7
wrpr %g0, 0x14, %pstate ! restore normal globals
ldx [%sp + 2047 + 0x120], %g1
ldx [%sp + 2047 + 0x128], %g2
ldx [%sp + 2047 + 0x130], %g3
ldx [%sp + 2047 + 0x138], %g4
ldx [%sp + 2047 + 0x140], %g5
ldx [%sp + 2047 + 0x148], %g6
ldx [%sp + 2047 + 0x150], %g7
wrpr %g0, 0x814, %pstate ! restore interrupt globals
ldx [%sp + 2047 + 0x0e8], %g1
ldx [%sp + 2047 + 0x0f0], %g2
ldx [%sp + 2047 + 0x0f8], %g3
ldx [%sp + 2047 + 0x100], %g4
ldx [%sp + 2047 + 0x108], %g5
ldx [%sp + 2047 + 0x110], %g6
ldx [%sp + 2047 + 0x118], %g7
wrpr %g0, 0x15, %pstate ! restore alternate globals
ldx [%sp + 2047 + 0x0b0], %g1
ldx [%sp + 2047 + 0x0b8], %g2
ldx [%sp + 2047 + 0x0c0], %g3
ldx [%sp + 2047 + 0x0c8], %g4
ldx [%sp + 2047 + 0x0d0], %g5
ldx [%sp + 2047 + 0x0d8], %g6
ldx [%sp + 2047 + 0x0e0], %g7
wrpr %l4, 0, %pstate ! restore original pstate
mov %l0, %g4
mov %l1, %g5
mov %l3, %g6
ret
restore

.globl prom_cif_callback
prom_cif_callback:
sethi %hi(p1275buf), %o1
or %o1, %lo(p1275buf), %o1
save %sp, -0x270, %sp
rdpr %pstate, %l4
wrpr %g0, 0x15, %pstate ! save PROM alternate globals
stx %g1, [%sp + 2047 + 0x0b0]
stx %g2, [%sp + 2047 + 0x0b8]
stx %g3, [%sp + 2047 + 0x0c0]
stx %g4, [%sp + 2047 + 0x0c8]
stx %g5, [%sp + 2047 + 0x0d0]
stx %g6, [%sp + 2047 + 0x0d8]
stx %g7, [%sp + 2047 + 0x0e0]
! restore Linux alternate globals
ldx [%sp + 2047 + 0x190], %g1
ldx [%sp + 2047 + 0x198], %g2
ldx [%sp + 2047 + 0x1a0], %g3
ldx [%sp + 2047 + 0x1a8], %g4
ldx [%sp + 2047 + 0x1b0], %g5
ldx [%sp + 2047 + 0x1b8], %g6
ldx [%sp + 2047 + 0x1c0], %g7
wrpr %g0, 0x814, %pstate ! save PROM interrupt globals
stx %g1, [%sp + 2047 + 0x0e8]
stx %g2, [%sp + 2047 + 0x0f0]
stx %g3, [%sp + 2047 + 0x0f8]
stx %g4, [%sp + 2047 + 0x100]
stx %g5, [%sp + 2047 + 0x108]
stx %g6, [%sp + 2047 + 0x110]
stx %g7, [%sp + 2047 + 0x118]
! restore Linux interrupt globals
ldx [%sp + 2047 + 0x1c8], %g1
ldx [%sp + 2047 + 0x1d0], %g2
ldx [%sp + 2047 + 0x1d8], %g3
ldx [%sp + 2047 + 0x1e0], %g4
ldx [%sp + 2047 + 0x1e8], %g5
ldx [%sp + 2047 + 0x1f0], %g6
ldx [%sp + 2047 + 0x1f8], %g7
wrpr %g0, 0x14, %pstate ! save PROM normal globals
stx %g1, [%sp + 2047 + 0x120]
stx %g2, [%sp + 2047 + 0x128]
stx %g3, [%sp + 2047 + 0x130]
stx %g4, [%sp + 2047 + 0x138]
stx %g5, [%sp + 2047 + 0x140]
stx %g6, [%sp + 2047 + 0x148]
stx %g7, [%sp + 2047 + 0x150]
! restore Linux normal globals
ldx [%sp + 2047 + 0x200], %g1
ldx [%sp + 2047 + 0x208], %g2
ldx [%sp + 2047 + 0x210], %g3
ldx [%sp + 2047 + 0x218], %g4
ldx [%sp + 2047 + 0x220], %g5
ldx [%sp + 2047 + 0x228], %g6
ldx [%sp + 2047 + 0x230], %g7
wrpr %g0, 0x414, %pstate ! save PROM mmu globals
stx %g1, [%sp + 2047 + 0x158]
stx %g2, [%sp + 2047 + 0x160]
stx %g3, [%sp + 2047 + 0x168]
stx %g4, [%sp + 2047 + 0x170]
stx %g5, [%sp + 2047 + 0x178]
stx %g6, [%sp + 2047 + 0x180]
stx %g7, [%sp + 2047 + 0x188]
! restore Linux mmu globals
ldx [%sp + 2047 + 0x238], %o0
ldx [%sp + 2047 + 0x240], %o1
ldx [%sp + 2047 + 0x248], %l2
ldx [%sp + 2047 + 0x250], %l3
ldx [%sp + 2047 + 0x258], %l5
ldx [%sp + 2047 + 0x260], %l6
ldx [%sp + 2047 + 0x268], %l7
! switch to Linux tba
sethi %hi(sparc64_ttable_tl0), %l1
rdpr %tba, %l0 ! save PROM tba
mov %o0, %g1
mov %o1, %g2
mov %l2, %g3
mov %l3, %g4
mov %l5, %g5
mov %l6, %g6
mov %l7, %g7
wrpr %l1, %tba ! install Linux tba
wrpr %l4, 0, %pstate ! restore PSTATE
save %sp, -192, %sp
TRAP_LOAD_THREAD_REG(%g6, %g1)
LOAD_PER_CPU_BASE(%g5, %g6, %g4, %g3, %o0)
ldx [%g6 + TI_TASK], %g4
call prom_world
mov %g0, %o0
mov 0, %o0
ldx [%i1 + 0x000], %l2
call %l2
mov %i0, %o0
mov %o0, %l1
call prom_world
or %g0, 1, %o0
wrpr %g0, 0x14, %pstate ! interrupts off
! restore PROM mmu globals
ldx [%sp + 2047 + 0x158], %o0
ldx [%sp + 2047 + 0x160], %o1
ldx [%sp + 2047 + 0x168], %l2
ldx [%sp + 2047 + 0x170], %l3
ldx [%sp + 2047 + 0x178], %l5
ldx [%sp + 2047 + 0x180], %l6
ldx [%sp + 2047 + 0x188], %l7
wrpr %g0, 0x414, %pstate ! restore PROM mmu globals
mov %o0, %g1
mov %o1, %g2
mov %l2, %g3
mov %l3, %g4
mov %l5, %g5
mov %l6, %g6
mov %l7, %g7
wrpr %l0, %tba ! restore PROM tba
wrpr %g0, 0x14, %pstate ! restore PROM normal globals
ldx [%sp + 2047 + 0x120], %g1
ldx [%sp + 2047 + 0x128], %g2
ldx [%sp + 2047 + 0x130], %g3
ldx [%sp + 2047 + 0x138], %g4
ldx [%sp + 2047 + 0x140], %g5
ldx [%sp + 2047 + 0x148], %g6
ldx [%sp + 2047 + 0x150], %g7
wrpr %g0, 0x814, %pstate ! restore PROM interrupt globals
ldx [%sp + 2047 + 0x0e8], %g1
ldx [%sp + 2047 + 0x0f0], %g2
ldx [%sp + 2047 + 0x0f8], %g3
ldx [%sp + 2047 + 0x100], %g4
ldx [%sp + 2047 + 0x108], %g5
ldx [%sp + 2047 + 0x110], %g6
ldx [%sp + 2047 + 0x118], %g7
wrpr %g0, 0x15, %pstate ! restore PROM alternate globals
ldx [%sp + 2047 + 0x0b0], %g1
ldx [%sp + 2047 + 0x0b8], %g2
ldx [%sp + 2047 + 0x0c0], %g3
ldx [%sp + 2047 + 0x0c8], %g4
ldx [%sp + 2047 + 0x0d0], %g5
ldx [%sp + 2047 + 0x0d8], %g6
ldx [%sp + 2047 + 0x0e0], %g7
wrpr %l4, 0, %pstate
mov 1, %o0
ret
restore %l1, 0, %o0

6 changes: 6 additions & 0 deletions include/asm-sparc64/cpudata.h
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,12 @@ struct gl_1insn_patch_entry {
unsigned int insn;
};
extern struct gl_1insn_patch_entry __gl_1insn_patch, __gl_1insn_patch_end;

struct gl_2insn_patch_entry {
unsigned int addr;
unsigned int insns[2];
};
extern struct gl_2insn_patch_entry __gl_2insn_patch, __gl_2insn_patch_end;
#endif /* !(__ASSEMBLY__) */

#define TRAP_PER_CPU_THREAD 0x00
Expand Down

0 comments on commit 45fec05

Please sign in to comment.