aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/sparc/include/asm/bitops_64.h7
-rw-r--r--arch/sparc/kernel/entry.h7
-rw-r--r--arch/sparc/kernel/setup_64.c32
-rw-r--r--arch/sparc/kernel/sparc_ksyms_64.c4
-rw-r--r--arch/sparc/kernel/vmlinux.lds.S5
-rw-r--r--arch/sparc/lib/Makefile2
-rw-r--r--arch/sparc/lib/ffs.S84
7 files changed, 126 insertions, 15 deletions
diff --git a/arch/sparc/include/asm/bitops_64.h b/arch/sparc/include/asm/bitops_64.h
index 3588807baa6e..29011cc0e4be 100644
--- a/arch/sparc/include/asm/bitops_64.h
+++ b/arch/sparc/include/asm/bitops_64.h
@@ -26,16 +26,17 @@ extern void change_bit(unsigned long nr, volatile unsigned long *addr);
26#define smp_mb__before_clear_bit() barrier() 26#define smp_mb__before_clear_bit() barrier()
27#define smp_mb__after_clear_bit() barrier() 27#define smp_mb__after_clear_bit() barrier()
28 28
29#include <asm-generic/bitops/ffz.h>
30#include <asm-generic/bitops/__ffs.h>
31#include <asm-generic/bitops/fls.h> 29#include <asm-generic/bitops/fls.h>
32#include <asm-generic/bitops/__fls.h> 30#include <asm-generic/bitops/__fls.h>
33#include <asm-generic/bitops/fls64.h> 31#include <asm-generic/bitops/fls64.h>
34 32
35#ifdef __KERNEL__ 33#ifdef __KERNEL__
36 34
35extern int ffs(int x);
36extern unsigned long __ffs(unsigned long);
37
38#include <asm-generic/bitops/ffz.h>
37#include <asm-generic/bitops/sched.h> 39#include <asm-generic/bitops/sched.h>
38#include <asm-generic/bitops/ffs.h>
39 40
40/* 41/*
41 * hweightN: returns the hamming weight (i.e. the number 42 * hweightN: returns the hamming weight (i.e. the number
diff --git a/arch/sparc/kernel/entry.h b/arch/sparc/kernel/entry.h
index 16d1545d84fc..e27f8ea8656e 100644
--- a/arch/sparc/kernel/entry.h
+++ b/arch/sparc/kernel/entry.h
@@ -49,6 +49,13 @@ struct popc_3insn_patch_entry {
49extern struct popc_3insn_patch_entry __popc_3insn_patch, 49extern struct popc_3insn_patch_entry __popc_3insn_patch,
50 __popc_3insn_patch_end; 50 __popc_3insn_patch_end;
51 51
52struct popc_6insn_patch_entry {
53 unsigned int addr;
54 unsigned int insns[6];
55};
56extern struct popc_6insn_patch_entry __popc_6insn_patch,
57 __popc_6insn_patch_end;
58
52extern void __init per_cpu_patch(void); 59extern void __init per_cpu_patch(void);
53extern void __init sun4v_patch(void); 60extern void __init sun4v_patch(void);
54extern void __init boot_cpu_id_too_large(int cpu); 61extern 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 26d114187e10..3e9daea1653d 100644
--- a/arch/sparc/kernel/setup_64.c
+++ b/arch/sparc/kernel/setup_64.c
@@ -275,24 +275,34 @@ void __init sun4v_patch(void)
275static void __init popc_patch(void) 275static void __init popc_patch(void)
276{ 276{
277 struct popc_3insn_patch_entry *p3; 277 struct popc_3insn_patch_entry *p3;
278 struct popc_6insn_patch_entry *p6;
278 279
279 p3 = &__popc_3insn_patch; 280 p3 = &__popc_3insn_patch;
280 while (p3 < &__popc_3insn_patch_end) { 281 while (p3 < &__popc_3insn_patch_end) {
281 unsigned long addr = p3->addr; 282 unsigned long i, addr = p3->addr;
282 283
283 *(unsigned int *) (addr + 0) = p3->insns[0]; 284 for (i = 0; i < 3; i++) {
284 wmb(); 285 *(unsigned int *) (addr + (i * 4)) = p3->insns[i];
285 __asm__ __volatile__("flush %0" : : "r" (addr + 0)); 286 wmb();
287 __asm__ __volatile__("flush %0"
288 : : "r" (addr + (i * 4)));
289 }
286 290
287 *(unsigned int *) (addr + 4) = p3->insns[1]; 291 p3++;
288 wmb(); 292 }
289 __asm__ __volatile__("flush %0" : : "r" (addr + 4));
290 293
291 *(unsigned int *) (addr + 8) = p3->insns[2]; 294 p6 = &__popc_6insn_patch;
292 wmb(); 295 while (p6 < &__popc_6insn_patch_end) {
293 __asm__ __volatile__("flush %0" : : "r" (addr + 4)); 296 unsigned long i, addr = p6->addr;
294 297
295 p3++; 298 for (i = 0; i < 6; i++) {
299 *(unsigned int *) (addr + (i * 4)) = p6->insns[i];
300 wmb();
301 __asm__ __volatile__("flush %0"
302 : : "r" (addr + (i * 4)));
303 }
304
305 p6++;
296 } 306 }
297} 307}
298 308
diff --git a/arch/sparc/kernel/sparc_ksyms_64.c b/arch/sparc/kernel/sparc_ksyms_64.c
index d0ee65aced0d..83b47ab02d96 100644
--- a/arch/sparc/kernel/sparc_ksyms_64.c
+++ b/arch/sparc/kernel/sparc_ksyms_64.c
@@ -45,5 +45,9 @@ EXPORT_SYMBOL(__arch_hweight16);
45EXPORT_SYMBOL(__arch_hweight32); 45EXPORT_SYMBOL(__arch_hweight32);
46EXPORT_SYMBOL(__arch_hweight64); 46EXPORT_SYMBOL(__arch_hweight64);
47 47
48/* from ffs_ffz.S */
49EXPORT_SYMBOL(ffs);
50EXPORT_SYMBOL(__ffs);
51
48/* Exporting a symbol from /init/main.c */ 52/* Exporting a symbol from /init/main.c */
49EXPORT_SYMBOL(saved_command_line); 53EXPORT_SYMBOL(saved_command_line);
diff --git a/arch/sparc/kernel/vmlinux.lds.S b/arch/sparc/kernel/vmlinux.lds.S
index de20c14625eb..94a954892d3f 100644
--- a/arch/sparc/kernel/vmlinux.lds.S
+++ b/arch/sparc/kernel/vmlinux.lds.S
@@ -112,6 +112,11 @@ SECTIONS
112 *(.popc_3insn_patch) 112 *(.popc_3insn_patch)
113 __popc_3insn_patch_end = .; 113 __popc_3insn_patch_end = .;
114 } 114 }
115 .popc_6insn_patch : {
116 __popc_6insn_patch = .;
117 *(.popc_6insn_patch)
118 __popc_6insn_patch_end = .;
119 }
115 PERCPU_SECTION(SMP_CACHE_BYTES) 120 PERCPU_SECTION(SMP_CACHE_BYTES)
116 121
117 . = ALIGN(PAGE_SIZE); 122 . = ALIGN(PAGE_SIZE);
diff --git a/arch/sparc/lib/Makefile b/arch/sparc/lib/Makefile
index 11c850a9b66f..a3fc4375a150 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
37lib-$(CONFIG_SPARC64) += GENpatch.o GENpage.o GENbzero.o 37lib-$(CONFIG_SPARC64) += GENpatch.o GENpage.o GENbzero.o
38 38
39lib-$(CONFIG_SPARC64) += copy_in_user.o user_fixup.o memmove.o 39lib-$(CONFIG_SPARC64) += copy_in_user.o user_fixup.o memmove.o
40lib-$(CONFIG_SPARC64) += mcount.o ipcsum.o xor.o hweight.o 40lib-$(CONFIG_SPARC64) += mcount.o ipcsum.o xor.o hweight.o ffs.o
41 41
42obj-y += iomap.o 42obj-y += iomap.o
43obj-$(CONFIG_SPARC32) += atomic32.o 43obj-$(CONFIG_SPARC32) += atomic32.o
diff --git a/arch/sparc/lib/ffs.S b/arch/sparc/lib/ffs.S
new file mode 100644
index 000000000000..b39389f69899
--- /dev/null
+++ b/arch/sparc/lib/ffs.S
@@ -0,0 +1,84 @@
1#include <linux/linkage.h>
2
3 .register %g2,#scratch
4
5 .text
6 .align 32
7
8ENTRY(ffs)
9 brnz,pt %o0, 1f
10 mov 1, %o1
11 retl
12 clr %o0
13 nop
14 nop
15ENTRY(__ffs)
16 sllx %o0, 32, %g1 /* 1 */
17 srlx %o0, 32, %g2
18
19 clr %o1 /* 2 */
20 movrz %g1, %g2, %o0
21
22 movrz %g1, 32, %o1 /* 3 */
231: clr %o2
24
25 sllx %o0, (64 - 16), %g1 /* 4 */
26 srlx %o0, 16, %g2
27
28 movrz %g1, %g2, %o0 /* 5 */
29 clr %o3
30
31 movrz %g1, 16, %o2 /* 6 */
32 clr %o4
33
34 and %o0, 0xff, %g1 /* 7 */
35 srlx %o0, 8, %g2
36
37 movrz %g1, %g2, %o0 /* 8 */
38 clr %o5
39
40 movrz %g1, 8, %o3 /* 9 */
41 add %o2, %o1, %o2
42
43 and %o0, 0xf, %g1 /* 10 */
44 srlx %o0, 4, %g2
45
46 movrz %g1, %g2, %o0 /* 11 */
47 add %o2, %o3, %o2
48
49 movrz %g1, 4, %o4 /* 12 */
50
51 and %o0, 0x3, %g1 /* 13 */
52 srlx %o0, 2, %g2
53
54 movrz %g1, %g2, %o0 /* 14 */
55 add %o2, %o4, %o2
56
57 movrz %g1, 2, %o5 /* 15 */
58
59 and %o0, 0x1, %g1 /* 16 */
60
61 add %o2, %o5, %o2 /* 17 */
62 xor %g1, 0x1, %g1
63
64 retl /* 18 */
65 add %o2, %g1, %o0
66ENDPROC(ffs)
67ENDPROC(__ffs)
68
69 .section .popc_6insn_patch, "ax"
70 .word ffs
71 brz,pn %o0, 98f
72 neg %o0, %g1
73 xnor %o0, %g1, %o1
74 popc %o1, %o0
7598: retl
76 nop
77 .word __ffs
78 neg %o0, %g1
79 xnor %o0, %g1, %o1
80 popc %o1, %o0
81 retl
82 sub %o0, 1, %o0
83 nop
84 .previous