diff options
| -rw-r--r-- | arch/sparc/include/asm/bitops_64.h | 42 | ||||
| -rw-r--r-- | arch/sparc/kernel/entry.h | 7 | ||||
| -rw-r--r-- | arch/sparc/kernel/setup_64.c | 27 | ||||
| -rw-r--r-- | arch/sparc/kernel/sparc_ksyms_64.c | 7 | ||||
| -rw-r--r-- | arch/sparc/kernel/vmlinux.lds.S | 6 | ||||
| -rw-r--r-- | arch/sparc/lib/Makefile | 2 | ||||
| -rw-r--r-- | arch/sparc/lib/hweight.S | 51 |
7 files changed, 102 insertions, 40 deletions
diff --git a/arch/sparc/include/asm/bitops_64.h b/arch/sparc/include/asm/bitops_64.h index 325e295d60de..3588807baa6e 100644 --- a/arch/sparc/include/asm/bitops_64.h +++ b/arch/sparc/include/asm/bitops_64.h | |||
| @@ -42,45 +42,11 @@ extern void change_bit(unsigned long nr, volatile unsigned long *addr); | |||
| 42 | * of bits set) of a N-bit word | 42 | * of bits set) of a N-bit word |
| 43 | */ | 43 | */ |
| 44 | 44 | ||
| 45 | #ifdef ULTRA_HAS_POPULATION_COUNT | 45 | extern unsigned long __arch_hweight64(__u64 w); |
| 46 | extern unsigned int __arch_hweight32(unsigned int w); | ||
| 47 | extern unsigned int __arch_hweight16(unsigned int w); | ||
| 48 | extern unsigned int __arch_hweight8(unsigned int w); | ||
| 46 | 49 | ||
| 47 | static inline unsigned int __arch_hweight64(unsigned long w) | ||
| 48 | { | ||
| 49 | unsigned int res; | ||
| 50 | |||
| 51 | __asm__ ("popc %1,%0" : "=r" (res) : "r" (w)); | ||
| 52 | return res; | ||
| 53 | } | ||
| 54 | |||
| 55 | static inline unsigned int __arch_hweight32(unsigned int w) | ||
| 56 | { | ||
| 57 | unsigned int res; | ||
| 58 | |||
| 59 | __asm__ ("popc %1,%0" : "=r" (res) : "r" (w & 0xffffffff)); | ||
| 60 | return res; | ||
| 61 | } | ||
| 62 | |||
| 63 | static inline unsigned int __arch_hweight16(unsigned int w) | ||
| 64 | { | ||
| 65 | unsigned int res; | ||
| 66 | |||
| 67 | __asm__ ("popc %1,%0" : "=r" (res) : "r" (w & 0xffff)); | ||
| 68 | return res; | ||
| 69 | } | ||
| 70 | |||
| 71 | static inline unsigned int __arch_hweight8(unsigned int w) | ||
| 72 | { | ||
| 73 | unsigned int res; | ||
| 74 | |||
| 75 | __asm__ ("popc %1,%0" : "=r" (res) : "r" (w & 0xff)); | ||
| 76 | return res; | ||
| 77 | } | ||
| 78 | |||
| 79 | #else | ||
| 80 | |||
| 81 | #include <asm-generic/bitops/arch_hweight.h> | ||
| 82 | |||
| 83 | #endif | ||
| 84 | #include <asm-generic/bitops/const_hweight.h> | 50 | #include <asm-generic/bitops/const_hweight.h> |
| 85 | #include <asm-generic/bitops/lock.h> | 51 | #include <asm-generic/bitops/lock.h> |
| 86 | #endif /* __KERNEL__ */ | 52 | #endif /* __KERNEL__ */ |
diff --git a/arch/sparc/kernel/entry.h b/arch/sparc/kernel/entry.h index d1f1361c4167..16d1545d84fc 100644 --- a/arch/sparc/kernel/entry.h +++ b/arch/sparc/kernel/entry.h | |||
| @@ -42,6 +42,13 @@ extern void fpsave(unsigned long *fpregs, unsigned long *fsr, | |||
| 42 | extern void fpload(unsigned long *fpregs, unsigned long *fsr); | 42 | extern void fpload(unsigned long *fpregs, unsigned long *fsr); |
| 43 | 43 | ||
| 44 | #else /* CONFIG_SPARC32 */ | 44 | #else /* CONFIG_SPARC32 */ |
| 45 | struct popc_3insn_patch_entry { | ||
| 46 | unsigned int addr; | ||
| 47 | unsigned int insns[3]; | ||
| 48 | }; | ||
| 49 | extern struct popc_3insn_patch_entry __popc_3insn_patch, | ||
| 50 | __popc_3insn_patch_end; | ||
| 51 | |||
| 45 | extern void __init per_cpu_patch(void); | 52 | extern void __init per_cpu_patch(void); |
| 46 | extern void __init sun4v_patch(void); | 53 | extern void __init sun4v_patch(void); |
| 47 | extern void __init boot_cpu_id_too_large(int cpu); | 54 | extern void __init boot_cpu_id_too_large(int cpu); |
diff --git a/arch/sparc/kernel/setup_64.c b/arch/sparc/kernel/setup_64.c index 242dbb3f31d2..26d114187e10 100644 --- a/arch/sparc/kernel/setup_64.c +++ b/arch/sparc/kernel/setup_64.c | |||
| @@ -272,6 +272,30 @@ void __init sun4v_patch(void) | |||
| 272 | sun4v_hvapi_init(); | 272 | sun4v_hvapi_init(); |
| 273 | } | 273 | } |
| 274 | 274 | ||
| 275 | static void __init popc_patch(void) | ||
| 276 | { | ||
| 277 | struct popc_3insn_patch_entry *p3; | ||
| 278 | |||
| 279 | p3 = &__popc_3insn_patch; | ||
| 280 | while (p3 < &__popc_3insn_patch_end) { | ||
| 281 | unsigned long addr = p3->addr; | ||
| 282 | |||
| 283 | *(unsigned int *) (addr + 0) = p3->insns[0]; | ||
| 284 | wmb(); | ||
| 285 | __asm__ __volatile__("flush %0" : : "r" (addr + 0)); | ||
| 286 | |||
| 287 | *(unsigned int *) (addr + 4) = p3->insns[1]; | ||
| 288 | wmb(); | ||
| 289 | __asm__ __volatile__("flush %0" : : "r" (addr + 4)); | ||
| 290 | |||
| 291 | *(unsigned int *) (addr + 8) = p3->insns[2]; | ||
| 292 | wmb(); | ||
| 293 | __asm__ __volatile__("flush %0" : : "r" (addr + 4)); | ||
| 294 | |||
| 295 | p3++; | ||
| 296 | } | ||
| 297 | } | ||
| 298 | |||
| 275 | #ifdef CONFIG_SMP | 299 | #ifdef CONFIG_SMP |
| 276 | void __init boot_cpu_id_too_large(int cpu) | 300 | void __init boot_cpu_id_too_large(int cpu) |
| 277 | { | 301 | { |
| @@ -424,6 +448,9 @@ static void __init init_sparc64_elf_hwcap(void) | |||
| 424 | sparc64_elf_hwcap = cap | mdesc_caps; | 448 | sparc64_elf_hwcap = cap | mdesc_caps; |
| 425 | 449 | ||
| 426 | report_hwcaps(sparc64_elf_hwcap); | 450 | report_hwcaps(sparc64_elf_hwcap); |
| 451 | |||
| 452 | if (sparc64_elf_hwcap & AV_SPARC_POPC) | ||
| 453 | popc_patch(); | ||
| 427 | } | 454 | } |
| 428 | 455 | ||
| 429 | void __init setup_arch(char **cmdline_p) | 456 | void __init setup_arch(char **cmdline_p) |
diff --git a/arch/sparc/kernel/sparc_ksyms_64.c b/arch/sparc/kernel/sparc_ksyms_64.c index 372ad59c4cba..d0ee65aced0d 100644 --- a/arch/sparc/kernel/sparc_ksyms_64.c +++ b/arch/sparc/kernel/sparc_ksyms_64.c | |||
| @@ -8,6 +8,7 @@ | |||
| 8 | #include <linux/module.h> | 8 | #include <linux/module.h> |
| 9 | #include <linux/pci.h> | 9 | #include <linux/pci.h> |
| 10 | #include <linux/init.h> | 10 | #include <linux/init.h> |
| 11 | #include <linux/bitops.h> | ||
| 11 | 12 | ||
| 12 | #include <asm/system.h> | 13 | #include <asm/system.h> |
| 13 | #include <asm/cpudata.h> | 14 | #include <asm/cpudata.h> |
| @@ -38,5 +39,11 @@ EXPORT_SYMBOL(sun4v_niagara_setperf); | |||
| 38 | EXPORT_SYMBOL(sun4v_niagara2_getperf); | 39 | EXPORT_SYMBOL(sun4v_niagara2_getperf); |
| 39 | EXPORT_SYMBOL(sun4v_niagara2_setperf); | 40 | EXPORT_SYMBOL(sun4v_niagara2_setperf); |
| 40 | 41 | ||
| 42 | /* from hweight.S */ | ||
| 43 | EXPORT_SYMBOL(__arch_hweight8); | ||
| 44 | EXPORT_SYMBOL(__arch_hweight16); | ||
| 45 | EXPORT_SYMBOL(__arch_hweight32); | ||
| 46 | EXPORT_SYMBOL(__arch_hweight64); | ||
| 47 | |||
| 41 | /* Exporting a symbol from /init/main.c */ | 48 | /* Exporting a symbol from /init/main.c */ |
| 42 | EXPORT_SYMBOL(saved_command_line); | 49 | EXPORT_SYMBOL(saved_command_line); |
diff --git a/arch/sparc/kernel/vmlinux.lds.S b/arch/sparc/kernel/vmlinux.lds.S index c0220759003e..de20c14625eb 100644 --- a/arch/sparc/kernel/vmlinux.lds.S +++ b/arch/sparc/kernel/vmlinux.lds.S | |||
| @@ -107,7 +107,11 @@ SECTIONS | |||
| 107 | *(.sun4v_2insn_patch) | 107 | *(.sun4v_2insn_patch) |
| 108 | __sun4v_2insn_patch_end = .; | 108 | __sun4v_2insn_patch_end = .; |
| 109 | } | 109 | } |
| 110 | 110 | .popc_3insn_patch : { | |
| 111 | __popc_3insn_patch = .; | ||
| 112 | *(.popc_3insn_patch) | ||
| 113 | __popc_3insn_patch_end = .; | ||
| 114 | } | ||
| 111 | PERCPU_SECTION(SMP_CACHE_BYTES) | 115 | PERCPU_SECTION(SMP_CACHE_BYTES) |
| 112 | 116 | ||
| 113 | . = ALIGN(PAGE_SIZE); | 117 | . = ALIGN(PAGE_SIZE); |
diff --git a/arch/sparc/lib/Makefile b/arch/sparc/lib/Makefile index c25f94d28df8..11c850a9b66f 100644 --- a/arch/sparc/lib/Makefile +++ b/arch/sparc/lib/Makefile | |||
| @@ -37,7 +37,7 @@ lib-$(CONFIG_SPARC64) += GENmemcpy.o GENcopy_from_user.o GENcopy_to_user.o | |||
| 37 | lib-$(CONFIG_SPARC64) += GENpatch.o GENpage.o GENbzero.o | 37 | lib-$(CONFIG_SPARC64) += GENpatch.o GENpage.o GENbzero.o |
| 38 | 38 | ||
| 39 | lib-$(CONFIG_SPARC64) += copy_in_user.o user_fixup.o memmove.o | 39 | lib-$(CONFIG_SPARC64) += copy_in_user.o user_fixup.o memmove.o |
| 40 | lib-$(CONFIG_SPARC64) += mcount.o ipcsum.o xor.o | 40 | lib-$(CONFIG_SPARC64) += mcount.o ipcsum.o xor.o hweight.o |
| 41 | 41 | ||
| 42 | obj-y += iomap.o | 42 | obj-y += iomap.o |
| 43 | obj-$(CONFIG_SPARC32) += atomic32.o | 43 | obj-$(CONFIG_SPARC32) += atomic32.o |
diff --git a/arch/sparc/lib/hweight.S b/arch/sparc/lib/hweight.S new file mode 100644 index 000000000000..95414e0a6808 --- /dev/null +++ b/arch/sparc/lib/hweight.S | |||
| @@ -0,0 +1,51 @@ | |||
| 1 | #include <linux/linkage.h> | ||
| 2 | |||
| 3 | .text | ||
| 4 | .align 32 | ||
| 5 | ENTRY(__arch_hweight8) | ||
| 6 | ba,pt %xcc, __sw_hweight8 | ||
| 7 | nop | ||
| 8 | nop | ||
| 9 | ENDPROC(__arch_hweight8) | ||
| 10 | .section .popc_3insn_patch, "ax" | ||
| 11 | .word __arch_hweight8 | ||
| 12 | sllx %o0, 64-8, %g1 | ||
| 13 | retl | ||
| 14 | popc %g1, %o0 | ||
| 15 | .previous | ||
| 16 | |||
| 17 | ENTRY(__arch_hweight16) | ||
| 18 | ba,pt %xcc, __sw_hweight16 | ||
| 19 | nop | ||
| 20 | nop | ||
| 21 | ENDPROC(__arch_hweight16) | ||
| 22 | .section .popc_3insn_patch, "ax" | ||
| 23 | .word __arch_hweight16 | ||
| 24 | sllx %o0, 64-16, %g1 | ||
| 25 | retl | ||
| 26 | popc %g1, %o0 | ||
| 27 | .previous | ||
| 28 | |||
| 29 | ENTRY(__arch_hweight32) | ||
| 30 | ba,pt %xcc, __sw_hweight32 | ||
| 31 | nop | ||
| 32 | nop | ||
| 33 | ENDPROC(__arch_hweight32) | ||
| 34 | .section .popc_3insn_patch, "ax" | ||
| 35 | .word __arch_hweight32 | ||
| 36 | sllx %o0, 64-32, %g1 | ||
| 37 | retl | ||
| 38 | popc %g1, %o0 | ||
| 39 | .previous | ||
| 40 | |||
| 41 | ENTRY(__arch_hweight64) | ||
| 42 | ba,pt %xcc, __sw_hweight64 | ||
| 43 | nop | ||
| 44 | nop | ||
| 45 | ENDPROC(__arch_hweight64) | ||
| 46 | .section .popc_3insn_patch, "ax" | ||
| 47 | .word __arch_hweight64 | ||
| 48 | retl | ||
| 49 | popc %o0, %o0 | ||
| 50 | nop | ||
| 51 | .previous | ||
