aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@woody.linux-foundation.org>2007-08-09 11:27:25 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-08-09 11:27:25 -0400
commite7bc15a9ad07269c48732e9a9874e5938b4700ee (patch)
treedfe010e71720a534a15bb38cd454c7f80db2b1f3 /arch
parent5a0276b7ae1fcd90cea07f65452aebbd1b0743c5 (diff)
parentb434e71933aa0519ee042c01419db76b7dcc058e (diff)
Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/sparc-2.6
* 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/sparc-2.6: [SPARC64]: Fix memory leak when cpu hotplugging. [SPARC64]: Do not assume sun4v chips have load-twin/store-init support. [SPARC64]: Fix hard-coding of cpu type output in /proc/cpuinfo on sun4v. [SPARC]: Centralize find_in_proplist() instead of duplicating N times.
Diffstat (limited to 'arch')
-rw-r--r--arch/sparc/kernel/prom.c15
-rw-r--r--arch/sparc64/kernel/cpu.c36
-rw-r--r--arch/sparc64/kernel/head.S111
-rw-r--r--arch/sparc64/kernel/hvtramp.S7
-rw-r--r--arch/sparc64/kernel/irq.c74
-rw-r--r--arch/sparc64/kernel/mdesc.c24
-rw-r--r--arch/sparc64/kernel/prom.c15
-rw-r--r--arch/sparc64/kernel/smp.c5
-rw-r--r--arch/sparc64/kernel/sparc64_ksyms.c1
-rw-r--r--arch/sparc64/kernel/trampoline.S7
-rw-r--r--arch/sparc64/kernel/vio.c19
-rw-r--r--arch/sparc64/lib/GENbzero.S160
-rw-r--r--arch/sparc64/lib/GENcopy_from_user.S34
-rw-r--r--arch/sparc64/lib/GENcopy_to_user.S38
-rw-r--r--arch/sparc64/lib/GENmemcpy.S121
-rw-r--r--arch/sparc64/lib/GENpage.S77
-rw-r--r--arch/sparc64/lib/GENpatch.S33
-rw-r--r--arch/sparc64/lib/Makefile4
18 files changed, 666 insertions, 115 deletions
diff --git a/arch/sparc/kernel/prom.c b/arch/sparc/kernel/prom.c
index 39fbd3c8ab0b..cd4fb79aa3a8 100644
--- a/arch/sparc/kernel/prom.c
+++ b/arch/sparc/kernel/prom.c
@@ -102,6 +102,21 @@ int of_set_property(struct device_node *dp, const char *name, void *val, int len
102} 102}
103EXPORT_SYMBOL(of_set_property); 103EXPORT_SYMBOL(of_set_property);
104 104
105int of_find_in_proplist(const char *list, const char *match, int len)
106{
107 while (len > 0) {
108 int l;
109
110 if (!strcmp(list, match))
111 return 1;
112 l = strlen(list) + 1;
113 list += l;
114 len -= l;
115 }
116 return 0;
117}
118EXPORT_SYMBOL(of_find_in_proplist);
119
105static unsigned int prom_early_allocated; 120static unsigned int prom_early_allocated;
106 121
107static void * __init prom_early_alloc(unsigned long size) 122static void * __init prom_early_alloc(unsigned long size)
diff --git a/arch/sparc64/kernel/cpu.c b/arch/sparc64/kernel/cpu.c
index 7eb81d3954d9..e43db73f2b91 100644
--- a/arch/sparc64/kernel/cpu.c
+++ b/arch/sparc64/kernel/cpu.c
@@ -1,7 +1,7 @@
1/* cpu.c: Dinky routines to look for the kind of Sparc cpu 1/* cpu.c: Dinky routines to look for the kind of Sparc cpu
2 * we are on. 2 * we are on.
3 * 3 *
4 * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) 4 * Copyright (C) 1996, 2007 David S. Miller (davem@davemloft.net)
5 */ 5 */
6 6
7#include <linux/kernel.h> 7#include <linux/kernel.h>
@@ -13,6 +13,7 @@
13#include <asm/fpumacro.h> 13#include <asm/fpumacro.h>
14#include <asm/cpudata.h> 14#include <asm/cpudata.h>
15#include <asm/spitfire.h> 15#include <asm/spitfire.h>
16#include <asm/oplib.h>
16 17
17DEFINE_PER_CPU(cpuinfo_sparc, __cpu_data) = { 0 }; 18DEFINE_PER_CPU(cpuinfo_sparc, __cpu_data) = { 0 };
18 19
@@ -61,21 +62,40 @@ struct cpu_iu_info linux_sparc_chips[] = {
61 62
62#define NSPARCCHIPS ARRAY_SIZE(linux_sparc_chips) 63#define NSPARCCHIPS ARRAY_SIZE(linux_sparc_chips)
63 64
64char *sparc_cpu_type = "cpu-oops"; 65char *sparc_cpu_type;
65char *sparc_fpu_type = "fpu-oops"; 66char *sparc_fpu_type;
66 67
67unsigned int fsr_storage; 68unsigned int fsr_storage;
68 69
70static void __init sun4v_cpu_probe(void)
71{
72 switch (sun4v_chip_type) {
73 case SUN4V_CHIP_NIAGARA1:
74 sparc_cpu_type = "UltraSparc T1 (Niagara)";
75 sparc_fpu_type = "UltraSparc T1 integrated FPU";
76 break;
77
78 case SUN4V_CHIP_NIAGARA2:
79 sparc_cpu_type = "UltraSparc T2 (Niagara2)";
80 sparc_fpu_type = "UltraSparc T2 integrated FPU";
81 break;
82
83 default:
84 printk(KERN_WARNING "CPU: Unknown sun4v cpu type [%s]\n",
85 prom_cpu_compatible);
86 sparc_cpu_type = "Unknown SUN4V CPU";
87 sparc_fpu_type = "Unknown SUN4V FPU";
88 break;
89 }
90}
91
69void __init cpu_probe(void) 92void __init cpu_probe(void)
70{ 93{
71 unsigned long ver, fpu_vers, manuf, impl, fprs; 94 unsigned long ver, fpu_vers, manuf, impl, fprs;
72 int i; 95 int i;
73 96
74 if (tlb_type == hypervisor) { 97 if (tlb_type == hypervisor)
75 sparc_cpu_type = "UltraSparc T1 (Niagara)"; 98 return sun4v_cpu_probe();
76 sparc_fpu_type = "UltraSparc T1 integrated FPU";
77 return;
78 }
79 99
80 fprs = fprs_read(); 100 fprs = fprs_read();
81 fprs_write(FPRS_FEF); 101 fprs_write(FPRS_FEF);
diff --git a/arch/sparc64/kernel/head.S b/arch/sparc64/kernel/head.S
index 9dbd833d79d6..ac18bd8e273f 100644
--- a/arch/sparc64/kernel/head.S
+++ b/arch/sparc64/kernel/head.S
@@ -97,7 +97,8 @@ sparc64_boot:
97 .globl prom_map_name, prom_unmap_name, prom_mmu_ihandle_cache 97 .globl prom_map_name, prom_unmap_name, prom_mmu_ihandle_cache
98 .globl prom_boot_mapped_pc, prom_boot_mapping_mode 98 .globl prom_boot_mapped_pc, prom_boot_mapping_mode
99 .globl prom_boot_mapping_phys_high, prom_boot_mapping_phys_low 99 .globl prom_boot_mapping_phys_high, prom_boot_mapping_phys_low
100 .globl is_sun4v 100 .globl prom_compatible_name, prom_cpu_path, prom_cpu_compatible
101 .globl is_sun4v, sun4v_chip_type
101prom_peer_name: 102prom_peer_name:
102 .asciz "peer" 103 .asciz "peer"
103prom_compatible_name: 104prom_compatible_name:
@@ -106,6 +107,8 @@ prom_finddev_name:
106 .asciz "finddevice" 107 .asciz "finddevice"
107prom_chosen_path: 108prom_chosen_path:
108 .asciz "/chosen" 109 .asciz "/chosen"
110prom_cpu_path:
111 .asciz "/cpu"
109prom_getprop_name: 112prom_getprop_name:
110 .asciz "getprop" 113 .asciz "getprop"
111prom_mmu_name: 114prom_mmu_name:
@@ -120,9 +123,13 @@ prom_unmap_name:
120 .asciz "unmap" 123 .asciz "unmap"
121prom_sun4v_name: 124prom_sun4v_name:
122 .asciz "sun4v" 125 .asciz "sun4v"
126prom_niagara_prefix:
127 .asciz "SUNW,UltraSPARC-T"
123 .align 4 128 .align 4
124prom_root_compatible: 129prom_root_compatible:
125 .skip 64 130 .skip 64
131prom_cpu_compatible:
132 .skip 64
126prom_root_node: 133prom_root_node:
127 .word 0 134 .word 0
128prom_mmu_ihandle_cache: 135prom_mmu_ihandle_cache:
@@ -138,6 +145,8 @@ prom_boot_mapping_phys_low:
138 .xword 0 145 .xword 0
139is_sun4v: 146is_sun4v:
140 .word 0 147 .word 0
148sun4v_chip_type:
149 .word SUN4V_CHIP_INVALID
1411: 1501:
142 rd %pc, %l0 151 rd %pc, %l0
143 152
@@ -296,13 +305,13 @@ is_sun4v:
296 sethi %hi(prom_sun4v_name), %g7 305 sethi %hi(prom_sun4v_name), %g7
297 or %g7, %lo(prom_sun4v_name), %g7 306 or %g7, %lo(prom_sun4v_name), %g7
298 mov 5, %g3 307 mov 5, %g3
2991: ldub [%g7], %g2 30890: ldub [%g7], %g2
300 ldub [%g1], %g4 309 ldub [%g1], %g4
301 cmp %g2, %g4 310 cmp %g2, %g4
302 bne,pn %icc, 2f 311 bne,pn %icc, 80f
303 add %g7, 1, %g7 312 add %g7, 1, %g7
304 subcc %g3, 1, %g3 313 subcc %g3, 1, %g3
305 bne,pt %xcc, 1b 314 bne,pt %xcc, 90b
306 add %g1, 1, %g1 315 add %g1, 1, %g1
307 316
308 sethi %hi(is_sun4v), %g1 317 sethi %hi(is_sun4v), %g1
@@ -310,7 +319,80 @@ is_sun4v:
310 mov 1, %g7 319 mov 1, %g7
311 stw %g7, [%g1] 320 stw %g7, [%g1]
312 321
3132: 322 /* cpu_node = prom_finddevice("/cpu") */
323 mov (1b - prom_finddev_name), %l1
324 mov (1b - prom_cpu_path), %l2
325 sub %l0, %l1, %l1
326 sub %l0, %l2, %l2
327 sub %sp, (192 + 128), %sp
328
329 stx %l1, [%sp + 2047 + 128 + 0x00] ! service, "finddevice"
330 mov 1, %l3
331 stx %l3, [%sp + 2047 + 128 + 0x08] ! num_args, 1
332 stx %l3, [%sp + 2047 + 128 + 0x10] ! num_rets, 1
333 stx %l2, [%sp + 2047 + 128 + 0x18] ! arg1, "/cpu"
334 stx %g0, [%sp + 2047 + 128 + 0x20] ! ret1
335 call %l7
336 add %sp, (2047 + 128), %o0 ! argument array
337
338 ldx [%sp + 2047 + 128 + 0x20], %l4 ! cpu device node
339
340 mov (1b - prom_getprop_name), %l1
341 mov (1b - prom_compatible_name), %l2
342 mov (1b - prom_cpu_compatible), %l5
343 sub %l0, %l1, %l1
344 sub %l0, %l2, %l2
345 sub %l0, %l5, %l5
346
347 /* prom_getproperty(cpu_node, "compatible",
348 * &prom_cpu_compatible, 64)
349 */
350 stx %l1, [%sp + 2047 + 128 + 0x00] ! service, "getprop"
351 mov 4, %l3
352 stx %l3, [%sp + 2047 + 128 + 0x08] ! num_args, 4
353 mov 1, %l3
354 stx %l3, [%sp + 2047 + 128 + 0x10] ! num_rets, 1
355 stx %l4, [%sp + 2047 + 128 + 0x18] ! arg1, cpu_node
356 stx %l2, [%sp + 2047 + 128 + 0x20] ! arg2, "compatible"
357 stx %l5, [%sp + 2047 + 128 + 0x28] ! arg3, &prom_cpu_compatible
358 mov 64, %l3
359 stx %l3, [%sp + 2047 + 128 + 0x30] ! arg4, size
360 stx %g0, [%sp + 2047 + 128 + 0x38] ! ret1
361 call %l7
362 add %sp, (2047 + 128), %o0 ! argument array
363
364 add %sp, (192 + 128), %sp
365
366 sethi %hi(prom_cpu_compatible), %g1
367 or %g1, %lo(prom_cpu_compatible), %g1
368 sethi %hi(prom_niagara_prefix), %g7
369 or %g7, %lo(prom_niagara_prefix), %g7
370 mov 17, %g3
37190: ldub [%g7], %g2
372 ldub [%g1], %g4
373 cmp %g2, %g4
374 bne,pn %icc, 4f
375 add %g7, 1, %g7
376 subcc %g3, 1, %g3
377 bne,pt %xcc, 90b
378 add %g1, 1, %g1
379
380 sethi %hi(prom_cpu_compatible), %g1
381 or %g1, %lo(prom_cpu_compatible), %g1
382 ldub [%g1 + 17], %g2
383 cmp %g2, '1'
384 be,pt %xcc, 5f
385 mov SUN4V_CHIP_NIAGARA1, %g4
386 cmp %g2, '2'
387 be,pt %xcc, 5f
388 mov SUN4V_CHIP_NIAGARA2, %g4
3894:
390 mov SUN4V_CHIP_UNKNOWN, %g4
3915: sethi %hi(sun4v_chip_type), %g2
392 or %g2, %lo(sun4v_chip_type), %g2
393 stw %g4, [%g2]
394
39580:
314 BRANCH_IF_SUN4V(g1, jump_to_sun4u_init) 396 BRANCH_IF_SUN4V(g1, jump_to_sun4u_init)
315 BRANCH_IF_CHEETAH_BASE(g1,g7,cheetah_boot) 397 BRANCH_IF_CHEETAH_BASE(g1,g7,cheetah_boot)
316 BRANCH_IF_CHEETAH_PLUS_OR_FOLLOWON(g1,g7,cheetah_plus_boot) 398 BRANCH_IF_CHEETAH_PLUS_OR_FOLLOWON(g1,g7,cheetah_plus_boot)
@@ -414,6 +496,24 @@ niagara_tlb_fixup:
414 stw %g2, [%g1 + %lo(tlb_type)] 496 stw %g2, [%g1 + %lo(tlb_type)]
415 497
416 /* Patch copy/clear ops. */ 498 /* Patch copy/clear ops. */
499 sethi %hi(sun4v_chip_type), %g1
500 lduw [%g1 + %lo(sun4v_chip_type)], %g1
501 cmp %g1, SUN4V_CHIP_NIAGARA1
502 be,pt %xcc, niagara_patch
503 cmp %g1, SUN4V_CHIP_NIAGARA2
504 be,pt %xcc, niagara_patch
505 nop
506
507 call generic_patch_copyops
508 nop
509 call generic_patch_bzero
510 nop
511 call generic_patch_pageops
512 nop
513
514 ba,a,pt %xcc, 80f
515
516niagara_patch:
417 call niagara_patch_copyops 517 call niagara_patch_copyops
418 nop 518 nop
419 call niagara_patch_bzero 519 call niagara_patch_bzero
@@ -421,6 +521,7 @@ niagara_tlb_fixup:
421 call niagara_patch_pageops 521 call niagara_patch_pageops
422 nop 522 nop
423 523
52480:
424 /* Patch TLB/cache ops. */ 525 /* Patch TLB/cache ops. */
425 call hypervisor_patch_cachetlbops 526 call hypervisor_patch_cachetlbops
426 nop 527 nop
diff --git a/arch/sparc64/kernel/hvtramp.S b/arch/sparc64/kernel/hvtramp.S
index a55c252e18cc..b692e044a463 100644
--- a/arch/sparc64/kernel/hvtramp.S
+++ b/arch/sparc64/kernel/hvtramp.S
@@ -115,11 +115,8 @@ hv_cpu_startup:
115 call hard_smp_processor_id 115 call hard_smp_processor_id
116 nop 116 nop
117 117
118 mov %o0, %o1 118 call sun4v_register_mondo_queues
119 mov 0, %o0 119 nop
120 mov 0, %o2
121 call sun4v_init_mondo_queues
122 mov 1, %o3
123 120
124 call init_cur_cpu_trap 121 call init_cur_cpu_trap
125 mov %g6, %o0 122 mov %g6, %o0
diff --git a/arch/sparc64/kernel/irq.c b/arch/sparc64/kernel/irq.c
index db31bf6b42db..384abf410cf0 100644
--- a/arch/sparc64/kernel/irq.c
+++ b/arch/sparc64/kernel/irq.c
@@ -929,7 +929,7 @@ static void __cpuinit register_one_mondo(unsigned long paddr, unsigned long type
929 } 929 }
930} 930}
931 931
932static void __cpuinit sun4v_register_mondo_queues(int this_cpu) 932void __cpuinit sun4v_register_mondo_queues(int this_cpu)
933{ 933{
934 struct trap_per_cpu *tb = &trap_block[this_cpu]; 934 struct trap_per_cpu *tb = &trap_block[this_cpu];
935 935
@@ -943,20 +943,10 @@ static void __cpuinit sun4v_register_mondo_queues(int this_cpu)
943 tb->nonresum_qmask); 943 tb->nonresum_qmask);
944} 944}
945 945
946static void __cpuinit alloc_one_mondo(unsigned long *pa_ptr, unsigned long qmask, int use_bootmem) 946static void __init alloc_one_mondo(unsigned long *pa_ptr, unsigned long qmask)
947{ 947{
948 unsigned long size = PAGE_ALIGN(qmask + 1); 948 unsigned long size = PAGE_ALIGN(qmask + 1);
949 unsigned long order = get_order(size); 949 void *p = __alloc_bootmem_low(size, size, 0);
950 void *p = NULL;
951
952 if (use_bootmem) {
953 p = __alloc_bootmem_low(size, size, 0);
954 } else {
955 struct page *page = alloc_pages(GFP_ATOMIC | __GFP_ZERO, order);
956 if (page)
957 p = page_address(page);
958 }
959
960 if (!p) { 950 if (!p) {
961 prom_printf("SUN4V: Error, cannot allocate mondo queue.\n"); 951 prom_printf("SUN4V: Error, cannot allocate mondo queue.\n");
962 prom_halt(); 952 prom_halt();
@@ -965,19 +955,10 @@ static void __cpuinit alloc_one_mondo(unsigned long *pa_ptr, unsigned long qmask
965 *pa_ptr = __pa(p); 955 *pa_ptr = __pa(p);
966} 956}
967 957
968static void __cpuinit alloc_one_kbuf(unsigned long *pa_ptr, unsigned long qmask, int use_bootmem) 958static void __init alloc_one_kbuf(unsigned long *pa_ptr, unsigned long qmask)
969{ 959{
970 unsigned long size = PAGE_ALIGN(qmask + 1); 960 unsigned long size = PAGE_ALIGN(qmask + 1);
971 unsigned long order = get_order(size); 961 void *p = __alloc_bootmem_low(size, size, 0);
972 void *p = NULL;
973
974 if (use_bootmem) {
975 p = __alloc_bootmem_low(size, size, 0);
976 } else {
977 struct page *page = alloc_pages(GFP_ATOMIC | __GFP_ZERO, order);
978 if (page)
979 p = page_address(page);
980 }
981 962
982 if (!p) { 963 if (!p) {
983 prom_printf("SUN4V: Error, cannot allocate kbuf page.\n"); 964 prom_printf("SUN4V: Error, cannot allocate kbuf page.\n");
@@ -987,18 +968,14 @@ static void __cpuinit alloc_one_kbuf(unsigned long *pa_ptr, unsigned long qmask,
987 *pa_ptr = __pa(p); 968 *pa_ptr = __pa(p);
988} 969}
989 970
990static void __cpuinit init_cpu_send_mondo_info(struct trap_per_cpu *tb, int use_bootmem) 971static void __init init_cpu_send_mondo_info(struct trap_per_cpu *tb)
991{ 972{
992#ifdef CONFIG_SMP 973#ifdef CONFIG_SMP
993 void *page; 974 void *page;
994 975
995 BUILD_BUG_ON((NR_CPUS * sizeof(u16)) > (PAGE_SIZE - 64)); 976 BUILD_BUG_ON((NR_CPUS * sizeof(u16)) > (PAGE_SIZE - 64));
996 977
997 if (use_bootmem) 978 page = alloc_bootmem_low_pages(PAGE_SIZE);
998 page = alloc_bootmem_low_pages(PAGE_SIZE);
999 else
1000 page = (void *) get_zeroed_page(GFP_ATOMIC);
1001
1002 if (!page) { 979 if (!page) {
1003 prom_printf("SUN4V: Error, cannot allocate cpu mondo page.\n"); 980 prom_printf("SUN4V: Error, cannot allocate cpu mondo page.\n");
1004 prom_halt(); 981 prom_halt();
@@ -1009,30 +986,27 @@ static void __cpuinit init_cpu_send_mondo_info(struct trap_per_cpu *tb, int use_
1009#endif 986#endif
1010} 987}
1011 988
1012/* Allocate and register the mondo and error queues for this cpu. */ 989/* Allocate mondo and error queues for all possible cpus. */
1013void __cpuinit sun4v_init_mondo_queues(int use_bootmem, int cpu, int alloc, int load) 990static void __init sun4v_init_mondo_queues(void)
1014{ 991{
1015 struct trap_per_cpu *tb = &trap_block[cpu]; 992 int cpu;
1016 993
1017 if (alloc) { 994 for_each_possible_cpu(cpu) {
1018 alloc_one_mondo(&tb->cpu_mondo_pa, tb->cpu_mondo_qmask, use_bootmem); 995 struct trap_per_cpu *tb = &trap_block[cpu];
1019 alloc_one_mondo(&tb->dev_mondo_pa, tb->dev_mondo_qmask, use_bootmem);
1020 alloc_one_mondo(&tb->resum_mondo_pa, tb->resum_qmask, use_bootmem);
1021 alloc_one_kbuf(&tb->resum_kernel_buf_pa, tb->resum_qmask, use_bootmem);
1022 alloc_one_mondo(&tb->nonresum_mondo_pa, tb->nonresum_qmask, use_bootmem);
1023 alloc_one_kbuf(&tb->nonresum_kernel_buf_pa, tb->nonresum_qmask, use_bootmem);
1024 996
1025 init_cpu_send_mondo_info(tb, use_bootmem); 997 alloc_one_mondo(&tb->cpu_mondo_pa, tb->cpu_mondo_qmask);
1026 } 998 alloc_one_mondo(&tb->dev_mondo_pa, tb->dev_mondo_qmask);
999 alloc_one_mondo(&tb->resum_mondo_pa, tb->resum_qmask);
1000 alloc_one_kbuf(&tb->resum_kernel_buf_pa, tb->resum_qmask);
1001 alloc_one_mondo(&tb->nonresum_mondo_pa, tb->nonresum_qmask);
1002 alloc_one_kbuf(&tb->nonresum_kernel_buf_pa,
1003 tb->nonresum_qmask);
1027 1004
1028 if (load) { 1005 init_cpu_send_mondo_info(tb);
1029 if (cpu != hard_smp_processor_id()) {
1030 prom_printf("SUN4V: init mondo on cpu %d not %d\n",
1031 cpu, hard_smp_processor_id());
1032 prom_halt();
1033 }
1034 sun4v_register_mondo_queues(cpu);
1035 } 1006 }
1007
1008 /* Load up the boot cpu's entries. */
1009 sun4v_register_mondo_queues(hard_smp_processor_id());
1036} 1010}
1037 1011
1038static struct irqaction timer_irq_action = { 1012static struct irqaction timer_irq_action = {
@@ -1047,7 +1021,7 @@ void __init init_IRQ(void)
1047 memset(&ivector_table[0], 0, sizeof(ivector_table)); 1021 memset(&ivector_table[0], 0, sizeof(ivector_table));
1048 1022
1049 if (tlb_type == hypervisor) 1023 if (tlb_type == hypervisor)
1050 sun4v_init_mondo_queues(1, hard_smp_processor_id(), 1, 1); 1024 sun4v_init_mondo_queues();
1051 1025
1052 /* We need to clear any IRQ's pending in the soft interrupt 1026 /* We need to clear any IRQ's pending in the soft interrupt
1053 * registers, a spurious one could be left around from the 1027 * registers, a spurious one could be left around from the
diff --git a/arch/sparc64/kernel/mdesc.c b/arch/sparc64/kernel/mdesc.c
index cce4d0ddf5d5..95059c2ec414 100644
--- a/arch/sparc64/kernel/mdesc.c
+++ b/arch/sparc64/kernel/mdesc.c
@@ -568,20 +568,6 @@ static void __init report_platform_properties(void)
568 mdesc_release(hp); 568 mdesc_release(hp);
569} 569}
570 570
571static int inline find_in_proplist(const char *list, const char *match, int len)
572{
573 while (len > 0) {
574 int l;
575
576 if (!strcmp(list, match))
577 return 1;
578 l = strlen(list) + 1;
579 list += l;
580 len -= l;
581 }
582 return 0;
583}
584
585static void __devinit fill_in_one_cache(cpuinfo_sparc *c, 571static void __devinit fill_in_one_cache(cpuinfo_sparc *c,
586 struct mdesc_handle *hp, 572 struct mdesc_handle *hp,
587 u64 mp) 573 u64 mp)
@@ -596,10 +582,10 @@ static void __devinit fill_in_one_cache(cpuinfo_sparc *c,
596 582
597 switch (*level) { 583 switch (*level) {
598 case 1: 584 case 1:
599 if (find_in_proplist(type, "instn", type_len)) { 585 if (of_find_in_proplist(type, "instn", type_len)) {
600 c->icache_size = *size; 586 c->icache_size = *size;
601 c->icache_line_size = *line_size; 587 c->icache_line_size = *line_size;
602 } else if (find_in_proplist(type, "data", type_len)) { 588 } else if (of_find_in_proplist(type, "data", type_len)) {
603 c->dcache_size = *size; 589 c->dcache_size = *size;
604 c->dcache_line_size = *line_size; 590 c->dcache_line_size = *line_size;
605 } 591 }
@@ -677,7 +663,7 @@ static void __devinit set_core_ids(struct mdesc_handle *hp)
677 continue; 663 continue;
678 664
679 type = mdesc_get_property(hp, mp, "type", &len); 665 type = mdesc_get_property(hp, mp, "type", &len);
680 if (!find_in_proplist(type, "instn", len)) 666 if (!of_find_in_proplist(type, "instn", len))
681 continue; 667 continue;
682 668
683 mark_core_ids(hp, mp, idx); 669 mark_core_ids(hp, mp, idx);
@@ -718,8 +704,8 @@ static void __devinit __set_proc_ids(struct mdesc_handle *hp,
718 int len; 704 int len;
719 705
720 type = mdesc_get_property(hp, mp, "type", &len); 706 type = mdesc_get_property(hp, mp, "type", &len);
721 if (!find_in_proplist(type, "int", len) && 707 if (!of_find_in_proplist(type, "int", len) &&
722 !find_in_proplist(type, "integer", len)) 708 !of_find_in_proplist(type, "integer", len))
723 continue; 709 continue;
724 710
725 mark_proc_ids(hp, mp, idx); 711 mark_proc_ids(hp, mp, idx);
diff --git a/arch/sparc64/kernel/prom.c b/arch/sparc64/kernel/prom.c
index f4e0a9ad9be3..d1a78c976cef 100644
--- a/arch/sparc64/kernel/prom.c
+++ b/arch/sparc64/kernel/prom.c
@@ -107,6 +107,21 @@ int of_set_property(struct device_node *dp, const char *name, void *val, int len
107} 107}
108EXPORT_SYMBOL(of_set_property); 108EXPORT_SYMBOL(of_set_property);
109 109
110int of_find_in_proplist(const char *list, const char *match, int len)
111{
112 while (len > 0) {
113 int l;
114
115 if (!strcmp(list, match))
116 return 1;
117 l = strlen(list) + 1;
118 list += l;
119 len -= l;
120 }
121 return 0;
122}
123EXPORT_SYMBOL(of_find_in_proplist);
124
110static unsigned int prom_early_allocated; 125static unsigned int prom_early_allocated;
111 126
112static void * __init prom_early_alloc(unsigned long size) 127static void * __init prom_early_alloc(unsigned long size)
diff --git a/arch/sparc64/kernel/smp.c b/arch/sparc64/kernel/smp.c
index b448d33321c6..b84c49e3697c 100644
--- a/arch/sparc64/kernel/smp.c
+++ b/arch/sparc64/kernel/smp.c
@@ -334,8 +334,6 @@ static void ldom_startcpu_cpuid(unsigned int cpu, unsigned long thread_reg)
334} 334}
335#endif 335#endif
336 336
337extern void sun4v_init_mondo_queues(int use_bootmem, int cpu, int alloc, int load);
338
339extern unsigned long sparc64_cpu_startup; 337extern unsigned long sparc64_cpu_startup;
340 338
341/* The OBP cpu startup callback truncates the 3rd arg cookie to 339/* The OBP cpu startup callback truncates the 3rd arg cookie to
@@ -359,9 +357,6 @@ static int __devinit smp_boot_one_cpu(unsigned int cpu)
359 cpu_new_thread = task_thread_info(p); 357 cpu_new_thread = task_thread_info(p);
360 358
361 if (tlb_type == hypervisor) { 359 if (tlb_type == hypervisor) {
362 /* Alloc the mondo queues, cpu will load them. */
363 sun4v_init_mondo_queues(0, cpu, 1, 0);
364
365#if defined(CONFIG_SUN_LDOMS) && defined(CONFIG_HOTPLUG_CPU) 360#if defined(CONFIG_SUN_LDOMS) && defined(CONFIG_HOTPLUG_CPU)
366 if (ldom_domaining_enabled) 361 if (ldom_domaining_enabled)
367 ldom_startcpu_cpuid(cpu, 362 ldom_startcpu_cpuid(cpu,
diff --git a/arch/sparc64/kernel/sparc64_ksyms.c b/arch/sparc64/kernel/sparc64_ksyms.c
index d270c2f0be0f..23fad7ebdd0d 100644
--- a/arch/sparc64/kernel/sparc64_ksyms.c
+++ b/arch/sparc64/kernel/sparc64_ksyms.c
@@ -168,6 +168,7 @@ EXPORT_SYMBOL(change_bit);
168EXPORT_SYMBOL(__flushw_user); 168EXPORT_SYMBOL(__flushw_user);
169 169
170EXPORT_SYMBOL(tlb_type); 170EXPORT_SYMBOL(tlb_type);
171EXPORT_SYMBOL(sun4v_chip_type);
171EXPORT_SYMBOL(get_fb_unmapped_area); 172EXPORT_SYMBOL(get_fb_unmapped_area);
172EXPORT_SYMBOL(flush_icache_range); 173EXPORT_SYMBOL(flush_icache_range);
173 174
diff --git a/arch/sparc64/kernel/trampoline.S b/arch/sparc64/kernel/trampoline.S
index a4dc01a3d238..9448595f9063 100644
--- a/arch/sparc64/kernel/trampoline.S
+++ b/arch/sparc64/kernel/trampoline.S
@@ -366,11 +366,8 @@ after_lock_tlb:
366 call hard_smp_processor_id 366 call hard_smp_processor_id
367 nop 367 nop
368 368
369 mov %o0, %o1 369 call sun4v_register_mondo_queues
370 mov 0, %o0 370 nop
371 mov 0, %o2
372 call sun4v_init_mondo_queues
373 mov 1, %o3
374 371
3751: call init_cur_cpu_trap 3721: call init_cur_cpu_trap
376 ldx [%l0], %o0 373 ldx [%l0], %o0
diff --git a/arch/sparc64/kernel/vio.c b/arch/sparc64/kernel/vio.c
index 3685daf5157f..1550ac5673da 100644
--- a/arch/sparc64/kernel/vio.c
+++ b/arch/sparc64/kernel/vio.c
@@ -16,21 +16,6 @@
16#include <asm/mdesc.h> 16#include <asm/mdesc.h>
17#include <asm/vio.h> 17#include <asm/vio.h>
18 18
19static inline int find_in_proplist(const char *list, const char *match,
20 int len)
21{
22 while (len > 0) {
23 int l;
24
25 if (!strcmp(list, match))
26 return 1;
27 l = strlen(list) + 1;
28 list += l;
29 len -= l;
30 }
31 return 0;
32}
33
34static const struct vio_device_id *vio_match_device( 19static const struct vio_device_id *vio_match_device(
35 const struct vio_device_id *matches, 20 const struct vio_device_id *matches,
36 const struct vio_dev *dev) 21 const struct vio_dev *dev)
@@ -49,7 +34,7 @@ static const struct vio_device_id *vio_match_device(
49 34
50 if (matches->compat[0]) { 35 if (matches->compat[0]) {
51 match &= len && 36 match &= len &&
52 find_in_proplist(compat, matches->compat, len); 37 of_find_in_proplist(compat, matches->compat, len);
53 } 38 }
54 if (match) 39 if (match)
55 return matches; 40 return matches;
@@ -406,7 +391,7 @@ static int __init vio_init(void)
406 "property\n"); 391 "property\n");
407 goto out_release; 392 goto out_release;
408 } 393 }
409 if (!find_in_proplist(compat, channel_devices_compat, len)) { 394 if (!of_find_in_proplist(compat, channel_devices_compat, len)) {
410 printk(KERN_ERR "VIO: Channel devices node lacks (%s) " 395 printk(KERN_ERR "VIO: Channel devices node lacks (%s) "
411 "compat entry.\n", channel_devices_compat); 396 "compat entry.\n", channel_devices_compat);
412 goto out_release; 397 goto out_release;
diff --git a/arch/sparc64/lib/GENbzero.S b/arch/sparc64/lib/GENbzero.S
new file mode 100644
index 000000000000..f9c71d64eba1
--- /dev/null
+++ b/arch/sparc64/lib/GENbzero.S
@@ -0,0 +1,160 @@
1/* GENbzero.S: Generic sparc64 memset/clear_user.
2 *
3 * Copyright (C) 2007 David S. Miller (davem@davemloft.net)
4 */
5#include <asm/asi.h>
6
7#define EX_ST(x,y) \
898: x,y; \
9 .section .fixup; \
10 .align 4; \
1199: retl; \
12 mov %o1, %o0; \
13 .section __ex_table; \
14 .align 4; \
15 .word 98b, 99b; \
16 .text; \
17 .align 4;
18
19 .align 32
20 .text
21
22 .globl GENmemset
23 .type GENmemset, #function
24GENmemset: /* %o0=buf, %o1=pat, %o2=len */
25 and %o1, 0xff, %o3
26 mov %o2, %o1
27 sllx %o3, 8, %g1
28 or %g1, %o3, %o2
29 sllx %o2, 16, %g1
30 or %g1, %o2, %o2
31 sllx %o2, 32, %g1
32 ba,pt %xcc, 1f
33 or %g1, %o2, %o2
34
35 .globl GENbzero
36 .type GENbzero, #function
37GENbzero:
38 clr %o2
391: brz,pn %o1, GENbzero_return
40 mov %o0, %o3
41
42 /* %o5: saved %asi, restored at GENbzero_done
43 * %o4: store %asi to use
44 */
45 rd %asi, %o5
46 mov ASI_P, %o4
47 wr %o4, 0x0, %asi
48
49GENbzero_from_clear_user:
50 cmp %o1, 15
51 bl,pn %icc, GENbzero_tiny
52 andcc %o0, 0x7, %g1
53 be,pt %xcc, 2f
54 mov 8, %g2
55 sub %g2, %g1, %g1
56 sub %o1, %g1, %o1
571: EX_ST(stba %o2, [%o0 + 0x00] %asi)
58 subcc %g1, 1, %g1
59 bne,pt %xcc, 1b
60 add %o0, 1, %o0
612: cmp %o1, 128
62 bl,pn %icc, GENbzero_medium
63 andcc %o0, (64 - 1), %g1
64 be,pt %xcc, GENbzero_pre_loop
65 mov 64, %g2
66 sub %g2, %g1, %g1
67 sub %o1, %g1, %o1
681: EX_ST(stxa %o2, [%o0 + 0x00] %asi)
69 subcc %g1, 8, %g1
70 bne,pt %xcc, 1b
71 add %o0, 8, %o0
72
73GENbzero_pre_loop:
74 andn %o1, (64 - 1), %g1
75 sub %o1, %g1, %o1
76GENbzero_loop:
77 EX_ST(stxa %o2, [%o0 + 0x00] %asi)
78 EX_ST(stxa %o2, [%o0 + 0x08] %asi)
79 EX_ST(stxa %o2, [%o0 + 0x10] %asi)
80 EX_ST(stxa %o2, [%o0 + 0x18] %asi)
81 EX_ST(stxa %o2, [%o0 + 0x20] %asi)
82 EX_ST(stxa %o2, [%o0 + 0x28] %asi)
83 EX_ST(stxa %o2, [%o0 + 0x30] %asi)
84 EX_ST(stxa %o2, [%o0 + 0x38] %asi)
85 subcc %g1, 64, %g1
86 bne,pt %xcc, GENbzero_loop
87 add %o0, 64, %o0
88
89 membar #Sync
90 wr %o4, 0x0, %asi
91 brz,pn %o1, GENbzero_done
92GENbzero_medium:
93 andncc %o1, 0x7, %g1
94 be,pn %xcc, 2f
95 sub %o1, %g1, %o1
961: EX_ST(stxa %o2, [%o0 + 0x00] %asi)
97 subcc %g1, 8, %g1
98 bne,pt %xcc, 1b
99 add %o0, 8, %o0
1002: brz,pt %o1, GENbzero_done
101 nop
102
103GENbzero_tiny:
1041: EX_ST(stba %o2, [%o0 + 0x00] %asi)
105 subcc %o1, 1, %o1
106 bne,pt %icc, 1b
107 add %o0, 1, %o0
108
109 /* fallthrough */
110
111GENbzero_done:
112 wr %o5, 0x0, %asi
113
114GENbzero_return:
115 retl
116 mov %o3, %o0
117 .size GENbzero, .-GENbzero
118 .size GENmemset, .-GENmemset
119
120 .globl GENclear_user
121 .type GENclear_user, #function
122GENclear_user: /* %o0=buf, %o1=len */
123 rd %asi, %o5
124 brz,pn %o1, GENbzero_done
125 clr %o3
126 cmp %o5, ASI_AIUS
127 bne,pn %icc, GENbzero
128 clr %o2
129 ba,pt %xcc, GENbzero_from_clear_user
130 mov ASI_AIUS, %o4
131 .size GENclear_user, .-GENclear_user
132
133#define BRANCH_ALWAYS 0x10680000
134#define NOP 0x01000000
135#define GEN_DO_PATCH(OLD, NEW) \
136 sethi %hi(NEW), %g1; \
137 or %g1, %lo(NEW), %g1; \
138 sethi %hi(OLD), %g2; \
139 or %g2, %lo(OLD), %g2; \
140 sub %g1, %g2, %g1; \
141 sethi %hi(BRANCH_ALWAYS), %g3; \
142 sll %g1, 11, %g1; \
143 srl %g1, 11 + 2, %g1; \
144 or %g3, %lo(BRANCH_ALWAYS), %g3; \
145 or %g3, %g1, %g3; \
146 stw %g3, [%g2]; \
147 sethi %hi(NOP), %g3; \
148 or %g3, %lo(NOP), %g3; \
149 stw %g3, [%g2 + 0x4]; \
150 flush %g2;
151
152 .globl generic_patch_bzero
153 .type generic_patch_bzero,#function
154generic_patch_bzero:
155 GEN_DO_PATCH(memset, GENmemset)
156 GEN_DO_PATCH(__bzero, GENbzero)
157 GEN_DO_PATCH(__clear_user, GENclear_user)
158 retl
159 nop
160 .size generic_patch_bzero,.-generic_patch_bzero
diff --git a/arch/sparc64/lib/GENcopy_from_user.S b/arch/sparc64/lib/GENcopy_from_user.S
new file mode 100644
index 000000000000..2b9df99e87f9
--- /dev/null
+++ b/arch/sparc64/lib/GENcopy_from_user.S
@@ -0,0 +1,34 @@
1/* GENcopy_from_user.S: Generic sparc64 copy from userspace.
2 *
3 * Copyright (C) 2007 David S. Miller (davem@davemloft.net)
4 */
5
6#define EX_LD(x) \
798: x; \
8 .section .fixup; \
9 .align 4; \
1099: retl; \
11 mov 1, %o0; \
12 .section __ex_table,"a";\
13 .align 4; \
14 .word 98b, 99b; \
15 .text; \
16 .align 4;
17
18#ifndef ASI_AIUS
19#define ASI_AIUS 0x11
20#endif
21
22#define FUNC_NAME GENcopy_from_user
23#define LOAD(type,addr,dest) type##a [addr] ASI_AIUS, dest
24#define EX_RETVAL(x) 0
25
26#ifdef __KERNEL__
27#define PREAMBLE \
28 rd %asi, %g1; \
29 cmp %g1, ASI_AIUS; \
30 bne,pn %icc, memcpy_user_stub; \
31 nop
32#endif
33
34#include "GENmemcpy.S"
diff --git a/arch/sparc64/lib/GENcopy_to_user.S b/arch/sparc64/lib/GENcopy_to_user.S
new file mode 100644
index 000000000000..bb3f7084daf9
--- /dev/null
+++ b/arch/sparc64/lib/GENcopy_to_user.S
@@ -0,0 +1,38 @@
1/* GENcopy_to_user.S: Generic sparc64 copy to userspace.
2 *
3 * Copyright (C) 2007 David S. Miller (davem@davemloft.net)
4 */
5
6#define EX_ST(x) \
798: x; \
8 .section .fixup; \
9 .align 4; \
1099: retl; \
11 mov 1, %o0; \
12 .section __ex_table,"a";\
13 .align 4; \
14 .word 98b, 99b; \
15 .text; \
16 .align 4;
17
18#ifndef ASI_AIUS
19#define ASI_AIUS 0x11
20#endif
21
22#define FUNC_NAME GENcopy_to_user
23#define STORE(type,src,addr) type##a src, [addr] ASI_AIUS
24#define EX_RETVAL(x) 0
25
26#ifdef __KERNEL__
27 /* Writing to %asi is _expensive_ so we hardcode it.
28 * Reading %asi to check for KERNEL_DS is comparatively
29 * cheap.
30 */
31#define PREAMBLE \
32 rd %asi, %g1; \
33 cmp %g1, ASI_AIUS; \
34 bne,pn %icc, memcpy_user_stub; \
35 nop
36#endif
37
38#include "GENmemcpy.S"
diff --git a/arch/sparc64/lib/GENmemcpy.S b/arch/sparc64/lib/GENmemcpy.S
new file mode 100644
index 000000000000..89358ee94851
--- /dev/null
+++ b/arch/sparc64/lib/GENmemcpy.S
@@ -0,0 +1,121 @@
1/* GENmemcpy.S: Generic sparc64 memcpy.
2 *
3 * Copyright (C) 2007 David S. Miller (davem@davemloft.net)
4 */
5
6#ifdef __KERNEL__
7#define GLOBAL_SPARE %g7
8#else
9#define GLOBAL_SPARE %g5
10#endif
11
12#ifndef EX_LD
13#define EX_LD(x) x
14#endif
15
16#ifndef EX_ST
17#define EX_ST(x) x
18#endif
19
20#ifndef EX_RETVAL
21#define EX_RETVAL(x) x
22#endif
23
24#ifndef LOAD
25#define LOAD(type,addr,dest) type [addr], dest
26#endif
27
28#ifndef STORE
29#define STORE(type,src,addr) type src, [addr]
30#endif
31
32#ifndef FUNC_NAME
33#define FUNC_NAME GENmemcpy
34#endif
35
36#ifndef PREAMBLE
37#define PREAMBLE
38#endif
39
40#ifndef XCC
41#define XCC xcc
42#endif
43
44 .register %g2,#scratch
45 .register %g3,#scratch
46
47 .text
48 .align 64
49
50 .globl FUNC_NAME
51 .type FUNC_NAME,#function
52FUNC_NAME: /* %o0=dst, %o1=src, %o2=len */
53 srlx %o2, 31, %g2
54 cmp %g2, 0
55 tne %XCC, 5
56 PREAMBLE
57 mov %o0, GLOBAL_SPARE
58
59 cmp %o2, 0
60 be,pn %XCC, 85f
61 or %o0, %o1, %o3
62 cmp %o2, 16
63 blu,a,pn %XCC, 80f
64 or %o3, %o2, %o3
65
66 xor %o0, %o1, %o4
67 andcc %o4, 0x7, %g0
68 bne,a,pn %XCC, 90f
69 sub %o0, %o1, %o3
70
71 and %o0, 0x7, %o4
72 sub %o4, 0x8, %o4
73 sub %g0, %o4, %o4
74 sub %o2, %o4, %o2
751: subcc %o4, 1, %o4
76 EX_LD(LOAD(ldub, %o1, %g1))
77 EX_ST(STORE(stb, %g1, %o0))
78 add %o1, 1, %o1
79 bne,pt %XCC, 1b
80 add %o0, 1, %o0
81
82 andn %o2, 0x7, %g1
83 sub %o2, %g1, %o2
841: subcc %g1, 0x8, %g1
85 EX_LD(LOAD(ldx, %o1, %g2))
86 EX_ST(STORE(stx, %g2, %o0))
87 add %o1, 0x8, %o1
88 bne,pt %XCC, 1b
89 add %o0, 0x8, %o0
90
91 brz,pt %o2, 85f
92 sub %o0, %o1, %o3
93 ba,a,pt %XCC, 90f
94
95 .align 64
9680: /* 0 < len <= 16 */
97 andcc %o3, 0x3, %g0
98 bne,pn %XCC, 90f
99 sub %o0, %o1, %o3
100
1011:
102 subcc %o2, 4, %o2
103 EX_LD(LOAD(lduw, %o1, %g1))
104 EX_ST(STORE(stw, %g1, %o1 + %o3))
105 bgu,pt %XCC, 1b
106 add %o1, 4, %o1
107
10885: retl
109 mov EX_RETVAL(GLOBAL_SPARE), %o0
110
111 .align 32
11290:
113 subcc %o2, 1, %o2
114 EX_LD(LOAD(ldub, %o1, %g1))
115 EX_ST(STORE(stb, %g1, %o1 + %o3))
116 bgu,pt %XCC, 90b
117 add %o1, 1, %o1
118 retl
119 mov EX_RETVAL(GLOBAL_SPARE), %o0
120
121 .size FUNC_NAME, .-FUNC_NAME
diff --git a/arch/sparc64/lib/GENpage.S b/arch/sparc64/lib/GENpage.S
new file mode 100644
index 000000000000..2ef9d05f21bc
--- /dev/null
+++ b/arch/sparc64/lib/GENpage.S
@@ -0,0 +1,77 @@
1/* GENpage.S: Generic clear and copy page.
2 *
3 * Copyright (C) 2007 (davem@davemloft.net)
4 */
5#include <asm/page.h>
6
7 .text
8 .align 32
9
10GENcopy_user_page:
11 set PAGE_SIZE, %g7
121: ldx [%o1 + 0x00], %o2
13 ldx [%o1 + 0x08], %o3
14 ldx [%o1 + 0x10], %o4
15 ldx [%o1 + 0x18], %o5
16 stx %o2, [%o0 + 0x00]
17 stx %o3, [%o0 + 0x08]
18 stx %o4, [%o0 + 0x10]
19 stx %o5, [%o0 + 0x18]
20 ldx [%o1 + 0x20], %o2
21 ldx [%o1 + 0x28], %o3
22 ldx [%o1 + 0x30], %o4
23 ldx [%o1 + 0x38], %o5
24 stx %o2, [%o0 + 0x20]
25 stx %o3, [%o0 + 0x28]
26 stx %o4, [%o0 + 0x30]
27 stx %o5, [%o0 + 0x38]
28 subcc %g7, 64, %g7
29 add %o1, 64, %o1
30 bne,pt %xcc, 1b
31 add %o0, 64, %o0
32 retl
33 nop
34
35GENclear_page:
36GENclear_user_page:
37 set PAGE_SIZE, %g7
381: stx %g0, [%o0 + 0x00]
39 stx %g0, [%o0 + 0x08]
40 stx %g0, [%o0 + 0x10]
41 stx %g0, [%o0 + 0x18]
42 stx %g0, [%o0 + 0x20]
43 stx %g0, [%o0 + 0x28]
44 stx %g0, [%o0 + 0x30]
45 stx %g0, [%o0 + 0x38]
46 subcc %g7, 64, %g7
47 bne,pt %xcc, 1b
48 add %o0, 64, %o0
49
50#define BRANCH_ALWAYS 0x10680000
51#define NOP 0x01000000
52#define GEN_DO_PATCH(OLD, NEW) \
53 sethi %hi(NEW), %g1; \
54 or %g1, %lo(NEW), %g1; \
55 sethi %hi(OLD), %g2; \
56 or %g2, %lo(OLD), %g2; \
57 sub %g1, %g2, %g1; \
58 sethi %hi(BRANCH_ALWAYS), %g3; \
59 sll %g1, 11, %g1; \
60 srl %g1, 11 + 2, %g1; \
61 or %g3, %lo(BRANCH_ALWAYS), %g3; \
62 or %g3, %g1, %g3; \
63 stw %g3, [%g2]; \
64 sethi %hi(NOP), %g3; \
65 or %g3, %lo(NOP), %g3; \
66 stw %g3, [%g2 + 0x4]; \
67 flush %g2;
68
69 .globl generic_patch_pageops
70 .type generic_patch_pageops,#function
71generic_patch_pageops:
72 GEN_DO_PATCH(copy_user_page, GENcopy_user_page)
73 GEN_DO_PATCH(_clear_page, GENclear_page)
74 GEN_DO_PATCH(clear_user_page, GENclear_user_page)
75 retl
76 nop
77 .size generic_patch_pageops,.-generic_patch_pageops
diff --git a/arch/sparc64/lib/GENpatch.S b/arch/sparc64/lib/GENpatch.S
new file mode 100644
index 000000000000..fab9e89f16bd
--- /dev/null
+++ b/arch/sparc64/lib/GENpatch.S
@@ -0,0 +1,33 @@
1/* GENpatch.S: Patch Ultra-I routines with generic variant.
2 *
3 * Copyright (C) 2007 David S. Miller <davem@davemloft.net>
4 */
5
6#define BRANCH_ALWAYS 0x10680000
7#define NOP 0x01000000
8#define GEN_DO_PATCH(OLD, NEW) \
9 sethi %hi(NEW), %g1; \
10 or %g1, %lo(NEW), %g1; \
11 sethi %hi(OLD), %g2; \
12 or %g2, %lo(OLD), %g2; \
13 sub %g1, %g2, %g1; \
14 sethi %hi(BRANCH_ALWAYS), %g3; \
15 sll %g1, 11, %g1; \
16 srl %g1, 11 + 2, %g1; \
17 or %g3, %lo(BRANCH_ALWAYS), %g3; \
18 or %g3, %g1, %g3; \
19 stw %g3, [%g2]; \
20 sethi %hi(NOP), %g3; \
21 or %g3, %lo(NOP), %g3; \
22 stw %g3, [%g2 + 0x4]; \
23 flush %g2;
24
25 .globl generic_patch_copyops
26 .type generic_patch_copyops,#function
27generic_patch_copyops:
28 GEN_DO_PATCH(memcpy, GENmemcpy)
29 GEN_DO_PATCH(___copy_from_user, GENcopy_from_user)
30 GEN_DO_PATCH(___copy_to_user, GENcopy_to_user)
31 retl
32 nop
33 .size generic_patch_copyops,.-generic_patch_copyops
diff --git a/arch/sparc64/lib/Makefile b/arch/sparc64/lib/Makefile
index c4a6d6e7d03c..f95fbfa3eeb8 100644
--- a/arch/sparc64/lib/Makefile
+++ b/arch/sparc64/lib/Makefile
@@ -1,4 +1,4 @@
1# $Id: Makefile,v 1.25 2000/12/14 22:57:25 davem Exp $ 1#
2# Makefile for Sparc64 library files.. 2# Makefile for Sparc64 library files..
3# 3#
4 4
@@ -13,6 +13,8 @@ lib-y := PeeCeeI.o copy_page.o clear_page.o strlen.o strncmp.o \
13 U3memcpy.o U3copy_from_user.o U3copy_to_user.o U3patch.o \ 13 U3memcpy.o U3copy_from_user.o U3copy_to_user.o U3patch.o \
14 NGmemcpy.o NGcopy_from_user.o NGcopy_to_user.o NGpatch.o \ 14 NGmemcpy.o NGcopy_from_user.o NGcopy_to_user.o NGpatch.o \
15 NGpage.o NGbzero.o \ 15 NGpage.o NGbzero.o \
16 GENmemcpy.o GENcopy_from_user.o GENcopy_to_user.o GENpatch.o \
17 GENpage.o GENbzero.o \
16 copy_in_user.o user_fixup.o memmove.o \ 18 copy_in_user.o user_fixup.o memmove.o \
17 mcount.o ipcsum.o rwsem.o xor.o 19 mcount.o ipcsum.o rwsem.o xor.o
18 20