aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sparc/kernel/setup_64.c
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2012-10-27 23:00:41 -0700
committerDavid S. Miller <davem@davemloft.net>2012-10-27 23:00:41 -0700
commite9b9eb59ffcdee09ec96b040f85c919618f4043e (patch)
tree30f93cc20aa577ec5b12f609641fdf84d0bd5124 /arch/sparc/kernel/setup_64.c
parentsparc64: Fix cpu strand yielding. (diff)
downloadlinux-dev-e9b9eb59ffcdee09ec96b040f85c919618f4043e.tar.xz
linux-dev-e9b9eb59ffcdee09ec96b040f85c919618f4043e.zip
sparc64: Use pause instruction when available.
In atomic backoff and cpu_relax(), use the pause instruction found on SPARC-T4 and later. It makes the cpu strand unselectable for the given number of cycles, unless an intervening disrupting trap occurs. Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'arch/sparc/kernel/setup_64.c')
-rw-r--r--arch/sparc/kernel/setup_64.c21
1 files changed, 21 insertions, 0 deletions
diff --git a/arch/sparc/kernel/setup_64.c b/arch/sparc/kernel/setup_64.c
index 0800e71d8a88..b45cff408de3 100644
--- a/arch/sparc/kernel/setup_64.c
+++ b/arch/sparc/kernel/setup_64.c
@@ -316,6 +316,25 @@ static void __init popc_patch(void)
}
}
+static void __init pause_patch(void)
+{
+ struct pause_patch_entry *p;
+
+ p = &__pause_patch;
+ while (p < &__pause_patch_end) {
+ unsigned long i, addr = p->addr;
+
+ for (i = 0; i < 3; i++) {
+ *(unsigned int *) (addr + (i * 4)) = p->insns[i];
+ wmb();
+ __asm__ __volatile__("flush %0"
+ : : "r" (addr + (i * 4)));
+ }
+
+ p++;
+ }
+}
+
#ifdef CONFIG_SMP
void __init boot_cpu_id_too_large(int cpu)
{
@@ -528,6 +547,8 @@ static void __init init_sparc64_elf_hwcap(void)
if (sparc64_elf_hwcap & AV_SPARC_POPC)
popc_patch();
+ if (sparc64_elf_hwcap & AV_SPARC_PAUSE)
+ pause_patch();
}
void __init setup_arch(char **cmdline_p)