aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sparc/kernel
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-05-21 13:32:01 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2012-05-21 13:32:01 -0400
commit9daeaa370526df1c19eba4780247bb7155541e38 (patch)
tree5ae2601c26e280e81d753c1fe65453a3b8b1d2a0 /arch/sparc/kernel
parentcb62ab71fe2b16e8203a0f0a2ef4eda23d761338 (diff)
parent1edc17832d8f49a0263d364c453ea35da0e4e2a6 (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc-next
Pull sparc updates from David Miller: 1) Kill off support for sun4c and Cypress sun4m chips. And as a result we were able to also kill off that ugly btfixup thing that required multi-stage links of the final vmlinux image in the Kbuild system. This should make the kbuild maintainers really happy. Thanks a lot to Sam Ravnborg for his tireless efforts to get this going. 2) Convert sparc64 to nobootmem. I suspect now with sparc32 being a lot cleaner, it should be able to fall in line and modernize in this area too. 3) Make sparc32 use generic clockevents, from Tkhai Kirill. [ I fixed up the BPF rules, and tried to clean up the build rules too. But I don't have - or want - a sparc cross-build environment, so the BPF rule bug and the related build cleanup was all done with just a bare "make -n" pseudo-test. - Linus ] * git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc-next: (110 commits) sparc32: use flushi when run-time patching in per_cpu_patch sparc32: fix cpuid_patch run-time patching sparc32: drop unused inline functions in srmmu.c sparc32: drop unused functions in pgtsrmmu.h sparc32,leon: move leon mmu functions to leon_mm.c sparc32,leon: remove duplicate definitions in leon.h sparc32,leon: remove duplicate UART register definitions sparc32,leon: move leon ASI definitions to asi.h sparc32: move trap table to a separate file sparc64: renamed ttable.S to ttable_64.S sparc32: Remove asm/sysen.h header. sparc32: Delete asm/smpprim.h sparc32: Remove unused empty_bad_page{,_table} declarations. sparc32: Kill boot_cpu_id4 sparc32: Move GET_PROCESSOR*_ID() out of asm/asmmacro.h sparc32: Remove completely unused code from asm/cache.h sparc32: Add ucmpdi2.o to obj-y instead of lib-y. sparc32: add ucmpdi2 sparc: introduce arch/sparc/Kbuild sparc: remove obsolete documentation ...
Diffstat (limited to 'arch/sparc/kernel')
-rw-r--r--arch/sparc/kernel/Makefile3
-rw-r--r--arch/sparc/kernel/auxio_32.c13
-rw-r--r--arch/sparc/kernel/devices.c4
-rw-r--r--arch/sparc/kernel/ds.c2
-rw-r--r--arch/sparc/kernel/entry.S432
-rw-r--r--arch/sparc/kernel/etrap_32.S50
-rw-r--r--arch/sparc/kernel/head_32.S639
-rw-r--r--arch/sparc/kernel/head_64.S2
-rw-r--r--arch/sparc/kernel/idprom.c19
-rw-r--r--arch/sparc/kernel/ioport.c23
-rw-r--r--arch/sparc/kernel/irq.h60
-rw-r--r--arch/sparc/kernel/irq_32.c19
-rw-r--r--arch/sparc/kernel/irq_64.c2
-rw-r--r--arch/sparc/kernel/kernel.h10
-rw-r--r--arch/sparc/kernel/leon_kernel.c98
-rw-r--r--arch/sparc/kernel/leon_smp.c113
-rw-r--r--arch/sparc/kernel/module.c21
-rw-r--r--arch/sparc/kernel/muldiv.c238
-rw-r--r--arch/sparc/kernel/of_device_32.c4
-rw-r--r--arch/sparc/kernel/pcic.c55
-rw-r--r--arch/sparc/kernel/process_32.c116
-rw-r--r--arch/sparc/kernel/rtrap_32.S76
-rw-r--r--arch/sparc/kernel/rtrap_64.S12
-rw-r--r--arch/sparc/kernel/setup_32.c70
-rw-r--r--arch/sparc/kernel/signal_32.c7
-rw-r--r--arch/sparc/kernel/smp_32.c175
-rw-r--r--arch/sparc/kernel/sparc_ksyms_32.c14
-rw-r--r--arch/sparc/kernel/sun4c_irq.c264
-rw-r--r--arch/sparc/kernel/sun4d_irq.c48
-rw-r--r--arch/sparc/kernel/sun4d_smp.c119
-rw-r--r--arch/sparc/kernel/sun4m_irq.c58
-rw-r--r--arch/sparc/kernel/sun4m_smp.c117
-rw-r--r--arch/sparc/kernel/sys_sparc_32.c11
-rw-r--r--arch/sparc/kernel/time_32.c220
-rw-r--r--arch/sparc/kernel/trampoline_32.S22
-rw-r--r--arch/sparc/kernel/traps_32.c2
-rw-r--r--arch/sparc/kernel/ttable_32.S417
-rw-r--r--arch/sparc/kernel/ttable_64.S (renamed from arch/sparc/kernel/ttable.S)0
-rw-r--r--arch/sparc/kernel/unaligned_64.c1
-rw-r--r--arch/sparc/kernel/wof.S72
-rw-r--r--arch/sparc/kernel/wuf.S60
41 files changed, 1088 insertions, 2600 deletions
diff --git a/arch/sparc/kernel/Makefile b/arch/sparc/kernel/Makefile
index cb85458f89d2..c19dd022b9cb 100644
--- a/arch/sparc/kernel/Makefile
+++ b/arch/sparc/kernel/Makefile
@@ -28,7 +28,7 @@ obj-y += traps_$(BITS).o
28 28
29# IRQ 29# IRQ
30obj-y += irq_$(BITS).o 30obj-y += irq_$(BITS).o
31obj-$(CONFIG_SPARC32) += sun4m_irq.o sun4c_irq.o sun4d_irq.o 31obj-$(CONFIG_SPARC32) += sun4m_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
@@ -46,7 +46,6 @@ obj-$(CONFIG_SPARC32) += tadpole.o
46obj-y += ptrace_$(BITS).o 46obj-y += ptrace_$(BITS).o
47obj-y += unaligned_$(BITS).o 47obj-y += unaligned_$(BITS).o
48obj-y += una_asm_$(BITS).o 48obj-y += una_asm_$(BITS).o
49obj-$(CONFIG_SPARC32) += muldiv.o
50obj-y += prom_common.o 49obj-y += prom_common.o
51obj-y += prom_$(BITS).o 50obj-y += prom_$(BITS).o
52obj-y += of_device_common.o 51obj-y += of_device_common.o
diff --git a/arch/sparc/kernel/auxio_32.c b/arch/sparc/kernel/auxio_32.c
index 56d0f52c3e62..e20cc55fb768 100644
--- a/arch/sparc/kernel/auxio_32.c
+++ b/arch/sparc/kernel/auxio_32.c
@@ -32,7 +32,6 @@ void __init auxio_probe(void)
32 switch (sparc_cpu_model) { 32 switch (sparc_cpu_model) {
33 case sparc_leon: 33 case sparc_leon:
34 case sun4d: 34 case sun4d:
35 case sun4:
36 return; 35 return;
37 default: 36 default:
38 break; 37 break;
@@ -65,9 +64,8 @@ void __init auxio_probe(void)
65 r.start = auxregs[0].phys_addr; 64 r.start = auxregs[0].phys_addr;
66 r.end = auxregs[0].phys_addr + auxregs[0].reg_size - 1; 65 r.end = auxregs[0].phys_addr + auxregs[0].reg_size - 1;
67 auxio_register = of_ioremap(&r, 0, auxregs[0].reg_size, "auxio"); 66 auxio_register = of_ioremap(&r, 0, auxregs[0].reg_size, "auxio");
68 /* Fix the address on sun4m and sun4c. */ 67 /* Fix the address on sun4m. */
69 if((((unsigned long) auxregs[0].phys_addr) & 3) == 3 || 68 if ((((unsigned long) auxregs[0].phys_addr) & 3) == 3)
70 sparc_cpu_model == sun4c)
71 auxio_register += (3 - ((unsigned long)auxio_register & 3)); 69 auxio_register += (3 - ((unsigned long)auxio_register & 3));
72 70
73 set_auxio(AUXIO_LED, 0); 71 set_auxio(AUXIO_LED, 0);
@@ -86,12 +84,7 @@ void set_auxio(unsigned char bits_on, unsigned char bits_off)
86 unsigned char regval; 84 unsigned char regval;
87 unsigned long flags; 85 unsigned long flags;
88 spin_lock_irqsave(&auxio_lock, flags); 86 spin_lock_irqsave(&auxio_lock, flags);
89 switch(sparc_cpu_model) { 87 switch (sparc_cpu_model) {
90 case sun4c:
91 regval = sbus_readb(auxio_register);
92 sbus_writeb(((regval | bits_on) & ~bits_off) | AUXIO_ORMEIN,
93 auxio_register);
94 break;
95 case sun4m: 88 case sun4m:
96 if(!auxio_register) 89 if(!auxio_register)
97 break; /* VME chassis sun4m, no auxio. */ 90 break; /* VME chassis sun4m, no auxio. */
diff --git a/arch/sparc/kernel/devices.c b/arch/sparc/kernel/devices.c
index 6b2f56a6f8af..3d465e87f7e2 100644
--- a/arch/sparc/kernel/devices.c
+++ b/arch/sparc/kernel/devices.c
@@ -21,7 +21,6 @@
21#include <asm/cpu_type.h> 21#include <asm/cpu_type.h>
22 22
23extern void clock_stop_probe(void); /* tadpole.c */ 23extern void clock_stop_probe(void); /* tadpole.c */
24extern void sun4c_probe_memerr_reg(void);
25 24
26static char *cpu_mid_prop(void) 25static char *cpu_mid_prop(void)
27{ 26{
@@ -139,7 +138,4 @@ void __init device_scan(void)
139 auxio_power_probe(); 138 auxio_power_probe();
140 } 139 }
141 clock_stop_probe(); 140 clock_stop_probe();
142
143 if (ARCH_SUN4C)
144 sun4c_probe_memerr_reg();
145} 141}
diff --git a/arch/sparc/kernel/ds.c b/arch/sparc/kernel/ds.c
index b93c2c9ccb1d..f09257c86107 100644
--- a/arch/sparc/kernel/ds.c
+++ b/arch/sparc/kernel/ds.c
@@ -868,7 +868,7 @@ void ldom_power_off(void)
868 868
869static void ds_conn_reset(struct ds_info *dp) 869static void ds_conn_reset(struct ds_info *dp)
870{ 870{
871 printk(KERN_ERR "ds-%llu: ds_conn_reset() from %p\n", 871 printk(KERN_ERR "ds-%llu: ds_conn_reset() from %pf\n",
872 dp->id, __builtin_return_address(0)); 872 dp->id, __builtin_return_address(0));
873} 873}
874 874
diff --git a/arch/sparc/kernel/entry.S b/arch/sparc/kernel/entry.S
index f445e98463e6..2dbe1806e530 100644
--- a/arch/sparc/kernel/entry.S
+++ b/arch/sparc/kernel/entry.S
@@ -7,6 +7,7 @@
7 * Copyright (C) 1997 Anton Blanchard (anton@progsoc.uts.edu.au) 7 * Copyright (C) 1997 Anton Blanchard (anton@progsoc.uts.edu.au)
8 */ 8 */
9 9
10#include <linux/linkage.h>
10#include <linux/errno.h> 11#include <linux/errno.h>
11 12
12#include <asm/head.h> 13#include <asm/head.h>
@@ -17,10 +18,8 @@
17#include <asm/asm-offsets.h> 18#include <asm/asm-offsets.h>
18#include <asm/psr.h> 19#include <asm/psr.h>
19#include <asm/vaddrs.h> 20#include <asm/vaddrs.h>
20#include <asm/memreg.h>
21#include <asm/page.h> 21#include <asm/page.h>
22#include <asm/pgtable.h> 22#include <asm/pgtable.h>
23#include <asm/pgtsun4c.h>
24#include <asm/winmacro.h> 23#include <asm/winmacro.h>
25#include <asm/signal.h> 24#include <asm/signal.h>
26#include <asm/obio.h> 25#include <asm/obio.h>
@@ -125,22 +124,11 @@ floppy_tdone:
125 set auxio_register, %l7 124 set auxio_register, %l7
126 ld [%l7], %l7 125 ld [%l7], %l7
127 126
128 set sparc_cpu_model, %l5 127 ldub [%l7], %l5
129 ld [%l5], %l5
130 subcc %l5, 1, %g0 /* enum { sun4c = 1 }; */
131 be 1f
132 ldub [%l7], %l5
133 128
134 or %l5, 0xc2, %l5 129 or %l5, 0xc2, %l5
135 stb %l5, [%l7] 130 stb %l5, [%l7]
136 andn %l5, 0x02, %l5 131 andn %l5, 0x02, %l5
137 b 2f
138 nop
139
1401:
141 or %l5, 0xf4, %l5
142 stb %l5, [%l7]
143 andn %l5, 0x04, %l5
144 132
1452: 1332:
146 /* Kill some time so the bits set */ 134 /* Kill some time so the bits set */
@@ -266,6 +254,11 @@ smp4m_ticker:
266 WRITE_PAUSE 254 WRITE_PAUSE
267 RESTORE_ALL 255 RESTORE_ALL
268 256
257#define GET_PROCESSOR4M_ID(reg) \
258 rd %tbr, %reg; \
259 srl %reg, 12, %reg; \
260 and %reg, 3, %reg;
261
269 /* Here is where we check for possible SMP IPI passed to us 262 /* Here is where we check for possible SMP IPI passed to us
270 * on some level other than 15 which is the NMI and only used 263 * on some level other than 15 which is the NMI and only used
271 * for cross calls. That has a separate entry point below. 264 * for cross calls. That has a separate entry point below.
@@ -328,7 +321,7 @@ linux_trap_ipi15_sun4m:
328 ld [%o5 + %o0], %o5 321 ld [%o5 + %o0], %o5
329 ld [%o5 + 0x00], %o3 ! sun4m_irq_percpu[cpu]->pending 322 ld [%o5 + 0x00], %o3 ! sun4m_irq_percpu[cpu]->pending
330 andcc %o3, %o2, %g0 323 andcc %o3, %o2, %g0
331 be 1f ! Must be an NMI async memory error 324 be sun4m_nmi_error ! Must be an NMI async memory error
332 st %o2, [%o5 + 0x04] ! sun4m_irq_percpu[cpu]->clear=0x80000000 325 st %o2, [%o5 + 0x04] ! sun4m_irq_percpu[cpu]->clear=0x80000000
333 WRITE_PAUSE 326 WRITE_PAUSE
334 ld [%o5 + 0x00], %g0 ! sun4m_irq_percpu[cpu]->pending 327 ld [%o5 + 0x00], %g0 ! sun4m_irq_percpu[cpu]->pending
@@ -342,27 +335,6 @@ linux_trap_ipi15_sun4m:
342 nop 335 nop
343 b ret_trap_lockless_ipi 336 b ret_trap_lockless_ipi
344 clr %l6 337 clr %l6
3451:
346 /* NMI async memory error handling. */
347 sethi %hi(0x80000000), %l4
348 sethi %hi(sun4m_irq_global), %o5
349 ld [%o5 + %lo(sun4m_irq_global)], %l5
350 st %l4, [%l5 + 0x0c] ! sun4m_irq_global->mask_set=0x80000000
351 WRITE_PAUSE
352 ld [%l5 + 0x00], %g0 ! sun4m_irq_global->pending
353 WRITE_PAUSE
354 or %l0, PSR_PIL, %l4
355 wr %l4, 0x0, %psr
356 WRITE_PAUSE
357 wr %l4, PSR_ET, %psr
358 WRITE_PAUSE
359 call sun4m_nmi
360 nop
361 st %l4, [%l5 + 0x08] ! sun4m_irq_global->mask_clear=0x80000000
362 WRITE_PAUSE
363 ld [%l5 + 0x00], %g0 ! sun4m_irq_global->pending
364 WRITE_PAUSE
365 RESTORE_ALL
366 338
367 .globl smp4d_ticker 339 .globl smp4d_ticker
368 /* SMP per-cpu ticker interrupts are handled specially. */ 340 /* SMP per-cpu ticker interrupts are handled specially. */
@@ -760,326 +732,37 @@ setcc_trap_handler:
760 jmp %l2 ! advance over trap instruction 732 jmp %l2 ! advance over trap instruction
761 rett %l2 + 0x4 ! like this... 733 rett %l2 + 0x4 ! like this...
762 734
763 .align 4 735sun4m_nmi_error:
764 .globl linux_trap_nmi_sun4c 736 /* NMI async memory error handling. */
765linux_trap_nmi_sun4c: 737 sethi %hi(0x80000000), %l4
766 SAVE_ALL 738 sethi %hi(sun4m_irq_global), %o5
767 739 ld [%o5 + %lo(sun4m_irq_global)], %l5
768 /* Ugh, we need to clear the IRQ line. This is now 740 st %l4, [%l5 + 0x0c] ! sun4m_irq_global->mask_set=0x80000000
769 * a very sun4c specific trap handler...
770 */
771 sethi %hi(interrupt_enable), %l5
772 ld [%l5 + %lo(interrupt_enable)], %l5
773 ldub [%l5], %l6
774 andn %l6, INTS_ENAB, %l6
775 stb %l6, [%l5]
776
777 /* Now it is safe to re-enable traps without recursion. */
778 or %l0, PSR_PIL, %l0
779 wr %l0, PSR_ET, %psr
780 WRITE_PAUSE 741 WRITE_PAUSE
781 742 ld [%l5 + 0x00], %g0 ! sun4m_irq_global->pending
782 /* Now call the c-code with the pt_regs frame ptr and the
783 * memory error registers as arguments. The ordering chosen
784 * here is due to unlatching semantics.
785 */
786 sethi %hi(AC_SYNC_ERR), %o0
787 add %o0, 0x4, %o0
788 lda [%o0] ASI_CONTROL, %o2 ! sync vaddr
789 sub %o0, 0x4, %o0
790 lda [%o0] ASI_CONTROL, %o1 ! sync error
791 add %o0, 0xc, %o0
792 lda [%o0] ASI_CONTROL, %o4 ! async vaddr
793 sub %o0, 0x4, %o0
794 lda [%o0] ASI_CONTROL, %o3 ! async error
795 call sparc_lvl15_nmi
796 add %sp, STACKFRAME_SZ, %o0
797
798 RESTORE_ALL
799
800 .align 4
801 .globl invalid_segment_patch1_ff
802 .globl invalid_segment_patch2_ff
803invalid_segment_patch1_ff: cmp %l4, 0xff
804invalid_segment_patch2_ff: mov 0xff, %l3
805
806 .align 4
807 .globl invalid_segment_patch1_1ff
808 .globl invalid_segment_patch2_1ff
809invalid_segment_patch1_1ff: cmp %l4, 0x1ff
810invalid_segment_patch2_1ff: mov 0x1ff, %l3
811
812 .align 4
813 .globl num_context_patch1_16, num_context_patch2_16
814num_context_patch1_16: mov 0x10, %l7
815num_context_patch2_16: mov 0x10, %l7
816
817 .align 4
818 .globl vac_linesize_patch_32
819vac_linesize_patch_32: subcc %l7, 32, %l7
820
821 .align 4
822 .globl vac_hwflush_patch1_on, vac_hwflush_patch2_on
823
824/*
825 * Ugly, but we can't use hardware flushing on the sun4 and we'd require
826 * two instructions (Anton)
827 */
828vac_hwflush_patch1_on: addcc %l7, -PAGE_SIZE, %l7
829
830vac_hwflush_patch2_on: sta %g0, [%l3 + %l7] ASI_HWFLUSHSEG
831
832 .globl invalid_segment_patch1, invalid_segment_patch2
833 .globl num_context_patch1
834 .globl vac_linesize_patch, vac_hwflush_patch1
835 .globl vac_hwflush_patch2
836
837 .align 4
838 .globl sun4c_fault
839
840! %l0 = %psr
841! %l1 = %pc
842! %l2 = %npc
843! %l3 = %wim
844! %l7 = 1 for textfault
845! We want error in %l5, vaddr in %l6
846sun4c_fault:
847 sethi %hi(AC_SYNC_ERR), %l4
848 add %l4, 0x4, %l6 ! AC_SYNC_VA in %l6
849 lda [%l6] ASI_CONTROL, %l5 ! Address
850 lda [%l4] ASI_CONTROL, %l6 ! Error, retained for a bit
851
852 andn %l5, 0xfff, %l5 ! Encode all info into l7
853 srl %l6, 14, %l4
854
855 and %l4, 2, %l4
856 or %l5, %l4, %l4
857
858 or %l4, %l7, %l7 ! l7 = [addr,write,txtfault]
859
860 andcc %l0, PSR_PS, %g0
861 be sun4c_fault_fromuser
862 andcc %l7, 1, %g0 ! Text fault?
863
864 be 1f
865 sethi %hi(KERNBASE), %l4
866
867 mov %l1, %l5 ! PC
868
8691:
870 cmp %l5, %l4
871 blu sun4c_fault_fromuser
872 sethi %hi(~((1 << SUN4C_REAL_PGDIR_SHIFT) - 1)), %l4
873
874 /* If the kernel references a bum kernel pointer, or a pte which
875 * points to a non existent page in ram, we will run this code
876 * _forever_ and lock up the machine!!!!! So we must check for
877 * this condition, the AC_SYNC_ERR bits are what we must examine.
878 * Also a parity error would make this happen as well. So we just
879 * check that we are in fact servicing a tlb miss and not some
880 * other type of fault for the kernel.
881 */
882 andcc %l6, 0x80, %g0
883 be sun4c_fault_fromuser
884 and %l5, %l4, %l5
885
886 /* Test for NULL pte_t * in vmalloc area. */
887 sethi %hi(VMALLOC_START), %l4
888 cmp %l5, %l4
889 blu,a invalid_segment_patch1
890 lduXa [%l5] ASI_SEGMAP, %l4
891
892 sethi %hi(swapper_pg_dir), %l4
893 srl %l5, SUN4C_PGDIR_SHIFT, %l6
894 or %l4, %lo(swapper_pg_dir), %l4
895 sll %l6, 2, %l6
896 ld [%l4 + %l6], %l4
897 andcc %l4, PAGE_MASK, %g0
898 be sun4c_fault_fromuser
899 lduXa [%l5] ASI_SEGMAP, %l4
900
901invalid_segment_patch1:
902 cmp %l4, 0x7f
903 bne 1f
904 sethi %hi(sun4c_kfree_ring), %l4
905 or %l4, %lo(sun4c_kfree_ring), %l4
906 ld [%l4 + 0x18], %l3
907 deccc %l3 ! do we have a free entry?
908 bcs,a 2f ! no, unmap one.
909 sethi %hi(sun4c_kernel_ring), %l4
910
911 st %l3, [%l4 + 0x18] ! sun4c_kfree_ring.num_entries--
912
913 ld [%l4 + 0x00], %l6 ! entry = sun4c_kfree_ring.ringhd.next
914 st %l5, [%l6 + 0x08] ! entry->vaddr = address
915
916 ld [%l6 + 0x00], %l3 ! next = entry->next
917 ld [%l6 + 0x04], %l7 ! entry->prev
918
919 st %l7, [%l3 + 0x04] ! next->prev = entry->prev
920 st %l3, [%l7 + 0x00] ! entry->prev->next = next
921
922 sethi %hi(sun4c_kernel_ring), %l4
923 or %l4, %lo(sun4c_kernel_ring), %l4
924 ! head = &sun4c_kernel_ring.ringhd
925
926 ld [%l4 + 0x00], %l7 ! head->next
927
928 st %l4, [%l6 + 0x04] ! entry->prev = head
929 st %l7, [%l6 + 0x00] ! entry->next = head->next
930 st %l6, [%l7 + 0x04] ! head->next->prev = entry
931
932 st %l6, [%l4 + 0x00] ! head->next = entry
933
934 ld [%l4 + 0x18], %l3
935 inc %l3 ! sun4c_kernel_ring.num_entries++
936 st %l3, [%l4 + 0x18]
937 b 4f
938 ld [%l6 + 0x08], %l5
939
9402:
941 or %l4, %lo(sun4c_kernel_ring), %l4
942 ! head = &sun4c_kernel_ring.ringhd
943
944 ld [%l4 + 0x04], %l6 ! entry = head->prev
945
946 ld [%l6 + 0x08], %l3 ! tmp = entry->vaddr
947
948 ! Flush segment from the cache.
949 sethi %hi((64 * 1024)), %l7
9509:
951vac_hwflush_patch1:
952vac_linesize_patch:
953 subcc %l7, 16, %l7
954 bne 9b
955vac_hwflush_patch2:
956 sta %g0, [%l3 + %l7] ASI_FLUSHSEG
957
958 st %l5, [%l6 + 0x08] ! entry->vaddr = address
959
960 ld [%l6 + 0x00], %l5 ! next = entry->next
961 ld [%l6 + 0x04], %l7 ! entry->prev
962
963 st %l7, [%l5 + 0x04] ! next->prev = entry->prev
964 st %l5, [%l7 + 0x00] ! entry->prev->next = next
965 st %l4, [%l6 + 0x04] ! entry->prev = head
966
967 ld [%l4 + 0x00], %l7 ! head->next
968
969 st %l7, [%l6 + 0x00] ! entry->next = head->next
970 st %l6, [%l7 + 0x04] ! head->next->prev = entry
971 st %l6, [%l4 + 0x00] ! head->next = entry
972
973 mov %l3, %l5 ! address = tmp
974
9754:
976num_context_patch1:
977 mov 0x08, %l7
978
979 ld [%l6 + 0x08], %l4
980 ldub [%l6 + 0x0c], %l3
981 or %l4, %l3, %l4 ! encode new vaddr/pseg into l4
982
983 sethi %hi(AC_CONTEXT), %l3
984 lduba [%l3] ASI_CONTROL, %l6
985
986 /* Invalidate old mapping, instantiate new mapping,
987 * for each context. Registers l6/l7 are live across
988 * this loop.
989 */
9903: deccc %l7
991 sethi %hi(AC_CONTEXT), %l3
992 stba %l7, [%l3] ASI_CONTROL
993invalid_segment_patch2:
994 mov 0x7f, %l3
995 stXa %l3, [%l5] ASI_SEGMAP
996 andn %l4, 0x1ff, %l3
997 bne 3b
998 stXa %l4, [%l3] ASI_SEGMAP
999
1000 sethi %hi(AC_CONTEXT), %l3
1001 stba %l6, [%l3] ASI_CONTROL
1002
1003 andn %l4, 0x1ff, %l5
1004
10051:
1006 sethi %hi(VMALLOC_START), %l4
1007 cmp %l5, %l4
1008
1009 bgeu 1f
1010 mov 1 << (SUN4C_REAL_PGDIR_SHIFT - PAGE_SHIFT), %l7
1011
1012 sethi %hi(KERNBASE), %l6
1013
1014 sub %l5, %l6, %l4
1015 srl %l4, PAGE_SHIFT, %l4
1016 sethi %hi((SUN4C_PAGE_KERNEL & 0xf4000000)), %l3
1017 or %l3, %l4, %l3
1018
1019 sethi %hi(PAGE_SIZE), %l4
1020
10212:
1022 sta %l3, [%l5] ASI_PTE
1023 deccc %l7
1024 inc %l3
1025 bne 2b
1026 add %l5, %l4, %l5
1027
1028 b 7f
1029 sethi %hi(sun4c_kernel_faults), %l4
1030
10311:
1032 srl %l5, SUN4C_PGDIR_SHIFT, %l3
1033 sethi %hi(swapper_pg_dir), %l4
1034 or %l4, %lo(swapper_pg_dir), %l4
1035 sll %l3, 2, %l3
1036 ld [%l4 + %l3], %l4
1037 and %l4, PAGE_MASK, %l4
1038
1039 srl %l5, (PAGE_SHIFT - 2), %l6
1040 and %l6, ((SUN4C_PTRS_PER_PTE - 1) << 2), %l6
1041 add %l6, %l4, %l6
1042
1043 sethi %hi(PAGE_SIZE), %l4
1044
10452:
1046 ld [%l6], %l3
1047 deccc %l7
1048 sta %l3, [%l5] ASI_PTE
1049 add %l6, 0x4, %l6
1050 bne 2b
1051 add %l5, %l4, %l5
1052
1053 sethi %hi(sun4c_kernel_faults), %l4
10547:
1055 ld [%l4 + %lo(sun4c_kernel_faults)], %l3
1056 inc %l3
1057 st %l3, [%l4 + %lo(sun4c_kernel_faults)]
1058
1059 /* Restore condition codes */
1060 wr %l0, 0x0, %psr
1061 WRITE_PAUSE 743 WRITE_PAUSE
1062 jmp %l1 744 or %l0, PSR_PIL, %l4
1063 rett %l2 745 wr %l4, 0x0, %psr
1064 746 WRITE_PAUSE
1065sun4c_fault_fromuser: 747 wr %l4, PSR_ET, %psr
1066 SAVE_ALL 748 WRITE_PAUSE
749 call sun4m_nmi
1067 nop 750 nop
1068 751 st %l4, [%l5 + 0x08] ! sun4m_irq_global->mask_clear=0x80000000
1069 mov %l7, %o1 ! Decode the info from %l7
1070 mov %l7, %o2
1071 and %o1, 1, %o1 ! arg2 = text_faultp
1072 mov %l7, %o3
1073 and %o2, 2, %o2 ! arg3 = writep
1074 andn %o3, 0xfff, %o3 ! arg4 = faulting address
1075
1076 wr %l0, PSR_ET, %psr
1077 WRITE_PAUSE 752 WRITE_PAUSE
753 ld [%l5 + 0x00], %g0 ! sun4m_irq_global->pending
754 WRITE_PAUSE
755 RESTORE_ALL
1078 756
1079 call do_sun4c_fault 757#ifndef CONFIG_SMP
1080 add %sp, STACKFRAME_SZ, %o0 ! arg1 = pt_regs ptr 758 .align 4
759 .globl linux_trap_ipi15_sun4m
760linux_trap_ipi15_sun4m:
761 SAVE_ALL
1081 762
1082 RESTORE_ALL 763 ba sun4m_nmi_error
764 nop
765#endif /* CONFIG_SMP */
1083 766
1084 .align 4 767 .align 4
1085 .globl srmmu_fault 768 .globl srmmu_fault
@@ -1483,11 +1166,13 @@ fpload:
1483 .globl __ndelay 1166 .globl __ndelay
1484__ndelay: 1167__ndelay:
1485 save %sp, -STACKFRAME_SZ, %sp 1168 save %sp, -STACKFRAME_SZ, %sp
1486 mov %i0, %o0 1169 mov %i0, %o0 ! round multiplier up so large ns ok
1487 call .umul ! round multiplier up so large ns ok 1170 mov 0x1ae, %o1 ! 2**32 / (1 000 000 000 / HZ)
1488 mov 0x1ae, %o1 ! 2**32 / (1 000 000 000 / HZ) 1171 umul %o0, %o1, %o0
1489 call .umul 1172 rd %y, %o1
1490 mov %i1, %o1 ! udelay_val 1173 mov %i1, %o1 ! udelay_val
1174 umul %o0, %o1, %o0
1175 rd %y, %o1
1491 ba delay_continue 1176 ba delay_continue
1492 mov %o1, %o0 ! >>32 later for better resolution 1177 mov %o1, %o0 ! >>32 later for better resolution
1493 1178
@@ -1496,18 +1181,21 @@ __udelay:
1496 save %sp, -STACKFRAME_SZ, %sp 1181 save %sp, -STACKFRAME_SZ, %sp
1497 mov %i0, %o0 1182 mov %i0, %o0
1498 sethi %hi(0x10c7), %o1 ! round multiplier up so large us ok 1183 sethi %hi(0x10c7), %o1 ! round multiplier up so large us ok
1499 call .umul 1184 or %o1, %lo(0x10c7), %o1 ! 2**32 / 1 000 000
1500 or %o1, %lo(0x10c7), %o1 ! 2**32 / 1 000 000 1185 umul %o0, %o1, %o0
1501 call .umul 1186 rd %y, %o1
1502 mov %i1, %o1 ! udelay_val 1187 mov %i1, %o1 ! udelay_val
1188 umul %o0, %o1, %o0
1189 rd %y, %o1
1503 sethi %hi(0x028f4b62), %l0 ! Add in rounding constant * 2**32, 1190 sethi %hi(0x028f4b62), %l0 ! Add in rounding constant * 2**32,
1504 or %g0, %lo(0x028f4b62), %l0 1191 or %g0, %lo(0x028f4b62), %l0
1505 addcc %o0, %l0, %o0 ! 2**32 * 0.009 999 1192 addcc %o0, %l0, %o0 ! 2**32 * 0.009 999
1506 bcs,a 3f 1193 bcs,a 3f
1507 add %o1, 0x01, %o1 1194 add %o1, 0x01, %o1
15083: 11953:
1509 call .umul 1196 mov HZ, %o0 ! >>32 earlier for wider range
1510 mov HZ, %o0 ! >>32 earlier for wider range 1197 umul %o0, %o1, %o0
1198 rd %y, %o1
1511 1199
1512delay_continue: 1200delay_continue:
1513 cmp %o0, 0x0 1201 cmp %o0, 0x0
@@ -1670,4 +1358,26 @@ flushw_all:
1670 ret 1358 ret
1671 restore 1359 restore
1672 1360
1361#ifdef CONFIG_SMP
1362ENTRY(hard_smp_processor_id)
1363661: rd %tbr, %g1
1364 srl %g1, 12, %o0
1365 and %o0, 3, %o0
1366 .section .cpuid_patch, "ax"
1367 /* Instruction location. */
1368 .word 661b
1369 /* SUN4D implementation. */
1370 lda [%g0] ASI_M_VIKING_TMP1, %o0
1371 nop
1372 nop
1373 /* LEON implementation. */
1374 rd %asr17, %o0
1375 srl %o0, 0x1c, %o0
1376 nop
1377 .previous
1378 retl
1379 nop
1380ENDPROC(hard_smp_processor_id)
1381#endif
1382
1673/* End of entry.S */ 1383/* End of entry.S */
diff --git a/arch/sparc/kernel/etrap_32.S b/arch/sparc/kernel/etrap_32.S
index e806fcdc46db..84b5f0d2afde 100644
--- a/arch/sparc/kernel/etrap_32.S
+++ b/arch/sparc/kernel/etrap_32.S
@@ -216,9 +216,7 @@ tsetup_patch6:
216 /* Call MMU-architecture dependent stack checking 216 /* Call MMU-architecture dependent stack checking
217 * routine. 217 * routine.
218 */ 218 */
219 .globl tsetup_mmu_patchme 219 b tsetup_srmmu_stackchk
220tsetup_mmu_patchme:
221 b tsetup_sun4c_stackchk
222 andcc %sp, 0x7, %g0 220 andcc %sp, 0x7, %g0
223 221
224 /* Architecture specific stack checking routines. When either 222 /* Architecture specific stack checking routines. When either
@@ -228,52 +226,6 @@ tsetup_mmu_patchme:
228 */ 226 */
229#define glob_tmp g1 227#define glob_tmp g1
230 228
231tsetup_sun4c_stackchk:
232 /* Done by caller: andcc %sp, 0x7, %g0 */
233 bne trap_setup_user_stack_is_bolixed
234 sra %sp, 29, %glob_tmp
235
236 add %glob_tmp, 0x1, %glob_tmp
237 andncc %glob_tmp, 0x1, %g0
238 bne trap_setup_user_stack_is_bolixed
239 and %sp, 0xfff, %glob_tmp ! delay slot
240
241 /* See if our dump area will be on more than one
242 * page.
243 */
244 add %glob_tmp, 0x38, %glob_tmp
245 andncc %glob_tmp, 0xff8, %g0
246 be tsetup_sun4c_onepage ! only one page to check
247 lda [%sp] ASI_PTE, %glob_tmp ! have to check first page anyways
248
249tsetup_sun4c_twopages:
250 /* Is first page ok permission wise? */
251 srl %glob_tmp, 29, %glob_tmp
252 cmp %glob_tmp, 0x6
253 bne trap_setup_user_stack_is_bolixed
254 add %sp, 0x38, %glob_tmp /* Is second page in vma hole? */
255
256 sra %glob_tmp, 29, %glob_tmp
257 add %glob_tmp, 0x1, %glob_tmp
258 andncc %glob_tmp, 0x1, %g0
259 bne trap_setup_user_stack_is_bolixed
260 add %sp, 0x38, %glob_tmp
261
262 lda [%glob_tmp] ASI_PTE, %glob_tmp
263
264tsetup_sun4c_onepage:
265 srl %glob_tmp, 29, %glob_tmp
266 cmp %glob_tmp, 0x6 ! can user write to it?
267 bne trap_setup_user_stack_is_bolixed ! failure
268 nop
269
270 STORE_WINDOW(sp)
271
272 restore %g0, %g0, %g0
273
274 jmpl %t_retpc + 0x8, %g0
275 mov %t_kstack, %sp
276
277 .globl tsetup_srmmu_stackchk 229 .globl tsetup_srmmu_stackchk
278tsetup_srmmu_stackchk: 230tsetup_srmmu_stackchk:
279 /* Check results of callers andcc %sp, 0x7, %g0 */ 231 /* Check results of callers andcc %sp, 0x7, %g0 */
diff --git a/arch/sparc/kernel/head_32.S b/arch/sparc/kernel/head_32.S
index 587785759838..a0f5c20e4b9c 100644
--- a/arch/sparc/kernel/head_32.S
+++ b/arch/sparc/kernel/head_32.S
@@ -26,11 +26,9 @@
26#include <asm/pgtsrmmu.h> /* SRMMU_PGDIR_SHIFT */ 26#include <asm/pgtsrmmu.h> /* SRMMU_PGDIR_SHIFT */
27 27
28 .data 28 .data
29/* 29/* The following are used with the prom_vector node-ops to figure out
30 * The following are used with the prom_vector node-ops to figure out 30 * the cpu-type
31 * the cpu-type
32 */ 31 */
33
34 .align 4 32 .align 4
35cputyp: 33cputyp:
36 .word 1 34 .word 1
@@ -38,384 +36,35 @@ cputyp:
38 .align 4 36 .align 4
39 .globl cputypval 37 .globl cputypval
40cputypval: 38cputypval:
41 .asciz "sun4c" 39 .asciz "sun4m"
42 .ascii " " 40 .ascii " "
43 41
44cputypvalend: 42/* Tested on SS-5, SS-10 */
45cputypvallen = cputypvar - cputypval
46
47 .align 4 43 .align 4
48/*
49 * Sun people can't spell worth damn. "compatability" indeed.
50 * At least we *know* we can't spell, and use a spell-checker.
51 */
52
53/* Uh, actually Linus it is I who cannot spell. Too much murky
54 * Sparc assembly will do this to ya.
55 */
56cputypvar: 44cputypvar:
57 .asciz "compatability"
58
59/* Tested on SS-5, SS-10. Probably someone at Sun applied a spell-checker. */
60 .align 4
61cputypvar_sun4m:
62 .asciz "compatible" 45 .asciz "compatible"
63 46
64 .align 4 47 .align 4
65 48
66sun4_notsup: 49sun4c_notsup:
67 .asciz "Sparc-Linux sun4 support does no longer exist.\n\n" 50 .asciz "Sparc-Linux sun4/sun4c support does no longer exist.\n\n"
68 .align 4 51 .align 4
69 52
70sun4e_notsup: 53sun4e_notsup:
71 .asciz "Sparc-Linux sun4e support does not exist\n\n" 54 .asciz "Sparc-Linux sun4e support does not exist\n\n"
72 .align 4 55 .align 4
73 56
74 /* The Sparc trap table, bootloader gives us control at _start. */ 57/* The trap-table - located in the __HEAD section */
75 __HEAD 58#include "ttable_32.S"
76 .globl _stext, _start, __stext
77 .globl trapbase
78_start: /* danger danger */
79__stext:
80_stext:
81trapbase:
82#ifdef CONFIG_SMP
83trapbase_cpu0:
84#endif
85/* We get control passed to us here at t_zero. */
86t_zero: b gokernel; nop; nop; nop;
87t_tflt: SPARC_TFAULT /* Inst. Access Exception */
88t_bins: TRAP_ENTRY(0x2, bad_instruction) /* Illegal Instruction */
89t_pins: TRAP_ENTRY(0x3, priv_instruction) /* Privileged Instruction */
90t_fpd: TRAP_ENTRY(0x4, fpd_trap_handler) /* Floating Point Disabled */
91t_wovf: WINDOW_SPILL /* Window Overflow */
92t_wunf: WINDOW_FILL /* Window Underflow */
93t_mna: TRAP_ENTRY(0x7, mna_handler) /* Memory Address Not Aligned */
94t_fpe: TRAP_ENTRY(0x8, fpe_trap_handler) /* Floating Point Exception */
95t_dflt: SPARC_DFAULT /* Data Miss Exception */
96t_tio: TRAP_ENTRY(0xa, do_tag_overflow) /* Tagged Instruction Ovrflw */
97t_wpt: TRAP_ENTRY(0xb, do_watchpoint) /* Watchpoint Detected */
98t_badc: BAD_TRAP(0xc) BAD_TRAP(0xd) BAD_TRAP(0xe) BAD_TRAP(0xf) BAD_TRAP(0x10)
99t_irq1: TRAP_ENTRY_INTERRUPT(1) /* IRQ Software/SBUS Level 1 */
100t_irq2: TRAP_ENTRY_INTERRUPT(2) /* IRQ SBUS Level 2 */
101t_irq3: TRAP_ENTRY_INTERRUPT(3) /* IRQ SCSI/DMA/SBUS Level 3 */
102t_irq4: TRAP_ENTRY_INTERRUPT(4) /* IRQ Software Level 4 */
103t_irq5: TRAP_ENTRY_INTERRUPT(5) /* IRQ SBUS/Ethernet Level 5 */
104t_irq6: TRAP_ENTRY_INTERRUPT(6) /* IRQ Software Level 6 */
105t_irq7: TRAP_ENTRY_INTERRUPT(7) /* IRQ Video/SBUS Level 5 */
106t_irq8: TRAP_ENTRY_INTERRUPT(8) /* IRQ SBUS Level 6 */
107t_irq9: TRAP_ENTRY_INTERRUPT(9) /* IRQ SBUS Level 7 */
108t_irq10:TRAP_ENTRY_INTERRUPT(10) /* IRQ Timer #1 (one we use) */
109t_irq11:TRAP_ENTRY_INTERRUPT(11) /* IRQ Floppy Intr. */
110t_irq12:TRAP_ENTRY_INTERRUPT(12) /* IRQ Zilog serial chip */
111t_irq13:TRAP_ENTRY_INTERRUPT(13) /* IRQ Audio Intr. */
112t_irq14:TRAP_ENTRY_INTERRUPT(14) /* IRQ Timer #2 */
113 .globl t_nmi
114#ifndef CONFIG_SMP
115t_nmi: NMI_TRAP /* Level 15 (NMI) */
116#else
117t_nmi: TRAP_ENTRY(0x1f, linux_trap_ipi15_sun4m)
118#endif
119t_racc: TRAP_ENTRY(0x20, do_reg_access) /* General Register Access Error */
120t_iacce:BAD_TRAP(0x21) /* Instr Access Error */
121t_bad22:BAD_TRAP(0x22) BAD_TRAP(0x23)
122t_cpdis:TRAP_ENTRY(0x24, do_cp_disabled) /* Co-Processor Disabled */
123t_uflsh:SKIP_TRAP(0x25, unimp_flush) /* Unimplemented FLUSH inst. */
124t_bad26:BAD_TRAP(0x26) BAD_TRAP(0x27)
125t_cpexc:TRAP_ENTRY(0x28, do_cp_exception) /* Co-Processor Exception */
126t_dacce:SPARC_DFAULT /* Data Access Error */
127t_hwdz: TRAP_ENTRY(0x2a, do_hw_divzero) /* Division by zero, you lose... */
128t_dserr:BAD_TRAP(0x2b) /* Data Store Error */
129t_daccm:BAD_TRAP(0x2c) /* Data Access MMU-Miss */
130t_bad2d:BAD_TRAP(0x2d) BAD_TRAP(0x2e) BAD_TRAP(0x2f) BAD_TRAP(0x30) BAD_TRAP(0x31)
131t_bad32:BAD_TRAP(0x32) BAD_TRAP(0x33) BAD_TRAP(0x34) BAD_TRAP(0x35) BAD_TRAP(0x36)
132t_bad37:BAD_TRAP(0x37) BAD_TRAP(0x38) BAD_TRAP(0x39) BAD_TRAP(0x3a) BAD_TRAP(0x3b)
133t_iaccm:BAD_TRAP(0x3c) /* Instr Access MMU-Miss */
134t_bad3d:BAD_TRAP(0x3d) BAD_TRAP(0x3e) BAD_TRAP(0x3f) BAD_TRAP(0x40) BAD_TRAP(0x41)
135t_bad42:BAD_TRAP(0x42) BAD_TRAP(0x43) BAD_TRAP(0x44) BAD_TRAP(0x45) BAD_TRAP(0x46)
136t_bad47:BAD_TRAP(0x47) BAD_TRAP(0x48) BAD_TRAP(0x49) BAD_TRAP(0x4a) BAD_TRAP(0x4b)
137t_bad4c:BAD_TRAP(0x4c) BAD_TRAP(0x4d) BAD_TRAP(0x4e) BAD_TRAP(0x4f) BAD_TRAP(0x50)
138t_bad51:BAD_TRAP(0x51) BAD_TRAP(0x52) BAD_TRAP(0x53) BAD_TRAP(0x54) BAD_TRAP(0x55)
139t_bad56:BAD_TRAP(0x56) BAD_TRAP(0x57) BAD_TRAP(0x58) BAD_TRAP(0x59) BAD_TRAP(0x5a)
140t_bad5b:BAD_TRAP(0x5b) BAD_TRAP(0x5c) BAD_TRAP(0x5d) BAD_TRAP(0x5e) BAD_TRAP(0x5f)
141t_bad60:BAD_TRAP(0x60) BAD_TRAP(0x61) BAD_TRAP(0x62) BAD_TRAP(0x63) BAD_TRAP(0x64)
142t_bad65:BAD_TRAP(0x65) BAD_TRAP(0x66) BAD_TRAP(0x67) BAD_TRAP(0x68) BAD_TRAP(0x69)
143t_bad6a:BAD_TRAP(0x6a) BAD_TRAP(0x6b) BAD_TRAP(0x6c) BAD_TRAP(0x6d) BAD_TRAP(0x6e)
144t_bad6f:BAD_TRAP(0x6f) BAD_TRAP(0x70) BAD_TRAP(0x71) BAD_TRAP(0x72) BAD_TRAP(0x73)
145t_bad74:BAD_TRAP(0x74) BAD_TRAP(0x75) BAD_TRAP(0x76) BAD_TRAP(0x77) BAD_TRAP(0x78)
146t_bad79:BAD_TRAP(0x79) BAD_TRAP(0x7a) BAD_TRAP(0x7b) BAD_TRAP(0x7c) BAD_TRAP(0x7d)
147t_bad7e:BAD_TRAP(0x7e) BAD_TRAP(0x7f)
148t_bad80:BAD_TRAP(0x80) /* SunOS System Call */
149t_sbkpt:BREAKPOINT_TRAP /* Software Breakpoint/KGDB */
150t_divz: TRAP_ENTRY(0x82, do_hw_divzero) /* Divide by zero trap */
151t_flwin:TRAP_ENTRY(0x83, do_flush_windows) /* Flush Windows Trap */
152t_clwin:BAD_TRAP(0x84) /* Clean Windows Trap */
153t_rchk: BAD_TRAP(0x85) /* Range Check */
154t_funal:BAD_TRAP(0x86) /* Fix Unaligned Access Trap */
155t_iovf: BAD_TRAP(0x87) /* Integer Overflow Trap */
156t_bad88:BAD_TRAP(0x88) /* Slowaris System Call */
157t_bad89:BAD_TRAP(0x89) /* Net-B.S. System Call */
158t_bad8a:BAD_TRAP(0x8a) BAD_TRAP(0x8b) BAD_TRAP(0x8c) BAD_TRAP(0x8d) BAD_TRAP(0x8e)
159t_bad8f:BAD_TRAP(0x8f)
160t_linux:LINUX_SYSCALL_TRAP /* Linux System Call */
161t_bad91:BAD_TRAP(0x91) BAD_TRAP(0x92) BAD_TRAP(0x93) BAD_TRAP(0x94) BAD_TRAP(0x95)
162t_bad96:BAD_TRAP(0x96) BAD_TRAP(0x97) BAD_TRAP(0x98) BAD_TRAP(0x99) BAD_TRAP(0x9a)
163t_bad9b:BAD_TRAP(0x9b) BAD_TRAP(0x9c) BAD_TRAP(0x9d) BAD_TRAP(0x9e) BAD_TRAP(0x9f)
164t_getcc:GETCC_TRAP /* Get Condition Codes */
165t_setcc:SETCC_TRAP /* Set Condition Codes */
166t_getpsr:GETPSR_TRAP /* Get PSR Register */
167t_bada3:BAD_TRAP(0xa3) BAD_TRAP(0xa4) BAD_TRAP(0xa5) BAD_TRAP(0xa6)
168t_bada7:BAD_TRAP(0xa7)
169t_bada8:BAD_TRAP(0xa8) BAD_TRAP(0xa9) BAD_TRAP(0xaa) BAD_TRAP(0xab)
170t_badac:BAD_TRAP(0xac) BAD_TRAP(0xad) BAD_TRAP(0xae) BAD_TRAP(0xaf) BAD_TRAP(0xb0)
171t_badb1:BAD_TRAP(0xb1) BAD_TRAP(0xb2) BAD_TRAP(0xb3) BAD_TRAP(0xb4) BAD_TRAP(0xb5)
172t_badb6:BAD_TRAP(0xb6) BAD_TRAP(0xb7) BAD_TRAP(0xb8) BAD_TRAP(0xb9) BAD_TRAP(0xba)
173t_badbb:BAD_TRAP(0xbb) BAD_TRAP(0xbc) BAD_TRAP(0xbd) BAD_TRAP(0xbe) BAD_TRAP(0xbf)
174t_badc0:BAD_TRAP(0xc0) BAD_TRAP(0xc1) BAD_TRAP(0xc2) BAD_TRAP(0xc3) BAD_TRAP(0xc4)
175t_badc5:BAD_TRAP(0xc5) BAD_TRAP(0xc6) BAD_TRAP(0xc7) BAD_TRAP(0xc8) BAD_TRAP(0xc9)
176t_badca:BAD_TRAP(0xca) BAD_TRAP(0xcb) BAD_TRAP(0xcc) BAD_TRAP(0xcd) BAD_TRAP(0xce)
177t_badcf:BAD_TRAP(0xcf) BAD_TRAP(0xd0) BAD_TRAP(0xd1) BAD_TRAP(0xd2) BAD_TRAP(0xd3)
178t_badd4:BAD_TRAP(0xd4) BAD_TRAP(0xd5) BAD_TRAP(0xd6) BAD_TRAP(0xd7) BAD_TRAP(0xd8)
179t_badd9:BAD_TRAP(0xd9) BAD_TRAP(0xda) BAD_TRAP(0xdb) BAD_TRAP(0xdc) BAD_TRAP(0xdd)
180t_badde:BAD_TRAP(0xde) BAD_TRAP(0xdf) BAD_TRAP(0xe0) BAD_TRAP(0xe1) BAD_TRAP(0xe2)
181t_bade3:BAD_TRAP(0xe3) BAD_TRAP(0xe4) BAD_TRAP(0xe5) BAD_TRAP(0xe6) BAD_TRAP(0xe7)
182t_bade8:BAD_TRAP(0xe8) BAD_TRAP(0xe9) BAD_TRAP(0xea) BAD_TRAP(0xeb) BAD_TRAP(0xec)
183t_baded:BAD_TRAP(0xed) BAD_TRAP(0xee) BAD_TRAP(0xef) BAD_TRAP(0xf0) BAD_TRAP(0xf1)
184t_badf2:BAD_TRAP(0xf2) BAD_TRAP(0xf3) BAD_TRAP(0xf4) BAD_TRAP(0xf5) BAD_TRAP(0xf6)
185t_badf7:BAD_TRAP(0xf7) BAD_TRAP(0xf8) BAD_TRAP(0xf9) BAD_TRAP(0xfa) BAD_TRAP(0xfb)
186t_badfc:BAD_TRAP(0xfc)
187t_kgdb: KGDB_TRAP(0xfd)
188dbtrap: BAD_TRAP(0xfe) /* Debugger/PROM breakpoint #1 */
189dbtrap2:BAD_TRAP(0xff) /* Debugger/PROM breakpoint #2 */
190
191 .globl end_traptable
192end_traptable:
193
194#ifdef CONFIG_SMP
195 /* Trap tables for the other cpus. */
196 .globl trapbase_cpu1, trapbase_cpu2, trapbase_cpu3
197trapbase_cpu1:
198 BAD_TRAP(0x0) SRMMU_TFAULT TRAP_ENTRY(0x2, bad_instruction)
199 TRAP_ENTRY(0x3, priv_instruction) TRAP_ENTRY(0x4, fpd_trap_handler)
200 WINDOW_SPILL WINDOW_FILL TRAP_ENTRY(0x7, mna_handler)
201 TRAP_ENTRY(0x8, fpe_trap_handler) SRMMU_DFAULT
202 TRAP_ENTRY(0xa, do_tag_overflow) TRAP_ENTRY(0xb, do_watchpoint)
203 BAD_TRAP(0xc) BAD_TRAP(0xd) BAD_TRAP(0xe) BAD_TRAP(0xf) BAD_TRAP(0x10)
204 TRAP_ENTRY_INTERRUPT(1) TRAP_ENTRY_INTERRUPT(2)
205 TRAP_ENTRY_INTERRUPT(3) TRAP_ENTRY_INTERRUPT(4)
206 TRAP_ENTRY_INTERRUPT(5) TRAP_ENTRY_INTERRUPT(6)
207 TRAP_ENTRY_INTERRUPT(7) TRAP_ENTRY_INTERRUPT(8)
208 TRAP_ENTRY_INTERRUPT(9) TRAP_ENTRY_INTERRUPT(10)
209 TRAP_ENTRY_INTERRUPT(11) TRAP_ENTRY_INTERRUPT(12)
210 TRAP_ENTRY_INTERRUPT(13) TRAP_ENTRY_INTERRUPT(14)
211 TRAP_ENTRY(0x1f, linux_trap_ipi15_sun4m)
212 TRAP_ENTRY(0x20, do_reg_access) BAD_TRAP(0x21) BAD_TRAP(0x22)
213 BAD_TRAP(0x23) TRAP_ENTRY(0x24, do_cp_disabled) SKIP_TRAP(0x25, unimp_flush)
214 BAD_TRAP(0x26) BAD_TRAP(0x27) TRAP_ENTRY(0x28, do_cp_exception)
215 SRMMU_DFAULT TRAP_ENTRY(0x2a, do_hw_divzero) BAD_TRAP(0x2b) BAD_TRAP(0x2c)
216 BAD_TRAP(0x2d) BAD_TRAP(0x2e) BAD_TRAP(0x2f) BAD_TRAP(0x30) BAD_TRAP(0x31)
217 BAD_TRAP(0x32) BAD_TRAP(0x33) BAD_TRAP(0x34) BAD_TRAP(0x35) BAD_TRAP(0x36)
218 BAD_TRAP(0x37) BAD_TRAP(0x38) BAD_TRAP(0x39) BAD_TRAP(0x3a) BAD_TRAP(0x3b)
219 BAD_TRAP(0x3c) BAD_TRAP(0x3d) BAD_TRAP(0x3e) BAD_TRAP(0x3f) BAD_TRAP(0x40)
220 BAD_TRAP(0x41) BAD_TRAP(0x42) BAD_TRAP(0x43) BAD_TRAP(0x44) BAD_TRAP(0x45)
221 BAD_TRAP(0x46) BAD_TRAP(0x47) BAD_TRAP(0x48) BAD_TRAP(0x49) BAD_TRAP(0x4a)
222 BAD_TRAP(0x4b) BAD_TRAP(0x4c) BAD_TRAP(0x4d) BAD_TRAP(0x4e) BAD_TRAP(0x4f)
223 BAD_TRAP(0x50)
224 BAD_TRAP(0x51) BAD_TRAP(0x52) BAD_TRAP(0x53) BAD_TRAP(0x54) BAD_TRAP(0x55)
225 BAD_TRAP(0x56) BAD_TRAP(0x57) BAD_TRAP(0x58) BAD_TRAP(0x59) BAD_TRAP(0x5a)
226 BAD_TRAP(0x5b) BAD_TRAP(0x5c) BAD_TRAP(0x5d) BAD_TRAP(0x5e) BAD_TRAP(0x5f)
227 BAD_TRAP(0x60) BAD_TRAP(0x61) BAD_TRAP(0x62) BAD_TRAP(0x63) BAD_TRAP(0x64)
228 BAD_TRAP(0x65) BAD_TRAP(0x66) BAD_TRAP(0x67) BAD_TRAP(0x68) BAD_TRAP(0x69)
229 BAD_TRAP(0x6a) BAD_TRAP(0x6b) BAD_TRAP(0x6c) BAD_TRAP(0x6d) BAD_TRAP(0x6e)
230 BAD_TRAP(0x6f) BAD_TRAP(0x70) BAD_TRAP(0x71) BAD_TRAP(0x72) BAD_TRAP(0x73)
231 BAD_TRAP(0x74) BAD_TRAP(0x75) BAD_TRAP(0x76) BAD_TRAP(0x77) BAD_TRAP(0x78)
232 BAD_TRAP(0x79) BAD_TRAP(0x7a) BAD_TRAP(0x7b) BAD_TRAP(0x7c) BAD_TRAP(0x7d)
233 BAD_TRAP(0x7e) BAD_TRAP(0x7f)
234 BAD_TRAP(0x80)
235 BREAKPOINT_TRAP
236 TRAP_ENTRY(0x82, do_hw_divzero)
237 TRAP_ENTRY(0x83, do_flush_windows) BAD_TRAP(0x84) BAD_TRAP(0x85)
238 BAD_TRAP(0x86) BAD_TRAP(0x87) BAD_TRAP(0x88)
239 BAD_TRAP(0x89) BAD_TRAP(0x8a) BAD_TRAP(0x8b) BAD_TRAP(0x8c)
240 BAD_TRAP(0x8d) BAD_TRAP(0x8e) BAD_TRAP(0x8f)
241 LINUX_SYSCALL_TRAP BAD_TRAP(0x91) BAD_TRAP(0x92) BAD_TRAP(0x93) BAD_TRAP(0x94)
242 BAD_TRAP(0x95) BAD_TRAP(0x96) BAD_TRAP(0x97) BAD_TRAP(0x98) BAD_TRAP(0x99)
243 BAD_TRAP(0x9a) BAD_TRAP(0x9b) BAD_TRAP(0x9c) BAD_TRAP(0x9d) BAD_TRAP(0x9e)
244 BAD_TRAP(0x9f) GETCC_TRAP SETCC_TRAP GETPSR_TRAP
245 BAD_TRAP(0xa3) BAD_TRAP(0xa4) BAD_TRAP(0xa5) BAD_TRAP(0xa6)
246 BAD_TRAP(0xa7) BAD_TRAP(0xa8) BAD_TRAP(0xa9) BAD_TRAP(0xaa) BAD_TRAP(0xab)
247 BAD_TRAP(0xac) BAD_TRAP(0xad) BAD_TRAP(0xae) BAD_TRAP(0xaf) BAD_TRAP(0xb0)
248 BAD_TRAP(0xb1) BAD_TRAP(0xb2) BAD_TRAP(0xb3) BAD_TRAP(0xb4) BAD_TRAP(0xb5)
249 BAD_TRAP(0xb6) BAD_TRAP(0xb7) BAD_TRAP(0xb8) BAD_TRAP(0xb9) BAD_TRAP(0xba)
250 BAD_TRAP(0xbb) BAD_TRAP(0xbc) BAD_TRAP(0xbd) BAD_TRAP(0xbe) BAD_TRAP(0xbf)
251 BAD_TRAP(0xc0) BAD_TRAP(0xc1) BAD_TRAP(0xc2) BAD_TRAP(0xc3) BAD_TRAP(0xc4)
252 BAD_TRAP(0xc5) BAD_TRAP(0xc6) BAD_TRAP(0xc7) BAD_TRAP(0xc8) BAD_TRAP(0xc9)
253 BAD_TRAP(0xca) BAD_TRAP(0xcb) BAD_TRAP(0xcc) BAD_TRAP(0xcd) BAD_TRAP(0xce)
254 BAD_TRAP(0xcf) BAD_TRAP(0xd0) BAD_TRAP(0xd1) BAD_TRAP(0xd2) BAD_TRAP(0xd3)
255 BAD_TRAP(0xd4) BAD_TRAP(0xd5) BAD_TRAP(0xd6) BAD_TRAP(0xd7) BAD_TRAP(0xd8)
256 BAD_TRAP(0xd9) BAD_TRAP(0xda) BAD_TRAP(0xdb) BAD_TRAP(0xdc) BAD_TRAP(0xdd)
257 BAD_TRAP(0xde) BAD_TRAP(0xdf) BAD_TRAP(0xe0) BAD_TRAP(0xe1) BAD_TRAP(0xe2)
258 BAD_TRAP(0xe3) BAD_TRAP(0xe4) BAD_TRAP(0xe5) BAD_TRAP(0xe6) BAD_TRAP(0xe7)
259 BAD_TRAP(0xe8) BAD_TRAP(0xe9) BAD_TRAP(0xea) BAD_TRAP(0xeb) BAD_TRAP(0xec)
260 BAD_TRAP(0xed) BAD_TRAP(0xee) BAD_TRAP(0xef) BAD_TRAP(0xf0) BAD_TRAP(0xf1)
261 BAD_TRAP(0xf2) BAD_TRAP(0xf3) BAD_TRAP(0xf4) BAD_TRAP(0xf5) BAD_TRAP(0xf6)
262 BAD_TRAP(0xf7) BAD_TRAP(0xf8) BAD_TRAP(0xf9) BAD_TRAP(0xfa) BAD_TRAP(0xfb)
263 BAD_TRAP(0xfc) KGDB_TRAP(0xfd) BAD_TRAP(0xfe) BAD_TRAP(0xff)
264
265trapbase_cpu2:
266 BAD_TRAP(0x0) SRMMU_TFAULT TRAP_ENTRY(0x2, bad_instruction)
267 TRAP_ENTRY(0x3, priv_instruction) TRAP_ENTRY(0x4, fpd_trap_handler)
268 WINDOW_SPILL WINDOW_FILL TRAP_ENTRY(0x7, mna_handler)
269 TRAP_ENTRY(0x8, fpe_trap_handler) SRMMU_DFAULT
270 TRAP_ENTRY(0xa, do_tag_overflow) TRAP_ENTRY(0xb, do_watchpoint)
271 BAD_TRAP(0xc) BAD_TRAP(0xd) BAD_TRAP(0xe) BAD_TRAP(0xf) BAD_TRAP(0x10)
272 TRAP_ENTRY_INTERRUPT(1) TRAP_ENTRY_INTERRUPT(2)
273 TRAP_ENTRY_INTERRUPT(3) TRAP_ENTRY_INTERRUPT(4)
274 TRAP_ENTRY_INTERRUPT(5) TRAP_ENTRY_INTERRUPT(6)
275 TRAP_ENTRY_INTERRUPT(7) TRAP_ENTRY_INTERRUPT(8)
276 TRAP_ENTRY_INTERRUPT(9) TRAP_ENTRY_INTERRUPT(10)
277 TRAP_ENTRY_INTERRUPT(11) TRAP_ENTRY_INTERRUPT(12)
278 TRAP_ENTRY_INTERRUPT(13) TRAP_ENTRY_INTERRUPT(14)
279 TRAP_ENTRY(0x1f, linux_trap_ipi15_sun4m)
280 TRAP_ENTRY(0x20, do_reg_access) BAD_TRAP(0x21) BAD_TRAP(0x22)
281 BAD_TRAP(0x23) TRAP_ENTRY(0x24, do_cp_disabled) SKIP_TRAP(0x25, unimp_flush)
282 BAD_TRAP(0x26) BAD_TRAP(0x27) TRAP_ENTRY(0x28, do_cp_exception)
283 SRMMU_DFAULT TRAP_ENTRY(0x2a, do_hw_divzero) BAD_TRAP(0x2b) BAD_TRAP(0x2c)
284 BAD_TRAP(0x2d) BAD_TRAP(0x2e) BAD_TRAP(0x2f) BAD_TRAP(0x30) BAD_TRAP(0x31)
285 BAD_TRAP(0x32) BAD_TRAP(0x33) BAD_TRAP(0x34) BAD_TRAP(0x35) BAD_TRAP(0x36)
286 BAD_TRAP(0x37) BAD_TRAP(0x38) BAD_TRAP(0x39) BAD_TRAP(0x3a) BAD_TRAP(0x3b)
287 BAD_TRAP(0x3c) BAD_TRAP(0x3d) BAD_TRAP(0x3e) BAD_TRAP(0x3f) BAD_TRAP(0x40)
288 BAD_TRAP(0x41) BAD_TRAP(0x42) BAD_TRAP(0x43) BAD_TRAP(0x44) BAD_TRAP(0x45)
289 BAD_TRAP(0x46) BAD_TRAP(0x47) BAD_TRAP(0x48) BAD_TRAP(0x49) BAD_TRAP(0x4a)
290 BAD_TRAP(0x4b) BAD_TRAP(0x4c) BAD_TRAP(0x4d) BAD_TRAP(0x4e) BAD_TRAP(0x4f)
291 BAD_TRAP(0x50)
292 BAD_TRAP(0x51) BAD_TRAP(0x52) BAD_TRAP(0x53) BAD_TRAP(0x54) BAD_TRAP(0x55)
293 BAD_TRAP(0x56) BAD_TRAP(0x57) BAD_TRAP(0x58) BAD_TRAP(0x59) BAD_TRAP(0x5a)
294 BAD_TRAP(0x5b) BAD_TRAP(0x5c) BAD_TRAP(0x5d) BAD_TRAP(0x5e) BAD_TRAP(0x5f)
295 BAD_TRAP(0x60) BAD_TRAP(0x61) BAD_TRAP(0x62) BAD_TRAP(0x63) BAD_TRAP(0x64)
296 BAD_TRAP(0x65) BAD_TRAP(0x66) BAD_TRAP(0x67) BAD_TRAP(0x68) BAD_TRAP(0x69)
297 BAD_TRAP(0x6a) BAD_TRAP(0x6b) BAD_TRAP(0x6c) BAD_TRAP(0x6d) BAD_TRAP(0x6e)
298 BAD_TRAP(0x6f) BAD_TRAP(0x70) BAD_TRAP(0x71) BAD_TRAP(0x72) BAD_TRAP(0x73)
299 BAD_TRAP(0x74) BAD_TRAP(0x75) BAD_TRAP(0x76) BAD_TRAP(0x77) BAD_TRAP(0x78)
300 BAD_TRAP(0x79) BAD_TRAP(0x7a) BAD_TRAP(0x7b) BAD_TRAP(0x7c) BAD_TRAP(0x7d)
301 BAD_TRAP(0x7e) BAD_TRAP(0x7f)
302 BAD_TRAP(0x80)
303 BREAKPOINT_TRAP
304 TRAP_ENTRY(0x82, do_hw_divzero)
305 TRAP_ENTRY(0x83, do_flush_windows) BAD_TRAP(0x84) BAD_TRAP(0x85)
306 BAD_TRAP(0x86) BAD_TRAP(0x87) BAD_TRAP(0x88)
307 BAD_TRAP(0x89) BAD_TRAP(0x8a) BAD_TRAP(0x8b) BAD_TRAP(0x8c)
308 BAD_TRAP(0x8d) BAD_TRAP(0x8e) BAD_TRAP(0x8f)
309 LINUX_SYSCALL_TRAP BAD_TRAP(0x91) BAD_TRAP(0x92) BAD_TRAP(0x93) BAD_TRAP(0x94)
310 BAD_TRAP(0x95) BAD_TRAP(0x96) BAD_TRAP(0x97) BAD_TRAP(0x98) BAD_TRAP(0x99)
311 BAD_TRAP(0x9a) BAD_TRAP(0x9b) BAD_TRAP(0x9c) BAD_TRAP(0x9d) BAD_TRAP(0x9e)
312 BAD_TRAP(0x9f) GETCC_TRAP SETCC_TRAP GETPSR_TRAP
313 BAD_TRAP(0xa3) BAD_TRAP(0xa4) BAD_TRAP(0xa5) BAD_TRAP(0xa6)
314 BAD_TRAP(0xa7) BAD_TRAP(0xa8) BAD_TRAP(0xa9) BAD_TRAP(0xaa) BAD_TRAP(0xab)
315 BAD_TRAP(0xac) BAD_TRAP(0xad) BAD_TRAP(0xae) BAD_TRAP(0xaf) BAD_TRAP(0xb0)
316 BAD_TRAP(0xb1) BAD_TRAP(0xb2) BAD_TRAP(0xb3) BAD_TRAP(0xb4) BAD_TRAP(0xb5)
317 BAD_TRAP(0xb6) BAD_TRAP(0xb7) BAD_TRAP(0xb8) BAD_TRAP(0xb9) BAD_TRAP(0xba)
318 BAD_TRAP(0xbb) BAD_TRAP(0xbc) BAD_TRAP(0xbd) BAD_TRAP(0xbe) BAD_TRAP(0xbf)
319 BAD_TRAP(0xc0) BAD_TRAP(0xc1) BAD_TRAP(0xc2) BAD_TRAP(0xc3) BAD_TRAP(0xc4)
320 BAD_TRAP(0xc5) BAD_TRAP(0xc6) BAD_TRAP(0xc7) BAD_TRAP(0xc8) BAD_TRAP(0xc9)
321 BAD_TRAP(0xca) BAD_TRAP(0xcb) BAD_TRAP(0xcc) BAD_TRAP(0xcd) BAD_TRAP(0xce)
322 BAD_TRAP(0xcf) BAD_TRAP(0xd0) BAD_TRAP(0xd1) BAD_TRAP(0xd2) BAD_TRAP(0xd3)
323 BAD_TRAP(0xd4) BAD_TRAP(0xd5) BAD_TRAP(0xd6) BAD_TRAP(0xd7) BAD_TRAP(0xd8)
324 BAD_TRAP(0xd9) BAD_TRAP(0xda) BAD_TRAP(0xdb) BAD_TRAP(0xdc) BAD_TRAP(0xdd)
325 BAD_TRAP(0xde) BAD_TRAP(0xdf) BAD_TRAP(0xe0) BAD_TRAP(0xe1) BAD_TRAP(0xe2)
326 BAD_TRAP(0xe3) BAD_TRAP(0xe4) BAD_TRAP(0xe5) BAD_TRAP(0xe6) BAD_TRAP(0xe7)
327 BAD_TRAP(0xe8) BAD_TRAP(0xe9) BAD_TRAP(0xea) BAD_TRAP(0xeb) BAD_TRAP(0xec)
328 BAD_TRAP(0xed) BAD_TRAP(0xee) BAD_TRAP(0xef) BAD_TRAP(0xf0) BAD_TRAP(0xf1)
329 BAD_TRAP(0xf2) BAD_TRAP(0xf3) BAD_TRAP(0xf4) BAD_TRAP(0xf5) BAD_TRAP(0xf6)
330 BAD_TRAP(0xf7) BAD_TRAP(0xf8) BAD_TRAP(0xf9) BAD_TRAP(0xfa) BAD_TRAP(0xfb)
331 BAD_TRAP(0xfc) KGDB_TRAP(0xfd) BAD_TRAP(0xfe) BAD_TRAP(0xff)
332
333trapbase_cpu3:
334 BAD_TRAP(0x0) SRMMU_TFAULT TRAP_ENTRY(0x2, bad_instruction)
335 TRAP_ENTRY(0x3, priv_instruction) TRAP_ENTRY(0x4, fpd_trap_handler)
336 WINDOW_SPILL WINDOW_FILL TRAP_ENTRY(0x7, mna_handler)
337 TRAP_ENTRY(0x8, fpe_trap_handler) SRMMU_DFAULT
338 TRAP_ENTRY(0xa, do_tag_overflow) TRAP_ENTRY(0xb, do_watchpoint)
339 BAD_TRAP(0xc) BAD_TRAP(0xd) BAD_TRAP(0xe) BAD_TRAP(0xf) BAD_TRAP(0x10)
340 TRAP_ENTRY_INTERRUPT(1) TRAP_ENTRY_INTERRUPT(2)
341 TRAP_ENTRY_INTERRUPT(3) TRAP_ENTRY_INTERRUPT(4)
342 TRAP_ENTRY_INTERRUPT(5) TRAP_ENTRY_INTERRUPT(6)
343 TRAP_ENTRY_INTERRUPT(7) TRAP_ENTRY_INTERRUPT(8)
344 TRAP_ENTRY_INTERRUPT(9) TRAP_ENTRY_INTERRUPT(10)
345 TRAP_ENTRY_INTERRUPT(11) TRAP_ENTRY_INTERRUPT(12)
346 TRAP_ENTRY_INTERRUPT(13) TRAP_ENTRY_INTERRUPT(14)
347 TRAP_ENTRY(0x1f, linux_trap_ipi15_sun4m)
348 TRAP_ENTRY(0x20, do_reg_access) BAD_TRAP(0x21) BAD_TRAP(0x22)
349 BAD_TRAP(0x23) TRAP_ENTRY(0x24, do_cp_disabled) SKIP_TRAP(0x25, unimp_flush)
350 BAD_TRAP(0x26) BAD_TRAP(0x27) TRAP_ENTRY(0x28, do_cp_exception)
351 SRMMU_DFAULT TRAP_ENTRY(0x2a, do_hw_divzero) BAD_TRAP(0x2b) BAD_TRAP(0x2c)
352 BAD_TRAP(0x2d) BAD_TRAP(0x2e) BAD_TRAP(0x2f) BAD_TRAP(0x30) BAD_TRAP(0x31)
353 BAD_TRAP(0x32) BAD_TRAP(0x33) BAD_TRAP(0x34) BAD_TRAP(0x35) BAD_TRAP(0x36)
354 BAD_TRAP(0x37) BAD_TRAP(0x38) BAD_TRAP(0x39) BAD_TRAP(0x3a) BAD_TRAP(0x3b)
355 BAD_TRAP(0x3c) BAD_TRAP(0x3d) BAD_TRAP(0x3e) BAD_TRAP(0x3f) BAD_TRAP(0x40)
356 BAD_TRAP(0x41) BAD_TRAP(0x42) BAD_TRAP(0x43) BAD_TRAP(0x44) BAD_TRAP(0x45)
357 BAD_TRAP(0x46) BAD_TRAP(0x47) BAD_TRAP(0x48) BAD_TRAP(0x49) BAD_TRAP(0x4a)
358 BAD_TRAP(0x4b) BAD_TRAP(0x4c) BAD_TRAP(0x4d) BAD_TRAP(0x4e) BAD_TRAP(0x4f)
359 BAD_TRAP(0x50)
360 BAD_TRAP(0x51) BAD_TRAP(0x52) BAD_TRAP(0x53) BAD_TRAP(0x54) BAD_TRAP(0x55)
361 BAD_TRAP(0x56) BAD_TRAP(0x57) BAD_TRAP(0x58) BAD_TRAP(0x59) BAD_TRAP(0x5a)
362 BAD_TRAP(0x5b) BAD_TRAP(0x5c) BAD_TRAP(0x5d) BAD_TRAP(0x5e) BAD_TRAP(0x5f)
363 BAD_TRAP(0x60) BAD_TRAP(0x61) BAD_TRAP(0x62) BAD_TRAP(0x63) BAD_TRAP(0x64)
364 BAD_TRAP(0x65) BAD_TRAP(0x66) BAD_TRAP(0x67) BAD_TRAP(0x68) BAD_TRAP(0x69)
365 BAD_TRAP(0x6a) BAD_TRAP(0x6b) BAD_TRAP(0x6c) BAD_TRAP(0x6d) BAD_TRAP(0x6e)
366 BAD_TRAP(0x6f) BAD_TRAP(0x70) BAD_TRAP(0x71) BAD_TRAP(0x72) BAD_TRAP(0x73)
367 BAD_TRAP(0x74) BAD_TRAP(0x75) BAD_TRAP(0x76) BAD_TRAP(0x77) BAD_TRAP(0x78)
368 BAD_TRAP(0x79) BAD_TRAP(0x7a) BAD_TRAP(0x7b) BAD_TRAP(0x7c) BAD_TRAP(0x7d)
369 BAD_TRAP(0x7e) BAD_TRAP(0x7f)
370 BAD_TRAP(0x80)
371 BREAKPOINT_TRAP
372 TRAP_ENTRY(0x82, do_hw_divzero)
373 TRAP_ENTRY(0x83, do_flush_windows) BAD_TRAP(0x84) BAD_TRAP(0x85)
374 BAD_TRAP(0x86) BAD_TRAP(0x87) BAD_TRAP(0x88)
375 BAD_TRAP(0x89) BAD_TRAP(0x8a) BAD_TRAP(0x8b) BAD_TRAP(0x8c)
376 BAD_TRAP(0x8d) BAD_TRAP(0x8e) BAD_TRAP(0x8f)
377 LINUX_SYSCALL_TRAP BAD_TRAP(0x91) BAD_TRAP(0x92) BAD_TRAP(0x93) BAD_TRAP(0x94)
378 BAD_TRAP(0x95) BAD_TRAP(0x96) BAD_TRAP(0x97) BAD_TRAP(0x98) BAD_TRAP(0x99)
379 BAD_TRAP(0x9a) BAD_TRAP(0x9b) BAD_TRAP(0x9c) BAD_TRAP(0x9d) BAD_TRAP(0x9e)
380 BAD_TRAP(0x9f) GETCC_TRAP SETCC_TRAP GETPSR_TRAP
381 BAD_TRAP(0xa3) BAD_TRAP(0xa4) BAD_TRAP(0xa5) BAD_TRAP(0xa6)
382 BAD_TRAP(0xa7) BAD_TRAP(0xa8) BAD_TRAP(0xa9) BAD_TRAP(0xaa) BAD_TRAP(0xab)
383 BAD_TRAP(0xac) BAD_TRAP(0xad) BAD_TRAP(0xae) BAD_TRAP(0xaf) BAD_TRAP(0xb0)
384 BAD_TRAP(0xb1) BAD_TRAP(0xb2) BAD_TRAP(0xb3) BAD_TRAP(0xb4) BAD_TRAP(0xb5)
385 BAD_TRAP(0xb6) BAD_TRAP(0xb7) BAD_TRAP(0xb8) BAD_TRAP(0xb9) BAD_TRAP(0xba)
386 BAD_TRAP(0xbb) BAD_TRAP(0xbc) BAD_TRAP(0xbd) BAD_TRAP(0xbe) BAD_TRAP(0xbf)
387 BAD_TRAP(0xc0) BAD_TRAP(0xc1) BAD_TRAP(0xc2) BAD_TRAP(0xc3) BAD_TRAP(0xc4)
388 BAD_TRAP(0xc5) BAD_TRAP(0xc6) BAD_TRAP(0xc7) BAD_TRAP(0xc8) BAD_TRAP(0xc9)
389 BAD_TRAP(0xca) BAD_TRAP(0xcb) BAD_TRAP(0xcc) BAD_TRAP(0xcd) BAD_TRAP(0xce)
390 BAD_TRAP(0xcf) BAD_TRAP(0xd0) BAD_TRAP(0xd1) BAD_TRAP(0xd2) BAD_TRAP(0xd3)
391 BAD_TRAP(0xd4) BAD_TRAP(0xd5) BAD_TRAP(0xd6) BAD_TRAP(0xd7) BAD_TRAP(0xd8)
392 BAD_TRAP(0xd9) BAD_TRAP(0xda) BAD_TRAP(0xdb) BAD_TRAP(0xdc) BAD_TRAP(0xdd)
393 BAD_TRAP(0xde) BAD_TRAP(0xdf) BAD_TRAP(0xe0) BAD_TRAP(0xe1) BAD_TRAP(0xe2)
394 BAD_TRAP(0xe3) BAD_TRAP(0xe4) BAD_TRAP(0xe5) BAD_TRAP(0xe6) BAD_TRAP(0xe7)
395 BAD_TRAP(0xe8) BAD_TRAP(0xe9) BAD_TRAP(0xea) BAD_TRAP(0xeb) BAD_TRAP(0xec)
396 BAD_TRAP(0xed) BAD_TRAP(0xee) BAD_TRAP(0xef) BAD_TRAP(0xf0) BAD_TRAP(0xf1)
397 BAD_TRAP(0xf2) BAD_TRAP(0xf3) BAD_TRAP(0xf4) BAD_TRAP(0xf5) BAD_TRAP(0xf6)
398 BAD_TRAP(0xf7) BAD_TRAP(0xf8) BAD_TRAP(0xf9) BAD_TRAP(0xfa) BAD_TRAP(0xfb)
399 BAD_TRAP(0xfc) KGDB_TRAP(0xfd) BAD_TRAP(0xfe) BAD_TRAP(0xff)
400 59
401#endif
402 .align PAGE_SIZE 60 .align PAGE_SIZE
403 61
404/* This was the only reasonable way I could think of to properly align 62/* This was the only reasonable way I could think of to properly align
405 * these page-table data structures. 63 * these page-table data structures.
406 */ 64 */
407 .globl pg0, pg1, pg2, pg3
408 .globl empty_bad_page
409 .globl empty_bad_page_table
410 .globl empty_zero_page
411 .globl swapper_pg_dir 65 .globl swapper_pg_dir
412swapper_pg_dir: .skip PAGE_SIZE 66swapper_pg_dir: .skip PAGE_SIZE
413pg0: .skip PAGE_SIZE 67 .globl empty_zero_page
414pg1: .skip PAGE_SIZE
415pg2: .skip PAGE_SIZE
416pg3: .skip PAGE_SIZE
417empty_bad_page: .skip PAGE_SIZE
418empty_bad_page_table: .skip PAGE_SIZE
419empty_zero_page: .skip PAGE_SIZE 68empty_zero_page: .skip PAGE_SIZE
420 69
421 .global root_flags 70 .global root_flags
@@ -523,10 +172,10 @@ copy_prom_lvl14:
523 ldd [%g2 + 0x8], %g4 172 ldd [%g2 + 0x8], %g4
524 std %g4, [%g3 + 0x8] ! Copy proms handler 173 std %g4, [%g3 + 0x8] ! Copy proms handler
525 174
526/* Must determine whether we are on a sun4c MMU, SRMMU, or SUN4/400 MUTANT 175/* DON'T TOUCH %l0 thru %l5 in these remapping routines,
527 * MMU so we can remap ourselves properly. DON'T TOUCH %l0 thru %l5 in these 176 * we need their values afterwards!
528 * remapping routines, we need their values afterwards!
529 */ 177 */
178
530 /* Now check whether we are already mapped, if we 179 /* Now check whether we are already mapped, if we
531 * are we can skip all this garbage coming up. 180 * are we can skip all this garbage coming up.
532 */ 181 */
@@ -535,26 +184,29 @@ copy_prom_done:
535 be go_to_highmem ! this will be a nop then 184 be go_to_highmem ! this will be a nop then
536 nop 185 nop
537 186
538 set LOAD_ADDR, %g6 187 /* Validate that we are in fact running on an
188 * SRMMU based cpu.
189 */
190 set 0x4000, %g6
539 cmp %g7, %g6 191 cmp %g7, %g6
540 bne remap_not_a_sun4 ! This is not a Sun4 192 bne not_a_sun4
541 nop 193 nop
542 194
543 or %g0, 0x1, %g1 195halt_sun4_or_sun4c:
544 lduba [%g1] ASI_CONTROL, %g1 ! Only safe to try on Sun4. 196 ld [%g7 + 0x68], %o1
545 subcc %g1, 0x24, %g0 ! Is this a mutant Sun4/400??? 197 set sun4c_notsup, %o0
546 be sun4_mutant_remap ! Ugh, it is... 198 sub %o0, %l6, %o0
199 call %o1
547 nop 200 nop
548 201 ba halt_me
549 b sun4_normal_remap ! regular sun4, 2 level mmu
550 nop 202 nop
551 203
552remap_not_a_sun4: 204not_a_sun4:
553 lda [%g0] ASI_M_MMUREGS, %g1 ! same as ASI_PTE on sun4c 205 lda [%g0] ASI_M_MMUREGS, %g1
554 and %g1, 0x1, %g1 ! Test SRMMU Enable bit ;-) 206 andcc %g1, 1, %g0
555 cmp %g1, 0x0 207 be halt_sun4_or_sun4c
556 be sun4c_remap ! A sun4c MMU or normal Sun4
557 nop 208 nop
209
558srmmu_remap: 210srmmu_remap:
559 /* First, check for a viking (TI) module. */ 211 /* First, check for a viking (TI) module. */
560 set 0x40000000, %g2 212 set 0x40000000, %g2
@@ -660,72 +312,6 @@ srmmu_nviking:
660 b go_to_highmem 312 b go_to_highmem
661 nop ! wheee.... 313 nop ! wheee....
662 314
663 /* This remaps the kernel on Sun4/4xx machines
664 * that have the Sun Mutant Three Level MMU.
665 * It's like a platypus, Sun didn't have the
666 * SRMMU in conception so they kludged the three
667 * level logic in the regular Sun4 MMU probably.
668 *
669 * Basically, you take each entry in the top level
670 * directory that maps the low 3MB starting at
671 * address zero and put the mapping in the KERNBASE
672 * slots. These top level pgd's are called regmaps.
673 */
674sun4_mutant_remap:
675 or %g0, %g0, %g3 ! source base
676 sethi %hi(KERNBASE), %g4 ! destination base
677 or %g4, %lo(KERNBASE), %g4
678 sethi %hi(0x300000), %g5
679 or %g5, %lo(0x300000), %g5 ! upper bound 3MB
680 or %g0, 0x1, %l6
681 sll %l6, 24, %l6 ! Regmap mapping size
682 add %g3, 0x2, %g3 ! Base magic
683 add %g4, 0x2, %g4 ! Base magic
684
685 /* Main remapping loop on Sun4-Mutant-MMU.
686 * "I am not an animal..." -Famous Mutant Person
687 */
688sun4_mutant_loop:
689 lduha [%g3] ASI_REGMAP, %g2 ! Get lower entry
690 stha %g2, [%g4] ASI_REGMAP ! Store in high entry
691 add %g4, %l6, %g4 ! Move up high memory ptr
692 subcc %g3, %g5, %g0 ! Reached our limit?
693 blu sun4_mutant_loop ! Nope, loop again
694 add %g3, %l6, %g3 ! delay, Move up low ptr
695 b go_to_highmem ! Jump to high memory.
696 nop
697
698 /* The following is for non-4/4xx sun4 MMU's. */
699sun4_normal_remap:
700 mov 0, %g3 ! source base
701 set KERNBASE, %g4 ! destination base
702 set 0x300000, %g5 ! upper bound 3MB
703 mov 1, %l6
704 sll %l6, 18, %l6 ! sun4 mmu segmap size
705sun4_normal_loop:
706 lduha [%g3] ASI_SEGMAP, %g6 ! load phys_seg
707 stha %g6, [%g4] ASI_SEGMAP ! stort new virt mapping
708 add %g3, %l6, %g3 ! increment source pointer
709 subcc %g3, %g5, %g0 ! reached limit?
710 blu sun4_normal_loop ! nope, loop again
711 add %g4, %l6, %g4 ! delay, increment dest ptr
712 b go_to_highmem
713 nop
714
715 /* The following works for Sun4c MMU's */
716sun4c_remap:
717 mov 0, %g3 ! source base
718 set KERNBASE, %g4 ! destination base
719 set 0x300000, %g5 ! upper bound 3MB
720 mov 1, %l6
721 sll %l6, 18, %l6 ! sun4c mmu segmap size
722sun4c_remap_loop:
723 lda [%g3] ASI_SEGMAP, %g6 ! load phys_seg
724 sta %g6, [%g4] ASI_SEGMAP ! store new virt mapping
725 add %g3, %l6, %g3 ! Increment source ptr
726 subcc %g3, %g5, %g0 ! Reached limit?
727 bl sun4c_remap_loop ! Nope, loop again
728 add %g4, %l6, %g4 ! delay, Increment dest ptr
729 315
730/* Now do a non-relative jump so that PC is in high-memory */ 316/* Now do a non-relative jump so that PC is in high-memory */
731go_to_highmem: 317go_to_highmem:
@@ -750,35 +336,12 @@ execute_in_high_mem:
750 sethi %hi(linux_dbvec), %g1 336 sethi %hi(linux_dbvec), %g1
751 st %o1, [%g1 + %lo(linux_dbvec)] 337 st %o1, [%g1 + %lo(linux_dbvec)]
752 338
753 ld [%o0 + 0x4], %o3
754 and %o3, 0x3, %o5 ! get the version
755
756 cmp %o3, 0x2 ! a v2 prom?
757 be found_version
758 nop
759
760 /* paul@sfe.com.au */
761 cmp %o3, 0x3 ! a v3 prom?
762 be found_version
763 nop
764
765/* Old sun4's pass our load address into %o0 instead of the prom
766 * pointer. On sun4's you have to hard code the romvec pointer into
767 * your code. Sun probably still does that because they don't even
768 * trust their own "OpenBoot" specifications.
769 */
770 set LOAD_ADDR, %g6
771 cmp %o0, %g6 ! an old sun4?
772 be sun4_init
773 nop
774
775found_version:
776/* Get the machine type via the mysterious romvec node operations. */ 339/* Get the machine type via the mysterious romvec node operations. */
777 340
778 add %g7, 0x1c, %l1 341 add %g7, 0x1c, %l1
779 ld [%l1], %l0 342 ld [%l1], %l0
780 ld [%l0], %l0 343 ld [%l0], %l0
781 call %l0 344 call %l0
782 or %g0, %g0, %o0 ! next_node(0) = first_node 345 or %g0, %g0, %o0 ! next_node(0) = first_node
783 or %o0, %g0, %g6 346 or %o0, %g0, %g6
784 347
@@ -786,28 +349,13 @@ found_version:
786 or %o1, %lo(cputypvar), %o1 349 or %o1, %lo(cputypvar), %o1
787 sethi %hi(cputypval), %o2 ! information, the string 350 sethi %hi(cputypval), %o2 ! information, the string
788 or %o2, %lo(cputypval), %o2 351 or %o2, %lo(cputypval), %o2
789 ld [%l1], %l0 ! 'compatibility' tells 352 ld [%l1], %l0 ! 'compatible' tells
790 ld [%l0 + 0xc], %l0 ! that we want 'sun4x' where 353 ld [%l0 + 0xc], %l0 ! that we want 'sun4x' where
791 call %l0 ! x is one of '', 'c', 'm', 354 call %l0 ! x is one of 'm', 'd' or 'e'.
792 nop ! 'd' or 'e'. %o2 holds pointer 355 nop ! %o2 holds pointer
793 ! to a buf where above string 356 ! to a buf where above string
794 ! will get stored by the prom. 357 ! will get stored by the prom.
795 358
796 subcc %o0, %g0, %g0
797 bpos got_prop ! Got the property
798 nop
799
800 or %g6, %g0, %o0
801 sethi %hi(cputypvar_sun4m), %o1
802 or %o1, %lo(cputypvar_sun4m), %o1
803 sethi %hi(cputypval), %o2
804 or %o2, %lo(cputypval), %o2
805 ld [%l1], %l0
806 ld [%l0 + 0xc], %l0
807 call %l0
808 nop
809
810got_prop:
811#ifdef CONFIG_SPARC_LEON 359#ifdef CONFIG_SPARC_LEON
812 /* no cpu-type check is needed, it is a SPARC-LEON */ 360 /* no cpu-type check is needed, it is a SPARC-LEON */
813 361
@@ -826,45 +374,29 @@ got_prop:
826 /* Update boot_cpu_id only on boot cpu */ 374 /* Update boot_cpu_id only on boot cpu */
827 stub %g1, [%g2 + %lo(boot_cpu_id)] 375 stub %g1, [%g2 + %lo(boot_cpu_id)]
828 376
829 ba sun4c_continue_boot 377 ba continue_boot
830 nop 378 nop
831#endif 379#endif
380
381/* Check to cputype. We may be booted on a sun4u (64 bit box),
382 * and sun4d needs special treatment.
383 */
384
832 set cputypval, %o2 385 set cputypval, %o2
833 ldub [%o2 + 0x4], %l1 386 ldub [%o2 + 0x4], %l1
834 387
835 cmp %l1, ' ' 388 cmp %l1, 'm'
836 be 1f 389 be sun4m_init
837 cmp %l1, 'c'
838 be 1f
839 cmp %l1, 'm'
840 be 1f
841 cmp %l1, 's' 390 cmp %l1, 's'
842 be 1f 391 be sun4m_init
843 cmp %l1, 'd' 392 cmp %l1, 'd'
844 be 1f 393 be sun4d_init
845 cmp %l1, 'e' 394 cmp %l1, 'e'
846 be no_sun4e_here ! Could be a sun4e. 395 be no_sun4e_here ! Could be a sun4e.
847 nop 396 nop
848 b no_sun4u_here ! AIEEE, a V9 sun4u... Get our BIG BROTHER kernel :)) 397 b no_sun4u_here ! AIEEE, a V9 sun4u... Get our BIG BROTHER kernel :))
849 nop 398 nop
850 399
8511: set cputypval, %l1
852 ldub [%l1 + 0x4], %l1
853 cmp %l1, 'm' ! Test for sun4d, sun4e ?
854 be sun4m_init
855 cmp %l1, 's' ! Treat sun4s as sun4m
856 be sun4m_init
857 cmp %l1, 'd' ! Let us see how the beast will die
858 be sun4d_init
859 nop
860
861 /* Jump into mmu context zero. */
862 set AC_CONTEXT, %g1
863 stba %g0, [%g1] ASI_CONTROL
864
865 b sun4c_continue_boot
866 nop
867
868/* CPUID in bootbus can be found at PA 0xff0140000 */ 400/* CPUID in bootbus can be found at PA 0xff0140000 */
869#define SUN4D_BOOTBUS_CPUID 0xf0140000 401#define SUN4D_BOOTBUS_CPUID 0xf0140000
870 402
@@ -892,66 +424,6 @@ sun4d_init:
892 /* Fall through to sun4m_init */ 424 /* Fall through to sun4m_init */
893 425
894sun4m_init: 426sun4m_init:
895 /* XXX Fucking Cypress... */
896 lda [%g0] ASI_M_MMUREGS, %g5
897 srl %g5, 28, %g4
898
899 cmp %g4, 1
900 bne 1f
901 srl %g5, 24, %g4
902
903 and %g4, 0xf, %g4
904 cmp %g4, 7 /* This would be a HyperSparc. */
905
906 bne 2f
907 nop
908
9091:
910
911#define PATCH_IT(dst, src) \
912 set (dst), %g5; \
913 set (src), %g4; \
914 ld [%g4], %g3; \
915 st %g3, [%g5]; \
916 ld [%g4+0x4], %g3; \
917 st %g3, [%g5+0x4];
918
919 /* Signed multiply. */
920 PATCH_IT(.mul, .mul_patch)
921 PATCH_IT(.mul+0x08, .mul_patch+0x08)
922
923 /* Signed remainder. */
924 PATCH_IT(.rem, .rem_patch)
925 PATCH_IT(.rem+0x08, .rem_patch+0x08)
926 PATCH_IT(.rem+0x10, .rem_patch+0x10)
927 PATCH_IT(.rem+0x18, .rem_patch+0x18)
928 PATCH_IT(.rem+0x20, .rem_patch+0x20)
929 PATCH_IT(.rem+0x28, .rem_patch+0x28)
930
931 /* Signed division. */
932 PATCH_IT(.div, .div_patch)
933 PATCH_IT(.div+0x08, .div_patch+0x08)
934 PATCH_IT(.div+0x10, .div_patch+0x10)
935 PATCH_IT(.div+0x18, .div_patch+0x18)
936 PATCH_IT(.div+0x20, .div_patch+0x20)
937
938 /* Unsigned multiply. */
939 PATCH_IT(.umul, .umul_patch)
940 PATCH_IT(.umul+0x08, .umul_patch+0x08)
941
942 /* Unsigned remainder. */
943 PATCH_IT(.urem, .urem_patch)
944 PATCH_IT(.urem+0x08, .urem_patch+0x08)
945 PATCH_IT(.urem+0x10, .urem_patch+0x10)
946 PATCH_IT(.urem+0x18, .urem_patch+0x18)
947
948 /* Unsigned division. */
949 PATCH_IT(.udiv, .udiv_patch)
950 PATCH_IT(.udiv+0x08, .udiv_patch+0x08)
951 PATCH_IT(.udiv+0x10, .udiv_patch+0x10)
952
953#undef PATCH_IT
954
955/* Ok, the PROM could have done funny things and apple cider could still 427/* Ok, the PROM could have done funny things and apple cider could still
956 * be sitting in the fault status/address registers. Read them all to 428 * be sitting in the fault status/address registers. Read them all to
957 * clear them so we don't get magic faults later on. 429 * clear them so we don't get magic faults later on.
@@ -962,7 +434,7 @@ sun4m_init:
962 srl %o1, 28, %o1 ! Get a type of the CPU 434 srl %o1, 28, %o1 ! Get a type of the CPU
963 435
964 subcc %o1, 4, %g0 ! TI: Viking or MicroSPARC 436 subcc %o1, 4, %g0 ! TI: Viking or MicroSPARC
965 be sun4c_continue_boot 437 be continue_boot
966 nop 438 nop
967 439
968 set AC_M_SFSR, %o0 440 set AC_M_SFSR, %o0
@@ -972,7 +444,7 @@ sun4m_init:
972 444
973 /* Fujitsu MicroSPARC-II has no asynchronous flavors of FARs */ 445 /* Fujitsu MicroSPARC-II has no asynchronous flavors of FARs */
974 subcc %o1, 0, %g0 446 subcc %o1, 0, %g0
975 be sun4c_continue_boot 447 be continue_boot
976 nop 448 nop
977 449
978 set AC_M_AFSR, %o0 450 set AC_M_AFSR, %o0
@@ -982,8 +454,7 @@ sun4m_init:
982 nop 454 nop
983 455
984 456
985sun4c_continue_boot: 457continue_boot:
986
987 458
988/* Aieee, now set PC and nPC, enable traps, give ourselves a stack and it's 459/* Aieee, now set PC and nPC, enable traps, give ourselves a stack and it's
989 * show-time! 460 * show-time!
@@ -1026,10 +497,7 @@ sun4c_continue_boot:
1026 mov %g0, %g3 497 mov %g0, %g3
1027 stub %g3, [%g2 + %lo(boot_cpu_id)] 498 stub %g3, [%g2 + %lo(boot_cpu_id)]
1028 499
10291: /* boot_cpu_id set. calculate boot_cpu_id4 = boot_cpu_id*4 */ 5001: sll %g3, 2, %g3
1030 sll %g3, 2, %g3
1031 sethi %hi(boot_cpu_id4), %g2
1032 stub %g3, [%g2 + %lo(boot_cpu_id4)]
1033 501
1034 /* Initialize the uwinmask value for init task just in case. 502 /* Initialize the uwinmask value for init task just in case.
1035 * But first make current_set[boot_cpu_id] point to something useful. 503 * But first make current_set[boot_cpu_id] point to something useful.
@@ -1165,19 +633,6 @@ sun4c_continue_boot:
1165 call halt_me 633 call halt_me
1166 nop 634 nop
1167 635
1168sun4_init:
1169 sethi %hi(SUN4_PROM_VECTOR+0x84), %o1
1170 ld [%o1 + %lo(SUN4_PROM_VECTOR+0x84)], %o1
1171 set sun4_notsup, %o0
1172 call %o1 /* printf */
1173 nop
1174 sethi %hi(SUN4_PROM_VECTOR+0xc4), %o1
1175 ld [%o1 + %lo(SUN4_PROM_VECTOR+0xc4)], %o1
1176 call %o1 /* exittomon */
1177 nop
11781: ba 1b ! Cannot exit into KMON
1179 nop
1180
1181no_sun4e_here: 636no_sun4e_here:
1182 ld [%g7 + 0x68], %o1 637 ld [%g7 + 0x68], %o1
1183 set sun4e_notsup, %o0 638 set sun4e_notsup, %o0
diff --git a/arch/sparc/kernel/head_64.S b/arch/sparc/kernel/head_64.S
index 0d810c2f1d00..b42ddbf9651e 100644
--- a/arch/sparc/kernel/head_64.S
+++ b/arch/sparc/kernel/head_64.S
@@ -906,7 +906,7 @@ swapper_4m_tsb:
906 * error and will instead write junk into the relocation and 906 * error and will instead write junk into the relocation and
907 * you'll have an unbootable kernel. 907 * you'll have an unbootable kernel.
908 */ 908 */
909#include "ttable.S" 909#include "ttable_64.S"
910 910
911! 0x0000000000428000 911! 0x0000000000428000
912 912
diff --git a/arch/sparc/kernel/idprom.c b/arch/sparc/kernel/idprom.c
index 9167db40720e..6bd75012109d 100644
--- a/arch/sparc/kernel/idprom.c
+++ b/arch/sparc/kernel/idprom.c
@@ -25,22 +25,9 @@ static struct idprom idprom_buffer;
25 * of the Sparc CPU and have a meaningful IDPROM machtype value that we 25 * of the Sparc CPU and have a meaningful IDPROM machtype value that we
26 * know about. See asm-sparc/machines.h for empirical constants. 26 * know about. See asm-sparc/machines.h for empirical constants.
27 */ 27 */
28static struct Sun_Machine_Models Sun_Machines[NUM_SUN_MACHINES] = { 28static struct Sun_Machine_Models Sun_Machines[] = {
29/* First, Sun4's */ 29/* First, Leon */
30{ .name = "Sun 4/100 Series", .id_machtype = (SM_SUN4 | SM_4_110) },
31{ .name = "Sun 4/200 Series", .id_machtype = (SM_SUN4 | SM_4_260) },
32{ .name = "Sun 4/300 Series", .id_machtype = (SM_SUN4 | SM_4_330) },
33{ .name = "Sun 4/400 Series", .id_machtype = (SM_SUN4 | SM_4_470) },
34/* Now Leon */
35{ .name = "Leon3 System-on-a-Chip", .id_machtype = (M_LEON | M_LEON3_SOC) }, 30{ .name = "Leon3 System-on-a-Chip", .id_machtype = (M_LEON | M_LEON3_SOC) },
36/* Now, Sun4c's */
37{ .name = "Sun4c SparcStation 1", .id_machtype = (SM_SUN4C | SM_4C_SS1) },
38{ .name = "Sun4c SparcStation IPC", .id_machtype = (SM_SUN4C | SM_4C_IPC) },
39{ .name = "Sun4c SparcStation 1+", .id_machtype = (SM_SUN4C | SM_4C_SS1PLUS) },
40{ .name = "Sun4c SparcStation SLC", .id_machtype = (SM_SUN4C | SM_4C_SLC) },
41{ .name = "Sun4c SparcStation 2", .id_machtype = (SM_SUN4C | SM_4C_SS2) },
42{ .name = "Sun4c SparcStation ELC", .id_machtype = (SM_SUN4C | SM_4C_ELC) },
43{ .name = "Sun4c SparcStation IPX", .id_machtype = (SM_SUN4C | SM_4C_IPX) },
44/* Finally, early Sun4m's */ 31/* Finally, early Sun4m's */
45{ .name = "Sun4m SparcSystem600", .id_machtype = (SM_SUN4M | SM_4M_SS60) }, 32{ .name = "Sun4m SparcSystem600", .id_machtype = (SM_SUN4M | SM_4M_SS60) },
46{ .name = "Sun4m SparcStation10/20", .id_machtype = (SM_SUN4M | SM_4M_SS50) }, 33{ .name = "Sun4m SparcStation10/20", .id_machtype = (SM_SUN4M | SM_4M_SS50) },
@@ -53,7 +40,7 @@ static void __init display_system_type(unsigned char machtype)
53 char sysname[128]; 40 char sysname[128];
54 register int i; 41 register int i;
55 42
56 for (i = 0; i < NUM_SUN_MACHINES; i++) { 43 for (i = 0; i < ARRAY_SIZE(Sun_Machines); i++) {
57 if (Sun_Machines[i].id_machtype == machtype) { 44 if (Sun_Machines[i].id_machtype == machtype) {
58 if (machtype != (SM_SUN4M_OBP | 0x00) || 45 if (machtype != (SM_SUN4M_OBP | 0x00) ||
59 prom_getproperty(prom_root_node, "banner-name", 46 prom_getproperty(prom_root_node, "banner-name",
diff --git a/arch/sparc/kernel/ioport.c b/arch/sparc/kernel/ioport.c
index 21bd73943f7f..a2846f5e32d8 100644
--- a/arch/sparc/kernel/ioport.c
+++ b/arch/sparc/kernel/ioport.c
@@ -50,6 +50,8 @@
50#include <asm/io-unit.h> 50#include <asm/io-unit.h>
51#include <asm/leon.h> 51#include <asm/leon.h>
52 52
53const struct sparc32_dma_ops *sparc32_dma_ops;
54
53/* This function must make sure that caches and memory are coherent after DMA 55/* This function must make sure that caches and memory are coherent after DMA
54 * On LEON systems without cache snooping it flushes the entire D-CACHE. 56 * On LEON systems without cache snooping it flushes the entire D-CACHE.
55 */ 57 */
@@ -229,7 +231,7 @@ _sparc_ioremap(struct resource *res, u32 bus, u32 pa, int sz)
229 } 231 }
230 232
231 pa &= PAGE_MASK; 233 pa &= PAGE_MASK;
232 sparc_mapiorange(bus, pa, res->start, resource_size(res)); 234 srmmu_mapiorange(bus, pa, res->start, resource_size(res));
233 235
234 return (void __iomem *)(unsigned long)(res->start + offset); 236 return (void __iomem *)(unsigned long)(res->start + offset);
235} 237}
@@ -243,7 +245,7 @@ static void _sparc_free_io(struct resource *res)
243 245
244 plen = resource_size(res); 246 plen = resource_size(res);
245 BUG_ON((plen & (PAGE_SIZE-1)) != 0); 247 BUG_ON((plen & (PAGE_SIZE-1)) != 0);
246 sparc_unmapiorange(res->start, plen); 248 srmmu_unmapiorange(res->start, plen);
247 release_resource(res); 249 release_resource(res);
248} 250}
249 251
@@ -292,13 +294,13 @@ static void *sbus_alloc_coherent(struct device *dev, size_t len,
292 goto err_nova; 294 goto err_nova;
293 } 295 }
294 296
295 // XXX The mmu_map_dma_area does this for us below, see comments. 297 // XXX The sbus_map_dma_area does this for us below, see comments.
296 // sparc_mapiorange(0, virt_to_phys(va), res->start, len_total); 298 // srmmu_mapiorange(0, virt_to_phys(va), res->start, len_total);
297 /* 299 /*
298 * XXX That's where sdev would be used. Currently we load 300 * XXX That's where sdev would be used. Currently we load
299 * all iommu tables with the same translations. 301 * all iommu tables with the same translations.
300 */ 302 */
301 if (mmu_map_dma_area(dev, dma_addrp, va, res->start, len_total) != 0) 303 if (sbus_map_dma_area(dev, dma_addrp, va, res->start, len_total) != 0)
302 goto err_noiommu; 304 goto err_noiommu;
303 305
304 res->name = op->dev.of_node->name; 306 res->name = op->dev.of_node->name;
@@ -343,7 +345,7 @@ static void sbus_free_coherent(struct device *dev, size_t n, void *p,
343 kfree(res); 345 kfree(res);
344 346
345 pgv = virt_to_page(p); 347 pgv = virt_to_page(p);
346 mmu_unmap_dma_area(dev, ba, n); 348 sbus_unmap_dma_area(dev, ba, n);
347 349
348 __free_pages(pgv, get_order(n)); 350 __free_pages(pgv, get_order(n));
349} 351}
@@ -381,11 +383,6 @@ static int sbus_map_sg(struct device *dev, struct scatterlist *sg, int n,
381 enum dma_data_direction dir, struct dma_attrs *attrs) 383 enum dma_data_direction dir, struct dma_attrs *attrs)
382{ 384{
383 mmu_get_scsi_sgl(dev, sg, n); 385 mmu_get_scsi_sgl(dev, sg, n);
384
385 /*
386 * XXX sparc64 can return a partial length here. sun4c should do this
387 * but it currently panics if it can't fulfill the request - Anton
388 */
389 return n; 386 return n;
390} 387}
391 388
@@ -469,7 +466,7 @@ static void *pci32_alloc_coherent(struct device *dev, size_t len,
469 printk("pci_alloc_consistent: cannot occupy 0x%lx", len_total); 466 printk("pci_alloc_consistent: cannot occupy 0x%lx", len_total);
470 goto err_nova; 467 goto err_nova;
471 } 468 }
472 sparc_mapiorange(0, virt_to_phys(va), res->start, len_total); 469 srmmu_mapiorange(0, virt_to_phys(va), res->start, len_total);
473 470
474 *pba = virt_to_phys(va); /* equals virt_to_bus (R.I.P.) for us. */ 471 *pba = virt_to_phys(va); /* equals virt_to_bus (R.I.P.) for us. */
475 return (void *) res->start; 472 return (void *) res->start;
@@ -514,7 +511,7 @@ static void pci32_free_coherent(struct device *dev, size_t n, void *p,
514 } 511 }
515 512
516 dma_make_coherent(ba, n); 513 dma_make_coherent(ba, n);
517 sparc_unmapiorange((unsigned long)p, n); 514 srmmu_unmapiorange((unsigned long)p, n);
518 515
519 release_resource(res); 516 release_resource(res);
520 kfree(res); 517 kfree(res);
diff --git a/arch/sparc/kernel/irq.h b/arch/sparc/kernel/irq.h
index 5a021dd2f854..b66b6aad1d6d 100644
--- a/arch/sparc/kernel/irq.h
+++ b/arch/sparc/kernel/irq.h
@@ -1,6 +1,5 @@
1#include <linux/platform_device.h> 1#include <linux/platform_device.h>
2 2
3#include <asm/btfixup.h>
4#include <asm/cpu_type.h> 3#include <asm/cpu_type.h>
5 4
6struct irq_bucket { 5struct irq_bucket {
@@ -10,6 +9,9 @@ struct irq_bucket {
10 unsigned int pil; 9 unsigned int pil;
11}; 10};
12 11
12#define SUN4M_HARD_INT(x) (0x000000001 << (x))
13#define SUN4M_SOFT_INT(x) (0x000010000 << (x))
14
13#define SUN4D_MAX_BOARD 10 15#define SUN4D_MAX_BOARD 10
14#define SUN4D_MAX_IRQ ((SUN4D_MAX_BOARD + 2) << 5) 16#define SUN4D_MAX_IRQ ((SUN4D_MAX_BOARD + 2) << 5)
15 17
@@ -41,52 +43,46 @@ struct sun4m_irq_global {
41extern struct sun4m_irq_percpu __iomem *sun4m_irq_percpu[SUN4M_NCPUS]; 43extern struct sun4m_irq_percpu __iomem *sun4m_irq_percpu[SUN4M_NCPUS];
42extern struct sun4m_irq_global __iomem *sun4m_irq_global; 44extern struct sun4m_irq_global __iomem *sun4m_irq_global;
43 45
46/* The following definitions describe the individual platform features: */
47#define FEAT_L10_CLOCKSOURCE (1 << 0) /* L10 timer is used as a clocksource */
48#define FEAT_L10_CLOCKEVENT (1 << 1) /* L10 timer is used as a clockevent */
49#define FEAT_L14_ONESHOT (1 << 2) /* L14 timer clockevent can oneshot */
50
44/* 51/*
45 * Platform specific irq configuration 52 * Platform specific configuration
46 * The individual platforms assign their platform 53 * The individual platforms assign their platform
47 * specifics in their init functions. 54 * specifics in their init functions.
48 */ 55 */
49struct sparc_irq_config { 56struct sparc_config {
50 void (*init_timers)(irq_handler_t); 57 void (*init_timers)(void);
51 unsigned int (*build_device_irq)(struct platform_device *op, 58 unsigned int (*build_device_irq)(struct platform_device *op,
52 unsigned int real_irq); 59 unsigned int real_irq);
60
61 /* generic clockevent features - see FEAT_* above */
62 int features;
63
64 /* clock rate used for clock event timer */
65 int clock_rate;
66
67 /* one period for clock source timer */
68 unsigned int cs_period;
69
70 /* function to obtain offsett for cs period */
71 unsigned int (*get_cycles_offset)(void);
72
73 void (*clear_clock_irq)(void);
74 void (*load_profile_irq)(int cpu, unsigned int limit);
53}; 75};
54extern struct sparc_irq_config sparc_irq_config; 76extern struct sparc_config sparc_config;
55 77
56unsigned int irq_alloc(unsigned int real_irq, unsigned int pil); 78unsigned int irq_alloc(unsigned int real_irq, unsigned int pil);
57void irq_link(unsigned int irq); 79void irq_link(unsigned int irq);
58void irq_unlink(unsigned int irq); 80void irq_unlink(unsigned int irq);
59void handler_irq(unsigned int pil, struct pt_regs *regs); 81void handler_irq(unsigned int pil, struct pt_regs *regs);
60 82
61/* Dave Redman (djhr@tadpole.co.uk) 83unsigned long leon_get_irqmask(unsigned int irq);
62 * changed these to function pointers.. it saves cycles and will allow
63 * the irq dependencies to be split into different files at a later date
64 * sun4c_irq.c, sun4m_irq.c etc so we could reduce the kernel size.
65 * Jakub Jelinek (jj@sunsite.mff.cuni.cz)
66 * Changed these to btfixup entities... It saves cycles :)
67 */
68
69BTFIXUPDEF_CALL(void, clear_clock_irq, void)
70BTFIXUPDEF_CALL(void, load_profile_irq, int, unsigned int)
71
72static inline void clear_clock_irq(void)
73{
74 BTFIXUP_CALL(clear_clock_irq)();
75}
76
77static inline void load_profile_irq(int cpu, int limit)
78{
79 BTFIXUP_CALL(load_profile_irq)(cpu, limit);
80}
81 84
82#ifdef CONFIG_SMP 85#ifdef CONFIG_SMP
83BTFIXUPDEF_CALL(void, set_cpu_int, int, int)
84BTFIXUPDEF_CALL(void, clear_cpu_int, int, int)
85BTFIXUPDEF_CALL(void, set_irq_udt, int)
86
87#define set_cpu_int(cpu,level) BTFIXUP_CALL(set_cpu_int)(cpu,level)
88#define clear_cpu_int(cpu,level) BTFIXUP_CALL(clear_cpu_int)(cpu,level)
89#define set_irq_udt(cpu) BTFIXUP_CALL(set_irq_udt)(cpu)
90 86
91/* All SUN4D IPIs are sent on this IRQ, may be shared with hard IRQs */ 87/* All SUN4D IPIs are sent on this IRQ, may be shared with hard IRQs */
92#define SUN4D_IPI_IRQ 13 88#define SUN4D_IPI_IRQ 13
diff --git a/arch/sparc/kernel/irq_32.c b/arch/sparc/kernel/irq_32.c
index b2668afd1c34..ae04914f7774 100644
--- a/arch/sparc/kernel/irq_32.c
+++ b/arch/sparc/kernel/irq_32.c
@@ -23,16 +23,8 @@
23#include "kernel.h" 23#include "kernel.h"
24#include "irq.h" 24#include "irq.h"
25 25
26#ifdef CONFIG_SMP
27#define SMP_NOP2 "nop; nop;\n\t"
28#define SMP_NOP3 "nop; nop; nop;\n\t"
29#else
30#define SMP_NOP2
31#define SMP_NOP3
32#endif /* SMP */
33
34/* platform specific irq setup */ 26/* platform specific irq setup */
35struct sparc_irq_config sparc_irq_config; 27struct sparc_config sparc_config;
36 28
37unsigned long arch_local_irq_save(void) 29unsigned long arch_local_irq_save(void)
38{ 30{
@@ -41,7 +33,6 @@ unsigned long arch_local_irq_save(void)
41 33
42 __asm__ __volatile__( 34 __asm__ __volatile__(
43 "rd %%psr, %0\n\t" 35 "rd %%psr, %0\n\t"
44 SMP_NOP3 /* Sun4m + Cypress + SMP bug */
45 "or %0, %2, %1\n\t" 36 "or %0, %2, %1\n\t"
46 "wr %1, 0, %%psr\n\t" 37 "wr %1, 0, %%psr\n\t"
47 "nop; nop; nop\n" 38 "nop; nop; nop\n"
@@ -59,7 +50,6 @@ void arch_local_irq_enable(void)
59 50
60 __asm__ __volatile__( 51 __asm__ __volatile__(
61 "rd %%psr, %0\n\t" 52 "rd %%psr, %0\n\t"
62 SMP_NOP3 /* Sun4m + Cypress + SMP bug */
63 "andn %0, %1, %0\n\t" 53 "andn %0, %1, %0\n\t"
64 "wr %0, 0, %%psr\n\t" 54 "wr %0, 0, %%psr\n\t"
65 "nop; nop; nop\n" 55 "nop; nop; nop\n"
@@ -76,7 +66,6 @@ void arch_local_irq_restore(unsigned long old_psr)
76 __asm__ __volatile__( 66 __asm__ __volatile__(
77 "rd %%psr, %0\n\t" 67 "rd %%psr, %0\n\t"
78 "and %2, %1, %2\n\t" 68 "and %2, %1, %2\n\t"
79 SMP_NOP2 /* Sun4m + Cypress + SMP bug */
80 "andn %0, %1, %0\n\t" 69 "andn %0, %1, %0\n\t"
81 "wr %0, %2, %%psr\n\t" 70 "wr %0, %2, %%psr\n\t"
82 "nop; nop; nop\n" 71 "nop; nop; nop\n"
@@ -346,11 +335,6 @@ void sparc_floppy_irq(int irq, void *dev_id, struct pt_regs *regs)
346void __init init_IRQ(void) 335void __init init_IRQ(void)
347{ 336{
348 switch (sparc_cpu_model) { 337 switch (sparc_cpu_model) {
349 case sun4c:
350 case sun4:
351 sun4c_init_IRQ();
352 break;
353
354 case sun4m: 338 case sun4m:
355 pcic_probe(); 339 pcic_probe();
356 if (pcic_present()) 340 if (pcic_present())
@@ -371,6 +355,5 @@ void __init init_IRQ(void)
371 prom_printf("Cannot initialize IRQs on this Sun machine..."); 355 prom_printf("Cannot initialize IRQs on this Sun machine...");
372 break; 356 break;
373 } 357 }
374 btfixup();
375} 358}
376 359
diff --git a/arch/sparc/kernel/irq_64.c b/arch/sparc/kernel/irq_64.c
index dff2c3d7d370..9bcbbe2c4e7e 100644
--- a/arch/sparc/kernel/irq_64.c
+++ b/arch/sparc/kernel/irq_64.c
@@ -799,7 +799,7 @@ static void kill_prom_timer(void)
799 prom_limit0 = prom_timers->limit0; 799 prom_limit0 = prom_timers->limit0;
800 prom_limit1 = prom_timers->limit1; 800 prom_limit1 = prom_timers->limit1;
801 801
802 /* Just as in sun4c/sun4m PROM uses timer which ticks at IRQ 14. 802 /* Just as in sun4c PROM uses timer which ticks at IRQ 14.
803 * We turn both off here just to be paranoid. 803 * We turn both off here just to be paranoid.
804 */ 804 */
805 prom_timers->limit0 = 0; 805 prom_timers->limit0 = 0;
diff --git a/arch/sparc/kernel/kernel.h b/arch/sparc/kernel/kernel.h
index fd6c36b1df74..a86372d34587 100644
--- a/arch/sparc/kernel/kernel.h
+++ b/arch/sparc/kernel/kernel.h
@@ -32,9 +32,6 @@ extern void cpu_probe(void);
32/* traps_32.c */ 32/* traps_32.c */
33extern void handle_hw_divzero(struct pt_regs *regs, unsigned long pc, 33extern void handle_hw_divzero(struct pt_regs *regs, unsigned long pc,
34 unsigned long npc, unsigned long psr); 34 unsigned long npc, unsigned long psr);
35/* muldiv.c */
36extern int do_user_muldiv (struct pt_regs *, unsigned long);
37
38/* irq_32.c */ 35/* irq_32.c */
39extern struct irqaction static_irqaction[]; 36extern struct irqaction static_irqaction[];
40extern int static_irq_count; 37extern int static_irq_count;
@@ -43,12 +40,7 @@ extern spinlock_t irq_action_lock;
43extern void unexpected_irq(int irq, void *dev_id, struct pt_regs * regs); 40extern void unexpected_irq(int irq, void *dev_id, struct pt_regs * regs);
44extern void init_IRQ(void); 41extern void init_IRQ(void);
45 42
46/* sun4c_irq.c */
47extern void sun4c_init_IRQ(void);
48
49/* sun4m_irq.c */ 43/* sun4m_irq.c */
50extern unsigned int lvl14_resolution;
51
52extern void sun4m_init_IRQ(void); 44extern void sun4m_init_IRQ(void);
53extern void sun4m_unmask_profile_irq(void); 45extern void sun4m_unmask_profile_irq(void);
54extern void sun4m_clear_profile_irq(int cpu); 46extern void sun4m_clear_profile_irq(int cpu);
@@ -85,8 +77,6 @@ extern unsigned int patchme_maybe_smp_msg[];
85extern void floppy_hardint(void); 77extern void floppy_hardint(void);
86 78
87/* trampoline_32.S */ 79/* trampoline_32.S */
88extern int __smp4m_processor_id(void);
89extern int __smp4d_processor_id(void);
90extern unsigned long sun4m_cpu_startup; 80extern unsigned long sun4m_cpu_startup;
91extern unsigned long sun4d_cpu_startup; 81extern unsigned long sun4d_cpu_startup;
92 82
diff --git a/arch/sparc/kernel/leon_kernel.c b/arch/sparc/kernel/leon_kernel.c
index 35e43673c453..77c1b916e4dd 100644
--- a/arch/sparc/kernel/leon_kernel.c
+++ b/arch/sparc/kernel/leon_kernel.c
@@ -10,6 +10,8 @@
10#include <linux/of_platform.h> 10#include <linux/of_platform.h>
11#include <linux/interrupt.h> 11#include <linux/interrupt.h>
12#include <linux/of_device.h> 12#include <linux/of_device.h>
13#include <linux/clocksource.h>
14#include <linux/clockchips.h>
13 15
14#include <asm/oplib.h> 16#include <asm/oplib.h>
15#include <asm/timer.h> 17#include <asm/timer.h>
@@ -84,7 +86,7 @@ void leon_eirq_setup(unsigned int eirq)
84 sparc_leon_eirq = eirq; 86 sparc_leon_eirq = eirq;
85} 87}
86 88
87static inline unsigned long get_irqmask(unsigned int irq) 89unsigned long leon_get_irqmask(unsigned int irq)
88{ 90{
89 unsigned long mask; 91 unsigned long mask;
90 92
@@ -210,7 +212,7 @@ unsigned int leon_build_device_irq(unsigned int real_irq,
210 unsigned long mask; 212 unsigned long mask;
211 213
212 irq = 0; 214 irq = 0;
213 mask = get_irqmask(real_irq); 215 mask = leon_get_irqmask(real_irq);
214 if (mask == 0) 216 if (mask == 0)
215 goto out; 217 goto out;
216 218
@@ -250,7 +252,38 @@ void leon_update_virq_handling(unsigned int virq,
250 irq_set_chip_data(virq, (void *)mask); 252 irq_set_chip_data(virq, (void *)mask);
251} 253}
252 254
253void __init leon_init_timers(irq_handler_t counter_fn) 255static u32 leon_cycles_offset(void)
256{
257 u32 rld, val, off;
258 rld = LEON3_BYPASS_LOAD_PA(&leon3_gptimer_regs->e[leon3_gptimer_idx].rld);
259 val = LEON3_BYPASS_LOAD_PA(&leon3_gptimer_regs->e[leon3_gptimer_idx].val);
260 off = rld - val;
261 return rld - val;
262}
263
264#ifdef CONFIG_SMP
265
266/* smp clockevent irq */
267irqreturn_t leon_percpu_timer_ce_interrupt(int irq, void *unused)
268{
269 struct clock_event_device *ce;
270 int cpu = smp_processor_id();
271
272 leon_clear_profile_irq(cpu);
273
274 ce = &per_cpu(sparc32_clockevent, cpu);
275
276 irq_enter();
277 if (ce->event_handler)
278 ce->event_handler(ce);
279 irq_exit();
280
281 return IRQ_HANDLED;
282}
283
284#endif /* CONFIG_SMP */
285
286void __init leon_init_timers(void)
254{ 287{
255 int irq, eirq; 288 int irq, eirq;
256 struct device_node *rootnp, *np, *nnp; 289 struct device_node *rootnp, *np, *nnp;
@@ -260,6 +293,14 @@ void __init leon_init_timers(irq_handler_t counter_fn)
260 int ampopts; 293 int ampopts;
261 int err; 294 int err;
262 295
296 sparc_config.get_cycles_offset = leon_cycles_offset;
297 sparc_config.cs_period = 1000000 / HZ;
298 sparc_config.features |= FEAT_L10_CLOCKSOURCE;
299
300#ifndef CONFIG_SMP
301 sparc_config.features |= FEAT_L10_CLOCKEVENT;
302#endif
303
263 leondebug_irq_disable = 0; 304 leondebug_irq_disable = 0;
264 leon_debug_irqout = 0; 305 leon_debug_irqout = 0;
265 master_l10_counter = (unsigned int *)&dummy_master_l10_counter; 306 master_l10_counter = (unsigned int *)&dummy_master_l10_counter;
@@ -369,7 +410,7 @@ void __init leon_init_timers(irq_handler_t counter_fn)
369 leon_eirq_setup(eirq); 410 leon_eirq_setup(eirq);
370 411
371 irq = _leon_build_device_irq(NULL, leon3_gptimer_irq+leon3_gptimer_idx); 412 irq = _leon_build_device_irq(NULL, leon3_gptimer_irq+leon3_gptimer_idx);
372 err = request_irq(irq, counter_fn, IRQF_TIMER, "timer", NULL); 413 err = request_irq(irq, timer_interrupt, IRQF_TIMER, "timer", NULL);
373 if (err) { 414 if (err) {
374 printk(KERN_ERR "unable to attach timer IRQ%d\n", irq); 415 printk(KERN_ERR "unable to attach timer IRQ%d\n", irq);
375 prom_halt(); 416 prom_halt();
@@ -386,7 +427,7 @@ void __init leon_init_timers(irq_handler_t counter_fn)
386 */ 427 */
387 local_irq_save(flags); 428 local_irq_save(flags);
388 patchme_maybe_smp_msg[0] = 0x01000000; /* NOP out the branch */ 429 patchme_maybe_smp_msg[0] = 0x01000000; /* NOP out the branch */
389 local_flush_cache_all(); 430 local_ops->cache_all();
390 local_irq_restore(flags); 431 local_irq_restore(flags);
391 } 432 }
392#endif 433#endif
@@ -401,7 +442,7 @@ void __init leon_init_timers(irq_handler_t counter_fn)
401 /* Install per-cpu IRQ handler for broadcasted ticker */ 442 /* Install per-cpu IRQ handler for broadcasted ticker */
402 irq = leon_build_device_irq(leon3_ticker_irq, handle_percpu_irq, 443 irq = leon_build_device_irq(leon3_ticker_irq, handle_percpu_irq,
403 "per-cpu", 0); 444 "per-cpu", 0);
404 err = request_irq(irq, leon_percpu_timer_interrupt, 445 err = request_irq(irq, leon_percpu_timer_ce_interrupt,
405 IRQF_PERCPU | IRQF_TIMER, "ticker", 446 IRQF_PERCPU | IRQF_TIMER, "ticker",
406 NULL); 447 NULL);
407 if (err) { 448 if (err) {
@@ -422,13 +463,12 @@ bad:
422 return; 463 return;
423} 464}
424 465
425void leon_clear_clock_irq(void) 466static void leon_clear_clock_irq(void)
426{ 467{
427} 468}
428 469
429void leon_load_profile_irq(int cpu, unsigned int limit) 470static void leon_load_profile_irq(int cpu, unsigned int limit)
430{ 471{
431 BUG();
432} 472}
433 473
434void __init leon_trans_init(struct device_node *dp) 474void __init leon_trans_init(struct device_node *dp)
@@ -457,25 +497,6 @@ void __init leon_node_init(struct device_node *dp, struct device_node ***nextp)
457} 497}
458 498
459#ifdef CONFIG_SMP 499#ifdef CONFIG_SMP
460
461void leon_set_cpu_int(int cpu, int level)
462{
463 unsigned long mask;
464 mask = get_irqmask(level);
465 LEON3_BYPASS_STORE_PA(&leon3_irqctrl_regs->force[cpu], mask);
466}
467
468static void leon_clear_ipi(int cpu, int level)
469{
470 unsigned long mask;
471 mask = get_irqmask(level);
472 LEON3_BYPASS_STORE_PA(&leon3_irqctrl_regs->force[cpu], mask<<16);
473}
474
475static void leon_set_udt(int cpu)
476{
477}
478
479void leon_clear_profile_irq(int cpu) 500void leon_clear_profile_irq(int cpu)
480{ 501{
481} 502}
@@ -483,7 +504,7 @@ void leon_clear_profile_irq(int cpu)
483void leon_enable_irq_cpu(unsigned int irq_nr, unsigned int cpu) 504void leon_enable_irq_cpu(unsigned int irq_nr, unsigned int cpu)
484{ 505{
485 unsigned long mask, flags, *addr; 506 unsigned long mask, flags, *addr;
486 mask = get_irqmask(irq_nr); 507 mask = leon_get_irqmask(irq_nr);
487 spin_lock_irqsave(&leon_irq_lock, flags); 508 spin_lock_irqsave(&leon_irq_lock, flags);
488 addr = (unsigned long *)LEON_IMASK(cpu); 509 addr = (unsigned long *)LEON_IMASK(cpu);
489 LEON3_BYPASS_STORE_PA(addr, (LEON3_BYPASS_LOAD_PA(addr) | mask)); 510 LEON3_BYPASS_STORE_PA(addr, (LEON3_BYPASS_LOAD_PA(addr) | mask));
@@ -494,20 +515,11 @@ void leon_enable_irq_cpu(unsigned int irq_nr, unsigned int cpu)
494 515
495void __init leon_init_IRQ(void) 516void __init leon_init_IRQ(void)
496{ 517{
497 sparc_irq_config.init_timers = leon_init_timers; 518 sparc_config.init_timers = leon_init_timers;
498 sparc_irq_config.build_device_irq = _leon_build_device_irq; 519 sparc_config.build_device_irq = _leon_build_device_irq;
499 520 sparc_config.clock_rate = 1000000;
500 BTFIXUPSET_CALL(clear_clock_irq, leon_clear_clock_irq, 521 sparc_config.clear_clock_irq = leon_clear_clock_irq;
501 BTFIXUPCALL_NORM); 522 sparc_config.load_profile_irq = leon_load_profile_irq;
502 BTFIXUPSET_CALL(load_profile_irq, leon_load_profile_irq,
503 BTFIXUPCALL_NOP);
504
505#ifdef CONFIG_SMP
506 BTFIXUPSET_CALL(set_cpu_int, leon_set_cpu_int, BTFIXUPCALL_NORM);
507 BTFIXUPSET_CALL(clear_cpu_int, leon_clear_ipi, BTFIXUPCALL_NORM);
508 BTFIXUPSET_CALL(set_irq_udt, leon_set_udt, BTFIXUPCALL_NORM);
509#endif
510
511} 523}
512 524
513void __init leon_init(void) 525void __init leon_init(void)
diff --git a/arch/sparc/kernel/leon_smp.c b/arch/sparc/kernel/leon_smp.c
index 160cac9c4036..29325bacba6f 100644
--- a/arch/sparc/kernel/leon_smp.c
+++ b/arch/sparc/kernel/leon_smp.c
@@ -24,6 +24,7 @@
24#include <linux/delay.h> 24#include <linux/delay.h>
25#include <linux/gfp.h> 25#include <linux/gfp.h>
26#include <linux/cpu.h> 26#include <linux/cpu.h>
27#include <linux/clockchips.h>
27 28
28#include <asm/cacheflush.h> 29#include <asm/cacheflush.h>
29#include <asm/tlbflush.h> 30#include <asm/tlbflush.h>
@@ -43,6 +44,7 @@
43#include <asm/asi.h> 44#include <asm/asi.h>
44#include <asm/leon.h> 45#include <asm/leon.h>
45#include <asm/leon_amba.h> 46#include <asm/leon_amba.h>
47#include <asm/timer.h>
46 48
47#include "kernel.h" 49#include "kernel.h"
48 50
@@ -69,26 +71,24 @@ static inline unsigned long do_swap(volatile unsigned long *ptr,
69 return val; 71 return val;
70} 72}
71 73
72static void smp_setup_percpu_timer(void);
73
74void __cpuinit leon_callin(void) 74void __cpuinit leon_callin(void)
75{ 75{
76 int cpuid = hard_smpleon_processor_id(); 76 int cpuid = hard_smp_processor_id();
77 77
78 local_flush_cache_all(); 78 local_ops->cache_all();
79 local_flush_tlb_all(); 79 local_ops->tlb_all();
80 leon_configure_cache_smp(); 80 leon_configure_cache_smp();
81 81
82 notify_cpu_starting(cpuid); 82 notify_cpu_starting(cpuid);
83 83
84 /* Get our local ticker going. */ 84 /* Get our local ticker going. */
85 smp_setup_percpu_timer(); 85 register_percpu_ce(cpuid);
86 86
87 calibrate_delay(); 87 calibrate_delay();
88 smp_store_cpu_info(cpuid); 88 smp_store_cpu_info(cpuid);
89 89
90 local_flush_cache_all(); 90 local_ops->cache_all();
91 local_flush_tlb_all(); 91 local_ops->tlb_all();
92 92
93 /* 93 /*
94 * Unblock the master CPU _only_ when the scheduler state 94 * Unblock the master CPU _only_ when the scheduler state
@@ -99,8 +99,8 @@ void __cpuinit leon_callin(void)
99 */ 99 */
100 do_swap(&cpu_callin_map[cpuid], 1); 100 do_swap(&cpu_callin_map[cpuid], 1);
101 101
102 local_flush_cache_all(); 102 local_ops->cache_all();
103 local_flush_tlb_all(); 103 local_ops->tlb_all();
104 104
105 /* Fix idle thread fields. */ 105 /* Fix idle thread fields. */
106 __asm__ __volatile__("ld [%0], %%g6\n\t" : : "r"(&current_set[cpuid]) 106 __asm__ __volatile__("ld [%0], %%g6\n\t" : : "r"(&current_set[cpuid])
@@ -143,8 +143,8 @@ void __init leon_configure_cache_smp(void)
143 } 143 }
144 } 144 }
145 145
146 local_flush_cache_all(); 146 local_ops->cache_all();
147 local_flush_tlb_all(); 147 local_ops->tlb_all();
148} 148}
149 149
150void leon_smp_setbroadcast(unsigned int mask) 150void leon_smp_setbroadcast(unsigned int mask)
@@ -199,8 +199,7 @@ void __init leon_boot_cpus(void)
199 leon_smp_setbroadcast(1 << LEON3_IRQ_TICKER); 199 leon_smp_setbroadcast(1 << LEON3_IRQ_TICKER);
200 200
201 leon_configure_cache_smp(); 201 leon_configure_cache_smp();
202 smp_setup_percpu_timer(); 202 local_ops->cache_all();
203 local_flush_cache_all();
204 203
205} 204}
206 205
@@ -227,7 +226,7 @@ int __cpuinit leon_boot_one_cpu(int i)
227 /* whirrr, whirrr, whirrrrrrrrr... */ 226 /* whirrr, whirrr, whirrrrrrrrr... */
228 printk(KERN_INFO "Starting CPU %d : (irqmp: 0x%x)\n", (unsigned int)i, 227 printk(KERN_INFO "Starting CPU %d : (irqmp: 0x%x)\n", (unsigned int)i,
229 (unsigned int)&leon3_irqctrl_regs->mpstatus); 228 (unsigned int)&leon3_irqctrl_regs->mpstatus);
230 local_flush_cache_all(); 229 local_ops->cache_all();
231 230
232 /* Make sure all IRQs are of from the start for this new CPU */ 231 /* Make sure all IRQs are of from the start for this new CPU */
233 LEON_BYPASS_STORE_PA(&leon3_irqctrl_regs->mask[i], 0); 232 LEON_BYPASS_STORE_PA(&leon3_irqctrl_regs->mask[i], 0);
@@ -252,7 +251,7 @@ int __cpuinit leon_boot_one_cpu(int i)
252 leon_enable_irq_cpu(leon_ipi_irq, i); 251 leon_enable_irq_cpu(leon_ipi_irq, i);
253 } 252 }
254 253
255 local_flush_cache_all(); 254 local_ops->cache_all();
256 return 0; 255 return 0;
257} 256}
258 257
@@ -272,7 +271,7 @@ void __init leon_smp_done(void)
272 } 271 }
273 } 272 }
274 *prev = first; 273 *prev = first;
275 local_flush_cache_all(); 274 local_ops->cache_all();
276 275
277 /* Free unneeded trap tables */ 276 /* Free unneeded trap tables */
278 if (!cpu_present(1)) { 277 if (!cpu_present(1)) {
@@ -338,7 +337,7 @@ static void __init leon_ipi_init(void)
338 local_irq_save(flags); 337 local_irq_save(flags);
339 trap_table = &sparc_ttable[SP_TRAP_IRQ1 + (leon_ipi_irq - 1)]; 338 trap_table = &sparc_ttable[SP_TRAP_IRQ1 + (leon_ipi_irq - 1)];
340 trap_table->inst_three += smpleon_ipi - real_irq_entry; 339 trap_table->inst_three += smpleon_ipi - real_irq_entry;
341 local_flush_cache_all(); 340 local_ops->cache_all();
342 local_irq_restore(flags); 341 local_irq_restore(flags);
343 342
344 for_each_possible_cpu(cpu) { 343 for_each_possible_cpu(cpu) {
@@ -347,6 +346,13 @@ static void __init leon_ipi_init(void)
347 } 346 }
348} 347}
349 348
349static void leon_send_ipi(int cpu, int level)
350{
351 unsigned long mask;
352 mask = leon_get_irqmask(level);
353 LEON3_BYPASS_STORE_PA(&leon3_irqctrl_regs->force[cpu], mask);
354}
355
350static void leon_ipi_single(int cpu) 356static void leon_ipi_single(int cpu)
351{ 357{
352 struct leon_ipi_work *work = &per_cpu(leon_ipi_work, cpu); 358 struct leon_ipi_work *work = &per_cpu(leon_ipi_work, cpu);
@@ -355,7 +361,7 @@ static void leon_ipi_single(int cpu)
355 work->single = 1; 361 work->single = 1;
356 362
357 /* Generate IRQ on the CPU */ 363 /* Generate IRQ on the CPU */
358 set_cpu_int(cpu, leon_ipi_irq); 364 leon_send_ipi(cpu, leon_ipi_irq);
359} 365}
360 366
361static void leon_ipi_mask_one(int cpu) 367static void leon_ipi_mask_one(int cpu)
@@ -366,7 +372,7 @@ static void leon_ipi_mask_one(int cpu)
366 work->msk = 1; 372 work->msk = 1;
367 373
368 /* Generate IRQ on the CPU */ 374 /* Generate IRQ on the CPU */
369 set_cpu_int(cpu, leon_ipi_irq); 375 leon_send_ipi(cpu, leon_ipi_irq);
370} 376}
371 377
372static void leon_ipi_resched(int cpu) 378static void leon_ipi_resched(int cpu)
@@ -377,7 +383,7 @@ static void leon_ipi_resched(int cpu)
377 work->resched = 1; 383 work->resched = 1;
378 384
379 /* Generate IRQ on the CPU (any IRQ will cause resched) */ 385 /* Generate IRQ on the CPU (any IRQ will cause resched) */
380 set_cpu_int(cpu, leon_ipi_irq); 386 leon_send_ipi(cpu, leon_ipi_irq);
381} 387}
382 388
383void leonsmp_ipi_interrupt(void) 389void leonsmp_ipi_interrupt(void)
@@ -449,7 +455,7 @@ static void leon_cross_call(smpfunc_t func, cpumask_t mask, unsigned long arg1,
449 if (cpumask_test_cpu(i, &mask)) { 455 if (cpumask_test_cpu(i, &mask)) {
450 ccall_info.processors_in[i] = 0; 456 ccall_info.processors_in[i] = 0;
451 ccall_info.processors_out[i] = 0; 457 ccall_info.processors_out[i] = 0;
452 set_cpu_int(i, LEON3_IRQ_CROSS_CALL); 458 leon_send_ipi(i, LEON3_IRQ_CROSS_CALL);
453 459
454 } 460 }
455 } 461 }
@@ -492,68 +498,19 @@ void leon_cross_call_irq(void)
492 ccall_info.processors_out[i] = 1; 498 ccall_info.processors_out[i] = 1;
493} 499}
494 500
495irqreturn_t leon_percpu_timer_interrupt(int irq, void *unused) 501static const struct sparc32_ipi_ops leon_ipi_ops = {
496{ 502 .cross_call = leon_cross_call,
497 int cpu = smp_processor_id(); 503 .resched = leon_ipi_resched,
498 504 .single = leon_ipi_single,
499 leon_clear_profile_irq(cpu); 505 .mask_one = leon_ipi_mask_one,
500 506};
501 profile_tick(CPU_PROFILING);
502
503 if (!--prof_counter(cpu)) {
504 int user = user_mode(get_irq_regs());
505
506 update_process_times(user);
507
508 prof_counter(cpu) = prof_multiplier(cpu);
509 }
510
511 return IRQ_HANDLED;
512}
513
514static void __init smp_setup_percpu_timer(void)
515{
516 int cpu = smp_processor_id();
517
518 prof_counter(cpu) = prof_multiplier(cpu) = 1;
519}
520
521void __init leon_blackbox_id(unsigned *addr)
522{
523 int rd = *addr & 0x3e000000;
524 int rs1 = rd >> 11;
525
526 /* patch places where ___b_hard_smp_processor_id appears */
527 addr[0] = 0x81444000 | rd; /* rd %asr17, reg */
528 addr[1] = 0x8130201c | rd | rs1; /* srl reg, 0x1c, reg */
529 addr[2] = 0x01000000; /* nop */
530}
531
532void __init leon_blackbox_current(unsigned *addr)
533{
534 int rd = *addr & 0x3e000000;
535 int rs1 = rd >> 11;
536
537 /* patch LOAD_CURRENT macro where ___b_load_current appears */
538 addr[0] = 0x81444000 | rd; /* rd %asr17, reg */
539 addr[2] = 0x8130201c | rd | rs1; /* srl reg, 0x1c, reg */
540 addr[4] = 0x81282002 | rd | rs1; /* sll reg, 0x2, reg */
541
542}
543 507
544void __init leon_init_smp(void) 508void __init leon_init_smp(void)
545{ 509{
546 /* Patch ipi15 trap table */ 510 /* Patch ipi15 trap table */
547 t_nmi[1] = t_nmi[1] + (linux_trap_ipi15_leon - linux_trap_ipi15_sun4m); 511 t_nmi[1] = t_nmi[1] + (linux_trap_ipi15_leon - linux_trap_ipi15_sun4m);
548 512
549 BTFIXUPSET_BLACKBOX(hard_smp_processor_id, leon_blackbox_id); 513 sparc32_ipi_ops = &leon_ipi_ops;
550 BTFIXUPSET_BLACKBOX(load_current, leon_blackbox_current);
551 BTFIXUPSET_CALL(smp_cross_call, leon_cross_call, BTFIXUPCALL_NORM);
552 BTFIXUPSET_CALL(__hard_smp_processor_id, __leon_processor_id,
553 BTFIXUPCALL_NORM);
554 BTFIXUPSET_CALL(smp_ipi_resched, leon_ipi_resched, BTFIXUPCALL_NORM);
555 BTFIXUPSET_CALL(smp_ipi_single, leon_ipi_single, BTFIXUPCALL_NORM);
556 BTFIXUPSET_CALL(smp_ipi_mask_one, leon_ipi_mask_one, BTFIXUPCALL_NORM);
557} 514}
558 515
559#endif /* CONFIG_SPARC_LEON */ 516#endif /* CONFIG_SPARC_LEON */
diff --git a/arch/sparc/kernel/module.c b/arch/sparc/kernel/module.c
index 276359e1ff56..15e0a1693976 100644
--- a/arch/sparc/kernel/module.c
+++ b/arch/sparc/kernel/module.c
@@ -32,26 +32,11 @@ static void *module_map(unsigned long size)
32 GFP_KERNEL, PAGE_KERNEL, -1, 32 GFP_KERNEL, PAGE_KERNEL, -1,
33 __builtin_return_address(0)); 33 __builtin_return_address(0));
34} 34}
35
36static char *dot2underscore(char *name)
37{
38 return name;
39}
40#else 35#else
41static void *module_map(unsigned long size) 36static void *module_map(unsigned long size)
42{ 37{
43 return vmalloc(size); 38 return vmalloc(size);
44} 39}
45
46/* Replace references to .func with _Func */
47static char *dot2underscore(char *name)
48{
49 if (name[0] == '.') {
50 name[0] = '_';
51 name[1] = toupper(name[1]);
52 }
53 return name;
54}
55#endif /* CONFIG_SPARC64 */ 40#endif /* CONFIG_SPARC64 */
56 41
57void *module_alloc(unsigned long size) 42void *module_alloc(unsigned long size)
@@ -93,12 +78,8 @@ int module_frob_arch_sections(Elf_Ehdr *hdr,
93 78
94 for (i = 1; i < sechdrs[symidx].sh_size / sizeof(Elf_Sym); i++) { 79 for (i = 1; i < sechdrs[symidx].sh_size / sizeof(Elf_Sym); i++) {
95 if (sym[i].st_shndx == SHN_UNDEF) { 80 if (sym[i].st_shndx == SHN_UNDEF) {
96 if (ELF_ST_TYPE(sym[i].st_info) == STT_REGISTER) { 81 if (ELF_ST_TYPE(sym[i].st_info) == STT_REGISTER)
97 sym[i].st_shndx = SHN_ABS; 82 sym[i].st_shndx = SHN_ABS;
98 } else {
99 char *name = strtab + sym[i].st_name;
100 dot2underscore(name);
101 }
102 } 83 }
103 } 84 }
104 return 0; 85 return 0;
diff --git a/arch/sparc/kernel/muldiv.c b/arch/sparc/kernel/muldiv.c
deleted file mode 100644
index f7db516b07d8..000000000000
--- a/arch/sparc/kernel/muldiv.c
+++ /dev/null
@@ -1,238 +0,0 @@
1/*
2 * muldiv.c: Hardware multiply/division illegal instruction trap
3 * for sun4c/sun4 (which do not have those instructions)
4 *
5 * Copyright (C) 1996 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
6 * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
7 *
8 * 2004-12-25 Krzysztof Helt (krzysztof.h1@wp.pl)
9 * - fixed registers constrains in inline assembly declarations
10 */
11
12#include <linux/kernel.h>
13#include <linux/sched.h>
14#include <linux/mm.h>
15#include <asm/ptrace.h>
16#include <asm/processor.h>
17#include <asm/uaccess.h>
18
19#include "kernel.h"
20
21/* #define DEBUG_MULDIV */
22
23static inline int has_imm13(int insn)
24{
25 return (insn & 0x2000);
26}
27
28static inline int is_foocc(int insn)
29{
30 return (insn & 0x800000);
31}
32
33static inline int sign_extend_imm13(int imm)
34{
35 return imm << 19 >> 19;
36}
37
38static inline void advance(struct pt_regs *regs)
39{
40 regs->pc = regs->npc;
41 regs->npc += 4;
42}
43
44static inline void maybe_flush_windows(unsigned int rs1, unsigned int rs2,
45 unsigned int rd)
46{
47 if(rs2 >= 16 || rs1 >= 16 || rd >= 16) {
48 /* Wheee... */
49 __asm__ __volatile__("save %sp, -0x40, %sp\n\t"
50 "save %sp, -0x40, %sp\n\t"
51 "save %sp, -0x40, %sp\n\t"
52 "save %sp, -0x40, %sp\n\t"
53 "save %sp, -0x40, %sp\n\t"
54 "save %sp, -0x40, %sp\n\t"
55 "save %sp, -0x40, %sp\n\t"
56 "restore; restore; restore; restore;\n\t"
57 "restore; restore; restore;\n\t");
58 }
59}
60
61#define fetch_reg(reg, regs) ({ \
62 struct reg_window32 __user *win; \
63 register unsigned long ret; \
64 \
65 if (!(reg)) ret = 0; \
66 else if ((reg) < 16) { \
67 ret = regs->u_regs[(reg)]; \
68 } else { \
69 /* Ho hum, the slightly complicated case. */ \
70 win = (struct reg_window32 __user *)regs->u_regs[UREG_FP];\
71 if (get_user (ret, &win->locals[(reg) - 16])) return -1;\
72 } \
73 ret; \
74})
75
76static inline int
77store_reg(unsigned int result, unsigned int reg, struct pt_regs *regs)
78{
79 struct reg_window32 __user *win;
80
81 if (!reg)
82 return 0;
83 if (reg < 16) {
84 regs->u_regs[reg] = result;
85 return 0;
86 } else {
87 /* need to use put_user() in this case: */
88 win = (struct reg_window32 __user *) regs->u_regs[UREG_FP];
89 return (put_user(result, &win->locals[reg - 16]));
90 }
91}
92
93/* Should return 0 if mul/div emulation succeeded and SIGILL should
94 * not be issued.
95 */
96int do_user_muldiv(struct pt_regs *regs, unsigned long pc)
97{
98 unsigned int insn;
99 int inst;
100 unsigned int rs1, rs2, rdv;
101
102 if (!pc)
103 return -1; /* This happens to often, I think */
104 if (get_user (insn, (unsigned int __user *)pc))
105 return -1;
106 if ((insn & 0xc1400000) != 0x80400000)
107 return -1;
108 inst = ((insn >> 19) & 0xf);
109 if ((inst & 0xe) != 10 && (inst & 0xe) != 14)
110 return -1;
111
112 /* Now we know we have to do something with umul, smul, udiv or sdiv */
113 rs1 = (insn >> 14) & 0x1f;
114 rs2 = insn & 0x1f;
115 rdv = (insn >> 25) & 0x1f;
116 if (has_imm13(insn)) {
117 maybe_flush_windows(rs1, 0, rdv);
118 rs2 = sign_extend_imm13(insn);
119 } else {
120 maybe_flush_windows(rs1, rs2, rdv);
121 rs2 = fetch_reg(rs2, regs);
122 }
123 rs1 = fetch_reg(rs1, regs);
124 switch (inst) {
125 case 10: /* umul */
126#ifdef DEBUG_MULDIV
127 printk ("unsigned muldiv: 0x%x * 0x%x = ", rs1, rs2);
128#endif
129 __asm__ __volatile__ ("\n\t"
130 "mov %0, %%o0\n\t"
131 "call .umul\n\t"
132 " mov %1, %%o1\n\t"
133 "mov %%o0, %0\n\t"
134 "mov %%o1, %1\n\t"
135 : "=r" (rs1), "=r" (rs2)
136 : "0" (rs1), "1" (rs2)
137 : "o0", "o1", "o2", "o3", "o4", "o5", "o7", "cc");
138#ifdef DEBUG_MULDIV
139 printk ("0x%x%08x\n", rs2, rs1);
140#endif
141 if (store_reg(rs1, rdv, regs))
142 return -1;
143 regs->y = rs2;
144 break;
145 case 11: /* smul */
146#ifdef DEBUG_MULDIV
147 printk ("signed muldiv: 0x%x * 0x%x = ", rs1, rs2);
148#endif
149 __asm__ __volatile__ ("\n\t"
150 "mov %0, %%o0\n\t"
151 "call .mul\n\t"
152 " mov %1, %%o1\n\t"
153 "mov %%o0, %0\n\t"
154 "mov %%o1, %1\n\t"
155 : "=r" (rs1), "=r" (rs2)
156 : "0" (rs1), "1" (rs2)
157 : "o0", "o1", "o2", "o3", "o4", "o5", "o7", "cc");
158#ifdef DEBUG_MULDIV
159 printk ("0x%x%08x\n", rs2, rs1);
160#endif
161 if (store_reg(rs1, rdv, regs))
162 return -1;
163 regs->y = rs2;
164 break;
165 case 14: /* udiv */
166#ifdef DEBUG_MULDIV
167 printk ("unsigned muldiv: 0x%x%08x / 0x%x = ", regs->y, rs1, rs2);
168#endif
169 if (!rs2) {
170#ifdef DEBUG_MULDIV
171 printk ("DIVISION BY ZERO\n");
172#endif
173 handle_hw_divzero (regs, pc, regs->npc, regs->psr);
174 return 0;
175 }
176 __asm__ __volatile__ ("\n\t"
177 "mov %2, %%o0\n\t"
178 "mov %0, %%o1\n\t"
179 "mov %%g0, %%o2\n\t"
180 "call __udivdi3\n\t"
181 " mov %1, %%o3\n\t"
182 "mov %%o1, %0\n\t"
183 "mov %%o0, %1\n\t"
184 : "=r" (rs1), "=r" (rs2)
185 : "r" (regs->y), "0" (rs1), "1" (rs2)
186 : "o0", "o1", "o2", "o3", "o4", "o5", "o7",
187 "g1", "g2", "g3", "cc");
188#ifdef DEBUG_MULDIV
189 printk ("0x%x\n", rs1);
190#endif
191 if (store_reg(rs1, rdv, regs))
192 return -1;
193 break;
194 case 15: /* sdiv */
195#ifdef DEBUG_MULDIV
196 printk ("signed muldiv: 0x%x%08x / 0x%x = ", regs->y, rs1, rs2);
197#endif
198 if (!rs2) {
199#ifdef DEBUG_MULDIV
200 printk ("DIVISION BY ZERO\n");
201#endif
202 handle_hw_divzero (regs, pc, regs->npc, regs->psr);
203 return 0;
204 }
205 __asm__ __volatile__ ("\n\t"
206 "mov %2, %%o0\n\t"
207 "mov %0, %%o1\n\t"
208 "mov %%g0, %%o2\n\t"
209 "call __divdi3\n\t"
210 " mov %1, %%o3\n\t"
211 "mov %%o1, %0\n\t"
212 "mov %%o0, %1\n\t"
213 : "=r" (rs1), "=r" (rs2)
214 : "r" (regs->y), "0" (rs1), "1" (rs2)
215 : "o0", "o1", "o2", "o3", "o4", "o5", "o7",
216 "g1", "g2", "g3", "cc");
217#ifdef DEBUG_MULDIV
218 printk ("0x%x\n", rs1);
219#endif
220 if (store_reg(rs1, rdv, regs))
221 return -1;
222 break;
223 }
224 if (is_foocc (insn)) {
225 regs->psr &= ~PSR_ICC;
226 if ((inst & 0xe) == 14) {
227 /* ?div */
228 if (rs2) regs->psr |= PSR_V;
229 }
230 if (!rs1) regs->psr |= PSR_Z;
231 if (((int)rs1) < 0) regs->psr |= PSR_N;
232#ifdef DEBUG_MULDIV
233 printk ("psr muldiv: %08x\n", regs->psr);
234#endif
235 }
236 advance(regs);
237 return 0;
238}
diff --git a/arch/sparc/kernel/of_device_32.c b/arch/sparc/kernel/of_device_32.c
index 4ee8ce0d5d8d..185aa96fa5be 100644
--- a/arch/sparc/kernel/of_device_32.c
+++ b/arch/sparc/kernel/of_device_32.c
@@ -356,7 +356,7 @@ static struct platform_device * __init scan_one_device(struct device_node *dp,
356 op->archdata.num_irqs = len / sizeof(struct linux_prom_irqs); 356 op->archdata.num_irqs = len / sizeof(struct linux_prom_irqs);
357 for (i = 0; i < op->archdata.num_irqs; i++) 357 for (i = 0; i < op->archdata.num_irqs; i++)
358 op->archdata.irqs[i] = 358 op->archdata.irqs[i] =
359 sparc_irq_config.build_device_irq(op, intr[i].pri); 359 sparc_config.build_device_irq(op, intr[i].pri);
360 } else { 360 } else {
361 const unsigned int *irq = 361 const unsigned int *irq =
362 of_get_property(dp, "interrupts", &len); 362 of_get_property(dp, "interrupts", &len);
@@ -365,7 +365,7 @@ static struct platform_device * __init scan_one_device(struct device_node *dp,
365 op->archdata.num_irqs = len / sizeof(unsigned int); 365 op->archdata.num_irqs = len / sizeof(unsigned int);
366 for (i = 0; i < op->archdata.num_irqs; i++) 366 for (i = 0; i < op->archdata.num_irqs; i++)
367 op->archdata.irqs[i] = 367 op->archdata.irqs[i] =
368 sparc_irq_config.build_device_irq(op, irq[i]); 368 sparc_config.build_device_irq(op, irq[i]);
369 } else { 369 } else {
370 op->archdata.num_irqs = 0; 370 op->archdata.num_irqs = 0;
371 } 371 }
diff --git a/arch/sparc/kernel/pcic.c b/arch/sparc/kernel/pcic.c
index fcc148effaac..ded3f6090c3f 100644
--- a/arch/sparc/kernel/pcic.c
+++ b/arch/sparc/kernel/pcic.c
@@ -703,31 +703,28 @@ static void pcic_clear_clock_irq(void)
703 pcic_timer_dummy = readl(pcic0.pcic_regs+PCI_SYS_LIMIT); 703 pcic_timer_dummy = readl(pcic0.pcic_regs+PCI_SYS_LIMIT);
704} 704}
705 705
706static irqreturn_t pcic_timer_handler (int irq, void *h) 706/* CPU frequency is 100 MHz, timer increments every 4 CPU clocks */
707#define USECS_PER_JIFFY (1000000 / HZ)
708#define TICK_TIMER_LIMIT ((100 * 1000000 / 4) / HZ)
709
710static unsigned int pcic_cycles_offset(void)
707{ 711{
708 pcic_clear_clock_irq(); 712 u32 value, count;
709 xtime_update(1);
710#ifndef CONFIG_SMP
711 update_process_times(user_mode(get_irq_regs()));
712#endif
713 return IRQ_HANDLED;
714}
715 713
716#define USECS_PER_JIFFY 10000 /* We have 100HZ "standard" timer for sparc */ 714 value = readl(pcic0.pcic_regs + PCI_SYS_COUNTER);
717#define TICK_TIMER_LIMIT ((100*1000000/4)/100) 715 count = value & ~PCI_SYS_COUNTER_OVERFLOW;
718 716
719u32 pci_gettimeoffset(void) 717 if (value & PCI_SYS_COUNTER_OVERFLOW)
720{ 718 count += TICK_TIMER_LIMIT;
721 /* 719 /*
722 * We divide all by 100 720 * We divide all by HZ
723 * to have microsecond resolution and to avoid overflow 721 * to have microsecond resolution and to avoid overflow
724 */ 722 */
725 unsigned long count = 723 count = ((count / HZ) * USECS_PER_JIFFY) / (TICK_TIMER_LIMIT / HZ);
726 readl(pcic0.pcic_regs+PCI_SYS_COUNTER) & ~PCI_SYS_COUNTER_OVERFLOW;
727 count = ((count/100)*USECS_PER_JIFFY) / (TICK_TIMER_LIMIT/100);
728 return count * 1000;
729}
730 724
725 /* Coordinate with the sparc_config.clock_rate setting */
726 return count * 2;
727}
731 728
732void __init pci_time_init(void) 729void __init pci_time_init(void)
733{ 730{
@@ -736,9 +733,16 @@ void __init pci_time_init(void)
736 int timer_irq, irq; 733 int timer_irq, irq;
737 int err; 734 int err;
738 735
739 do_arch_gettimeoffset = pci_gettimeoffset; 736#ifndef CONFIG_SMP
740 737 /*
741 btfixup(); 738 * The clock_rate is in SBUS dimension.
739 * We take into account this in pcic_cycles_offset()
740 */
741 sparc_config.clock_rate = SBUS_CLOCK_RATE / HZ;
742 sparc_config.features |= FEAT_L10_CLOCKEVENT;
743#endif
744 sparc_config.features |= FEAT_L10_CLOCKSOURCE;
745 sparc_config.get_cycles_offset = pcic_cycles_offset;
742 746
743 writel (TICK_TIMER_LIMIT, pcic->pcic_regs+PCI_SYS_LIMIT); 747 writel (TICK_TIMER_LIMIT, pcic->pcic_regs+PCI_SYS_LIMIT);
744 /* PROM should set appropriate irq */ 748 /* PROM should set appropriate irq */
@@ -747,7 +751,7 @@ void __init pci_time_init(void)
747 writel (PCI_COUNTER_IRQ_SET(timer_irq, 0), 751 writel (PCI_COUNTER_IRQ_SET(timer_irq, 0),
748 pcic->pcic_regs+PCI_COUNTER_IRQ); 752 pcic->pcic_regs+PCI_COUNTER_IRQ);
749 irq = pcic_build_device_irq(NULL, timer_irq); 753 irq = pcic_build_device_irq(NULL, timer_irq);
750 err = request_irq(irq, pcic_timer_handler, 754 err = request_irq(irq, timer_interrupt,
751 IRQF_TIMER, "timer", NULL); 755 IRQF_TIMER, "timer", NULL);
752 if (err) { 756 if (err) {
753 prom_printf("time_init: unable to attach IRQ%d\n", timer_irq); 757 prom_printf("time_init: unable to attach IRQ%d\n", timer_irq);
@@ -875,10 +879,9 @@ static void pcic_load_profile_irq(int cpu, unsigned int limit)
875 879
876void __init sun4m_pci_init_IRQ(void) 880void __init sun4m_pci_init_IRQ(void)
877{ 881{
878 sparc_irq_config.build_device_irq = pcic_build_device_irq; 882 sparc_config.build_device_irq = pcic_build_device_irq;
879 883 sparc_config.clear_clock_irq = pcic_clear_clock_irq;
880 BTFIXUPSET_CALL(clear_clock_irq, pcic_clear_clock_irq, BTFIXUPCALL_NORM); 884 sparc_config.load_profile_irq = pcic_load_profile_irq;
881 BTFIXUPSET_CALL(load_profile_irq, pcic_load_profile_irq, BTFIXUPCALL_NORM);
882} 885}
883 886
884int pcibios_assign_resource(struct pci_dev *pdev, int resource) 887int pcibios_assign_resource(struct pci_dev *pdev, int resource)
diff --git a/arch/sparc/kernel/process_32.c b/arch/sparc/kernel/process_32.c
index efa07542e85f..fe6787cc62fc 100644
--- a/arch/sparc/kernel/process_32.c
+++ b/arch/sparc/kernel/process_32.c
@@ -67,8 +67,6 @@ struct thread_info *current_set[NR_CPUS];
67 67
68#ifndef CONFIG_SMP 68#ifndef CONFIG_SMP
69 69
70#define SUN4C_FAULT_HIGH 100
71
72/* 70/*
73 * the idle loop on a Sparc... ;) 71 * the idle loop on a Sparc... ;)
74 */ 72 */
@@ -76,36 +74,6 @@ void cpu_idle(void)
76{ 74{
77 /* endless idle loop with no priority at all */ 75 /* endless idle loop with no priority at all */
78 for (;;) { 76 for (;;) {
79 if (ARCH_SUN4C) {
80 static int count = HZ;
81 static unsigned long last_jiffies;
82 static unsigned long last_faults;
83 static unsigned long fps;
84 unsigned long now;
85 unsigned long faults;
86
87 extern unsigned long sun4c_kernel_faults;
88 extern void sun4c_grow_kernel_ring(void);
89
90 local_irq_disable();
91 now = jiffies;
92 count -= (now - last_jiffies);
93 last_jiffies = now;
94 if (count < 0) {
95 count += HZ;
96 faults = sun4c_kernel_faults;
97 fps = (fps + (faults - last_faults)) >> 1;
98 last_faults = faults;
99#if 0
100 printk("kernel faults / second = %ld\n", fps);
101#endif
102 if (fps >= SUN4C_FAULT_HIGH) {
103 sun4c_grow_kernel_ring();
104 }
105 }
106 local_irq_enable();
107 }
108
109 if (pm_idle) { 77 if (pm_idle) {
110 while (!need_resched()) 78 while (!need_resched())
111 (*pm_idle)(); 79 (*pm_idle)();
@@ -114,7 +82,6 @@ void cpu_idle(void)
114 cpu_relax(); 82 cpu_relax();
115 } 83 }
116 schedule_preempt_disabled(); 84 schedule_preempt_disabled();
117 check_pgt_cache();
118 } 85 }
119} 86}
120 87
@@ -137,7 +104,6 @@ void cpu_idle(void)
137 cpu_relax(); 104 cpu_relax();
138 } 105 }
139 schedule_preempt_disabled(); 106 schedule_preempt_disabled();
140 check_pgt_cache();
141 } 107 }
142} 108}
143 109
@@ -179,88 +145,6 @@ void machine_power_off(void)
179 machine_halt(); 145 machine_halt();
180} 146}
181 147
182#if 0
183
184static DEFINE_SPINLOCK(sparc_backtrace_lock);
185
186void __show_backtrace(unsigned long fp)
187{
188 struct reg_window32 *rw;
189 unsigned long flags;
190 int cpu = smp_processor_id();
191
192 spin_lock_irqsave(&sparc_backtrace_lock, flags);
193
194 rw = (struct reg_window32 *)fp;
195 while(rw && (((unsigned long) rw) >= PAGE_OFFSET) &&
196 !(((unsigned long) rw) & 0x7)) {
197 printk("CPU[%d]: ARGS[%08lx,%08lx,%08lx,%08lx,%08lx,%08lx] "
198 "FP[%08lx] CALLER[%08lx]: ", cpu,
199 rw->ins[0], rw->ins[1], rw->ins[2], rw->ins[3],
200 rw->ins[4], rw->ins[5],
201 rw->ins[6],
202 rw->ins[7]);
203 printk("%pS\n", (void *) rw->ins[7]);
204 rw = (struct reg_window32 *) rw->ins[6];
205 }
206 spin_unlock_irqrestore(&sparc_backtrace_lock, flags);
207}
208
209#define __SAVE __asm__ __volatile__("save %sp, -0x40, %sp\n\t")
210#define __RESTORE __asm__ __volatile__("restore %g0, %g0, %g0\n\t")
211#define __GET_FP(fp) __asm__ __volatile__("mov %%i6, %0" : "=r" (fp))
212
213void show_backtrace(void)
214{
215 unsigned long fp;
216
217 __SAVE; __SAVE; __SAVE; __SAVE;
218 __SAVE; __SAVE; __SAVE; __SAVE;
219 __RESTORE; __RESTORE; __RESTORE; __RESTORE;
220 __RESTORE; __RESTORE; __RESTORE; __RESTORE;
221
222 __GET_FP(fp);
223
224 __show_backtrace(fp);
225}
226
227#ifdef CONFIG_SMP
228void smp_show_backtrace_all_cpus(void)
229{
230 xc0((smpfunc_t) show_backtrace);
231 show_backtrace();
232}
233#endif
234
235void show_stackframe(struct sparc_stackf *sf)
236{
237 unsigned long size;
238 unsigned long *stk;
239 int i;
240
241 printk("l0: %08lx l1: %08lx l2: %08lx l3: %08lx "
242 "l4: %08lx l5: %08lx l6: %08lx l7: %08lx\n",
243 sf->locals[0], sf->locals[1], sf->locals[2], sf->locals[3],
244 sf->locals[4], sf->locals[5], sf->locals[6], sf->locals[7]);
245 printk("i0: %08lx i1: %08lx i2: %08lx i3: %08lx "
246 "i4: %08lx i5: %08lx fp: %08lx i7: %08lx\n",
247 sf->ins[0], sf->ins[1], sf->ins[2], sf->ins[3],
248 sf->ins[4], sf->ins[5], (unsigned long)sf->fp, sf->callers_pc);
249 printk("sp: %08lx x0: %08lx x1: %08lx x2: %08lx "
250 "x3: %08lx x4: %08lx x5: %08lx xx: %08lx\n",
251 (unsigned long)sf->structptr, sf->xargs[0], sf->xargs[1],
252 sf->xargs[2], sf->xargs[3], sf->xargs[4], sf->xargs[5],
253 sf->xxargs[0]);
254 size = ((unsigned long)sf->fp) - ((unsigned long)sf);
255 size -= STACKFRAME_SZ;
256 stk = (unsigned long *)((unsigned long)sf + STACKFRAME_SZ);
257 i = 0;
258 do {
259 printk("s%d: %08lx\n", i++, *stk++);
260 } while ((size -= sizeof(unsigned long)));
261}
262#endif
263
264void show_regs(struct pt_regs *r) 148void show_regs(struct pt_regs *r)
265{ 149{
266 struct reg_window32 *rw = (struct reg_window32 *) r->u_regs[14]; 150 struct reg_window32 *rw = (struct reg_window32 *) r->u_regs[14];
diff --git a/arch/sparc/kernel/rtrap_32.S b/arch/sparc/kernel/rtrap_32.S
index 5f5f74c2c2ca..7abc24e2bf1a 100644
--- a/arch/sparc/kernel/rtrap_32.S
+++ b/arch/sparc/kernel/rtrap_32.S
@@ -128,13 +128,12 @@ rtrap_patch2: and %glob_tmp, 0xff, %glob_tmp
128 128
129 wr %glob_tmp, 0x0, %wim 129 wr %glob_tmp, 0x0, %wim
130 130
131 /* Here comes the architecture specific 131 /* Here comes the architecture specific
132 * branch to the user stack checking routine 132 * branch to the user stack checking routine
133 * for return from traps. 133 * for return from traps.
134 */ 134 */
135 .globl rtrap_mmu_patchme 135 b srmmu_rett_stackchk
136rtrap_mmu_patchme: b sun4c_rett_stackchk 136 andcc %fp, 0x7, %g0
137 andcc %fp, 0x7, %g0
138 137
139ret_trap_userwins_ok: 138ret_trap_userwins_ok:
140 LOAD_PT_PRIV(sp, t_psr, t_pc, t_npc) 139 LOAD_PT_PRIV(sp, t_psr, t_pc, t_npc)
@@ -225,69 +224,6 @@ ret_trap_user_stack_is_bolixed:
225 b signal_p 224 b signal_p
226 ld [%curptr + TI_FLAGS], %g2 225 ld [%curptr + TI_FLAGS], %g2
227 226
228sun4c_rett_stackchk:
229 be 1f
230 and %fp, 0xfff, %g1 ! delay slot
231
232 b ret_trap_user_stack_is_bolixed + 0x4
233 wr %t_wim, 0x0, %wim
234
235 /* See if we have to check the sanity of one page or two */
2361:
237 add %g1, 0x38, %g1
238 sra %fp, 29, %g2
239 add %g2, 0x1, %g2
240 andncc %g2, 0x1, %g0
241 be 1f
242 andncc %g1, 0xff8, %g0
243
244 /* %sp is in vma hole, yuck */
245 b ret_trap_user_stack_is_bolixed + 0x4
246 wr %t_wim, 0x0, %wim
247
2481:
249 be sun4c_rett_onepage /* Only one page to check */
250 lda [%fp] ASI_PTE, %g2
251
252sun4c_rett_twopages:
253 add %fp, 0x38, %g1
254 sra %g1, 29, %g2
255 add %g2, 0x1, %g2
256 andncc %g2, 0x1, %g0
257 be 1f
258 lda [%g1] ASI_PTE, %g2
259
260 /* Second page is in vma hole */
261 b ret_trap_user_stack_is_bolixed + 0x4
262 wr %t_wim, 0x0, %wim
263
2641:
265 srl %g2, 29, %g2
266 andcc %g2, 0x4, %g0
267 bne sun4c_rett_onepage
268 lda [%fp] ASI_PTE, %g2
269
270 /* Second page has bad perms */
271 b ret_trap_user_stack_is_bolixed + 0x4
272 wr %t_wim, 0x0, %wim
273
274sun4c_rett_onepage:
275 srl %g2, 29, %g2
276 andcc %g2, 0x4, %g0
277 bne,a 1f
278 restore %g0, %g0, %g0
279
280 /* A page had bad page permissions, losing... */
281 b ret_trap_user_stack_is_bolixed + 0x4
282 wr %t_wim, 0x0, %wim
283
284 /* Whee, things are ok, load the window and continue. */
2851:
286 LOAD_WINDOW(sp)
287
288 b ret_trap_userwins_ok
289 save %g0, %g0, %g0
290
291 .globl srmmu_rett_stackchk 227 .globl srmmu_rett_stackchk
292srmmu_rett_stackchk: 228srmmu_rett_stackchk:
293 bne ret_trap_user_stack_is_bolixed 229 bne ret_trap_user_stack_is_bolixed
diff --git a/arch/sparc/kernel/rtrap_64.S b/arch/sparc/kernel/rtrap_64.S
index 9171fc238def..afa2a9e3d0a0 100644
--- a/arch/sparc/kernel/rtrap_64.S
+++ b/arch/sparc/kernel/rtrap_64.S
@@ -73,18 +73,8 @@ rtrap_nmi: ldx [%sp + PTREGS_OFF + PT_V9_TSTATE], %l1
73 .globl rtrap_irq, rtrap, irqsz_patchme, rtrap_xcall 73 .globl rtrap_irq, rtrap, irqsz_patchme, rtrap_xcall
74rtrap_irq: 74rtrap_irq:
75rtrap: 75rtrap:
76#ifndef CONFIG_SMP
77 sethi %hi(__cpu_data), %l0
78 lduw [%l0 + %lo(__cpu_data)], %l1
79#else
80 sethi %hi(__cpu_data), %l0
81 or %l0, %lo(__cpu_data), %l0
82 lduw [%l0 + %g5], %l1
83#endif
84 cmp %l1, 0
85
86 /* mm/ultra.S:xcall_report_regs KNOWS about this load. */ 76 /* mm/ultra.S:xcall_report_regs KNOWS about this load. */
87 ldx [%sp + PTREGS_OFF + PT_V9_TSTATE], %l1 77 ldx [%sp + PTREGS_OFF + PT_V9_TSTATE], %l1
88rtrap_xcall: 78rtrap_xcall:
89 sethi %hi(0xf << 20), %l4 79 sethi %hi(0xf << 20), %l4
90 and %l1, %l4, %l4 80 and %l1, %l4, %l4
diff --git a/arch/sparc/kernel/setup_32.c b/arch/sparc/kernel/setup_32.c
index d444468b27f6..c052313f4dc5 100644
--- a/arch/sparc/kernel/setup_32.c
+++ b/arch/sparc/kernel/setup_32.c
@@ -42,7 +42,6 @@
42#include <asm/vaddrs.h> 42#include <asm/vaddrs.h>
43#include <asm/mbus.h> 43#include <asm/mbus.h>
44#include <asm/idprom.h> 44#include <asm/idprom.h>
45#include <asm/machines.h>
46#include <asm/cpudata.h> 45#include <asm/cpudata.h>
47#include <asm/setup.h> 46#include <asm/setup.h>
48#include <asm/cacheflush.h> 47#include <asm/cacheflush.h>
@@ -106,7 +105,6 @@ unsigned long cmdline_memory_size __initdata = 0;
106 105
107/* which CPU booted us (0xff = not set) */ 106/* which CPU booted us (0xff = not set) */
108unsigned char boot_cpu_id = 0xff; /* 0xff will make it into DATA section... */ 107unsigned char boot_cpu_id = 0xff; /* 0xff will make it into DATA section... */
109unsigned char boot_cpu_id4; /* boot_cpu_id << 2 */
110 108
111static void 109static void
112prom_console_write(struct console *con, const char *s, unsigned n) 110prom_console_write(struct console *con, const char *s, unsigned n)
@@ -182,13 +180,6 @@ static void __init boot_flags_init(char *commands)
182 } 180 }
183} 181}
184 182
185/* This routine will in the future do all the nasty prom stuff
186 * to probe for the mmu type and its parameters, etc. This will
187 * also be where SMP things happen.
188 */
189
190extern void sun4c_probe_vac(void);
191
192extern unsigned short root_flags; 183extern unsigned short root_flags;
193extern unsigned short root_dev; 184extern unsigned short root_dev;
194extern unsigned short ram_flags; 185extern unsigned short ram_flags;
@@ -200,6 +191,52 @@ extern int root_mountflags;
200 191
201char reboot_command[COMMAND_LINE_SIZE]; 192char reboot_command[COMMAND_LINE_SIZE];
202 193
194struct cpuid_patch_entry {
195 unsigned int addr;
196 unsigned int sun4d[3];
197 unsigned int leon[3];
198};
199extern struct cpuid_patch_entry __cpuid_patch, __cpuid_patch_end;
200
201static void __init per_cpu_patch(void)
202{
203 struct cpuid_patch_entry *p;
204
205 if (sparc_cpu_model == sun4m) {
206 /* Nothing to do, this is what the unpatched code
207 * targets.
208 */
209 return;
210 }
211
212 p = &__cpuid_patch;
213 while (p < &__cpuid_patch_end) {
214 unsigned long addr = p->addr;
215 unsigned int *insns;
216
217 switch (sparc_cpu_model) {
218 case sun4d:
219 insns = &p->sun4d[0];
220 break;
221
222 case sparc_leon:
223 insns = &p->leon[0];
224 break;
225 default:
226 prom_printf("Unknown cpu type, halting.\n");
227 prom_halt();
228 }
229 *(unsigned int *) (addr + 0) = insns[0];
230 flushi(addr + 0);
231 *(unsigned int *) (addr + 4) = insns[1];
232 flushi(addr + 4);
233 *(unsigned int *) (addr + 8) = insns[2];
234 flushi(addr + 8);
235
236 p++;
237 }
238}
239
203enum sparc_cpu sparc_cpu_model; 240enum sparc_cpu sparc_cpu_model;
204EXPORT_SYMBOL(sparc_cpu_model); 241EXPORT_SYMBOL(sparc_cpu_model);
205 242
@@ -225,10 +262,6 @@ void __init setup_arch(char **cmdline_p)
225 262
226 /* Set sparc_cpu_model */ 263 /* Set sparc_cpu_model */
227 sparc_cpu_model = sun_unknown; 264 sparc_cpu_model = sun_unknown;
228 if (!strcmp(&cputypval[0], "sun4 "))
229 sparc_cpu_model = sun4;
230 if (!strcmp(&cputypval[0], "sun4c"))
231 sparc_cpu_model = sun4c;
232 if (!strcmp(&cputypval[0], "sun4m")) 265 if (!strcmp(&cputypval[0], "sun4m"))
233 sparc_cpu_model = sun4m; 266 sparc_cpu_model = sun4m;
234 if (!strcmp(&cputypval[0], "sun4s")) 267 if (!strcmp(&cputypval[0], "sun4s"))
@@ -244,12 +277,6 @@ void __init setup_arch(char **cmdline_p)
244 277
245 printk("ARCH: "); 278 printk("ARCH: ");
246 switch(sparc_cpu_model) { 279 switch(sparc_cpu_model) {
247 case sun4:
248 printk("SUN4\n");
249 break;
250 case sun4c:
251 printk("SUN4C\n");
252 break;
253 case sun4m: 280 case sun4m:
254 printk("SUN4M\n"); 281 printk("SUN4M\n");
255 break; 282 break;
@@ -275,8 +302,6 @@ void __init setup_arch(char **cmdline_p)
275#endif 302#endif
276 303
277 idprom_init(); 304 idprom_init();
278 if (ARCH_SUN4C)
279 sun4c_probe_vac();
280 load_mmu(); 305 load_mmu();
281 306
282 phys_base = 0xffffffffUL; 307 phys_base = 0xffffffffUL;
@@ -313,6 +338,9 @@ void __init setup_arch(char **cmdline_p)
313 init_mm.context = (unsigned long) NO_CONTEXT; 338 init_mm.context = (unsigned long) NO_CONTEXT;
314 init_task.thread.kregs = &fake_swapper_regs; 339 init_task.thread.kregs = &fake_swapper_regs;
315 340
341 /* Run-time patch instructions to match the cpu model */
342 per_cpu_patch();
343
316 paging_init(); 344 paging_init();
317 345
318 smp_setup_cpu_possible_map(); 346 smp_setup_cpu_possible_map();
diff --git a/arch/sparc/kernel/signal_32.c b/arch/sparc/kernel/signal_32.c
index 1e750e415d7a..ac8e66b50f07 100644
--- a/arch/sparc/kernel/signal_32.c
+++ b/arch/sparc/kernel/signal_32.c
@@ -217,12 +217,9 @@ segv:
217/* Checks if the fp is valid */ 217/* Checks if the fp is valid */
218static inline int invalid_frame_pointer(void __user *fp, int fplen) 218static inline int invalid_frame_pointer(void __user *fp, int fplen)
219{ 219{
220 if ((((unsigned long) fp) & 7) || 220 if ((((unsigned long) fp) & 7) || !__access_ok((unsigned long)fp, fplen))
221 !__access_ok((unsigned long)fp, fplen) ||
222 ((sparc_cpu_model == sun4 || sparc_cpu_model == sun4c) &&
223 ((unsigned long) fp < 0xe0000000 && (unsigned long) fp >= 0x20000000)))
224 return 1; 221 return 1;
225 222
226 return 0; 223 return 0;
227} 224}
228 225
diff --git a/arch/sparc/kernel/smp_32.c b/arch/sparc/kernel/smp_32.c
index f671e7fd6ddc..57713758079e 100644
--- a/arch/sparc/kernel/smp_32.c
+++ b/arch/sparc/kernel/smp_32.c
@@ -40,6 +40,8 @@ volatile unsigned long cpu_callin_map[NR_CPUS] __cpuinitdata = {0,};
40 40
41cpumask_t smp_commenced_mask = CPU_MASK_NONE; 41cpumask_t smp_commenced_mask = CPU_MASK_NONE;
42 42
43const struct sparc32_ipi_ops *sparc32_ipi_ops;
44
43/* The only guaranteed locking primitive available on all Sparc 45/* The only guaranteed locking primitive available on all Sparc
44 * processors is 'ldstub [%reg + immediate], %dest_reg' which atomically 46 * processors is 'ldstub [%reg + immediate], %dest_reg' which atomically
45 * places the current byte at the effective address into dest_reg and 47 * places the current byte at the effective address into dest_reg and
@@ -85,14 +87,6 @@ void __init smp_cpus_done(unsigned int max_cpus)
85 (bogosum/(5000/HZ))%100); 87 (bogosum/(5000/HZ))%100);
86 88
87 switch(sparc_cpu_model) { 89 switch(sparc_cpu_model) {
88 case sun4:
89 printk("SUN4\n");
90 BUG();
91 break;
92 case sun4c:
93 printk("SUN4C\n");
94 BUG();
95 break;
96 case sun4m: 90 case sun4m:
97 smp4m_smp_done(); 91 smp4m_smp_done();
98 break; 92 break;
@@ -132,7 +126,7 @@ void smp_send_reschedule(int cpu)
132 * a single CPU. The trap handler needs only to do trap entry/return 126 * a single CPU. The trap handler needs only to do trap entry/return
133 * to call schedule. 127 * to call schedule.
134 */ 128 */
135 BTFIXUP_CALL(smp_ipi_resched)(cpu); 129 sparc32_ipi_ops->resched(cpu);
136} 130}
137 131
138void smp_send_stop(void) 132void smp_send_stop(void)
@@ -142,7 +136,7 @@ void smp_send_stop(void)
142void arch_send_call_function_single_ipi(int cpu) 136void arch_send_call_function_single_ipi(int cpu)
143{ 137{
144 /* trigger one IPI single call on one CPU */ 138 /* trigger one IPI single call on one CPU */
145 BTFIXUP_CALL(smp_ipi_single)(cpu); 139 sparc32_ipi_ops->single(cpu);
146} 140}
147 141
148void arch_send_call_function_ipi_mask(const struct cpumask *mask) 142void arch_send_call_function_ipi_mask(const struct cpumask *mask)
@@ -151,7 +145,7 @@ void arch_send_call_function_ipi_mask(const struct cpumask *mask)
151 145
152 /* trigger IPI mask call on each CPU */ 146 /* trigger IPI mask call on each CPU */
153 for_each_cpu(cpu, mask) 147 for_each_cpu(cpu, mask)
154 BTFIXUP_CALL(smp_ipi_mask_one)(cpu); 148 sparc32_ipi_ops->mask_one(cpu);
155} 149}
156 150
157void smp_resched_interrupt(void) 151void smp_resched_interrupt(void)
@@ -179,150 +173,9 @@ void smp_call_function_interrupt(void)
179 irq_exit(); 173 irq_exit();
180} 174}
181 175
182void smp_flush_cache_all(void)
183{
184 xc0((smpfunc_t) BTFIXUP_CALL(local_flush_cache_all));
185 local_flush_cache_all();
186}
187
188void smp_flush_tlb_all(void)
189{
190 xc0((smpfunc_t) BTFIXUP_CALL(local_flush_tlb_all));
191 local_flush_tlb_all();
192}
193
194void smp_flush_cache_mm(struct mm_struct *mm)
195{
196 if(mm->context != NO_CONTEXT) {
197 cpumask_t cpu_mask;
198 cpumask_copy(&cpu_mask, mm_cpumask(mm));
199 cpumask_clear_cpu(smp_processor_id(), &cpu_mask);
200 if (!cpumask_empty(&cpu_mask))
201 xc1((smpfunc_t) BTFIXUP_CALL(local_flush_cache_mm), (unsigned long) mm);
202 local_flush_cache_mm(mm);
203 }
204}
205
206void smp_flush_tlb_mm(struct mm_struct *mm)
207{
208 if(mm->context != NO_CONTEXT) {
209 cpumask_t cpu_mask;
210 cpumask_copy(&cpu_mask, mm_cpumask(mm));
211 cpumask_clear_cpu(smp_processor_id(), &cpu_mask);
212 if (!cpumask_empty(&cpu_mask)) {
213 xc1((smpfunc_t) BTFIXUP_CALL(local_flush_tlb_mm), (unsigned long) mm);
214 if(atomic_read(&mm->mm_users) == 1 && current->active_mm == mm)
215 cpumask_copy(mm_cpumask(mm),
216 cpumask_of(smp_processor_id()));
217 }
218 local_flush_tlb_mm(mm);
219 }
220}
221
222void smp_flush_cache_range(struct vm_area_struct *vma, unsigned long start,
223 unsigned long end)
224{
225 struct mm_struct *mm = vma->vm_mm;
226
227 if (mm->context != NO_CONTEXT) {
228 cpumask_t cpu_mask;
229 cpumask_copy(&cpu_mask, mm_cpumask(mm));
230 cpumask_clear_cpu(smp_processor_id(), &cpu_mask);
231 if (!cpumask_empty(&cpu_mask))
232 xc3((smpfunc_t) BTFIXUP_CALL(local_flush_cache_range), (unsigned long) vma, start, end);
233 local_flush_cache_range(vma, start, end);
234 }
235}
236
237void smp_flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
238 unsigned long end)
239{
240 struct mm_struct *mm = vma->vm_mm;
241
242 if (mm->context != NO_CONTEXT) {
243 cpumask_t cpu_mask;
244 cpumask_copy(&cpu_mask, mm_cpumask(mm));
245 cpumask_clear_cpu(smp_processor_id(), &cpu_mask);
246 if (!cpumask_empty(&cpu_mask))
247 xc3((smpfunc_t) BTFIXUP_CALL(local_flush_tlb_range), (unsigned long) vma, start, end);
248 local_flush_tlb_range(vma, start, end);
249 }
250}
251
252void smp_flush_cache_page(struct vm_area_struct *vma, unsigned long page)
253{
254 struct mm_struct *mm = vma->vm_mm;
255
256 if(mm->context != NO_CONTEXT) {
257 cpumask_t cpu_mask;
258 cpumask_copy(&cpu_mask, mm_cpumask(mm));
259 cpumask_clear_cpu(smp_processor_id(), &cpu_mask);
260 if (!cpumask_empty(&cpu_mask))
261 xc2((smpfunc_t) BTFIXUP_CALL(local_flush_cache_page), (unsigned long) vma, page);
262 local_flush_cache_page(vma, page);
263 }
264}
265
266void smp_flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
267{
268 struct mm_struct *mm = vma->vm_mm;
269
270 if(mm->context != NO_CONTEXT) {
271 cpumask_t cpu_mask;
272 cpumask_copy(&cpu_mask, mm_cpumask(mm));
273 cpumask_clear_cpu(smp_processor_id(), &cpu_mask);
274 if (!cpumask_empty(&cpu_mask))
275 xc2((smpfunc_t) BTFIXUP_CALL(local_flush_tlb_page), (unsigned long) vma, page);
276 local_flush_tlb_page(vma, page);
277 }
278}
279
280void smp_flush_page_to_ram(unsigned long page)
281{
282 /* Current theory is that those who call this are the one's
283 * who have just dirtied their cache with the pages contents
284 * in kernel space, therefore we only run this on local cpu.
285 *
286 * XXX This experiment failed, research further... -DaveM
287 */
288#if 1
289 xc1((smpfunc_t) BTFIXUP_CALL(local_flush_page_to_ram), page);
290#endif
291 local_flush_page_to_ram(page);
292}
293
294void smp_flush_sig_insns(struct mm_struct *mm, unsigned long insn_addr)
295{
296 cpumask_t cpu_mask;
297 cpumask_copy(&cpu_mask, mm_cpumask(mm));
298 cpumask_clear_cpu(smp_processor_id(), &cpu_mask);
299 if (!cpumask_empty(&cpu_mask))
300 xc2((smpfunc_t) BTFIXUP_CALL(local_flush_sig_insns), (unsigned long) mm, insn_addr);
301 local_flush_sig_insns(mm, insn_addr);
302}
303
304extern unsigned int lvl14_resolution;
305
306/* /proc/profile writes can call this, don't __init it please. */
307static DEFINE_SPINLOCK(prof_setup_lock);
308
309int setup_profiling_timer(unsigned int multiplier) 176int setup_profiling_timer(unsigned int multiplier)
310{ 177{
311 int i; 178 return -EINVAL;
312 unsigned long flags;
313
314 /* Prevent level14 ticker IRQ flooding. */
315 if((!multiplier) || (lvl14_resolution / multiplier) < 500)
316 return -EINVAL;
317
318 spin_lock_irqsave(&prof_setup_lock, flags);
319 for_each_possible_cpu(i) {
320 load_profile_irq(i, lvl14_resolution / multiplier);
321 prof_multiplier(i) = multiplier;
322 }
323 spin_unlock_irqrestore(&prof_setup_lock, flags);
324
325 return 0;
326} 179}
327 180
328void __init smp_prepare_cpus(unsigned int max_cpus) 181void __init smp_prepare_cpus(unsigned int max_cpus)
@@ -345,14 +198,6 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
345 smp_store_cpu_info(boot_cpu_id); 198 smp_store_cpu_info(boot_cpu_id);
346 199
347 switch(sparc_cpu_model) { 200 switch(sparc_cpu_model) {
348 case sun4:
349 printk("SUN4\n");
350 BUG();
351 break;
352 case sun4c:
353 printk("SUN4C\n");
354 BUG();
355 break;
356 case sun4m: 201 case sun4m:
357 smp4m_boot_cpus(); 202 smp4m_boot_cpus();
358 break; 203 break;
@@ -418,14 +263,6 @@ int __cpuinit __cpu_up(unsigned int cpu)
418 int ret=0; 263 int ret=0;
419 264
420 switch(sparc_cpu_model) { 265 switch(sparc_cpu_model) {
421 case sun4:
422 printk("SUN4\n");
423 BUG();
424 break;
425 case sun4c:
426 printk("SUN4C\n");
427 BUG();
428 break;
429 case sun4m: 266 case sun4m:
430 ret = smp4m_boot_one_cpu(cpu); 267 ret = smp4m_boot_one_cpu(cpu);
431 break; 268 break;
diff --git a/arch/sparc/kernel/sparc_ksyms_32.c b/arch/sparc/kernel/sparc_ksyms_32.c
index baeab8720237..e521c54560f9 100644
--- a/arch/sparc/kernel/sparc_ksyms_32.c
+++ b/arch/sparc/kernel/sparc_ksyms_32.c
@@ -28,19 +28,5 @@ EXPORT_SYMBOL(__ndelay);
28EXPORT_SYMBOL(__ret_efault); 28EXPORT_SYMBOL(__ret_efault);
29EXPORT_SYMBOL(empty_zero_page); 29EXPORT_SYMBOL(empty_zero_page);
30 30
31/* Defined using magic */
32#ifndef CONFIG_SMP
33EXPORT_SYMBOL(BTFIXUP_CALL(___xchg32));
34#else
35EXPORT_SYMBOL(BTFIXUP_CALL(__hard_smp_processor_id));
36#endif
37EXPORT_SYMBOL(BTFIXUP_CALL(mmu_unlockarea));
38EXPORT_SYMBOL(BTFIXUP_CALL(mmu_lockarea));
39EXPORT_SYMBOL(BTFIXUP_CALL(mmu_get_scsi_sgl));
40EXPORT_SYMBOL(BTFIXUP_CALL(mmu_get_scsi_one));
41EXPORT_SYMBOL(BTFIXUP_CALL(mmu_release_scsi_sgl));
42EXPORT_SYMBOL(BTFIXUP_CALL(mmu_release_scsi_one));
43EXPORT_SYMBOL(BTFIXUP_CALL(pgprot_noncached));
44
45/* Exporting a symbol from /init/main.c */ 31/* Exporting a symbol from /init/main.c */
46EXPORT_SYMBOL(saved_command_line); 32EXPORT_SYMBOL(saved_command_line);
diff --git a/arch/sparc/kernel/sun4c_irq.c b/arch/sparc/kernel/sun4c_irq.c
deleted file mode 100644
index f6bf25a2ff80..000000000000
--- a/arch/sparc/kernel/sun4c_irq.c
+++ /dev/null
@@ -1,264 +0,0 @@
1/*
2 * sun4c irq support
3 *
4 * djhr: Hacked out of irq.c into a CPU dependent version.
5 *
6 * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
7 * Copyright (C) 1995 Miguel de Icaza (miguel@nuclecu.unam.mx)
8 * Copyright (C) 1995 Pete A. Zaitcev (zaitcev@yahoo.com)
9 * Copyright (C) 1996 Dave Redman (djhr@tadpole.co.uk)
10 */
11
12#include <linux/init.h>
13
14#include <asm/oplib.h>
15#include <asm/timer.h>
16#include <asm/irq.h>
17#include <asm/io.h>
18
19#include "irq.h"
20
21/* Sun4c interrupts are typically laid out as follows:
22 *
23 * 1 - Software interrupt, SBUS level 1
24 * 2 - SBUS level 2
25 * 3 - ESP SCSI, SBUS level 3
26 * 4 - Software interrupt
27 * 5 - Lance ethernet, SBUS level 4
28 * 6 - Software interrupt
29 * 7 - Graphics card, SBUS level 5
30 * 8 - SBUS level 6
31 * 9 - SBUS level 7
32 * 10 - Counter timer
33 * 11 - Floppy
34 * 12 - Zilog uart
35 * 13 - CS4231 audio
36 * 14 - Profiling timer
37 * 15 - NMI
38 *
39 * The interrupt enable bits in the interrupt mask register are
40 * really only used to enable/disable the timer interrupts, and
41 * for signalling software interrupts. There is also a master
42 * interrupt enable bit in this register.
43 *
44 * Interrupts are enabled by setting the SUN4C_INT_* bits, they
45 * are disabled by clearing those bits.
46 */
47
48/*
49 * Bit field defines for the interrupt registers on various
50 * Sparc machines.
51 */
52
53/* The sun4c interrupt register. */
54#define SUN4C_INT_ENABLE 0x01 /* Allow interrupts. */
55#define SUN4C_INT_E14 0x80 /* Enable level 14 IRQ. */
56#define SUN4C_INT_E10 0x20 /* Enable level 10 IRQ. */
57#define SUN4C_INT_E8 0x10 /* Enable level 8 IRQ. */
58#define SUN4C_INT_E6 0x08 /* Enable level 6 IRQ. */
59#define SUN4C_INT_E4 0x04 /* Enable level 4 IRQ. */
60#define SUN4C_INT_E1 0x02 /* Enable level 1 IRQ. */
61
62/*
63 * Pointer to the interrupt enable byte
64 * Used by entry.S
65 */
66unsigned char __iomem *interrupt_enable;
67
68static void sun4c_mask_irq(struct irq_data *data)
69{
70 unsigned long mask = (unsigned long)data->chip_data;
71
72 if (mask) {
73 unsigned long flags;
74
75 local_irq_save(flags);
76 mask = sbus_readb(interrupt_enable) & ~mask;
77 sbus_writeb(mask, interrupt_enable);
78 local_irq_restore(flags);
79 }
80}
81
82static void sun4c_unmask_irq(struct irq_data *data)
83{
84 unsigned long mask = (unsigned long)data->chip_data;
85
86 if (mask) {
87 unsigned long flags;
88
89 local_irq_save(flags);
90 mask = sbus_readb(interrupt_enable) | mask;
91 sbus_writeb(mask, interrupt_enable);
92 local_irq_restore(flags);
93 }
94}
95
96static unsigned int sun4c_startup_irq(struct irq_data *data)
97{
98 irq_link(data->irq);
99 sun4c_unmask_irq(data);
100
101 return 0;
102}
103
104static void sun4c_shutdown_irq(struct irq_data *data)
105{
106 sun4c_mask_irq(data);
107 irq_unlink(data->irq);
108}
109
110static struct irq_chip sun4c_irq = {
111 .name = "sun4c",
112 .irq_startup = sun4c_startup_irq,
113 .irq_shutdown = sun4c_shutdown_irq,
114 .irq_mask = sun4c_mask_irq,
115 .irq_unmask = sun4c_unmask_irq,
116};
117
118static unsigned int sun4c_build_device_irq(struct platform_device *op,
119 unsigned int real_irq)
120{
121 unsigned int irq;
122
123 if (real_irq >= 16) {
124 prom_printf("Bogus sun4c IRQ %u\n", real_irq);
125 prom_halt();
126 }
127
128 irq = irq_alloc(real_irq, real_irq);
129 if (irq) {
130 unsigned long mask = 0UL;
131
132 switch (real_irq) {
133 case 1:
134 mask = SUN4C_INT_E1;
135 break;
136 case 8:
137 mask = SUN4C_INT_E8;
138 break;
139 case 10:
140 mask = SUN4C_INT_E10;
141 break;
142 case 14:
143 mask = SUN4C_INT_E14;
144 break;
145 default:
146 /* All the rest are either always enabled,
147 * or are for signalling software interrupts.
148 */
149 break;
150 }
151 irq_set_chip_and_handler_name(irq, &sun4c_irq,
152 handle_level_irq, "level");
153 irq_set_chip_data(irq, (void *)mask);
154 }
155 return irq;
156}
157
158struct sun4c_timer_info {
159 u32 l10_count;
160 u32 l10_limit;
161 u32 l14_count;
162 u32 l14_limit;
163};
164
165static struct sun4c_timer_info __iomem *sun4c_timers;
166
167static void sun4c_clear_clock_irq(void)
168{
169 sbus_readl(&sun4c_timers->l10_limit);
170}
171
172static void sun4c_load_profile_irq(int cpu, unsigned int limit)
173{
174 /* Errm.. not sure how to do this.. */
175}
176
177static void __init sun4c_init_timers(irq_handler_t counter_fn)
178{
179 const struct linux_prom_irqs *prom_irqs;
180 struct device_node *dp;
181 unsigned int irq;
182 const u32 *addr;
183 int err;
184
185 dp = of_find_node_by_name(NULL, "counter-timer");
186 if (!dp) {
187 prom_printf("sun4c_init_timers: Unable to find counter-timer\n");
188 prom_halt();
189 }
190
191 addr = of_get_property(dp, "address", NULL);
192 if (!addr) {
193 prom_printf("sun4c_init_timers: No address property\n");
194 prom_halt();
195 }
196
197 sun4c_timers = (void __iomem *) (unsigned long) addr[0];
198
199 prom_irqs = of_get_property(dp, "intr", NULL);
200 of_node_put(dp);
201 if (!prom_irqs) {
202 prom_printf("sun4c_init_timers: No intr property\n");
203 prom_halt();
204 }
205
206 /* Have the level 10 timer tick at 100HZ. We don't touch the
207 * level 14 timer limit since we are letting the prom handle
208 * them until we have a real console driver so L1-A works.
209 */
210 sbus_writel((((1000000/HZ) + 1) << 10), &sun4c_timers->l10_limit);
211
212 master_l10_counter = &sun4c_timers->l10_count;
213
214 irq = sun4c_build_device_irq(NULL, prom_irqs[0].pri);
215 err = request_irq(irq, counter_fn, IRQF_TIMER, "timer", NULL);
216 if (err) {
217 prom_printf("sun4c_init_timers: request_irq() fails with %d\n", err);
218 prom_halt();
219 }
220
221 /* disable timer interrupt */
222 sun4c_mask_irq(irq_get_irq_data(irq));
223}
224
225#ifdef CONFIG_SMP
226static void sun4c_nop(void)
227{
228}
229#endif
230
231void __init sun4c_init_IRQ(void)
232{
233 struct device_node *dp;
234 const u32 *addr;
235
236 dp = of_find_node_by_name(NULL, "interrupt-enable");
237 if (!dp) {
238 prom_printf("sun4c_init_IRQ: Unable to find interrupt-enable\n");
239 prom_halt();
240 }
241
242 addr = of_get_property(dp, "address", NULL);
243 of_node_put(dp);
244 if (!addr) {
245 prom_printf("sun4c_init_IRQ: No address property\n");
246 prom_halt();
247 }
248
249 interrupt_enable = (void __iomem *) (unsigned long) addr[0];
250
251 BTFIXUPSET_CALL(clear_clock_irq, sun4c_clear_clock_irq, BTFIXUPCALL_NORM);
252 BTFIXUPSET_CALL(load_profile_irq, sun4c_load_profile_irq, BTFIXUPCALL_NOP);
253
254 sparc_irq_config.init_timers = sun4c_init_timers;
255 sparc_irq_config.build_device_irq = sun4c_build_device_irq;
256
257#ifdef CONFIG_SMP
258 BTFIXUPSET_CALL(set_cpu_int, sun4c_nop, BTFIXUPCALL_NOP);
259 BTFIXUPSET_CALL(clear_cpu_int, sun4c_nop, BTFIXUPCALL_NOP);
260 BTFIXUPSET_CALL(set_irq_udt, sun4c_nop, BTFIXUPCALL_NOP);
261#endif
262 sbus_writeb(SUN4C_INT_ENABLE, interrupt_enable);
263 /* Cannot enable interrupts until OBP ticker is disabled. */
264}
diff --git a/arch/sparc/kernel/sun4d_irq.c b/arch/sparc/kernel/sun4d_irq.c
index 1d13c5bda0b1..e490ac9327c7 100644
--- a/arch/sparc/kernel/sun4d_irq.c
+++ b/arch/sparc/kernel/sun4d_irq.c
@@ -15,6 +15,7 @@
15#include <asm/sbi.h> 15#include <asm/sbi.h>
16#include <asm/cacheflush.h> 16#include <asm/cacheflush.h>
17#include <asm/setup.h> 17#include <asm/setup.h>
18#include <asm/oplib.h>
18 19
19#include "kernel.h" 20#include "kernel.h"
20#include "irq.h" 21#include "irq.h"
@@ -243,19 +244,6 @@ struct irq_chip sun4d_irq = {
243}; 244};
244 245
245#ifdef CONFIG_SMP 246#ifdef CONFIG_SMP
246static void sun4d_set_cpu_int(int cpu, int level)
247{
248 sun4d_send_ipi(cpu, level);
249}
250
251static void sun4d_clear_ipi(int cpu, int level)
252{
253}
254
255static void sun4d_set_udt(int cpu)
256{
257}
258
259/* Setup IRQ distribution scheme. */ 247/* Setup IRQ distribution scheme. */
260void __init sun4d_distribute_irqs(void) 248void __init sun4d_distribute_irqs(void)
261{ 249{
@@ -282,7 +270,8 @@ static void sun4d_clear_clock_irq(void)
282 270
283static void sun4d_load_profile_irq(int cpu, unsigned int limit) 271static void sun4d_load_profile_irq(int cpu, unsigned int limit)
284{ 272{
285 bw_set_prof_limit(cpu, limit); 273 unsigned int value = limit ? timer_value(limit) : 0;
274 bw_set_prof_limit(cpu, value);
286} 275}
287 276
288static void __init sun4d_load_profile_irqs(void) 277static void __init sun4d_load_profile_irqs(void)
@@ -418,12 +407,12 @@ static void __init sun4d_fixup_trap_table(void)
418 trap_table->inst_two = lvl14_save[1]; 407 trap_table->inst_two = lvl14_save[1];
419 trap_table->inst_three = lvl14_save[2]; 408 trap_table->inst_three = lvl14_save[2];
420 trap_table->inst_four = lvl14_save[3]; 409 trap_table->inst_four = lvl14_save[3];
421 local_flush_cache_all(); 410 local_ops->cache_all();
422 local_irq_restore(flags); 411 local_irq_restore(flags);
423#endif 412#endif
424} 413}
425 414
426static void __init sun4d_init_timers(irq_handler_t counter_fn) 415static void __init sun4d_init_timers(void)
427{ 416{
428 struct device_node *dp; 417 struct device_node *dp;
429 struct resource res; 418 struct resource res;
@@ -466,12 +455,20 @@ static void __init sun4d_init_timers(irq_handler_t counter_fn)
466 prom_halt(); 455 prom_halt();
467 } 456 }
468 457
469 sbus_writel((((1000000/HZ) + 1) << 10), &sun4d_timers->l10_timer_limit); 458#ifdef CONFIG_SMP
459 sparc_config.cs_period = SBUS_CLOCK_RATE * 2; /* 2 seconds */
460#else
461 sparc_config.cs_period = SBUS_CLOCK_RATE / HZ; /* 1/HZ sec */
462 sparc_config.features |= FEAT_L10_CLOCKEVENT;
463#endif
464 sparc_config.features |= FEAT_L10_CLOCKSOURCE;
465 sbus_writel(timer_value(sparc_config.cs_period),
466 &sun4d_timers->l10_timer_limit);
470 467
471 master_l10_counter = &sun4d_timers->l10_cur_count; 468 master_l10_counter = &sun4d_timers->l10_cur_count;
472 469
473 irq = sun4d_build_timer_irq(board, SUN4D_TIMER_IRQ); 470 irq = sun4d_build_timer_irq(board, SUN4D_TIMER_IRQ);
474 err = request_irq(irq, counter_fn, IRQF_TIMER, "timer", NULL); 471 err = request_irq(irq, timer_interrupt, IRQF_TIMER, "timer", NULL);
475 if (err) { 472 if (err) {
476 prom_printf("sun4d_init_timers: request_irq() failed with %d\n", 473 prom_printf("sun4d_init_timers: request_irq() failed with %d\n",
477 err); 474 err);
@@ -509,16 +506,11 @@ void __init sun4d_init_IRQ(void)
509{ 506{
510 local_irq_disable(); 507 local_irq_disable();
511 508
512 BTFIXUPSET_CALL(clear_clock_irq, sun4d_clear_clock_irq, BTFIXUPCALL_NORM); 509 sparc_config.init_timers = sun4d_init_timers;
513 BTFIXUPSET_CALL(load_profile_irq, sun4d_load_profile_irq, BTFIXUPCALL_NORM); 510 sparc_config.build_device_irq = sun4d_build_device_irq;
511 sparc_config.clock_rate = SBUS_CLOCK_RATE;
512 sparc_config.clear_clock_irq = sun4d_clear_clock_irq;
513 sparc_config.load_profile_irq = sun4d_load_profile_irq;
514 514
515 sparc_irq_config.init_timers = sun4d_init_timers;
516 sparc_irq_config.build_device_irq = sun4d_build_device_irq;
517
518#ifdef CONFIG_SMP
519 BTFIXUPSET_CALL(set_cpu_int, sun4d_set_cpu_int, BTFIXUPCALL_NORM);
520 BTFIXUPSET_CALL(clear_cpu_int, sun4d_clear_ipi, BTFIXUPCALL_NOP);
521 BTFIXUPSET_CALL(set_irq_udt, sun4d_set_udt, BTFIXUPCALL_NOP);
522#endif
523 /* Cannot enable interrupts until OBP ticker is disabled. */ 515 /* Cannot enable interrupts until OBP ticker is disabled. */
524} 516}
diff --git a/arch/sparc/kernel/sun4d_smp.c b/arch/sparc/kernel/sun4d_smp.c
index 540b2fec09f0..f9a1a33cbb2c 100644
--- a/arch/sparc/kernel/sun4d_smp.c
+++ b/arch/sparc/kernel/sun4d_smp.c
@@ -6,16 +6,20 @@
6 * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) 6 * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
7 */ 7 */
8 8
9#include <linux/clockchips.h>
9#include <linux/interrupt.h> 10#include <linux/interrupt.h>
10#include <linux/profile.h> 11#include <linux/profile.h>
11#include <linux/delay.h> 12#include <linux/delay.h>
13#include <linux/sched.h>
12#include <linux/cpu.h> 14#include <linux/cpu.h>
13 15
16#include <asm/cacheflush.h>
17#include <asm/switch_to.h>
18#include <asm/tlbflush.h>
19#include <asm/timer.h>
20#include <asm/oplib.h>
14#include <asm/sbi.h> 21#include <asm/sbi.h>
15#include <asm/mmu.h> 22#include <asm/mmu.h>
16#include <asm/tlbflush.h>
17#include <asm/switch_to.h>
18#include <asm/cacheflush.h>
19 23
20#include "kernel.h" 24#include "kernel.h"
21#include "irq.h" 25#include "irq.h"
@@ -34,7 +38,6 @@ static inline unsigned long sun4d_swap(volatile unsigned long *ptr, unsigned lon
34} 38}
35 39
36static void smp4d_ipi_init(void); 40static void smp4d_ipi_init(void);
37static void smp_setup_percpu_timer(void);
38 41
39static unsigned char cpu_leds[32]; 42static unsigned char cpu_leds[32];
40 43
@@ -49,7 +52,7 @@ static inline void show_leds(int cpuid)
49 52
50void __cpuinit smp4d_callin(void) 53void __cpuinit smp4d_callin(void)
51{ 54{
52 int cpuid = hard_smp4d_processor_id(); 55 int cpuid = hard_smp_processor_id();
53 unsigned long flags; 56 unsigned long flags;
54 57
55 /* Show we are alive */ 58 /* Show we are alive */
@@ -59,8 +62,8 @@ void __cpuinit smp4d_callin(void)
59 /* Enable level15 interrupt, disable level14 interrupt for now */ 62 /* Enable level15 interrupt, disable level14 interrupt for now */
60 cc_set_imsk((cc_get_imsk() & ~0x8000) | 0x4000); 63 cc_set_imsk((cc_get_imsk() & ~0x8000) | 0x4000);
61 64
62 local_flush_cache_all(); 65 local_ops->cache_all();
63 local_flush_tlb_all(); 66 local_ops->tlb_all();
64 67
65 notify_cpu_starting(cpuid); 68 notify_cpu_starting(cpuid);
66 /* 69 /*
@@ -70,17 +73,17 @@ void __cpuinit smp4d_callin(void)
70 * to call the scheduler code. 73 * to call the scheduler code.
71 */ 74 */
72 /* Get our local ticker going. */ 75 /* Get our local ticker going. */
73 smp_setup_percpu_timer(); 76 register_percpu_ce(cpuid);
74 77
75 calibrate_delay(); 78 calibrate_delay();
76 smp_store_cpu_info(cpuid); 79 smp_store_cpu_info(cpuid);
77 local_flush_cache_all(); 80 local_ops->cache_all();
78 local_flush_tlb_all(); 81 local_ops->tlb_all();
79 82
80 /* Allow master to continue. */ 83 /* Allow master to continue. */
81 sun4d_swap((unsigned long *)&cpu_callin_map[cpuid], 1); 84 sun4d_swap((unsigned long *)&cpu_callin_map[cpuid], 1);
82 local_flush_cache_all(); 85 local_ops->cache_all();
83 local_flush_tlb_all(); 86 local_ops->tlb_all();
84 87
85 while ((unsigned long)current_set[cpuid] < PAGE_OFFSET) 88 while ((unsigned long)current_set[cpuid] < PAGE_OFFSET)
86 barrier(); 89 barrier();
@@ -100,8 +103,8 @@ void __cpuinit smp4d_callin(void)
100 atomic_inc(&init_mm.mm_count); 103 atomic_inc(&init_mm.mm_count);
101 current->active_mm = &init_mm; 104 current->active_mm = &init_mm;
102 105
103 local_flush_cache_all(); 106 local_ops->cache_all();
104 local_flush_tlb_all(); 107 local_ops->tlb_all();
105 108
106 local_irq_enable(); /* We don't allow PIL 14 yet */ 109 local_irq_enable(); /* We don't allow PIL 14 yet */
107 110
@@ -123,8 +126,7 @@ void __init smp4d_boot_cpus(void)
123 smp4d_ipi_init(); 126 smp4d_ipi_init();
124 if (boot_cpu_id) 127 if (boot_cpu_id)
125 current_set[0] = NULL; 128 current_set[0] = NULL;
126 smp_setup_percpu_timer(); 129 local_ops->cache_all();
127 local_flush_cache_all();
128} 130}
129 131
130int __cpuinit smp4d_boot_one_cpu(int i) 132int __cpuinit smp4d_boot_one_cpu(int i)
@@ -150,7 +152,7 @@ int __cpuinit smp4d_boot_one_cpu(int i)
150 152
151 /* whirrr, whirrr, whirrrrrrrrr... */ 153 /* whirrr, whirrr, whirrrrrrrrr... */
152 printk(KERN_INFO "Starting CPU %d at %p\n", i, entry); 154 printk(KERN_INFO "Starting CPU %d at %p\n", i, entry);
153 local_flush_cache_all(); 155 local_ops->cache_all();
154 prom_startcpu(cpu_node, 156 prom_startcpu(cpu_node,
155 &smp_penguin_ctable, 0, (char *)entry); 157 &smp_penguin_ctable, 0, (char *)entry);
156 158
@@ -168,7 +170,7 @@ int __cpuinit smp4d_boot_one_cpu(int i)
168 return -ENODEV; 170 return -ENODEV;
169 171
170 } 172 }
171 local_flush_cache_all(); 173 local_ops->cache_all();
172 return 0; 174 return 0;
173} 175}
174 176
@@ -185,7 +187,7 @@ void __init smp4d_smp_done(void)
185 prev = &cpu_data(i).next; 187 prev = &cpu_data(i).next;
186 } 188 }
187 *prev = first; 189 *prev = first;
188 local_flush_cache_all(); 190 local_ops->cache_all();
189 191
190 /* Ok, they are spinning and ready to go. */ 192 /* Ok, they are spinning and ready to go. */
191 smp_processors_ready = 1; 193 smp_processors_ready = 1;
@@ -233,7 +235,20 @@ void sun4d_ipi_interrupt(void)
233 } 235 }
234} 236}
235 237
236static void smp4d_ipi_single(int cpu) 238/* +-------+-------------+-----------+------------------------------------+
239 * | bcast | devid | sid | levels mask |
240 * +-------+-------------+-----------+------------------------------------+
241 * 31 30 23 22 15 14 0
242 */
243#define IGEN_MESSAGE(bcast, devid, sid, levels) \
244 (((bcast) << 31) | ((devid) << 23) | ((sid) << 15) | (levels))
245
246static void sun4d_send_ipi(int cpu, int level)
247{
248 cc_set_igen(IGEN_MESSAGE(0, cpu << 3, 6 + ((level >> 1) & 7), 1 << (level - 1)));
249}
250
251static void sun4d_ipi_single(int cpu)
237{ 252{
238 struct sun4d_ipi_work *work = &per_cpu(sun4d_ipi_work, cpu); 253 struct sun4d_ipi_work *work = &per_cpu(sun4d_ipi_work, cpu);
239 254
@@ -244,7 +259,7 @@ static void smp4d_ipi_single(int cpu)
244 sun4d_send_ipi(cpu, SUN4D_IPI_IRQ); 259 sun4d_send_ipi(cpu, SUN4D_IPI_IRQ);
245} 260}
246 261
247static void smp4d_ipi_mask_one(int cpu) 262static void sun4d_ipi_mask_one(int cpu)
248{ 263{
249 struct sun4d_ipi_work *work = &per_cpu(sun4d_ipi_work, cpu); 264 struct sun4d_ipi_work *work = &per_cpu(sun4d_ipi_work, cpu);
250 265
@@ -255,7 +270,7 @@ static void smp4d_ipi_mask_one(int cpu)
255 sun4d_send_ipi(cpu, SUN4D_IPI_IRQ); 270 sun4d_send_ipi(cpu, SUN4D_IPI_IRQ);
256} 271}
257 272
258static void smp4d_ipi_resched(int cpu) 273static void sun4d_ipi_resched(int cpu)
259{ 274{
260 struct sun4d_ipi_work *work = &per_cpu(sun4d_ipi_work, cpu); 275 struct sun4d_ipi_work *work = &per_cpu(sun4d_ipi_work, cpu);
261 276
@@ -280,7 +295,7 @@ static struct smp_funcall {
280static DEFINE_SPINLOCK(cross_call_lock); 295static DEFINE_SPINLOCK(cross_call_lock);
281 296
282/* Cross calls must be serialized, at least currently. */ 297/* Cross calls must be serialized, at least currently. */
283static void smp4d_cross_call(smpfunc_t func, cpumask_t mask, unsigned long arg1, 298static void sun4d_cross_call(smpfunc_t func, cpumask_t mask, unsigned long arg1,
284 unsigned long arg2, unsigned long arg3, 299 unsigned long arg2, unsigned long arg3,
285 unsigned long arg4) 300 unsigned long arg4)
286{ 301{
@@ -352,7 +367,7 @@ static void smp4d_cross_call(smpfunc_t func, cpumask_t mask, unsigned long arg1,
352/* Running cross calls. */ 367/* Running cross calls. */
353void smp4d_cross_call_irq(void) 368void smp4d_cross_call_irq(void)
354{ 369{
355 int i = hard_smp4d_processor_id(); 370 int i = hard_smp_processor_id();
356 371
357 ccall_info.processors_in[i] = 1; 372 ccall_info.processors_in[i] = 1;
358 ccall_info.func(ccall_info.arg1, ccall_info.arg2, ccall_info.arg3, 373 ccall_info.func(ccall_info.arg1, ccall_info.arg2, ccall_info.arg3,
@@ -363,7 +378,8 @@ void smp4d_cross_call_irq(void)
363void smp4d_percpu_timer_interrupt(struct pt_regs *regs) 378void smp4d_percpu_timer_interrupt(struct pt_regs *regs)
364{ 379{
365 struct pt_regs *old_regs; 380 struct pt_regs *old_regs;
366 int cpu = hard_smp4d_processor_id(); 381 int cpu = hard_smp_processor_id();
382 struct clock_event_device *ce;
367 static int cpu_tick[NR_CPUS]; 383 static int cpu_tick[NR_CPUS];
368 static char led_mask[] = { 0xe, 0xd, 0xb, 0x7, 0xb, 0xd }; 384 static char led_mask[] = { 0xe, 0xd, 0xb, 0x7, 0xb, 0xd };
369 385
@@ -379,45 +395,21 @@ void smp4d_percpu_timer_interrupt(struct pt_regs *regs)
379 show_leds(cpu); 395 show_leds(cpu);
380 } 396 }
381 397
382 profile_tick(CPU_PROFILING); 398 ce = &per_cpu(sparc32_clockevent, cpu);
383
384 if (!--prof_counter(cpu)) {
385 int user = user_mode(regs);
386 399
387 irq_enter(); 400 irq_enter();
388 update_process_times(user); 401 ce->event_handler(ce);
389 irq_exit(); 402 irq_exit();
390 403
391 prof_counter(cpu) = prof_multiplier(cpu);
392 }
393 set_irq_regs(old_regs); 404 set_irq_regs(old_regs);
394} 405}
395 406
396static void __cpuinit smp_setup_percpu_timer(void) 407static const struct sparc32_ipi_ops sun4d_ipi_ops = {
397{ 408 .cross_call = sun4d_cross_call,
398 int cpu = hard_smp4d_processor_id(); 409 .resched = sun4d_ipi_resched,
399 410 .single = sun4d_ipi_single,
400 prof_counter(cpu) = prof_multiplier(cpu) = 1; 411 .mask_one = sun4d_ipi_mask_one,
401 load_profile_irq(cpu, lvl14_resolution); 412};
402}
403
404void __init smp4d_blackbox_id(unsigned *addr)
405{
406 int rd = *addr & 0x3e000000;
407
408 addr[0] = 0xc0800800 | rd; /* lda [%g0] ASI_M_VIKING_TMP1, reg */
409 addr[1] = 0x01000000; /* nop */
410 addr[2] = 0x01000000; /* nop */
411}
412
413void __init smp4d_blackbox_current(unsigned *addr)
414{
415 int rd = *addr & 0x3e000000;
416
417 addr[0] = 0xc0800800 | rd; /* lda [%g0] ASI_M_VIKING_TMP1, reg */
418 addr[2] = 0x81282002 | rd | (rd >> 11); /* sll reg, 2, reg */
419 addr[4] = 0x01000000; /* nop */
420}
421 413
422void __init sun4d_init_smp(void) 414void __init sun4d_init_smp(void)
423{ 415{
@@ -426,14 +418,7 @@ void __init sun4d_init_smp(void)
426 /* Patch ipi15 trap table */ 418 /* Patch ipi15 trap table */
427 t_nmi[1] = t_nmi[1] + (linux_trap_ipi15_sun4d - linux_trap_ipi15_sun4m); 419 t_nmi[1] = t_nmi[1] + (linux_trap_ipi15_sun4d - linux_trap_ipi15_sun4m);
428 420
429 /* And set btfixup... */ 421 sparc32_ipi_ops = &sun4d_ipi_ops;
430 BTFIXUPSET_BLACKBOX(hard_smp_processor_id, smp4d_blackbox_id);
431 BTFIXUPSET_BLACKBOX(load_current, smp4d_blackbox_current);
432 BTFIXUPSET_CALL(smp_cross_call, smp4d_cross_call, BTFIXUPCALL_NORM);
433 BTFIXUPSET_CALL(__hard_smp_processor_id, __smp4d_processor_id, BTFIXUPCALL_NORM);
434 BTFIXUPSET_CALL(smp_ipi_resched, smp4d_ipi_resched, BTFIXUPCALL_NORM);
435 BTFIXUPSET_CALL(smp_ipi_single, smp4d_ipi_single, BTFIXUPCALL_NORM);
436 BTFIXUPSET_CALL(smp_ipi_mask_one, smp4d_ipi_mask_one, BTFIXUPCALL_NORM);
437 422
438 for (i = 0; i < NR_CPUS; i++) { 423 for (i = 0; i < NR_CPUS; i++) {
439 ccall_info.processors_in[i] = 1; 424 ccall_info.processors_in[i] = 1;
diff --git a/arch/sparc/kernel/sun4m_irq.c b/arch/sparc/kernel/sun4m_irq.c
index e61165161dd3..c5ade9d27a1d 100644
--- a/arch/sparc/kernel/sun4m_irq.c
+++ b/arch/sparc/kernel/sun4m_irq.c
@@ -112,9 +112,6 @@ struct sun4m_handler_data {
112#define SUN4M_INT_E14 0x00000080 112#define SUN4M_INT_E14 0x00000080
113#define SUN4M_INT_E10 0x00080000 113#define SUN4M_INT_E10 0x00080000
114 114
115#define SUN4M_HARD_INT(x) (0x000000001 << (x))
116#define SUN4M_SOFT_INT(x) (0x000010000 << (x))
117
118#define SUN4M_INT_MASKALL 0x80000000 /* mask all interrupts */ 115#define SUN4M_INT_MASKALL 0x80000000 /* mask all interrupts */
119#define SUN4M_INT_MODULE_ERR 0x40000000 /* module error */ 116#define SUN4M_INT_MODULE_ERR 0x40000000 /* module error */
120#define SUN4M_INT_M2S_WRITE_ERR 0x20000000 /* write buffer error */ 117#define SUN4M_INT_M2S_WRITE_ERR 0x20000000 /* write buffer error */
@@ -282,23 +279,6 @@ out:
282 return irq; 279 return irq;
283} 280}
284 281
285#ifdef CONFIG_SMP
286static void sun4m_send_ipi(int cpu, int level)
287{
288 sbus_writel(SUN4M_SOFT_INT(level), &sun4m_irq_percpu[cpu]->set);
289}
290
291static void sun4m_clear_ipi(int cpu, int level)
292{
293 sbus_writel(SUN4M_SOFT_INT(level), &sun4m_irq_percpu[cpu]->clear);
294}
295
296static void sun4m_set_udt(int cpu)
297{
298 sbus_writel(cpu, &sun4m_irq_global->interrupt_target);
299}
300#endif
301
302struct sun4m_timer_percpu { 282struct sun4m_timer_percpu {
303 u32 l14_limit; 283 u32 l14_limit;
304 u32 l14_count; 284 u32 l14_count;
@@ -318,9 +298,6 @@ struct sun4m_timer_global {
318 298
319static struct sun4m_timer_global __iomem *timers_global; 299static struct sun4m_timer_global __iomem *timers_global;
320 300
321
322unsigned int lvl14_resolution = (((1000000/HZ) + 1) << 10);
323
324static void sun4m_clear_clock_irq(void) 301static void sun4m_clear_clock_irq(void)
325{ 302{
326 sbus_readl(&timers_global->l10_limit); 303 sbus_readl(&timers_global->l10_limit);
@@ -369,10 +346,11 @@ void sun4m_clear_profile_irq(int cpu)
369 346
370static void sun4m_load_profile_irq(int cpu, unsigned int limit) 347static void sun4m_load_profile_irq(int cpu, unsigned int limit)
371{ 348{
372 sbus_writel(limit, &timers_percpu[cpu]->l14_limit); 349 unsigned int value = limit ? timer_value(limit) : 0;
350 sbus_writel(value, &timers_percpu[cpu]->l14_limit);
373} 351}
374 352
375static void __init sun4m_init_timers(irq_handler_t counter_fn) 353static void __init sun4m_init_timers(void)
376{ 354{
377 struct device_node *dp = of_find_node_by_name(NULL, "counter"); 355 struct device_node *dp = of_find_node_by_name(NULL, "counter");
378 int i, err, len, num_cpu_timers; 356 int i, err, len, num_cpu_timers;
@@ -402,13 +380,22 @@ static void __init sun4m_init_timers(irq_handler_t counter_fn)
402 /* Every per-cpu timer works in timer mode */ 380 /* Every per-cpu timer works in timer mode */
403 sbus_writel(0x00000000, &timers_global->timer_config); 381 sbus_writel(0x00000000, &timers_global->timer_config);
404 382
405 sbus_writel((((1000000/HZ) + 1) << 10), &timers_global->l10_limit); 383#ifdef CONFIG_SMP
384 sparc_config.cs_period = SBUS_CLOCK_RATE * 2; /* 2 seconds */
385 sparc_config.features |= FEAT_L14_ONESHOT;
386#else
387 sparc_config.cs_period = SBUS_CLOCK_RATE / HZ; /* 1/HZ sec */
388 sparc_config.features |= FEAT_L10_CLOCKEVENT;
389#endif
390 sparc_config.features |= FEAT_L10_CLOCKSOURCE;
391 sbus_writel(timer_value(sparc_config.cs_period),
392 &timers_global->l10_limit);
406 393
407 master_l10_counter = &timers_global->l10_count; 394 master_l10_counter = &timers_global->l10_count;
408 395
409 irq = sun4m_build_device_irq(NULL, SUN4M_TIMER_IRQ); 396 irq = sun4m_build_device_irq(NULL, SUN4M_TIMER_IRQ);
410 397
411 err = request_irq(irq, counter_fn, IRQF_TIMER, "timer", NULL); 398 err = request_irq(irq, timer_interrupt, IRQF_TIMER, "timer", NULL);
412 if (err) { 399 if (err) {
413 printk(KERN_ERR "sun4m_init_timers: Register IRQ error %d.\n", 400 printk(KERN_ERR "sun4m_init_timers: Register IRQ error %d.\n",
414 err); 401 err);
@@ -434,7 +421,7 @@ static void __init sun4m_init_timers(irq_handler_t counter_fn)
434 trap_table->inst_two = lvl14_save[1]; 421 trap_table->inst_two = lvl14_save[1];
435 trap_table->inst_three = lvl14_save[2]; 422 trap_table->inst_three = lvl14_save[2];
436 trap_table->inst_four = lvl14_save[3]; 423 trap_table->inst_four = lvl14_save[3];
437 local_flush_cache_all(); 424 local_ops->cache_all();
438 local_irq_restore(flags); 425 local_irq_restore(flags);
439 } 426 }
440#endif 427#endif
@@ -475,17 +462,12 @@ void __init sun4m_init_IRQ(void)
475 if (num_cpu_iregs == 4) 462 if (num_cpu_iregs == 4)
476 sbus_writel(0, &sun4m_irq_global->interrupt_target); 463 sbus_writel(0, &sun4m_irq_global->interrupt_target);
477 464
478 BTFIXUPSET_CALL(clear_clock_irq, sun4m_clear_clock_irq, BTFIXUPCALL_NORM); 465 sparc_config.init_timers = sun4m_init_timers;
479 BTFIXUPSET_CALL(load_profile_irq, sun4m_load_profile_irq, BTFIXUPCALL_NORM); 466 sparc_config.build_device_irq = sun4m_build_device_irq;
480 467 sparc_config.clock_rate = SBUS_CLOCK_RATE;
481 sparc_irq_config.init_timers = sun4m_init_timers; 468 sparc_config.clear_clock_irq = sun4m_clear_clock_irq;
482 sparc_irq_config.build_device_irq = sun4m_build_device_irq; 469 sparc_config.load_profile_irq = sun4m_load_profile_irq;
483 470
484#ifdef CONFIG_SMP
485 BTFIXUPSET_CALL(set_cpu_int, sun4m_send_ipi, BTFIXUPCALL_NORM);
486 BTFIXUPSET_CALL(clear_cpu_int, sun4m_clear_ipi, BTFIXUPCALL_NORM);
487 BTFIXUPSET_CALL(set_irq_udt, sun4m_set_udt, BTFIXUPCALL_NORM);
488#endif
489 471
490 /* Cannot enable interrupts until OBP ticker is disabled. */ 472 /* Cannot enable interrupts until OBP ticker is disabled. */
491} 473}
diff --git a/arch/sparc/kernel/sun4m_smp.c b/arch/sparc/kernel/sun4m_smp.c
index 02db9a0412ce..960e8ab47b12 100644
--- a/arch/sparc/kernel/sun4m_smp.c
+++ b/arch/sparc/kernel/sun4m_smp.c
@@ -4,14 +4,18 @@
4 * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) 4 * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
5 */ 5 */
6 6
7#include <linux/clockchips.h>
7#include <linux/interrupt.h> 8#include <linux/interrupt.h>
8#include <linux/profile.h> 9#include <linux/profile.h>
9#include <linux/delay.h> 10#include <linux/delay.h>
11#include <linux/sched.h>
10#include <linux/cpu.h> 12#include <linux/cpu.h>
11 13
12#include <asm/cacheflush.h> 14#include <asm/cacheflush.h>
13#include <asm/switch_to.h> 15#include <asm/switch_to.h>
14#include <asm/tlbflush.h> 16#include <asm/tlbflush.h>
17#include <asm/timer.h>
18#include <asm/oplib.h>
15 19
16#include "irq.h" 20#include "irq.h"
17#include "kernel.h" 21#include "kernel.h"
@@ -30,26 +34,22 @@ swap_ulong(volatile unsigned long *ptr, unsigned long val)
30 return val; 34 return val;
31} 35}
32 36
33static void smp4m_ipi_init(void);
34static void smp_setup_percpu_timer(void);
35
36void __cpuinit smp4m_callin(void) 37void __cpuinit smp4m_callin(void)
37{ 38{
38 int cpuid = hard_smp_processor_id(); 39 int cpuid = hard_smp_processor_id();
39 40
40 local_flush_cache_all(); 41 local_ops->cache_all();
41 local_flush_tlb_all(); 42 local_ops->tlb_all();
42 43
43 notify_cpu_starting(cpuid); 44 notify_cpu_starting(cpuid);
44 45
45 /* Get our local ticker going. */ 46 register_percpu_ce(cpuid);
46 smp_setup_percpu_timer();
47 47
48 calibrate_delay(); 48 calibrate_delay();
49 smp_store_cpu_info(cpuid); 49 smp_store_cpu_info(cpuid);
50 50
51 local_flush_cache_all(); 51 local_ops->cache_all();
52 local_flush_tlb_all(); 52 local_ops->tlb_all();
53 53
54 /* 54 /*
55 * Unblock the master CPU _only_ when the scheduler state 55 * Unblock the master CPU _only_ when the scheduler state
@@ -61,8 +61,8 @@ void __cpuinit smp4m_callin(void)
61 swap_ulong(&cpu_callin_map[cpuid], 1); 61 swap_ulong(&cpu_callin_map[cpuid], 1);
62 62
63 /* XXX: What's up with all the flushes? */ 63 /* XXX: What's up with all the flushes? */
64 local_flush_cache_all(); 64 local_ops->cache_all();
65 local_flush_tlb_all(); 65 local_ops->tlb_all();
66 66
67 /* Fix idle thread fields. */ 67 /* Fix idle thread fields. */
68 __asm__ __volatile__("ld [%0], %%g6\n\t" 68 __asm__ __volatile__("ld [%0], %%g6\n\t"
@@ -86,9 +86,8 @@ void __cpuinit smp4m_callin(void)
86 */ 86 */
87void __init smp4m_boot_cpus(void) 87void __init smp4m_boot_cpus(void)
88{ 88{
89 smp4m_ipi_init(); 89 sun4m_unmask_profile_irq();
90 smp_setup_percpu_timer(); 90 local_ops->cache_all();
91 local_flush_cache_all();
92} 91}
93 92
94int __cpuinit smp4m_boot_one_cpu(int i) 93int __cpuinit smp4m_boot_one_cpu(int i)
@@ -117,7 +116,7 @@ int __cpuinit smp4m_boot_one_cpu(int i)
117 116
118 /* whirrr, whirrr, whirrrrrrrrr... */ 117 /* whirrr, whirrr, whirrrrrrrrr... */
119 printk(KERN_INFO "Starting CPU %d at %p\n", i, entry); 118 printk(KERN_INFO "Starting CPU %d at %p\n", i, entry);
120 local_flush_cache_all(); 119 local_ops->cache_all();
121 prom_startcpu(cpu_node, &smp_penguin_ctable, 0, (char *)entry); 120 prom_startcpu(cpu_node, &smp_penguin_ctable, 0, (char *)entry);
122 121
123 /* wheee... it's going... */ 122 /* wheee... it's going... */
@@ -132,7 +131,7 @@ int __cpuinit smp4m_boot_one_cpu(int i)
132 return -ENODEV; 131 return -ENODEV;
133 } 132 }
134 133
135 local_flush_cache_all(); 134 local_ops->cache_all();
136 return 0; 135 return 0;
137} 136}
138 137
@@ -149,30 +148,29 @@ void __init smp4m_smp_done(void)
149 prev = &cpu_data(i).next; 148 prev = &cpu_data(i).next;
150 } 149 }
151 *prev = first; 150 *prev = first;
152 local_flush_cache_all(); 151 local_ops->cache_all();
153 152
154 /* Ok, they are spinning and ready to go. */ 153 /* Ok, they are spinning and ready to go. */
155} 154}
156 155
157 156static void sun4m_send_ipi(int cpu, int level)
158/* Initialize IPIs on the SUN4M SMP machine */
159static void __init smp4m_ipi_init(void)
160{ 157{
158 sbus_writel(SUN4M_SOFT_INT(level), &sun4m_irq_percpu[cpu]->set);
161} 159}
162 160
163static void smp4m_ipi_resched(int cpu) 161static void sun4m_ipi_resched(int cpu)
164{ 162{
165 set_cpu_int(cpu, IRQ_IPI_RESCHED); 163 sun4m_send_ipi(cpu, IRQ_IPI_RESCHED);
166} 164}
167 165
168static void smp4m_ipi_single(int cpu) 166static void sun4m_ipi_single(int cpu)
169{ 167{
170 set_cpu_int(cpu, IRQ_IPI_SINGLE); 168 sun4m_send_ipi(cpu, IRQ_IPI_SINGLE);
171} 169}
172 170
173static void smp4m_ipi_mask_one(int cpu) 171static void sun4m_ipi_mask_one(int cpu)
174{ 172{
175 set_cpu_int(cpu, IRQ_IPI_MASK); 173 sun4m_send_ipi(cpu, IRQ_IPI_MASK);
176} 174}
177 175
178static struct smp_funcall { 176static struct smp_funcall {
@@ -189,7 +187,7 @@ static struct smp_funcall {
189static DEFINE_SPINLOCK(cross_call_lock); 187static DEFINE_SPINLOCK(cross_call_lock);
190 188
191/* Cross calls must be serialized, at least currently. */ 189/* Cross calls must be serialized, at least currently. */
192static void smp4m_cross_call(smpfunc_t func, cpumask_t mask, unsigned long arg1, 190static void sun4m_cross_call(smpfunc_t func, cpumask_t mask, unsigned long arg1,
193 unsigned long arg2, unsigned long arg3, 191 unsigned long arg2, unsigned long arg3,
194 unsigned long arg4) 192 unsigned long arg4)
195{ 193{
@@ -216,7 +214,7 @@ static void smp4m_cross_call(smpfunc_t func, cpumask_t mask, unsigned long arg1,
216 if (cpumask_test_cpu(i, &mask)) { 214 if (cpumask_test_cpu(i, &mask)) {
217 ccall_info.processors_in[i] = 0; 215 ccall_info.processors_in[i] = 0;
218 ccall_info.processors_out[i] = 0; 216 ccall_info.processors_out[i] = 0;
219 set_cpu_int(i, IRQ_CROSS_CALL); 217 sun4m_send_ipi(i, IRQ_CROSS_CALL);
220 } else { 218 } else {
221 ccall_info.processors_in[i] = 1; 219 ccall_info.processors_in[i] = 1;
222 ccall_info.processors_out[i] = 1; 220 ccall_info.processors_out[i] = 1;
@@ -260,64 +258,33 @@ void smp4m_cross_call_irq(void)
260void smp4m_percpu_timer_interrupt(struct pt_regs *regs) 258void smp4m_percpu_timer_interrupt(struct pt_regs *regs)
261{ 259{
262 struct pt_regs *old_regs; 260 struct pt_regs *old_regs;
261 struct clock_event_device *ce;
263 int cpu = smp_processor_id(); 262 int cpu = smp_processor_id();
264 263
265 old_regs = set_irq_regs(regs); 264 old_regs = set_irq_regs(regs);
266 265
267 sun4m_clear_profile_irq(cpu); 266 ce = &per_cpu(sparc32_clockevent, cpu);
268
269 profile_tick(CPU_PROFILING);
270 267
271 if (!--prof_counter(cpu)) { 268 if (ce->mode & CLOCK_EVT_MODE_PERIODIC)
272 int user = user_mode(regs); 269 sun4m_clear_profile_irq(cpu);
270 else
271 sparc_config.load_profile_irq(cpu, 0); /* Is this needless? */
273 272
274 irq_enter(); 273 irq_enter();
275 update_process_times(user); 274 ce->event_handler(ce);
276 irq_exit(); 275 irq_exit();
277 276
278 prof_counter(cpu) = prof_multiplier(cpu);
279 }
280 set_irq_regs(old_regs); 277 set_irq_regs(old_regs);
281} 278}
282 279
283static void __cpuinit smp_setup_percpu_timer(void) 280static const struct sparc32_ipi_ops sun4m_ipi_ops = {
284{ 281 .cross_call = sun4m_cross_call,
285 int cpu = smp_processor_id(); 282 .resched = sun4m_ipi_resched,
286 283 .single = sun4m_ipi_single,
287 prof_counter(cpu) = prof_multiplier(cpu) = 1; 284 .mask_one = sun4m_ipi_mask_one,
288 load_profile_irq(cpu, lvl14_resolution); 285};
289
290 if (cpu == boot_cpu_id)
291 sun4m_unmask_profile_irq();
292}
293
294static void __init smp4m_blackbox_id(unsigned *addr)
295{
296 int rd = *addr & 0x3e000000;
297 int rs1 = rd >> 11;
298
299 addr[0] = 0x81580000 | rd; /* rd %tbr, reg */
300 addr[1] = 0x8130200c | rd | rs1; /* srl reg, 0xc, reg */
301 addr[2] = 0x80082003 | rd | rs1; /* and reg, 3, reg */
302}
303
304static void __init smp4m_blackbox_current(unsigned *addr)
305{
306 int rd = *addr & 0x3e000000;
307 int rs1 = rd >> 11;
308
309 addr[0] = 0x81580000 | rd; /* rd %tbr, reg */
310 addr[2] = 0x8130200a | rd | rs1; /* srl reg, 0xa, reg */
311 addr[4] = 0x8008200c | rd | rs1; /* and reg, 0xc, reg */
312}
313 286
314void __init sun4m_init_smp(void) 287void __init sun4m_init_smp(void)
315{ 288{
316 BTFIXUPSET_BLACKBOX(hard_smp_processor_id, smp4m_blackbox_id); 289 sparc32_ipi_ops = &sun4m_ipi_ops;
317 BTFIXUPSET_BLACKBOX(load_current, smp4m_blackbox_current);
318 BTFIXUPSET_CALL(smp_cross_call, smp4m_cross_call, BTFIXUPCALL_NORM);
319 BTFIXUPSET_CALL(__hard_smp_processor_id, __smp4m_processor_id, BTFIXUPCALL_NORM);
320 BTFIXUPSET_CALL(smp_ipi_resched, smp4m_ipi_resched, BTFIXUPCALL_NORM);
321 BTFIXUPSET_CALL(smp_ipi_single, smp4m_ipi_single, BTFIXUPCALL_NORM);
322 BTFIXUPSET_CALL(smp_ipi_mask_one, smp4m_ipi_mask_one, BTFIXUPCALL_NORM);
323} 290}
diff --git a/arch/sparc/kernel/sys_sparc_32.c b/arch/sparc/kernel/sys_sparc_32.c
index 42b282fa6112..627e89af1d71 100644
--- a/arch/sparc/kernel/sys_sparc_32.c
+++ b/arch/sparc/kernel/sys_sparc_32.c
@@ -53,8 +53,6 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, unsi
53 /* See asm-sparc/uaccess.h */ 53 /* See asm-sparc/uaccess.h */
54 if (len > TASK_SIZE - PAGE_SIZE) 54 if (len > TASK_SIZE - PAGE_SIZE)
55 return -ENOMEM; 55 return -ENOMEM;
56 if (ARCH_SUN4C && len > 0x20000000)
57 return -ENOMEM;
58 if (!addr) 56 if (!addr)
59 addr = TASK_UNMAPPED_BASE; 57 addr = TASK_UNMAPPED_BASE;
60 58
@@ -65,10 +63,6 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, unsi
65 63
66 for (vmm = find_vma(current->mm, addr); ; vmm = vmm->vm_next) { 64 for (vmm = find_vma(current->mm, addr); ; vmm = vmm->vm_next) {
67 /* At this point: (!vmm || addr < vmm->vm_end). */ 65 /* At this point: (!vmm || addr < vmm->vm_end). */
68 if (ARCH_SUN4C && addr < 0xe0000000 && 0x20000000 - len < addr) {
69 addr = PAGE_OFFSET;
70 vmm = find_vma(current->mm, PAGE_OFFSET);
71 }
72 if (TASK_SIZE - PAGE_SIZE - len < addr) 66 if (TASK_SIZE - PAGE_SIZE - len < addr)
73 return -ENOMEM; 67 return -ENOMEM;
74 if (!vmm || addr + len <= vmm->vm_start) 68 if (!vmm || addr + len <= vmm->vm_start)
@@ -99,11 +93,6 @@ out:
99 93
100int sparc_mmap_check(unsigned long addr, unsigned long len) 94int sparc_mmap_check(unsigned long addr, unsigned long len)
101{ 95{
102 if (ARCH_SUN4C &&
103 (len > 0x20000000 ||
104 (addr < 0xe0000000 && addr + len > 0x20000000)))
105 return -EINVAL;
106
107 /* See asm-sparc/uaccess.h */ 96 /* See asm-sparc/uaccess.h */
108 if (len > TASK_SIZE - PAGE_SIZE || addr + len > TASK_SIZE - PAGE_SIZE) 97 if (len > TASK_SIZE - PAGE_SIZE || addr + len > TASK_SIZE - PAGE_SIZE)
109 return -EINVAL; 98 return -EINVAL;
diff --git a/arch/sparc/kernel/time_32.c b/arch/sparc/kernel/time_32.c
index 7d0c088e8aba..953641549e82 100644
--- a/arch/sparc/kernel/time_32.c
+++ b/arch/sparc/kernel/time_32.c
@@ -26,6 +26,8 @@
26#include <linux/rtc.h> 26#include <linux/rtc.h>
27#include <linux/rtc/m48t59.h> 27#include <linux/rtc/m48t59.h>
28#include <linux/timex.h> 28#include <linux/timex.h>
29#include <linux/clocksource.h>
30#include <linux/clockchips.h>
29#include <linux/init.h> 31#include <linux/init.h>
30#include <linux/pci.h> 32#include <linux/pci.h>
31#include <linux/ioport.h> 33#include <linux/ioport.h>
@@ -40,13 +42,24 @@
40#include <asm/irq.h> 42#include <asm/irq.h>
41#include <asm/io.h> 43#include <asm/io.h>
42#include <asm/idprom.h> 44#include <asm/idprom.h>
43#include <asm/machines.h>
44#include <asm/page.h> 45#include <asm/page.h>
45#include <asm/pcic.h> 46#include <asm/pcic.h>
46#include <asm/irq_regs.h> 47#include <asm/irq_regs.h>
48#include <asm/setup.h>
47 49
48#include "irq.h" 50#include "irq.h"
49 51
52static __cacheline_aligned_in_smp DEFINE_SEQLOCK(timer_cs_lock);
53static __volatile__ u64 timer_cs_internal_counter = 0;
54static char timer_cs_enabled = 0;
55
56static struct clock_event_device timer_ce;
57static char timer_ce_enabled = 0;
58
59#ifdef CONFIG_SMP
60DEFINE_PER_CPU(struct clock_event_device, sparc32_clockevent);
61#endif
62
50DEFINE_SPINLOCK(rtc_lock); 63DEFINE_SPINLOCK(rtc_lock);
51EXPORT_SYMBOL(rtc_lock); 64EXPORT_SYMBOL(rtc_lock);
52 65
@@ -55,7 +68,6 @@ static int set_rtc_mmss(unsigned long);
55unsigned long profile_pc(struct pt_regs *regs) 68unsigned long profile_pc(struct pt_regs *regs)
56{ 69{
57 extern char __copy_user_begin[], __copy_user_end[]; 70 extern char __copy_user_begin[], __copy_user_end[];
58 extern char __atomic_begin[], __atomic_end[];
59 extern char __bzero_begin[], __bzero_end[]; 71 extern char __bzero_begin[], __bzero_end[];
60 72
61 unsigned long pc = regs->pc; 73 unsigned long pc = regs->pc;
@@ -63,8 +75,6 @@ unsigned long profile_pc(struct pt_regs *regs)
63 if (in_lock_functions(pc) || 75 if (in_lock_functions(pc) ||
64 (pc >= (unsigned long) __copy_user_begin && 76 (pc >= (unsigned long) __copy_user_begin &&
65 pc < (unsigned long) __copy_user_end) || 77 pc < (unsigned long) __copy_user_end) ||
66 (pc >= (unsigned long) __atomic_begin &&
67 pc < (unsigned long) __atomic_end) ||
68 (pc >= (unsigned long) __bzero_begin && 78 (pc >= (unsigned long) __bzero_begin &&
69 pc < (unsigned long) __bzero_end)) 79 pc < (unsigned long) __bzero_end))
70 pc = regs->u_regs[UREG_RETPC]; 80 pc = regs->u_regs[UREG_RETPC];
@@ -75,36 +85,168 @@ EXPORT_SYMBOL(profile_pc);
75 85
76__volatile__ unsigned int *master_l10_counter; 86__volatile__ unsigned int *master_l10_counter;
77 87
78u32 (*do_arch_gettimeoffset)(void);
79
80int update_persistent_clock(struct timespec now) 88int update_persistent_clock(struct timespec now)
81{ 89{
82 return set_rtc_mmss(now.tv_sec); 90 return set_rtc_mmss(now.tv_sec);
83} 91}
84 92
85/* 93irqreturn_t notrace timer_interrupt(int dummy, void *dev_id)
86 * timer_interrupt() needs to keep up the real-time clock, 94{
87 * as well as call the "xtime_update()" routine every clocktick 95 if (timer_cs_enabled) {
88 */ 96 write_seqlock(&timer_cs_lock);
97 timer_cs_internal_counter++;
98 sparc_config.clear_clock_irq();
99 write_sequnlock(&timer_cs_lock);
100 } else {
101 sparc_config.clear_clock_irq();
102 }
89 103
90#define TICK_SIZE (tick_nsec / 1000) 104 if (timer_ce_enabled)
105 timer_ce.event_handler(&timer_ce);
91 106
92static irqreturn_t timer_interrupt(int dummy, void *dev_id) 107 return IRQ_HANDLED;
108}
109
110static void timer_ce_set_mode(enum clock_event_mode mode,
111 struct clock_event_device *evt)
93{ 112{
94#ifndef CONFIG_SMP 113 switch (mode) {
95 profile_tick(CPU_PROFILING); 114 case CLOCK_EVT_MODE_PERIODIC:
96#endif 115 case CLOCK_EVT_MODE_RESUME:
116 timer_ce_enabled = 1;
117 break;
118 case CLOCK_EVT_MODE_SHUTDOWN:
119 timer_ce_enabled = 0;
120 break;
121 default:
122 break;
123 }
124 smp_mb();
125}
97 126
98 clear_clock_irq(); 127static __init void setup_timer_ce(void)
128{
129 struct clock_event_device *ce = &timer_ce;
130
131 BUG_ON(smp_processor_id() != boot_cpu_id);
132
133 ce->name = "timer_ce";
134 ce->rating = 100;
135 ce->features = CLOCK_EVT_FEAT_PERIODIC;
136 ce->set_mode = timer_ce_set_mode;
137 ce->cpumask = cpu_possible_mask;
138 ce->shift = 32;
139 ce->mult = div_sc(sparc_config.clock_rate, NSEC_PER_SEC,
140 ce->shift);
141 clockevents_register_device(ce);
142}
99 143
100 xtime_update(1); 144static unsigned int sbus_cycles_offset(void)
145{
146 unsigned int val, offset;
101 147
102#ifndef CONFIG_SMP 148 val = *master_l10_counter;
103 update_process_times(user_mode(get_irq_regs())); 149 offset = (val >> TIMER_VALUE_SHIFT) & TIMER_VALUE_MASK;
104#endif 150
105 return IRQ_HANDLED; 151 /* Limit hit? */
152 if (val & TIMER_LIMIT_BIT)
153 offset += sparc_config.cs_period;
154
155 return offset;
156}
157
158static cycle_t timer_cs_read(struct clocksource *cs)
159{
160 unsigned int seq, offset;
161 u64 cycles;
162
163 do {
164 seq = read_seqbegin(&timer_cs_lock);
165
166 cycles = timer_cs_internal_counter;
167 offset = sparc_config.get_cycles_offset();
168 } while (read_seqretry(&timer_cs_lock, seq));
169
170 /* Count absolute cycles */
171 cycles *= sparc_config.cs_period;
172 cycles += offset;
173
174 return cycles;
175}
176
177static struct clocksource timer_cs = {
178 .name = "timer_cs",
179 .rating = 100,
180 .read = timer_cs_read,
181 .mask = CLOCKSOURCE_MASK(64),
182 .shift = 2,
183 .flags = CLOCK_SOURCE_IS_CONTINUOUS,
184};
185
186static __init int setup_timer_cs(void)
187{
188 timer_cs_enabled = 1;
189 timer_cs.mult = clocksource_hz2mult(sparc_config.clock_rate,
190 timer_cs.shift);
191
192 return clocksource_register(&timer_cs);
106} 193}
107 194
195#ifdef CONFIG_SMP
196static void percpu_ce_setup(enum clock_event_mode mode,
197 struct clock_event_device *evt)
198{
199 int cpu = __first_cpu(evt->cpumask);
200
201 switch (mode) {
202 case CLOCK_EVT_MODE_PERIODIC:
203 sparc_config.load_profile_irq(cpu,
204 SBUS_CLOCK_RATE / HZ);
205 break;
206 case CLOCK_EVT_MODE_ONESHOT:
207 case CLOCK_EVT_MODE_SHUTDOWN:
208 case CLOCK_EVT_MODE_UNUSED:
209 sparc_config.load_profile_irq(cpu, 0);
210 break;
211 default:
212 break;
213 }
214}
215
216static int percpu_ce_set_next_event(unsigned long delta,
217 struct clock_event_device *evt)
218{
219 int cpu = __first_cpu(evt->cpumask);
220 unsigned int next = (unsigned int)delta;
221
222 sparc_config.load_profile_irq(cpu, next);
223 return 0;
224}
225
226void register_percpu_ce(int cpu)
227{
228 struct clock_event_device *ce = &per_cpu(sparc32_clockevent, cpu);
229 unsigned int features = CLOCK_EVT_FEAT_PERIODIC;
230
231 if (sparc_config.features & FEAT_L14_ONESHOT)
232 features |= CLOCK_EVT_FEAT_ONESHOT;
233
234 ce->name = "percpu_ce";
235 ce->rating = 200;
236 ce->features = features;
237 ce->set_mode = percpu_ce_setup;
238 ce->set_next_event = percpu_ce_set_next_event;
239 ce->cpumask = cpumask_of(cpu);
240 ce->shift = 32;
241 ce->mult = div_sc(sparc_config.clock_rate, NSEC_PER_SEC,
242 ce->shift);
243 ce->max_delta_ns = clockevent_delta2ns(sparc_config.clock_rate, ce);
244 ce->min_delta_ns = clockevent_delta2ns(100, ce);
245
246 clockevents_register_device(ce);
247}
248#endif
249
108static unsigned char mostek_read_byte(struct device *dev, u32 ofs) 250static unsigned char mostek_read_byte(struct device *dev, u32 ofs)
109{ 251{
110 struct platform_device *pdev = to_platform_device(dev); 252 struct platform_device *pdev = to_platform_device(dev);
@@ -195,38 +337,28 @@ static int __init clock_init(void)
195 */ 337 */
196fs_initcall(clock_init); 338fs_initcall(clock_init);
197 339
198 340static void __init sparc32_late_time_init(void)
199u32 sbus_do_gettimeoffset(void)
200{
201 unsigned long val = *master_l10_counter;
202 unsigned long usec = (val >> 10) & 0x1fffff;
203
204 /* Limit hit? */
205 if (val & 0x80000000)
206 usec += 1000000 / HZ;
207
208 return usec * 1000;
209}
210
211
212u32 arch_gettimeoffset(void)
213{ 341{
214 if (unlikely(!do_arch_gettimeoffset)) 342 if (sparc_config.features & FEAT_L10_CLOCKEVENT)
215 return 0; 343 setup_timer_ce();
216 return do_arch_gettimeoffset(); 344 if (sparc_config.features & FEAT_L10_CLOCKSOURCE)
345 setup_timer_cs();
346#ifdef CONFIG_SMP
347 register_percpu_ce(smp_processor_id());
348#endif
217} 349}
218 350
219static void __init sbus_time_init(void) 351static void __init sbus_time_init(void)
220{ 352{
221 do_arch_gettimeoffset = sbus_do_gettimeoffset; 353 sparc_config.get_cycles_offset = sbus_cycles_offset;
222 354 sparc_config.init_timers();
223 btfixup();
224
225 sparc_irq_config.init_timers(timer_interrupt);
226} 355}
227 356
228void __init time_init(void) 357void __init time_init(void)
229{ 358{
359 sparc_config.features = 0;
360 late_time_init = sparc32_late_time_init;
361
230 if (pcic_present()) 362 if (pcic_present())
231 pci_time_init(); 363 pci_time_init();
232 else 364 else
diff --git a/arch/sparc/kernel/trampoline_32.S b/arch/sparc/kernel/trampoline_32.S
index 691f484e03b3..7364ddc9e5aa 100644
--- a/arch/sparc/kernel/trampoline_32.S
+++ b/arch/sparc/kernel/trampoline_32.S
@@ -15,8 +15,8 @@
15#include <asm/contregs.h> 15#include <asm/contregs.h>
16#include <asm/thread_info.h> 16#include <asm/thread_info.h>
17 17
18 .globl sun4m_cpu_startup, __smp4m_processor_id, __leon_processor_id 18 .globl sun4m_cpu_startup
19 .globl sun4d_cpu_startup, __smp4d_processor_id 19 .globl sun4d_cpu_startup
20 20
21 __CPUINIT 21 __CPUINIT
22 .align 4 22 .align 4
@@ -94,24 +94,6 @@ smp_do_cpu_idle:
94 call cpu_panic 94 call cpu_panic
95 nop 95 nop
96 96
97__smp4m_processor_id:
98 rd %tbr, %g2
99 srl %g2, 12, %g2
100 and %g2, 3, %g2
101 retl
102 mov %g1, %o7
103
104__smp4d_processor_id:
105 lda [%g0] ASI_M_VIKING_TMP1, %g2
106 retl
107 mov %g1, %o7
108
109__leon_processor_id:
110 rd %asr17,%g2
111 srl %g2,28,%g2
112 retl
113 mov %g1, %o7
114
115/* CPUID in bootbus can be found at PA 0xff0140000 */ 97/* CPUID in bootbus can be found at PA 0xff0140000 */
116#define SUN4D_BOOTBUS_CPUID 0xf0140000 98#define SUN4D_BOOTBUS_CPUID 0xf0140000
117 99
diff --git a/arch/sparc/kernel/traps_32.c b/arch/sparc/kernel/traps_32.c
index d2de21333146..a5785ea2a85d 100644
--- a/arch/sparc/kernel/traps_32.c
+++ b/arch/sparc/kernel/traps_32.c
@@ -120,8 +120,6 @@ void do_illegal_instruction(struct pt_regs *regs, unsigned long pc, unsigned lon
120 printk("Ill instr. at pc=%08lx instruction is %08lx\n", 120 printk("Ill instr. at pc=%08lx instruction is %08lx\n",
121 regs->pc, *(unsigned long *)regs->pc); 121 regs->pc, *(unsigned long *)regs->pc);
122#endif 122#endif
123 if (!do_user_muldiv (regs, pc))
124 return;
125 123
126 info.si_signo = SIGILL; 124 info.si_signo = SIGILL;
127 info.si_errno = 0; 125 info.si_errno = 0;
diff --git a/arch/sparc/kernel/ttable_32.S b/arch/sparc/kernel/ttable_32.S
new file mode 100644
index 000000000000..8a7a96ca676f
--- /dev/null
+++ b/arch/sparc/kernel/ttable_32.S
@@ -0,0 +1,417 @@
1/* The Sparc trap table, bootloader gives us control at _start. */
2 __HEAD
3
4 .globl _start
5_start:
6
7 .globl _stext
8_stext:
9
10 .globl trapbase
11trapbase:
12
13#ifdef CONFIG_SMP
14trapbase_cpu0:
15#endif
16/* We get control passed to us here at t_zero. */
17t_zero: b gokernel; nop; nop; nop;
18t_tflt: SRMMU_TFAULT /* Inst. Access Exception */
19t_bins: TRAP_ENTRY(0x2, bad_instruction) /* Illegal Instruction */
20t_pins: TRAP_ENTRY(0x3, priv_instruction) /* Privileged Instruction */
21t_fpd: TRAP_ENTRY(0x4, fpd_trap_handler) /* Floating Point Disabled */
22t_wovf: WINDOW_SPILL /* Window Overflow */
23t_wunf: WINDOW_FILL /* Window Underflow */
24t_mna: TRAP_ENTRY(0x7, mna_handler) /* Memory Address Not Aligned */
25t_fpe: TRAP_ENTRY(0x8, fpe_trap_handler) /* Floating Point Exception */
26t_dflt: SRMMU_DFAULT /* Data Miss Exception */
27t_tio: TRAP_ENTRY(0xa, do_tag_overflow) /* Tagged Instruction Ovrflw */
28t_wpt: TRAP_ENTRY(0xb, do_watchpoint) /* Watchpoint Detected */
29t_badc: BAD_TRAP(0xc) BAD_TRAP(0xd) BAD_TRAP(0xe) BAD_TRAP(0xf) BAD_TRAP(0x10)
30t_irq1: TRAP_ENTRY_INTERRUPT(1) /* IRQ Software/SBUS Level 1 */
31t_irq2: TRAP_ENTRY_INTERRUPT(2) /* IRQ SBUS Level 2 */
32t_irq3: TRAP_ENTRY_INTERRUPT(3) /* IRQ SCSI/DMA/SBUS Level 3 */
33t_irq4: TRAP_ENTRY_INTERRUPT(4) /* IRQ Software Level 4 */
34t_irq5: TRAP_ENTRY_INTERRUPT(5) /* IRQ SBUS/Ethernet Level 5 */
35t_irq6: TRAP_ENTRY_INTERRUPT(6) /* IRQ Software Level 6 */
36t_irq7: TRAP_ENTRY_INTERRUPT(7) /* IRQ Video/SBUS Level 5 */
37t_irq8: TRAP_ENTRY_INTERRUPT(8) /* IRQ SBUS Level 6 */
38t_irq9: TRAP_ENTRY_INTERRUPT(9) /* IRQ SBUS Level 7 */
39t_irq10:TRAP_ENTRY_INTERRUPT(10) /* IRQ Timer #1 (one we use) */
40t_irq11:TRAP_ENTRY_INTERRUPT(11) /* IRQ Floppy Intr. */
41t_irq12:TRAP_ENTRY_INTERRUPT(12) /* IRQ Zilog serial chip */
42t_irq13:TRAP_ENTRY_INTERRUPT(13) /* IRQ Audio Intr. */
43t_irq14:TRAP_ENTRY_INTERRUPT(14) /* IRQ Timer #2 */
44
45 .globl t_nmi
46t_nmi: TRAP_ENTRY(0x1f, linux_trap_ipi15_sun4m)
47
48t_racc: TRAP_ENTRY(0x20, do_reg_access) /* General Register Access Error */
49t_iacce:BAD_TRAP(0x21) /* Instr Access Error */
50t_bad22:BAD_TRAP(0x22)
51 BAD_TRAP(0x23)
52t_cpdis:TRAP_ENTRY(0x24, do_cp_disabled) /* Co-Processor Disabled */
53t_uflsh:SKIP_TRAP(0x25, unimp_flush) /* Unimplemented FLUSH inst. */
54t_bad26:BAD_TRAP(0x26) BAD_TRAP(0x27)
55t_cpexc:TRAP_ENTRY(0x28, do_cp_exception) /* Co-Processor Exception */
56t_dacce:SRMMU_DFAULT /* Data Access Error */
57t_hwdz: TRAP_ENTRY(0x2a, do_hw_divzero) /* Division by zero, you lose... */
58t_dserr:BAD_TRAP(0x2b) /* Data Store Error */
59t_daccm:BAD_TRAP(0x2c) /* Data Access MMU-Miss */
60t_bad2d:BAD_TRAP(0x2d) BAD_TRAP(0x2e) BAD_TRAP(0x2f) BAD_TRAP(0x30) BAD_TRAP(0x31)
61t_bad32:BAD_TRAP(0x32) BAD_TRAP(0x33) BAD_TRAP(0x34) BAD_TRAP(0x35) BAD_TRAP(0x36)
62t_bad37:BAD_TRAP(0x37) BAD_TRAP(0x38) BAD_TRAP(0x39) BAD_TRAP(0x3a) BAD_TRAP(0x3b)
63t_iaccm:BAD_TRAP(0x3c) /* Instr Access MMU-Miss */
64t_bad3d:BAD_TRAP(0x3d) BAD_TRAP(0x3e) BAD_TRAP(0x3f) BAD_TRAP(0x40) BAD_TRAP(0x41)
65t_bad42:BAD_TRAP(0x42) BAD_TRAP(0x43) BAD_TRAP(0x44) BAD_TRAP(0x45) BAD_TRAP(0x46)
66t_bad47:BAD_TRAP(0x47) BAD_TRAP(0x48) BAD_TRAP(0x49) BAD_TRAP(0x4a) BAD_TRAP(0x4b)
67t_bad4c:BAD_TRAP(0x4c) BAD_TRAP(0x4d) BAD_TRAP(0x4e) BAD_TRAP(0x4f) BAD_TRAP(0x50)
68t_bad51:BAD_TRAP(0x51) BAD_TRAP(0x52) BAD_TRAP(0x53) BAD_TRAP(0x54) BAD_TRAP(0x55)
69t_bad56:BAD_TRAP(0x56) BAD_TRAP(0x57) BAD_TRAP(0x58) BAD_TRAP(0x59) BAD_TRAP(0x5a)
70t_bad5b:BAD_TRAP(0x5b) BAD_TRAP(0x5c) BAD_TRAP(0x5d) BAD_TRAP(0x5e) BAD_TRAP(0x5f)
71t_bad60:BAD_TRAP(0x60) BAD_TRAP(0x61) BAD_TRAP(0x62) BAD_TRAP(0x63) BAD_TRAP(0x64)
72t_bad65:BAD_TRAP(0x65) BAD_TRAP(0x66) BAD_TRAP(0x67) BAD_TRAP(0x68) BAD_TRAP(0x69)
73t_bad6a:BAD_TRAP(0x6a) BAD_TRAP(0x6b) BAD_TRAP(0x6c) BAD_TRAP(0x6d) BAD_TRAP(0x6e)
74t_bad6f:BAD_TRAP(0x6f) BAD_TRAP(0x70) BAD_TRAP(0x71) BAD_TRAP(0x72) BAD_TRAP(0x73)
75t_bad74:BAD_TRAP(0x74) BAD_TRAP(0x75) BAD_TRAP(0x76) BAD_TRAP(0x77) BAD_TRAP(0x78)
76t_bad79:BAD_TRAP(0x79) BAD_TRAP(0x7a) BAD_TRAP(0x7b) BAD_TRAP(0x7c) BAD_TRAP(0x7d)
77t_bad7e:BAD_TRAP(0x7e) BAD_TRAP(0x7f)
78t_bad80:BAD_TRAP(0x80) /* SunOS System Call */
79t_sbkpt:BREAKPOINT_TRAP /* Software Breakpoint/KGDB */
80t_divz: TRAP_ENTRY(0x82, do_hw_divzero) /* Divide by zero trap */
81t_flwin:TRAP_ENTRY(0x83, do_flush_windows) /* Flush Windows Trap */
82t_clwin:BAD_TRAP(0x84) /* Clean Windows Trap */
83t_rchk: BAD_TRAP(0x85) /* Range Check */
84t_funal:BAD_TRAP(0x86) /* Fix Unaligned Access Trap */
85t_iovf: BAD_TRAP(0x87) /* Integer Overflow Trap */
86t_bad88:BAD_TRAP(0x88) /* Slowaris System Call */
87t_bad89:BAD_TRAP(0x89) /* Net-B.S. System Call */
88t_bad8a:BAD_TRAP(0x8a) BAD_TRAP(0x8b) BAD_TRAP(0x8c) BAD_TRAP(0x8d) BAD_TRAP(0x8e)
89t_bad8f:BAD_TRAP(0x8f)
90t_linux:LINUX_SYSCALL_TRAP /* Linux System Call */
91t_bad91:BAD_TRAP(0x91) BAD_TRAP(0x92) BAD_TRAP(0x93) BAD_TRAP(0x94) BAD_TRAP(0x95)
92t_bad96:BAD_TRAP(0x96) BAD_TRAP(0x97) BAD_TRAP(0x98) BAD_TRAP(0x99) BAD_TRAP(0x9a)
93t_bad9b:BAD_TRAP(0x9b) BAD_TRAP(0x9c) BAD_TRAP(0x9d) BAD_TRAP(0x9e) BAD_TRAP(0x9f)
94t_getcc:GETCC_TRAP /* Get Condition Codes */
95t_setcc:SETCC_TRAP /* Set Condition Codes */
96t_getpsr:GETPSR_TRAP /* Get PSR Register */
97t_bada3:BAD_TRAP(0xa3) BAD_TRAP(0xa4) BAD_TRAP(0xa5) BAD_TRAP(0xa6)
98t_bada7:BAD_TRAP(0xa7)
99t_bada8:BAD_TRAP(0xa8) BAD_TRAP(0xa9) BAD_TRAP(0xaa) BAD_TRAP(0xab)
100t_badac:BAD_TRAP(0xac) BAD_TRAP(0xad) BAD_TRAP(0xae) BAD_TRAP(0xaf) BAD_TRAP(0xb0)
101t_badb1:BAD_TRAP(0xb1) BAD_TRAP(0xb2) BAD_TRAP(0xb3) BAD_TRAP(0xb4) BAD_TRAP(0xb5)
102t_badb6:BAD_TRAP(0xb6) BAD_TRAP(0xb7) BAD_TRAP(0xb8) BAD_TRAP(0xb9) BAD_TRAP(0xba)
103t_badbb:BAD_TRAP(0xbb) BAD_TRAP(0xbc) BAD_TRAP(0xbd) BAD_TRAP(0xbe) BAD_TRAP(0xbf)
104t_badc0:BAD_TRAP(0xc0) BAD_TRAP(0xc1) BAD_TRAP(0xc2) BAD_TRAP(0xc3) BAD_TRAP(0xc4)
105t_badc5:BAD_TRAP(0xc5) BAD_TRAP(0xc6) BAD_TRAP(0xc7) BAD_TRAP(0xc8) BAD_TRAP(0xc9)
106t_badca:BAD_TRAP(0xca) BAD_TRAP(0xcb) BAD_TRAP(0xcc) BAD_TRAP(0xcd) BAD_TRAP(0xce)
107t_badcf:BAD_TRAP(0xcf) BAD_TRAP(0xd0) BAD_TRAP(0xd1) BAD_TRAP(0xd2) BAD_TRAP(0xd3)
108t_badd4:BAD_TRAP(0xd4) BAD_TRAP(0xd5) BAD_TRAP(0xd6) BAD_TRAP(0xd7) BAD_TRAP(0xd8)
109t_badd9:BAD_TRAP(0xd9) BAD_TRAP(0xda) BAD_TRAP(0xdb) BAD_TRAP(0xdc) BAD_TRAP(0xdd)
110t_badde:BAD_TRAP(0xde) BAD_TRAP(0xdf) BAD_TRAP(0xe0) BAD_TRAP(0xe1) BAD_TRAP(0xe2)
111t_bade3:BAD_TRAP(0xe3) BAD_TRAP(0xe4) BAD_TRAP(0xe5) BAD_TRAP(0xe6) BAD_TRAP(0xe7)
112t_bade8:BAD_TRAP(0xe8) BAD_TRAP(0xe9) BAD_TRAP(0xea) BAD_TRAP(0xeb) BAD_TRAP(0xec)
113t_baded:BAD_TRAP(0xed) BAD_TRAP(0xee) BAD_TRAP(0xef) BAD_TRAP(0xf0) BAD_TRAP(0xf1)
114t_badf2:BAD_TRAP(0xf2) BAD_TRAP(0xf3) BAD_TRAP(0xf4) BAD_TRAP(0xf5) BAD_TRAP(0xf6)
115t_badf7:BAD_TRAP(0xf7) BAD_TRAP(0xf8) BAD_TRAP(0xf9) BAD_TRAP(0xfa) BAD_TRAP(0xfb)
116t_badfc:BAD_TRAP(0xfc)
117t_kgdb: KGDB_TRAP(0xfd)
118dbtrap: BAD_TRAP(0xfe) /* Debugger/PROM breakpoint #1 */
119dbtrap2:BAD_TRAP(0xff) /* Debugger/PROM breakpoint #2 */
120
121 .globl end_traptable
122end_traptable:
123
124#ifdef CONFIG_SMP
125 /* Trap tables for the other cpus. */
126 .globl trapbase_cpu1, trapbase_cpu2, trapbase_cpu3
127trapbase_cpu1:
128 BAD_TRAP(0x0)
129 SRMMU_TFAULT
130 TRAP_ENTRY(0x2, bad_instruction)
131 TRAP_ENTRY(0x3, priv_instruction)
132 TRAP_ENTRY(0x4, fpd_trap_handler)
133 WINDOW_SPILL
134 WINDOW_FILL
135 TRAP_ENTRY(0x7, mna_handler)
136 TRAP_ENTRY(0x8, fpe_trap_handler)
137 SRMMU_DFAULT
138 TRAP_ENTRY(0xa, do_tag_overflow)
139 TRAP_ENTRY(0xb, do_watchpoint)
140 BAD_TRAP(0xc) BAD_TRAP(0xd) BAD_TRAP(0xe) BAD_TRAP(0xf) BAD_TRAP(0x10)
141 TRAP_ENTRY_INTERRUPT(1) TRAP_ENTRY_INTERRUPT(2)
142 TRAP_ENTRY_INTERRUPT(3) TRAP_ENTRY_INTERRUPT(4)
143 TRAP_ENTRY_INTERRUPT(5) TRAP_ENTRY_INTERRUPT(6)
144 TRAP_ENTRY_INTERRUPT(7) TRAP_ENTRY_INTERRUPT(8)
145 TRAP_ENTRY_INTERRUPT(9) TRAP_ENTRY_INTERRUPT(10)
146 TRAP_ENTRY_INTERRUPT(11) TRAP_ENTRY_INTERRUPT(12)
147 TRAP_ENTRY_INTERRUPT(13) TRAP_ENTRY_INTERRUPT(14)
148 TRAP_ENTRY(0x1f, linux_trap_ipi15_sun4m)
149 TRAP_ENTRY(0x20, do_reg_access)
150 BAD_TRAP(0x21)
151 BAD_TRAP(0x22)
152 BAD_TRAP(0x23)
153 TRAP_ENTRY(0x24, do_cp_disabled)
154 SKIP_TRAP(0x25, unimp_flush)
155 BAD_TRAP(0x26)
156 BAD_TRAP(0x27)
157 TRAP_ENTRY(0x28, do_cp_exception)
158 SRMMU_DFAULT
159 TRAP_ENTRY(0x2a, do_hw_divzero)
160 BAD_TRAP(0x2b)
161 BAD_TRAP(0x2c)
162 BAD_TRAP(0x2d) BAD_TRAP(0x2e) BAD_TRAP(0x2f) BAD_TRAP(0x30) BAD_TRAP(0x31)
163 BAD_TRAP(0x32) BAD_TRAP(0x33) BAD_TRAP(0x34) BAD_TRAP(0x35) BAD_TRAP(0x36)
164 BAD_TRAP(0x37) BAD_TRAP(0x38) BAD_TRAP(0x39) BAD_TRAP(0x3a) BAD_TRAP(0x3b)
165 BAD_TRAP(0x3c) BAD_TRAP(0x3d) BAD_TRAP(0x3e) BAD_TRAP(0x3f) BAD_TRAP(0x40)
166 BAD_TRAP(0x41) BAD_TRAP(0x42) BAD_TRAP(0x43) BAD_TRAP(0x44) BAD_TRAP(0x45)
167 BAD_TRAP(0x46) BAD_TRAP(0x47) BAD_TRAP(0x48) BAD_TRAP(0x49) BAD_TRAP(0x4a)
168 BAD_TRAP(0x4b) BAD_TRAP(0x4c) BAD_TRAP(0x4d) BAD_TRAP(0x4e) BAD_TRAP(0x4f)
169 BAD_TRAP(0x50)
170 BAD_TRAP(0x51) BAD_TRAP(0x52) BAD_TRAP(0x53) BAD_TRAP(0x54) BAD_TRAP(0x55)
171 BAD_TRAP(0x56) BAD_TRAP(0x57) BAD_TRAP(0x58) BAD_TRAP(0x59) BAD_TRAP(0x5a)
172 BAD_TRAP(0x5b) BAD_TRAP(0x5c) BAD_TRAP(0x5d) BAD_TRAP(0x5e) BAD_TRAP(0x5f)
173 BAD_TRAP(0x60) BAD_TRAP(0x61) BAD_TRAP(0x62) BAD_TRAP(0x63) BAD_TRAP(0x64)
174 BAD_TRAP(0x65) BAD_TRAP(0x66) BAD_TRAP(0x67) BAD_TRAP(0x68) BAD_TRAP(0x69)
175 BAD_TRAP(0x6a) BAD_TRAP(0x6b) BAD_TRAP(0x6c) BAD_TRAP(0x6d) BAD_TRAP(0x6e)
176 BAD_TRAP(0x6f) BAD_TRAP(0x70) BAD_TRAP(0x71) BAD_TRAP(0x72) BAD_TRAP(0x73)
177 BAD_TRAP(0x74) BAD_TRAP(0x75) BAD_TRAP(0x76) BAD_TRAP(0x77) BAD_TRAP(0x78)
178 BAD_TRAP(0x79) BAD_TRAP(0x7a) BAD_TRAP(0x7b) BAD_TRAP(0x7c) BAD_TRAP(0x7d)
179 BAD_TRAP(0x7e) BAD_TRAP(0x7f)
180 BAD_TRAP(0x80)
181 BREAKPOINT_TRAP
182 TRAP_ENTRY(0x82, do_hw_divzero)
183 TRAP_ENTRY(0x83, do_flush_windows)
184 BAD_TRAP(0x84) BAD_TRAP(0x85) BAD_TRAP(0x86)
185 BAD_TRAP(0x87) BAD_TRAP(0x88) BAD_TRAP(0x89)
186 BAD_TRAP(0x8a) BAD_TRAP(0x8b) BAD_TRAP(0x8c)
187 BAD_TRAP(0x8d) BAD_TRAP(0x8e) BAD_TRAP(0x8f)
188 LINUX_SYSCALL_TRAP BAD_TRAP(0x91)
189 BAD_TRAP(0x92) BAD_TRAP(0x93) BAD_TRAP(0x94)
190 BAD_TRAP(0x95) BAD_TRAP(0x96) BAD_TRAP(0x97) BAD_TRAP(0x98) BAD_TRAP(0x99)
191 BAD_TRAP(0x9a) BAD_TRAP(0x9b) BAD_TRAP(0x9c) BAD_TRAP(0x9d) BAD_TRAP(0x9e)
192 BAD_TRAP(0x9f)
193 GETCC_TRAP
194 SETCC_TRAP
195 GETPSR_TRAP
196 BAD_TRAP(0xa3) BAD_TRAP(0xa4) BAD_TRAP(0xa5) BAD_TRAP(0xa6)
197 BAD_TRAP(0xa7) BAD_TRAP(0xa8) BAD_TRAP(0xa9) BAD_TRAP(0xaa) BAD_TRAP(0xab)
198 BAD_TRAP(0xac) BAD_TRAP(0xad) BAD_TRAP(0xae) BAD_TRAP(0xaf) BAD_TRAP(0xb0)
199 BAD_TRAP(0xb1) BAD_TRAP(0xb2) BAD_TRAP(0xb3) BAD_TRAP(0xb4) BAD_TRAP(0xb5)
200 BAD_TRAP(0xb6) BAD_TRAP(0xb7) BAD_TRAP(0xb8) BAD_TRAP(0xb9) BAD_TRAP(0xba)
201 BAD_TRAP(0xbb) BAD_TRAP(0xbc) BAD_TRAP(0xbd) BAD_TRAP(0xbe) BAD_TRAP(0xbf)
202 BAD_TRAP(0xc0) BAD_TRAP(0xc1) BAD_TRAP(0xc2) BAD_TRAP(0xc3) BAD_TRAP(0xc4)
203 BAD_TRAP(0xc5) BAD_TRAP(0xc6) BAD_TRAP(0xc7) BAD_TRAP(0xc8) BAD_TRAP(0xc9)
204 BAD_TRAP(0xca) BAD_TRAP(0xcb) BAD_TRAP(0xcc) BAD_TRAP(0xcd) BAD_TRAP(0xce)
205 BAD_TRAP(0xcf) BAD_TRAP(0xd0) BAD_TRAP(0xd1) BAD_TRAP(0xd2) BAD_TRAP(0xd3)
206 BAD_TRAP(0xd4) BAD_TRAP(0xd5) BAD_TRAP(0xd6) BAD_TRAP(0xd7) BAD_TRAP(0xd8)
207 BAD_TRAP(0xd9) BAD_TRAP(0xda) BAD_TRAP(0xdb) BAD_TRAP(0xdc) BAD_TRAP(0xdd)
208 BAD_TRAP(0xde) BAD_TRAP(0xdf) BAD_TRAP(0xe0) BAD_TRAP(0xe1) BAD_TRAP(0xe2)
209 BAD_TRAP(0xe3) BAD_TRAP(0xe4) BAD_TRAP(0xe5) BAD_TRAP(0xe6) BAD_TRAP(0xe7)
210 BAD_TRAP(0xe8) BAD_TRAP(0xe9) BAD_TRAP(0xea) BAD_TRAP(0xeb) BAD_TRAP(0xec)
211 BAD_TRAP(0xed) BAD_TRAP(0xee) BAD_TRAP(0xef) BAD_TRAP(0xf0) BAD_TRAP(0xf1)
212 BAD_TRAP(0xf2) BAD_TRAP(0xf3) BAD_TRAP(0xf4) BAD_TRAP(0xf5) BAD_TRAP(0xf6)
213 BAD_TRAP(0xf7) BAD_TRAP(0xf8) BAD_TRAP(0xf9) BAD_TRAP(0xfa) BAD_TRAP(0xfb)
214 BAD_TRAP(0xfc)
215 KGDB_TRAP(0xfd)
216 BAD_TRAP(0xfe)
217 BAD_TRAP(0xff)
218
219trapbase_cpu2:
220 BAD_TRAP(0x0)
221 SRMMU_TFAULT
222 TRAP_ENTRY(0x2, bad_instruction)
223 TRAP_ENTRY(0x3, priv_instruction)
224 TRAP_ENTRY(0x4, fpd_trap_handler)
225 WINDOW_SPILL
226 WINDOW_FILL
227 TRAP_ENTRY(0x7, mna_handler)
228 TRAP_ENTRY(0x8, fpe_trap_handler)
229 SRMMU_DFAULT
230 TRAP_ENTRY(0xa, do_tag_overflow)
231 TRAP_ENTRY(0xb, do_watchpoint)
232 BAD_TRAP(0xc) BAD_TRAP(0xd) BAD_TRAP(0xe) BAD_TRAP(0xf) BAD_TRAP(0x10)
233 TRAP_ENTRY_INTERRUPT(1)
234 TRAP_ENTRY_INTERRUPT(2)
235 TRAP_ENTRY_INTERRUPT(3)
236 TRAP_ENTRY_INTERRUPT(4)
237 TRAP_ENTRY_INTERRUPT(5)
238 TRAP_ENTRY_INTERRUPT(6)
239 TRAP_ENTRY_INTERRUPT(7)
240 TRAP_ENTRY_INTERRUPT(8)
241 TRAP_ENTRY_INTERRUPT(9)
242 TRAP_ENTRY_INTERRUPT(10)
243 TRAP_ENTRY_INTERRUPT(11)
244 TRAP_ENTRY_INTERRUPT(12)
245 TRAP_ENTRY_INTERRUPT(13)
246 TRAP_ENTRY_INTERRUPT(14)
247 TRAP_ENTRY(0x1f, linux_trap_ipi15_sun4m)
248 TRAP_ENTRY(0x20, do_reg_access)
249 BAD_TRAP(0x21)
250 BAD_TRAP(0x22)
251 BAD_TRAP(0x23)
252 TRAP_ENTRY(0x24, do_cp_disabled)
253 SKIP_TRAP(0x25, unimp_flush)
254 BAD_TRAP(0x26)
255 BAD_TRAP(0x27)
256 TRAP_ENTRY(0x28, do_cp_exception)
257 SRMMU_DFAULT
258 TRAP_ENTRY(0x2a, do_hw_divzero)
259 BAD_TRAP(0x2b)
260 BAD_TRAP(0x2c)
261 BAD_TRAP(0x2d) BAD_TRAP(0x2e) BAD_TRAP(0x2f) BAD_TRAP(0x30) BAD_TRAP(0x31)
262 BAD_TRAP(0x32) BAD_TRAP(0x33) BAD_TRAP(0x34) BAD_TRAP(0x35) BAD_TRAP(0x36)
263 BAD_TRAP(0x37) BAD_TRAP(0x38) BAD_TRAP(0x39) BAD_TRAP(0x3a) BAD_TRAP(0x3b)
264 BAD_TRAP(0x3c) BAD_TRAP(0x3d) BAD_TRAP(0x3e) BAD_TRAP(0x3f) BAD_TRAP(0x40)
265 BAD_TRAP(0x41) BAD_TRAP(0x42) BAD_TRAP(0x43) BAD_TRAP(0x44) BAD_TRAP(0x45)
266 BAD_TRAP(0x46) BAD_TRAP(0x47) BAD_TRAP(0x48) BAD_TRAP(0x49) BAD_TRAP(0x4a)
267 BAD_TRAP(0x4b) BAD_TRAP(0x4c) BAD_TRAP(0x4d) BAD_TRAP(0x4e) BAD_TRAP(0x4f)
268 BAD_TRAP(0x50)
269 BAD_TRAP(0x51) BAD_TRAP(0x52) BAD_TRAP(0x53) BAD_TRAP(0x54) BAD_TRAP(0x55)
270 BAD_TRAP(0x56) BAD_TRAP(0x57) BAD_TRAP(0x58) BAD_TRAP(0x59) BAD_TRAP(0x5a)
271 BAD_TRAP(0x5b) BAD_TRAP(0x5c) BAD_TRAP(0x5d) BAD_TRAP(0x5e) BAD_TRAP(0x5f)
272 BAD_TRAP(0x60) BAD_TRAP(0x61) BAD_TRAP(0x62) BAD_TRAP(0x63) BAD_TRAP(0x64)
273 BAD_TRAP(0x65) BAD_TRAP(0x66) BAD_TRAP(0x67) BAD_TRAP(0x68) BAD_TRAP(0x69)
274 BAD_TRAP(0x6a) BAD_TRAP(0x6b) BAD_TRAP(0x6c) BAD_TRAP(0x6d) BAD_TRAP(0x6e)
275 BAD_TRAP(0x6f) BAD_TRAP(0x70) BAD_TRAP(0x71) BAD_TRAP(0x72) BAD_TRAP(0x73)
276 BAD_TRAP(0x74) BAD_TRAP(0x75) BAD_TRAP(0x76) BAD_TRAP(0x77) BAD_TRAP(0x78)
277 BAD_TRAP(0x79) BAD_TRAP(0x7a) BAD_TRAP(0x7b) BAD_TRAP(0x7c) BAD_TRAP(0x7d)
278 BAD_TRAP(0x7e) BAD_TRAP(0x7f)
279 BAD_TRAP(0x80)
280 BREAKPOINT_TRAP
281 TRAP_ENTRY(0x82, do_hw_divzero)
282 TRAP_ENTRY(0x83, do_flush_windows)
283 BAD_TRAP(0x84)
284 BAD_TRAP(0x85)
285 BAD_TRAP(0x86) BAD_TRAP(0x87) BAD_TRAP(0x88)
286 BAD_TRAP(0x89) BAD_TRAP(0x8a) BAD_TRAP(0x8b) BAD_TRAP(0x8c)
287 BAD_TRAP(0x8d) BAD_TRAP(0x8e) BAD_TRAP(0x8f)
288 LINUX_SYSCALL_TRAP BAD_TRAP(0x91)
289 BAD_TRAP(0x92) BAD_TRAP(0x93) BAD_TRAP(0x94)
290 BAD_TRAP(0x95) BAD_TRAP(0x96) BAD_TRAP(0x97) BAD_TRAP(0x98) BAD_TRAP(0x99)
291 BAD_TRAP(0x9a) BAD_TRAP(0x9b) BAD_TRAP(0x9c) BAD_TRAP(0x9d) BAD_TRAP(0x9e)
292 BAD_TRAP(0x9f)
293 GETCC_TRAP
294 SETCC_TRAP
295 GETPSR_TRAP
296 BAD_TRAP(0xa3) BAD_TRAP(0xa4) BAD_TRAP(0xa5) BAD_TRAP(0xa6)
297 BAD_TRAP(0xa7) BAD_TRAP(0xa8) BAD_TRAP(0xa9) BAD_TRAP(0xaa) BAD_TRAP(0xab)
298 BAD_TRAP(0xac) BAD_TRAP(0xad) BAD_TRAP(0xae) BAD_TRAP(0xaf) BAD_TRAP(0xb0)
299 BAD_TRAP(0xb1) BAD_TRAP(0xb2) BAD_TRAP(0xb3) BAD_TRAP(0xb4) BAD_TRAP(0xb5)
300 BAD_TRAP(0xb6) BAD_TRAP(0xb7) BAD_TRAP(0xb8) BAD_TRAP(0xb9) BAD_TRAP(0xba)
301 BAD_TRAP(0xbb) BAD_TRAP(0xbc) BAD_TRAP(0xbd) BAD_TRAP(0xbe) BAD_TRAP(0xbf)
302 BAD_TRAP(0xc0) BAD_TRAP(0xc1) BAD_TRAP(0xc2) BAD_TRAP(0xc3) BAD_TRAP(0xc4)
303 BAD_TRAP(0xc5) BAD_TRAP(0xc6) BAD_TRAP(0xc7) BAD_TRAP(0xc8) BAD_TRAP(0xc9)
304 BAD_TRAP(0xca) BAD_TRAP(0xcb) BAD_TRAP(0xcc) BAD_TRAP(0xcd) BAD_TRAP(0xce)
305 BAD_TRAP(0xcf) BAD_TRAP(0xd0) BAD_TRAP(0xd1) BAD_TRAP(0xd2) BAD_TRAP(0xd3)
306 BAD_TRAP(0xd4) BAD_TRAP(0xd5) BAD_TRAP(0xd6) BAD_TRAP(0xd7) BAD_TRAP(0xd8)
307 BAD_TRAP(0xd9) BAD_TRAP(0xda) BAD_TRAP(0xdb) BAD_TRAP(0xdc) BAD_TRAP(0xdd)
308 BAD_TRAP(0xde) BAD_TRAP(0xdf) BAD_TRAP(0xe0) BAD_TRAP(0xe1) BAD_TRAP(0xe2)
309 BAD_TRAP(0xe3) BAD_TRAP(0xe4) BAD_TRAP(0xe5) BAD_TRAP(0xe6) BAD_TRAP(0xe7)
310 BAD_TRAP(0xe8) BAD_TRAP(0xe9) BAD_TRAP(0xea) BAD_TRAP(0xeb) BAD_TRAP(0xec)
311 BAD_TRAP(0xed) BAD_TRAP(0xee) BAD_TRAP(0xef) BAD_TRAP(0xf0) BAD_TRAP(0xf1)
312 BAD_TRAP(0xf2) BAD_TRAP(0xf3) BAD_TRAP(0xf4) BAD_TRAP(0xf5) BAD_TRAP(0xf6)
313 BAD_TRAP(0xf7) BAD_TRAP(0xf8) BAD_TRAP(0xf9) BAD_TRAP(0xfa) BAD_TRAP(0xfb)
314 BAD_TRAP(0xfc)
315 KGDB_TRAP(0xfd)
316 BAD_TRAP(0xfe)
317 BAD_TRAP(0xff)
318
319trapbase_cpu3:
320 BAD_TRAP(0x0)
321 SRMMU_TFAULT
322 TRAP_ENTRY(0x2, bad_instruction)
323 TRAP_ENTRY(0x3, priv_instruction)
324 TRAP_ENTRY(0x4, fpd_trap_handler)
325 WINDOW_SPILL
326 WINDOW_FILL
327 TRAP_ENTRY(0x7, mna_handler)
328 TRAP_ENTRY(0x8, fpe_trap_handler)
329 SRMMU_DFAULT
330 TRAP_ENTRY(0xa, do_tag_overflow)
331 TRAP_ENTRY(0xb, do_watchpoint)
332 BAD_TRAP(0xc) BAD_TRAP(0xd) BAD_TRAP(0xe) BAD_TRAP(0xf) BAD_TRAP(0x10)
333 TRAP_ENTRY_INTERRUPT(1)
334 TRAP_ENTRY_INTERRUPT(2)
335 TRAP_ENTRY_INTERRUPT(3)
336 TRAP_ENTRY_INTERRUPT(4)
337 TRAP_ENTRY_INTERRUPT(5)
338 TRAP_ENTRY_INTERRUPT(6)
339 TRAP_ENTRY_INTERRUPT(7)
340 TRAP_ENTRY_INTERRUPT(8)
341 TRAP_ENTRY_INTERRUPT(9)
342 TRAP_ENTRY_INTERRUPT(10)
343 TRAP_ENTRY_INTERRUPT(11)
344 TRAP_ENTRY_INTERRUPT(12)
345 TRAP_ENTRY_INTERRUPT(13)
346 TRAP_ENTRY_INTERRUPT(14)
347 TRAP_ENTRY(0x1f, linux_trap_ipi15_sun4m)
348 TRAP_ENTRY(0x20, do_reg_access)
349 BAD_TRAP(0x21)
350 BAD_TRAP(0x22)
351 BAD_TRAP(0x23)
352 TRAP_ENTRY(0x24, do_cp_disabled)
353 SKIP_TRAP(0x25, unimp_flush)
354 BAD_TRAP(0x26)
355 BAD_TRAP(0x27)
356 TRAP_ENTRY(0x28, do_cp_exception)
357 SRMMU_DFAULT
358 TRAP_ENTRY(0x2a, do_hw_divzero)
359 BAD_TRAP(0x2b) BAD_TRAP(0x2c)
360 BAD_TRAP(0x2d) BAD_TRAP(0x2e) BAD_TRAP(0x2f) BAD_TRAP(0x30) BAD_TRAP(0x31)
361 BAD_TRAP(0x32) BAD_TRAP(0x33) BAD_TRAP(0x34) BAD_TRAP(0x35) BAD_TRAP(0x36)
362 BAD_TRAP(0x37) BAD_TRAP(0x38) BAD_TRAP(0x39) BAD_TRAP(0x3a) BAD_TRAP(0x3b)
363 BAD_TRAP(0x3c) BAD_TRAP(0x3d) BAD_TRAP(0x3e) BAD_TRAP(0x3f) BAD_TRAP(0x40)
364 BAD_TRAP(0x41) BAD_TRAP(0x42) BAD_TRAP(0x43) BAD_TRAP(0x44) BAD_TRAP(0x45)
365 BAD_TRAP(0x46) BAD_TRAP(0x47) BAD_TRAP(0x48) BAD_TRAP(0x49) BAD_TRAP(0x4a)
366 BAD_TRAP(0x4b) BAD_TRAP(0x4c) BAD_TRAP(0x4d) BAD_TRAP(0x4e) BAD_TRAP(0x4f)
367 BAD_TRAP(0x50)
368 BAD_TRAP(0x51) BAD_TRAP(0x52) BAD_TRAP(0x53) BAD_TRAP(0x54) BAD_TRAP(0x55)
369 BAD_TRAP(0x56) BAD_TRAP(0x57) BAD_TRAP(0x58) BAD_TRAP(0x59) BAD_TRAP(0x5a)
370 BAD_TRAP(0x5b) BAD_TRAP(0x5c) BAD_TRAP(0x5d) BAD_TRAP(0x5e) BAD_TRAP(0x5f)
371 BAD_TRAP(0x60) BAD_TRAP(0x61) BAD_TRAP(0x62) BAD_TRAP(0x63) BAD_TRAP(0x64)
372 BAD_TRAP(0x65) BAD_TRAP(0x66) BAD_TRAP(0x67) BAD_TRAP(0x68) BAD_TRAP(0x69)
373 BAD_TRAP(0x6a) BAD_TRAP(0x6b) BAD_TRAP(0x6c) BAD_TRAP(0x6d) BAD_TRAP(0x6e)
374 BAD_TRAP(0x6f) BAD_TRAP(0x70) BAD_TRAP(0x71) BAD_TRAP(0x72) BAD_TRAP(0x73)
375 BAD_TRAP(0x74) BAD_TRAP(0x75) BAD_TRAP(0x76) BAD_TRAP(0x77) BAD_TRAP(0x78)
376 BAD_TRAP(0x79) BAD_TRAP(0x7a) BAD_TRAP(0x7b) BAD_TRAP(0x7c) BAD_TRAP(0x7d)
377 BAD_TRAP(0x7e) BAD_TRAP(0x7f)
378 BAD_TRAP(0x80)
379 BREAKPOINT_TRAP
380 TRAP_ENTRY(0x82, do_hw_divzero)
381 TRAP_ENTRY(0x83, do_flush_windows)
382 BAD_TRAP(0x84) BAD_TRAP(0x85)
383 BAD_TRAP(0x86) BAD_TRAP(0x87) BAD_TRAP(0x88)
384 BAD_TRAP(0x89) BAD_TRAP(0x8a) BAD_TRAP(0x8b) BAD_TRAP(0x8c)
385 BAD_TRAP(0x8d) BAD_TRAP(0x8e) BAD_TRAP(0x8f)
386 LINUX_SYSCALL_TRAP
387 BAD_TRAP(0x91) BAD_TRAP(0x92) BAD_TRAP(0x93) BAD_TRAP(0x94)
388 BAD_TRAP(0x95) BAD_TRAP(0x96) BAD_TRAP(0x97) BAD_TRAP(0x98) BAD_TRAP(0x99)
389 BAD_TRAP(0x9a) BAD_TRAP(0x9b) BAD_TRAP(0x9c) BAD_TRAP(0x9d) BAD_TRAP(0x9e)
390 BAD_TRAP(0x9f)
391 GETCC_TRAP
392 SETCC_TRAP
393 GETPSR_TRAP
394 BAD_TRAP(0xa3) BAD_TRAP(0xa4) BAD_TRAP(0xa5) BAD_TRAP(0xa6)
395 BAD_TRAP(0xa7) BAD_TRAP(0xa8) BAD_TRAP(0xa9) BAD_TRAP(0xaa) BAD_TRAP(0xab)
396 BAD_TRAP(0xac) BAD_TRAP(0xad) BAD_TRAP(0xae) BAD_TRAP(0xaf) BAD_TRAP(0xb0)
397 BAD_TRAP(0xb1) BAD_TRAP(0xb2) BAD_TRAP(0xb3) BAD_TRAP(0xb4) BAD_TRAP(0xb5)
398 BAD_TRAP(0xb6) BAD_TRAP(0xb7) BAD_TRAP(0xb8) BAD_TRAP(0xb9) BAD_TRAP(0xba)
399 BAD_TRAP(0xbb) BAD_TRAP(0xbc) BAD_TRAP(0xbd) BAD_TRAP(0xbe) BAD_TRAP(0xbf)
400 BAD_TRAP(0xc0) BAD_TRAP(0xc1) BAD_TRAP(0xc2) BAD_TRAP(0xc3) BAD_TRAP(0xc4)
401 BAD_TRAP(0xc5) BAD_TRAP(0xc6) BAD_TRAP(0xc7) BAD_TRAP(0xc8) BAD_TRAP(0xc9)
402 BAD_TRAP(0xca) BAD_TRAP(0xcb) BAD_TRAP(0xcc) BAD_TRAP(0xcd) BAD_TRAP(0xce)
403 BAD_TRAP(0xcf) BAD_TRAP(0xd0) BAD_TRAP(0xd1) BAD_TRAP(0xd2) BAD_TRAP(0xd3)
404 BAD_TRAP(0xd4) BAD_TRAP(0xd5) BAD_TRAP(0xd6) BAD_TRAP(0xd7) BAD_TRAP(0xd8)
405 BAD_TRAP(0xd9) BAD_TRAP(0xda) BAD_TRAP(0xdb) BAD_TRAP(0xdc) BAD_TRAP(0xdd)
406 BAD_TRAP(0xde) BAD_TRAP(0xdf) BAD_TRAP(0xe0) BAD_TRAP(0xe1) BAD_TRAP(0xe2)
407 BAD_TRAP(0xe3) BAD_TRAP(0xe4) BAD_TRAP(0xe5) BAD_TRAP(0xe6) BAD_TRAP(0xe7)
408 BAD_TRAP(0xe8) BAD_TRAP(0xe9) BAD_TRAP(0xea) BAD_TRAP(0xeb) BAD_TRAP(0xec)
409 BAD_TRAP(0xed) BAD_TRAP(0xee) BAD_TRAP(0xef) BAD_TRAP(0xf0) BAD_TRAP(0xf1)
410 BAD_TRAP(0xf2) BAD_TRAP(0xf3) BAD_TRAP(0xf4) BAD_TRAP(0xf5) BAD_TRAP(0xf6)
411 BAD_TRAP(0xf7) BAD_TRAP(0xf8) BAD_TRAP(0xf9) BAD_TRAP(0xfa) BAD_TRAP(0xfb)
412 BAD_TRAP(0xfc)
413 KGDB_TRAP(0xfd)
414 BAD_TRAP(0xfe)
415 BAD_TRAP(0xff)
416
417#endif
diff --git a/arch/sparc/kernel/ttable.S b/arch/sparc/kernel/ttable_64.S
index c6dfdaa29e20..c6dfdaa29e20 100644
--- a/arch/sparc/kernel/ttable.S
+++ b/arch/sparc/kernel/ttable_64.S
diff --git a/arch/sparc/kernel/unaligned_64.c b/arch/sparc/kernel/unaligned_64.c
index dae85bc2eda5..f81d038f7340 100644
--- a/arch/sparc/kernel/unaligned_64.c
+++ b/arch/sparc/kernel/unaligned_64.c
@@ -21,7 +21,6 @@
21#include <linux/bitops.h> 21#include <linux/bitops.h>
22#include <linux/perf_event.h> 22#include <linux/perf_event.h>
23#include <linux/ratelimit.h> 23#include <linux/ratelimit.h>
24#include <linux/bitops.h>
25#include <asm/fpumacro.h> 24#include <asm/fpumacro.h>
26#include <asm/cacheflush.h> 25#include <asm/cacheflush.h>
27 26
diff --git a/arch/sparc/kernel/wof.S b/arch/sparc/kernel/wof.S
index 3bbcd8dc9abf..4c2de3cf309b 100644
--- a/arch/sparc/kernel/wof.S
+++ b/arch/sparc/kernel/wof.S
@@ -163,9 +163,8 @@ spwin_fromuser:
163 * the label 'spwin_user_stack_is_bolixed' which will take 163 * the label 'spwin_user_stack_is_bolixed' which will take
164 * care of things at that point. 164 * care of things at that point.
165 */ 165 */
166 .globl spwin_mmu_patchme 166 b spwin_srmmu_stackchk
167spwin_mmu_patchme: b spwin_sun4c_stackchk 167 andcc %sp, 0x7, %g0
168 andcc %sp, 0x7, %g0
169 168
170spwin_good_ustack: 169spwin_good_ustack:
171 /* LOCATION: Window to be saved */ 170 /* LOCATION: Window to be saved */
@@ -306,73 +305,6 @@ spwin_bad_ustack_from_kernel:
306 * As noted above %curptr cannot be touched by this routine at all. 305 * As noted above %curptr cannot be touched by this routine at all.
307 */ 306 */
308 307
309spwin_sun4c_stackchk:
310 /* LOCATION: Window to be saved on the stack */
311
312 /* See if the stack is in the address space hole but first,
313 * check results of callers andcc %sp, 0x7, %g0
314 */
315 be 1f
316 sra %sp, 29, %glob_tmp
317
318 rd %psr, %glob_tmp
319 b spwin_user_stack_is_bolixed + 0x4
320 nop
321
3221:
323 add %glob_tmp, 0x1, %glob_tmp
324 andncc %glob_tmp, 0x1, %g0
325 be 1f
326 and %sp, 0xfff, %glob_tmp ! delay slot
327
328 rd %psr, %glob_tmp
329 b spwin_user_stack_is_bolixed + 0x4
330 nop
331
332 /* See if our dump area will be on more than one
333 * page.
334 */
3351:
336 add %glob_tmp, 0x38, %glob_tmp
337 andncc %glob_tmp, 0xff8, %g0
338 be spwin_sun4c_onepage ! only one page to check
339 lda [%sp] ASI_PTE, %glob_tmp ! have to check first page anyways
340
341spwin_sun4c_twopages:
342 /* Is first page ok permission wise? */
343 srl %glob_tmp, 29, %glob_tmp
344 cmp %glob_tmp, 0x6
345 be 1f
346 add %sp, 0x38, %glob_tmp /* Is second page in vma hole? */
347
348 rd %psr, %glob_tmp
349 b spwin_user_stack_is_bolixed + 0x4
350 nop
351
3521:
353 sra %glob_tmp, 29, %glob_tmp
354 add %glob_tmp, 0x1, %glob_tmp
355 andncc %glob_tmp, 0x1, %g0
356 be 1f
357 add %sp, 0x38, %glob_tmp
358
359 rd %psr, %glob_tmp
360 b spwin_user_stack_is_bolixed + 0x4
361 nop
362
3631:
364 lda [%glob_tmp] ASI_PTE, %glob_tmp
365
366spwin_sun4c_onepage:
367 srl %glob_tmp, 29, %glob_tmp
368 cmp %glob_tmp, 0x6 ! can user write to it?
369 be spwin_good_ustack ! success
370 nop
371
372 rd %psr, %glob_tmp
373 b spwin_user_stack_is_bolixed + 0x4
374 nop
375
376 /* This is a generic SRMMU routine. As far as I know this 308 /* This is a generic SRMMU routine. As far as I know this
377 * works for all current v8/srmmu implementations, we'll 309 * works for all current v8/srmmu implementations, we'll
378 * see... 310 * see...
diff --git a/arch/sparc/kernel/wuf.S b/arch/sparc/kernel/wuf.S
index 779ff750603d..9fde91a249e0 100644
--- a/arch/sparc/kernel/wuf.S
+++ b/arch/sparc/kernel/wuf.S
@@ -131,12 +131,9 @@ fwin_from_user:
131 131
132 /* LOCATION: Window 'W' */ 132 /* LOCATION: Window 'W' */
133 133
134 /* Branch to the architecture specific stack validation 134 /* Branch to the stack validation routine */
135 * routine. They can be found below... 135 b srmmu_fwin_stackchk
136 */ 136 andcc %sp, 0x7, %g0
137 .globl fwin_mmu_patchme
138fwin_mmu_patchme: b sun4c_fwin_stackchk
139 andcc %sp, 0x7, %g0
140 137
141#define STACK_OFFSET (THREAD_SIZE - TRACEREG_SZ - STACKFRAME_SZ) 138#define STACK_OFFSET (THREAD_SIZE - TRACEREG_SZ - STACKFRAME_SZ)
142 139
@@ -242,57 +239,6 @@ fwin_user_finish_up:
242 * 'someone elses' window possibly. 239 * 'someone elses' window possibly.
243 */ 240 */
244 241
245 .align 4
246sun4c_fwin_stackchk:
247 /* LOCATION: Window 'W' */
248
249 /* Caller did 'andcc %sp, 0x7, %g0' */
250 be 1f
251 and %sp, 0xfff, %l0 ! delay slot
252
253 b,a fwin_user_stack_is_bolixed
254
255 /* See if we have to check the sanity of one page or two */
2561:
257 add %l0, 0x38, %l0
258 sra %sp, 29, %l5
259 add %l5, 0x1, %l5
260 andncc %l5, 0x1, %g0
261 be 1f
262 andncc %l0, 0xff8, %g0
263
264 b,a fwin_user_stack_is_bolixed /* %sp is in vma hole, yuck */
265
2661:
267 be sun4c_fwin_onepage /* Only one page to check */
268 lda [%sp] ASI_PTE, %l1
269sun4c_fwin_twopages:
270 add %sp, 0x38, %l0
271 sra %l0, 29, %l5
272 add %l5, 0x1, %l5
273 andncc %l5, 0x1, %g0
274 be 1f
275 lda [%l0] ASI_PTE, %l1
276
277 b,a fwin_user_stack_is_bolixed /* Second page in vma hole */
278
2791:
280 srl %l1, 29, %l1
281 andcc %l1, 0x4, %g0
282 bne sun4c_fwin_onepage
283 lda [%sp] ASI_PTE, %l1
284
285 b,a fwin_user_stack_is_bolixed /* Second page has bad perms */
286
287sun4c_fwin_onepage:
288 srl %l1, 29, %l1
289 andcc %l1, 0x4, %g0
290 bne fwin_user_stack_is_ok
291 nop
292
293 /* A page had bad page permissions, losing... */
294 b,a fwin_user_stack_is_bolixed
295
296 .globl srmmu_fwin_stackchk 242 .globl srmmu_fwin_stackchk
297srmmu_fwin_stackchk: 243srmmu_fwin_stackchk:
298 /* LOCATION: Window 'W' */ 244 /* LOCATION: Window 'W' */