diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-05-21 13:32:01 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-05-21 13:32:01 -0400 |
commit | 9daeaa370526df1c19eba4780247bb7155541e38 (patch) | |
tree | 5ae2601c26e280e81d753c1fe65453a3b8b1d2a0 /arch/sparc/kernel | |
parent | cb62ab71fe2b16e8203a0f0a2ef4eda23d761338 (diff) | |
parent | 1edc17832d8f49a0263d364c453ea35da0e4e2a6 (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')
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 |
30 | obj-y += irq_$(BITS).o | 30 | obj-y += irq_$(BITS).o |
31 | obj-$(CONFIG_SPARC32) += sun4m_irq.o sun4c_irq.o sun4d_irq.o | 31 | obj-$(CONFIG_SPARC32) += sun4m_irq.o sun4d_irq.o |
32 | 32 | ||
33 | obj-y += process_$(BITS).o | 33 | obj-y += process_$(BITS).o |
34 | obj-y += signal_$(BITS).o | 34 | obj-y += signal_$(BITS).o |
@@ -46,7 +46,6 @@ obj-$(CONFIG_SPARC32) += tadpole.o | |||
46 | obj-y += ptrace_$(BITS).o | 46 | obj-y += ptrace_$(BITS).o |
47 | obj-y += unaligned_$(BITS).o | 47 | obj-y += unaligned_$(BITS).o |
48 | obj-y += una_asm_$(BITS).o | 48 | obj-y += una_asm_$(BITS).o |
49 | obj-$(CONFIG_SPARC32) += muldiv.o | ||
50 | obj-y += prom_common.o | 49 | obj-y += prom_common.o |
51 | obj-y += prom_$(BITS).o | 50 | obj-y += prom_$(BITS).o |
52 | obj-y += of_device_common.o | 51 | obj-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 | ||
23 | extern void clock_stop_probe(void); /* tadpole.c */ | 23 | extern void clock_stop_probe(void); /* tadpole.c */ |
24 | extern void sun4c_probe_memerr_reg(void); | ||
25 | 24 | ||
26 | static char *cpu_mid_prop(void) | 25 | static 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 | ||
869 | static void ds_conn_reset(struct ds_info *dp) | 869 | static 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 | |||
140 | 1: | ||
141 | or %l5, 0xf4, %l5 | ||
142 | stb %l5, [%l7] | ||
143 | andn %l5, 0x04, %l5 | ||
144 | 132 | ||
145 | 2: | 133 | 2: |
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 |
345 | 1: | ||
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 | 735 | sun4m_nmi_error: |
764 | .globl linux_trap_nmi_sun4c | 736 | /* NMI async memory error handling. */ |
765 | linux_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 | ||
803 | invalid_segment_patch1_ff: cmp %l4, 0xff | ||
804 | invalid_segment_patch2_ff: mov 0xff, %l3 | ||
805 | |||
806 | .align 4 | ||
807 | .globl invalid_segment_patch1_1ff | ||
808 | .globl invalid_segment_patch2_1ff | ||
809 | invalid_segment_patch1_1ff: cmp %l4, 0x1ff | ||
810 | invalid_segment_patch2_1ff: mov 0x1ff, %l3 | ||
811 | |||
812 | .align 4 | ||
813 | .globl num_context_patch1_16, num_context_patch2_16 | ||
814 | num_context_patch1_16: mov 0x10, %l7 | ||
815 | num_context_patch2_16: mov 0x10, %l7 | ||
816 | |||
817 | .align 4 | ||
818 | .globl vac_linesize_patch_32 | ||
819 | vac_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 | */ | ||
828 | vac_hwflush_patch1_on: addcc %l7, -PAGE_SIZE, %l7 | ||
829 | |||
830 | vac_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 | ||
846 | sun4c_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 | |||
869 | 1: | ||
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 | |||
901 | invalid_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 | |||
940 | 2: | ||
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 | ||
950 | 9: | ||
951 | vac_hwflush_patch1: | ||
952 | vac_linesize_patch: | ||
953 | subcc %l7, 16, %l7 | ||
954 | bne 9b | ||
955 | vac_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 | |||
975 | 4: | ||
976 | num_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 | */ | ||
990 | 3: deccc %l7 | ||
991 | sethi %hi(AC_CONTEXT), %l3 | ||
992 | stba %l7, [%l3] ASI_CONTROL | ||
993 | invalid_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 | |||
1005 | 1: | ||
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 | |||
1021 | 2: | ||
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 | |||
1031 | 1: | ||
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 | |||
1045 | 2: | ||
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 | ||
1054 | 7: | ||
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 | |
1065 | sun4c_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 | ||
760 | linux_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 |
1508 | 3: | 1195 | 3: |
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 | ||
1512 | delay_continue: | 1200 | delay_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 | ||
1362 | ENTRY(hard_smp_processor_id) | ||
1363 | 661: 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 | ||
1380 | ENDPROC(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 |
220 | tsetup_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 | ||
231 | tsetup_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 | |||
249 | tsetup_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 | |||
264 | tsetup_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 |
278 | tsetup_srmmu_stackchk: | 230 | tsetup_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 |
35 | cputyp: | 33 | cputyp: |
36 | .word 1 | 34 | .word 1 |
@@ -38,384 +36,35 @@ cputyp: | |||
38 | .align 4 | 36 | .align 4 |
39 | .globl cputypval | 37 | .globl cputypval |
40 | cputypval: | 38 | cputypval: |
41 | .asciz "sun4c" | 39 | .asciz "sun4m" |
42 | .ascii " " | 40 | .ascii " " |
43 | 41 | ||
44 | cputypvalend: | 42 | /* Tested on SS-5, SS-10 */ |
45 | cputypvallen = 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 | */ | ||
56 | cputypvar: | 44 | cputypvar: |
57 | .asciz "compatability" | ||
58 | |||
59 | /* Tested on SS-5, SS-10. Probably someone at Sun applied a spell-checker. */ | ||
60 | .align 4 | ||
61 | cputypvar_sun4m: | ||
62 | .asciz "compatible" | 45 | .asciz "compatible" |
63 | 46 | ||
64 | .align 4 | 47 | .align 4 |
65 | 48 | ||
66 | sun4_notsup: | 49 | sun4c_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 | ||
70 | sun4e_notsup: | 53 | sun4e_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: | ||
81 | trapbase: | ||
82 | #ifdef CONFIG_SMP | ||
83 | trapbase_cpu0: | ||
84 | #endif | ||
85 | /* We get control passed to us here at t_zero. */ | ||
86 | t_zero: b gokernel; nop; nop; nop; | ||
87 | t_tflt: SPARC_TFAULT /* Inst. Access Exception */ | ||
88 | t_bins: TRAP_ENTRY(0x2, bad_instruction) /* Illegal Instruction */ | ||
89 | t_pins: TRAP_ENTRY(0x3, priv_instruction) /* Privileged Instruction */ | ||
90 | t_fpd: TRAP_ENTRY(0x4, fpd_trap_handler) /* Floating Point Disabled */ | ||
91 | t_wovf: WINDOW_SPILL /* Window Overflow */ | ||
92 | t_wunf: WINDOW_FILL /* Window Underflow */ | ||
93 | t_mna: TRAP_ENTRY(0x7, mna_handler) /* Memory Address Not Aligned */ | ||
94 | t_fpe: TRAP_ENTRY(0x8, fpe_trap_handler) /* Floating Point Exception */ | ||
95 | t_dflt: SPARC_DFAULT /* Data Miss Exception */ | ||
96 | t_tio: TRAP_ENTRY(0xa, do_tag_overflow) /* Tagged Instruction Ovrflw */ | ||
97 | t_wpt: TRAP_ENTRY(0xb, do_watchpoint) /* Watchpoint Detected */ | ||
98 | t_badc: BAD_TRAP(0xc) BAD_TRAP(0xd) BAD_TRAP(0xe) BAD_TRAP(0xf) BAD_TRAP(0x10) | ||
99 | t_irq1: TRAP_ENTRY_INTERRUPT(1) /* IRQ Software/SBUS Level 1 */ | ||
100 | t_irq2: TRAP_ENTRY_INTERRUPT(2) /* IRQ SBUS Level 2 */ | ||
101 | t_irq3: TRAP_ENTRY_INTERRUPT(3) /* IRQ SCSI/DMA/SBUS Level 3 */ | ||
102 | t_irq4: TRAP_ENTRY_INTERRUPT(4) /* IRQ Software Level 4 */ | ||
103 | t_irq5: TRAP_ENTRY_INTERRUPT(5) /* IRQ SBUS/Ethernet Level 5 */ | ||
104 | t_irq6: TRAP_ENTRY_INTERRUPT(6) /* IRQ Software Level 6 */ | ||
105 | t_irq7: TRAP_ENTRY_INTERRUPT(7) /* IRQ Video/SBUS Level 5 */ | ||
106 | t_irq8: TRAP_ENTRY_INTERRUPT(8) /* IRQ SBUS Level 6 */ | ||
107 | t_irq9: TRAP_ENTRY_INTERRUPT(9) /* IRQ SBUS Level 7 */ | ||
108 | t_irq10:TRAP_ENTRY_INTERRUPT(10) /* IRQ Timer #1 (one we use) */ | ||
109 | t_irq11:TRAP_ENTRY_INTERRUPT(11) /* IRQ Floppy Intr. */ | ||
110 | t_irq12:TRAP_ENTRY_INTERRUPT(12) /* IRQ Zilog serial chip */ | ||
111 | t_irq13:TRAP_ENTRY_INTERRUPT(13) /* IRQ Audio Intr. */ | ||
112 | t_irq14:TRAP_ENTRY_INTERRUPT(14) /* IRQ Timer #2 */ | ||
113 | .globl t_nmi | ||
114 | #ifndef CONFIG_SMP | ||
115 | t_nmi: NMI_TRAP /* Level 15 (NMI) */ | ||
116 | #else | ||
117 | t_nmi: TRAP_ENTRY(0x1f, linux_trap_ipi15_sun4m) | ||
118 | #endif | ||
119 | t_racc: TRAP_ENTRY(0x20, do_reg_access) /* General Register Access Error */ | ||
120 | t_iacce:BAD_TRAP(0x21) /* Instr Access Error */ | ||
121 | t_bad22:BAD_TRAP(0x22) BAD_TRAP(0x23) | ||
122 | t_cpdis:TRAP_ENTRY(0x24, do_cp_disabled) /* Co-Processor Disabled */ | ||
123 | t_uflsh:SKIP_TRAP(0x25, unimp_flush) /* Unimplemented FLUSH inst. */ | ||
124 | t_bad26:BAD_TRAP(0x26) BAD_TRAP(0x27) | ||
125 | t_cpexc:TRAP_ENTRY(0x28, do_cp_exception) /* Co-Processor Exception */ | ||
126 | t_dacce:SPARC_DFAULT /* Data Access Error */ | ||
127 | t_hwdz: TRAP_ENTRY(0x2a, do_hw_divzero) /* Division by zero, you lose... */ | ||
128 | t_dserr:BAD_TRAP(0x2b) /* Data Store Error */ | ||
129 | t_daccm:BAD_TRAP(0x2c) /* Data Access MMU-Miss */ | ||
130 | t_bad2d:BAD_TRAP(0x2d) BAD_TRAP(0x2e) BAD_TRAP(0x2f) BAD_TRAP(0x30) BAD_TRAP(0x31) | ||
131 | t_bad32:BAD_TRAP(0x32) BAD_TRAP(0x33) BAD_TRAP(0x34) BAD_TRAP(0x35) BAD_TRAP(0x36) | ||
132 | t_bad37:BAD_TRAP(0x37) BAD_TRAP(0x38) BAD_TRAP(0x39) BAD_TRAP(0x3a) BAD_TRAP(0x3b) | ||
133 | t_iaccm:BAD_TRAP(0x3c) /* Instr Access MMU-Miss */ | ||
134 | t_bad3d:BAD_TRAP(0x3d) BAD_TRAP(0x3e) BAD_TRAP(0x3f) BAD_TRAP(0x40) BAD_TRAP(0x41) | ||
135 | t_bad42:BAD_TRAP(0x42) BAD_TRAP(0x43) BAD_TRAP(0x44) BAD_TRAP(0x45) BAD_TRAP(0x46) | ||
136 | t_bad47:BAD_TRAP(0x47) BAD_TRAP(0x48) BAD_TRAP(0x49) BAD_TRAP(0x4a) BAD_TRAP(0x4b) | ||
137 | t_bad4c:BAD_TRAP(0x4c) BAD_TRAP(0x4d) BAD_TRAP(0x4e) BAD_TRAP(0x4f) BAD_TRAP(0x50) | ||
138 | t_bad51:BAD_TRAP(0x51) BAD_TRAP(0x52) BAD_TRAP(0x53) BAD_TRAP(0x54) BAD_TRAP(0x55) | ||
139 | t_bad56:BAD_TRAP(0x56) BAD_TRAP(0x57) BAD_TRAP(0x58) BAD_TRAP(0x59) BAD_TRAP(0x5a) | ||
140 | t_bad5b:BAD_TRAP(0x5b) BAD_TRAP(0x5c) BAD_TRAP(0x5d) BAD_TRAP(0x5e) BAD_TRAP(0x5f) | ||
141 | t_bad60:BAD_TRAP(0x60) BAD_TRAP(0x61) BAD_TRAP(0x62) BAD_TRAP(0x63) BAD_TRAP(0x64) | ||
142 | t_bad65:BAD_TRAP(0x65) BAD_TRAP(0x66) BAD_TRAP(0x67) BAD_TRAP(0x68) BAD_TRAP(0x69) | ||
143 | t_bad6a:BAD_TRAP(0x6a) BAD_TRAP(0x6b) BAD_TRAP(0x6c) BAD_TRAP(0x6d) BAD_TRAP(0x6e) | ||
144 | t_bad6f:BAD_TRAP(0x6f) BAD_TRAP(0x70) BAD_TRAP(0x71) BAD_TRAP(0x72) BAD_TRAP(0x73) | ||
145 | t_bad74:BAD_TRAP(0x74) BAD_TRAP(0x75) BAD_TRAP(0x76) BAD_TRAP(0x77) BAD_TRAP(0x78) | ||
146 | t_bad79:BAD_TRAP(0x79) BAD_TRAP(0x7a) BAD_TRAP(0x7b) BAD_TRAP(0x7c) BAD_TRAP(0x7d) | ||
147 | t_bad7e:BAD_TRAP(0x7e) BAD_TRAP(0x7f) | ||
148 | t_bad80:BAD_TRAP(0x80) /* SunOS System Call */ | ||
149 | t_sbkpt:BREAKPOINT_TRAP /* Software Breakpoint/KGDB */ | ||
150 | t_divz: TRAP_ENTRY(0x82, do_hw_divzero) /* Divide by zero trap */ | ||
151 | t_flwin:TRAP_ENTRY(0x83, do_flush_windows) /* Flush Windows Trap */ | ||
152 | t_clwin:BAD_TRAP(0x84) /* Clean Windows Trap */ | ||
153 | t_rchk: BAD_TRAP(0x85) /* Range Check */ | ||
154 | t_funal:BAD_TRAP(0x86) /* Fix Unaligned Access Trap */ | ||
155 | t_iovf: BAD_TRAP(0x87) /* Integer Overflow Trap */ | ||
156 | t_bad88:BAD_TRAP(0x88) /* Slowaris System Call */ | ||
157 | t_bad89:BAD_TRAP(0x89) /* Net-B.S. System Call */ | ||
158 | t_bad8a:BAD_TRAP(0x8a) BAD_TRAP(0x8b) BAD_TRAP(0x8c) BAD_TRAP(0x8d) BAD_TRAP(0x8e) | ||
159 | t_bad8f:BAD_TRAP(0x8f) | ||
160 | t_linux:LINUX_SYSCALL_TRAP /* Linux System Call */ | ||
161 | t_bad91:BAD_TRAP(0x91) BAD_TRAP(0x92) BAD_TRAP(0x93) BAD_TRAP(0x94) BAD_TRAP(0x95) | ||
162 | t_bad96:BAD_TRAP(0x96) BAD_TRAP(0x97) BAD_TRAP(0x98) BAD_TRAP(0x99) BAD_TRAP(0x9a) | ||
163 | t_bad9b:BAD_TRAP(0x9b) BAD_TRAP(0x9c) BAD_TRAP(0x9d) BAD_TRAP(0x9e) BAD_TRAP(0x9f) | ||
164 | t_getcc:GETCC_TRAP /* Get Condition Codes */ | ||
165 | t_setcc:SETCC_TRAP /* Set Condition Codes */ | ||
166 | t_getpsr:GETPSR_TRAP /* Get PSR Register */ | ||
167 | t_bada3:BAD_TRAP(0xa3) BAD_TRAP(0xa4) BAD_TRAP(0xa5) BAD_TRAP(0xa6) | ||
168 | t_bada7:BAD_TRAP(0xa7) | ||
169 | t_bada8:BAD_TRAP(0xa8) BAD_TRAP(0xa9) BAD_TRAP(0xaa) BAD_TRAP(0xab) | ||
170 | t_badac:BAD_TRAP(0xac) BAD_TRAP(0xad) BAD_TRAP(0xae) BAD_TRAP(0xaf) BAD_TRAP(0xb0) | ||
171 | t_badb1:BAD_TRAP(0xb1) BAD_TRAP(0xb2) BAD_TRAP(0xb3) BAD_TRAP(0xb4) BAD_TRAP(0xb5) | ||
172 | t_badb6:BAD_TRAP(0xb6) BAD_TRAP(0xb7) BAD_TRAP(0xb8) BAD_TRAP(0xb9) BAD_TRAP(0xba) | ||
173 | t_badbb:BAD_TRAP(0xbb) BAD_TRAP(0xbc) BAD_TRAP(0xbd) BAD_TRAP(0xbe) BAD_TRAP(0xbf) | ||
174 | t_badc0:BAD_TRAP(0xc0) BAD_TRAP(0xc1) BAD_TRAP(0xc2) BAD_TRAP(0xc3) BAD_TRAP(0xc4) | ||
175 | t_badc5:BAD_TRAP(0xc5) BAD_TRAP(0xc6) BAD_TRAP(0xc7) BAD_TRAP(0xc8) BAD_TRAP(0xc9) | ||
176 | t_badca:BAD_TRAP(0xca) BAD_TRAP(0xcb) BAD_TRAP(0xcc) BAD_TRAP(0xcd) BAD_TRAP(0xce) | ||
177 | t_badcf:BAD_TRAP(0xcf) BAD_TRAP(0xd0) BAD_TRAP(0xd1) BAD_TRAP(0xd2) BAD_TRAP(0xd3) | ||
178 | t_badd4:BAD_TRAP(0xd4) BAD_TRAP(0xd5) BAD_TRAP(0xd6) BAD_TRAP(0xd7) BAD_TRAP(0xd8) | ||
179 | t_badd9:BAD_TRAP(0xd9) BAD_TRAP(0xda) BAD_TRAP(0xdb) BAD_TRAP(0xdc) BAD_TRAP(0xdd) | ||
180 | t_badde:BAD_TRAP(0xde) BAD_TRAP(0xdf) BAD_TRAP(0xe0) BAD_TRAP(0xe1) BAD_TRAP(0xe2) | ||
181 | t_bade3:BAD_TRAP(0xe3) BAD_TRAP(0xe4) BAD_TRAP(0xe5) BAD_TRAP(0xe6) BAD_TRAP(0xe7) | ||
182 | t_bade8:BAD_TRAP(0xe8) BAD_TRAP(0xe9) BAD_TRAP(0xea) BAD_TRAP(0xeb) BAD_TRAP(0xec) | ||
183 | t_baded:BAD_TRAP(0xed) BAD_TRAP(0xee) BAD_TRAP(0xef) BAD_TRAP(0xf0) BAD_TRAP(0xf1) | ||
184 | t_badf2:BAD_TRAP(0xf2) BAD_TRAP(0xf3) BAD_TRAP(0xf4) BAD_TRAP(0xf5) BAD_TRAP(0xf6) | ||
185 | t_badf7:BAD_TRAP(0xf7) BAD_TRAP(0xf8) BAD_TRAP(0xf9) BAD_TRAP(0xfa) BAD_TRAP(0xfb) | ||
186 | t_badfc:BAD_TRAP(0xfc) | ||
187 | t_kgdb: KGDB_TRAP(0xfd) | ||
188 | dbtrap: BAD_TRAP(0xfe) /* Debugger/PROM breakpoint #1 */ | ||
189 | dbtrap2:BAD_TRAP(0xff) /* Debugger/PROM breakpoint #2 */ | ||
190 | |||
191 | .globl end_traptable | ||
192 | end_traptable: | ||
193 | |||
194 | #ifdef CONFIG_SMP | ||
195 | /* Trap tables for the other cpus. */ | ||
196 | .globl trapbase_cpu1, trapbase_cpu2, trapbase_cpu3 | ||
197 | trapbase_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 | |||
265 | trapbase_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 | |||
333 | trapbase_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 |
412 | swapper_pg_dir: .skip PAGE_SIZE | 66 | swapper_pg_dir: .skip PAGE_SIZE |
413 | pg0: .skip PAGE_SIZE | 67 | .globl empty_zero_page |
414 | pg1: .skip PAGE_SIZE | ||
415 | pg2: .skip PAGE_SIZE | ||
416 | pg3: .skip PAGE_SIZE | ||
417 | empty_bad_page: .skip PAGE_SIZE | ||
418 | empty_bad_page_table: .skip PAGE_SIZE | ||
419 | empty_zero_page: .skip PAGE_SIZE | 68 | empty_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 | 195 | halt_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 | ||
552 | remap_not_a_sun4: | 204 | not_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 | |||
558 | srmmu_remap: | 210 | srmmu_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 | */ | ||
674 | sun4_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 | */ | ||
688 | sun4_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. */ | ||
699 | sun4_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 | ||
705 | sun4_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 */ | ||
716 | sun4c_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 | ||
722 | sun4c_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 */ |
731 | go_to_highmem: | 317 | go_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 | |||
775 | found_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 | |||
810 | got_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 | ||
851 | 1: 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 | ||
894 | sun4m_init: | 426 | sun4m_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 | |||
909 | 1: | ||
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 | ||
985 | sun4c_continue_boot: | 457 | continue_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 | ||
1029 | 1: /* boot_cpu_id set. calculate boot_cpu_id4 = boot_cpu_id*4 */ | 500 | 1: 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 | ||
1168 | sun4_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 | ||
1178 | 1: ba 1b ! Cannot exit into KMON | ||
1179 | nop | ||
1180 | |||
1181 | no_sun4e_here: | 636 | no_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 | */ |
28 | static struct Sun_Machine_Models Sun_Machines[NUM_SUN_MACHINES] = { | 28 | static 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 | ||
53 | const 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 | ||
6 | struct irq_bucket { | 5 | struct 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 { | |||
41 | extern struct sun4m_irq_percpu __iomem *sun4m_irq_percpu[SUN4M_NCPUS]; | 43 | extern struct sun4m_irq_percpu __iomem *sun4m_irq_percpu[SUN4M_NCPUS]; |
42 | extern struct sun4m_irq_global __iomem *sun4m_irq_global; | 44 | extern 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 | */ |
49 | struct sparc_irq_config { | 56 | struct 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 | }; |
54 | extern struct sparc_irq_config sparc_irq_config; | 76 | extern struct sparc_config sparc_config; |
55 | 77 | ||
56 | unsigned int irq_alloc(unsigned int real_irq, unsigned int pil); | 78 | unsigned int irq_alloc(unsigned int real_irq, unsigned int pil); |
57 | void irq_link(unsigned int irq); | 79 | void irq_link(unsigned int irq); |
58 | void irq_unlink(unsigned int irq); | 80 | void irq_unlink(unsigned int irq); |
59 | void handler_irq(unsigned int pil, struct pt_regs *regs); | 81 | void handler_irq(unsigned int pil, struct pt_regs *regs); |
60 | 82 | ||
61 | /* Dave Redman (djhr@tadpole.co.uk) | 83 | unsigned 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 | |||
69 | BTFIXUPDEF_CALL(void, clear_clock_irq, void) | ||
70 | BTFIXUPDEF_CALL(void, load_profile_irq, int, unsigned int) | ||
71 | |||
72 | static inline void clear_clock_irq(void) | ||
73 | { | ||
74 | BTFIXUP_CALL(clear_clock_irq)(); | ||
75 | } | ||
76 | |||
77 | static 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 |
83 | BTFIXUPDEF_CALL(void, set_cpu_int, int, int) | ||
84 | BTFIXUPDEF_CALL(void, clear_cpu_int, int, int) | ||
85 | BTFIXUPDEF_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 */ |
35 | struct sparc_irq_config sparc_irq_config; | 27 | struct sparc_config sparc_config; |
36 | 28 | ||
37 | unsigned long arch_local_irq_save(void) | 29 | unsigned 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) | |||
346 | void __init init_IRQ(void) | 335 | void __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 */ |
33 | extern void handle_hw_divzero(struct pt_regs *regs, unsigned long pc, | 33 | extern 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 */ | ||
36 | extern int do_user_muldiv (struct pt_regs *, unsigned long); | ||
37 | |||
38 | /* irq_32.c */ | 35 | /* irq_32.c */ |
39 | extern struct irqaction static_irqaction[]; | 36 | extern struct irqaction static_irqaction[]; |
40 | extern int static_irq_count; | 37 | extern int static_irq_count; |
@@ -43,12 +40,7 @@ extern spinlock_t irq_action_lock; | |||
43 | extern void unexpected_irq(int irq, void *dev_id, struct pt_regs * regs); | 40 | extern void unexpected_irq(int irq, void *dev_id, struct pt_regs * regs); |
44 | extern void init_IRQ(void); | 41 | extern void init_IRQ(void); |
45 | 42 | ||
46 | /* sun4c_irq.c */ | ||
47 | extern void sun4c_init_IRQ(void); | ||
48 | |||
49 | /* sun4m_irq.c */ | 43 | /* sun4m_irq.c */ |
50 | extern unsigned int lvl14_resolution; | ||
51 | |||
52 | extern void sun4m_init_IRQ(void); | 44 | extern void sun4m_init_IRQ(void); |
53 | extern void sun4m_unmask_profile_irq(void); | 45 | extern void sun4m_unmask_profile_irq(void); |
54 | extern void sun4m_clear_profile_irq(int cpu); | 46 | extern void sun4m_clear_profile_irq(int cpu); |
@@ -85,8 +77,6 @@ extern unsigned int patchme_maybe_smp_msg[]; | |||
85 | extern void floppy_hardint(void); | 77 | extern void floppy_hardint(void); |
86 | 78 | ||
87 | /* trampoline_32.S */ | 79 | /* trampoline_32.S */ |
88 | extern int __smp4m_processor_id(void); | ||
89 | extern int __smp4d_processor_id(void); | ||
90 | extern unsigned long sun4m_cpu_startup; | 80 | extern unsigned long sun4m_cpu_startup; |
91 | extern unsigned long sun4d_cpu_startup; | 81 | extern 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 | ||
87 | static inline unsigned long get_irqmask(unsigned int irq) | 89 | unsigned 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 | ||
253 | void __init leon_init_timers(irq_handler_t counter_fn) | 255 | static 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 */ | ||
267 | irqreturn_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 | |||
286 | void __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 | ||
425 | void leon_clear_clock_irq(void) | 466 | static void leon_clear_clock_irq(void) |
426 | { | 467 | { |
427 | } | 468 | } |
428 | 469 | ||
429 | void leon_load_profile_irq(int cpu, unsigned int limit) | 470 | static void leon_load_profile_irq(int cpu, unsigned int limit) |
430 | { | 471 | { |
431 | BUG(); | ||
432 | } | 472 | } |
433 | 473 | ||
434 | void __init leon_trans_init(struct device_node *dp) | 474 | void __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 | |||
461 | void 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 | |||
468 | static 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 | |||
475 | static void leon_set_udt(int cpu) | ||
476 | { | ||
477 | } | ||
478 | |||
479 | void leon_clear_profile_irq(int cpu) | 500 | void leon_clear_profile_irq(int cpu) |
480 | { | 501 | { |
481 | } | 502 | } |
@@ -483,7 +504,7 @@ void leon_clear_profile_irq(int cpu) | |||
483 | void leon_enable_irq_cpu(unsigned int irq_nr, unsigned int cpu) | 504 | void 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 | ||
495 | void __init leon_init_IRQ(void) | 516 | void __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 | ||
513 | void __init leon_init(void) | 525 | void __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 | ||
72 | static void smp_setup_percpu_timer(void); | ||
73 | |||
74 | void __cpuinit leon_callin(void) | 74 | void __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"(¤t_set[cpuid]) | 106 | __asm__ __volatile__("ld [%0], %%g6\n\t" : : "r"(¤t_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 | ||
150 | void leon_smp_setbroadcast(unsigned int mask) | 150 | void 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 | ||
349 | static 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 | |||
350 | static void leon_ipi_single(int cpu) | 356 | static 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 | ||
361 | static void leon_ipi_mask_one(int cpu) | 367 | static 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 | ||
372 | static void leon_ipi_resched(int cpu) | 378 | static 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 | ||
383 | void leonsmp_ipi_interrupt(void) | 389 | void 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 | ||
495 | irqreturn_t leon_percpu_timer_interrupt(int irq, void *unused) | 501 | static 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 | |||
514 | static 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 | |||
521 | void __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 | |||
532 | void __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 | ||
544 | void __init leon_init_smp(void) | 508 | void __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 | |||
36 | static char *dot2underscore(char *name) | ||
37 | { | ||
38 | return name; | ||
39 | } | ||
40 | #else | 35 | #else |
41 | static void *module_map(unsigned long size) | 36 | static 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 */ | ||
47 | static 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 | ||
57 | void *module_alloc(unsigned long size) | 42 | void *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 | |||
23 | static inline int has_imm13(int insn) | ||
24 | { | ||
25 | return (insn & 0x2000); | ||
26 | } | ||
27 | |||
28 | static inline int is_foocc(int insn) | ||
29 | { | ||
30 | return (insn & 0x800000); | ||
31 | } | ||
32 | |||
33 | static inline int sign_extend_imm13(int imm) | ||
34 | { | ||
35 | return imm << 19 >> 19; | ||
36 | } | ||
37 | |||
38 | static inline void advance(struct pt_regs *regs) | ||
39 | { | ||
40 | regs->pc = regs->npc; | ||
41 | regs->npc += 4; | ||
42 | } | ||
43 | |||
44 | static 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 | |||
76 | static inline int | ||
77 | store_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 | */ | ||
96 | int 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 | ||
706 | static 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 | |||
710 | static 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 | ||
719 | u32 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 | ||
732 | void __init pci_time_init(void) | 729 | void __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 | ||
876 | void __init sun4m_pci_init_IRQ(void) | 880 | void __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 | ||
884 | int pcibios_assign_resource(struct pci_dev *pdev, int resource) | 887 | int 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 | |||
184 | static DEFINE_SPINLOCK(sparc_backtrace_lock); | ||
185 | |||
186 | void __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 | |||
213 | void 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 | ||
228 | void smp_show_backtrace_all_cpus(void) | ||
229 | { | ||
230 | xc0((smpfunc_t) show_backtrace); | ||
231 | show_backtrace(); | ||
232 | } | ||
233 | #endif | ||
234 | |||
235 | void 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 | |||
264 | void show_regs(struct pt_regs *r) | 148 | void 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 |
136 | rtrap_mmu_patchme: b sun4c_rett_stackchk | 136 | andcc %fp, 0x7, %g0 |
137 | andcc %fp, 0x7, %g0 | ||
138 | 137 | ||
139 | ret_trap_userwins_ok: | 138 | ret_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 | ||
228 | sun4c_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 */ | ||
236 | 1: | ||
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 | |||
248 | 1: | ||
249 | be sun4c_rett_onepage /* Only one page to check */ | ||
250 | lda [%fp] ASI_PTE, %g2 | ||
251 | |||
252 | sun4c_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 | |||
264 | 1: | ||
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 | |||
274 | sun4c_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. */ | ||
285 | 1: | ||
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 |
292 | srmmu_rett_stackchk: | 228 | srmmu_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 |
74 | rtrap_irq: | 74 | rtrap_irq: |
75 | rtrap: | 75 | rtrap: |
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 |
88 | rtrap_xcall: | 78 | rtrap_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) */ |
108 | unsigned char boot_cpu_id = 0xff; /* 0xff will make it into DATA section... */ | 107 | unsigned char boot_cpu_id = 0xff; /* 0xff will make it into DATA section... */ |
109 | unsigned char boot_cpu_id4; /* boot_cpu_id << 2 */ | ||
110 | 108 | ||
111 | static void | 109 | static void |
112 | prom_console_write(struct console *con, const char *s, unsigned n) | 110 | prom_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 | |||
190 | extern void sun4c_probe_vac(void); | ||
191 | |||
192 | extern unsigned short root_flags; | 183 | extern unsigned short root_flags; |
193 | extern unsigned short root_dev; | 184 | extern unsigned short root_dev; |
194 | extern unsigned short ram_flags; | 185 | extern unsigned short ram_flags; |
@@ -200,6 +191,52 @@ extern int root_mountflags; | |||
200 | 191 | ||
201 | char reboot_command[COMMAND_LINE_SIZE]; | 192 | char reboot_command[COMMAND_LINE_SIZE]; |
202 | 193 | ||
194 | struct cpuid_patch_entry { | ||
195 | unsigned int addr; | ||
196 | unsigned int sun4d[3]; | ||
197 | unsigned int leon[3]; | ||
198 | }; | ||
199 | extern struct cpuid_patch_entry __cpuid_patch, __cpuid_patch_end; | ||
200 | |||
201 | static 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 | |||
203 | enum sparc_cpu sparc_cpu_model; | 240 | enum sparc_cpu sparc_cpu_model; |
204 | EXPORT_SYMBOL(sparc_cpu_model); | 241 | EXPORT_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 */ |
218 | static inline int invalid_frame_pointer(void __user *fp, int fplen) | 218 | static 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 | ||
41 | cpumask_t smp_commenced_mask = CPU_MASK_NONE; | 41 | cpumask_t smp_commenced_mask = CPU_MASK_NONE; |
42 | 42 | ||
43 | const 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 | ||
138 | void smp_send_stop(void) | 132 | void smp_send_stop(void) |
@@ -142,7 +136,7 @@ void smp_send_stop(void) | |||
142 | void arch_send_call_function_single_ipi(int cpu) | 136 | void 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 | ||
148 | void arch_send_call_function_ipi_mask(const struct cpumask *mask) | 142 | void 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 | ||
157 | void smp_resched_interrupt(void) | 151 | void smp_resched_interrupt(void) |
@@ -179,150 +173,9 @@ void smp_call_function_interrupt(void) | |||
179 | irq_exit(); | 173 | irq_exit(); |
180 | } | 174 | } |
181 | 175 | ||
182 | void smp_flush_cache_all(void) | ||
183 | { | ||
184 | xc0((smpfunc_t) BTFIXUP_CALL(local_flush_cache_all)); | ||
185 | local_flush_cache_all(); | ||
186 | } | ||
187 | |||
188 | void smp_flush_tlb_all(void) | ||
189 | { | ||
190 | xc0((smpfunc_t) BTFIXUP_CALL(local_flush_tlb_all)); | ||
191 | local_flush_tlb_all(); | ||
192 | } | ||
193 | |||
194 | void 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 | |||
206 | void 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 | |||
222 | void 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 | |||
237 | void 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 | |||
252 | void 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 | |||
266 | void 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 | |||
280 | void 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 | |||
294 | void 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 | |||
304 | extern unsigned int lvl14_resolution; | ||
305 | |||
306 | /* /proc/profile writes can call this, don't __init it please. */ | ||
307 | static DEFINE_SPINLOCK(prof_setup_lock); | ||
308 | |||
309 | int setup_profiling_timer(unsigned int multiplier) | 176 | int 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 | ||
328 | void __init smp_prepare_cpus(unsigned int max_cpus) | 181 | void __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); | |||
28 | EXPORT_SYMBOL(__ret_efault); | 28 | EXPORT_SYMBOL(__ret_efault); |
29 | EXPORT_SYMBOL(empty_zero_page); | 29 | EXPORT_SYMBOL(empty_zero_page); |
30 | 30 | ||
31 | /* Defined using magic */ | ||
32 | #ifndef CONFIG_SMP | ||
33 | EXPORT_SYMBOL(BTFIXUP_CALL(___xchg32)); | ||
34 | #else | ||
35 | EXPORT_SYMBOL(BTFIXUP_CALL(__hard_smp_processor_id)); | ||
36 | #endif | ||
37 | EXPORT_SYMBOL(BTFIXUP_CALL(mmu_unlockarea)); | ||
38 | EXPORT_SYMBOL(BTFIXUP_CALL(mmu_lockarea)); | ||
39 | EXPORT_SYMBOL(BTFIXUP_CALL(mmu_get_scsi_sgl)); | ||
40 | EXPORT_SYMBOL(BTFIXUP_CALL(mmu_get_scsi_one)); | ||
41 | EXPORT_SYMBOL(BTFIXUP_CALL(mmu_release_scsi_sgl)); | ||
42 | EXPORT_SYMBOL(BTFIXUP_CALL(mmu_release_scsi_one)); | ||
43 | EXPORT_SYMBOL(BTFIXUP_CALL(pgprot_noncached)); | ||
44 | |||
45 | /* Exporting a symbol from /init/main.c */ | 31 | /* Exporting a symbol from /init/main.c */ |
46 | EXPORT_SYMBOL(saved_command_line); | 32 | EXPORT_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 | */ | ||
66 | unsigned char __iomem *interrupt_enable; | ||
67 | |||
68 | static 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 | |||
82 | static 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 | |||
96 | static 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 | |||
104 | static void sun4c_shutdown_irq(struct irq_data *data) | ||
105 | { | ||
106 | sun4c_mask_irq(data); | ||
107 | irq_unlink(data->irq); | ||
108 | } | ||
109 | |||
110 | static 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 | |||
118 | static 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 | |||
158 | struct sun4c_timer_info { | ||
159 | u32 l10_count; | ||
160 | u32 l10_limit; | ||
161 | u32 l14_count; | ||
162 | u32 l14_limit; | ||
163 | }; | ||
164 | |||
165 | static struct sun4c_timer_info __iomem *sun4c_timers; | ||
166 | |||
167 | static void sun4c_clear_clock_irq(void) | ||
168 | { | ||
169 | sbus_readl(&sun4c_timers->l10_limit); | ||
170 | } | ||
171 | |||
172 | static void sun4c_load_profile_irq(int cpu, unsigned int limit) | ||
173 | { | ||
174 | /* Errm.. not sure how to do this.. */ | ||
175 | } | ||
176 | |||
177 | static 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 | ||
226 | static void sun4c_nop(void) | ||
227 | { | ||
228 | } | ||
229 | #endif | ||
230 | |||
231 | void __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 |
246 | static void sun4d_set_cpu_int(int cpu, int level) | ||
247 | { | ||
248 | sun4d_send_ipi(cpu, level); | ||
249 | } | ||
250 | |||
251 | static void sun4d_clear_ipi(int cpu, int level) | ||
252 | { | ||
253 | } | ||
254 | |||
255 | static void sun4d_set_udt(int cpu) | ||
256 | { | ||
257 | } | ||
258 | |||
259 | /* Setup IRQ distribution scheme. */ | 247 | /* Setup IRQ distribution scheme. */ |
260 | void __init sun4d_distribute_irqs(void) | 248 | void __init sun4d_distribute_irqs(void) |
261 | { | 249 | { |
@@ -282,7 +270,8 @@ static void sun4d_clear_clock_irq(void) | |||
282 | 270 | ||
283 | static void sun4d_load_profile_irq(int cpu, unsigned int limit) | 271 | static 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 | ||
288 | static void __init sun4d_load_profile_irqs(void) | 277 | static 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 | ||
426 | static void __init sun4d_init_timers(irq_handler_t counter_fn) | 415 | static 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 | ||
36 | static void smp4d_ipi_init(void); | 40 | static void smp4d_ipi_init(void); |
37 | static void smp_setup_percpu_timer(void); | ||
38 | 41 | ||
39 | static unsigned char cpu_leds[32]; | 42 | static unsigned char cpu_leds[32]; |
40 | 43 | ||
@@ -49,7 +52,7 @@ static inline void show_leds(int cpuid) | |||
49 | 52 | ||
50 | void __cpuinit smp4d_callin(void) | 53 | void __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 | ||
130 | int __cpuinit smp4d_boot_one_cpu(int i) | 132 | int __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 | ||
236 | static 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 | |||
246 | static 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 | |||
251 | static 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 | ||
247 | static void smp4d_ipi_mask_one(int cpu) | 262 | static 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 | ||
258 | static void smp4d_ipi_resched(int cpu) | 273 | static 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 { | |||
280 | static DEFINE_SPINLOCK(cross_call_lock); | 295 | static 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. */ |
283 | static void smp4d_cross_call(smpfunc_t func, cpumask_t mask, unsigned long arg1, | 298 | static 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. */ |
353 | void smp4d_cross_call_irq(void) | 368 | void 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) | |||
363 | void smp4d_percpu_timer_interrupt(struct pt_regs *regs) | 378 | void 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 | ||
396 | static void __cpuinit smp_setup_percpu_timer(void) | 407 | static 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 | |||
404 | void __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 | |||
413 | void __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 | ||
422 | void __init sun4d_init_smp(void) | 414 | void __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 | ||
286 | static void sun4m_send_ipi(int cpu, int level) | ||
287 | { | ||
288 | sbus_writel(SUN4M_SOFT_INT(level), &sun4m_irq_percpu[cpu]->set); | ||
289 | } | ||
290 | |||
291 | static void sun4m_clear_ipi(int cpu, int level) | ||
292 | { | ||
293 | sbus_writel(SUN4M_SOFT_INT(level), &sun4m_irq_percpu[cpu]->clear); | ||
294 | } | ||
295 | |||
296 | static void sun4m_set_udt(int cpu) | ||
297 | { | ||
298 | sbus_writel(cpu, &sun4m_irq_global->interrupt_target); | ||
299 | } | ||
300 | #endif | ||
301 | |||
302 | struct sun4m_timer_percpu { | 282 | struct 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 | ||
319 | static struct sun4m_timer_global __iomem *timers_global; | 299 | static struct sun4m_timer_global __iomem *timers_global; |
320 | 300 | ||
321 | |||
322 | unsigned int lvl14_resolution = (((1000000/HZ) + 1) << 10); | ||
323 | |||
324 | static void sun4m_clear_clock_irq(void) | 301 | static 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 | ||
370 | static void sun4m_load_profile_irq(int cpu, unsigned int limit) | 347 | static 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 | ||
375 | static void __init sun4m_init_timers(irq_handler_t counter_fn) | 353 | static 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 | ||
33 | static void smp4m_ipi_init(void); | ||
34 | static void smp_setup_percpu_timer(void); | ||
35 | |||
36 | void __cpuinit smp4m_callin(void) | 37 | void __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 | */ |
87 | void __init smp4m_boot_cpus(void) | 87 | void __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 | ||
94 | int __cpuinit smp4m_boot_one_cpu(int i) | 93 | int __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 | 156 | static void sun4m_send_ipi(int cpu, int level) | |
158 | /* Initialize IPIs on the SUN4M SMP machine */ | ||
159 | static void __init smp4m_ipi_init(void) | ||
160 | { | 157 | { |
158 | sbus_writel(SUN4M_SOFT_INT(level), &sun4m_irq_percpu[cpu]->set); | ||
161 | } | 159 | } |
162 | 160 | ||
163 | static void smp4m_ipi_resched(int cpu) | 161 | static 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 | ||
168 | static void smp4m_ipi_single(int cpu) | 166 | static 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 | ||
173 | static void smp4m_ipi_mask_one(int cpu) | 171 | static 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 | ||
178 | static struct smp_funcall { | 176 | static struct smp_funcall { |
@@ -189,7 +187,7 @@ static struct smp_funcall { | |||
189 | static DEFINE_SPINLOCK(cross_call_lock); | 187 | static 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. */ |
192 | static void smp4m_cross_call(smpfunc_t func, cpumask_t mask, unsigned long arg1, | 190 | static 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) | |||
260 | void smp4m_percpu_timer_interrupt(struct pt_regs *regs) | 258 | void 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 | ||
283 | static void __cpuinit smp_setup_percpu_timer(void) | 280 | static 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 | |||
294 | static 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 | |||
304 | static 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 | ||
314 | void __init sun4m_init_smp(void) | 287 | void __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 | ||
100 | int sparc_mmap_check(unsigned long addr, unsigned long len) | 94 | int 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 | ||
52 | static __cacheline_aligned_in_smp DEFINE_SEQLOCK(timer_cs_lock); | ||
53 | static __volatile__ u64 timer_cs_internal_counter = 0; | ||
54 | static char timer_cs_enabled = 0; | ||
55 | |||
56 | static struct clock_event_device timer_ce; | ||
57 | static char timer_ce_enabled = 0; | ||
58 | |||
59 | #ifdef CONFIG_SMP | ||
60 | DEFINE_PER_CPU(struct clock_event_device, sparc32_clockevent); | ||
61 | #endif | ||
62 | |||
50 | DEFINE_SPINLOCK(rtc_lock); | 63 | DEFINE_SPINLOCK(rtc_lock); |
51 | EXPORT_SYMBOL(rtc_lock); | 64 | EXPORT_SYMBOL(rtc_lock); |
52 | 65 | ||
@@ -55,7 +68,6 @@ static int set_rtc_mmss(unsigned long); | |||
55 | unsigned long profile_pc(struct pt_regs *regs) | 68 | unsigned 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 | ||
78 | u32 (*do_arch_gettimeoffset)(void); | ||
79 | |||
80 | int update_persistent_clock(struct timespec now) | 88 | int 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 | /* | 93 | irqreturn_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 | ||
92 | static irqreturn_t timer_interrupt(int dummy, void *dev_id) | 107 | return IRQ_HANDLED; |
108 | } | ||
109 | |||
110 | static 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(); | 127 | static __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); | 144 | static 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 | |||
158 | static 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 | |||
177 | static 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 | |||
186 | static __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 | ||
196 | static 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 | |||
216 | static 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 | |||
226 | void 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 | |||
108 | static unsigned char mostek_read_byte(struct device *dev, u32 ofs) | 250 | static 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 | */ |
196 | fs_initcall(clock_init); | 338 | fs_initcall(clock_init); |
197 | 339 | ||
198 | 340 | static void __init sparc32_late_time_init(void) | |
199 | u32 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 | |||
212 | u32 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 | ||
219 | static void __init sbus_time_init(void) | 351 | static 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 | ||
228 | void __init time_init(void) | 357 | void __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 | ||
11 | trapbase: | ||
12 | |||
13 | #ifdef CONFIG_SMP | ||
14 | trapbase_cpu0: | ||
15 | #endif | ||
16 | /* We get control passed to us here at t_zero. */ | ||
17 | t_zero: b gokernel; nop; nop; nop; | ||
18 | t_tflt: SRMMU_TFAULT /* Inst. Access Exception */ | ||
19 | t_bins: TRAP_ENTRY(0x2, bad_instruction) /* Illegal Instruction */ | ||
20 | t_pins: TRAP_ENTRY(0x3, priv_instruction) /* Privileged Instruction */ | ||
21 | t_fpd: TRAP_ENTRY(0x4, fpd_trap_handler) /* Floating Point Disabled */ | ||
22 | t_wovf: WINDOW_SPILL /* Window Overflow */ | ||
23 | t_wunf: WINDOW_FILL /* Window Underflow */ | ||
24 | t_mna: TRAP_ENTRY(0x7, mna_handler) /* Memory Address Not Aligned */ | ||
25 | t_fpe: TRAP_ENTRY(0x8, fpe_trap_handler) /* Floating Point Exception */ | ||
26 | t_dflt: SRMMU_DFAULT /* Data Miss Exception */ | ||
27 | t_tio: TRAP_ENTRY(0xa, do_tag_overflow) /* Tagged Instruction Ovrflw */ | ||
28 | t_wpt: TRAP_ENTRY(0xb, do_watchpoint) /* Watchpoint Detected */ | ||
29 | t_badc: BAD_TRAP(0xc) BAD_TRAP(0xd) BAD_TRAP(0xe) BAD_TRAP(0xf) BAD_TRAP(0x10) | ||
30 | t_irq1: TRAP_ENTRY_INTERRUPT(1) /* IRQ Software/SBUS Level 1 */ | ||
31 | t_irq2: TRAP_ENTRY_INTERRUPT(2) /* IRQ SBUS Level 2 */ | ||
32 | t_irq3: TRAP_ENTRY_INTERRUPT(3) /* IRQ SCSI/DMA/SBUS Level 3 */ | ||
33 | t_irq4: TRAP_ENTRY_INTERRUPT(4) /* IRQ Software Level 4 */ | ||
34 | t_irq5: TRAP_ENTRY_INTERRUPT(5) /* IRQ SBUS/Ethernet Level 5 */ | ||
35 | t_irq6: TRAP_ENTRY_INTERRUPT(6) /* IRQ Software Level 6 */ | ||
36 | t_irq7: TRAP_ENTRY_INTERRUPT(7) /* IRQ Video/SBUS Level 5 */ | ||
37 | t_irq8: TRAP_ENTRY_INTERRUPT(8) /* IRQ SBUS Level 6 */ | ||
38 | t_irq9: TRAP_ENTRY_INTERRUPT(9) /* IRQ SBUS Level 7 */ | ||
39 | t_irq10:TRAP_ENTRY_INTERRUPT(10) /* IRQ Timer #1 (one we use) */ | ||
40 | t_irq11:TRAP_ENTRY_INTERRUPT(11) /* IRQ Floppy Intr. */ | ||
41 | t_irq12:TRAP_ENTRY_INTERRUPT(12) /* IRQ Zilog serial chip */ | ||
42 | t_irq13:TRAP_ENTRY_INTERRUPT(13) /* IRQ Audio Intr. */ | ||
43 | t_irq14:TRAP_ENTRY_INTERRUPT(14) /* IRQ Timer #2 */ | ||
44 | |||
45 | .globl t_nmi | ||
46 | t_nmi: TRAP_ENTRY(0x1f, linux_trap_ipi15_sun4m) | ||
47 | |||
48 | t_racc: TRAP_ENTRY(0x20, do_reg_access) /* General Register Access Error */ | ||
49 | t_iacce:BAD_TRAP(0x21) /* Instr Access Error */ | ||
50 | t_bad22:BAD_TRAP(0x22) | ||
51 | BAD_TRAP(0x23) | ||
52 | t_cpdis:TRAP_ENTRY(0x24, do_cp_disabled) /* Co-Processor Disabled */ | ||
53 | t_uflsh:SKIP_TRAP(0x25, unimp_flush) /* Unimplemented FLUSH inst. */ | ||
54 | t_bad26:BAD_TRAP(0x26) BAD_TRAP(0x27) | ||
55 | t_cpexc:TRAP_ENTRY(0x28, do_cp_exception) /* Co-Processor Exception */ | ||
56 | t_dacce:SRMMU_DFAULT /* Data Access Error */ | ||
57 | t_hwdz: TRAP_ENTRY(0x2a, do_hw_divzero) /* Division by zero, you lose... */ | ||
58 | t_dserr:BAD_TRAP(0x2b) /* Data Store Error */ | ||
59 | t_daccm:BAD_TRAP(0x2c) /* Data Access MMU-Miss */ | ||
60 | t_bad2d:BAD_TRAP(0x2d) BAD_TRAP(0x2e) BAD_TRAP(0x2f) BAD_TRAP(0x30) BAD_TRAP(0x31) | ||
61 | t_bad32:BAD_TRAP(0x32) BAD_TRAP(0x33) BAD_TRAP(0x34) BAD_TRAP(0x35) BAD_TRAP(0x36) | ||
62 | t_bad37:BAD_TRAP(0x37) BAD_TRAP(0x38) BAD_TRAP(0x39) BAD_TRAP(0x3a) BAD_TRAP(0x3b) | ||
63 | t_iaccm:BAD_TRAP(0x3c) /* Instr Access MMU-Miss */ | ||
64 | t_bad3d:BAD_TRAP(0x3d) BAD_TRAP(0x3e) BAD_TRAP(0x3f) BAD_TRAP(0x40) BAD_TRAP(0x41) | ||
65 | t_bad42:BAD_TRAP(0x42) BAD_TRAP(0x43) BAD_TRAP(0x44) BAD_TRAP(0x45) BAD_TRAP(0x46) | ||
66 | t_bad47:BAD_TRAP(0x47) BAD_TRAP(0x48) BAD_TRAP(0x49) BAD_TRAP(0x4a) BAD_TRAP(0x4b) | ||
67 | t_bad4c:BAD_TRAP(0x4c) BAD_TRAP(0x4d) BAD_TRAP(0x4e) BAD_TRAP(0x4f) BAD_TRAP(0x50) | ||
68 | t_bad51:BAD_TRAP(0x51) BAD_TRAP(0x52) BAD_TRAP(0x53) BAD_TRAP(0x54) BAD_TRAP(0x55) | ||
69 | t_bad56:BAD_TRAP(0x56) BAD_TRAP(0x57) BAD_TRAP(0x58) BAD_TRAP(0x59) BAD_TRAP(0x5a) | ||
70 | t_bad5b:BAD_TRAP(0x5b) BAD_TRAP(0x5c) BAD_TRAP(0x5d) BAD_TRAP(0x5e) BAD_TRAP(0x5f) | ||
71 | t_bad60:BAD_TRAP(0x60) BAD_TRAP(0x61) BAD_TRAP(0x62) BAD_TRAP(0x63) BAD_TRAP(0x64) | ||
72 | t_bad65:BAD_TRAP(0x65) BAD_TRAP(0x66) BAD_TRAP(0x67) BAD_TRAP(0x68) BAD_TRAP(0x69) | ||
73 | t_bad6a:BAD_TRAP(0x6a) BAD_TRAP(0x6b) BAD_TRAP(0x6c) BAD_TRAP(0x6d) BAD_TRAP(0x6e) | ||
74 | t_bad6f:BAD_TRAP(0x6f) BAD_TRAP(0x70) BAD_TRAP(0x71) BAD_TRAP(0x72) BAD_TRAP(0x73) | ||
75 | t_bad74:BAD_TRAP(0x74) BAD_TRAP(0x75) BAD_TRAP(0x76) BAD_TRAP(0x77) BAD_TRAP(0x78) | ||
76 | t_bad79:BAD_TRAP(0x79) BAD_TRAP(0x7a) BAD_TRAP(0x7b) BAD_TRAP(0x7c) BAD_TRAP(0x7d) | ||
77 | t_bad7e:BAD_TRAP(0x7e) BAD_TRAP(0x7f) | ||
78 | t_bad80:BAD_TRAP(0x80) /* SunOS System Call */ | ||
79 | t_sbkpt:BREAKPOINT_TRAP /* Software Breakpoint/KGDB */ | ||
80 | t_divz: TRAP_ENTRY(0x82, do_hw_divzero) /* Divide by zero trap */ | ||
81 | t_flwin:TRAP_ENTRY(0x83, do_flush_windows) /* Flush Windows Trap */ | ||
82 | t_clwin:BAD_TRAP(0x84) /* Clean Windows Trap */ | ||
83 | t_rchk: BAD_TRAP(0x85) /* Range Check */ | ||
84 | t_funal:BAD_TRAP(0x86) /* Fix Unaligned Access Trap */ | ||
85 | t_iovf: BAD_TRAP(0x87) /* Integer Overflow Trap */ | ||
86 | t_bad88:BAD_TRAP(0x88) /* Slowaris System Call */ | ||
87 | t_bad89:BAD_TRAP(0x89) /* Net-B.S. System Call */ | ||
88 | t_bad8a:BAD_TRAP(0x8a) BAD_TRAP(0x8b) BAD_TRAP(0x8c) BAD_TRAP(0x8d) BAD_TRAP(0x8e) | ||
89 | t_bad8f:BAD_TRAP(0x8f) | ||
90 | t_linux:LINUX_SYSCALL_TRAP /* Linux System Call */ | ||
91 | t_bad91:BAD_TRAP(0x91) BAD_TRAP(0x92) BAD_TRAP(0x93) BAD_TRAP(0x94) BAD_TRAP(0x95) | ||
92 | t_bad96:BAD_TRAP(0x96) BAD_TRAP(0x97) BAD_TRAP(0x98) BAD_TRAP(0x99) BAD_TRAP(0x9a) | ||
93 | t_bad9b:BAD_TRAP(0x9b) BAD_TRAP(0x9c) BAD_TRAP(0x9d) BAD_TRAP(0x9e) BAD_TRAP(0x9f) | ||
94 | t_getcc:GETCC_TRAP /* Get Condition Codes */ | ||
95 | t_setcc:SETCC_TRAP /* Set Condition Codes */ | ||
96 | t_getpsr:GETPSR_TRAP /* Get PSR Register */ | ||
97 | t_bada3:BAD_TRAP(0xa3) BAD_TRAP(0xa4) BAD_TRAP(0xa5) BAD_TRAP(0xa6) | ||
98 | t_bada7:BAD_TRAP(0xa7) | ||
99 | t_bada8:BAD_TRAP(0xa8) BAD_TRAP(0xa9) BAD_TRAP(0xaa) BAD_TRAP(0xab) | ||
100 | t_badac:BAD_TRAP(0xac) BAD_TRAP(0xad) BAD_TRAP(0xae) BAD_TRAP(0xaf) BAD_TRAP(0xb0) | ||
101 | t_badb1:BAD_TRAP(0xb1) BAD_TRAP(0xb2) BAD_TRAP(0xb3) BAD_TRAP(0xb4) BAD_TRAP(0xb5) | ||
102 | t_badb6:BAD_TRAP(0xb6) BAD_TRAP(0xb7) BAD_TRAP(0xb8) BAD_TRAP(0xb9) BAD_TRAP(0xba) | ||
103 | t_badbb:BAD_TRAP(0xbb) BAD_TRAP(0xbc) BAD_TRAP(0xbd) BAD_TRAP(0xbe) BAD_TRAP(0xbf) | ||
104 | t_badc0:BAD_TRAP(0xc0) BAD_TRAP(0xc1) BAD_TRAP(0xc2) BAD_TRAP(0xc3) BAD_TRAP(0xc4) | ||
105 | t_badc5:BAD_TRAP(0xc5) BAD_TRAP(0xc6) BAD_TRAP(0xc7) BAD_TRAP(0xc8) BAD_TRAP(0xc9) | ||
106 | t_badca:BAD_TRAP(0xca) BAD_TRAP(0xcb) BAD_TRAP(0xcc) BAD_TRAP(0xcd) BAD_TRAP(0xce) | ||
107 | t_badcf:BAD_TRAP(0xcf) BAD_TRAP(0xd0) BAD_TRAP(0xd1) BAD_TRAP(0xd2) BAD_TRAP(0xd3) | ||
108 | t_badd4:BAD_TRAP(0xd4) BAD_TRAP(0xd5) BAD_TRAP(0xd6) BAD_TRAP(0xd7) BAD_TRAP(0xd8) | ||
109 | t_badd9:BAD_TRAP(0xd9) BAD_TRAP(0xda) BAD_TRAP(0xdb) BAD_TRAP(0xdc) BAD_TRAP(0xdd) | ||
110 | t_badde:BAD_TRAP(0xde) BAD_TRAP(0xdf) BAD_TRAP(0xe0) BAD_TRAP(0xe1) BAD_TRAP(0xe2) | ||
111 | t_bade3:BAD_TRAP(0xe3) BAD_TRAP(0xe4) BAD_TRAP(0xe5) BAD_TRAP(0xe6) BAD_TRAP(0xe7) | ||
112 | t_bade8:BAD_TRAP(0xe8) BAD_TRAP(0xe9) BAD_TRAP(0xea) BAD_TRAP(0xeb) BAD_TRAP(0xec) | ||
113 | t_baded:BAD_TRAP(0xed) BAD_TRAP(0xee) BAD_TRAP(0xef) BAD_TRAP(0xf0) BAD_TRAP(0xf1) | ||
114 | t_badf2:BAD_TRAP(0xf2) BAD_TRAP(0xf3) BAD_TRAP(0xf4) BAD_TRAP(0xf5) BAD_TRAP(0xf6) | ||
115 | t_badf7:BAD_TRAP(0xf7) BAD_TRAP(0xf8) BAD_TRAP(0xf9) BAD_TRAP(0xfa) BAD_TRAP(0xfb) | ||
116 | t_badfc:BAD_TRAP(0xfc) | ||
117 | t_kgdb: KGDB_TRAP(0xfd) | ||
118 | dbtrap: BAD_TRAP(0xfe) /* Debugger/PROM breakpoint #1 */ | ||
119 | dbtrap2:BAD_TRAP(0xff) /* Debugger/PROM breakpoint #2 */ | ||
120 | |||
121 | .globl end_traptable | ||
122 | end_traptable: | ||
123 | |||
124 | #ifdef CONFIG_SMP | ||
125 | /* Trap tables for the other cpus. */ | ||
126 | .globl trapbase_cpu1, trapbase_cpu2, trapbase_cpu3 | ||
127 | trapbase_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 | |||
219 | trapbase_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 | |||
319 | trapbase_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 |
167 | spwin_mmu_patchme: b spwin_sun4c_stackchk | 167 | andcc %sp, 0x7, %g0 |
168 | andcc %sp, 0x7, %g0 | ||
169 | 168 | ||
170 | spwin_good_ustack: | 169 | spwin_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 | ||
309 | spwin_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 | |||
322 | 1: | ||
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 | */ | ||
335 | 1: | ||
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 | |||
341 | spwin_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 | |||
352 | 1: | ||
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 | |||
363 | 1: | ||
364 | lda [%glob_tmp] ASI_PTE, %glob_tmp | ||
365 | |||
366 | spwin_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 | ||
138 | fwin_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 | ||
246 | sun4c_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 */ | ||
256 | 1: | ||
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 | |||
266 | 1: | ||
267 | be sun4c_fwin_onepage /* Only one page to check */ | ||
268 | lda [%sp] ASI_PTE, %l1 | ||
269 | sun4c_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 | |||
279 | 1: | ||
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 | |||
287 | sun4c_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 |
297 | srmmu_fwin_stackchk: | 243 | srmmu_fwin_stackchk: |
298 | /* LOCATION: Window 'W' */ | 244 | /* LOCATION: Window 'W' */ |