aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sparc
diff options
context:
space:
mode:
Diffstat (limited to 'arch/sparc')
-rw-r--r--arch/sparc/Kconfig1
-rw-r--r--arch/sparc/include/asm/compat.h3
-rw-r--r--arch/sparc/include/asm/pgtsrmmu.h2
-rw-r--r--arch/sparc/include/asm/sigcontext.h14
-rw-r--r--arch/sparc/include/asm/spinlock_32.h11
-rw-r--r--arch/sparc/include/asm/spinlock_64.h6
-rw-r--r--arch/sparc/include/asm/spitfire.h2
-rw-r--r--arch/sparc/include/asm/xor_64.h4
-rw-r--r--arch/sparc/kernel/Makefile1
-rw-r--r--arch/sparc/kernel/cpu.c12
-rw-r--r--arch/sparc/kernel/cpumap.c2
-rw-r--r--arch/sparc/kernel/ds.c13
-rw-r--r--arch/sparc/kernel/head_64.S25
-rw-r--r--arch/sparc/kernel/irq.h2
-rw-r--r--arch/sparc/kernel/pci.c3
-rw-r--r--arch/sparc/kernel/pcic.c4
-rw-r--r--arch/sparc/kernel/process_32.c3
-rw-r--r--arch/sparc/kernel/process_64.c3
-rw-r--r--arch/sparc/kernel/setup_32.c2
-rw-r--r--arch/sparc/kernel/setup_64.c28
-rw-r--r--arch/sparc/kernel/signal32.c205
-rw-r--r--arch/sparc/kernel/signal_32.c204
-rw-r--r--arch/sparc/kernel/signal_64.c140
-rw-r--r--arch/sparc/kernel/sigutil.h9
-rw-r--r--arch/sparc/kernel/sigutil_32.c120
-rw-r--r--arch/sparc/kernel/sigutil_64.c93
-rw-r--r--arch/sparc/kernel/sys32.S1
-rw-r--r--arch/sparc/kernel/systbls_32.S2
-rw-r--r--arch/sparc/kernel/systbls_64.S4
-rw-r--r--arch/sparc/kernel/visemul.c32
-rw-r--r--arch/sparc/lib/memcpy.S804
-rw-r--r--arch/sparc/mm/gup.c2
-rw-r--r--arch/sparc/mm/init_64.c5
-rw-r--r--arch/sparc/mm/leon_mm.c2
34 files changed, 716 insertions, 1048 deletions
diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig
index 29ead342a4a8..f92602e86607 100644
--- a/arch/sparc/Kconfig
+++ b/arch/sparc/Kconfig
@@ -55,6 +55,7 @@ config SPARC64
55 select PERF_USE_VMALLOC 55 select PERF_USE_VMALLOC
56 select IRQ_PREFLOW_FASTEOI 56 select IRQ_PREFLOW_FASTEOI
57 select ARCH_HAVE_NMI_SAFE_CMPXCHG 57 select ARCH_HAVE_NMI_SAFE_CMPXCHG
58 select HAVE_C_RECORDMCOUNT
58 59
59config ARCH_DEFCONFIG 60config ARCH_DEFCONFIG
60 string 61 string
diff --git a/arch/sparc/include/asm/compat.h b/arch/sparc/include/asm/compat.h
index 6f57325bb883..b8be20d42a0a 100644
--- a/arch/sparc/include/asm/compat.h
+++ b/arch/sparc/include/asm/compat.h
@@ -134,7 +134,8 @@ struct compat_statfs {
134 compat_fsid_t f_fsid; 134 compat_fsid_t f_fsid;
135 int f_namelen; /* SunOS ignores this field. */ 135 int f_namelen; /* SunOS ignores this field. */
136 int f_frsize; 136 int f_frsize;
137 int f_spare[5]; 137 int f_flags;
138 int f_spare[4];
138}; 139};
139 140
140#define COMPAT_RLIM_INFINITY 0x7fffffff 141#define COMPAT_RLIM_INFINITY 0x7fffffff
diff --git a/arch/sparc/include/asm/pgtsrmmu.h b/arch/sparc/include/asm/pgtsrmmu.h
index 1407c07bdade..f6ae2b2b6870 100644
--- a/arch/sparc/include/asm/pgtsrmmu.h
+++ b/arch/sparc/include/asm/pgtsrmmu.h
@@ -280,7 +280,7 @@ static inline unsigned long srmmu_hwprobe(unsigned long vaddr)
280 return retval; 280 return retval;
281} 281}
282#else 282#else
283#define srmmu_hwprobe(addr) (srmmu_swprobe(addr, 0) & SRMMU_PTE_PMASK) 283#define srmmu_hwprobe(addr) srmmu_swprobe(addr, 0)
284#endif 284#endif
285 285
286static inline int 286static inline int
diff --git a/arch/sparc/include/asm/sigcontext.h b/arch/sparc/include/asm/sigcontext.h
index a1607d180354..69914d748130 100644
--- a/arch/sparc/include/asm/sigcontext.h
+++ b/arch/sparc/include/asm/sigcontext.h
@@ -45,6 +45,19 @@ typedef struct {
45 int si_mask; 45 int si_mask;
46} __siginfo32_t; 46} __siginfo32_t;
47 47
48#define __SIGC_MAXWIN 7
49
50typedef struct {
51 unsigned long locals[8];
52 unsigned long ins[8];
53} __siginfo_reg_window;
54
55typedef struct {
56 int wsaved;
57 __siginfo_reg_window reg_window[__SIGC_MAXWIN];
58 unsigned long rwbuf_stkptrs[__SIGC_MAXWIN];
59} __siginfo_rwin_t;
60
48#ifdef CONFIG_SPARC64 61#ifdef CONFIG_SPARC64
49typedef struct { 62typedef struct {
50 unsigned int si_float_regs [64]; 63 unsigned int si_float_regs [64];
@@ -73,6 +86,7 @@ struct sigcontext {
73 unsigned long ss_size; 86 unsigned long ss_size;
74 } sigc_stack; 87 } sigc_stack;
75 unsigned long sigc_mask; 88 unsigned long sigc_mask;
89 __siginfo_rwin_t * sigc_rwin_save;
76}; 90};
77 91
78#else 92#else
diff --git a/arch/sparc/include/asm/spinlock_32.h b/arch/sparc/include/asm/spinlock_32.h
index 5f5b8bf3f50d..bcc98fc35281 100644
--- a/arch/sparc/include/asm/spinlock_32.h
+++ b/arch/sparc/include/asm/spinlock_32.h
@@ -131,6 +131,15 @@ static inline void arch_write_lock(arch_rwlock_t *rw)
131 *(volatile __u32 *)&lp->lock = ~0U; 131 *(volatile __u32 *)&lp->lock = ~0U;
132} 132}
133 133
134static void inline arch_write_unlock(arch_rwlock_t *lock)
135{
136 __asm__ __volatile__(
137" st %%g0, [%0]"
138 : /* no outputs */
139 : "r" (lock)
140 : "memory");
141}
142
134static inline int arch_write_trylock(arch_rwlock_t *rw) 143static inline int arch_write_trylock(arch_rwlock_t *rw)
135{ 144{
136 unsigned int val; 145 unsigned int val;
@@ -175,8 +184,6 @@ static inline int __arch_read_trylock(arch_rwlock_t *rw)
175 res; \ 184 res; \
176}) 185})
177 186
178#define arch_write_unlock(rw) do { (rw)->lock = 0; } while(0)
179
180#define arch_spin_lock_flags(lock, flags) arch_spin_lock(lock) 187#define arch_spin_lock_flags(lock, flags) arch_spin_lock(lock)
181#define arch_read_lock_flags(rw, flags) arch_read_lock(rw) 188#define arch_read_lock_flags(rw, flags) arch_read_lock(rw)
182#define arch_write_lock_flags(rw, flags) arch_write_lock(rw) 189#define arch_write_lock_flags(rw, flags) arch_write_lock(rw)
diff --git a/arch/sparc/include/asm/spinlock_64.h b/arch/sparc/include/asm/spinlock_64.h
index 073936a8b275..968917694978 100644
--- a/arch/sparc/include/asm/spinlock_64.h
+++ b/arch/sparc/include/asm/spinlock_64.h
@@ -210,14 +210,8 @@ static int inline arch_write_trylock(arch_rwlock_t *lock)
210 return result; 210 return result;
211} 211}
212 212
213#define arch_read_lock(p) arch_read_lock(p)
214#define arch_read_lock_flags(p, f) arch_read_lock(p) 213#define arch_read_lock_flags(p, f) arch_read_lock(p)
215#define arch_read_trylock(p) arch_read_trylock(p)
216#define arch_read_unlock(p) arch_read_unlock(p)
217#define arch_write_lock(p) arch_write_lock(p)
218#define arch_write_lock_flags(p, f) arch_write_lock(p) 214#define arch_write_lock_flags(p, f) arch_write_lock(p)
219#define arch_write_unlock(p) arch_write_unlock(p)
220#define arch_write_trylock(p) arch_write_trylock(p)
221 215
222#define arch_read_can_lock(rw) (!((rw)->lock & 0x80000000UL)) 216#define arch_read_can_lock(rw) (!((rw)->lock & 0x80000000UL))
223#define arch_write_can_lock(rw) (!(rw)->lock) 217#define arch_write_can_lock(rw) (!(rw)->lock)
diff --git a/arch/sparc/include/asm/spitfire.h b/arch/sparc/include/asm/spitfire.h
index 55a17c6efeb8..d06a26601753 100644
--- a/arch/sparc/include/asm/spitfire.h
+++ b/arch/sparc/include/asm/spitfire.h
@@ -43,6 +43,8 @@
43#define SUN4V_CHIP_NIAGARA1 0x01 43#define SUN4V_CHIP_NIAGARA1 0x01
44#define SUN4V_CHIP_NIAGARA2 0x02 44#define SUN4V_CHIP_NIAGARA2 0x02
45#define SUN4V_CHIP_NIAGARA3 0x03 45#define SUN4V_CHIP_NIAGARA3 0x03
46#define SUN4V_CHIP_NIAGARA4 0x04
47#define SUN4V_CHIP_NIAGARA5 0x05
46#define SUN4V_CHIP_UNKNOWN 0xff 48#define SUN4V_CHIP_UNKNOWN 0xff
47 49
48#ifndef __ASSEMBLY__ 50#ifndef __ASSEMBLY__
diff --git a/arch/sparc/include/asm/xor_64.h b/arch/sparc/include/asm/xor_64.h
index 9ed6ff679ab7..ee8edc68423e 100644
--- a/arch/sparc/include/asm/xor_64.h
+++ b/arch/sparc/include/asm/xor_64.h
@@ -66,6 +66,8 @@ static struct xor_block_template xor_block_niagara = {
66 ((tlb_type == hypervisor && \ 66 ((tlb_type == hypervisor && \
67 (sun4v_chip_type == SUN4V_CHIP_NIAGARA1 || \ 67 (sun4v_chip_type == SUN4V_CHIP_NIAGARA1 || \
68 sun4v_chip_type == SUN4V_CHIP_NIAGARA2 || \ 68 sun4v_chip_type == SUN4V_CHIP_NIAGARA2 || \
69 sun4v_chip_type == SUN4V_CHIP_NIAGARA3)) ? \ 69 sun4v_chip_type == SUN4V_CHIP_NIAGARA3 || \
70 sun4v_chip_type == SUN4V_CHIP_NIAGARA4 || \
71 sun4v_chip_type == SUN4V_CHIP_NIAGARA5)) ? \
70 &xor_block_niagara : \ 72 &xor_block_niagara : \
71 &xor_block_VIS) 73 &xor_block_VIS)
diff --git a/arch/sparc/kernel/Makefile b/arch/sparc/kernel/Makefile
index b90b4a1d070a..cb85458f89d2 100644
--- a/arch/sparc/kernel/Makefile
+++ b/arch/sparc/kernel/Makefile
@@ -32,6 +32,7 @@ obj-$(CONFIG_SPARC32) += sun4m_irq.o sun4c_irq.o sun4d_irq.o
32 32
33obj-y += process_$(BITS).o 33obj-y += process_$(BITS).o
34obj-y += signal_$(BITS).o 34obj-y += signal_$(BITS).o
35obj-y += sigutil_$(BITS).o
35obj-$(CONFIG_SPARC32) += ioport.o 36obj-$(CONFIG_SPARC32) += ioport.o
36obj-y += setup_$(BITS).o 37obj-y += setup_$(BITS).o
37obj-y += idprom.o 38obj-y += idprom.o
diff --git a/arch/sparc/kernel/cpu.c b/arch/sparc/kernel/cpu.c
index 9810fd881058..ba9b1cec4e6b 100644
--- a/arch/sparc/kernel/cpu.c
+++ b/arch/sparc/kernel/cpu.c
@@ -481,6 +481,18 @@ static void __init sun4v_cpu_probe(void)
481 sparc_pmu_type = "niagara3"; 481 sparc_pmu_type = "niagara3";
482 break; 482 break;
483 483
484 case SUN4V_CHIP_NIAGARA4:
485 sparc_cpu_type = "UltraSparc T4 (Niagara4)";
486 sparc_fpu_type = "UltraSparc T4 integrated FPU";
487 sparc_pmu_type = "niagara4";
488 break;
489
490 case SUN4V_CHIP_NIAGARA5:
491 sparc_cpu_type = "UltraSparc T5 (Niagara5)";
492 sparc_fpu_type = "UltraSparc T5 integrated FPU";
493 sparc_pmu_type = "niagara5";
494 break;
495
484 default: 496 default:
485 printk(KERN_WARNING "CPU: Unknown sun4v cpu type [%s]\n", 497 printk(KERN_WARNING "CPU: Unknown sun4v cpu type [%s]\n",
486 prom_cpu_compatible); 498 prom_cpu_compatible);
diff --git a/arch/sparc/kernel/cpumap.c b/arch/sparc/kernel/cpumap.c
index 4197e8d62d4c..9323eafccb93 100644
--- a/arch/sparc/kernel/cpumap.c
+++ b/arch/sparc/kernel/cpumap.c
@@ -325,6 +325,8 @@ static int iterate_cpu(struct cpuinfo_tree *t, unsigned int root_index)
325 case SUN4V_CHIP_NIAGARA1: 325 case SUN4V_CHIP_NIAGARA1:
326 case SUN4V_CHIP_NIAGARA2: 326 case SUN4V_CHIP_NIAGARA2:
327 case SUN4V_CHIP_NIAGARA3: 327 case SUN4V_CHIP_NIAGARA3:
328 case SUN4V_CHIP_NIAGARA4:
329 case SUN4V_CHIP_NIAGARA5:
328 rover_inc_table = niagara_iterate_method; 330 rover_inc_table = niagara_iterate_method;
329 break; 331 break;
330 default: 332 default:
diff --git a/arch/sparc/kernel/ds.c b/arch/sparc/kernel/ds.c
index 490e5418740d..7429b47c3aca 100644
--- a/arch/sparc/kernel/ds.c
+++ b/arch/sparc/kernel/ds.c
@@ -1256,13 +1256,14 @@ static int __init ds_init(void)
1256{ 1256{
1257 unsigned long hv_ret, major, minor; 1257 unsigned long hv_ret, major, minor;
1258 1258
1259 hv_ret = sun4v_get_version(HV_GRP_REBOOT_DATA, &major, &minor); 1259 if (tlb_type == hypervisor) {
1260 if (hv_ret == HV_EOK) { 1260 hv_ret = sun4v_get_version(HV_GRP_REBOOT_DATA, &major, &minor);
1261 pr_info("SUN4V: Reboot data supported (maj=%lu,min=%lu).\n", 1261 if (hv_ret == HV_EOK) {
1262 major, minor); 1262 pr_info("SUN4V: Reboot data supported (maj=%lu,min=%lu).\n",
1263 reboot_data_supported = 1; 1263 major, minor);
1264 reboot_data_supported = 1;
1265 }
1264 } 1266 }
1265
1266 kthread_run(ds_thread, NULL, "kldomd"); 1267 kthread_run(ds_thread, NULL, "kldomd");
1267 1268
1268 return vio_register_driver(&ds_driver); 1269 return vio_register_driver(&ds_driver);
diff --git a/arch/sparc/kernel/head_64.S b/arch/sparc/kernel/head_64.S
index 0eac1b2fc53d..0d810c2f1d00 100644
--- a/arch/sparc/kernel/head_64.S
+++ b/arch/sparc/kernel/head_64.S
@@ -133,7 +133,7 @@ prom_sun4v_name:
133prom_niagara_prefix: 133prom_niagara_prefix:
134 .asciz "SUNW,UltraSPARC-T" 134 .asciz "SUNW,UltraSPARC-T"
135prom_sparc_prefix: 135prom_sparc_prefix:
136 .asciz "SPARC-T" 136 .asciz "SPARC-"
137 .align 4 137 .align 4
138prom_root_compatible: 138prom_root_compatible:
139 .skip 64 139 .skip 64
@@ -396,7 +396,7 @@ sun4v_chip_type:
396 or %g1, %lo(prom_cpu_compatible), %g1 396 or %g1, %lo(prom_cpu_compatible), %g1
397 sethi %hi(prom_sparc_prefix), %g7 397 sethi %hi(prom_sparc_prefix), %g7
398 or %g7, %lo(prom_sparc_prefix), %g7 398 or %g7, %lo(prom_sparc_prefix), %g7
399 mov 7, %g3 399 mov 6, %g3
40090: ldub [%g7], %g2 40090: ldub [%g7], %g2
401 ldub [%g1], %g4 401 ldub [%g1], %g4
402 cmp %g2, %g4 402 cmp %g2, %g4
@@ -408,10 +408,23 @@ sun4v_chip_type:
408 408
409 sethi %hi(prom_cpu_compatible), %g1 409 sethi %hi(prom_cpu_compatible), %g1
410 or %g1, %lo(prom_cpu_compatible), %g1 410 or %g1, %lo(prom_cpu_compatible), %g1
411 ldub [%g1 + 7], %g2 411 ldub [%g1 + 6], %g2
412 cmp %g2, 'T'
413 be,pt %xcc, 70f
414 cmp %g2, 'M'
415 bne,pn %xcc, 4f
416 nop
417
41870: ldub [%g1 + 7], %g2
412 cmp %g2, '3' 419 cmp %g2, '3'
413 be,pt %xcc, 5f 420 be,pt %xcc, 5f
414 mov SUN4V_CHIP_NIAGARA3, %g4 421 mov SUN4V_CHIP_NIAGARA3, %g4
422 cmp %g2, '4'
423 be,pt %xcc, 5f
424 mov SUN4V_CHIP_NIAGARA4, %g4
425 cmp %g2, '5'
426 be,pt %xcc, 5f
427 mov SUN4V_CHIP_NIAGARA5, %g4
415 ba,pt %xcc, 4f 428 ba,pt %xcc, 4f
416 nop 429 nop
417 430
@@ -545,6 +558,12 @@ niagara_tlb_fixup:
545 cmp %g1, SUN4V_CHIP_NIAGARA3 558 cmp %g1, SUN4V_CHIP_NIAGARA3
546 be,pt %xcc, niagara2_patch 559 be,pt %xcc, niagara2_patch
547 nop 560 nop
561 cmp %g1, SUN4V_CHIP_NIAGARA4
562 be,pt %xcc, niagara2_patch
563 nop
564 cmp %g1, SUN4V_CHIP_NIAGARA5
565 be,pt %xcc, niagara2_patch
566 nop
548 567
549 call generic_patch_copyops 568 call generic_patch_copyops
550 nop 569 nop
diff --git a/arch/sparc/kernel/irq.h b/arch/sparc/kernel/irq.h
index 100b9c204e78..42851122bbd9 100644
--- a/arch/sparc/kernel/irq.h
+++ b/arch/sparc/kernel/irq.h
@@ -88,7 +88,7 @@ BTFIXUPDEF_CALL(void, set_irq_udt, int)
88#define set_irq_udt(cpu) BTFIXUP_CALL(set_irq_udt)(cpu) 88#define set_irq_udt(cpu) BTFIXUP_CALL(set_irq_udt)(cpu)
89 89
90/* All SUN4D IPIs are sent on this IRQ, may be shared with hard IRQs */ 90/* All SUN4D IPIs are sent on this IRQ, may be shared with hard IRQs */
91#define SUN4D_IPI_IRQ 14 91#define SUN4D_IPI_IRQ 13
92 92
93extern void sun4d_ipi_interrupt(void); 93extern void sun4d_ipi_interrupt(void);
94 94
diff --git a/arch/sparc/kernel/pci.c b/arch/sparc/kernel/pci.c
index 1e94f946570e..8aa0d4408586 100644
--- a/arch/sparc/kernel/pci.c
+++ b/arch/sparc/kernel/pci.c
@@ -230,7 +230,8 @@ static void pci_parse_of_addrs(struct platform_device *op,
230 res = &dev->resource[(i - PCI_BASE_ADDRESS_0) >> 2]; 230 res = &dev->resource[(i - PCI_BASE_ADDRESS_0) >> 2];
231 } else if (i == dev->rom_base_reg) { 231 } else if (i == dev->rom_base_reg) {
232 res = &dev->resource[PCI_ROM_RESOURCE]; 232 res = &dev->resource[PCI_ROM_RESOURCE];
233 flags |= IORESOURCE_READONLY | IORESOURCE_CACHEABLE; 233 flags |= IORESOURCE_READONLY | IORESOURCE_CACHEABLE
234 | IORESOURCE_SIZEALIGN;
234 } else { 235 } else {
235 printk(KERN_ERR "PCI: bad cfg reg num 0x%x\n", i); 236 printk(KERN_ERR "PCI: bad cfg reg num 0x%x\n", i);
236 continue; 237 continue;
diff --git a/arch/sparc/kernel/pcic.c b/arch/sparc/kernel/pcic.c
index a19f04195478..1aaf8c180be5 100644
--- a/arch/sparc/kernel/pcic.c
+++ b/arch/sparc/kernel/pcic.c
@@ -352,8 +352,8 @@ int __init pcic_probe(void)
352 strcpy(pbm->prom_name, namebuf); 352 strcpy(pbm->prom_name, namebuf);
353 353
354 { 354 {
355 extern volatile int t_nmi[1]; 355 extern volatile int t_nmi[4];
356 extern int pcic_nmi_trap_patch[1]; 356 extern int pcic_nmi_trap_patch[4];
357 357
358 t_nmi[0] = pcic_nmi_trap_patch[0]; 358 t_nmi[0] = pcic_nmi_trap_patch[0];
359 t_nmi[1] = pcic_nmi_trap_patch[1]; 359 t_nmi[1] = pcic_nmi_trap_patch[1];
diff --git a/arch/sparc/kernel/process_32.c b/arch/sparc/kernel/process_32.c
index c8cc461ff75f..f793742eec2b 100644
--- a/arch/sparc/kernel/process_32.c
+++ b/arch/sparc/kernel/process_32.c
@@ -380,8 +380,7 @@ void flush_thread(void)
380#endif 380#endif
381 } 381 }
382 382
383 /* Now, this task is no longer a kernel thread. */ 383 /* This task is no longer a kernel thread. */
384 current->thread.current_ds = USER_DS;
385 if (current->thread.flags & SPARC_FLAG_KTHREAD) { 384 if (current->thread.flags & SPARC_FLAG_KTHREAD) {
386 current->thread.flags &= ~SPARC_FLAG_KTHREAD; 385 current->thread.flags &= ~SPARC_FLAG_KTHREAD;
387 386
diff --git a/arch/sparc/kernel/process_64.c b/arch/sparc/kernel/process_64.c
index c158a95ec664..d959cd0a4aa4 100644
--- a/arch/sparc/kernel/process_64.c
+++ b/arch/sparc/kernel/process_64.c
@@ -368,9 +368,6 @@ void flush_thread(void)
368 368
369 /* Clear FPU register state. */ 369 /* Clear FPU register state. */
370 t->fpsaved[0] = 0; 370 t->fpsaved[0] = 0;
371
372 if (get_thread_current_ds() != ASI_AIUS)
373 set_fs(USER_DS);
374} 371}
375 372
376/* It's a bit more tricky when 64-bit tasks are involved... */ 373/* It's a bit more tricky when 64-bit tasks are involved... */
diff --git a/arch/sparc/kernel/setup_32.c b/arch/sparc/kernel/setup_32.c
index d26e1f6c717a..3e3e2914c70b 100644
--- a/arch/sparc/kernel/setup_32.c
+++ b/arch/sparc/kernel/setup_32.c
@@ -137,7 +137,7 @@ static void __init process_switch(char c)
137 prom_halt(); 137 prom_halt();
138 break; 138 break;
139 case 'p': 139 case 'p':
140 /* Just ignore, this behavior is now the default. */ 140 prom_early_console.flags &= ~CON_BOOT;
141 break; 141 break;
142 default: 142 default:
143 printk("Unknown boot switch (-%c)\n", c); 143 printk("Unknown boot switch (-%c)\n", c);
diff --git a/arch/sparc/kernel/setup_64.c b/arch/sparc/kernel/setup_64.c
index 3e9daea1653d..c965595aa7e9 100644
--- a/arch/sparc/kernel/setup_64.c
+++ b/arch/sparc/kernel/setup_64.c
@@ -106,7 +106,7 @@ static void __init process_switch(char c)
106 prom_halt(); 106 prom_halt();
107 break; 107 break;
108 case 'p': 108 case 'p':
109 /* Just ignore, this behavior is now the default. */ 109 prom_early_console.flags &= ~CON_BOOT;
110 break; 110 break;
111 case 'P': 111 case 'P':
112 /* Force UltraSPARC-III P-Cache on. */ 112 /* Force UltraSPARC-III P-Cache on. */
@@ -425,10 +425,14 @@ static void __init init_sparc64_elf_hwcap(void)
425 else if (tlb_type == hypervisor) { 425 else if (tlb_type == hypervisor) {
426 if (sun4v_chip_type == SUN4V_CHIP_NIAGARA1 || 426 if (sun4v_chip_type == SUN4V_CHIP_NIAGARA1 ||
427 sun4v_chip_type == SUN4V_CHIP_NIAGARA2 || 427 sun4v_chip_type == SUN4V_CHIP_NIAGARA2 ||
428 sun4v_chip_type == SUN4V_CHIP_NIAGARA3) 428 sun4v_chip_type == SUN4V_CHIP_NIAGARA3 ||
429 sun4v_chip_type == SUN4V_CHIP_NIAGARA4 ||
430 sun4v_chip_type == SUN4V_CHIP_NIAGARA5)
429 cap |= HWCAP_SPARC_BLKINIT; 431 cap |= HWCAP_SPARC_BLKINIT;
430 if (sun4v_chip_type == SUN4V_CHIP_NIAGARA2 || 432 if (sun4v_chip_type == SUN4V_CHIP_NIAGARA2 ||
431 sun4v_chip_type == SUN4V_CHIP_NIAGARA3) 433 sun4v_chip_type == SUN4V_CHIP_NIAGARA3 ||
434 sun4v_chip_type == SUN4V_CHIP_NIAGARA4 ||
435 sun4v_chip_type == SUN4V_CHIP_NIAGARA5)
432 cap |= HWCAP_SPARC_N2; 436 cap |= HWCAP_SPARC_N2;
433 } 437 }
434 438
@@ -440,17 +444,27 @@ static void __init init_sparc64_elf_hwcap(void)
440 cap |= AV_SPARC_VIS; 444 cap |= AV_SPARC_VIS;
441 if (tlb_type == cheetah || tlb_type == cheetah_plus) 445 if (tlb_type == cheetah || tlb_type == cheetah_plus)
442 cap |= AV_SPARC_VIS | AV_SPARC_VIS2; 446 cap |= AV_SPARC_VIS | AV_SPARC_VIS2;
443 if (tlb_type == cheetah_plus) 447 if (tlb_type == cheetah_plus) {
444 cap |= AV_SPARC_POPC; 448 unsigned long impl, ver;
449
450 __asm__ __volatile__("rdpr %%ver, %0" : "=r" (ver));
451 impl = ((ver >> 32) & 0xffff);
452 if (impl == PANTHER_IMPL)
453 cap |= AV_SPARC_POPC;
454 }
445 if (tlb_type == hypervisor) { 455 if (tlb_type == hypervisor) {
446 if (sun4v_chip_type == SUN4V_CHIP_NIAGARA1) 456 if (sun4v_chip_type == SUN4V_CHIP_NIAGARA1)
447 cap |= AV_SPARC_ASI_BLK_INIT; 457 cap |= AV_SPARC_ASI_BLK_INIT;
448 if (sun4v_chip_type == SUN4V_CHIP_NIAGARA2 || 458 if (sun4v_chip_type == SUN4V_CHIP_NIAGARA2 ||
449 sun4v_chip_type == SUN4V_CHIP_NIAGARA3) 459 sun4v_chip_type == SUN4V_CHIP_NIAGARA3 ||
460 sun4v_chip_type == SUN4V_CHIP_NIAGARA4 ||
461 sun4v_chip_type == SUN4V_CHIP_NIAGARA5)
450 cap |= (AV_SPARC_VIS | AV_SPARC_VIS2 | 462 cap |= (AV_SPARC_VIS | AV_SPARC_VIS2 |
451 AV_SPARC_ASI_BLK_INIT | 463 AV_SPARC_ASI_BLK_INIT |
452 AV_SPARC_POPC); 464 AV_SPARC_POPC);
453 if (sun4v_chip_type == SUN4V_CHIP_NIAGARA3) 465 if (sun4v_chip_type == SUN4V_CHIP_NIAGARA3 ||
466 sun4v_chip_type == SUN4V_CHIP_NIAGARA4 ||
467 sun4v_chip_type == SUN4V_CHIP_NIAGARA5)
454 cap |= (AV_SPARC_VIS3 | AV_SPARC_HPC | 468 cap |= (AV_SPARC_VIS3 | AV_SPARC_HPC |
455 AV_SPARC_FMAF); 469 AV_SPARC_FMAF);
456 } 470 }
diff --git a/arch/sparc/kernel/signal32.c b/arch/sparc/kernel/signal32.c
index 75fad425e249..2caa556db86d 100644
--- a/arch/sparc/kernel/signal32.c
+++ b/arch/sparc/kernel/signal32.c
@@ -29,6 +29,8 @@
29#include <asm/visasm.h> 29#include <asm/visasm.h>
30#include <asm/compat_signal.h> 30#include <asm/compat_signal.h>
31 31
32#include "sigutil.h"
33
32#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) 34#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
33 35
34/* This magic should be in g_upper[0] for all upper parts 36/* This magic should be in g_upper[0] for all upper parts
@@ -44,14 +46,14 @@ typedef struct {
44struct signal_frame32 { 46struct signal_frame32 {
45 struct sparc_stackf32 ss; 47 struct sparc_stackf32 ss;
46 __siginfo32_t info; 48 __siginfo32_t info;
47 /* __siginfo_fpu32_t * */ u32 fpu_save; 49 /* __siginfo_fpu_t * */ u32 fpu_save;
48 unsigned int insns[2]; 50 unsigned int insns[2];
49 unsigned int extramask[_COMPAT_NSIG_WORDS - 1]; 51 unsigned int extramask[_COMPAT_NSIG_WORDS - 1];
50 unsigned int extra_size; /* Should be sizeof(siginfo_extra_v8plus_t) */ 52 unsigned int extra_size; /* Should be sizeof(siginfo_extra_v8plus_t) */
51 /* Only valid if (info.si_regs.psr & (PSR_VERS|PSR_IMPL)) == PSR_V8PLUS */ 53 /* Only valid if (info.si_regs.psr & (PSR_VERS|PSR_IMPL)) == PSR_V8PLUS */
52 siginfo_extra_v8plus_t v8plus; 54 siginfo_extra_v8plus_t v8plus;
53 __siginfo_fpu_t fpu_state; 55 /* __siginfo_rwin_t * */u32 rwin_save;
54}; 56} __attribute__((aligned(8)));
55 57
56typedef struct compat_siginfo{ 58typedef struct compat_siginfo{
57 int si_signo; 59 int si_signo;
@@ -110,18 +112,14 @@ struct rt_signal_frame32 {
110 compat_siginfo_t info; 112 compat_siginfo_t info;
111 struct pt_regs32 regs; 113 struct pt_regs32 regs;
112 compat_sigset_t mask; 114 compat_sigset_t mask;
113 /* __siginfo_fpu32_t * */ u32 fpu_save; 115 /* __siginfo_fpu_t * */ u32 fpu_save;
114 unsigned int insns[2]; 116 unsigned int insns[2];
115 stack_t32 stack; 117 stack_t32 stack;
116 unsigned int extra_size; /* Should be sizeof(siginfo_extra_v8plus_t) */ 118 unsigned int extra_size; /* Should be sizeof(siginfo_extra_v8plus_t) */
117 /* Only valid if (regs.psr & (PSR_VERS|PSR_IMPL)) == PSR_V8PLUS */ 119 /* Only valid if (regs.psr & (PSR_VERS|PSR_IMPL)) == PSR_V8PLUS */
118 siginfo_extra_v8plus_t v8plus; 120 siginfo_extra_v8plus_t v8plus;
119 __siginfo_fpu_t fpu_state; 121 /* __siginfo_rwin_t * */u32 rwin_save;
120}; 122} __attribute__((aligned(8)));
121
122/* Align macros */
123#define SF_ALIGNEDSZ (((sizeof(struct signal_frame32) + 15) & (~15)))
124#define RT_ALIGNEDSZ (((sizeof(struct rt_signal_frame32) + 15) & (~15)))
125 123
126int copy_siginfo_to_user32(compat_siginfo_t __user *to, siginfo_t *from) 124int copy_siginfo_to_user32(compat_siginfo_t __user *to, siginfo_t *from)
127{ 125{
@@ -192,30 +190,13 @@ int copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from)
192 return 0; 190 return 0;
193} 191}
194 192
195static int restore_fpu_state32(struct pt_regs *regs, __siginfo_fpu_t __user *fpu)
196{
197 unsigned long *fpregs = current_thread_info()->fpregs;
198 unsigned long fprs;
199 int err;
200
201 err = __get_user(fprs, &fpu->si_fprs);
202 fprs_write(0);
203 regs->tstate &= ~TSTATE_PEF;
204 if (fprs & FPRS_DL)
205 err |= copy_from_user(fpregs, &fpu->si_float_regs[0], (sizeof(unsigned int) * 32));
206 if (fprs & FPRS_DU)
207 err |= copy_from_user(fpregs+16, &fpu->si_float_regs[32], (sizeof(unsigned int) * 32));
208 err |= __get_user(current_thread_info()->xfsr[0], &fpu->si_fsr);
209 err |= __get_user(current_thread_info()->gsr[0], &fpu->si_gsr);
210 current_thread_info()->fpsaved[0] |= fprs;
211 return err;
212}
213
214void do_sigreturn32(struct pt_regs *regs) 193void do_sigreturn32(struct pt_regs *regs)
215{ 194{
216 struct signal_frame32 __user *sf; 195 struct signal_frame32 __user *sf;
196 compat_uptr_t fpu_save;
197 compat_uptr_t rwin_save;
217 unsigned int psr; 198 unsigned int psr;
218 unsigned pc, npc, fpu_save; 199 unsigned pc, npc;
219 sigset_t set; 200 sigset_t set;
220 unsigned seta[_COMPAT_NSIG_WORDS]; 201 unsigned seta[_COMPAT_NSIG_WORDS];
221 int err, i; 202 int err, i;
@@ -273,8 +254,13 @@ void do_sigreturn32(struct pt_regs *regs)
273 pt_regs_clear_syscall(regs); 254 pt_regs_clear_syscall(regs);
274 255
275 err |= __get_user(fpu_save, &sf->fpu_save); 256 err |= __get_user(fpu_save, &sf->fpu_save);
276 if (fpu_save) 257 if (!err && fpu_save)
277 err |= restore_fpu_state32(regs, &sf->fpu_state); 258 err |= restore_fpu_state(regs, compat_ptr(fpu_save));
259 err |= __get_user(rwin_save, &sf->rwin_save);
260 if (!err && rwin_save) {
261 if (restore_rwin_state(compat_ptr(rwin_save)))
262 goto segv;
263 }
278 err |= __get_user(seta[0], &sf->info.si_mask); 264 err |= __get_user(seta[0], &sf->info.si_mask);
279 err |= copy_from_user(seta+1, &sf->extramask, 265 err |= copy_from_user(seta+1, &sf->extramask,
280 (_COMPAT_NSIG_WORDS - 1) * sizeof(unsigned int)); 266 (_COMPAT_NSIG_WORDS - 1) * sizeof(unsigned int));
@@ -287,10 +273,7 @@ void do_sigreturn32(struct pt_regs *regs)
287 case 1: set.sig[0] = seta[0] + (((long)seta[1]) << 32); 273 case 1: set.sig[0] = seta[0] + (((long)seta[1]) << 32);
288 } 274 }
289 sigdelsetmask(&set, ~_BLOCKABLE); 275 sigdelsetmask(&set, ~_BLOCKABLE);
290 spin_lock_irq(&current->sighand->siglock); 276 set_current_blocked(&set);
291 current->blocked = set;
292 recalc_sigpending();
293 spin_unlock_irq(&current->sighand->siglock);
294 return; 277 return;
295 278
296segv: 279segv:
@@ -300,7 +283,9 @@ segv:
300asmlinkage void do_rt_sigreturn32(struct pt_regs *regs) 283asmlinkage void do_rt_sigreturn32(struct pt_regs *regs)
301{ 284{
302 struct rt_signal_frame32 __user *sf; 285 struct rt_signal_frame32 __user *sf;
303 unsigned int psr, pc, npc, fpu_save, u_ss_sp; 286 unsigned int psr, pc, npc, u_ss_sp;
287 compat_uptr_t fpu_save;
288 compat_uptr_t rwin_save;
304 mm_segment_t old_fs; 289 mm_segment_t old_fs;
305 sigset_t set; 290 sigset_t set;
306 compat_sigset_t seta; 291 compat_sigset_t seta;
@@ -359,8 +344,8 @@ asmlinkage void do_rt_sigreturn32(struct pt_regs *regs)
359 pt_regs_clear_syscall(regs); 344 pt_regs_clear_syscall(regs);
360 345
361 err |= __get_user(fpu_save, &sf->fpu_save); 346 err |= __get_user(fpu_save, &sf->fpu_save);
362 if (fpu_save) 347 if (!err && fpu_save)
363 err |= restore_fpu_state32(regs, &sf->fpu_state); 348 err |= restore_fpu_state(regs, compat_ptr(fpu_save));
364 err |= copy_from_user(&seta, &sf->mask, sizeof(compat_sigset_t)); 349 err |= copy_from_user(&seta, &sf->mask, sizeof(compat_sigset_t));
365 err |= __get_user(u_ss_sp, &sf->stack.ss_sp); 350 err |= __get_user(u_ss_sp, &sf->stack.ss_sp);
366 st.ss_sp = compat_ptr(u_ss_sp); 351 st.ss_sp = compat_ptr(u_ss_sp);
@@ -376,6 +361,12 @@ asmlinkage void do_rt_sigreturn32(struct pt_regs *regs)
376 do_sigaltstack((stack_t __user *) &st, NULL, (unsigned long)sf); 361 do_sigaltstack((stack_t __user *) &st, NULL, (unsigned long)sf);
377 set_fs(old_fs); 362 set_fs(old_fs);
378 363
364 err |= __get_user(rwin_save, &sf->rwin_save);
365 if (!err && rwin_save) {
366 if (restore_rwin_state(compat_ptr(rwin_save)))
367 goto segv;
368 }
369
379 switch (_NSIG_WORDS) { 370 switch (_NSIG_WORDS) {
380 case 4: set.sig[3] = seta.sig[6] + (((long)seta.sig[7]) << 32); 371 case 4: set.sig[3] = seta.sig[6] + (((long)seta.sig[7]) << 32);
381 case 3: set.sig[2] = seta.sig[4] + (((long)seta.sig[5]) << 32); 372 case 3: set.sig[2] = seta.sig[4] + (((long)seta.sig[5]) << 32);
@@ -383,10 +374,7 @@ asmlinkage void do_rt_sigreturn32(struct pt_regs *regs)
383 case 1: set.sig[0] = seta.sig[0] + (((long)seta.sig[1]) << 32); 374 case 1: set.sig[0] = seta.sig[0] + (((long)seta.sig[1]) << 32);
384 } 375 }
385 sigdelsetmask(&set, ~_BLOCKABLE); 376 sigdelsetmask(&set, ~_BLOCKABLE);
386 spin_lock_irq(&current->sighand->siglock); 377 set_current_blocked(&set);
387 current->blocked = set;
388 recalc_sigpending();
389 spin_unlock_irq(&current->sighand->siglock);
390 return; 378 return;
391segv: 379segv:
392 force_sig(SIGSEGV, current); 380 force_sig(SIGSEGV, current);
@@ -433,26 +421,6 @@ static void __user *get_sigframe(struct sigaction *sa, struct pt_regs *regs, uns
433 return (void __user *) sp; 421 return (void __user *) sp;
434} 422}
435 423
436static int save_fpu_state32(struct pt_regs *regs, __siginfo_fpu_t __user *fpu)
437{
438 unsigned long *fpregs = current_thread_info()->fpregs;
439 unsigned long fprs;
440 int err = 0;
441
442 fprs = current_thread_info()->fpsaved[0];
443 if (fprs & FPRS_DL)
444 err |= copy_to_user(&fpu->si_float_regs[0], fpregs,
445 (sizeof(unsigned int) * 32));
446 if (fprs & FPRS_DU)
447 err |= copy_to_user(&fpu->si_float_regs[32], fpregs+16,
448 (sizeof(unsigned int) * 32));
449 err |= __put_user(current_thread_info()->xfsr[0], &fpu->si_fsr);
450 err |= __put_user(current_thread_info()->gsr[0], &fpu->si_gsr);
451 err |= __put_user(fprs, &fpu->si_fprs);
452
453 return err;
454}
455
456/* The I-cache flush instruction only works in the primary ASI, which 424/* The I-cache flush instruction only works in the primary ASI, which
457 * right now is the nucleus, aka. kernel space. 425 * right now is the nucleus, aka. kernel space.
458 * 426 *
@@ -515,18 +483,23 @@ static int setup_frame32(struct k_sigaction *ka, struct pt_regs *regs,
515 int signo, sigset_t *oldset) 483 int signo, sigset_t *oldset)
516{ 484{
517 struct signal_frame32 __user *sf; 485 struct signal_frame32 __user *sf;
486 int i, err, wsaved;
487 void __user *tail;
518 int sigframe_size; 488 int sigframe_size;
519 u32 psr; 489 u32 psr;
520 int i, err;
521 unsigned int seta[_COMPAT_NSIG_WORDS]; 490 unsigned int seta[_COMPAT_NSIG_WORDS];
522 491
523 /* 1. Make sure everything is clean */ 492 /* 1. Make sure everything is clean */
524 synchronize_user_stack(); 493 synchronize_user_stack();
525 save_and_clear_fpu(); 494 save_and_clear_fpu();
526 495
527 sigframe_size = SF_ALIGNEDSZ; 496 wsaved = get_thread_wsaved();
528 if (!(current_thread_info()->fpsaved[0] & FPRS_FEF)) 497
529 sigframe_size -= sizeof(__siginfo_fpu_t); 498 sigframe_size = sizeof(*sf);
499 if (current_thread_info()->fpsaved[0] & FPRS_FEF)
500 sigframe_size += sizeof(__siginfo_fpu_t);
501 if (wsaved)
502 sigframe_size += sizeof(__siginfo_rwin_t);
530 503
531 sf = (struct signal_frame32 __user *) 504 sf = (struct signal_frame32 __user *)
532 get_sigframe(&ka->sa, regs, sigframe_size); 505 get_sigframe(&ka->sa, regs, sigframe_size);
@@ -534,8 +507,7 @@ static int setup_frame32(struct k_sigaction *ka, struct pt_regs *regs,
534 if (invalid_frame_pointer(sf, sigframe_size)) 507 if (invalid_frame_pointer(sf, sigframe_size))
535 goto sigill; 508 goto sigill;
536 509
537 if (get_thread_wsaved() != 0) 510 tail = (sf + 1);
538 goto sigill;
539 511
540 /* 2. Save the current process state */ 512 /* 2. Save the current process state */
541 if (test_thread_flag(TIF_32BIT)) { 513 if (test_thread_flag(TIF_32BIT)) {
@@ -560,11 +532,22 @@ static int setup_frame32(struct k_sigaction *ka, struct pt_regs *regs,
560 &sf->v8plus.asi); 532 &sf->v8plus.asi);
561 533
562 if (psr & PSR_EF) { 534 if (psr & PSR_EF) {
563 err |= save_fpu_state32(regs, &sf->fpu_state); 535 __siginfo_fpu_t __user *fp = tail;
564 err |= __put_user((u64)&sf->fpu_state, &sf->fpu_save); 536 tail += sizeof(*fp);
537 err |= save_fpu_state(regs, fp);
538 err |= __put_user((u64)fp, &sf->fpu_save);
565 } else { 539 } else {
566 err |= __put_user(0, &sf->fpu_save); 540 err |= __put_user(0, &sf->fpu_save);
567 } 541 }
542 if (wsaved) {
543 __siginfo_rwin_t __user *rwp = tail;
544 tail += sizeof(*rwp);
545 err |= save_rwin_state(wsaved, rwp);
546 err |= __put_user((u64)rwp, &sf->rwin_save);
547 set_thread_wsaved(0);
548 } else {
549 err |= __put_user(0, &sf->rwin_save);
550 }
568 551
569 switch (_NSIG_WORDS) { 552 switch (_NSIG_WORDS) {
570 case 4: seta[7] = (oldset->sig[3] >> 32); 553 case 4: seta[7] = (oldset->sig[3] >> 32);
@@ -580,10 +563,21 @@ static int setup_frame32(struct k_sigaction *ka, struct pt_regs *regs,
580 err |= __copy_to_user(sf->extramask, seta + 1, 563 err |= __copy_to_user(sf->extramask, seta + 1,
581 (_COMPAT_NSIG_WORDS - 1) * sizeof(unsigned int)); 564 (_COMPAT_NSIG_WORDS - 1) * sizeof(unsigned int));
582 565
583 err |= copy_in_user((u32 __user *)sf, 566 if (!wsaved) {
584 (u32 __user *)(regs->u_regs[UREG_FP]), 567 err |= copy_in_user((u32 __user *)sf,
585 sizeof(struct reg_window32)); 568 (u32 __user *)(regs->u_regs[UREG_FP]),
586 569 sizeof(struct reg_window32));
570 } else {
571 struct reg_window *rp;
572
573 rp = &current_thread_info()->reg_window[wsaved - 1];
574 for (i = 0; i < 8; i++)
575 err |= __put_user(rp->locals[i], &sf->ss.locals[i]);
576 for (i = 0; i < 6; i++)
577 err |= __put_user(rp->ins[i], &sf->ss.ins[i]);
578 err |= __put_user(rp->ins[6], &sf->ss.fp);
579 err |= __put_user(rp->ins[7], &sf->ss.callers_pc);
580 }
587 if (err) 581 if (err)
588 goto sigsegv; 582 goto sigsegv;
589 583
@@ -613,7 +607,6 @@ static int setup_frame32(struct k_sigaction *ka, struct pt_regs *regs,
613 err |= __put_user(0x91d02010, &sf->insns[1]); /*t 0x10*/ 607 err |= __put_user(0x91d02010, &sf->insns[1]); /*t 0x10*/
614 if (err) 608 if (err)
615 goto sigsegv; 609 goto sigsegv;
616
617 flush_signal_insns(address); 610 flush_signal_insns(address);
618 } 611 }
619 return 0; 612 return 0;
@@ -632,18 +625,23 @@ static int setup_rt_frame32(struct k_sigaction *ka, struct pt_regs *regs,
632 siginfo_t *info) 625 siginfo_t *info)
633{ 626{
634 struct rt_signal_frame32 __user *sf; 627 struct rt_signal_frame32 __user *sf;
628 int i, err, wsaved;
629 void __user *tail;
635 int sigframe_size; 630 int sigframe_size;
636 u32 psr; 631 u32 psr;
637 int i, err;
638 compat_sigset_t seta; 632 compat_sigset_t seta;
639 633
640 /* 1. Make sure everything is clean */ 634 /* 1. Make sure everything is clean */
641 synchronize_user_stack(); 635 synchronize_user_stack();
642 save_and_clear_fpu(); 636 save_and_clear_fpu();
643 637
644 sigframe_size = RT_ALIGNEDSZ; 638 wsaved = get_thread_wsaved();
645 if (!(current_thread_info()->fpsaved[0] & FPRS_FEF)) 639
646 sigframe_size -= sizeof(__siginfo_fpu_t); 640 sigframe_size = sizeof(*sf);
641 if (current_thread_info()->fpsaved[0] & FPRS_FEF)
642 sigframe_size += sizeof(__siginfo_fpu_t);
643 if (wsaved)
644 sigframe_size += sizeof(__siginfo_rwin_t);
647 645
648 sf = (struct rt_signal_frame32 __user *) 646 sf = (struct rt_signal_frame32 __user *)
649 get_sigframe(&ka->sa, regs, sigframe_size); 647 get_sigframe(&ka->sa, regs, sigframe_size);
@@ -651,8 +649,7 @@ static int setup_rt_frame32(struct k_sigaction *ka, struct pt_regs *regs,
651 if (invalid_frame_pointer(sf, sigframe_size)) 649 if (invalid_frame_pointer(sf, sigframe_size))
652 goto sigill; 650 goto sigill;
653 651
654 if (get_thread_wsaved() != 0) 652 tail = (sf + 1);
655 goto sigill;
656 653
657 /* 2. Save the current process state */ 654 /* 2. Save the current process state */
658 if (test_thread_flag(TIF_32BIT)) { 655 if (test_thread_flag(TIF_32BIT)) {
@@ -677,11 +674,22 @@ static int setup_rt_frame32(struct k_sigaction *ka, struct pt_regs *regs,
677 &sf->v8plus.asi); 674 &sf->v8plus.asi);
678 675
679 if (psr & PSR_EF) { 676 if (psr & PSR_EF) {
680 err |= save_fpu_state32(regs, &sf->fpu_state); 677 __siginfo_fpu_t __user *fp = tail;
681 err |= __put_user((u64)&sf->fpu_state, &sf->fpu_save); 678 tail += sizeof(*fp);
679 err |= save_fpu_state(regs, fp);
680 err |= __put_user((u64)fp, &sf->fpu_save);
682 } else { 681 } else {
683 err |= __put_user(0, &sf->fpu_save); 682 err |= __put_user(0, &sf->fpu_save);
684 } 683 }
684 if (wsaved) {
685 __siginfo_rwin_t __user *rwp = tail;
686 tail += sizeof(*rwp);
687 err |= save_rwin_state(wsaved, rwp);
688 err |= __put_user((u64)rwp, &sf->rwin_save);
689 set_thread_wsaved(0);
690 } else {
691 err |= __put_user(0, &sf->rwin_save);
692 }
685 693
686 /* Update the siginfo structure. */ 694 /* Update the siginfo structure. */
687 err |= copy_siginfo_to_user32(&sf->info, info); 695 err |= copy_siginfo_to_user32(&sf->info, info);
@@ -703,9 +711,21 @@ static int setup_rt_frame32(struct k_sigaction *ka, struct pt_regs *regs,
703 } 711 }
704 err |= __copy_to_user(&sf->mask, &seta, sizeof(compat_sigset_t)); 712 err |= __copy_to_user(&sf->mask, &seta, sizeof(compat_sigset_t));
705 713
706 err |= copy_in_user((u32 __user *)sf, 714 if (!wsaved) {
707 (u32 __user *)(regs->u_regs[UREG_FP]), 715 err |= copy_in_user((u32 __user *)sf,
708 sizeof(struct reg_window32)); 716 (u32 __user *)(regs->u_regs[UREG_FP]),
717 sizeof(struct reg_window32));
718 } else {
719 struct reg_window *rp;
720
721 rp = &current_thread_info()->reg_window[wsaved - 1];
722 for (i = 0; i < 8; i++)
723 err |= __put_user(rp->locals[i], &sf->ss.locals[i]);
724 for (i = 0; i < 6; i++)
725 err |= __put_user(rp->ins[i], &sf->ss.ins[i]);
726 err |= __put_user(rp->ins[6], &sf->ss.fp);
727 err |= __put_user(rp->ins[7], &sf->ss.callers_pc);
728 }
709 if (err) 729 if (err)
710 goto sigsegv; 730 goto sigsegv;
711 731
@@ -756,6 +776,7 @@ static inline int handle_signal32(unsigned long signr, struct k_sigaction *ka,
756 siginfo_t *info, 776 siginfo_t *info,
757 sigset_t *oldset, struct pt_regs *regs) 777 sigset_t *oldset, struct pt_regs *regs)
758{ 778{
779 sigset_t blocked;
759 int err; 780 int err;
760 781
761 if (ka->sa.sa_flags & SA_SIGINFO) 782 if (ka->sa.sa_flags & SA_SIGINFO)
@@ -766,12 +787,10 @@ static inline int handle_signal32(unsigned long signr, struct k_sigaction *ka,
766 if (err) 787 if (err)
767 return err; 788 return err;
768 789
769 spin_lock_irq(&current->sighand->siglock); 790 sigorsets(&blocked, &current->blocked, &ka->sa.sa_mask);
770 sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
771 if (!(ka->sa.sa_flags & SA_NOMASK)) 791 if (!(ka->sa.sa_flags & SA_NOMASK))
772 sigaddset(&current->blocked,signr); 792 sigaddset(&blocked, signr);
773 recalc_sigpending(); 793 set_current_blocked(&blocked);
774 spin_unlock_irq(&current->sighand->siglock);
775 794
776 tracehook_signal_handler(signr, info, ka, regs, 0); 795 tracehook_signal_handler(signr, info, ka, regs, 0);
777 796
@@ -855,7 +874,7 @@ void do_signal32(sigset_t *oldset, struct pt_regs * regs,
855 */ 874 */
856 if (current_thread_info()->status & TS_RESTORE_SIGMASK) { 875 if (current_thread_info()->status & TS_RESTORE_SIGMASK) {
857 current_thread_info()->status &= ~TS_RESTORE_SIGMASK; 876 current_thread_info()->status &= ~TS_RESTORE_SIGMASK;
858 sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL); 877 set_current_blocked(&current->saved_sigmask);
859 } 878 }
860} 879}
861 880
diff --git a/arch/sparc/kernel/signal_32.c b/arch/sparc/kernel/signal_32.c
index 5e5c5fd03783..8ce247ac04cc 100644
--- a/arch/sparc/kernel/signal_32.c
+++ b/arch/sparc/kernel/signal_32.c
@@ -26,6 +26,8 @@
26#include <asm/pgtable.h> 26#include <asm/pgtable.h>
27#include <asm/cacheflush.h> /* flush_sig_insns */ 27#include <asm/cacheflush.h> /* flush_sig_insns */
28 28
29#include "sigutil.h"
30
29#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) 31#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
30 32
31extern void fpsave(unsigned long *fpregs, unsigned long *fsr, 33extern void fpsave(unsigned long *fpregs, unsigned long *fsr,
@@ -39,8 +41,8 @@ struct signal_frame {
39 unsigned long insns[2] __attribute__ ((aligned (8))); 41 unsigned long insns[2] __attribute__ ((aligned (8)));
40 unsigned int extramask[_NSIG_WORDS - 1]; 42 unsigned int extramask[_NSIG_WORDS - 1];
41 unsigned int extra_size; /* Should be 0 */ 43 unsigned int extra_size; /* Should be 0 */
42 __siginfo_fpu_t fpu_state; 44 __siginfo_rwin_t __user *rwin_save;
43}; 45} __attribute__((aligned(8)));
44 46
45struct rt_signal_frame { 47struct rt_signal_frame {
46 struct sparc_stackf ss; 48 struct sparc_stackf ss;
@@ -51,8 +53,8 @@ struct rt_signal_frame {
51 unsigned int insns[2]; 53 unsigned int insns[2];
52 stack_t stack; 54 stack_t stack;
53 unsigned int extra_size; /* Should be 0 */ 55 unsigned int extra_size; /* Should be 0 */
54 __siginfo_fpu_t fpu_state; 56 __siginfo_rwin_t __user *rwin_save;
55}; 57} __attribute__((aligned(8)));
56 58
57/* Align macros */ 59/* Align macros */
58#define SF_ALIGNEDSZ (((sizeof(struct signal_frame) + 7) & (~7))) 60#define SF_ALIGNEDSZ (((sizeof(struct signal_frame) + 7) & (~7)))
@@ -60,12 +62,13 @@ struct rt_signal_frame {
60 62
61static int _sigpause_common(old_sigset_t set) 63static int _sigpause_common(old_sigset_t set)
62{ 64{
63 set &= _BLOCKABLE; 65 sigset_t blocked;
64 spin_lock_irq(&current->sighand->siglock); 66
65 current->saved_sigmask = current->blocked; 67 current->saved_sigmask = current->blocked;
66 siginitset(&current->blocked, set); 68
67 recalc_sigpending(); 69 set &= _BLOCKABLE;
68 spin_unlock_irq(&current->sighand->siglock); 70 siginitset(&blocked, set);
71 set_current_blocked(&blocked);
69 72
70 current->state = TASK_INTERRUPTIBLE; 73 current->state = TASK_INTERRUPTIBLE;
71 schedule(); 74 schedule();
@@ -79,43 +82,13 @@ asmlinkage int sys_sigsuspend(old_sigset_t set)
79 return _sigpause_common(set); 82 return _sigpause_common(set);
80} 83}
81 84
82static inline int
83restore_fpu_state(struct pt_regs *regs, __siginfo_fpu_t __user *fpu)
84{
85 int err;
86#ifdef CONFIG_SMP
87 if (test_tsk_thread_flag(current, TIF_USEDFPU))
88 regs->psr &= ~PSR_EF;
89#else
90 if (current == last_task_used_math) {
91 last_task_used_math = NULL;
92 regs->psr &= ~PSR_EF;
93 }
94#endif
95 set_used_math();
96 clear_tsk_thread_flag(current, TIF_USEDFPU);
97
98 if (!access_ok(VERIFY_READ, fpu, sizeof(*fpu)))
99 return -EFAULT;
100
101 err = __copy_from_user(&current->thread.float_regs[0], &fpu->si_float_regs[0],
102 (sizeof(unsigned long) * 32));
103 err |= __get_user(current->thread.fsr, &fpu->si_fsr);
104 err |= __get_user(current->thread.fpqdepth, &fpu->si_fpqdepth);
105 if (current->thread.fpqdepth != 0)
106 err |= __copy_from_user(&current->thread.fpqueue[0],
107 &fpu->si_fpqueue[0],
108 ((sizeof(unsigned long) +
109 (sizeof(unsigned long *)))*16));
110 return err;
111}
112
113asmlinkage void do_sigreturn(struct pt_regs *regs) 85asmlinkage void do_sigreturn(struct pt_regs *regs)
114{ 86{
115 struct signal_frame __user *sf; 87 struct signal_frame __user *sf;
116 unsigned long up_psr, pc, npc; 88 unsigned long up_psr, pc, npc;
117 sigset_t set; 89 sigset_t set;
118 __siginfo_fpu_t __user *fpu_save; 90 __siginfo_fpu_t __user *fpu_save;
91 __siginfo_rwin_t __user *rwin_save;
119 int err; 92 int err;
120 93
121 /* Always make any pending restarted system calls return -EINTR */ 94 /* Always make any pending restarted system calls return -EINTR */
@@ -150,9 +123,11 @@ asmlinkage void do_sigreturn(struct pt_regs *regs)
150 pt_regs_clear_syscall(regs); 123 pt_regs_clear_syscall(regs);
151 124
152 err |= __get_user(fpu_save, &sf->fpu_save); 125 err |= __get_user(fpu_save, &sf->fpu_save);
153
154 if (fpu_save) 126 if (fpu_save)
155 err |= restore_fpu_state(regs, fpu_save); 127 err |= restore_fpu_state(regs, fpu_save);
128 err |= __get_user(rwin_save, &sf->rwin_save);
129 if (rwin_save)
130 err |= restore_rwin_state(rwin_save);
156 131
157 /* This is pretty much atomic, no amount locking would prevent 132 /* This is pretty much atomic, no amount locking would prevent
158 * the races which exist anyways. 133 * the races which exist anyways.
@@ -165,10 +140,7 @@ asmlinkage void do_sigreturn(struct pt_regs *regs)
165 goto segv_and_exit; 140 goto segv_and_exit;
166 141
167 sigdelsetmask(&set, ~_BLOCKABLE); 142 sigdelsetmask(&set, ~_BLOCKABLE);
168 spin_lock_irq(&current->sighand->siglock); 143 set_current_blocked(&set);
169 current->blocked = set;
170 recalc_sigpending();
171 spin_unlock_irq(&current->sighand->siglock);
172 return; 144 return;
173 145
174segv_and_exit: 146segv_and_exit:
@@ -180,6 +152,7 @@ asmlinkage void do_rt_sigreturn(struct pt_regs *regs)
180 struct rt_signal_frame __user *sf; 152 struct rt_signal_frame __user *sf;
181 unsigned int psr, pc, npc; 153 unsigned int psr, pc, npc;
182 __siginfo_fpu_t __user *fpu_save; 154 __siginfo_fpu_t __user *fpu_save;
155 __siginfo_rwin_t __user *rwin_save;
183 mm_segment_t old_fs; 156 mm_segment_t old_fs;
184 sigset_t set; 157 sigset_t set;
185 stack_t st; 158 stack_t st;
@@ -207,8 +180,7 @@ asmlinkage void do_rt_sigreturn(struct pt_regs *regs)
207 pt_regs_clear_syscall(regs); 180 pt_regs_clear_syscall(regs);
208 181
209 err |= __get_user(fpu_save, &sf->fpu_save); 182 err |= __get_user(fpu_save, &sf->fpu_save);
210 183 if (!err && fpu_save)
211 if (fpu_save)
212 err |= restore_fpu_state(regs, fpu_save); 184 err |= restore_fpu_state(regs, fpu_save);
213 err |= __copy_from_user(&set, &sf->mask, sizeof(sigset_t)); 185 err |= __copy_from_user(&set, &sf->mask, sizeof(sigset_t));
214 186
@@ -228,11 +200,14 @@ asmlinkage void do_rt_sigreturn(struct pt_regs *regs)
228 do_sigaltstack((const stack_t __user *) &st, NULL, (unsigned long)sf); 200 do_sigaltstack((const stack_t __user *) &st, NULL, (unsigned long)sf);
229 set_fs(old_fs); 201 set_fs(old_fs);
230 202
203 err |= __get_user(rwin_save, &sf->rwin_save);
204 if (!err && rwin_save) {
205 if (restore_rwin_state(rwin_save))
206 goto segv;
207 }
208
231 sigdelsetmask(&set, ~_BLOCKABLE); 209 sigdelsetmask(&set, ~_BLOCKABLE);
232 spin_lock_irq(&current->sighand->siglock); 210 set_current_blocked(&set);
233 current->blocked = set;
234 recalc_sigpending();
235 spin_unlock_irq(&current->sighand->siglock);
236 return; 211 return;
237segv: 212segv:
238 force_sig(SIGSEGV, current); 213 force_sig(SIGSEGV, current);
@@ -280,53 +255,23 @@ static inline void __user *get_sigframe(struct sigaction *sa, struct pt_regs *re
280 return (void __user *) sp; 255 return (void __user *) sp;
281} 256}
282 257
283static inline int
284save_fpu_state(struct pt_regs *regs, __siginfo_fpu_t __user *fpu)
285{
286 int err = 0;
287#ifdef CONFIG_SMP
288 if (test_tsk_thread_flag(current, TIF_USEDFPU)) {
289 put_psr(get_psr() | PSR_EF);
290 fpsave(&current->thread.float_regs[0], &current->thread.fsr,
291 &current->thread.fpqueue[0], &current->thread.fpqdepth);
292 regs->psr &= ~(PSR_EF);
293 clear_tsk_thread_flag(current, TIF_USEDFPU);
294 }
295#else
296 if (current == last_task_used_math) {
297 put_psr(get_psr() | PSR_EF);
298 fpsave(&current->thread.float_regs[0], &current->thread.fsr,
299 &current->thread.fpqueue[0], &current->thread.fpqdepth);
300 last_task_used_math = NULL;
301 regs->psr &= ~(PSR_EF);
302 }
303#endif
304 err |= __copy_to_user(&fpu->si_float_regs[0],
305 &current->thread.float_regs[0],
306 (sizeof(unsigned long) * 32));
307 err |= __put_user(current->thread.fsr, &fpu->si_fsr);
308 err |= __put_user(current->thread.fpqdepth, &fpu->si_fpqdepth);
309 if (current->thread.fpqdepth != 0)
310 err |= __copy_to_user(&fpu->si_fpqueue[0],
311 &current->thread.fpqueue[0],
312 ((sizeof(unsigned long) +
313 (sizeof(unsigned long *)))*16));
314 clear_used_math();
315 return err;
316}
317
318static int setup_frame(struct k_sigaction *ka, struct pt_regs *regs, 258static int setup_frame(struct k_sigaction *ka, struct pt_regs *regs,
319 int signo, sigset_t *oldset) 259 int signo, sigset_t *oldset)
320{ 260{
321 struct signal_frame __user *sf; 261 struct signal_frame __user *sf;
322 int sigframe_size, err; 262 int sigframe_size, err, wsaved;
263 void __user *tail;
323 264
324 /* 1. Make sure everything is clean */ 265 /* 1. Make sure everything is clean */
325 synchronize_user_stack(); 266 synchronize_user_stack();
326 267
327 sigframe_size = SF_ALIGNEDSZ; 268 wsaved = current_thread_info()->w_saved;
328 if (!used_math()) 269
329 sigframe_size -= sizeof(__siginfo_fpu_t); 270 sigframe_size = sizeof(*sf);
271 if (used_math())
272 sigframe_size += sizeof(__siginfo_fpu_t);
273 if (wsaved)
274 sigframe_size += sizeof(__siginfo_rwin_t);
330 275
331 sf = (struct signal_frame __user *) 276 sf = (struct signal_frame __user *)
332 get_sigframe(&ka->sa, regs, sigframe_size); 277 get_sigframe(&ka->sa, regs, sigframe_size);
@@ -334,8 +279,7 @@ static int setup_frame(struct k_sigaction *ka, struct pt_regs *regs,
334 if (invalid_frame_pointer(sf, sigframe_size)) 279 if (invalid_frame_pointer(sf, sigframe_size))
335 goto sigill_and_return; 280 goto sigill_and_return;
336 281
337 if (current_thread_info()->w_saved != 0) 282 tail = sf + 1;
338 goto sigill_and_return;
339 283
340 /* 2. Save the current process state */ 284 /* 2. Save the current process state */
341 err = __copy_to_user(&sf->info.si_regs, regs, sizeof(struct pt_regs)); 285 err = __copy_to_user(&sf->info.si_regs, regs, sizeof(struct pt_regs));
@@ -343,17 +287,34 @@ static int setup_frame(struct k_sigaction *ka, struct pt_regs *regs,
343 err |= __put_user(0, &sf->extra_size); 287 err |= __put_user(0, &sf->extra_size);
344 288
345 if (used_math()) { 289 if (used_math()) {
346 err |= save_fpu_state(regs, &sf->fpu_state); 290 __siginfo_fpu_t __user *fp = tail;
347 err |= __put_user(&sf->fpu_state, &sf->fpu_save); 291 tail += sizeof(*fp);
292 err |= save_fpu_state(regs, fp);
293 err |= __put_user(fp, &sf->fpu_save);
348 } else { 294 } else {
349 err |= __put_user(0, &sf->fpu_save); 295 err |= __put_user(0, &sf->fpu_save);
350 } 296 }
297 if (wsaved) {
298 __siginfo_rwin_t __user *rwp = tail;
299 tail += sizeof(*rwp);
300 err |= save_rwin_state(wsaved, rwp);
301 err |= __put_user(rwp, &sf->rwin_save);
302 } else {
303 err |= __put_user(0, &sf->rwin_save);
304 }
351 305
352 err |= __put_user(oldset->sig[0], &sf->info.si_mask); 306 err |= __put_user(oldset->sig[0], &sf->info.si_mask);
353 err |= __copy_to_user(sf->extramask, &oldset->sig[1], 307 err |= __copy_to_user(sf->extramask, &oldset->sig[1],
354 (_NSIG_WORDS - 1) * sizeof(unsigned int)); 308 (_NSIG_WORDS - 1) * sizeof(unsigned int));
355 err |= __copy_to_user(sf, (char *) regs->u_regs[UREG_FP], 309 if (!wsaved) {
356 sizeof(struct reg_window32)); 310 err |= __copy_to_user(sf, (char *) regs->u_regs[UREG_FP],
311 sizeof(struct reg_window32));
312 } else {
313 struct reg_window32 *rp;
314
315 rp = &current_thread_info()->reg_window[wsaved - 1];
316 err |= __copy_to_user(sf, rp, sizeof(struct reg_window32));
317 }
357 if (err) 318 if (err)
358 goto sigsegv; 319 goto sigsegv;
359 320
@@ -399,21 +360,24 @@ static int setup_rt_frame(struct k_sigaction *ka, struct pt_regs *regs,
399 int signo, sigset_t *oldset, siginfo_t *info) 360 int signo, sigset_t *oldset, siginfo_t *info)
400{ 361{
401 struct rt_signal_frame __user *sf; 362 struct rt_signal_frame __user *sf;
402 int sigframe_size; 363 int sigframe_size, wsaved;
364 void __user *tail;
403 unsigned int psr; 365 unsigned int psr;
404 int err; 366 int err;
405 367
406 synchronize_user_stack(); 368 synchronize_user_stack();
407 sigframe_size = RT_ALIGNEDSZ; 369 wsaved = current_thread_info()->w_saved;
408 if (!used_math()) 370 sigframe_size = sizeof(*sf);
409 sigframe_size -= sizeof(__siginfo_fpu_t); 371 if (used_math())
372 sigframe_size += sizeof(__siginfo_fpu_t);
373 if (wsaved)
374 sigframe_size += sizeof(__siginfo_rwin_t);
410 sf = (struct rt_signal_frame __user *) 375 sf = (struct rt_signal_frame __user *)
411 get_sigframe(&ka->sa, regs, sigframe_size); 376 get_sigframe(&ka->sa, regs, sigframe_size);
412 if (invalid_frame_pointer(sf, sigframe_size)) 377 if (invalid_frame_pointer(sf, sigframe_size))
413 goto sigill; 378 goto sigill;
414 if (current_thread_info()->w_saved != 0)
415 goto sigill;
416 379
380 tail = sf + 1;
417 err = __put_user(regs->pc, &sf->regs.pc); 381 err = __put_user(regs->pc, &sf->regs.pc);
418 err |= __put_user(regs->npc, &sf->regs.npc); 382 err |= __put_user(regs->npc, &sf->regs.npc);
419 err |= __put_user(regs->y, &sf->regs.y); 383 err |= __put_user(regs->y, &sf->regs.y);
@@ -425,11 +389,21 @@ static int setup_rt_frame(struct k_sigaction *ka, struct pt_regs *regs,
425 err |= __put_user(0, &sf->extra_size); 389 err |= __put_user(0, &sf->extra_size);
426 390
427 if (psr & PSR_EF) { 391 if (psr & PSR_EF) {
428 err |= save_fpu_state(regs, &sf->fpu_state); 392 __siginfo_fpu_t *fp = tail;
429 err |= __put_user(&sf->fpu_state, &sf->fpu_save); 393 tail += sizeof(*fp);
394 err |= save_fpu_state(regs, fp);
395 err |= __put_user(fp, &sf->fpu_save);
430 } else { 396 } else {
431 err |= __put_user(0, &sf->fpu_save); 397 err |= __put_user(0, &sf->fpu_save);
432 } 398 }
399 if (wsaved) {
400 __siginfo_rwin_t *rwp = tail;
401 tail += sizeof(*rwp);
402 err |= save_rwin_state(wsaved, rwp);
403 err |= __put_user(rwp, &sf->rwin_save);
404 } else {
405 err |= __put_user(0, &sf->rwin_save);
406 }
433 err |= __copy_to_user(&sf->mask, &oldset->sig[0], sizeof(sigset_t)); 407 err |= __copy_to_user(&sf->mask, &oldset->sig[0], sizeof(sigset_t));
434 408
435 /* Setup sigaltstack */ 409 /* Setup sigaltstack */
@@ -437,8 +411,15 @@ static int setup_rt_frame(struct k_sigaction *ka, struct pt_regs *regs,
437 err |= __put_user(sas_ss_flags(regs->u_regs[UREG_FP]), &sf->stack.ss_flags); 411 err |= __put_user(sas_ss_flags(regs->u_regs[UREG_FP]), &sf->stack.ss_flags);
438 err |= __put_user(current->sas_ss_size, &sf->stack.ss_size); 412 err |= __put_user(current->sas_ss_size, &sf->stack.ss_size);
439 413
440 err |= __copy_to_user(sf, (char *) regs->u_regs[UREG_FP], 414 if (!wsaved) {
441 sizeof(struct reg_window32)); 415 err |= __copy_to_user(sf, (char *) regs->u_regs[UREG_FP],
416 sizeof(struct reg_window32));
417 } else {
418 struct reg_window32 *rp;
419
420 rp = &current_thread_info()->reg_window[wsaved - 1];
421 err |= __copy_to_user(sf, rp, sizeof(struct reg_window32));
422 }
442 423
443 err |= copy_siginfo_to_user(&sf->info, info); 424 err |= copy_siginfo_to_user(&sf->info, info);
444 425
@@ -484,6 +465,7 @@ static inline int
484handle_signal(unsigned long signr, struct k_sigaction *ka, 465handle_signal(unsigned long signr, struct k_sigaction *ka,
485 siginfo_t *info, sigset_t *oldset, struct pt_regs *regs) 466 siginfo_t *info, sigset_t *oldset, struct pt_regs *regs)
486{ 467{
468 sigset_t blocked;
487 int err; 469 int err;
488 470
489 if (ka->sa.sa_flags & SA_SIGINFO) 471 if (ka->sa.sa_flags & SA_SIGINFO)
@@ -494,12 +476,10 @@ handle_signal(unsigned long signr, struct k_sigaction *ka,
494 if (err) 476 if (err)
495 return err; 477 return err;
496 478
497 spin_lock_irq(&current->sighand->siglock); 479 sigorsets(&blocked, &current->blocked, &ka->sa.sa_mask);
498 sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
499 if (!(ka->sa.sa_flags & SA_NOMASK)) 480 if (!(ka->sa.sa_flags & SA_NOMASK))
500 sigaddset(&current->blocked, signr); 481 sigaddset(&blocked, signr);
501 recalc_sigpending(); 482 set_current_blocked(&blocked);
502 spin_unlock_irq(&current->sighand->siglock);
503 483
504 tracehook_signal_handler(signr, info, ka, regs, 0); 484 tracehook_signal_handler(signr, info, ka, regs, 0);
505 485
@@ -595,7 +575,7 @@ static void do_signal(struct pt_regs *regs, unsigned long orig_i0)
595 */ 575 */
596 if (test_thread_flag(TIF_RESTORE_SIGMASK)) { 576 if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
597 clear_thread_flag(TIF_RESTORE_SIGMASK); 577 clear_thread_flag(TIF_RESTORE_SIGMASK);
598 sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL); 578 set_current_blocked(&current->saved_sigmask);
599 } 579 }
600} 580}
601 581
diff --git a/arch/sparc/kernel/signal_64.c b/arch/sparc/kernel/signal_64.c
index 006fe4515886..a2b81598d905 100644
--- a/arch/sparc/kernel/signal_64.c
+++ b/arch/sparc/kernel/signal_64.c
@@ -34,6 +34,7 @@
34 34
35#include "entry.h" 35#include "entry.h"
36#include "systbls.h" 36#include "systbls.h"
37#include "sigutil.h"
37 38
38#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) 39#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
39 40
@@ -69,10 +70,7 @@ asmlinkage void sparc64_set_context(struct pt_regs *regs)
69 goto do_sigsegv; 70 goto do_sigsegv;
70 } 71 }
71 sigdelsetmask(&set, ~_BLOCKABLE); 72 sigdelsetmask(&set, ~_BLOCKABLE);
72 spin_lock_irq(&current->sighand->siglock); 73 set_current_blocked(&set);
73 current->blocked = set;
74 recalc_sigpending();
75 spin_unlock_irq(&current->sighand->siglock);
76 } 74 }
77 if (test_thread_flag(TIF_32BIT)) { 75 if (test_thread_flag(TIF_32BIT)) {
78 pc &= 0xffffffff; 76 pc &= 0xffffffff;
@@ -236,17 +234,18 @@ struct rt_signal_frame {
236 __siginfo_fpu_t __user *fpu_save; 234 __siginfo_fpu_t __user *fpu_save;
237 stack_t stack; 235 stack_t stack;
238 sigset_t mask; 236 sigset_t mask;
239 __siginfo_fpu_t fpu_state; 237 __siginfo_rwin_t *rwin_save;
240}; 238};
241 239
242static long _sigpause_common(old_sigset_t set) 240static long _sigpause_common(old_sigset_t set)
243{ 241{
244 set &= _BLOCKABLE; 242 sigset_t blocked;
245 spin_lock_irq(&current->sighand->siglock); 243
246 current->saved_sigmask = current->blocked; 244 current->saved_sigmask = current->blocked;
247 siginitset(&current->blocked, set); 245
248 recalc_sigpending(); 246 set &= _BLOCKABLE;
249 spin_unlock_irq(&current->sighand->siglock); 247 siginitset(&blocked, set);
248 set_current_blocked(&blocked);
250 249
251 current->state = TASK_INTERRUPTIBLE; 250 current->state = TASK_INTERRUPTIBLE;
252 schedule(); 251 schedule();
@@ -266,33 +265,12 @@ asmlinkage long sys_sigsuspend(old_sigset_t set)
266 return _sigpause_common(set); 265 return _sigpause_common(set);
267} 266}
268 267
269static inline int
270restore_fpu_state(struct pt_regs *regs, __siginfo_fpu_t __user *fpu)
271{
272 unsigned long *fpregs = current_thread_info()->fpregs;
273 unsigned long fprs;
274 int err;
275
276 err = __get_user(fprs, &fpu->si_fprs);
277 fprs_write(0);
278 regs->tstate &= ~TSTATE_PEF;
279 if (fprs & FPRS_DL)
280 err |= copy_from_user(fpregs, &fpu->si_float_regs[0],
281 (sizeof(unsigned int) * 32));
282 if (fprs & FPRS_DU)
283 err |= copy_from_user(fpregs+16, &fpu->si_float_regs[32],
284 (sizeof(unsigned int) * 32));
285 err |= __get_user(current_thread_info()->xfsr[0], &fpu->si_fsr);
286 err |= __get_user(current_thread_info()->gsr[0], &fpu->si_gsr);
287 current_thread_info()->fpsaved[0] |= fprs;
288 return err;
289}
290
291void do_rt_sigreturn(struct pt_regs *regs) 268void do_rt_sigreturn(struct pt_regs *regs)
292{ 269{
293 struct rt_signal_frame __user *sf; 270 struct rt_signal_frame __user *sf;
294 unsigned long tpc, tnpc, tstate; 271 unsigned long tpc, tnpc, tstate;
295 __siginfo_fpu_t __user *fpu_save; 272 __siginfo_fpu_t __user *fpu_save;
273 __siginfo_rwin_t __user *rwin_save;
296 sigset_t set; 274 sigset_t set;
297 int err; 275 int err;
298 276
@@ -325,8 +303,8 @@ void do_rt_sigreturn(struct pt_regs *regs)
325 regs->tstate |= (tstate & (TSTATE_ASI | TSTATE_ICC | TSTATE_XCC)); 303 regs->tstate |= (tstate & (TSTATE_ASI | TSTATE_ICC | TSTATE_XCC));
326 304
327 err |= __get_user(fpu_save, &sf->fpu_save); 305 err |= __get_user(fpu_save, &sf->fpu_save);
328 if (fpu_save) 306 if (!err && fpu_save)
329 err |= restore_fpu_state(regs, &sf->fpu_state); 307 err |= restore_fpu_state(regs, fpu_save);
330 308
331 err |= __copy_from_user(&set, &sf->mask, sizeof(sigset_t)); 309 err |= __copy_from_user(&set, &sf->mask, sizeof(sigset_t));
332 err |= do_sigaltstack(&sf->stack, NULL, (unsigned long)sf); 310 err |= do_sigaltstack(&sf->stack, NULL, (unsigned long)sf);
@@ -334,6 +312,12 @@ void do_rt_sigreturn(struct pt_regs *regs)
334 if (err) 312 if (err)
335 goto segv; 313 goto segv;
336 314
315 err |= __get_user(rwin_save, &sf->rwin_save);
316 if (!err && rwin_save) {
317 if (restore_rwin_state(rwin_save))
318 goto segv;
319 }
320
337 regs->tpc = tpc; 321 regs->tpc = tpc;
338 regs->tnpc = tnpc; 322 regs->tnpc = tnpc;
339 323
@@ -341,44 +325,20 @@ void do_rt_sigreturn(struct pt_regs *regs)
341 pt_regs_clear_syscall(regs); 325 pt_regs_clear_syscall(regs);
342 326
343 sigdelsetmask(&set, ~_BLOCKABLE); 327 sigdelsetmask(&set, ~_BLOCKABLE);
344 spin_lock_irq(&current->sighand->siglock); 328 set_current_blocked(&set);
345 current->blocked = set;
346 recalc_sigpending();
347 spin_unlock_irq(&current->sighand->siglock);
348 return; 329 return;
349segv: 330segv:
350 force_sig(SIGSEGV, current); 331 force_sig(SIGSEGV, current);
351} 332}
352 333
353/* Checks if the fp is valid */ 334/* Checks if the fp is valid */
354static int invalid_frame_pointer(void __user *fp, int fplen) 335static int invalid_frame_pointer(void __user *fp)
355{ 336{
356 if (((unsigned long) fp) & 15) 337 if (((unsigned long) fp) & 15)
357 return 1; 338 return 1;
358 return 0; 339 return 0;
359} 340}
360 341
361static inline int
362save_fpu_state(struct pt_regs *regs, __siginfo_fpu_t __user *fpu)
363{
364 unsigned long *fpregs = current_thread_info()->fpregs;
365 unsigned long fprs;
366 int err = 0;
367
368 fprs = current_thread_info()->fpsaved[0];
369 if (fprs & FPRS_DL)
370 err |= copy_to_user(&fpu->si_float_regs[0], fpregs,
371 (sizeof(unsigned int) * 32));
372 if (fprs & FPRS_DU)
373 err |= copy_to_user(&fpu->si_float_regs[32], fpregs+16,
374 (sizeof(unsigned int) * 32));
375 err |= __put_user(current_thread_info()->xfsr[0], &fpu->si_fsr);
376 err |= __put_user(current_thread_info()->gsr[0], &fpu->si_gsr);
377 err |= __put_user(fprs, &fpu->si_fprs);
378
379 return err;
380}
381
382static inline void __user *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, unsigned long framesize) 342static inline void __user *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, unsigned long framesize)
383{ 343{
384 unsigned long sp = regs->u_regs[UREG_FP] + STACK_BIAS; 344 unsigned long sp = regs->u_regs[UREG_FP] + STACK_BIAS;
@@ -414,34 +374,48 @@ setup_rt_frame(struct k_sigaction *ka, struct pt_regs *regs,
414 int signo, sigset_t *oldset, siginfo_t *info) 374 int signo, sigset_t *oldset, siginfo_t *info)
415{ 375{
416 struct rt_signal_frame __user *sf; 376 struct rt_signal_frame __user *sf;
417 int sigframe_size, err; 377 int wsaved, err, sf_size;
378 void __user *tail;
418 379
419 /* 1. Make sure everything is clean */ 380 /* 1. Make sure everything is clean */
420 synchronize_user_stack(); 381 synchronize_user_stack();
421 save_and_clear_fpu(); 382 save_and_clear_fpu();
422 383
423 sigframe_size = sizeof(struct rt_signal_frame); 384 wsaved = get_thread_wsaved();
424 if (!(current_thread_info()->fpsaved[0] & FPRS_FEF))
425 sigframe_size -= sizeof(__siginfo_fpu_t);
426 385
386 sf_size = sizeof(struct rt_signal_frame);
387 if (current_thread_info()->fpsaved[0] & FPRS_FEF)
388 sf_size += sizeof(__siginfo_fpu_t);
389 if (wsaved)
390 sf_size += sizeof(__siginfo_rwin_t);
427 sf = (struct rt_signal_frame __user *) 391 sf = (struct rt_signal_frame __user *)
428 get_sigframe(ka, regs, sigframe_size); 392 get_sigframe(ka, regs, sf_size);
429
430 if (invalid_frame_pointer (sf, sigframe_size))
431 goto sigill;
432 393
433 if (get_thread_wsaved() != 0) 394 if (invalid_frame_pointer (sf))
434 goto sigill; 395 goto sigill;
435 396
397 tail = (sf + 1);
398
436 /* 2. Save the current process state */ 399 /* 2. Save the current process state */
437 err = copy_to_user(&sf->regs, regs, sizeof (*regs)); 400 err = copy_to_user(&sf->regs, regs, sizeof (*regs));
438 401
439 if (current_thread_info()->fpsaved[0] & FPRS_FEF) { 402 if (current_thread_info()->fpsaved[0] & FPRS_FEF) {
440 err |= save_fpu_state(regs, &sf->fpu_state); 403 __siginfo_fpu_t __user *fpu_save = tail;
441 err |= __put_user((u64)&sf->fpu_state, &sf->fpu_save); 404 tail += sizeof(__siginfo_fpu_t);
405 err |= save_fpu_state(regs, fpu_save);
406 err |= __put_user((u64)fpu_save, &sf->fpu_save);
442 } else { 407 } else {
443 err |= __put_user(0, &sf->fpu_save); 408 err |= __put_user(0, &sf->fpu_save);
444 } 409 }
410 if (wsaved) {
411 __siginfo_rwin_t __user *rwin_save = tail;
412 tail += sizeof(__siginfo_rwin_t);
413 err |= save_rwin_state(wsaved, rwin_save);
414 err |= __put_user((u64)rwin_save, &sf->rwin_save);
415 set_thread_wsaved(0);
416 } else {
417 err |= __put_user(0, &sf->rwin_save);
418 }
445 419
446 /* Setup sigaltstack */ 420 /* Setup sigaltstack */
447 err |= __put_user(current->sas_ss_sp, &sf->stack.ss_sp); 421 err |= __put_user(current->sas_ss_sp, &sf->stack.ss_sp);
@@ -450,10 +424,17 @@ setup_rt_frame(struct k_sigaction *ka, struct pt_regs *regs,
450 424
451 err |= copy_to_user(&sf->mask, oldset, sizeof(sigset_t)); 425 err |= copy_to_user(&sf->mask, oldset, sizeof(sigset_t));
452 426
453 err |= copy_in_user((u64 __user *)sf, 427 if (!wsaved) {
454 (u64 __user *)(regs->u_regs[UREG_FP]+STACK_BIAS), 428 err |= copy_in_user((u64 __user *)sf,
455 sizeof(struct reg_window)); 429 (u64 __user *)(regs->u_regs[UREG_FP] +
430 STACK_BIAS),
431 sizeof(struct reg_window));
432 } else {
433 struct reg_window *rp;
456 434
435 rp = &current_thread_info()->reg_window[wsaved - 1];
436 err |= copy_to_user(sf, rp, sizeof(struct reg_window));
437 }
457 if (info) 438 if (info)
458 err |= copy_siginfo_to_user(&sf->info, info); 439 err |= copy_siginfo_to_user(&sf->info, info);
459 else { 440 else {
@@ -498,18 +479,17 @@ static inline int handle_signal(unsigned long signr, struct k_sigaction *ka,
498 siginfo_t *info, 479 siginfo_t *info,
499 sigset_t *oldset, struct pt_regs *regs) 480 sigset_t *oldset, struct pt_regs *regs)
500{ 481{
482 sigset_t blocked;
501 int err; 483 int err;
502 484
503 err = setup_rt_frame(ka, regs, signr, oldset, 485 err = setup_rt_frame(ka, regs, signr, oldset,
504 (ka->sa.sa_flags & SA_SIGINFO) ? info : NULL); 486 (ka->sa.sa_flags & SA_SIGINFO) ? info : NULL);
505 if (err) 487 if (err)
506 return err; 488 return err;
507 spin_lock_irq(&current->sighand->siglock); 489 sigorsets(&blocked, &current->blocked, &ka->sa.sa_mask);
508 sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
509 if (!(ka->sa.sa_flags & SA_NOMASK)) 490 if (!(ka->sa.sa_flags & SA_NOMASK))
510 sigaddset(&current->blocked,signr); 491 sigaddset(&blocked, signr);
511 recalc_sigpending(); 492 set_current_blocked(&blocked);
512 spin_unlock_irq(&current->sighand->siglock);
513 493
514 tracehook_signal_handler(signr, info, ka, regs, 0); 494 tracehook_signal_handler(signr, info, ka, regs, 0);
515 495
@@ -615,7 +595,7 @@ static void do_signal(struct pt_regs *regs, unsigned long orig_i0)
615 */ 595 */
616 if (current_thread_info()->status & TS_RESTORE_SIGMASK) { 596 if (current_thread_info()->status & TS_RESTORE_SIGMASK) {
617 current_thread_info()->status &= ~TS_RESTORE_SIGMASK; 597 current_thread_info()->status &= ~TS_RESTORE_SIGMASK;
618 sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL); 598 set_current_blocked(&current->saved_sigmask);
619 } 599 }
620} 600}
621 601
diff --git a/arch/sparc/kernel/sigutil.h b/arch/sparc/kernel/sigutil.h
new file mode 100644
index 000000000000..d223aa432bb6
--- /dev/null
+++ b/arch/sparc/kernel/sigutil.h
@@ -0,0 +1,9 @@
1#ifndef _SIGUTIL_H
2#define _SIGUTIL_H
3
4int save_fpu_state(struct pt_regs *regs, __siginfo_fpu_t __user *fpu);
5int restore_fpu_state(struct pt_regs *regs, __siginfo_fpu_t __user *fpu);
6int save_rwin_state(int wsaved, __siginfo_rwin_t __user *rwin);
7int restore_rwin_state(__siginfo_rwin_t __user *rp);
8
9#endif /* _SIGUTIL_H */
diff --git a/arch/sparc/kernel/sigutil_32.c b/arch/sparc/kernel/sigutil_32.c
new file mode 100644
index 000000000000..35c7897b009a
--- /dev/null
+++ b/arch/sparc/kernel/sigutil_32.c
@@ -0,0 +1,120 @@
1#include <linux/kernel.h>
2#include <linux/types.h>
3#include <linux/thread_info.h>
4#include <linux/uaccess.h>
5#include <linux/sched.h>
6
7#include <asm/sigcontext.h>
8#include <asm/fpumacro.h>
9#include <asm/ptrace.h>
10
11#include "sigutil.h"
12
13int save_fpu_state(struct pt_regs *regs, __siginfo_fpu_t __user *fpu)
14{
15 int err = 0;
16#ifdef CONFIG_SMP
17 if (test_tsk_thread_flag(current, TIF_USEDFPU)) {
18 put_psr(get_psr() | PSR_EF);
19 fpsave(&current->thread.float_regs[0], &current->thread.fsr,
20 &current->thread.fpqueue[0], &current->thread.fpqdepth);
21 regs->psr &= ~(PSR_EF);
22 clear_tsk_thread_flag(current, TIF_USEDFPU);
23 }
24#else
25 if (current == last_task_used_math) {
26 put_psr(get_psr() | PSR_EF);
27 fpsave(&current->thread.float_regs[0], &current->thread.fsr,
28 &current->thread.fpqueue[0], &current->thread.fpqdepth);
29 last_task_used_math = NULL;
30 regs->psr &= ~(PSR_EF);
31 }
32#endif
33 err |= __copy_to_user(&fpu->si_float_regs[0],
34 &current->thread.float_regs[0],
35 (sizeof(unsigned long) * 32));
36 err |= __put_user(current->thread.fsr, &fpu->si_fsr);
37 err |= __put_user(current->thread.fpqdepth, &fpu->si_fpqdepth);
38 if (current->thread.fpqdepth != 0)
39 err |= __copy_to_user(&fpu->si_fpqueue[0],
40 &current->thread.fpqueue[0],
41 ((sizeof(unsigned long) +
42 (sizeof(unsigned long *)))*16));
43 clear_used_math();
44 return err;
45}
46
47int restore_fpu_state(struct pt_regs *regs, __siginfo_fpu_t __user *fpu)
48{
49 int err;
50#ifdef CONFIG_SMP
51 if (test_tsk_thread_flag(current, TIF_USEDFPU))
52 regs->psr &= ~PSR_EF;
53#else
54 if (current == last_task_used_math) {
55 last_task_used_math = NULL;
56 regs->psr &= ~PSR_EF;
57 }
58#endif
59 set_used_math();
60 clear_tsk_thread_flag(current, TIF_USEDFPU);
61
62 if (!access_ok(VERIFY_READ, fpu, sizeof(*fpu)))
63 return -EFAULT;
64
65 err = __copy_from_user(&current->thread.float_regs[0], &fpu->si_float_regs[0],
66 (sizeof(unsigned long) * 32));
67 err |= __get_user(current->thread.fsr, &fpu->si_fsr);
68 err |= __get_user(current->thread.fpqdepth, &fpu->si_fpqdepth);
69 if (current->thread.fpqdepth != 0)
70 err |= __copy_from_user(&current->thread.fpqueue[0],
71 &fpu->si_fpqueue[0],
72 ((sizeof(unsigned long) +
73 (sizeof(unsigned long *)))*16));
74 return err;
75}
76
77int save_rwin_state(int wsaved, __siginfo_rwin_t __user *rwin)
78{
79 int i, err = __put_user(wsaved, &rwin->wsaved);
80
81 for (i = 0; i < wsaved; i++) {
82 struct reg_window32 *rp;
83 unsigned long fp;
84
85 rp = &current_thread_info()->reg_window[i];
86 fp = current_thread_info()->rwbuf_stkptrs[i];
87 err |= copy_to_user(&rwin->reg_window[i], rp,
88 sizeof(struct reg_window32));
89 err |= __put_user(fp, &rwin->rwbuf_stkptrs[i]);
90 }
91 return err;
92}
93
94int restore_rwin_state(__siginfo_rwin_t __user *rp)
95{
96 struct thread_info *t = current_thread_info();
97 int i, wsaved, err;
98
99 __get_user(wsaved, &rp->wsaved);
100 if (wsaved > NSWINS)
101 return -EFAULT;
102
103 err = 0;
104 for (i = 0; i < wsaved; i++) {
105 err |= copy_from_user(&t->reg_window[i],
106 &rp->reg_window[i],
107 sizeof(struct reg_window32));
108 err |= __get_user(t->rwbuf_stkptrs[i],
109 &rp->rwbuf_stkptrs[i]);
110 }
111 if (err)
112 return err;
113
114 t->w_saved = wsaved;
115 synchronize_user_stack();
116 if (t->w_saved)
117 return -EFAULT;
118 return 0;
119
120}
diff --git a/arch/sparc/kernel/sigutil_64.c b/arch/sparc/kernel/sigutil_64.c
new file mode 100644
index 000000000000..e7dc508c38eb
--- /dev/null
+++ b/arch/sparc/kernel/sigutil_64.c
@@ -0,0 +1,93 @@
1#include <linux/kernel.h>
2#include <linux/types.h>
3#include <linux/thread_info.h>
4#include <linux/uaccess.h>
5
6#include <asm/sigcontext.h>
7#include <asm/fpumacro.h>
8#include <asm/ptrace.h>
9
10#include "sigutil.h"
11
12int save_fpu_state(struct pt_regs *regs, __siginfo_fpu_t __user *fpu)
13{
14 unsigned long *fpregs = current_thread_info()->fpregs;
15 unsigned long fprs;
16 int err = 0;
17
18 fprs = current_thread_info()->fpsaved[0];
19 if (fprs & FPRS_DL)
20 err |= copy_to_user(&fpu->si_float_regs[0], fpregs,
21 (sizeof(unsigned int) * 32));
22 if (fprs & FPRS_DU)
23 err |= copy_to_user(&fpu->si_float_regs[32], fpregs+16,
24 (sizeof(unsigned int) * 32));
25 err |= __put_user(current_thread_info()->xfsr[0], &fpu->si_fsr);
26 err |= __put_user(current_thread_info()->gsr[0], &fpu->si_gsr);
27 err |= __put_user(fprs, &fpu->si_fprs);
28
29 return err;
30}
31
32int restore_fpu_state(struct pt_regs *regs, __siginfo_fpu_t __user *fpu)
33{
34 unsigned long *fpregs = current_thread_info()->fpregs;
35 unsigned long fprs;
36 int err;
37
38 err = __get_user(fprs, &fpu->si_fprs);
39 fprs_write(0);
40 regs->tstate &= ~TSTATE_PEF;
41 if (fprs & FPRS_DL)
42 err |= copy_from_user(fpregs, &fpu->si_float_regs[0],
43 (sizeof(unsigned int) * 32));
44 if (fprs & FPRS_DU)
45 err |= copy_from_user(fpregs+16, &fpu->si_float_regs[32],
46 (sizeof(unsigned int) * 32));
47 err |= __get_user(current_thread_info()->xfsr[0], &fpu->si_fsr);
48 err |= __get_user(current_thread_info()->gsr[0], &fpu->si_gsr);
49 current_thread_info()->fpsaved[0] |= fprs;
50 return err;
51}
52
53int save_rwin_state(int wsaved, __siginfo_rwin_t __user *rwin)
54{
55 int i, err = __put_user(wsaved, &rwin->wsaved);
56
57 for (i = 0; i < wsaved; i++) {
58 struct reg_window *rp = &current_thread_info()->reg_window[i];
59 unsigned long fp = current_thread_info()->rwbuf_stkptrs[i];
60
61 err |= copy_to_user(&rwin->reg_window[i], rp,
62 sizeof(struct reg_window));
63 err |= __put_user(fp, &rwin->rwbuf_stkptrs[i]);
64 }
65 return err;
66}
67
68int restore_rwin_state(__siginfo_rwin_t __user *rp)
69{
70 struct thread_info *t = current_thread_info();
71 int i, wsaved, err;
72
73 __get_user(wsaved, &rp->wsaved);
74 if (wsaved > NSWINS)
75 return -EFAULT;
76
77 err = 0;
78 for (i = 0; i < wsaved; i++) {
79 err |= copy_from_user(&t->reg_window[i],
80 &rp->reg_window[i],
81 sizeof(struct reg_window));
82 err |= __get_user(t->rwbuf_stkptrs[i],
83 &rp->rwbuf_stkptrs[i]);
84 }
85 if (err)
86 return err;
87
88 set_thread_wsaved(wsaved);
89 synchronize_user_stack();
90 if (get_thread_wsaved())
91 return -EFAULT;
92 return 0;
93}
diff --git a/arch/sparc/kernel/sys32.S b/arch/sparc/kernel/sys32.S
index 44e5faf1ad5f..d97f3eb72e06 100644
--- a/arch/sparc/kernel/sys32.S
+++ b/arch/sparc/kernel/sys32.S
@@ -81,7 +81,6 @@ SIGN2(sys32_fadvise64, compat_sys_fadvise64, %o0, %o4)
81SIGN2(sys32_fadvise64_64, compat_sys_fadvise64_64, %o0, %o5) 81SIGN2(sys32_fadvise64_64, compat_sys_fadvise64_64, %o0, %o5)
82SIGN2(sys32_bdflush, sys_bdflush, %o0, %o1) 82SIGN2(sys32_bdflush, sys_bdflush, %o0, %o1)
83SIGN1(sys32_mlockall, sys_mlockall, %o0) 83SIGN1(sys32_mlockall, sys_mlockall, %o0)
84SIGN1(sys32_nfsservctl, compat_sys_nfsservctl, %o0)
85SIGN1(sys32_clock_nanosleep, compat_sys_clock_nanosleep, %o1) 84SIGN1(sys32_clock_nanosleep, compat_sys_clock_nanosleep, %o1)
86SIGN1(sys32_timer_settime, compat_sys_timer_settime, %o1) 85SIGN1(sys32_timer_settime, compat_sys_timer_settime, %o1)
87SIGN1(sys32_io_submit, compat_sys_io_submit, %o1) 86SIGN1(sys32_io_submit, compat_sys_io_submit, %o1)
diff --git a/arch/sparc/kernel/systbls_32.S b/arch/sparc/kernel/systbls_32.S
index 6e492d59f6b1..09d8ec454450 100644
--- a/arch/sparc/kernel/systbls_32.S
+++ b/arch/sparc/kernel/systbls_32.S
@@ -67,7 +67,7 @@ sys_call_table:
67/*235*/ .long sys_fstatfs64, sys_llseek, sys_mlock, sys_munlock, sys_mlockall 67/*235*/ .long sys_fstatfs64, sys_llseek, sys_mlock, sys_munlock, sys_mlockall
68/*240*/ .long sys_munlockall, sys_sched_setparam, sys_sched_getparam, sys_sched_setscheduler, sys_sched_getscheduler 68/*240*/ .long sys_munlockall, sys_sched_setparam, sys_sched_getparam, sys_sched_setscheduler, sys_sched_getscheduler
69/*245*/ .long sys_sched_yield, sys_sched_get_priority_max, sys_sched_get_priority_min, sys_sched_rr_get_interval, sys_nanosleep 69/*245*/ .long sys_sched_yield, sys_sched_get_priority_max, sys_sched_get_priority_min, sys_sched_rr_get_interval, sys_nanosleep
70/*250*/ .long sys_mremap, sys_sysctl, sys_getsid, sys_fdatasync, sys_nfsservctl 70/*250*/ .long sys_mremap, sys_sysctl, sys_getsid, sys_fdatasync, sys_ni_syscall
71/*255*/ .long sys_sync_file_range, sys_clock_settime, sys_clock_gettime, sys_clock_getres, sys_clock_nanosleep 71/*255*/ .long sys_sync_file_range, sys_clock_settime, sys_clock_gettime, sys_clock_getres, sys_clock_nanosleep
72/*260*/ .long sys_sched_getaffinity, sys_sched_setaffinity, sys_timer_settime, sys_timer_gettime, sys_timer_getoverrun 72/*260*/ .long sys_sched_getaffinity, sys_sched_setaffinity, sys_timer_settime, sys_timer_gettime, sys_timer_getoverrun
73/*265*/ .long sys_timer_delete, sys_timer_create, sys_nis_syscall, sys_io_setup, sys_io_destroy 73/*265*/ .long sys_timer_delete, sys_timer_create, sys_nis_syscall, sys_io_setup, sys_io_destroy
diff --git a/arch/sparc/kernel/systbls_64.S b/arch/sparc/kernel/systbls_64.S
index f566518483b5..edbec45d4688 100644
--- a/arch/sparc/kernel/systbls_64.S
+++ b/arch/sparc/kernel/systbls_64.S
@@ -68,7 +68,7 @@ sys_call_table32:
68 .word compat_sys_fstatfs64, sys_llseek, sys_mlock, sys_munlock, sys32_mlockall 68 .word compat_sys_fstatfs64, sys_llseek, sys_mlock, sys_munlock, sys32_mlockall
69/*240*/ .word sys_munlockall, sys32_sched_setparam, sys32_sched_getparam, sys32_sched_setscheduler, sys32_sched_getscheduler 69/*240*/ .word sys_munlockall, sys32_sched_setparam, sys32_sched_getparam, sys32_sched_setscheduler, sys32_sched_getscheduler
70 .word sys_sched_yield, sys32_sched_get_priority_max, sys32_sched_get_priority_min, sys32_sched_rr_get_interval, compat_sys_nanosleep 70 .word sys_sched_yield, sys32_sched_get_priority_max, sys32_sched_get_priority_min, sys32_sched_rr_get_interval, compat_sys_nanosleep
71/*250*/ .word sys_mremap, compat_sys_sysctl, sys32_getsid, sys_fdatasync, sys32_nfsservctl 71/*250*/ .word sys_mremap, compat_sys_sysctl, sys32_getsid, sys_fdatasync, sys_nis_syscall
72 .word sys32_sync_file_range, compat_sys_clock_settime, compat_sys_clock_gettime, compat_sys_clock_getres, sys32_clock_nanosleep 72 .word sys32_sync_file_range, compat_sys_clock_settime, compat_sys_clock_gettime, compat_sys_clock_getres, sys32_clock_nanosleep
73/*260*/ .word compat_sys_sched_getaffinity, compat_sys_sched_setaffinity, sys32_timer_settime, compat_sys_timer_gettime, sys_timer_getoverrun 73/*260*/ .word compat_sys_sched_getaffinity, compat_sys_sched_setaffinity, sys32_timer_settime, compat_sys_timer_gettime, sys_timer_getoverrun
74 .word sys_timer_delete, compat_sys_timer_create, sys_ni_syscall, compat_sys_io_setup, sys_io_destroy 74 .word sys_timer_delete, compat_sys_timer_create, sys_ni_syscall, compat_sys_io_setup, sys_io_destroy
@@ -145,7 +145,7 @@ sys_call_table:
145 .word sys_fstatfs64, sys_llseek, sys_mlock, sys_munlock, sys_mlockall 145 .word sys_fstatfs64, sys_llseek, sys_mlock, sys_munlock, sys_mlockall
146/*240*/ .word sys_munlockall, sys_sched_setparam, sys_sched_getparam, sys_sched_setscheduler, sys_sched_getscheduler 146/*240*/ .word sys_munlockall, sys_sched_setparam, sys_sched_getparam, sys_sched_setscheduler, sys_sched_getscheduler
147 .word sys_sched_yield, sys_sched_get_priority_max, sys_sched_get_priority_min, sys_sched_rr_get_interval, sys_nanosleep 147 .word sys_sched_yield, sys_sched_get_priority_max, sys_sched_get_priority_min, sys_sched_rr_get_interval, sys_nanosleep
148/*250*/ .word sys_64_mremap, sys_sysctl, sys_getsid, sys_fdatasync, sys_nfsservctl 148/*250*/ .word sys_64_mremap, sys_sysctl, sys_getsid, sys_fdatasync, sys_nis_syscall
149 .word sys_sync_file_range, sys_clock_settime, sys_clock_gettime, sys_clock_getres, sys_clock_nanosleep 149 .word sys_sync_file_range, sys_clock_settime, sys_clock_gettime, sys_clock_getres, sys_clock_nanosleep
150/*260*/ .word sys_sched_getaffinity, sys_sched_setaffinity, sys_timer_settime, sys_timer_gettime, sys_timer_getoverrun 150/*260*/ .word sys_sched_getaffinity, sys_sched_setaffinity, sys_timer_settime, sys_timer_gettime, sys_timer_getoverrun
151 .word sys_timer_delete, sys_timer_create, sys_ni_syscall, sys_io_setup, sys_io_destroy 151 .word sys_timer_delete, sys_timer_create, sys_ni_syscall, sys_io_setup, sys_io_destroy
diff --git a/arch/sparc/kernel/visemul.c b/arch/sparc/kernel/visemul.c
index 32b626c9d815..73370674ccff 100644
--- a/arch/sparc/kernel/visemul.c
+++ b/arch/sparc/kernel/visemul.c
@@ -713,17 +713,17 @@ static void pcmp(struct pt_regs *regs, unsigned int insn, unsigned int opf)
713 s16 b = (rs2 >> (i * 16)) & 0xffff; 713 s16 b = (rs2 >> (i * 16)) & 0xffff;
714 714
715 if (a > b) 715 if (a > b)
716 rd_val |= 1 << i; 716 rd_val |= 8 >> i;
717 } 717 }
718 break; 718 break;
719 719
720 case FCMPGT32_OPF: 720 case FCMPGT32_OPF:
721 for (i = 0; i < 2; i++) { 721 for (i = 0; i < 2; i++) {
722 s32 a = (rs1 >> (i * 32)) & 0xffff; 722 s32 a = (rs1 >> (i * 32)) & 0xffffffff;
723 s32 b = (rs2 >> (i * 32)) & 0xffff; 723 s32 b = (rs2 >> (i * 32)) & 0xffffffff;
724 724
725 if (a > b) 725 if (a > b)
726 rd_val |= 1 << i; 726 rd_val |= 2 >> i;
727 } 727 }
728 break; 728 break;
729 729
@@ -733,17 +733,17 @@ static void pcmp(struct pt_regs *regs, unsigned int insn, unsigned int opf)
733 s16 b = (rs2 >> (i * 16)) & 0xffff; 733 s16 b = (rs2 >> (i * 16)) & 0xffff;
734 734
735 if (a <= b) 735 if (a <= b)
736 rd_val |= 1 << i; 736 rd_val |= 8 >> i;
737 } 737 }
738 break; 738 break;
739 739
740 case FCMPLE32_OPF: 740 case FCMPLE32_OPF:
741 for (i = 0; i < 2; i++) { 741 for (i = 0; i < 2; i++) {
742 s32 a = (rs1 >> (i * 32)) & 0xffff; 742 s32 a = (rs1 >> (i * 32)) & 0xffffffff;
743 s32 b = (rs2 >> (i * 32)) & 0xffff; 743 s32 b = (rs2 >> (i * 32)) & 0xffffffff;
744 744
745 if (a <= b) 745 if (a <= b)
746 rd_val |= 1 << i; 746 rd_val |= 2 >> i;
747 } 747 }
748 break; 748 break;
749 749
@@ -753,17 +753,17 @@ static void pcmp(struct pt_regs *regs, unsigned int insn, unsigned int opf)
753 s16 b = (rs2 >> (i * 16)) & 0xffff; 753 s16 b = (rs2 >> (i * 16)) & 0xffff;
754 754
755 if (a != b) 755 if (a != b)
756 rd_val |= 1 << i; 756 rd_val |= 8 >> i;
757 } 757 }
758 break; 758 break;
759 759
760 case FCMPNE32_OPF: 760 case FCMPNE32_OPF:
761 for (i = 0; i < 2; i++) { 761 for (i = 0; i < 2; i++) {
762 s32 a = (rs1 >> (i * 32)) & 0xffff; 762 s32 a = (rs1 >> (i * 32)) & 0xffffffff;
763 s32 b = (rs2 >> (i * 32)) & 0xffff; 763 s32 b = (rs2 >> (i * 32)) & 0xffffffff;
764 764
765 if (a != b) 765 if (a != b)
766 rd_val |= 1 << i; 766 rd_val |= 2 >> i;
767 } 767 }
768 break; 768 break;
769 769
@@ -773,17 +773,17 @@ static void pcmp(struct pt_regs *regs, unsigned int insn, unsigned int opf)
773 s16 b = (rs2 >> (i * 16)) & 0xffff; 773 s16 b = (rs2 >> (i * 16)) & 0xffff;
774 774
775 if (a == b) 775 if (a == b)
776 rd_val |= 1 << i; 776 rd_val |= 8 >> i;
777 } 777 }
778 break; 778 break;
779 779
780 case FCMPEQ32_OPF: 780 case FCMPEQ32_OPF:
781 for (i = 0; i < 2; i++) { 781 for (i = 0; i < 2; i++) {
782 s32 a = (rs1 >> (i * 32)) & 0xffff; 782 s32 a = (rs1 >> (i * 32)) & 0xffffffff;
783 s32 b = (rs2 >> (i * 32)) & 0xffff; 783 s32 b = (rs2 >> (i * 32)) & 0xffffffff;
784 784
785 if (a == b) 785 if (a == b)
786 rd_val |= 1 << i; 786 rd_val |= 2 >> i;
787 } 787 }
788 break; 788 break;
789 } 789 }
diff --git a/arch/sparc/lib/memcpy.S b/arch/sparc/lib/memcpy.S
index 34fe65751737..4d8c497517bd 100644
--- a/arch/sparc/lib/memcpy.S
+++ b/arch/sparc/lib/memcpy.S
@@ -7,40 +7,12 @@
7 * Copyright (C) 1996 Jakub Jelinek (jj@sunsite.mff.cuni.cz) 7 * Copyright (C) 1996 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
8 */ 8 */
9 9
10#ifdef __KERNEL__ 10#define FUNC(x) \
11
12#define FUNC(x) \
13 .globl x; \ 11 .globl x; \
14 .type x,@function; \ 12 .type x,@function; \
15 .align 4; \ 13 .align 4; \
16x: 14x:
17 15
18#undef FASTER_REVERSE
19#undef FASTER_NONALIGNED
20#define FASTER_ALIGNED
21
22/* In kernel these functions don't return a value.
23 * One should use macros in asm/string.h for that purpose.
24 * We return 0, so that bugs are more apparent.
25 */
26#define SETUP_RETL
27#define RETL_INSN clr %o0
28
29#else
30
31/* libc */
32
33#include "DEFS.h"
34
35#define FASTER_REVERSE
36#define FASTER_NONALIGNED
37#define FASTER_ALIGNED
38
39#define SETUP_RETL mov %o0, %g6
40#define RETL_INSN mov %g6, %o0
41
42#endif
43
44/* Both these macros have to start with exactly the same insn */ 16/* Both these macros have to start with exactly the same insn */
45#define MOVE_BIGCHUNK(src, dst, offset, t0, t1, t2, t3, t4, t5, t6, t7) \ 17#define MOVE_BIGCHUNK(src, dst, offset, t0, t1, t2, t3, t4, t5, t6, t7) \
46 ldd [%src + (offset) + 0x00], %t0; \ 18 ldd [%src + (offset) + 0x00], %t0; \
@@ -164,30 +136,6 @@ x:
164 .text 136 .text
165 .align 4 137 .align 4
166 138
167#ifdef FASTER_REVERSE
168
16970: /* rdword_align */
170
171 andcc %o1, 1, %g0
172 be 4f
173 andcc %o1, 2, %g0
174
175 ldub [%o1 - 1], %g2
176 sub %o1, 1, %o1
177 stb %g2, [%o0 - 1]
178 sub %o2, 1, %o2
179 be 3f
180 sub %o0, 1, %o0
1814:
182 lduh [%o1 - 2], %g2
183 sub %o1, 2, %o1
184 sth %g2, [%o0 - 2]
185 sub %o2, 2, %o2
186 b 3f
187 sub %o0, 2, %o0
188
189#endif /* FASTER_REVERSE */
190
1910: 1390:
192 retl 140 retl
193 nop ! Only bcopy returns here and it retuns void... 141 nop ! Only bcopy returns here and it retuns void...
@@ -198,7 +146,7 @@ FUNC(__memmove)
198#endif 146#endif
199FUNC(memmove) 147FUNC(memmove)
200 cmp %o0, %o1 148 cmp %o0, %o1
201 SETUP_RETL 149 mov %o0, %g7
202 bleu 9f 150 bleu 9f
203 sub %o0, %o1, %o4 151 sub %o0, %o1, %o4
204 152
@@ -207,8 +155,6 @@ FUNC(memmove)
207 bleu 0f 155 bleu 0f
208 andcc %o4, 3, %o5 156 andcc %o4, 3, %o5
209 157
210#ifndef FASTER_REVERSE
211
212 add %o1, %o2, %o1 158 add %o1, %o2, %o1
213 add %o0, %o2, %o0 159 add %o0, %o2, %o0
214 sub %o1, 1, %o1 160 sub %o1, 1, %o1
@@ -224,295 +170,7 @@ FUNC(memmove)
224 sub %o0, 1, %o0 170 sub %o0, 1, %o0
225 171
226 retl 172 retl
227 RETL_INSN 173 mov %g7, %o0
228
229#else /* FASTER_REVERSE */
230
231 add %o1, %o2, %o1
232 add %o0, %o2, %o0
233 bne 77f
234 cmp %o2, 15
235 bleu 91f
236 andcc %o1, 3, %g0
237 bne 70b
2383:
239 andcc %o1, 4, %g0
240
241 be 2f
242 mov %o2, %g1
243
244 ld [%o1 - 4], %o4
245 sub %g1, 4, %g1
246 st %o4, [%o0 - 4]
247 sub %o1, 4, %o1
248 sub %o0, 4, %o0
2492:
250 andcc %g1, 0xffffff80, %g7
251 be 3f
252 andcc %o0, 4, %g0
253
254 be 74f + 4
2555:
256 RMOVE_BIGCHUNK(o1, o0, 0x00, o2, o3, o4, o5, g2, g3, g4, g5)
257 RMOVE_BIGCHUNK(o1, o0, 0x20, o2, o3, o4, o5, g2, g3, g4, g5)
258 RMOVE_BIGCHUNK(o1, o0, 0x40, o2, o3, o4, o5, g2, g3, g4, g5)
259 RMOVE_BIGCHUNK(o1, o0, 0x60, o2, o3, o4, o5, g2, g3, g4, g5)
260 subcc %g7, 128, %g7
261 sub %o1, 128, %o1
262 bne 5b
263 sub %o0, 128, %o0
2643:
265 andcc %g1, 0x70, %g7
266 be 72f
267 andcc %g1, 8, %g0
268
269 sethi %hi(72f), %o5
270 srl %g7, 1, %o4
271 add %g7, %o4, %o4
272 sub %o1, %g7, %o1
273 sub %o5, %o4, %o5
274 jmpl %o5 + %lo(72f), %g0
275 sub %o0, %g7, %o0
276
27771: /* rmemcpy_table */
278 RMOVE_LASTCHUNK(o1, o0, 0x60, g2, g3, g4, g5)
279 RMOVE_LASTCHUNK(o1, o0, 0x50, g2, g3, g4, g5)
280 RMOVE_LASTCHUNK(o1, o0, 0x40, g2, g3, g4, g5)
281 RMOVE_LASTCHUNK(o1, o0, 0x30, g2, g3, g4, g5)
282 RMOVE_LASTCHUNK(o1, o0, 0x20, g2, g3, g4, g5)
283 RMOVE_LASTCHUNK(o1, o0, 0x10, g2, g3, g4, g5)
284 RMOVE_LASTCHUNK(o1, o0, 0x00, g2, g3, g4, g5)
285
28672: /* rmemcpy_table_end */
287
288 be 73f
289 andcc %g1, 4, %g0
290
291 ldd [%o1 - 0x08], %g2
292 sub %o0, 8, %o0
293 sub %o1, 8, %o1
294 st %g2, [%o0]
295 st %g3, [%o0 + 0x04]
296
29773: /* rmemcpy_last7 */
298
299 be 1f
300 andcc %g1, 2, %g0
301
302 ld [%o1 - 4], %g2
303 sub %o1, 4, %o1
304 st %g2, [%o0 - 4]
305 sub %o0, 4, %o0
3061:
307 be 1f
308 andcc %g1, 1, %g0
309
310 lduh [%o1 - 2], %g2
311 sub %o1, 2, %o1
312 sth %g2, [%o0 - 2]
313 sub %o0, 2, %o0
3141:
315 be 1f
316 nop
317
318 ldub [%o1 - 1], %g2
319 stb %g2, [%o0 - 1]
3201:
321 retl
322 RETL_INSN
323
32474: /* rldd_std */
325 RMOVE_BIGALIGNCHUNK(o1, o0, 0x00, o2, o3, o4, o5, g2, g3, g4, g5)
326 RMOVE_BIGALIGNCHUNK(o1, o0, 0x20, o2, o3, o4, o5, g2, g3, g4, g5)
327 RMOVE_BIGALIGNCHUNK(o1, o0, 0x40, o2, o3, o4, o5, g2, g3, g4, g5)
328 RMOVE_BIGALIGNCHUNK(o1, o0, 0x60, o2, o3, o4, o5, g2, g3, g4, g5)
329 subcc %g7, 128, %g7
330 sub %o1, 128, %o1
331 bne 74b
332 sub %o0, 128, %o0
333
334 andcc %g1, 0x70, %g7
335 be 72b
336 andcc %g1, 8, %g0
337
338 sethi %hi(72b), %o5
339 srl %g7, 1, %o4
340 add %g7, %o4, %o4
341 sub %o1, %g7, %o1
342 sub %o5, %o4, %o5
343 jmpl %o5 + %lo(72b), %g0
344 sub %o0, %g7, %o0
345
34675: /* rshort_end */
347
348 and %o2, 0xe, %o3
3492:
350 sethi %hi(76f), %o5
351 sll %o3, 3, %o4
352 sub %o0, %o3, %o0
353 sub %o5, %o4, %o5
354 sub %o1, %o3, %o1
355 jmpl %o5 + %lo(76f), %g0
356 andcc %o2, 1, %g0
357
358 RMOVE_SHORTCHUNK(o1, o0, 0x0c, g2, g3)
359 RMOVE_SHORTCHUNK(o1, o0, 0x0a, g2, g3)
360 RMOVE_SHORTCHUNK(o1, o0, 0x08, g2, g3)
361 RMOVE_SHORTCHUNK(o1, o0, 0x06, g2, g3)
362 RMOVE_SHORTCHUNK(o1, o0, 0x04, g2, g3)
363 RMOVE_SHORTCHUNK(o1, o0, 0x02, g2, g3)
364 RMOVE_SHORTCHUNK(o1, o0, 0x00, g2, g3)
365
36676: /* rshort_table_end */
367
368 be 1f
369 nop
370 ldub [%o1 - 1], %g2
371 stb %g2, [%o0 - 1]
3721:
373 retl
374 RETL_INSN
375
37691: /* rshort_aligned_end */
377
378 bne 75b
379 andcc %o2, 8, %g0
380
381 be 1f
382 andcc %o2, 4, %g0
383
384 ld [%o1 - 0x08], %g2
385 ld [%o1 - 0x04], %g3
386 sub %o1, 8, %o1
387 st %g2, [%o0 - 0x08]
388 st %g3, [%o0 - 0x04]
389 sub %o0, 8, %o0
3901:
391 b 73b
392 mov %o2, %g1
393
39477: /* rnon_aligned */
395 cmp %o2, 15
396 bleu 75b
397 andcc %o0, 3, %g0
398 be 64f
399 andcc %o0, 1, %g0
400 be 63f
401 andcc %o0, 2, %g0
402 ldub [%o1 - 1], %g5
403 sub %o1, 1, %o1
404 stb %g5, [%o0 - 1]
405 sub %o0, 1, %o0
406 be 64f
407 sub %o2, 1, %o2
40863:
409 ldub [%o1 - 1], %g5
410 sub %o1, 2, %o1
411 stb %g5, [%o0 - 1]
412 sub %o0, 2, %o0
413 ldub [%o1], %g5
414 sub %o2, 2, %o2
415 stb %g5, [%o0]
41664:
417 and %o1, 3, %g2
418 and %o1, -4, %o1
419 and %o2, 0xc, %g3
420 add %o1, 4, %o1
421 cmp %g3, 4
422 sll %g2, 3, %g4
423 mov 32, %g2
424 be 4f
425 sub %g2, %g4, %g7
426
427 blu 3f
428 cmp %g3, 8
429
430 be 2f
431 srl %o2, 2, %g3
432
433 ld [%o1 - 4], %o3
434 add %o0, -8, %o0
435 ld [%o1 - 8], %o4
436 add %o1, -16, %o1
437 b 7f
438 add %g3, 1, %g3
4392:
440 ld [%o1 - 4], %o4
441 add %o0, -4, %o0
442 ld [%o1 - 8], %g1
443 add %o1, -12, %o1
444 b 8f
445 add %g3, 2, %g3
4463:
447 ld [%o1 - 4], %o5
448 add %o0, -12, %o0
449 ld [%o1 - 8], %o3
450 add %o1, -20, %o1
451 b 6f
452 srl %o2, 2, %g3
4534:
454 ld [%o1 - 4], %g1
455 srl %o2, 2, %g3
456 ld [%o1 - 8], %o5
457 add %o1, -24, %o1
458 add %o0, -16, %o0
459 add %g3, -1, %g3
460
461 ld [%o1 + 12], %o3
4625:
463 sll %o5, %g4, %g2
464 srl %g1, %g7, %g5
465 or %g2, %g5, %g2
466 st %g2, [%o0 + 12]
4676:
468 ld [%o1 + 8], %o4
469 sll %o3, %g4, %g2
470 srl %o5, %g7, %g5
471 or %g2, %g5, %g2
472 st %g2, [%o0 + 8]
4737:
474 ld [%o1 + 4], %g1
475 sll %o4, %g4, %g2
476 srl %o3, %g7, %g5
477 or %g2, %g5, %g2
478 st %g2, [%o0 + 4]
4798:
480 ld [%o1], %o5
481 sll %g1, %g4, %g2
482 srl %o4, %g7, %g5
483 addcc %g3, -4, %g3
484 or %g2, %g5, %g2
485 add %o1, -16, %o1
486 st %g2, [%o0]
487 add %o0, -16, %o0
488 bne,a 5b
489 ld [%o1 + 12], %o3
490 sll %o5, %g4, %g2
491 srl %g1, %g7, %g5
492 srl %g4, 3, %g3
493 or %g2, %g5, %g2
494 add %o1, %g3, %o1
495 andcc %o2, 2, %g0
496 st %g2, [%o0 + 12]
497 be 1f
498 andcc %o2, 1, %g0
499
500 ldub [%o1 + 15], %g5
501 add %o1, -2, %o1
502 stb %g5, [%o0 + 11]
503 add %o0, -2, %o0
504 ldub [%o1 + 16], %g5
505 stb %g5, [%o0 + 12]
5061:
507 be 1f
508 nop
509 ldub [%o1 + 15], %g5
510 stb %g5, [%o0 + 11]
5111:
512 retl
513 RETL_INSN
514
515#endif /* FASTER_REVERSE */
516 174
517/* NOTE: This code is executed just for the cases, 175/* NOTE: This code is executed just for the cases,
518 where %src (=%o1) & 3 is != 0. 176 where %src (=%o1) & 3 is != 0.
@@ -546,7 +204,7 @@ FUNC(memmove)
546FUNC(memcpy) /* %o0=dst %o1=src %o2=len */ 204FUNC(memcpy) /* %o0=dst %o1=src %o2=len */
547 205
548 sub %o0, %o1, %o4 206 sub %o0, %o1, %o4
549 SETUP_RETL 207 mov %o0, %g7
5509: 2089:
551 andcc %o4, 3, %o5 209 andcc %o4, 3, %o5
5520: 2100:
@@ -569,7 +227,7 @@ FUNC(memcpy) /* %o0=dst %o1=src %o2=len */
569 add %o1, 4, %o1 227 add %o1, 4, %o1
570 add %o0, 4, %o0 228 add %o0, 4, %o0
5712: 2292:
572 andcc %g1, 0xffffff80, %g7 230 andcc %g1, 0xffffff80, %g0
573 be 3f 231 be 3f
574 andcc %o0, 4, %g0 232 andcc %o0, 4, %g0
575 233
@@ -579,22 +237,23 @@ FUNC(memcpy) /* %o0=dst %o1=src %o2=len */
579 MOVE_BIGCHUNK(o1, o0, 0x20, o2, o3, o4, o5, g2, g3, g4, g5) 237 MOVE_BIGCHUNK(o1, o0, 0x20, o2, o3, o4, o5, g2, g3, g4, g5)
580 MOVE_BIGCHUNK(o1, o0, 0x40, o2, o3, o4, o5, g2, g3, g4, g5) 238 MOVE_BIGCHUNK(o1, o0, 0x40, o2, o3, o4, o5, g2, g3, g4, g5)
581 MOVE_BIGCHUNK(o1, o0, 0x60, o2, o3, o4, o5, g2, g3, g4, g5) 239 MOVE_BIGCHUNK(o1, o0, 0x60, o2, o3, o4, o5, g2, g3, g4, g5)
582 subcc %g7, 128, %g7 240 sub %g1, 128, %g1
583 add %o1, 128, %o1 241 add %o1, 128, %o1
584 bne 5b 242 cmp %g1, 128
243 bge 5b
585 add %o0, 128, %o0 244 add %o0, 128, %o0
5863: 2453:
587 andcc %g1, 0x70, %g7 246 andcc %g1, 0x70, %g4
588 be 80f 247 be 80f
589 andcc %g1, 8, %g0 248 andcc %g1, 8, %g0
590 249
591 sethi %hi(80f), %o5 250 sethi %hi(80f), %o5
592 srl %g7, 1, %o4 251 srl %g4, 1, %o4
593 add %g7, %o4, %o4 252 add %g4, %o4, %o4
594 add %o1, %g7, %o1 253 add %o1, %g4, %o1
595 sub %o5, %o4, %o5 254 sub %o5, %o4, %o5
596 jmpl %o5 + %lo(80f), %g0 255 jmpl %o5 + %lo(80f), %g0
597 add %o0, %g7, %o0 256 add %o0, %g4, %o0
598 257
59979: /* memcpy_table */ 25879: /* memcpy_table */
600 259
@@ -641,43 +300,28 @@ FUNC(memcpy) /* %o0=dst %o1=src %o2=len */
641 stb %g2, [%o0] 300 stb %g2, [%o0]
6421: 3011:
643 retl 302 retl
644 RETL_INSN 303 mov %g7, %o0
645 304
64682: /* ldd_std */ 30582: /* ldd_std */
647 MOVE_BIGALIGNCHUNK(o1, o0, 0x00, o2, o3, o4, o5, g2, g3, g4, g5) 306 MOVE_BIGALIGNCHUNK(o1, o0, 0x00, o2, o3, o4, o5, g2, g3, g4, g5)
648 MOVE_BIGALIGNCHUNK(o1, o0, 0x20, o2, o3, o4, o5, g2, g3, g4, g5) 307 MOVE_BIGALIGNCHUNK(o1, o0, 0x20, o2, o3, o4, o5, g2, g3, g4, g5)
649 MOVE_BIGALIGNCHUNK(o1, o0, 0x40, o2, o3, o4, o5, g2, g3, g4, g5) 308 MOVE_BIGALIGNCHUNK(o1, o0, 0x40, o2, o3, o4, o5, g2, g3, g4, g5)
650 MOVE_BIGALIGNCHUNK(o1, o0, 0x60, o2, o3, o4, o5, g2, g3, g4, g5) 309 MOVE_BIGALIGNCHUNK(o1, o0, 0x60, o2, o3, o4, o5, g2, g3, g4, g5)
651 subcc %g7, 128, %g7 310 subcc %g1, 128, %g1
652 add %o1, 128, %o1 311 add %o1, 128, %o1
653 bne 82b 312 cmp %g1, 128
313 bge 82b
654 add %o0, 128, %o0 314 add %o0, 128, %o0
655 315
656#ifndef FASTER_ALIGNED 316 andcc %g1, 0x70, %g4
657
658 andcc %g1, 0x70, %g7
659 be 80b
660 andcc %g1, 8, %g0
661
662 sethi %hi(80b), %o5
663 srl %g7, 1, %o4
664 add %g7, %o4, %o4
665 add %o1, %g7, %o1
666 sub %o5, %o4, %o5
667 jmpl %o5 + %lo(80b), %g0
668 add %o0, %g7, %o0
669
670#else /* FASTER_ALIGNED */
671
672 andcc %g1, 0x70, %g7
673 be 84f 317 be 84f
674 andcc %g1, 8, %g0 318 andcc %g1, 8, %g0
675 319
676 sethi %hi(84f), %o5 320 sethi %hi(84f), %o5
677 add %o1, %g7, %o1 321 add %o1, %g4, %o1
678 sub %o5, %g7, %o5 322 sub %o5, %g4, %o5
679 jmpl %o5 + %lo(84f), %g0 323 jmpl %o5 + %lo(84f), %g0
680 add %o0, %g7, %o0 324 add %o0, %g4, %o0
681 325
68283: /* amemcpy_table */ 32683: /* amemcpy_table */
683 327
@@ -721,382 +365,132 @@ FUNC(memcpy) /* %o0=dst %o1=src %o2=len */
721 stb %g2, [%o0] 365 stb %g2, [%o0]
7221: 3661:
723 retl 367 retl
724 RETL_INSN 368 mov %g7, %o0
725
726#endif /* FASTER_ALIGNED */
727 369
72886: /* non_aligned */ 37086: /* non_aligned */
729 cmp %o2, 6 371 cmp %o2, 6
730 bleu 88f 372 bleu 88f
373 nop
731 374
732#ifdef FASTER_NONALIGNED 375 save %sp, -96, %sp
733 376 andcc %i0, 3, %g0
734 cmp %o2, 256
735 bcc 87f
736
737#endif /* FASTER_NONALIGNED */
738
739 andcc %o0, 3, %g0
740 be 61f 377 be 61f
741 andcc %o0, 1, %g0 378 andcc %i0, 1, %g0
742 be 60f 379 be 60f
743 andcc %o0, 2, %g0 380 andcc %i0, 2, %g0
744 381
745 ldub [%o1], %g5 382 ldub [%i1], %g5
746 add %o1, 1, %o1 383 add %i1, 1, %i1
747 stb %g5, [%o0] 384 stb %g5, [%i0]
748 sub %o2, 1, %o2 385 sub %i2, 1, %i2
749 bne 61f 386 bne 61f
750 add %o0, 1, %o0 387 add %i0, 1, %i0
75160: 38860:
752 ldub [%o1], %g3 389 ldub [%i1], %g3
753 add %o1, 2, %o1 390 add %i1, 2, %i1
754 stb %g3, [%o0] 391 stb %g3, [%i0]
755 sub %o2, 2, %o2 392 sub %i2, 2, %i2
756 ldub [%o1 - 1], %g3 393 ldub [%i1 - 1], %g3
757 add %o0, 2, %o0 394 add %i0, 2, %i0
758 stb %g3, [%o0 - 1] 395 stb %g3, [%i0 - 1]
75961: 39661:
760 and %o1, 3, %g2 397 and %i1, 3, %g2
761 and %o2, 0xc, %g3 398 and %i2, 0xc, %g3
762 and %o1, -4, %o1 399 and %i1, -4, %i1
763 cmp %g3, 4 400 cmp %g3, 4
764 sll %g2, 3, %g4 401 sll %g2, 3, %g4
765 mov 32, %g2 402 mov 32, %g2
766 be 4f 403 be 4f
767 sub %g2, %g4, %g7 404 sub %g2, %g4, %l0
768 405
769 blu 3f 406 blu 3f
770 cmp %g3, 0x8 407 cmp %g3, 0x8
771 408
772 be 2f 409 be 2f
773 srl %o2, 2, %g3 410 srl %i2, 2, %g3
774 411
775 ld [%o1], %o3 412 ld [%i1], %i3
776 add %o0, -8, %o0 413 add %i0, -8, %i0
777 ld [%o1 + 4], %o4 414 ld [%i1 + 4], %i4
778 b 8f 415 b 8f
779 add %g3, 1, %g3 416 add %g3, 1, %g3
7802: 4172:
781 ld [%o1], %o4 418 ld [%i1], %i4
782 add %o0, -12, %o0 419 add %i0, -12, %i0
783 ld [%o1 + 4], %o5 420 ld [%i1 + 4], %i5
784 add %g3, 2, %g3 421 add %g3, 2, %g3
785 b 9f 422 b 9f
786 add %o1, -4, %o1 423 add %i1, -4, %i1
7873: 4243:
788 ld [%o1], %g1 425 ld [%i1], %g1
789 add %o0, -4, %o0 426 add %i0, -4, %i0
790 ld [%o1 + 4], %o3 427 ld [%i1 + 4], %i3
791 srl %o2, 2, %g3 428 srl %i2, 2, %g3
792 b 7f 429 b 7f
793 add %o1, 4, %o1 430 add %i1, 4, %i1
7944: 4314:
795 ld [%o1], %o5 432 ld [%i1], %i5
796 cmp %o2, 7 433 cmp %i2, 7
797 ld [%o1 + 4], %g1 434 ld [%i1 + 4], %g1
798 srl %o2, 2, %g3 435 srl %i2, 2, %g3
799 bleu 10f 436 bleu 10f
800 add %o1, 8, %o1 437 add %i1, 8, %i1
801 438
802 ld [%o1], %o3 439 ld [%i1], %i3
803 add %g3, -1, %g3 440 add %g3, -1, %g3
8045: 4415:
805 sll %o5, %g4, %g2 442 sll %i5, %g4, %g2
806 srl %g1, %g7, %g5 443 srl %g1, %l0, %g5
807 or %g2, %g5, %g2 444 or %g2, %g5, %g2
808 st %g2, [%o0] 445 st %g2, [%i0]
8097: 4467:
810 ld [%o1 + 4], %o4 447 ld [%i1 + 4], %i4
811 sll %g1, %g4, %g2 448 sll %g1, %g4, %g2
812 srl %o3, %g7, %g5 449 srl %i3, %l0, %g5
813 or %g2, %g5, %g2 450 or %g2, %g5, %g2
814 st %g2, [%o0 + 4] 451 st %g2, [%i0 + 4]
8158: 4528:
816 ld [%o1 + 8], %o5 453 ld [%i1 + 8], %i5
817 sll %o3, %g4, %g2 454 sll %i3, %g4, %g2
818 srl %o4, %g7, %g5 455 srl %i4, %l0, %g5
819 or %g2, %g5, %g2 456 or %g2, %g5, %g2
820 st %g2, [%o0 + 8] 457 st %g2, [%i0 + 8]
8219: 4589:
822 ld [%o1 + 12], %g1 459 ld [%i1 + 12], %g1
823 sll %o4, %g4, %g2 460 sll %i4, %g4, %g2
824 srl %o5, %g7, %g5 461 srl %i5, %l0, %g5
825 addcc %g3, -4, %g3 462 addcc %g3, -4, %g3
826 or %g2, %g5, %g2 463 or %g2, %g5, %g2
827 add %o1, 16, %o1 464 add %i1, 16, %i1
828 st %g2, [%o0 + 12] 465 st %g2, [%i0 + 12]
829 add %o0, 16, %o0 466 add %i0, 16, %i0
830 bne,a 5b 467 bne,a 5b
831 ld [%o1], %o3 468 ld [%i1], %i3
83210: 46910:
833 sll %o5, %g4, %g2 470 sll %i5, %g4, %g2
834 srl %g1, %g7, %g5 471 srl %g1, %l0, %g5
835 srl %g7, 3, %g3 472 srl %l0, 3, %g3
836 or %g2, %g5, %g2 473 or %g2, %g5, %g2
837 sub %o1, %g3, %o1 474 sub %i1, %g3, %i1
838 andcc %o2, 2, %g0 475 andcc %i2, 2, %g0
839 st %g2, [%o0] 476 st %g2, [%i0]
840 be 1f 477 be 1f
841 andcc %o2, 1, %g0 478 andcc %i2, 1, %g0
842 479
843 ldub [%o1], %g2 480 ldub [%i1], %g2
844 add %o1, 2, %o1 481 add %i1, 2, %i1
845 stb %g2, [%o0 + 4] 482 stb %g2, [%i0 + 4]
846 add %o0, 2, %o0 483 add %i0, 2, %i0
847 ldub [%o1 - 1], %g2 484 ldub [%i1 - 1], %g2
848 stb %g2, [%o0 + 3] 485 stb %g2, [%i0 + 3]
8491: 4861:
850 be 1f 487 be 1f
851 nop 488 nop
852 ldub [%o1], %g2 489 ldub [%i1], %g2
853 stb %g2, [%o0 + 4] 490 stb %g2, [%i0 + 4]
8541:
855 retl
856 RETL_INSN
857
858#ifdef FASTER_NONALIGNED
859
86087: /* faster_nonaligned */
861
862 andcc %o1, 3, %g0
863 be 3f
864 andcc %o1, 1, %g0
865
866 be 4f
867 andcc %o1, 2, %g0
868
869 ldub [%o1], %g2
870 add %o1, 1, %o1
871 stb %g2, [%o0]
872 sub %o2, 1, %o2
873 bne 3f
874 add %o0, 1, %o0
8754:
876 lduh [%o1], %g2
877 add %o1, 2, %o1
878 srl %g2, 8, %g3
879 sub %o2, 2, %o2
880 stb %g3, [%o0]
881 add %o0, 2, %o0
882 stb %g2, [%o0 - 1]
8833:
884 andcc %o1, 4, %g0
885
886 bne 2f
887 cmp %o5, 1
888
889 ld [%o1], %o4
890 srl %o4, 24, %g2
891 stb %g2, [%o0]
892 srl %o4, 16, %g3
893 stb %g3, [%o0 + 1]
894 srl %o4, 8, %g2
895 stb %g2, [%o0 + 2]
896 sub %o2, 4, %o2
897 stb %o4, [%o0 + 3]
898 add %o1, 4, %o1
899 add %o0, 4, %o0
9002:
901 be 33f
902 cmp %o5, 2
903 be 32f
904 sub %o2, 4, %o2
90531:
906 ld [%o1], %g2
907 add %o1, 4, %o1
908 srl %g2, 24, %g3
909 and %o0, 7, %g5
910 stb %g3, [%o0]
911 cmp %g5, 7
912 sll %g2, 8, %g1
913 add %o0, 4, %o0
914 be 41f
915 and %o2, 0xffffffc0, %o3
916 ld [%o0 - 7], %o4
9174:
918 SMOVE_CHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g7, g1, 8, 24, -3)
919 SMOVE_CHUNK(o1, o0, 0x10, g2, g3, g4, g5, o4, o5, g7, g1, 8, 24, -3)
920 SMOVE_CHUNK(o1, o0, 0x20, g2, g3, g4, g5, o4, o5, g7, g1, 8, 24, -3)
921 SMOVE_CHUNK(o1, o0, 0x30, g2, g3, g4, g5, o4, o5, g7, g1, 8, 24, -3)
922 subcc %o3, 64, %o3
923 add %o1, 64, %o1
924 bne 4b
925 add %o0, 64, %o0
926
927 andcc %o2, 0x30, %o3
928 be,a 1f
929 srl %g1, 16, %g2
9304:
931 SMOVE_CHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g7, g1, 8, 24, -3)
932 subcc %o3, 16, %o3
933 add %o1, 16, %o1
934 bne 4b
935 add %o0, 16, %o0
936
937 srl %g1, 16, %g2
9381:
939 st %o4, [%o0 - 7]
940 sth %g2, [%o0 - 3]
941 srl %g1, 8, %g4
942 b 88f
943 stb %g4, [%o0 - 1]
94432:
945 ld [%o1], %g2
946 add %o1, 4, %o1
947 srl %g2, 16, %g3
948 and %o0, 7, %g5
949 sth %g3, [%o0]
950 cmp %g5, 6
951 sll %g2, 16, %g1
952 add %o0, 4, %o0
953 be 42f
954 and %o2, 0xffffffc0, %o3
955 ld [%o0 - 6], %o4
9564:
957 SMOVE_CHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g7, g1, 16, 16, -2)
958 SMOVE_CHUNK(o1, o0, 0x10, g2, g3, g4, g5, o4, o5, g7, g1, 16, 16, -2)
959 SMOVE_CHUNK(o1, o0, 0x20, g2, g3, g4, g5, o4, o5, g7, g1, 16, 16, -2)
960 SMOVE_CHUNK(o1, o0, 0x30, g2, g3, g4, g5, o4, o5, g7, g1, 16, 16, -2)
961 subcc %o3, 64, %o3
962 add %o1, 64, %o1
963 bne 4b
964 add %o0, 64, %o0
965
966 andcc %o2, 0x30, %o3
967 be,a 1f
968 srl %g1, 16, %g2
9694:
970 SMOVE_CHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g7, g1, 16, 16, -2)
971 subcc %o3, 16, %o3
972 add %o1, 16, %o1
973 bne 4b
974 add %o0, 16, %o0
975
976 srl %g1, 16, %g2
9771:
978 st %o4, [%o0 - 6]
979 b 88f
980 sth %g2, [%o0 - 2]
98133:
982 ld [%o1], %g2
983 sub %o2, 4, %o2
984 srl %g2, 24, %g3
985 and %o0, 7, %g5
986 stb %g3, [%o0]
987 cmp %g5, 5
988 srl %g2, 8, %g4
989 sll %g2, 24, %g1
990 sth %g4, [%o0 + 1]
991 add %o1, 4, %o1
992 be 43f
993 and %o2, 0xffffffc0, %o3
994
995 ld [%o0 - 1], %o4
996 add %o0, 4, %o0
9974:
998 SMOVE_CHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g7, g1, 24, 8, -1)
999 SMOVE_CHUNK(o1, o0, 0x10, g2, g3, g4, g5, o4, o5, g7, g1, 24, 8, -1)
1000 SMOVE_CHUNK(o1, o0, 0x20, g2, g3, g4, g5, o4, o5, g7, g1, 24, 8, -1)
1001 SMOVE_CHUNK(o1, o0, 0x30, g2, g3, g4, g5, o4, o5, g7, g1, 24, 8, -1)
1002 subcc %o3, 64, %o3
1003 add %o1, 64, %o1
1004 bne 4b
1005 add %o0, 64, %o0
1006
1007 andcc %o2, 0x30, %o3
1008 be,a 1f
1009 srl %g1, 24, %g2
10104:
1011 SMOVE_CHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g7, g1, 24, 8, -1)
1012 subcc %o3, 16, %o3
1013 add %o1, 16, %o1
1014 bne 4b
1015 add %o0, 16, %o0
1016
1017 srl %g1, 24, %g2
10181:
1019 st %o4, [%o0 - 5]
1020 b 88f
1021 stb %g2, [%o0 - 1]
102241:
1023 SMOVE_ALIGNCHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g7, g1, 8, 24, -3)
1024 SMOVE_ALIGNCHUNK(o1, o0, 0x10, g2, g3, g4, g5, o4, o5, g7, g1, 8, 24, -3)
1025 SMOVE_ALIGNCHUNK(o1, o0, 0x20, g2, g3, g4, g5, o4, o5, g7, g1, 8, 24, -3)
1026 SMOVE_ALIGNCHUNK(o1, o0, 0x30, g2, g3, g4, g5, o4, o5, g7, g1, 8, 24, -3)
1027 subcc %o3, 64, %o3
1028 add %o1, 64, %o1
1029 bne 41b
1030 add %o0, 64, %o0
1031
1032 andcc %o2, 0x30, %o3
1033 be,a 1f
1034 srl %g1, 16, %g2
10354:
1036 SMOVE_ALIGNCHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g7, g1, 8, 24, -3)
1037 subcc %o3, 16, %o3
1038 add %o1, 16, %o1
1039 bne 4b
1040 add %o0, 16, %o0
1041
1042 srl %g1, 16, %g2
10431: 4911:
1044 sth %g2, [%o0 - 3] 492 ret
1045 srl %g1, 8, %g4 493 restore %g7, %g0, %o0
1046 b 88f
1047 stb %g4, [%o0 - 1]
104843:
1049 SMOVE_ALIGNCHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g7, g1, 24, 8, 3)
1050 SMOVE_ALIGNCHUNK(o1, o0, 0x10, g2, g3, g4, g5, o4, o5, g7, g1, 24, 8, 3)
1051 SMOVE_ALIGNCHUNK(o1, o0, 0x20, g2, g3, g4, g5, o4, o5, g7, g1, 24, 8, 3)
1052 SMOVE_ALIGNCHUNK(o1, o0, 0x30, g2, g3, g4, g5, o4, o5, g7, g1, 24, 8, 3)
1053 subcc %o3, 64, %o3
1054 add %o1, 64, %o1
1055 bne 43b
1056 add %o0, 64, %o0
1057
1058 andcc %o2, 0x30, %o3
1059 be,a 1f
1060 srl %g1, 24, %g2
10614:
1062 SMOVE_ALIGNCHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g7, g1, 24, 8, 3)
1063 subcc %o3, 16, %o3
1064 add %o1, 16, %o1
1065 bne 4b
1066 add %o0, 16, %o0
1067
1068 srl %g1, 24, %g2
10691:
1070 stb %g2, [%o0 + 3]
1071 b 88f
1072 add %o0, 4, %o0
107342:
1074 SMOVE_ALIGNCHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g7, g1, 16, 16, -2)
1075 SMOVE_ALIGNCHUNK(o1, o0, 0x10, g2, g3, g4, g5, o4, o5, g7, g1, 16, 16, -2)
1076 SMOVE_ALIGNCHUNK(o1, o0, 0x20, g2, g3, g4, g5, o4, o5, g7, g1, 16, 16, -2)
1077 SMOVE_ALIGNCHUNK(o1, o0, 0x30, g2, g3, g4, g5, o4, o5, g7, g1, 16, 16, -2)
1078 subcc %o3, 64, %o3
1079 add %o1, 64, %o1
1080 bne 42b
1081 add %o0, 64, %o0
1082
1083 andcc %o2, 0x30, %o3
1084 be,a 1f
1085 srl %g1, 16, %g2
10864:
1087 SMOVE_ALIGNCHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g7, g1, 16, 16, -2)
1088 subcc %o3, 16, %o3
1089 add %o1, 16, %o1
1090 bne 4b
1091 add %o0, 16, %o0
1092
1093 srl %g1, 16, %g2
10941:
1095 sth %g2, [%o0 - 2]
1096
1097 /* Fall through */
1098
1099#endif /* FASTER_NONALIGNED */
1100 494
110188: /* short_end */ 49588: /* short_end */
1102 496
@@ -1127,7 +521,7 @@ FUNC(memcpy) /* %o0=dst %o1=src %o2=len */
1127 stb %g2, [%o0] 521 stb %g2, [%o0]
11281: 5221:
1129 retl 523 retl
1130 RETL_INSN 524 mov %g7, %o0
1131 525
113290: /* short_aligned_end */ 52690: /* short_aligned_end */
1133 bne 88b 527 bne 88b
diff --git a/arch/sparc/mm/gup.c b/arch/sparc/mm/gup.c
index a986b5d05712..42c55df3aec3 100644
--- a/arch/sparc/mm/gup.c
+++ b/arch/sparc/mm/gup.c
@@ -56,6 +56,8 @@ static noinline int gup_pte_range(pmd_t pmd, unsigned long addr,
56 put_page(head); 56 put_page(head);
57 return 0; 57 return 0;
58 } 58 }
59 if (head != page)
60 get_huge_page_tail(page);
59 61
60 pages[*nr] = page; 62 pages[*nr] = page;
61 (*nr)++; 63 (*nr)++;
diff --git a/arch/sparc/mm/init_64.c b/arch/sparc/mm/init_64.c
index 581531dbc8b5..8e073d802139 100644
--- a/arch/sparc/mm/init_64.c
+++ b/arch/sparc/mm/init_64.c
@@ -511,6 +511,11 @@ static void __init read_obp_translations(void)
511 for (i = 0; i < prom_trans_ents; i++) 511 for (i = 0; i < prom_trans_ents; i++)
512 prom_trans[i].data &= ~0x0003fe0000000000UL; 512 prom_trans[i].data &= ~0x0003fe0000000000UL;
513 } 513 }
514
515 /* Force execute bit on. */
516 for (i = 0; i < prom_trans_ents; i++)
517 prom_trans[i].data |= (tlb_type == hypervisor ?
518 _PAGE_EXEC_4V : _PAGE_EXEC_4U);
514} 519}
515 520
516static void __init hypervisor_tlb_lock(unsigned long vaddr, 521static void __init hypervisor_tlb_lock(unsigned long vaddr,
diff --git a/arch/sparc/mm/leon_mm.c b/arch/sparc/mm/leon_mm.c
index e485a6804998..13c2169822a8 100644
--- a/arch/sparc/mm/leon_mm.c
+++ b/arch/sparc/mm/leon_mm.c
@@ -162,7 +162,7 @@ ready:
162 printk(KERN_INFO "swprobe: padde %x\n", paddr_calc); 162 printk(KERN_INFO "swprobe: padde %x\n", paddr_calc);
163 if (paddr) 163 if (paddr)
164 *paddr = paddr_calc; 164 *paddr = paddr_calc;
165 return paddrbase; 165 return pte;
166} 166}
167 167
168void leon_flush_icache_all(void) 168void leon_flush_icache_all(void)