summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid S. Miller <davem@sunset.davemloft.net>2006-02-06 06:29:28 +0100
committerDavid S. Miller <davem@sunset.davemloft.net>2006-03-20 10:11:48 +0100
commit936f482af1743141d637483ec10eb881537c26dc (patch)
tree913da89a4d9f4038c510c9ecf2f5957b0f6d167f
parent[SPARC64]: Fill dead cycles on trap entry with real work. (diff)
downloadlinux-936f482af1743141d637483ec10eb881537c26dc.tar.xz
linux-936f482af1743141d637483ec10eb881537c26dc.zip
[SPARC64]: Add initial code to twiddle %gl on trap entry/exit.
Instead of setting/clearing PSTATE_AG we have to change the %gl register value on sun4v. Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--arch/sparc64/kernel/etrap.S17
-rw-r--r--arch/sparc64/kernel/rtrap.S16
-rw-r--r--arch/sparc64/kernel/setup.c20
-rw-r--r--arch/sparc64/kernel/vmlinux.lds.S3
-rw-r--r--include/asm-sparc64/cpudata.h5
-rw-r--r--include/asm-sparc64/head.h4
6 files changed, 62 insertions, 3 deletions
diff --git a/arch/sparc64/kernel/etrap.S b/arch/sparc64/kernel/etrap.S
index f2556146a735..4d644949ad49 100644
--- a/arch/sparc64/kernel/etrap.S
+++ b/arch/sparc64/kernel/etrap.S
@@ -102,7 +102,14 @@ etrap_save: save %g2, -STACK_BIAS, %sp
2: mov %g4, %l4
mov %g5, %l5
add %g7, 4, %l2
- wrpr %g0, ETRAP_PSTATE1, %pstate
+
+ /* Go to trap time globals so we can save them. */
+661: wrpr %g0, ETRAP_PSTATE1, %pstate
+ .section .gl_1insn_patch, "ax"
+ .word 661b
+ SET_GL(0)
+ .previous
+
stx %g1, [%sp + PTREGS_OFF + PT_V9_G1]
stx %g2, [%sp + PTREGS_OFF + PT_V9_G2]
sllx %l7, 24, %l7
@@ -195,9 +202,15 @@ etraptl1: /* Save tstate/tpc/tnpc of TL 1-->4 and the tl register itself.
rdpr %tt, %g3
stx %g3, [%g2 + STACK_BIAS + 0x78]
- wrpr %g1, %tl
stx %g1, [%g2 + STACK_BIAS + 0x80]
+ wrpr %g0, 1, %tl
+661: nop
+ .section .gl_1insn_patch, "ax"
+ .word 661b
+ SET_GL(1)
+ .previous
+
rdpr %tstate, %g1
sub %g2, STACKFRAME_SZ + TRACEREG_SZ - STACK_BIAS, %g2
ba,pt %xcc, 1b
diff --git a/arch/sparc64/kernel/rtrap.S b/arch/sparc64/kernel/rtrap.S
index ecfbbdc56125..e6130956307f 100644
--- a/arch/sparc64/kernel/rtrap.S
+++ b/arch/sparc64/kernel/rtrap.S
@@ -230,7 +230,14 @@ rt_continue: ldx [%sp + PTREGS_OFF + PT_V9_G1], %g1
1:
ldx [%sp + PTREGS_OFF + PT_V9_G6], %g6
ldx [%sp + PTREGS_OFF + PT_V9_G7], %g7
- wrpr %g0, RTRAP_PSTATE_AG_IRQOFF, %pstate
+
+ /* Normal globals are restored, go to trap globals. */
+661: wrpr %g0, RTRAP_PSTATE_AG_IRQOFF, %pstate
+ .section .gl_1insn_patch, "ax"
+ .word 661b
+ SET_GL(1)
+ .previous
+
ldx [%sp + PTREGS_OFF + PT_V9_I0], %i0
ldx [%sp + PTREGS_OFF + PT_V9_I1], %i1
@@ -304,6 +311,13 @@ user_rtt_fill_fixup:
mov %g6, %l1
wrpr %g0, 0x0, %tl
wrpr %g0, RTRAP_PSTATE, %pstate
+
+661: nop
+ .section .gl_1insn_patch, "ax"
+ .word 661b
+ SET_GL(0)
+ .previous
+
mov %l1, %g6
ldx [%g6 + TI_TASK], %g4
LOAD_PER_CPU_BASE(%g5, %g6, %g1, %g2, %g3)
diff --git a/arch/sparc64/kernel/setup.c b/arch/sparc64/kernel/setup.c
index 2918ed3eb1ba..aaab319ad885 100644
--- a/arch/sparc64/kernel/setup.c
+++ b/arch/sparc64/kernel/setup.c
@@ -545,6 +545,24 @@ static void __init per_cpu_patch(void)
#endif
}
+static void __init gl_patch(void)
+{
+ struct gl_1insn_patch_entry *p;
+
+ if (tlb_type != hypervisor)
+ return;
+
+ p = &__gl_1insn_patch;
+ while (p < &__gl_1insn_patch_end) {
+ unsigned long addr = p->addr;
+
+ *(unsigned int *) (addr + 0) = p->insn;
+ __asm__ __volatile__("flush %0" : : "r" (addr + 0));
+
+ p++;
+ }
+}
+
void __init setup_arch(char **cmdline_p)
{
/* Initialize PROM console and command line. */
@@ -567,6 +585,8 @@ void __init setup_arch(char **cmdline_p)
*/
per_cpu_patch();
+ gl_patch();
+
boot_flags_init(*cmdline_p);
idprom_init();
diff --git a/arch/sparc64/kernel/vmlinux.lds.S b/arch/sparc64/kernel/vmlinux.lds.S
index 1639d9c935c3..482d1ed87f4d 100644
--- a/arch/sparc64/kernel/vmlinux.lds.S
+++ b/arch/sparc64/kernel/vmlinux.lds.S
@@ -77,6 +77,9 @@ SECTIONS
__cpuid_patch = .;
.cpuid_patch : { *(.cpuid_patch) }
__cpuid_patch_end = .;
+ __gl_1insn_patch = .;
+ .gl_1insn_patch : { *(.gl_1insn_patch) }
+ __gl_1insn_patch_end = .;
. = ALIGN(8192);
__initramfs_start = .;
.init.ramfs : { *(.init.ramfs) }
diff --git a/include/asm-sparc64/cpudata.h b/include/asm-sparc64/cpudata.h
index 4f28a85c1043..8666440c89af 100644
--- a/include/asm-sparc64/cpudata.h
+++ b/include/asm-sparc64/cpudata.h
@@ -73,6 +73,11 @@ struct cpuid_patch_entry {
extern struct cpuid_patch_entry __cpuid_patch, __cpuid_patch_end;
#endif
+struct gl_1insn_patch_entry {
+ unsigned int addr;
+ unsigned int insn;
+};
+extern struct gl_1insn_patch_entry __gl_1insn_patch, __gl_1insn_patch_end;
#endif /* !(__ASSEMBLY__) */
#define TRAP_PER_CPU_THREAD 0x00
diff --git a/include/asm-sparc64/head.h b/include/asm-sparc64/head.h
index 731c842f3d11..ff76c0981b63 100644
--- a/include/asm-sparc64/head.h
+++ b/include/asm-sparc64/head.h
@@ -4,6 +4,10 @@
#include <asm/pstate.h>
+ /* wrpr %g0, val, %gl */
+#define SET_GL(val) \
+ .word 0xa1902000 | val
+
#define KERNBASE 0x400000
#define PTREGS_OFF (STACK_BIAS + STACKFRAME_SZ)