diff options
author | David S. Miller <davem@davemloft.net> | 2011-07-29 09:42:07 -0700 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2011-08-02 21:28:50 -0700 |
commit | ef7c4d4675d2a9206f913f26ca1a5cd41bff9d41 (patch) | |
tree | 88839b80e603ba395882df98b8a8c8f8385337b1 /arch/sparc/kernel/setup_64.c | |
parent | e95ade083939dcb4b0c51c1a2c8504ea9ef3d6ef (diff) |
sparc: Use popc if possible for hweight routines.
Just like powerpc, we code patch at boot time.
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.c | 27 |
1 files changed, 27 insertions, 0 deletions
diff --git a/arch/sparc/kernel/setup_64.c b/arch/sparc/kernel/setup_64.c index 242dbb3f31d..26d114187e1 100644 --- a/arch/sparc/kernel/setup_64.c +++ b/arch/sparc/kernel/setup_64.c @@ -272,6 +272,30 @@ void __init sun4v_patch(void) sun4v_hvapi_init(); } +static void __init popc_patch(void) +{ + struct popc_3insn_patch_entry *p3; + + p3 = &__popc_3insn_patch; + while (p3 < &__popc_3insn_patch_end) { + unsigned long addr = p3->addr; + + *(unsigned int *) (addr + 0) = p3->insns[0]; + wmb(); + __asm__ __volatile__("flush %0" : : "r" (addr + 0)); + + *(unsigned int *) (addr + 4) = p3->insns[1]; + wmb(); + __asm__ __volatile__("flush %0" : : "r" (addr + 4)); + + *(unsigned int *) (addr + 8) = p3->insns[2]; + wmb(); + __asm__ __volatile__("flush %0" : : "r" (addr + 4)); + + p3++; + } +} + #ifdef CONFIG_SMP void __init boot_cpu_id_too_large(int cpu) { @@ -424,6 +448,9 @@ static void __init init_sparc64_elf_hwcap(void) sparc64_elf_hwcap = cap | mdesc_caps; report_hwcaps(sparc64_elf_hwcap); + + if (sparc64_elf_hwcap & AV_SPARC_POPC) + popc_patch(); } void __init setup_arch(char **cmdline_p) |