aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-05-21 13:32:01 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2012-05-21 13:32:01 -0400
commit9daeaa370526df1c19eba4780247bb7155541e38 (patch)
tree5ae2601c26e280e81d753c1fe65453a3b8b1d2a0
parentcb62ab71fe2b16e8203a0f0a2ef4eda23d761338 (diff)
parent1edc17832d8f49a0263d364c453ea35da0e4e2a6 (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc-next
Pull sparc updates from David Miller: 1) Kill off support for sun4c and Cypress sun4m chips. And as a result we were able to also kill off that ugly btfixup thing that required multi-stage links of the final vmlinux image in the Kbuild system. This should make the kbuild maintainers really happy. Thanks a lot to Sam Ravnborg for his tireless efforts to get this going. 2) Convert sparc64 to nobootmem. I suspect now with sparc32 being a lot cleaner, it should be able to fall in line and modernize in this area too. 3) Make sparc32 use generic clockevents, from Tkhai Kirill. [ I fixed up the BPF rules, and tried to clean up the build rules too. But I don't have - or want - a sparc cross-build environment, so the BPF rule bug and the related build cleanup was all done with just a bare "make -n" pseudo-test. - Linus ] * git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc-next: (110 commits) sparc32: use flushi when run-time patching in per_cpu_patch sparc32: fix cpuid_patch run-time patching sparc32: drop unused inline functions in srmmu.c sparc32: drop unused functions in pgtsrmmu.h sparc32,leon: move leon mmu functions to leon_mm.c sparc32,leon: remove duplicate definitions in leon.h sparc32,leon: remove duplicate UART register definitions sparc32,leon: move leon ASI definitions to asi.h sparc32: move trap table to a separate file sparc64: renamed ttable.S to ttable_64.S sparc32: Remove asm/sysen.h header. sparc32: Delete asm/smpprim.h sparc32: Remove unused empty_bad_page{,_table} declarations. sparc32: Kill boot_cpu_id4 sparc32: Move GET_PROCESSOR*_ID() out of asm/asmmacro.h sparc32: Remove completely unused code from asm/cache.h sparc32: Add ucmpdi2.o to obj-y instead of lib-y. sparc32: add ucmpdi2 sparc: introduce arch/sparc/Kbuild sparc: remove obsolete documentation ...
-rw-r--r--Documentation/sparc/README-2.546
-rw-r--r--arch/sparc/Kbuild8
-rw-r--r--arch/sparc/Kconfig12
-rw-r--r--arch/sparc/Makefile48
-rw-r--r--arch/sparc/boot/Makefile61
-rw-r--r--arch/sparc/boot/btfixupprep.c386
-rw-r--r--arch/sparc/include/asm/asi.h14
-rw-r--r--arch/sparc/include/asm/asmmacro.h17
-rw-r--r--arch/sparc/include/asm/btfixup.h208
-rw-r--r--arch/sparc/include/asm/cache.h114
-rw-r--r--arch/sparc/include/asm/cacheflush.h4
-rw-r--r--arch/sparc/include/asm/cacheflush_32.h73
-rw-r--r--arch/sparc/include/asm/cacheflush_64.h3
-rw-r--r--arch/sparc/include/asm/cachetlb_32.h29
-rw-r--r--arch/sparc/include/asm/cmpxchg_32.h27
-rw-r--r--arch/sparc/include/asm/contregs.h22
-rw-r--r--arch/sparc/include/asm/cpu_type.h20
-rw-r--r--arch/sparc/include/asm/cpudata_32.h1
-rw-r--r--arch/sparc/include/asm/cypress.h79
-rw-r--r--arch/sparc/include/asm/dma.h52
-rw-r--r--arch/sparc/include/asm/elf_32.h13
-rw-r--r--arch/sparc/include/asm/floppy_32.h45
-rw-r--r--arch/sparc/include/asm/floppy_64.h6
-rw-r--r--arch/sparc/include/asm/head_32.h21
-rw-r--r--arch/sparc/include/asm/leon.h61
-rw-r--r--arch/sparc/include/asm/machines.h23
-rw-r--r--arch/sparc/include/asm/mbus.h4
-rw-r--r--arch/sparc/include/asm/memreg.h51
-rw-r--r--arch/sparc/include/asm/mmu_context_32.h11
-rw-r--r--arch/sparc/include/asm/obio.h13
-rw-r--r--arch/sparc/include/asm/oplib_32.h8
-rw-r--r--arch/sparc/include/asm/page_32.h13
-rw-r--r--arch/sparc/include/asm/pgalloc_32.h76
-rw-r--r--arch/sparc/include/asm/pgtable_32.h387
-rw-r--r--arch/sparc/include/asm/pgtable_64.h4
-rw-r--r--arch/sparc/include/asm/pgtsrmmu.h50
-rw-r--r--arch/sparc/include/asm/pgtsun4c.h172
-rw-r--r--arch/sparc/include/asm/processor_32.h1
-rw-r--r--arch/sparc/include/asm/setup.h3
-rw-r--r--arch/sparc/include/asm/shmparam_32.h4
-rw-r--r--arch/sparc/include/asm/smp_32.h114
-rw-r--r--arch/sparc/include/asm/smpprim.h54
-rw-r--r--arch/sparc/include/asm/string_32.h63
-rw-r--r--arch/sparc/include/asm/sysen.h15
-rw-r--r--arch/sparc/include/asm/thread_info_32.h8
-rw-r--r--arch/sparc/include/asm/timer_32.h33
-rw-r--r--arch/sparc/include/asm/timex_32.h1
-rw-r--r--arch/sparc/include/asm/tlbflush_32.h56
-rw-r--r--arch/sparc/include/asm/uaccess_32.h1
-rw-r--r--arch/sparc/include/asm/vac-ops.h127
-rw-r--r--arch/sparc/include/asm/vaddrs.h16
-rw-r--r--arch/sparc/include/asm/winmacro.h49
-rw-r--r--arch/sparc/kernel/Makefile3
-rw-r--r--arch/sparc/kernel/auxio_32.c13
-rw-r--r--arch/sparc/kernel/devices.c4
-rw-r--r--arch/sparc/kernel/ds.c2
-rw-r--r--arch/sparc/kernel/entry.S432
-rw-r--r--arch/sparc/kernel/etrap_32.S50
-rw-r--r--arch/sparc/kernel/head_32.S639
-rw-r--r--arch/sparc/kernel/head_64.S2
-rw-r--r--arch/sparc/kernel/idprom.c19
-rw-r--r--arch/sparc/kernel/ioport.c23
-rw-r--r--arch/sparc/kernel/irq.h60
-rw-r--r--arch/sparc/kernel/irq_32.c19
-rw-r--r--arch/sparc/kernel/irq_64.c2
-rw-r--r--arch/sparc/kernel/kernel.h10
-rw-r--r--arch/sparc/kernel/leon_kernel.c98
-rw-r--r--arch/sparc/kernel/leon_smp.c113
-rw-r--r--arch/sparc/kernel/module.c21
-rw-r--r--arch/sparc/kernel/muldiv.c238
-rw-r--r--arch/sparc/kernel/of_device_32.c4
-rw-r--r--arch/sparc/kernel/pcic.c55
-rw-r--r--arch/sparc/kernel/process_32.c116
-rw-r--r--arch/sparc/kernel/rtrap_32.S76
-rw-r--r--arch/sparc/kernel/rtrap_64.S12
-rw-r--r--arch/sparc/kernel/setup_32.c70
-rw-r--r--arch/sparc/kernel/signal_32.c7
-rw-r--r--arch/sparc/kernel/smp_32.c175
-rw-r--r--arch/sparc/kernel/sparc_ksyms_32.c14
-rw-r--r--arch/sparc/kernel/sun4c_irq.c264
-rw-r--r--arch/sparc/kernel/sun4d_irq.c48
-rw-r--r--arch/sparc/kernel/sun4d_smp.c119
-rw-r--r--arch/sparc/kernel/sun4m_irq.c58
-rw-r--r--arch/sparc/kernel/sun4m_smp.c117
-rw-r--r--arch/sparc/kernel/sys_sparc_32.c11
-rw-r--r--arch/sparc/kernel/time_32.c220
-rw-r--r--arch/sparc/kernel/trampoline_32.S22
-rw-r--r--arch/sparc/kernel/traps_32.c2
-rw-r--r--arch/sparc/kernel/ttable_32.S417
-rw-r--r--arch/sparc/kernel/ttable_64.S (renamed from arch/sparc/kernel/ttable.S)0
-rw-r--r--arch/sparc/kernel/unaligned_64.c1
-rw-r--r--arch/sparc/kernel/wof.S72
-rw-r--r--arch/sparc/kernel/wuf.S60
-rw-r--r--arch/sparc/lib/Makefile6
-rw-r--r--arch/sparc/lib/ashldi3.S7
-rw-r--r--arch/sparc/lib/ashrdi3.S7
-rw-r--r--arch/sparc/lib/atomic_32.S44
-rw-r--r--arch/sparc/lib/atomic_64.S49
-rw-r--r--arch/sparc/lib/bitops.S37
-rw-r--r--arch/sparc/lib/blockops.S10
-rw-r--r--arch/sparc/lib/bzero.S20
-rw-r--r--arch/sparc/lib/divdi3.S4
-rw-r--r--arch/sparc/lib/ipcsum.S9
-rw-r--r--arch/sparc/lib/ksyms.c22
-rw-r--r--arch/sparc/lib/lshrdi3.S5
-rw-r--r--arch/sparc/lib/memmove.S9
-rw-r--r--arch/sparc/lib/mul.S137
-rw-r--r--arch/sparc/lib/muldi3.S4
-rw-r--r--arch/sparc/lib/rem.S384
-rw-r--r--arch/sparc/lib/sdiv.S381
-rw-r--r--arch/sparc/lib/strlen_user_64.S8
-rw-r--r--arch/sparc/lib/strncmp_32.S8
-rw-r--r--arch/sparc/lib/strncmp_64.S8
-rw-r--r--arch/sparc/lib/strncpy_from_user_32.S6
-rw-r--r--arch/sparc/lib/strncpy_from_user_64.S8
-rw-r--r--arch/sparc/lib/ucmpdi2.c19
-rw-r--r--arch/sparc/lib/udiv.S357
-rw-r--r--arch/sparc/lib/udivdi3.S3
-rw-r--r--arch/sparc/lib/umul.S171
-rw-r--r--arch/sparc/lib/urem.S357
-rw-r--r--arch/sparc/lib/xor.S50
-rw-r--r--arch/sparc/mm/Makefile9
-rw-r--r--arch/sparc/mm/btfixup.c328
-rw-r--r--arch/sparc/mm/fault_32.c207
-rw-r--r--arch/sparc/mm/init_32.c51
-rw-r--r--arch/sparc/mm/init_64.c121
-rw-r--r--arch/sparc/mm/io-unit.c35
-rw-r--r--arch/sparc/mm/iommu.c71
-rw-r--r--arch/sparc/mm/leon_mm.c95
-rw-r--r--arch/sparc/mm/loadmmu.c43
-rw-r--r--arch/sparc/mm/nosun4c.c77
-rw-r--r--arch/sparc/mm/srmmu.c1232
-rw-r--r--arch/sparc/mm/srmmu.h4
-rw-r--r--arch/sparc/mm/sun4c.c2166
-rw-r--r--arch/sparc/mm/viking.S1
-rw-r--r--arch/sparc/prom/Makefile1
-rw-r--r--arch/sparc/prom/segment.c28
137 files changed, 2242 insertions, 10772 deletions
diff --git a/Documentation/sparc/README-2.5 b/Documentation/sparc/README-2.5
deleted file mode 100644
index 806fe490a56d..000000000000
--- a/Documentation/sparc/README-2.5
+++ /dev/null
@@ -1,46 +0,0 @@
1BTFIXUP
2-------
3
4To build new kernels you have to issue "make image". The ready kernel
5in ELF format is placed in arch/sparc/boot/image. Explanation is below.
6
7BTFIXUP is a unique feature of Linux/sparc among other architectures,
8developed by Jakub Jelinek (I think... Obviously David S. Miller took
9part, too). It allows to boot the same kernel at different
10sub-architectures, such as sun4c, sun4m, sun4d, where SunOS uses
11different kernels. This feature is convinient for people who you move
12disks between boxes and for distrution builders.
13
14To function, BTFIXUP must link the kernel "in the draft" first,
15analyze the result, write a special stub code based on that, and
16build the final kernel with the stub (btfix.o).
17
18Kai Germaschewski improved the build system of the kernel in the 2.5 series
19significantly. Unfortunately, the traditional way of running the draft
20linking from architecture specific Makefile before the actual linking
21by generic Makefile is nearly impossible to support properly in the
22new build system. Therefore, the way we integrate BTFIXUP with the
23build system was changed in 2.5.40. Now, generic Makefile performs
24the draft linking and stores the result in file vmlinux. Architecture
25specific post-processing invokes BTFIXUP machinery and final linking
26in the same way as other architectures do bootstraps.
27
28Implications of that change are as follows.
29
301. Hackers must type "make image" now, instead of just "make", in the same
31 way as s390 people do now. It is analogous to "make bzImage" on i386.
32 This does NOT affect sparc64, you continue to use "make" to build sparc64
33 kernels.
34
352. vmlinux is not the final kernel, so RPM builders have to adjust
36 their spec files (if they delivered vmlinux for debugging).
37 System.map generated for vmlinux is still valid.
38
393. Scripts that produce a.out images have to be changed. First, if they
40 invoke make, they have to use "make image". Second, they have to pick up
41 the new kernel in arch/sparc/boot/image instead of vmlinux.
42
434. Since we are compliant with Kai's build system now, make -j is permitted.
44
45-- Pete Zaitcev
46zaitcev@yahoo.com
diff --git a/arch/sparc/Kbuild b/arch/sparc/Kbuild
new file mode 100644
index 000000000000..5cd01161fd00
--- /dev/null
+++ b/arch/sparc/Kbuild
@@ -0,0 +1,8 @@
1#
2# core part of the sparc kernel
3#
4
5obj-y += kernel/
6obj-y += mm/
7obj-y += math-emu/
8obj-y += net/
diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig
index 5f6acce45a0d..6c49ed2ee786 100644
--- a/arch/sparc/Kconfig
+++ b/arch/sparc/Kconfig
@@ -30,7 +30,7 @@ config SPARC
30 select USE_GENERIC_SMP_HELPERS if SMP 30 select USE_GENERIC_SMP_HELPERS if SMP
31 select GENERIC_PCI_IOMAP 31 select GENERIC_PCI_IOMAP
32 select HAVE_NMI_WATCHDOG if SPARC64 32 select HAVE_NMI_WATCHDOG if SPARC64
33 select HAVE_BPF_JIT 33 select HAVE_BPF_JIT if NET
34 34
35config SPARC32 35config SPARC32
36 def_bool !64BIT 36 def_bool !64BIT
@@ -62,6 +62,7 @@ config SPARC64
62 select IRQ_PREFLOW_FASTEOI 62 select IRQ_PREFLOW_FASTEOI
63 select ARCH_HAVE_NMI_SAFE_CMPXCHG 63 select ARCH_HAVE_NMI_SAFE_CMPXCHG
64 select HAVE_C_RECORDMCOUNT 64 select HAVE_C_RECORDMCOUNT
65 select NO_BOOTMEM
65 66
66config ARCH_DEFCONFIG 67config ARCH_DEFCONFIG
67 string 68 string
@@ -74,17 +75,12 @@ config BITS
74 default 32 if SPARC32 75 default 32 if SPARC32
75 default 64 if SPARC64 76 default 64 if SPARC64
76 77
77config ARCH_USES_GETTIMEOFFSET
78 bool
79 default y if SPARC32
80
81config GENERIC_CMOS_UPDATE 78config GENERIC_CMOS_UPDATE
82 bool 79 bool
83 default y 80 default y
84 81
85config GENERIC_CLOCKEVENTS 82config GENERIC_CLOCKEVENTS
86 bool 83 def_bool y
87 default y if SPARC64
88 84
89config IOMMU_HELPER 85config IOMMU_HELPER
90 bool 86 bool
@@ -155,7 +151,7 @@ source "kernel/Kconfig.freezer"
155menu "Processor type and features" 151menu "Processor type and features"
156 152
157config SMP 153config SMP
158 bool "Symmetric multi-processing support (does not work on sun4/sun4c)" 154 bool "Symmetric multi-processing support"
159 ---help--- 155 ---help---
160 This enables support for systems with more than one CPU. If you have 156 This enables support for systems with more than one CPU. If you have
161 a system with only one CPU, say N. If you have a system with more 157 a system with only one CPU, say N. If you have a system with more
diff --git a/arch/sparc/Makefile b/arch/sparc/Makefile
index 0e5de13b56c5..b9a72e2b8acc 100644
--- a/arch/sparc/Makefile
+++ b/arch/sparc/Makefile
@@ -19,39 +19,27 @@ ifeq ($(CONFIG_SPARC32),y)
19# sparc32 19# sparc32
20# 20#
21 21
22#
23# Uncomment the first KBUILD_CFLAGS if you are doing kgdb source level
24# debugging of the kernel to get the proper debugging information.
25
26AS := $(AS) -32
27LDFLAGS := -m elf32_sparc
28CHECKFLAGS += -D__sparc__ 22CHECKFLAGS += -D__sparc__
23LDFLAGS := -m elf32_sparc
29export BITS := 32 24export BITS := 32
30UTS_MACHINE := sparc 25UTS_MACHINE := sparc
31 26
32#KBUILD_CFLAGS += -g -pipe -fcall-used-g5 -fcall-used-g7 27KBUILD_CFLAGS += -m32 -mcpu=v8 -pipe -mno-fpu -fcall-used-g5 -fcall-used-g7
33KBUILD_CFLAGS += -m32 -pipe -mno-fpu -fcall-used-g5 -fcall-used-g7 28KBUILD_AFLAGS += -m32 -Wa,-Av8
34KBUILD_AFLAGS += -m32 -Wa,-Av8
35
36#LDFLAGS_vmlinux = -N -Ttext 0xf0004000
37# Since 2.5.40, the first stage is left not btfix-ed.
38# Actual linking is done with "make image".
39LDFLAGS_vmlinux = -r
40 29
41else 30else
42##### 31#####
43# sparc64 32# sparc64
44# 33#
45 34
46CHECKFLAGS += -D__sparc__ -D__sparc_v9__ -D__arch64__ -m64 35CHECKFLAGS += -D__sparc__ -D__sparc_v9__ -D__arch64__ -m64
36LDFLAGS := -m elf64_sparc
37export BITS := 64
38UTS_MACHINE := sparc64
47 39
48LDFLAGS := -m elf64_sparc 40KBUILD_CFLAGS += -m64 -pipe -mno-fpu -mcpu=ultrasparc -mcmodel=medlow
49export BITS := 64 41KBUILD_CFLAGS += -ffixed-g4 -ffixed-g5 -fcall-used-g7 -Wno-sign-compare
50UTS_MACHINE := sparc64 42KBUILD_CFLAGS += -Wa,--undeclared-regs
51
52KBUILD_CFLAGS += -m64 -pipe -mno-fpu -mcpu=ultrasparc -mcmodel=medlow \
53 -ffixed-g4 -ffixed-g5 -fcall-used-g7 -Wno-sign-compare \
54 -Wa,--undeclared-regs
55KBUILD_CFLAGS += $(call cc-option,-mtune=ultrasparc3) 43KBUILD_CFLAGS += $(call cc-option,-mtune=ultrasparc3)
56KBUILD_AFLAGS += -m64 -mcpu=ultrasparc -Wa,--undeclared-regs 44KBUILD_AFLAGS += -m64 -mcpu=ultrasparc -Wa,--undeclared-regs
57 45
@@ -64,26 +52,14 @@ endif
64head-y := arch/sparc/kernel/head_$(BITS).o 52head-y := arch/sparc/kernel/head_$(BITS).o
65head-y += arch/sparc/kernel/init_task.o 53head-y += arch/sparc/kernel/init_task.o
66 54
67core-y += arch/sparc/kernel/ 55# See arch/sparc/Kbuild for the core part of the kernel
68core-y += arch/sparc/mm/ arch/sparc/math-emu/ 56core-y += arch/sparc/
69core-y += arch/sparc/net/
70 57
71libs-y += arch/sparc/prom/ 58libs-y += arch/sparc/prom/
72libs-y += arch/sparc/lib/ 59libs-y += arch/sparc/lib/
73 60
74drivers-$(CONFIG_OPROFILE) += arch/sparc/oprofile/ 61drivers-$(CONFIG_OPROFILE) += arch/sparc/oprofile/
75 62
76# Export what is needed by arch/sparc/boot/Makefile
77export VMLINUX_INIT VMLINUX_MAIN
78VMLINUX_INIT := $(head-y) $(init-y)
79VMLINUX_MAIN := $(core-y) kernel/ mm/ fs/ ipc/ security/ crypto/ block/
80VMLINUX_MAIN += $(patsubst %/, %/lib.a, $(libs-y)) $(libs-y)
81VMLINUX_MAIN += $(drivers-y) $(net-y)
82
83ifdef CONFIG_KALLSYMS
84export kallsyms.o := .tmp_kallsyms2.o
85endif
86
87boot := arch/sparc/boot 63boot := arch/sparc/boot
88 64
89# Default target 65# Default target
diff --git a/arch/sparc/boot/Makefile b/arch/sparc/boot/Makefile
index d56d199c1aa8..6e63afb128d9 100644
--- a/arch/sparc/boot/Makefile
+++ b/arch/sparc/boot/Makefile
@@ -6,8 +6,8 @@
6ROOT_IMG := /usr/src/root.img 6ROOT_IMG := /usr/src/root.img
7ELFTOAOUT := elftoaout 7ELFTOAOUT := elftoaout
8 8
9hostprogs-y := piggyback btfixupprep 9hostprogs-y := piggyback
10targets := tftpboot.img btfix.o btfix.S image zImage vmlinux.aout 10targets := tftpboot.img image zImage vmlinux.aout
11clean-files := System.map 11clean-files := System.map
12 12
13quiet_cmd_elftoaout = ELFTOAOUT $@ 13quiet_cmd_elftoaout = ELFTOAOUT $@
@@ -17,58 +17,9 @@ quiet_cmd_piggy = PIGGY $@
17quiet_cmd_strip = STRIP $@ 17quiet_cmd_strip = STRIP $@
18 cmd_strip = $(STRIP) -R .comment -R .note -K sun4u_init -K _end -K _start $< -o $@ 18 cmd_strip = $(STRIP) -R .comment -R .note -K sun4u_init -K _end -K _start $< -o $@
19 19
20ifeq ($(CONFIG_SPARC32),y)
21quiet_cmd_btfix = BTFIX $@
22 cmd_btfix = $(OBJDUMP) -x vmlinux | $(obj)/btfixupprep > $@
23quiet_cmd_sysmap = SYSMAP $(obj)/System.map
24 cmd_sysmap = $(CONFIG_SHELL) $(srctree)/scripts/mksysmap
25quiet_cmd_image = LD $@
26 cmd_image = $(LD) $(LDFLAGS) $(EXTRA_LDFLAGS) $(LDFLAGS_$(@F)) -o $@
27
28define rule_image
29 $(if $($(quiet)cmd_image), \
30 echo ' $($(quiet)cmd_image)' &&) \
31 $(cmd_image); \
32 $(if $($(quiet)cmd_sysmap), \
33 echo ' $($(quiet)cmd_sysmap)' &&) \
34 $(cmd_sysmap) $@ $(obj)/System.map; \
35 if [ $$? -ne 0 ]; then \
36 rm -f $@; \
37 /bin/false; \
38 fi; \
39 echo 'cmd_$@ := $(cmd_image)' > $(@D)/.$(@F).cmd
40endef
41
42BTOBJS := $(patsubst %/, %/built-in.o, $(VMLINUX_INIT))
43BTLIBS := $(patsubst %/, %/built-in.o, $(VMLINUX_MAIN))
44LDFLAGS_image := -T arch/sparc/kernel/vmlinux.lds $(BTOBJS) \
45 --start-group $(BTLIBS) --end-group \
46 $(kallsyms.o) $(obj)/btfix.o
47
48# Link the final image including btfixup'ed symbols.
49# This is a replacement for the link done in the top-level Makefile.
50# Note: No dependency on the prerequisite files since that would require
51# make to try check if they are updated - and due to changes
52# in gcc options (path for example) this would result in
53# these files being recompiled for each build.
54$(obj)/image: $(obj)/btfix.o FORCE
55 $(call if_changed_rule,image)
56
57$(obj)/zImage: $(obj)/image
58 $(call if_changed,strip)
59 @echo ' kernel: $@ is ready'
60
61$(obj)/btfix.S: $(obj)/btfixupprep vmlinux FORCE
62 $(call if_changed,btfix)
63
64endif
65
66ifeq ($(CONFIG_SPARC64),y) 20ifeq ($(CONFIG_SPARC64),y)
67 21
68# Actual linking 22# Actual linking
69$(obj)/image: vmlinux FORCE
70 $(call if_changed,strip)
71 @echo ' kernel: $@ is ready'
72 23
73$(obj)/zImage: $(obj)/image 24$(obj)/zImage: $(obj)/image
74 $(call if_changed,gzip) 25 $(call if_changed,gzip)
@@ -79,6 +30,10 @@ $(obj)/vmlinux.aout: vmlinux FORCE
79 @echo ' kernel: $@ is ready' 30 @echo ' kernel: $@ is ready'
80else 31else
81 32
33$(obj)/zImage: $(obj)/image
34 $(call if_changed,strip)
35 @echo ' kernel: $@ is ready'
36
82# The following lines make a readable image for U-Boot. 37# The following lines make a readable image for U-Boot.
83# uImage - Binary file read by U-boot 38# uImage - Binary file read by U-boot
84# uImage.o - object file of uImage for loading with a 39# uImage.o - object file of uImage for loading with a
@@ -107,6 +62,10 @@ $(obj)/uImage: $(obj)/image.gz
107 62
108endif 63endif
109 64
65$(obj)/image: vmlinux FORCE
66 $(call if_changed,strip)
67 @echo ' kernel: $@ is ready'
68
110$(obj)/tftpboot.img: $(obj)/image $(obj)/piggyback System.map $(ROOT_IMG) FORCE 69$(obj)/tftpboot.img: $(obj)/image $(obj)/piggyback System.map $(ROOT_IMG) FORCE
111 $(call if_changed,elftoaout) 70 $(call if_changed,elftoaout)
112 $(call if_changed,piggy) 71 $(call if_changed,piggy)
diff --git a/arch/sparc/boot/btfixupprep.c b/arch/sparc/boot/btfixupprep.c
deleted file mode 100644
index da031159e2b7..000000000000
--- a/arch/sparc/boot/btfixupprep.c
+++ /dev/null
@@ -1,386 +0,0 @@
1/*
2 Simple utility to prepare vmlinux image for sparc.
3 Resolves all BTFIXUP uses and settings and creates
4 a special .s object to link to the image.
5
6 Copyright (C) 1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
21
22#include <stdio.h>
23#include <string.h>
24#include <ctype.h>
25#include <errno.h>
26#include <unistd.h>
27#include <stdlib.h>
28#include <malloc.h>
29
30#define MAXSYMS 1024
31
32static char *symtab = "SYMBOL TABLE:";
33static char *relrec = "RELOCATION RECORDS FOR [";
34static int rellen;
35static int symlen;
36int mode;
37
38struct _btfixup;
39
40typedef struct _btfixuprel {
41 char *sect;
42 unsigned long offset;
43 struct _btfixup *f;
44 int frel;
45 struct _btfixuprel *next;
46} btfixuprel;
47
48typedef struct _btfixup {
49 int type;
50 int setinitval;
51 unsigned int initval;
52 char *initvalstr;
53 char *name;
54 btfixuprel *rel;
55} btfixup;
56
57btfixup array[MAXSYMS];
58int last = 0;
59char buffer[1024];
60unsigned long lastfoffset = -1;
61unsigned long lastfrelno;
62btfixup *lastf;
63
64static void fatal(void) __attribute__((noreturn));
65static void fatal(void)
66{
67 fprintf(stderr, "Malformed output from objdump\n%s\n", buffer);
68 exit(1);
69}
70
71static btfixup *find(int type, char *name)
72{
73 int i;
74 for (i = 0; i < last; i++) {
75 if (array[i].type == type && !strcmp(array[i].name, name))
76 return array + i;
77 }
78 array[last].type = type;
79 array[last].name = strdup(name);
80 array[last].setinitval = 0;
81 if (!array[last].name) fatal();
82 array[last].rel = NULL;
83 last++;
84 if (last >= MAXSYMS) {
85 fprintf(stderr, "Ugh. Something strange. More than %d different BTFIXUP symbols\n", MAXSYMS);
86 exit(1);
87 }
88 return array + last - 1;
89}
90
91static void set_mode (char *buffer)
92{
93 for (mode = 0;; mode++)
94 if (buffer[mode] < '0' || buffer[mode] > '9')
95 break;
96 if (mode != 8 && mode != 16)
97 fatal();
98}
99
100
101int main(int argc,char **argv)
102{
103 char *p, *q;
104 char *sect;
105 int i, j, k;
106 unsigned int initval;
107 int shift;
108 btfixup *f;
109 btfixuprel *r, **rr;
110 unsigned long offset;
111 char *initvalstr;
112
113 symlen = strlen(symtab);
114 while (fgets (buffer, 1024, stdin) != NULL)
115 if (!strncmp (buffer, symtab, symlen))
116 goto main0;
117 fatal();
118main0:
119 rellen = strlen(relrec);
120 while (fgets (buffer, 1024, stdin) != NULL)
121 if (!strncmp (buffer, relrec, rellen))
122 goto main1;
123 fatal();
124main1:
125 sect = malloc(strlen (buffer + rellen) + 1);
126 if (!sect) fatal();
127 strcpy (sect, buffer + rellen);
128 p = strchr (sect, ']');
129 if (!p) fatal();
130 *p = 0;
131 if (fgets (buffer, 1024, stdin) == NULL)
132 fatal();
133 while (fgets (buffer, 1024, stdin) != NULL) {
134 int nbase;
135 if (!strncmp (buffer, relrec, rellen))
136 goto main1;
137 if (mode == 0)
138 set_mode (buffer);
139 p = strchr (buffer, '\n');
140 if (p) *p = 0;
141 if (strlen (buffer) < 22+mode)
142 continue;
143 if (strncmp (buffer + mode, " R_SPARC_", 9))
144 continue;
145 nbase = 27 - 8 + mode;
146 if (buffer[nbase] != '_' || buffer[nbase+1] != '_' || buffer[nbase+2] != '_')
147 continue;
148 switch (buffer[nbase+3]) {
149 case 'f': /* CALL */
150 case 'b': /* BLACKBOX */
151 case 's': /* SIMM13 */
152 case 'a': /* HALF */
153 case 'h': /* SETHI */
154 case 'i': /* INT */
155 break;
156 default:
157 continue;
158 }
159 p = strchr (buffer + nbase+5, '+');
160 if (p) *p = 0;
161 shift = nbase + 5;
162 if (buffer[nbase+4] == 's' && buffer[nbase+5] == '_') {
163 shift = nbase + 6;
164 if (strcmp (sect, ".init.text")) {
165 fprintf(stderr,
166 "Wrong use of '%s' BTFIXUPSET in '%s' section.\n"
167 "BTFIXUPSET_CALL can be used only in"
168 " __init sections\n",
169 buffer + shift, sect);
170 exit(1);
171 }
172 } else if (buffer[nbase+4] != '_')
173 continue;
174 if (!strcmp (sect, ".text.exit"))
175 continue;
176 if (strcmp (sect, ".text") &&
177 strcmp (sect, ".init.text") &&
178 strcmp (sect, ".fixup") &&
179 (strcmp (sect, "__ksymtab") || buffer[nbase+3] != 'f')) {
180 if (buffer[nbase+3] == 'f')
181 fprintf(stderr,
182 "Wrong use of '%s' in '%s' section.\n"
183 " It can be used only in .text, .init.text,"
184 " .fixup and __ksymtab\n",
185 buffer + shift, sect);
186 else
187 fprintf(stderr,
188 "Wrong use of '%s' in '%s' section.\n"
189 " It can be only used in .text, .init.text,"
190 " and .fixup\n", buffer + shift, sect);
191 exit(1);
192 }
193 p = strstr (buffer + shift, "__btset_");
194 if (p && buffer[nbase+4] == 's') {
195 fprintf(stderr, "__btset_ in BTFIXUP name can only be used when defining the variable, not for setting\n%s\n", buffer);
196 exit(1);
197 }
198 initval = 0;
199 initvalstr = NULL;
200 if (p) {
201 if (p[8] != '0' || p[9] != 'x') {
202 fprintf(stderr, "Pre-initialized values can be only initialized with hexadecimal constants starting 0x\n%s\n", buffer);
203 exit(1);
204 }
205 initval = strtoul(p + 10, &q, 16);
206 if (*q || !initval) {
207 fprintf(stderr, "Pre-initialized values can be only in the form name__btset_0xXXXXXXXX where X are hex digits.\nThey cannot be name__btset_0x00000000 though. Use BTFIXUPDEF_XX instead of BTFIXUPDEF_XX_INIT then.\n%s\n", buffer);
208 exit(1);
209 }
210 initvalstr = p + 10;
211 *p = 0;
212 }
213 f = find(buffer[nbase+3], buffer + shift);
214 if (buffer[nbase+4] == 's')
215 continue;
216 switch (buffer[nbase+3]) {
217 case 'f':
218 if (initval) {
219 fprintf(stderr, "Cannot use pre-initialized fixups for calls\n%s\n", buffer);
220 exit(1);
221 }
222 if (!strcmp (sect, "__ksymtab")) {
223 if (strncmp (buffer + mode+9, "32 ", 10)) {
224 fprintf(stderr, "BTFIXUP_CALL in EXPORT_SYMBOL results in relocation other than R_SPARC_32\n\%s\n", buffer);
225 exit(1);
226 }
227 } else if (strncmp (buffer + mode+9, "WDISP30 ", 10) &&
228 strncmp (buffer + mode+9, "HI22 ", 10) &&
229 strncmp (buffer + mode+9, "LO10 ", 10)) {
230 fprintf(stderr, "BTFIXUP_CALL results in relocation other than R_SPARC_WDISP30, R_SPARC_HI22 or R_SPARC_LO10\n%s\n", buffer);
231 exit(1);
232 }
233 break;
234 case 'b':
235 if (initval) {
236 fprintf(stderr, "Cannot use pre-initialized fixups for blackboxes\n%s\n", buffer);
237 exit(1);
238 }
239 if (strncmp (buffer + mode+9, "HI22 ", 10)) {
240 fprintf(stderr, "BTFIXUP_BLACKBOX results in relocation other than R_SPARC_HI22\n%s\n", buffer);
241 exit(1);
242 }
243 break;
244 case 's':
245 if (initval + 0x1000 >= 0x2000) {
246 fprintf(stderr, "Wrong initializer for SIMM13. Has to be from $fffff000 to $00000fff\n%s\n", buffer);
247 exit(1);
248 }
249 if (strncmp (buffer + mode+9, "13 ", 10)) {
250 fprintf(stderr, "BTFIXUP_SIMM13 results in relocation other than R_SPARC_13\n%s\n", buffer);
251 exit(1);
252 }
253 break;
254 case 'a':
255 if (initval + 0x1000 >= 0x2000 && (initval & 0x3ff)) {
256 fprintf(stderr, "Wrong initializer for HALF.\n%s\n", buffer);
257 exit(1);
258 }
259 if (strncmp (buffer + mode+9, "13 ", 10)) {
260 fprintf(stderr, "BTFIXUP_HALF results in relocation other than R_SPARC_13\n%s\n", buffer);
261 exit(1);
262 }
263 break;
264 case 'h':
265 if (initval & 0x3ff) {
266 fprintf(stderr, "Wrong initializer for SETHI. Cannot have set low 10 bits\n%s\n", buffer);
267 exit(1);
268 }
269 if (strncmp (buffer + mode+9, "HI22 ", 10)) {
270 fprintf(stderr, "BTFIXUP_SETHI results in relocation other than R_SPARC_HI22\n%s\n", buffer);
271 exit(1);
272 }
273 break;
274 case 'i':
275 if (initval) {
276 fprintf(stderr, "Cannot use pre-initialized fixups for INT\n%s\n", buffer);
277 exit(1);
278 }
279 if (strncmp (buffer + mode+9, "HI22 ", 10) && strncmp (buffer + mode+9, "LO10 ", 10)) {
280 fprintf(stderr, "BTFIXUP_INT results in relocation other than R_SPARC_HI22 and R_SPARC_LO10\n%s\n", buffer);
281 exit(1);
282 }
283 break;
284 }
285 if (!f->setinitval) {
286 f->initval = initval;
287 if (initvalstr) {
288 f->initvalstr = strdup(initvalstr);
289 if (!f->initvalstr) fatal();
290 }
291 f->setinitval = 1;
292 } else if (f->initval != initval) {
293 fprintf(stderr, "Btfixup %s previously used with initializer %s which doesn't match with current initializer\n%s\n",
294 f->name, f->initvalstr ? : "0x00000000", buffer);
295 exit(1);
296 } else if (initval && strcmp(f->initvalstr, initvalstr)) {
297 fprintf(stderr, "Btfixup %s previously used with initializer %s which doesn't match with current initializer.\n"
298 "Initializers have to match literally as well.\n%s\n",
299 f->name, f->initvalstr, buffer);
300 exit(1);
301 }
302 offset = strtoul(buffer, &q, 16);
303 if (q != buffer + mode || (!offset && (mode == 8 ? strncmp (buffer, "00000000 ", 9) : strncmp (buffer, "0000000000000000 ", 17)))) {
304 fprintf(stderr, "Malformed relocation address in\n%s\n", buffer);
305 exit(1);
306 }
307 for (k = 0, r = f->rel, rr = &f->rel; r; rr = &r->next, r = r->next, k++)
308 if (r->offset == offset && !strcmp(r->sect, sect)) {
309 fprintf(stderr, "Ugh. One address has two relocation records\n");
310 exit(1);
311 }
312 *rr = malloc(sizeof(btfixuprel));
313 if (!*rr) fatal();
314 (*rr)->offset = offset;
315 (*rr)->f = NULL;
316 if (buffer[nbase+3] == 'f') {
317 lastf = f;
318 lastfoffset = offset;
319 lastfrelno = k;
320 } else if (lastfoffset + 4 == offset) {
321 (*rr)->f = lastf;
322 (*rr)->frel = lastfrelno;
323 }
324 (*rr)->sect = sect;
325 (*rr)->next = NULL;
326 }
327 printf("! Generated by btfixupprep. Do not edit.\n\n");
328 printf("\t.section\t\".data..init\",#alloc,#write\n\t.align\t4\n\n");
329 printf("\t.global\t___btfixup_start\n___btfixup_start:\n\n");
330 for (i = 0; i < last; i++) {
331 f = array + i;
332 printf("\t.global\t___%cs_%s\n", f->type, f->name);
333 if (f->type == 'f')
334 printf("___%cs_%s:\n\t.word 0x%08x,0,0,", f->type, f->name, f->type << 24);
335 else
336 printf("___%cs_%s:\n\t.word 0x%08x,0,", f->type, f->name, f->type << 24);
337 for (j = 0, r = f->rel; r != NULL; j++, r = r->next);
338 if (j)
339 printf("%d\n\t.word\t", j * 2);
340 else
341 printf("0\n");
342 for (r = f->rel, j--; r != NULL; j--, r = r->next) {
343 if (!strcmp (r->sect, ".text"))
344 printf ("_stext+0x%08lx", r->offset);
345 else if (!strcmp (r->sect, ".init.text"))
346 printf ("__init_begin+0x%08lx", r->offset);
347 else if (!strcmp (r->sect, "__ksymtab"))
348 printf ("__start___ksymtab+0x%08lx", r->offset);
349 else if (!strcmp (r->sect, ".fixup"))
350 printf ("__start___fixup+0x%08lx", r->offset);
351 else
352 fatal();
353 if (f->type == 'f' || !r->f)
354 printf (",0");
355 else
356 printf (",___fs_%s+0x%08x", r->f->name, (4 + r->frel*2)*4 + 4);
357 if (j) printf (",");
358 else printf ("\n");
359 }
360 printf("\n");
361 }
362 printf("\n\t.global\t___btfixup_end\n___btfixup_end:\n");
363 printf("\n\n! Define undefined references\n\n");
364 for (i = 0; i < last; i++) {
365 f = array + i;
366 if (f->type == 'f') {
367 printf("\t.global\t___f_%s\n", f->name);
368 printf("___f_%s:\n", f->name);
369 }
370 }
371 printf("\tretl\n\t nop\n\n");
372 for (i = 0; i < last; i++) {
373 f = array + i;
374 if (f->type != 'f') {
375 if (!f->initval) {
376 printf("\t.global\t___%c_%s\n", f->type, f->name);
377 printf("___%c_%s = 0\n", f->type, f->name);
378 } else {
379 printf("\t.global\t___%c_%s__btset_0x%s\n", f->type, f->name, f->initvalstr);
380 printf("___%c_%s__btset_0x%s = 0x%08x\n", f->type, f->name, f->initvalstr, f->initval);
381 }
382 }
383 }
384 printf("\n\n");
385 exit(0);
386}
diff --git a/arch/sparc/include/asm/asi.h b/arch/sparc/include/asm/asi.h
index b2e3db63a64b..cbb93e5141de 100644
--- a/arch/sparc/include/asm/asi.h
+++ b/arch/sparc/include/asm/asi.h
@@ -112,6 +112,20 @@
112 112
113#define ASI_M_ACTION 0x4c /* Breakpoint Action Register (GNU/Viking) */ 113#define ASI_M_ACTION 0x4c /* Breakpoint Action Register (GNU/Viking) */
114 114
115/* LEON ASI */
116#define ASI_LEON_NOCACHE 0x01
117
118#define ASI_LEON_DCACHE_MISS 0x01
119
120#define ASI_LEON_CACHEREGS 0x02
121#define ASI_LEON_IFLUSH 0x10
122#define ASI_LEON_DFLUSH 0x11
123
124#define ASI_LEON_MMUFLUSH 0x18
125#define ASI_LEON_MMUREGS 0x19
126#define ASI_LEON_BYPASS 0x1c
127#define ASI_LEON_FLUSH_PAGE 0x10
128
115/* V9 Architecture mandary ASIs. */ 129/* V9 Architecture mandary ASIs. */
116#define ASI_N 0x04 /* Nucleus */ 130#define ASI_N 0x04 /* Nucleus */
117#define ASI_NL 0x0c /* Nucleus, little endian */ 131#define ASI_NL 0x0c /* Nucleus, little endian */
diff --git a/arch/sparc/include/asm/asmmacro.h b/arch/sparc/include/asm/asmmacro.h
index a995bf8aba3f..02a172fb193a 100644
--- a/arch/sparc/include/asm/asmmacro.h
+++ b/arch/sparc/include/asm/asmmacro.h
@@ -6,17 +6,6 @@
6#ifndef _SPARC_ASMMACRO_H 6#ifndef _SPARC_ASMMACRO_H
7#define _SPARC_ASMMACRO_H 7#define _SPARC_ASMMACRO_H
8 8
9#include <asm/btfixup.h>
10#include <asm/asi.h>
11
12#define GET_PROCESSOR4M_ID(reg) \
13 rd %tbr, %reg; \
14 srl %reg, 12, %reg; \
15 and %reg, 3, %reg;
16
17#define GET_PROCESSOR4D_ID(reg) \
18 lda [%g0] ASI_M_VIKING_TMP1, %reg;
19
20/* All trap entry points _must_ begin with this macro or else you 9/* All trap entry points _must_ begin with this macro or else you
21 * lose. It makes sure the kernel has a proper window so that 10 * lose. It makes sure the kernel has a proper window so that
22 * c-code can be called. 11 * c-code can be called.
@@ -31,10 +20,4 @@
31/* All traps low-level code here must end with this macro. */ 20/* All traps low-level code here must end with this macro. */
32#define RESTORE_ALL b ret_trap_entry; clr %l6; 21#define RESTORE_ALL b ret_trap_entry; clr %l6;
33 22
34/* sun4 probably wants half word accesses to ASI_SEGMAP, while sun4c+
35 likes byte accesses. These are to avoid ifdef mania. */
36
37#define lduXa lduba
38#define stXa stba
39
40#endif /* !(_SPARC_ASMMACRO_H) */ 23#endif /* !(_SPARC_ASMMACRO_H) */
diff --git a/arch/sparc/include/asm/btfixup.h b/arch/sparc/include/asm/btfixup.h
deleted file mode 100644
index 797722cf69f2..000000000000
--- a/arch/sparc/include/asm/btfixup.h
+++ /dev/null
@@ -1,208 +0,0 @@
1/*
2 * asm/btfixup.h: Macros for boot time linking.
3 *
4 * Copyright (C) 1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
5 */
6
7#ifndef _SPARC_BTFIXUP_H
8#define _SPARC_BTFIXUP_H
9
10#include <linux/init.h>
11
12#ifndef __ASSEMBLY__
13
14#ifdef MODULE
15extern unsigned int ___illegal_use_of_BTFIXUP_SIMM13_in_module(void);
16extern unsigned int ___illegal_use_of_BTFIXUP_SETHI_in_module(void);
17extern unsigned int ___illegal_use_of_BTFIXUP_HALF_in_module(void);
18extern unsigned int ___illegal_use_of_BTFIXUP_INT_in_module(void);
19
20#define BTFIXUP_SIMM13(__name) ___illegal_use_of_BTFIXUP_SIMM13_in_module()
21#define BTFIXUP_HALF(__name) ___illegal_use_of_BTFIXUP_HALF_in_module()
22#define BTFIXUP_SETHI(__name) ___illegal_use_of_BTFIXUP_SETHI_in_module()
23#define BTFIXUP_INT(__name) ___illegal_use_of_BTFIXUP_INT_in_module()
24#define BTFIXUP_BLACKBOX(__name) ___illegal_use_of_BTFIXUP_BLACKBOX_in_module
25
26#else
27
28#define BTFIXUP_SIMM13(__name) ___sf_##__name()
29#define BTFIXUP_HALF(__name) ___af_##__name()
30#define BTFIXUP_SETHI(__name) ___hf_##__name()
31#define BTFIXUP_INT(__name) ((unsigned int)&___i_##__name)
32/* This must be written in assembly and present in a sethi */
33#define BTFIXUP_BLACKBOX(__name) ___b_##__name
34#endif /* MODULE */
35
36/* Fixup call xx */
37
38#define BTFIXUPDEF_CALL(__type, __name, __args...) \
39 extern __type ___f_##__name(__args); \
40 extern unsigned ___fs_##__name[3];
41#define BTFIXUPDEF_CALL_CONST(__type, __name, __args...) \
42 extern __type ___f_##__name(__args) __attribute_const__; \
43 extern unsigned ___fs_##__name[3];
44#define BTFIXUP_CALL(__name) ___f_##__name
45
46#define BTFIXUPDEF_BLACKBOX(__name) \
47 extern unsigned ___bs_##__name[2];
48
49/* Put bottom 13bits into some register variable */
50
51#define BTFIXUPDEF_SIMM13(__name) \
52 static inline unsigned int ___sf_##__name(void) __attribute_const__; \
53 extern unsigned ___ss_##__name[2]; \
54 static inline unsigned int ___sf_##__name(void) { \
55 unsigned int ret; \
56 __asm__ ("or %%g0, ___s_" #__name ", %0" : "=r"(ret)); \
57 return ret; \
58 }
59#define BTFIXUPDEF_SIMM13_INIT(__name,__val) \
60 static inline unsigned int ___sf_##__name(void) __attribute_const__; \
61 extern unsigned ___ss_##__name[2]; \
62 static inline unsigned int ___sf_##__name(void) { \
63 unsigned int ret; \
64 __asm__ ("or %%g0, ___s_" #__name "__btset_" #__val ", %0" : "=r"(ret));\
65 return ret; \
66 }
67
68/* Put either bottom 13 bits, or upper 22 bits into some register variable
69 * (depending on the value, this will lead into sethi FIX, reg; or
70 * mov FIX, reg; )
71 */
72
73#define BTFIXUPDEF_HALF(__name) \
74 static inline unsigned int ___af_##__name(void) __attribute_const__; \
75 extern unsigned ___as_##__name[2]; \
76 static inline unsigned int ___af_##__name(void) { \
77 unsigned int ret; \
78 __asm__ ("or %%g0, ___a_" #__name ", %0" : "=r"(ret)); \
79 return ret; \
80 }
81#define BTFIXUPDEF_HALF_INIT(__name,__val) \
82 static inline unsigned int ___af_##__name(void) __attribute_const__; \
83 extern unsigned ___as_##__name[2]; \
84 static inline unsigned int ___af_##__name(void) { \
85 unsigned int ret; \
86 __asm__ ("or %%g0, ___a_" #__name "__btset_" #__val ", %0" : "=r"(ret));\
87 return ret; \
88 }
89
90/* Put upper 22 bits into some register variable */
91
92#define BTFIXUPDEF_SETHI(__name) \
93 static inline unsigned int ___hf_##__name(void) __attribute_const__; \
94 extern unsigned ___hs_##__name[2]; \
95 static inline unsigned int ___hf_##__name(void) { \
96 unsigned int ret; \
97 __asm__ ("sethi %%hi(___h_" #__name "), %0" : "=r"(ret)); \
98 return ret; \
99 }
100#define BTFIXUPDEF_SETHI_INIT(__name,__val) \
101 static inline unsigned int ___hf_##__name(void) __attribute_const__; \
102 extern unsigned ___hs_##__name[2]; \
103 static inline unsigned int ___hf_##__name(void) { \
104 unsigned int ret; \
105 __asm__ ("sethi %%hi(___h_" #__name "__btset_" #__val "), %0" : \
106 "=r"(ret)); \
107 return ret; \
108 }
109
110/* Put a full 32bit integer into some register variable */
111
112#define BTFIXUPDEF_INT(__name) \
113 extern unsigned char ___i_##__name; \
114 extern unsigned ___is_##__name[2];
115
116#define BTFIXUPCALL_NORM 0x00000000 /* Always call */
117#define BTFIXUPCALL_NOP 0x01000000 /* Possibly optimize to nop */
118#define BTFIXUPCALL_RETINT(i) (0x90102000|((i) & 0x1fff)) /* Possibly optimize to mov i, %o0 */
119#define BTFIXUPCALL_ORINT(i) (0x90122000|((i) & 0x1fff)) /* Possibly optimize to or %o0, i, %o0 */
120#define BTFIXUPCALL_RETO0 0x01000000 /* Return first parameter, actually a nop */
121#define BTFIXUPCALL_ANDNINT(i) (0x902a2000|((i) & 0x1fff)) /* Possibly optimize to andn %o0, i, %o0 */
122#define BTFIXUPCALL_SWAPO0O1 0xd27a0000 /* Possibly optimize to swap [%o0],%o1 */
123#define BTFIXUPCALL_SWAPO0G0 0xc07a0000 /* Possibly optimize to swap [%o0],%g0 */
124#define BTFIXUPCALL_SWAPG1G2 0xc4784000 /* Possibly optimize to swap [%g1],%g2 */
125#define BTFIXUPCALL_STG0O0 0xc0220000 /* Possibly optimize to st %g0,[%o0] */
126#define BTFIXUPCALL_STO1O0 0xd2220000 /* Possibly optimize to st %o1,[%o0] */
127
128#define BTFIXUPSET_CALL(__name, __addr, __insn) \
129 do { \
130 ___fs_##__name[0] |= 1; \
131 ___fs_##__name[1] = (unsigned long)__addr; \
132 ___fs_##__name[2] = __insn; \
133 } while (0)
134
135#define BTFIXUPSET_BLACKBOX(__name, __func) \
136 do { \
137 ___bs_##__name[0] |= 1; \
138 ___bs_##__name[1] = (unsigned long)__func; \
139 } while (0)
140
141#define BTFIXUPCOPY_CALL(__name, __from) \
142 do { \
143 ___fs_##__name[0] |= 1; \
144 ___fs_##__name[1] = ___fs_##__from[1]; \
145 ___fs_##__name[2] = ___fs_##__from[2]; \
146 } while (0)
147
148#define BTFIXUPSET_SIMM13(__name, __val) \
149 do { \
150 ___ss_##__name[0] |= 1; \
151 ___ss_##__name[1] = (unsigned)__val; \
152 } while (0)
153
154#define BTFIXUPCOPY_SIMM13(__name, __from) \
155 do { \
156 ___ss_##__name[0] |= 1; \
157 ___ss_##__name[1] = ___ss_##__from[1]; \
158 } while (0)
159
160#define BTFIXUPSET_HALF(__name, __val) \
161 do { \
162 ___as_##__name[0] |= 1; \
163 ___as_##__name[1] = (unsigned)__val; \
164 } while (0)
165
166#define BTFIXUPCOPY_HALF(__name, __from) \
167 do { \
168 ___as_##__name[0] |= 1; \
169 ___as_##__name[1] = ___as_##__from[1]; \
170 } while (0)
171
172#define BTFIXUPSET_SETHI(__name, __val) \
173 do { \
174 ___hs_##__name[0] |= 1; \
175 ___hs_##__name[1] = (unsigned)__val; \
176 } while (0)
177
178#define BTFIXUPCOPY_SETHI(__name, __from) \
179 do { \
180 ___hs_##__name[0] |= 1; \
181 ___hs_##__name[1] = ___hs_##__from[1]; \
182 } while (0)
183
184#define BTFIXUPSET_INT(__name, __val) \
185 do { \
186 ___is_##__name[0] |= 1; \
187 ___is_##__name[1] = (unsigned)__val; \
188 } while (0)
189
190#define BTFIXUPCOPY_INT(__name, __from) \
191 do { \
192 ___is_##__name[0] |= 1; \
193 ___is_##__name[1] = ___is_##__from[1]; \
194 } while (0)
195
196#define BTFIXUPVAL_CALL(__name) \
197 ((unsigned long)___fs_##__name[1])
198
199extern void btfixup(void);
200
201#else /* __ASSEMBLY__ */
202
203#define BTFIXUP_SETHI(__name) %hi(___h_ ## __name)
204#define BTFIXUP_SETHI_INIT(__name,__val) %hi(___h_ ## __name ## __btset_ ## __val)
205
206#endif /* __ASSEMBLY__ */
207
208#endif /* !(_SPARC_BTFIXUP_H) */
diff --git a/arch/sparc/include/asm/cache.h b/arch/sparc/include/asm/cache.h
index 69358b590c91..5bb6991b4857 100644
--- a/arch/sparc/include/asm/cache.h
+++ b/arch/sparc/include/asm/cache.h
@@ -22,118 +22,4 @@
22 22
23#define __read_mostly __attribute__((__section__(".data..read_mostly"))) 23#define __read_mostly __attribute__((__section__(".data..read_mostly")))
24 24
25#ifdef CONFIG_SPARC32
26#include <asm/asi.h>
27
28/* Direct access to the instruction cache is provided through and
29 * alternate address space. The IDC bit must be off in the ICCR on
30 * HyperSparcs for these accesses to work. The code below does not do
31 * any checking, the caller must do so. These routines are for
32 * diagnostics only, but could end up being useful. Use with care.
33 * Also, you are asking for trouble if you execute these in one of the
34 * three instructions following a %asr/%psr access or modification.
35 */
36
37/* First, cache-tag access. */
38static inline unsigned int get_icache_tag(int setnum, int tagnum)
39{
40 unsigned int vaddr, retval;
41
42 vaddr = ((setnum&1) << 12) | ((tagnum&0x7f) << 5);
43 __asm__ __volatile__("lda [%1] %2, %0\n\t" :
44 "=r" (retval) :
45 "r" (vaddr), "i" (ASI_M_TXTC_TAG));
46 return retval;
47}
48
49static inline void put_icache_tag(int setnum, int tagnum, unsigned int entry)
50{
51 unsigned int vaddr;
52
53 vaddr = ((setnum&1) << 12) | ((tagnum&0x7f) << 5);
54 __asm__ __volatile__("sta %0, [%1] %2\n\t" : :
55 "r" (entry), "r" (vaddr), "i" (ASI_M_TXTC_TAG) :
56 "memory");
57}
58
59/* Second cache-data access. The data is returned two-32bit quantities
60 * at a time.
61 */
62static inline void get_icache_data(int setnum, int tagnum, int subblock,
63 unsigned int *data)
64{
65 unsigned int value1, value2, vaddr;
66
67 vaddr = ((setnum&0x1) << 12) | ((tagnum&0x7f) << 5) |
68 ((subblock&0x3) << 3);
69 __asm__ __volatile__("ldda [%2] %3, %%g2\n\t"
70 "or %%g0, %%g2, %0\n\t"
71 "or %%g0, %%g3, %1\n\t" :
72 "=r" (value1), "=r" (value2) :
73 "r" (vaddr), "i" (ASI_M_TXTC_DATA) :
74 "g2", "g3");
75 data[0] = value1; data[1] = value2;
76}
77
78static inline void put_icache_data(int setnum, int tagnum, int subblock,
79 unsigned int *data)
80{
81 unsigned int value1, value2, vaddr;
82
83 vaddr = ((setnum&0x1) << 12) | ((tagnum&0x7f) << 5) |
84 ((subblock&0x3) << 3);
85 value1 = data[0]; value2 = data[1];
86 __asm__ __volatile__("or %%g0, %0, %%g2\n\t"
87 "or %%g0, %1, %%g3\n\t"
88 "stda %%g2, [%2] %3\n\t" : :
89 "r" (value1), "r" (value2),
90 "r" (vaddr), "i" (ASI_M_TXTC_DATA) :
91 "g2", "g3", "memory" /* no joke */);
92}
93
94/* Different types of flushes with the ICACHE. Some of the flushes
95 * affect both the ICACHE and the external cache. Others only clear
96 * the ICACHE entries on the cpu itself. V8's (most) allow
97 * granularity of flushes on the packet (element in line), whole line,
98 * and entire cache (ie. all lines) level. The ICACHE only flushes are
99 * ROSS HyperSparc specific and are in ross.h
100 */
101
102/* Flushes which clear out both the on-chip and external caches */
103static inline void flush_ei_page(unsigned int addr)
104{
105 __asm__ __volatile__("sta %%g0, [%0] %1\n\t" : :
106 "r" (addr), "i" (ASI_M_FLUSH_PAGE) :
107 "memory");
108}
109
110static inline void flush_ei_seg(unsigned int addr)
111{
112 __asm__ __volatile__("sta %%g0, [%0] %1\n\t" : :
113 "r" (addr), "i" (ASI_M_FLUSH_SEG) :
114 "memory");
115}
116
117static inline void flush_ei_region(unsigned int addr)
118{
119 __asm__ __volatile__("sta %%g0, [%0] %1\n\t" : :
120 "r" (addr), "i" (ASI_M_FLUSH_REGION) :
121 "memory");
122}
123
124static inline void flush_ei_ctx(unsigned int addr)
125{
126 __asm__ __volatile__("sta %%g0, [%0] %1\n\t" : :
127 "r" (addr), "i" (ASI_M_FLUSH_CTX) :
128 "memory");
129}
130
131static inline void flush_ei_user(unsigned int addr)
132{
133 __asm__ __volatile__("sta %%g0, [%0] %1\n\t" : :
134 "r" (addr), "i" (ASI_M_FLUSH_USER) :
135 "memory");
136}
137#endif /* CONFIG_SPARC32 */
138
139#endif /* !(_SPARC_CACHE_H) */ 25#endif /* !(_SPARC_CACHE_H) */
diff --git a/arch/sparc/include/asm/cacheflush.h b/arch/sparc/include/asm/cacheflush.h
index 049168087b19..f6c4839b8388 100644
--- a/arch/sparc/include/asm/cacheflush.h
+++ b/arch/sparc/include/asm/cacheflush.h
@@ -1,5 +1,9 @@
1#ifndef ___ASM_SPARC_CACHEFLUSH_H 1#ifndef ___ASM_SPARC_CACHEFLUSH_H
2#define ___ASM_SPARC_CACHEFLUSH_H 2#define ___ASM_SPARC_CACHEFLUSH_H
3
4/* flush addr - to allow use of self-modifying code */
5#define flushi(addr) __asm__ __volatile__ ("flush %0" : : "r" (addr) : "memory")
6
3#if defined(__sparc__) && defined(__arch64__) 7#if defined(__sparc__) && defined(__arch64__)
4#include <asm/cacheflush_64.h> 8#include <asm/cacheflush_64.h>
5#else 9#else
diff --git a/arch/sparc/include/asm/cacheflush_32.h b/arch/sparc/include/asm/cacheflush_32.h
index 68431b47a22a..bb014c24f318 100644
--- a/arch/sparc/include/asm/cacheflush_32.h
+++ b/arch/sparc/include/asm/cacheflush_32.h
@@ -1,56 +1,18 @@
1#ifndef _SPARC_CACHEFLUSH_H 1#ifndef _SPARC_CACHEFLUSH_H
2#define _SPARC_CACHEFLUSH_H 2#define _SPARC_CACHEFLUSH_H
3 3
4#include <linux/mm.h> /* Common for other includes */ 4#include <asm/cachetlb_32.h>
5// #include <linux/kernel.h> from pgalloc.h 5
6// #include <linux/sched.h> from pgalloc.h 6#define flush_cache_all() \
7 7 sparc32_cachetlb_ops->cache_all()
8// #include <asm/page.h> 8#define flush_cache_mm(mm) \
9#include <asm/btfixup.h> 9 sparc32_cachetlb_ops->cache_mm(mm)
10 10#define flush_cache_dup_mm(mm) \
11/* 11 sparc32_cachetlb_ops->cache_mm(mm)
12 * Fine grained cache flushing. 12#define flush_cache_range(vma,start,end) \
13 */ 13 sparc32_cachetlb_ops->cache_range(vma, start, end)
14#ifdef CONFIG_SMP 14#define flush_cache_page(vma,addr,pfn) \
15 15 sparc32_cachetlb_ops->cache_page(vma, addr)
16BTFIXUPDEF_CALL(void, local_flush_cache_all, void)
17BTFIXUPDEF_CALL(void, local_flush_cache_mm, struct mm_struct *)
18BTFIXUPDEF_CALL(void, local_flush_cache_range, struct vm_area_struct *, unsigned long, unsigned long)
19BTFIXUPDEF_CALL(void, local_flush_cache_page, struct vm_area_struct *, unsigned long)
20
21#define local_flush_cache_all() BTFIXUP_CALL(local_flush_cache_all)()
22#define local_flush_cache_mm(mm) BTFIXUP_CALL(local_flush_cache_mm)(mm)
23#define local_flush_cache_range(vma,start,end) BTFIXUP_CALL(local_flush_cache_range)(vma,start,end)
24#define local_flush_cache_page(vma,addr) BTFIXUP_CALL(local_flush_cache_page)(vma,addr)
25
26BTFIXUPDEF_CALL(void, local_flush_page_to_ram, unsigned long)
27BTFIXUPDEF_CALL(void, local_flush_sig_insns, struct mm_struct *, unsigned long)
28
29#define local_flush_page_to_ram(addr) BTFIXUP_CALL(local_flush_page_to_ram)(addr)
30#define local_flush_sig_insns(mm,insn_addr) BTFIXUP_CALL(local_flush_sig_insns)(mm,insn_addr)
31
32extern void smp_flush_cache_all(void);
33extern void smp_flush_cache_mm(struct mm_struct *mm);
34extern void smp_flush_cache_range(struct vm_area_struct *vma,
35 unsigned long start,
36 unsigned long end);
37extern void smp_flush_cache_page(struct vm_area_struct *vma, unsigned long page);
38
39extern void smp_flush_page_to_ram(unsigned long page);
40extern void smp_flush_sig_insns(struct mm_struct *mm, unsigned long insn_addr);
41
42#endif /* CONFIG_SMP */
43
44BTFIXUPDEF_CALL(void, flush_cache_all, void)
45BTFIXUPDEF_CALL(void, flush_cache_mm, struct mm_struct *)
46BTFIXUPDEF_CALL(void, flush_cache_range, struct vm_area_struct *, unsigned long, unsigned long)
47BTFIXUPDEF_CALL(void, flush_cache_page, struct vm_area_struct *, unsigned long)
48
49#define flush_cache_all() BTFIXUP_CALL(flush_cache_all)()
50#define flush_cache_mm(mm) BTFIXUP_CALL(flush_cache_mm)(mm)
51#define flush_cache_dup_mm(mm) BTFIXUP_CALL(flush_cache_mm)(mm)
52#define flush_cache_range(vma,start,end) BTFIXUP_CALL(flush_cache_range)(vma,start,end)
53#define flush_cache_page(vma,addr,pfn) BTFIXUP_CALL(flush_cache_page)(vma,addr)
54#define flush_icache_range(start, end) do { } while (0) 16#define flush_icache_range(start, end) do { } while (0)
55#define flush_icache_page(vma, pg) do { } while (0) 17#define flush_icache_page(vma, pg) do { } while (0)
56 18
@@ -67,11 +29,12 @@ BTFIXUPDEF_CALL(void, flush_cache_page, struct vm_area_struct *, unsigned long)
67 memcpy(dst, src, len); \ 29 memcpy(dst, src, len); \
68 } while (0) 30 } while (0)
69 31
70BTFIXUPDEF_CALL(void, __flush_page_to_ram, unsigned long) 32#define __flush_page_to_ram(addr) \
71BTFIXUPDEF_CALL(void, flush_sig_insns, struct mm_struct *, unsigned long) 33 sparc32_cachetlb_ops->page_to_ram(addr)
72 34#define flush_sig_insns(mm,insn_addr) \
73#define __flush_page_to_ram(addr) BTFIXUP_CALL(__flush_page_to_ram)(addr) 35 sparc32_cachetlb_ops->sig_insns(mm, insn_addr)
74#define flush_sig_insns(mm,insn_addr) BTFIXUP_CALL(flush_sig_insns)(mm,insn_addr) 36#define flush_page_for_dma(addr) \
37 sparc32_cachetlb_ops->page_for_dma(addr)
75 38
76extern void sparc_flush_page_to_ram(struct page *page); 39extern void sparc_flush_page_to_ram(struct page *page);
77 40
diff --git a/arch/sparc/include/asm/cacheflush_64.h b/arch/sparc/include/asm/cacheflush_64.h
index 2efea2ff88b7..301736d9e7a1 100644
--- a/arch/sparc/include/asm/cacheflush_64.h
+++ b/arch/sparc/include/asm/cacheflush_64.h
@@ -8,9 +8,6 @@
8#include <linux/mm.h> 8#include <linux/mm.h>
9 9
10/* Cache flush operations. */ 10/* Cache flush operations. */
11
12
13#define flushi(addr) __asm__ __volatile__ ("flush %0" : : "r" (addr) : "memory")
14#define flushw_all() __asm__ __volatile__("flushw") 11#define flushw_all() __asm__ __volatile__("flushw")
15 12
16extern void __flushw_user(void); 13extern void __flushw_user(void);
diff --git a/arch/sparc/include/asm/cachetlb_32.h b/arch/sparc/include/asm/cachetlb_32.h
new file mode 100644
index 000000000000..efb19889a083
--- /dev/null
+++ b/arch/sparc/include/asm/cachetlb_32.h
@@ -0,0 +1,29 @@
1#ifndef _SPARC_CACHETLB_H
2#define _SPARC_CACHETLB_H
3
4struct mm_struct;
5struct vm_area_struct;
6
7struct sparc32_cachetlb_ops {
8 void (*cache_all)(void);
9 void (*cache_mm)(struct mm_struct *);
10 void (*cache_range)(struct vm_area_struct *, unsigned long,
11 unsigned long);
12 void (*cache_page)(struct vm_area_struct *, unsigned long);
13
14 void (*tlb_all)(void);
15 void (*tlb_mm)(struct mm_struct *);
16 void (*tlb_range)(struct vm_area_struct *, unsigned long,
17 unsigned long);
18 void (*tlb_page)(struct vm_area_struct *, unsigned long);
19
20 void (*page_to_ram)(unsigned long);
21 void (*sig_insns)(struct mm_struct *, unsigned long);
22 void (*page_for_dma)(unsigned long);
23};
24extern const struct sparc32_cachetlb_ops *sparc32_cachetlb_ops;
25#ifdef CONFIG_SMP
26extern const struct sparc32_cachetlb_ops *local_ops;
27#endif
28
29#endif /* SPARC_CACHETLB_H */
diff --git a/arch/sparc/include/asm/cmpxchg_32.h b/arch/sparc/include/asm/cmpxchg_32.h
index c786b0a92b51..1fae1a02e3c2 100644
--- a/arch/sparc/include/asm/cmpxchg_32.h
+++ b/arch/sparc/include/asm/cmpxchg_32.h
@@ -11,40 +11,13 @@
11#ifndef __ARCH_SPARC_CMPXCHG__ 11#ifndef __ARCH_SPARC_CMPXCHG__
12#define __ARCH_SPARC_CMPXCHG__ 12#define __ARCH_SPARC_CMPXCHG__
13 13
14#include <asm/btfixup.h>
15
16/* This has special calling conventions */
17#ifndef CONFIG_SMP
18BTFIXUPDEF_CALL(void, ___xchg32, void)
19#endif
20
21static inline unsigned long xchg_u32(__volatile__ unsigned long *m, unsigned long val) 14static inline unsigned long xchg_u32(__volatile__ unsigned long *m, unsigned long val)
22{ 15{
23#ifdef CONFIG_SMP
24 __asm__ __volatile__("swap [%2], %0" 16 __asm__ __volatile__("swap [%2], %0"
25 : "=&r" (val) 17 : "=&r" (val)
26 : "0" (val), "r" (m) 18 : "0" (val), "r" (m)
27 : "memory"); 19 : "memory");
28 return val; 20 return val;
29#else
30 register unsigned long *ptr asm("g1");
31 register unsigned long ret asm("g2");
32
33 ptr = (unsigned long *) m;
34 ret = val;
35
36 /* Note: this is magic and the nop there is
37 really needed. */
38 __asm__ __volatile__(
39 "mov %%o7, %%g4\n\t"
40 "call ___f____xchg32\n\t"
41 " nop\n\t"
42 : "=&r" (ret)
43 : "0" (ret), "r" (ptr)
44 : "g3", "g4", "g7", "memory", "cc");
45
46 return ret;
47#endif
48} 21}
49 22
50extern void __xchg_called_with_bad_pointer(void); 23extern void __xchg_called_with_bad_pointer(void);
diff --git a/arch/sparc/include/asm/contregs.h b/arch/sparc/include/asm/contregs.h
index 48fa8a4ef357..b8abdfcf5555 100644
--- a/arch/sparc/include/asm/contregs.h
+++ b/arch/sparc/include/asm/contregs.h
@@ -7,28 +7,6 @@
7 * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) 7 * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
8 */ 8 */
9 9
10/* 3=sun3
11 4=sun4 (as in sun4 sysmaint student book)
12 c=sun4c (according to davem) */
13
14#define AC_IDPROM 0x00000000 /* 34 ID PROM, R/O, byte, 32 bytes */
15#define AC_PAGEMAP 0x10000000 /* 3 Pagemap R/W, long */
16#define AC_SEGMAP 0x20000000 /* 3 Segment map, byte */
17#define AC_CONTEXT 0x30000000 /* 34c current mmu-context */
18#define AC_SENABLE 0x40000000 /* 34c system dvma/cache/reset enable reg*/
19#define AC_UDVMA_ENB 0x50000000 /* 34 Not used on Sun boards, byte */
20#define AC_BUS_ERROR 0x60000000 /* 34 Not cleared on read, byte. */
21#define AC_SYNC_ERR 0x60000000 /* c fault type */
22#define AC_SYNC_VA 0x60000004 /* c fault virtual address */
23#define AC_ASYNC_ERR 0x60000008 /* c asynchronous fault type */
24#define AC_ASYNC_VA 0x6000000c /* c async fault virtual address */
25#define AC_LEDS 0x70000000 /* 34 Zero turns on LEDs, byte */
26#define AC_CACHETAGS 0x80000000 /* 34c direct access to the VAC tags */
27#define AC_CACHEDDATA 0x90000000 /* 3 c direct access to the VAC data */
28#define AC_UDVMA_MAP 0xD0000000 /* 4 Not used on Sun boards, byte */
29#define AC_VME_VECTOR 0xE0000000 /* 4 For non-Autovector VME, byte */
30#define AC_BOOT_SCC 0xF0000000 /* 34 bypass to access Zilog 8530. byte.*/
31
32/* s=Swift, h=Ross_HyperSPARC, v=TI_Viking, t=Tsunami, r=Ross_Cypress */ 10/* s=Swift, h=Ross_HyperSPARC, v=TI_Viking, t=Tsunami, r=Ross_Cypress */
33#define AC_M_PCR 0x0000 /* shv Processor Control Reg */ 11#define AC_M_PCR 0x0000 /* shv Processor Control Reg */
34#define AC_M_CTPR 0x0100 /* shv Context Table Pointer Reg */ 12#define AC_M_CTPR 0x0100 /* shv Context Table Pointer Reg */
diff --git a/arch/sparc/include/asm/cpu_type.h b/arch/sparc/include/asm/cpu_type.h
index 4ca184d95d82..84d7d83b8084 100644
--- a/arch/sparc/include/asm/cpu_type.h
+++ b/arch/sparc/include/asm/cpu_type.h
@@ -5,30 +5,24 @@
5 * Sparc (general) CPU types 5 * Sparc (general) CPU types
6 */ 6 */
7enum sparc_cpu { 7enum sparc_cpu {
8 sun4 = 0x00, 8 sun4m = 0x00,
9 sun4c = 0x01, 9 sun4d = 0x01,
10 sun4m = 0x02, 10 sun4e = 0x02,
11 sun4d = 0x03, 11 sun4u = 0x03, /* V8 ploos ploos */
12 sun4e = 0x04, 12 sun_unknown = 0x04,
13 sun4u = 0x05, /* V8 ploos ploos */ 13 ap1000 = 0x05, /* almost a sun4m */
14 sun_unknown = 0x06, 14 sparc_leon = 0x06, /* Leon SoC */
15 ap1000 = 0x07, /* almost a sun4m */
16 sparc_leon = 0x08, /* Leon SoC */
17}; 15};
18 16
19#ifdef CONFIG_SPARC32 17#ifdef CONFIG_SPARC32
20extern enum sparc_cpu sparc_cpu_model; 18extern enum sparc_cpu sparc_cpu_model;
21 19
22#define ARCH_SUN4C (sparc_cpu_model==sun4c)
23
24#define SUN4M_NCPUS 4 /* Architectural limit of sun4m. */ 20#define SUN4M_NCPUS 4 /* Architectural limit of sun4m. */
25 21
26#else 22#else
27 23
28#define sparc_cpu_model sun4u 24#define sparc_cpu_model sun4u
29 25
30/* This cannot ever be a sun4c :) That's just history. */
31#define ARCH_SUN4C 0
32#endif 26#endif
33 27
34#endif /* __ASM_CPU_TYPE_H */ 28#endif /* __ASM_CPU_TYPE_H */
diff --git a/arch/sparc/include/asm/cpudata_32.h b/arch/sparc/include/asm/cpudata_32.h
index a4c5a938b936..0300d94c25b3 100644
--- a/arch/sparc/include/asm/cpudata_32.h
+++ b/arch/sparc/include/asm/cpudata_32.h
@@ -14,7 +14,6 @@
14typedef struct { 14typedef struct {
15 unsigned long udelay_val; 15 unsigned long udelay_val;
16 unsigned long clock_tick; 16 unsigned long clock_tick;
17 unsigned int multiplier;
18 unsigned int counter; 17 unsigned int counter;
19#ifdef CONFIG_SMP 18#ifdef CONFIG_SMP
20 unsigned int irq_resched_count; 19 unsigned int irq_resched_count;
diff --git a/arch/sparc/include/asm/cypress.h b/arch/sparc/include/asm/cypress.h
deleted file mode 100644
index 95e9772ea394..000000000000
--- a/arch/sparc/include/asm/cypress.h
+++ /dev/null
@@ -1,79 +0,0 @@
1/*
2 * cypress.h: Cypress module specific definitions and defines.
3 *
4 * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
5 */
6
7#ifndef _SPARC_CYPRESS_H
8#define _SPARC_CYPRESS_H
9
10/* Cypress chips have %psr 'impl' of '0001' and 'vers' of '0001'. */
11
12/* The MMU control register fields on the Sparc Cypress 604/605 MMU's.
13 *
14 * ---------------------------------------------------------------
15 * |implvers| MCA | MCM |MV| MID |BM| C|RSV|MR|CM|CL|CE|RSV|NF|ME|
16 * ---------------------------------------------------------------
17 * 31 24 23-22 21-20 19 18-15 14 13 12 11 10 9 8 7-2 1 0
18 *
19 * MCA: MultiChip Access -- Used for configuration of multiple
20 * CY7C604/605 cache units.
21 * MCM: MultiChip Mask -- Again, for multiple cache unit config.
22 * MV: MultiChip Valid -- Indicates MCM and MCA have valid settings.
23 * MID: ModuleID -- Unique processor ID for MBus transactions. (605 only)
24 * BM: Boot Mode -- 0 = not in boot mode, 1 = in boot mode
25 * C: Cacheable -- Indicates whether accesses are cacheable while
26 * the MMU is off. 0=no 1=yes
27 * MR: MemoryReflection -- Indicates whether the bus attached to the
28 * MBus supports memory reflection. 0=no 1=yes (605 only)
29 * CM: CacheMode -- Indicates whether the cache is operating in write
30 * through or copy-back mode. 0=write-through 1=copy-back
31 * CL: CacheLock -- Indicates if the entire cache is locked or not.
32 * 0=not-locked 1=locked (604 only)
33 * CE: CacheEnable -- Is the virtual cache on? 0=no 1=yes
34 * NF: NoFault -- Do faults generate traps? 0=yes 1=no
35 * ME: MmuEnable -- Is the MMU doing translations? 0=no 1=yes
36 */
37
38#define CYPRESS_MCA 0x00c00000
39#define CYPRESS_MCM 0x00300000
40#define CYPRESS_MVALID 0x00080000
41#define CYPRESS_MIDMASK 0x00078000 /* Only on 605 */
42#define CYPRESS_BMODE 0x00004000
43#define CYPRESS_ACENABLE 0x00002000
44#define CYPRESS_MRFLCT 0x00000800 /* Only on 605 */
45#define CYPRESS_CMODE 0x00000400
46#define CYPRESS_CLOCK 0x00000200 /* Only on 604 */
47#define CYPRESS_CENABLE 0x00000100
48#define CYPRESS_NFAULT 0x00000002
49#define CYPRESS_MENABLE 0x00000001
50
51static inline void cypress_flush_page(unsigned long page)
52{
53 __asm__ __volatile__("sta %%g0, [%0] %1\n\t" : :
54 "r" (page), "i" (ASI_M_FLUSH_PAGE));
55}
56
57static inline void cypress_flush_segment(unsigned long addr)
58{
59 __asm__ __volatile__("sta %%g0, [%0] %1\n\t" : :
60 "r" (addr), "i" (ASI_M_FLUSH_SEG));
61}
62
63static inline void cypress_flush_region(unsigned long addr)
64{
65 __asm__ __volatile__("sta %%g0, [%0] %1\n\t" : :
66 "r" (addr), "i" (ASI_M_FLUSH_REGION));
67}
68
69static inline void cypress_flush_context(void)
70{
71 __asm__ __volatile__("sta %%g0, [%%g0] %0\n\t" : :
72 "i" (ASI_M_FLUSH_CTX));
73}
74
75/* XXX Displacement flushes for buggy chips and initial testing
76 * XXX go here.
77 */
78
79#endif /* !(_SPARC_CYPRESS_H) */
diff --git a/arch/sparc/include/asm/dma.h b/arch/sparc/include/asm/dma.h
index b554927bbaf6..3d434ef5eae3 100644
--- a/arch/sparc/include/asm/dma.h
+++ b/arch/sparc/include/asm/dma.h
@@ -92,27 +92,31 @@ extern int isa_dma_bridge_buggy;
92#ifdef CONFIG_SPARC32 92#ifdef CONFIG_SPARC32
93 93
94/* Routines for data transfer buffers. */ 94/* Routines for data transfer buffers. */
95BTFIXUPDEF_CALL(char *, mmu_lockarea, char *, unsigned long)
96BTFIXUPDEF_CALL(void, mmu_unlockarea, char *, unsigned long)
97
98#define mmu_lockarea(vaddr,len) BTFIXUP_CALL(mmu_lockarea)(vaddr,len)
99#define mmu_unlockarea(vaddr,len) BTFIXUP_CALL(mmu_unlockarea)(vaddr,len)
100
101struct page;
102struct device; 95struct device;
103struct scatterlist; 96struct scatterlist;
104 97
105/* These are implementations for sbus_map_sg/sbus_unmap_sg... collapse later */ 98struct sparc32_dma_ops {
106BTFIXUPDEF_CALL(__u32, mmu_get_scsi_one, struct device *, char *, unsigned long) 99 __u32 (*get_scsi_one)(struct device *, char *, unsigned long);
107BTFIXUPDEF_CALL(void, mmu_get_scsi_sgl, struct device *, struct scatterlist *, int) 100 void (*get_scsi_sgl)(struct device *, struct scatterlist *, int);
108BTFIXUPDEF_CALL(void, mmu_release_scsi_one, struct device *, __u32, unsigned long) 101 void (*release_scsi_one)(struct device *, __u32, unsigned long);
109BTFIXUPDEF_CALL(void, mmu_release_scsi_sgl, struct device *, struct scatterlist *, int) 102 void (*release_scsi_sgl)(struct device *, struct scatterlist *,int);
110 103#ifdef CONFIG_SBUS
111#define mmu_get_scsi_one(dev,vaddr,len) BTFIXUP_CALL(mmu_get_scsi_one)(dev,vaddr,len) 104 int (*map_dma_area)(struct device *, dma_addr_t *, unsigned long, unsigned long, int);
112#define mmu_get_scsi_sgl(dev,sg,sz) BTFIXUP_CALL(mmu_get_scsi_sgl)(dev,sg,sz) 105 void (*unmap_dma_area)(struct device *, unsigned long, int);
113#define mmu_release_scsi_one(dev,vaddr,len) BTFIXUP_CALL(mmu_release_scsi_one)(dev,vaddr,len) 106#endif
114#define mmu_release_scsi_sgl(dev,sg,sz) BTFIXUP_CALL(mmu_release_scsi_sgl)(dev,sg,sz) 107};
115 108extern const struct sparc32_dma_ops *sparc32_dma_ops;
109
110#define mmu_get_scsi_one(dev,vaddr,len) \
111 sparc32_dma_ops->get_scsi_one(dev, vaddr, len)
112#define mmu_get_scsi_sgl(dev,sg,sz) \
113 sparc32_dma_ops->get_scsi_sgl(dev, sg, sz)
114#define mmu_release_scsi_one(dev,vaddr,len) \
115 sparc32_dma_ops->release_scsi_one(dev, vaddr,len)
116#define mmu_release_scsi_sgl(dev,sg,sz) \
117 sparc32_dma_ops->release_scsi_sgl(dev, sg, sz)
118
119#ifdef CONFIG_SBUS
116/* 120/*
117 * mmu_map/unmap are provided by iommu/iounit; Invalid to call on IIep. 121 * mmu_map/unmap are provided by iommu/iounit; Invalid to call on IIep.
118 * 122 *
@@ -123,17 +127,17 @@ BTFIXUPDEF_CALL(void, mmu_release_scsi_sgl, struct device *, struct scatterlist
123 * Second mapping is for device visible address, or "bus" address. 127 * Second mapping is for device visible address, or "bus" address.
124 * The bus address is returned at '*pba'. 128 * The bus address is returned at '*pba'.
125 * 129 *
126 * These functions seem distinct, but are hard to split. On sun4c, 130 * These functions seem distinct, but are hard to split.
127 * at least for now, 'a' is equal to bus address, and retured in *pba.
128 * On sun4m, page attributes depend on the CPU type, so we have to 131 * On sun4m, page attributes depend on the CPU type, so we have to
129 * know if we are mapping RAM or I/O, so it has to be an additional argument 132 * know if we are mapping RAM or I/O, so it has to be an additional argument
130 * to a separate mapping function for CPU visible mappings. 133 * to a separate mapping function for CPU visible mappings.
131 */ 134 */
132BTFIXUPDEF_CALL(int, mmu_map_dma_area, struct device *, dma_addr_t *, unsigned long, unsigned long, int len) 135#define sbus_map_dma_area(dev,pba,va,a,len) \
133BTFIXUPDEF_CALL(void, mmu_unmap_dma_area, struct device *, unsigned long busa, int len) 136 sparc32_dma_ops->map_dma_area(dev, pba, va, a, len)
137#define sbus_unmap_dma_area(dev,ba,len) \
138 sparc32_dma_ops->unmap_dma_area(dev, ba, len)
139#endif /* CONFIG_SBUS */
134 140
135#define mmu_map_dma_area(dev,pba,va,a,len) BTFIXUP_CALL(mmu_map_dma_area)(dev,pba,va,a,len)
136#define mmu_unmap_dma_area(dev,ba,len) BTFIXUP_CALL(mmu_unmap_dma_area)(dev,ba,len)
137#endif 141#endif
138 142
139#endif /* !(_ASM_SPARC_DMA_H) */ 143#endif /* !(_ASM_SPARC_DMA_H) */
diff --git a/arch/sparc/include/asm/elf_32.h b/arch/sparc/include/asm/elf_32.h
index 4269ca6ad18a..2d4d755cba9e 100644
--- a/arch/sparc/include/asm/elf_32.h
+++ b/arch/sparc/include/asm/elf_32.h
@@ -118,16 +118,9 @@ typedef struct {
118 instruction set this cpu supports. This can NOT be done in userspace 118 instruction set this cpu supports. This can NOT be done in userspace
119 on Sparc. */ 119 on Sparc. */
120 120
121/* Sun4c has none of the capabilities, most sun4m's have them all. 121/* Most sun4m's have them all. */
122 * XXX This is gross, set some global variable at boot time. -DaveM 122#define ELF_HWCAP (HWCAP_SPARC_FLUSH | HWCAP_SPARC_STBAR | \
123 */ 123 HWCAP_SPARC_SWAP | HWCAP_SPARC_MULDIV)
124#define ELF_HWCAP ((ARCH_SUN4C) ? 0 : \
125 (HWCAP_SPARC_FLUSH | HWCAP_SPARC_STBAR | \
126 HWCAP_SPARC_SWAP | \
127 ((srmmu_modtype != Cypress && \
128 srmmu_modtype != Cypress_vE && \
129 srmmu_modtype != Cypress_vD) ? \
130 HWCAP_SPARC_MULDIV : 0)))
131 124
132/* This yields a string that ld.so will use to load implementation 125/* This yields a string that ld.so will use to load implementation
133 specific libraries for optimization. This is more specific in 126 specific libraries for optimization. This is more specific in
diff --git a/arch/sparc/include/asm/floppy_32.h b/arch/sparc/include/asm/floppy_32.h
index 698d9559fead..fb3f16954c69 100644
--- a/arch/sparc/include/asm/floppy_32.h
+++ b/arch/sparc/include/asm/floppy_32.h
@@ -12,7 +12,6 @@
12#include <asm/page.h> 12#include <asm/page.h>
13#include <asm/pgtable.h> 13#include <asm/pgtable.h>
14#include <asm/idprom.h> 14#include <asm/idprom.h>
15#include <asm/machines.h>
16#include <asm/oplib.h> 15#include <asm/oplib.h>
17#include <asm/auxio.h> 16#include <asm/auxio.h>
18#include <asm/irq.h> 17#include <asm/irq.h>
@@ -103,25 +102,13 @@ static struct sun_floppy_ops sun_fdops;
103/* Routines unique to each controller type on a Sun. */ 102/* Routines unique to each controller type on a Sun. */
104static void sun_set_dor(unsigned char value, int fdc_82077) 103static void sun_set_dor(unsigned char value, int fdc_82077)
105{ 104{
106 if (sparc_cpu_model == sun4c) { 105 if (fdc_82077)
107 unsigned int bits = 0;
108 if (value & 0x10)
109 bits |= AUXIO_FLPY_DSEL;
110 if ((value & 0x80) == 0)
111 bits |= AUXIO_FLPY_EJCT;
112 set_auxio(bits, (~bits) & (AUXIO_FLPY_DSEL|AUXIO_FLPY_EJCT));
113 }
114 if (fdc_82077) {
115 sun_fdc->dor_82077 = value; 106 sun_fdc->dor_82077 = value;
116 }
117} 107}
118 108
119static unsigned char sun_read_dir(void) 109static unsigned char sun_read_dir(void)
120{ 110{
121 if (sparc_cpu_model == sun4c) 111 return sun_fdc->dir_82077;
122 return (get_auxio() & AUXIO_FLPY_DCHG) ? 0x80 : 0;
123 else
124 return sun_fdc->dir_82077;
125} 112}
126 113
127static unsigned char sun_82072_fd_inb(int port) 114static unsigned char sun_82072_fd_inb(int port)
@@ -242,10 +229,7 @@ static inline void virtual_dma_init(void)
242static inline void sun_fd_disable_dma(void) 229static inline void sun_fd_disable_dma(void)
243{ 230{
244 doing_pdma = 0; 231 doing_pdma = 0;
245 if (pdma_base) { 232 pdma_base = NULL;
246 mmu_unlockarea(pdma_base, pdma_areasize);
247 pdma_base = NULL;
248 }
249} 233}
250 234
251static inline void sun_fd_set_dma_mode(int mode) 235static inline void sun_fd_set_dma_mode(int mode)
@@ -275,7 +259,6 @@ static inline void sun_fd_set_dma_count(int length)
275 259
276static inline void sun_fd_enable_dma(void) 260static inline void sun_fd_enable_dma(void)
277{ 261{
278 pdma_vaddr = mmu_lockarea(pdma_vaddr, pdma_size);
279 pdma_base = pdma_vaddr; 262 pdma_base = pdma_vaddr;
280 pdma_areasize = pdma_size; 263 pdma_areasize = pdma_size;
281} 264}
@@ -301,38 +284,36 @@ static int sun_floppy_init(void)
301{ 284{
302 struct platform_device *op; 285 struct platform_device *op;
303 struct device_node *dp; 286 struct device_node *dp;
287 struct resource r;
304 char state[128]; 288 char state[128];
305 phandle tnode, fd_node; 289 phandle fd_node;
290 phandle tnode;
306 int num_regs; 291 int num_regs;
307 struct resource r;
308 292
309 use_virtual_dma = 1; 293 use_virtual_dma = 1;
310 294
311 /* Forget it if we aren't on a machine that could possibly 295 /* Forget it if we aren't on a machine that could possibly
312 * ever have a floppy drive. 296 * ever have a floppy drive.
313 */ 297 */
314 if((sparc_cpu_model != sun4c && sparc_cpu_model != sun4m) || 298 if (sparc_cpu_model != sun4m) {
315 ((idprom->id_machtype == (SM_SUN4C | SM_4C_SLC)) ||
316 (idprom->id_machtype == (SM_SUN4C | SM_4C_ELC)))) {
317 /* We certainly don't have a floppy controller. */ 299 /* We certainly don't have a floppy controller. */
318 goto no_sun_fdc; 300 goto no_sun_fdc;
319 } 301 }
320 /* Well, try to find one. */ 302 /* Well, try to find one. */
321 tnode = prom_getchild(prom_root_node); 303 tnode = prom_getchild(prom_root_node);
322 fd_node = prom_searchsiblings(tnode, "obio"); 304 fd_node = prom_searchsiblings(tnode, "obio");
323 if(fd_node != 0) { 305 if (fd_node != 0) {
324 tnode = prom_getchild(fd_node); 306 tnode = prom_getchild(fd_node);
325 fd_node = prom_searchsiblings(tnode, "SUNW,fdtwo"); 307 fd_node = prom_searchsiblings(tnode, "SUNW,fdtwo");
326 } else { 308 } else {
327 fd_node = prom_searchsiblings(tnode, "fd"); 309 fd_node = prom_searchsiblings(tnode, "fd");
328 } 310 }
329 if(fd_node == 0) { 311 if (fd_node == 0) {
330 goto no_sun_fdc; 312 goto no_sun_fdc;
331 } 313 }
332 314
333 /* The sun4m lets us know if the controller is actually usable. */ 315 /* The sun4m lets us know if the controller is actually usable. */
334 if(sparc_cpu_model == sun4m && 316 if (prom_getproperty(fd_node, "status", state, sizeof(state)) != -1) {
335 prom_getproperty(fd_node, "status", state, sizeof(state)) != -1) {
336 if(!strcmp(state, "disabled")) { 317 if(!strcmp(state, "disabled")) {
337 goto no_sun_fdc; 318 goto no_sun_fdc;
338 } 319 }
@@ -343,12 +324,12 @@ static int sun_floppy_init(void)
343 memset(&r, 0, sizeof(r)); 324 memset(&r, 0, sizeof(r));
344 r.flags = fd_regs[0].which_io; 325 r.flags = fd_regs[0].which_io;
345 r.start = fd_regs[0].phys_addr; 326 r.start = fd_regs[0].phys_addr;
346 sun_fdc = (struct sun_flpy_controller *) 327 sun_fdc = of_ioremap(&r, 0, fd_regs[0].reg_size, "floppy");
347 of_ioremap(&r, 0, fd_regs[0].reg_size, "floppy");
348 328
349 /* Look up irq in platform_device. 329 /* Look up irq in platform_device.
350 * We try "SUNW,fdtwo" and "fd" 330 * We try "SUNW,fdtwo" and "fd"
351 */ 331 */
332 op = NULL;
352 for_each_node_by_name(dp, "SUNW,fdtwo") { 333 for_each_node_by_name(dp, "SUNW,fdtwo") {
353 op = of_find_device_by_node(dp); 334 op = of_find_device_by_node(dp);
354 if (op) 335 if (op)
@@ -367,7 +348,7 @@ static int sun_floppy_init(void)
367 FLOPPY_IRQ = op->archdata.irqs[0]; 348 FLOPPY_IRQ = op->archdata.irqs[0];
368 349
369 /* Last minute sanity check... */ 350 /* Last minute sanity check... */
370 if(sun_fdc->status_82072 == 0xff) { 351 if (sun_fdc->status_82072 == 0xff) {
371 sun_fdc = NULL; 352 sun_fdc = NULL;
372 goto no_sun_fdc; 353 goto no_sun_fdc;
373 } 354 }
diff --git a/arch/sparc/include/asm/floppy_64.h b/arch/sparc/include/asm/floppy_64.h
index bcef1f5a2a6d..e204f902e6c9 100644
--- a/arch/sparc/include/asm/floppy_64.h
+++ b/arch/sparc/include/asm/floppy_64.h
@@ -161,10 +161,7 @@ unsigned long pdma_areasize;
161static void sun_fd_disable_dma(void) 161static void sun_fd_disable_dma(void)
162{ 162{
163 doing_pdma = 0; 163 doing_pdma = 0;
164 if (pdma_base) { 164 pdma_base = NULL;
165 mmu_unlockarea(pdma_base, pdma_areasize);
166 pdma_base = NULL;
167 }
168} 165}
169 166
170static void sun_fd_set_dma_mode(int mode) 167static void sun_fd_set_dma_mode(int mode)
@@ -194,7 +191,6 @@ static void sun_fd_set_dma_count(int length)
194 191
195static void sun_fd_enable_dma(void) 192static void sun_fd_enable_dma(void)
196{ 193{
197 pdma_vaddr = mmu_lockarea(pdma_vaddr, pdma_size);
198 pdma_base = pdma_vaddr; 194 pdma_base = pdma_vaddr;
199 pdma_areasize = pdma_size; 195 pdma_areasize = pdma_size;
200} 196}
diff --git a/arch/sparc/include/asm/head_32.h b/arch/sparc/include/asm/head_32.h
index 7c35491a8b53..a76874838f61 100644
--- a/arch/sparc/include/asm/head_32.h
+++ b/arch/sparc/include/asm/head_32.h
@@ -2,15 +2,8 @@
2#define __SPARC_HEAD_H 2#define __SPARC_HEAD_H
3 3
4#define KERNBASE 0xf0000000 /* First address the kernel will eventually be */ 4#define KERNBASE 0xf0000000 /* First address the kernel will eventually be */
5#define LOAD_ADDR 0x4000 /* prom jumps to us here unless this is elf /boot */
6#define SUN4C_SEGSZ (1 << 18)
7#define SRMMU_L1_KBASE_OFFSET ((KERNBASE>>24)<<2) /* Used in boot remapping. */
8#define INTS_ENAB 0x01 /* entry.S uses this. */
9
10#define SUN4_PROM_VECTOR 0xFFE81000 /* SUN4 PROM needs to be hardwired */
11 5
12#define WRITE_PAUSE nop; nop; nop; /* Have to do this after %wim/%psr chg */ 6#define WRITE_PAUSE nop; nop; nop; /* Have to do this after %wim/%psr chg */
13#define NOP_INSN 0x01000000 /* Used to patch sparc_save_state */
14 7
15/* Here are some trap goodies */ 8/* Here are some trap goodies */
16 9
@@ -18,9 +11,7 @@
18#define TRAP_ENTRY(type, label) \ 11#define TRAP_ENTRY(type, label) \
19 rd %psr, %l0; b label; rd %wim, %l3; nop; 12 rd %psr, %l0; b label; rd %wim, %l3; nop;
20 13
21/* Data/text faults. Defaults to sun4c version at boot time. */ 14/* Data/text faults */
22#define SPARC_TFAULT rd %psr, %l0; rd %wim, %l3; b sun4c_fault; mov 1, %l7;
23#define SPARC_DFAULT rd %psr, %l0; rd %wim, %l3; b sun4c_fault; mov 0, %l7;
24#define SRMMU_TFAULT rd %psr, %l0; rd %wim, %l3; b srmmu_fault; mov 1, %l7; 15#define SRMMU_TFAULT rd %psr, %l0; rd %wim, %l3; b srmmu_fault; mov 1, %l7;
25#define SRMMU_DFAULT rd %psr, %l0; rd %wim, %l3; b srmmu_fault; mov 0, %l7; 16#define SRMMU_DFAULT rd %psr, %l0; rd %wim, %l3; b srmmu_fault; mov 0, %l7;
26 17
@@ -80,16 +71,6 @@
80#define TRAP_ENTRY_INTERRUPT(int_level) \ 71#define TRAP_ENTRY_INTERRUPT(int_level) \
81 mov int_level, %l7; rd %psr, %l0; b real_irq_entry; rd %wim, %l3; 72 mov int_level, %l7; rd %psr, %l0; b real_irq_entry; rd %wim, %l3;
82 73
83/* NMI's (Non Maskable Interrupts) are special, you can't keep them
84 * from coming in, and basically if you get one, the shows over. ;(
85 * On the sun4c they are usually asynchronous memory errors, on the
86 * the sun4m they could be either due to mem errors or a software
87 * initiated interrupt from the prom/kern on an SMP box saying "I
88 * command you to do CPU tricks, read your mailbox for more info."
89 */
90#define NMI_TRAP \
91 rd %wim, %l3; b linux_trap_nmi_sun4c; mov %psr, %l0; nop;
92
93/* Window overflows/underflows are special and we need to try to be as 74/* Window overflows/underflows are special and we need to try to be as
94 * efficient as possible here.... 75 * efficient as possible here....
95 */ 76 */
diff --git a/arch/sparc/include/asm/leon.h b/arch/sparc/include/asm/leon.h
index a4e457f003ed..24f802beffb9 100644
--- a/arch/sparc/include/asm/leon.h
+++ b/arch/sparc/include/asm/leon.h
@@ -10,19 +10,6 @@
10 10
11#ifdef CONFIG_SPARC_LEON 11#ifdef CONFIG_SPARC_LEON
12 12
13#define ASI_LEON_NOCACHE 0x01
14
15#define ASI_LEON_DCACHE_MISS 0x1
16
17#define ASI_LEON_CACHEREGS 0x02
18#define ASI_LEON_IFLUSH 0x10
19#define ASI_LEON_DFLUSH 0x11
20
21#define ASI_LEON_MMUFLUSH 0x18
22#define ASI_LEON_MMUREGS 0x19
23#define ASI_LEON_BYPASS 0x1c
24#define ASI_LEON_FLUSH_PAGE 0x10
25
26/* mmu register access, ASI_LEON_MMUREGS */ 13/* mmu register access, ASI_LEON_MMUREGS */
27#define LEON_CNR_CTRL 0x000 14#define LEON_CNR_CTRL 0x000
28#define LEON_CNR_CTXP 0x100 15#define LEON_CNR_CTXP 0x100
@@ -57,29 +44,6 @@
57#define LEON_IRQMASK_R 0x0000fffe /* bit 15- 1 of lregs.irqmask */ 44#define LEON_IRQMASK_R 0x0000fffe /* bit 15- 1 of lregs.irqmask */
58#define LEON_IRQPRIO_R 0xfffe0000 /* bit 31-17 of lregs.irqmask */ 45#define LEON_IRQPRIO_R 0xfffe0000 /* bit 31-17 of lregs.irqmask */
59 46
60/* leon uart register definitions */
61#define LEON_OFF_UDATA 0x0
62#define LEON_OFF_USTAT 0x4
63#define LEON_OFF_UCTRL 0x8
64#define LEON_OFF_USCAL 0xc
65
66#define LEON_UCTRL_RE 0x01
67#define LEON_UCTRL_TE 0x02
68#define LEON_UCTRL_RI 0x04
69#define LEON_UCTRL_TI 0x08
70#define LEON_UCTRL_PS 0x10
71#define LEON_UCTRL_PE 0x20
72#define LEON_UCTRL_FL 0x40
73#define LEON_UCTRL_LB 0x80
74
75#define LEON_USTAT_DR 0x01
76#define LEON_USTAT_TS 0x02
77#define LEON_USTAT_TH 0x04
78#define LEON_USTAT_BR 0x08
79#define LEON_USTAT_OV 0x10
80#define LEON_USTAT_PE 0x20
81#define LEON_USTAT_FE 0x40
82
83#define LEON_MCFG2_SRAMDIS 0x00002000 47#define LEON_MCFG2_SRAMDIS 0x00002000
84#define LEON_MCFG2_SDRAMEN 0x00004000 48#define LEON_MCFG2_SDRAMEN 0x00004000
85#define LEON_MCFG2_SRAMBANKSZ 0x00001e00 /* [12-9] */ 49#define LEON_MCFG2_SRAMBANKSZ 0x00001e00 /* [12-9] */
@@ -89,8 +53,6 @@
89 53
90#define LEON_TCNT0_MASK 0x7fffff 54#define LEON_TCNT0_MASK 0x7fffff
91 55
92#define LEON_USTAT_ERROR (LEON_USTAT_OV | LEON_USTAT_PE | LEON_USTAT_FE)
93/* no break yet */
94 56
95#define ASI_LEON3_SYSCTRL 0x02 57#define ASI_LEON3_SYSCTRL 0x02
96#define ASI_LEON3_SYSCTRL_ICFG 0x08 58#define ASI_LEON3_SYSCTRL_ICFG 0x08
@@ -278,18 +240,11 @@ static inline int sparc_leon3_cpuid(void)
278#define LEON2_CFG_SSIZE_MASK 0x00007000UL 240#define LEON2_CFG_SSIZE_MASK 0x00007000UL
279 241
280#ifndef __ASSEMBLY__ 242#ifndef __ASSEMBLY__
281extern unsigned long srmmu_swprobe(unsigned long vaddr, unsigned long *paddr);
282extern void leon_flush_icache_all(void);
283extern void leon_flush_dcache_all(void);
284extern void leon_flush_cache_all(void);
285extern void leon_flush_tlb_all(void);
286extern int leon_flush_during_switch;
287extern int leon_flush_needed(void);
288
289struct vm_area_struct; 243struct vm_area_struct;
244
245extern unsigned long srmmu_swprobe(unsigned long vaddr, unsigned long *paddr);
290extern void leon_flush_icache_all(void); 246extern void leon_flush_icache_all(void);
291extern void leon_flush_dcache_all(void); 247extern void leon_flush_dcache_all(void);
292extern void leon_flush_pcache_all(struct vm_area_struct *vma, unsigned long page);
293extern void leon_flush_cache_all(void); 248extern void leon_flush_cache_all(void);
294extern void leon_flush_tlb_all(void); 249extern void leon_flush_tlb_all(void);
295extern int leon_flush_during_switch; 250extern int leon_flush_during_switch;
@@ -321,22 +276,12 @@ extern unsigned int leon_build_device_irq(unsigned int real_irq,
321extern void leon_update_virq_handling(unsigned int virq, 276extern void leon_update_virq_handling(unsigned int virq,
322 irq_flow_handler_t flow_handler, 277 irq_flow_handler_t flow_handler,
323 const char *name, int do_ack); 278 const char *name, int do_ack);
324extern void leon_clear_clock_irq(void); 279extern void leon_init_timers(void);
325extern void leon_load_profile_irq(int cpu, unsigned int limit);
326extern void leon_init_timers(irq_handler_t counter_fn);
327extern void leon_clear_clock_irq(void);
328extern void leon_load_profile_irq(int cpu, unsigned int limit);
329extern void leon_trans_init(struct device_node *dp); 280extern void leon_trans_init(struct device_node *dp);
330extern void leon_node_init(struct device_node *dp, struct device_node ***nextp); 281extern void leon_node_init(struct device_node *dp, struct device_node ***nextp);
331extern void leon_init_IRQ(void);
332extern void leon_init(void);
333extern unsigned long srmmu_swprobe(unsigned long vaddr, unsigned long *paddr);
334extern void init_leon(void); 282extern void init_leon(void);
335extern void poke_leonsparc(void); 283extern void poke_leonsparc(void);
336extern void leon3_getCacheRegs(struct leon3_cacheregs *regs); 284extern void leon3_getCacheRegs(struct leon3_cacheregs *regs);
337extern int leon_flush_needed(void);
338extern void leon_switch_mm(void);
339extern int srmmu_swprobe_trace;
340extern int leon3_ticker_irq; 285extern int leon3_ticker_irq;
341 286
342#ifdef CONFIG_SMP 287#ifdef CONFIG_SMP
diff --git a/arch/sparc/include/asm/machines.h b/arch/sparc/include/asm/machines.h
index cd9c099567e4..fd6ddb05d1b7 100644
--- a/arch/sparc/include/asm/machines.h
+++ b/arch/sparc/include/asm/machines.h
@@ -12,11 +12,6 @@ struct Sun_Machine_Models {
12 unsigned char id_machtype; 12 unsigned char id_machtype;
13}; 13};
14 14
15/* Current number of machines we know about that has an IDPROM
16 * machtype entry including one entry for the 0x80 OBP machines.
17 */
18#define NUM_SUN_MACHINES 16
19
20/* The machine type in the idprom area looks like this: 15/* The machine type in the idprom area looks like this:
21 * 16 *
22 * --------------- 17 * ---------------
@@ -24,36 +19,20 @@ struct Sun_Machine_Models {
24 * --------------- 19 * ---------------
25 * 7 4 3 0 20 * 7 4 3 0
26 * 21 *
27 * The ARCH field determines the architecture line (sun4, sun4c, etc). 22 * The ARCH field determines the architecture line (sun4m, etc).
28 * The MACH field determines the machine make within that architecture. 23 * The MACH field determines the machine make within that architecture.
29 */ 24 */
30 25
31#define SM_ARCH_MASK 0xf0 26#define SM_ARCH_MASK 0xf0
32#define SM_SUN4 0x20
33#define M_LEON 0x30 27#define M_LEON 0x30
34#define SM_SUN4C 0x50
35#define SM_SUN4M 0x70 28#define SM_SUN4M 0x70
36#define SM_SUN4M_OBP 0x80 29#define SM_SUN4M_OBP 0x80
37 30
38#define SM_TYP_MASK 0x0f 31#define SM_TYP_MASK 0x0f
39/* Sun4 machines */
40#define SM_4_260 0x01 /* Sun 4/200 series */
41#define SM_4_110 0x02 /* Sun 4/100 series */
42#define SM_4_330 0x03 /* Sun 4/300 series */
43#define SM_4_470 0x04 /* Sun 4/400 series */
44 32
45/* Leon machines */ 33/* Leon machines */
46#define M_LEON3_SOC 0x02 /* Leon3 SoC */ 34#define M_LEON3_SOC 0x02 /* Leon3 SoC */
47 35
48/* Sun4c machines Full Name - PROM NAME */
49#define SM_4C_SS1 0x01 /* Sun4c SparcStation 1 - Sun 4/60 */
50#define SM_4C_IPC 0x02 /* Sun4c SparcStation IPC - Sun 4/40 */
51#define SM_4C_SS1PLUS 0x03 /* Sun4c SparcStation 1+ - Sun 4/65 */
52#define SM_4C_SLC 0x04 /* Sun4c SparcStation SLC - Sun 4/20 */
53#define SM_4C_SS2 0x05 /* Sun4c SparcStation 2 - Sun 4/75 */
54#define SM_4C_ELC 0x06 /* Sun4c SparcStation ELC - Sun 4/25 */
55#define SM_4C_IPX 0x07 /* Sun4c SparcStation IPX - Sun 4/50 */
56
57/* Sun4m machines, these predate the OpenBoot. These values only mean 36/* Sun4m machines, these predate the OpenBoot. These values only mean
58 * something if the value in the ARCH field is SM_SUN4M, if it is 37 * something if the value in the ARCH field is SM_SUN4M, if it is
59 * SM_SUN4M_OBP then you have the following situation: 38 * SM_SUN4M_OBP then you have the following situation:
diff --git a/arch/sparc/include/asm/mbus.h b/arch/sparc/include/asm/mbus.h
index 69f07a022ee6..14128bcc5821 100644
--- a/arch/sparc/include/asm/mbus.h
+++ b/arch/sparc/include/asm/mbus.h
@@ -8,14 +8,10 @@
8#define _SPARC_MBUS_H 8#define _SPARC_MBUS_H
9 9
10#include <asm/ross.h> /* HyperSparc stuff */ 10#include <asm/ross.h> /* HyperSparc stuff */
11#include <asm/cypress.h> /* Cypress Chips */
12#include <asm/viking.h> /* Ugh, bug city... */ 11#include <asm/viking.h> /* Ugh, bug city... */
13 12
14enum mbus_module { 13enum mbus_module {
15 HyperSparc = 0, 14 HyperSparc = 0,
16 Cypress = 1,
17 Cypress_vE = 2,
18 Cypress_vD = 3,
19 Swift_ok = 4, 15 Swift_ok = 4,
20 Swift_bad_c = 5, 16 Swift_bad_c = 5,
21 Swift_lots_o_bugs = 6, 17 Swift_lots_o_bugs = 6,
diff --git a/arch/sparc/include/asm/memreg.h b/arch/sparc/include/asm/memreg.h
deleted file mode 100644
index 845ad2b39183..000000000000
--- a/arch/sparc/include/asm/memreg.h
+++ /dev/null
@@ -1,51 +0,0 @@
1#ifndef _SPARC_MEMREG_H
2#define _SPARC_MEMREG_H
3/* memreg.h: Definitions of the values found in the synchronous
4 * and asynchronous memory error registers when a fault
5 * occurs on the sun4c.
6 *
7 * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
8 */
9
10/* First the synchronous error codes, these are usually just
11 * normal page faults.
12 */
13
14#define SUN4C_SYNC_WDRESET 0x0001 /* watchdog reset */
15#define SUN4C_SYNC_SIZE 0x0002 /* bad access size? whuz this? */
16#define SUN4C_SYNC_PARITY 0x0008 /* bad ram chips caused a parity error */
17#define SUN4C_SYNC_SBUS 0x0010 /* the SBUS had some problems... */
18#define SUN4C_SYNC_NOMEM 0x0020 /* translation to non-existent ram */
19#define SUN4C_SYNC_PROT 0x0040 /* access violated pte protections */
20#define SUN4C_SYNC_NPRESENT 0x0080 /* pte said that page was not present */
21#define SUN4C_SYNC_BADWRITE 0x8000 /* while writing something went bogus */
22
23#define SUN4C_SYNC_BOLIXED \
24 (SUN4C_SYNC_WDRESET | SUN4C_SYNC_SIZE | SUN4C_SYNC_SBUS | \
25 SUN4C_SYNC_NOMEM | SUN4C_SYNC_PARITY)
26
27/* Now the asynchronous error codes, these are almost always produced
28 * by the cache writing things back to memory and getting a bad translation.
29 * Bad DVMA transactions can cause these faults too.
30 */
31
32#define SUN4C_ASYNC_BADDVMA 0x0010 /* error during DVMA access */
33#define SUN4C_ASYNC_NOMEM 0x0020 /* write back pointed to bad phys addr */
34#define SUN4C_ASYNC_BADWB 0x0080 /* write back points to non-present page */
35
36/* Memory parity error register with associated bit constants. */
37#ifndef __ASSEMBLY__
38extern __volatile__ unsigned long __iomem *sun4c_memerr_reg;
39#endif
40
41#define SUN4C_MPE_ERROR 0x80 /* Parity error detected. (ro) */
42#define SUN4C_MPE_MULTI 0x40 /* Multiple parity errors detected. (ro) */
43#define SUN4C_MPE_TEST 0x20 /* Write inverse parity. (rw) */
44#define SUN4C_MPE_CHECK 0x10 /* Enable parity checking. (rw) */
45#define SUN4C_MPE_ERR00 0x08 /* Parity error in bits 0-7. (ro) */
46#define SUN4C_MPE_ERR08 0x04 /* Parity error in bits 8-15. (ro) */
47#define SUN4C_MPE_ERR16 0x02 /* Parity error in bits 16-23. (ro) */
48#define SUN4C_MPE_ERR24 0x01 /* Parity error in bits 24-31. (ro) */
49#define SUN4C_MPE_ERRS 0x0F /* Bit mask for the error bits. (ro) */
50
51#endif /* !(_SPARC_MEMREG_H) */
diff --git a/arch/sparc/include/asm/mmu_context_32.h b/arch/sparc/include/asm/mmu_context_32.h
index 671a997b9e69..01456c900720 100644
--- a/arch/sparc/include/asm/mmu_context_32.h
+++ b/arch/sparc/include/asm/mmu_context_32.h
@@ -1,8 +1,6 @@
1#ifndef __SPARC_MMU_CONTEXT_H 1#ifndef __SPARC_MMU_CONTEXT_H
2#define __SPARC_MMU_CONTEXT_H 2#define __SPARC_MMU_CONTEXT_H
3 3
4#include <asm/btfixup.h>
5
6#ifndef __ASSEMBLY__ 4#ifndef __ASSEMBLY__
7 5
8#include <asm-generic/mm_hooks.h> 6#include <asm-generic/mm_hooks.h>
@@ -23,14 +21,11 @@ static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)
23 * all the page tables have been flushed. Our job is to destroy 21 * all the page tables have been flushed. Our job is to destroy
24 * any remaining processor-specific state. 22 * any remaining processor-specific state.
25 */ 23 */
26BTFIXUPDEF_CALL(void, destroy_context, struct mm_struct *) 24void destroy_context(struct mm_struct *mm);
27
28#define destroy_context(mm) BTFIXUP_CALL(destroy_context)(mm)
29 25
30/* Switch the current MM context. */ 26/* Switch the current MM context. */
31BTFIXUPDEF_CALL(void, switch_mm, struct mm_struct *, struct mm_struct *, struct task_struct *) 27void switch_mm(struct mm_struct *old_mm, struct mm_struct *mm,
32 28 struct task_struct *tsk);
33#define switch_mm(old_mm, mm, tsk) BTFIXUP_CALL(switch_mm)(old_mm, mm, tsk)
34 29
35#define deactivate_mm(tsk,mm) do { } while (0) 30#define deactivate_mm(tsk,mm) do { } while (0)
36 31
diff --git a/arch/sparc/include/asm/obio.h b/arch/sparc/include/asm/obio.h
index 4ade0c8a2c79..910c1d9af1f8 100644
--- a/arch/sparc/include/asm/obio.h
+++ b/arch/sparc/include/asm/obio.h
@@ -220,19 +220,6 @@ static inline void cc_set_igen(unsigned gen)
220 "i" (ASI_M_MXCC)); 220 "i" (ASI_M_MXCC));
221} 221}
222 222
223/* +-------+-------------+-----------+------------------------------------+
224 * | bcast | devid | sid | levels mask |
225 * +-------+-------------+-----------+------------------------------------+
226 * 31 30 23 22 15 14 0
227 */
228#define IGEN_MESSAGE(bcast, devid, sid, levels) \
229 (((bcast) << 31) | ((devid) << 23) | ((sid) << 15) | (levels))
230
231static inline void sun4d_send_ipi(int cpu, int level)
232{
233 cc_set_igen(IGEN_MESSAGE(0, cpu << 3, 6 + ((level >> 1) & 7), 1 << (level - 1)));
234}
235
236#endif /* !__ASSEMBLY__ */ 223#endif /* !__ASSEMBLY__ */
237 224
238#endif /* !(_SPARC_OBIO_H) */ 225#endif /* !(_SPARC_OBIO_H) */
diff --git a/arch/sparc/include/asm/oplib_32.h b/arch/sparc/include/asm/oplib_32.h
index 71e5e9aeb67e..27517879a6c2 100644
--- a/arch/sparc/include/asm/oplib_32.h
+++ b/arch/sparc/include/asm/oplib_32.h
@@ -105,14 +105,6 @@ extern void prom_write(const char *buf, unsigned int len);
105extern int prom_startcpu(int cpunode, struct linux_prom_registers *context_table, 105extern int prom_startcpu(int cpunode, struct linux_prom_registers *context_table,
106 int context, char *program_counter); 106 int context, char *program_counter);
107 107
108/* Sun4/sun4c specific memory-management startup hook. */
109
110/* Map the passed segment in the given context at the passed
111 * virtual address.
112 */
113extern void prom_putsegment(int context, unsigned long virt_addr,
114 int physical_segment);
115
116/* Initialize the memory lists based upon the prom version. */ 108/* Initialize the memory lists based upon the prom version. */
117void prom_meminit(void); 109void prom_meminit(void);
118 110
diff --git a/arch/sparc/include/asm/page_32.h b/arch/sparc/include/asm/page_32.h
index bb5c2ac4055d..fab78a308ebf 100644
--- a/arch/sparc/include/asm/page_32.h
+++ b/arch/sparc/include/asm/page_32.h
@@ -14,8 +14,6 @@
14#define PAGE_SIZE (_AC(1, UL) << PAGE_SHIFT) 14#define PAGE_SIZE (_AC(1, UL) << PAGE_SHIFT)
15#define PAGE_MASK (~(PAGE_SIZE-1)) 15#define PAGE_MASK (~(PAGE_SIZE-1))
16 16
17#include <asm/btfixup.h>
18
19#ifndef __ASSEMBLY__ 17#ifndef __ASSEMBLY__
20 18
21#define clear_page(page) memset((void *)(page), 0, PAGE_SIZE) 19#define clear_page(page) memset((void *)(page), 0, PAGE_SIZE)
@@ -45,12 +43,6 @@ struct sparc_phys_banks {
45 43
46extern struct sparc_phys_banks sp_banks[SPARC_PHYS_BANKS+1]; 44extern struct sparc_phys_banks sp_banks[SPARC_PHYS_BANKS+1];
47 45
48/* Cache alias structure. Entry is valid if context != -1. */
49struct cache_palias {
50 unsigned long vaddr;
51 int context;
52};
53
54/* passing structs on the Sparc slow us down tremendously... */ 46/* passing structs on the Sparc slow us down tremendously... */
55 47
56/* #define STRICT_MM_TYPECHECKS */ 48/* #define STRICT_MM_TYPECHECKS */
@@ -116,10 +108,7 @@ typedef unsigned long iopgprot_t;
116typedef struct page *pgtable_t; 108typedef struct page *pgtable_t;
117 109
118extern unsigned long sparc_unmapped_base; 110extern unsigned long sparc_unmapped_base;
119 111#define TASK_UNMAPPED_BASE sparc_unmapped_base
120BTFIXUPDEF_SETHI(sparc_unmapped_base)
121
122#define TASK_UNMAPPED_BASE BTFIXUP_SETHI(sparc_unmapped_base)
123 112
124#else /* !(__ASSEMBLY__) */ 113#else /* !(__ASSEMBLY__) */
125 114
diff --git a/arch/sparc/include/asm/pgalloc_32.h b/arch/sparc/include/asm/pgalloc_32.h
index ca2b34456c4b..e5b169b46d21 100644
--- a/arch/sparc/include/asm/pgalloc_32.h
+++ b/arch/sparc/include/asm/pgalloc_32.h
@@ -4,8 +4,10 @@
4#include <linux/kernel.h> 4#include <linux/kernel.h>
5#include <linux/sched.h> 5#include <linux/sched.h>
6 6
7#include <asm/pgtsrmmu.h>
8#include <asm/pgtable.h>
9#include <asm/vaddrs.h>
7#include <asm/page.h> 10#include <asm/page.h>
8#include <asm/btfixup.h>
9 11
10struct page; 12struct page;
11 13
@@ -15,54 +17,74 @@ extern struct pgtable_cache_struct {
15 unsigned long pgtable_cache_sz; 17 unsigned long pgtable_cache_sz;
16 unsigned long pgd_cache_sz; 18 unsigned long pgd_cache_sz;
17} pgt_quicklists; 19} pgt_quicklists;
20
21unsigned long srmmu_get_nocache(int size, int align);
22void srmmu_free_nocache(unsigned long vaddr, int size);
23
18#define pgd_quicklist (pgt_quicklists.pgd_cache) 24#define pgd_quicklist (pgt_quicklists.pgd_cache)
19#define pmd_quicklist ((unsigned long *)0) 25#define pmd_quicklist ((unsigned long *)0)
20#define pte_quicklist (pgt_quicklists.pte_cache) 26#define pte_quicklist (pgt_quicklists.pte_cache)
21#define pgtable_cache_size (pgt_quicklists.pgtable_cache_sz) 27#define pgtable_cache_size (pgt_quicklists.pgtable_cache_sz)
22#define pgd_cache_size (pgt_quicklists.pgd_cache_sz) 28#define pgd_cache_size (pgt_quicklists.pgd_cache_sz)
23 29
24extern void check_pgt_cache(void); 30#define check_pgt_cache() do { } while (0)
25BTFIXUPDEF_CALL(void, do_check_pgt_cache, int, int)
26#define do_check_pgt_cache(low,high) BTFIXUP_CALL(do_check_pgt_cache)(low,high)
27
28BTFIXUPDEF_CALL(pgd_t *, get_pgd_fast, void)
29#define get_pgd_fast() BTFIXUP_CALL(get_pgd_fast)()
30 31
31BTFIXUPDEF_CALL(void, free_pgd_fast, pgd_t *) 32pgd_t *get_pgd_fast(void);
32#define free_pgd_fast(pgd) BTFIXUP_CALL(free_pgd_fast)(pgd) 33static inline void free_pgd_fast(pgd_t *pgd)
34{
35 srmmu_free_nocache((unsigned long)pgd, SRMMU_PGD_TABLE_SIZE);
36}
33 37
34#define pgd_free(mm, pgd) free_pgd_fast(pgd) 38#define pgd_free(mm, pgd) free_pgd_fast(pgd)
35#define pgd_alloc(mm) get_pgd_fast() 39#define pgd_alloc(mm) get_pgd_fast()
36 40
37BTFIXUPDEF_CALL(void, pgd_set, pgd_t *, pmd_t *) 41static inline void pgd_set(pgd_t * pgdp, pmd_t * pmdp)
38#define pgd_set(pgdp,pmdp) BTFIXUP_CALL(pgd_set)(pgdp,pmdp) 42{
43 unsigned long pa = __nocache_pa((unsigned long)pmdp);
44
45 set_pte((pte_t *)pgdp, (SRMMU_ET_PTD | (pa >> 4)));
46}
47
39#define pgd_populate(MM, PGD, PMD) pgd_set(PGD, PMD) 48#define pgd_populate(MM, PGD, PMD) pgd_set(PGD, PMD)
40 49
41BTFIXUPDEF_CALL(pmd_t *, pmd_alloc_one, struct mm_struct *, unsigned long) 50static inline pmd_t *pmd_alloc_one(struct mm_struct *mm,
42#define pmd_alloc_one(mm, address) BTFIXUP_CALL(pmd_alloc_one)(mm, address) 51 unsigned long address)
52{
53 return (pmd_t *)srmmu_get_nocache(SRMMU_PMD_TABLE_SIZE,
54 SRMMU_PMD_TABLE_SIZE);
55}
43 56
44BTFIXUPDEF_CALL(void, free_pmd_fast, pmd_t *) 57static inline void free_pmd_fast(pmd_t * pmd)
45#define free_pmd_fast(pmd) BTFIXUP_CALL(free_pmd_fast)(pmd) 58{
59 srmmu_free_nocache((unsigned long)pmd, SRMMU_PMD_TABLE_SIZE);
60}
46 61
47#define pmd_free(mm, pmd) free_pmd_fast(pmd) 62#define pmd_free(mm, pmd) free_pmd_fast(pmd)
48#define __pmd_free_tlb(tlb, pmd, addr) pmd_free((tlb)->mm, pmd) 63#define __pmd_free_tlb(tlb, pmd, addr) pmd_free((tlb)->mm, pmd)
49 64
50BTFIXUPDEF_CALL(void, pmd_populate, pmd_t *, struct page *) 65void pmd_populate(struct mm_struct *mm, pmd_t *pmdp, struct page *ptep);
51#define pmd_populate(MM, PMD, PTE) BTFIXUP_CALL(pmd_populate)(PMD, PTE)
52#define pmd_pgtable(pmd) pmd_page(pmd) 66#define pmd_pgtable(pmd) pmd_page(pmd)
53BTFIXUPDEF_CALL(void, pmd_set, pmd_t *, pte_t *)
54#define pmd_populate_kernel(MM, PMD, PTE) BTFIXUP_CALL(pmd_set)(PMD, PTE)
55 67
56BTFIXUPDEF_CALL(pgtable_t , pte_alloc_one, struct mm_struct *, unsigned long) 68void pmd_set(pmd_t *pmdp, pte_t *ptep);
57#define pte_alloc_one(mm, address) BTFIXUP_CALL(pte_alloc_one)(mm, address) 69#define pmd_populate_kernel(MM, PMD, PTE) pmd_set(PMD, PTE)
58BTFIXUPDEF_CALL(pte_t *, pte_alloc_one_kernel, struct mm_struct *, unsigned long) 70
59#define pte_alloc_one_kernel(mm, addr) BTFIXUP_CALL(pte_alloc_one_kernel)(mm, addr) 71pgtable_t pte_alloc_one(struct mm_struct *mm, unsigned long address);
72
73static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm,
74 unsigned long address)
75{
76 return (pte_t *)srmmu_get_nocache(PTE_SIZE, PTE_SIZE);
77}
78
79
80static inline void free_pte_fast(pte_t *pte)
81{
82 srmmu_free_nocache((unsigned long)pte, PTE_SIZE);
83}
60 84
61BTFIXUPDEF_CALL(void, free_pte_fast, pte_t *) 85#define pte_free_kernel(mm, pte) free_pte_fast(pte)
62#define pte_free_kernel(mm, pte) BTFIXUP_CALL(free_pte_fast)(pte)
63 86
64BTFIXUPDEF_CALL(void, pte_free, pgtable_t ) 87void pte_free(struct mm_struct * mm, pgtable_t pte);
65#define pte_free(mm, pte) BTFIXUP_CALL(pte_free)(pte)
66#define __pte_free_tlb(tlb, pte, addr) pte_free((tlb)->mm, pte) 88#define __pte_free_tlb(tlb, pte, addr) pte_free((tlb)->mm, pte)
67 89
68#endif /* _SPARC_PGALLOC_H */ 90#endif /* _SPARC_PGALLOC_H */
diff --git a/arch/sparc/include/asm/pgtable_32.h b/arch/sparc/include/asm/pgtable_32.h
index 3d7101860e68..cbbbed5cb3aa 100644
--- a/arch/sparc/include/asm/pgtable_32.h
+++ b/arch/sparc/include/asm/pgtable_32.h
@@ -16,11 +16,9 @@
16#include <linux/spinlock.h> 16#include <linux/spinlock.h>
17#include <linux/swap.h> 17#include <linux/swap.h>
18#include <asm/types.h> 18#include <asm/types.h>
19#include <asm/pgtsun4c.h>
20#include <asm/pgtsrmmu.h> 19#include <asm/pgtsrmmu.h>
21#include <asm/vac-ops.h> 20#include <asm/vaddrs.h>
22#include <asm/oplib.h> 21#include <asm/oplib.h>
23#include <asm/btfixup.h>
24#include <asm/cpu_type.h> 22#include <asm/cpu_type.h>
25 23
26 24
@@ -30,87 +28,55 @@ struct page;
30extern void load_mmu(void); 28extern void load_mmu(void);
31extern unsigned long calc_highpages(void); 29extern unsigned long calc_highpages(void);
32 30
33BTFIXUPDEF_SIMM13(pgdir_shift)
34BTFIXUPDEF_SETHI(pgdir_size)
35BTFIXUPDEF_SETHI(pgdir_mask)
36
37BTFIXUPDEF_SIMM13(ptrs_per_pmd)
38BTFIXUPDEF_SIMM13(ptrs_per_pgd)
39BTFIXUPDEF_SIMM13(user_ptrs_per_pgd)
40
41#define pte_ERROR(e) __builtin_trap() 31#define pte_ERROR(e) __builtin_trap()
42#define pmd_ERROR(e) __builtin_trap() 32#define pmd_ERROR(e) __builtin_trap()
43#define pgd_ERROR(e) __builtin_trap() 33#define pgd_ERROR(e) __builtin_trap()
44 34
45BTFIXUPDEF_INT(page_none) 35#define PMD_SHIFT 22
46BTFIXUPDEF_INT(page_copy)
47BTFIXUPDEF_INT(page_readonly)
48BTFIXUPDEF_INT(page_kernel)
49
50#define PMD_SHIFT SUN4C_PMD_SHIFT
51#define PMD_SIZE (1UL << PMD_SHIFT) 36#define PMD_SIZE (1UL << PMD_SHIFT)
52#define PMD_MASK (~(PMD_SIZE-1)) 37#define PMD_MASK (~(PMD_SIZE-1))
53#define PMD_ALIGN(__addr) (((__addr) + ~PMD_MASK) & PMD_MASK) 38#define PMD_ALIGN(__addr) (((__addr) + ~PMD_MASK) & PMD_MASK)
54#define PGDIR_SHIFT BTFIXUP_SIMM13(pgdir_shift) 39#define PGDIR_SHIFT SRMMU_PGDIR_SHIFT
55#define PGDIR_SIZE BTFIXUP_SETHI(pgdir_size) 40#define PGDIR_SIZE SRMMU_PGDIR_SIZE
56#define PGDIR_MASK BTFIXUP_SETHI(pgdir_mask) 41#define PGDIR_MASK SRMMU_PGDIR_MASK
57#define PTRS_PER_PTE 1024 42#define PTRS_PER_PTE 1024
58#define PTRS_PER_PMD BTFIXUP_SIMM13(ptrs_per_pmd) 43#define PTRS_PER_PMD SRMMU_PTRS_PER_PMD
59#define PTRS_PER_PGD BTFIXUP_SIMM13(ptrs_per_pgd) 44#define PTRS_PER_PGD SRMMU_PTRS_PER_PGD
60#define USER_PTRS_PER_PGD BTFIXUP_SIMM13(user_ptrs_per_pgd) 45#define USER_PTRS_PER_PGD PAGE_OFFSET / SRMMU_PGDIR_SIZE
61#define FIRST_USER_ADDRESS 0 46#define FIRST_USER_ADDRESS 0
62#define PTE_SIZE (PTRS_PER_PTE*4) 47#define PTE_SIZE (PTRS_PER_PTE*4)
63 48
64#define PAGE_NONE __pgprot(BTFIXUP_INT(page_none)) 49#define PAGE_NONE SRMMU_PAGE_NONE
65extern pgprot_t PAGE_SHARED; 50#define PAGE_SHARED SRMMU_PAGE_SHARED
66#define PAGE_COPY __pgprot(BTFIXUP_INT(page_copy)) 51#define PAGE_COPY SRMMU_PAGE_COPY
67#define PAGE_READONLY __pgprot(BTFIXUP_INT(page_readonly)) 52#define PAGE_READONLY SRMMU_PAGE_RDONLY
68 53#define PAGE_KERNEL SRMMU_PAGE_KERNEL
69extern unsigned long page_kernel;
70
71#ifdef MODULE
72#define PAGE_KERNEL page_kernel
73#else
74#define PAGE_KERNEL __pgprot(BTFIXUP_INT(page_kernel))
75#endif
76 54
77/* Top-level page directory */ 55/* Top-level page directory */
78extern pgd_t swapper_pg_dir[1024]; 56extern pgd_t swapper_pg_dir[1024];
79 57
80extern void paging_init(void); 58extern void paging_init(void);
81 59
82/* Page table for 0-4MB for everybody, on the Sparc this
83 * holds the same as on the i386.
84 */
85extern pte_t pg0[1024];
86extern pte_t pg1[1024];
87extern pte_t pg2[1024];
88extern pte_t pg3[1024];
89
90extern unsigned long ptr_in_current_pgd; 60extern unsigned long ptr_in_current_pgd;
91 61
92/* Here is a trick, since mmap.c need the initializer elements for 62/* xwr */
93 * protection_map[] to be constant at compile time, I set the following 63#define __P000 PAGE_NONE
94 * to all zeros. I set it to the real values after I link in the 64#define __P001 PAGE_READONLY
95 * appropriate MMU page table routines at boot time. 65#define __P010 PAGE_COPY
96 */ 66#define __P011 PAGE_COPY
97#define __P000 __pgprot(0) 67#define __P100 PAGE_READONLY
98#define __P001 __pgprot(0) 68#define __P101 PAGE_READONLY
99#define __P010 __pgprot(0) 69#define __P110 PAGE_COPY
100#define __P011 __pgprot(0) 70#define __P111 PAGE_COPY
101#define __P100 __pgprot(0) 71
102#define __P101 __pgprot(0) 72#define __S000 PAGE_NONE
103#define __P110 __pgprot(0) 73#define __S001 PAGE_READONLY
104#define __P111 __pgprot(0) 74#define __S010 PAGE_SHARED
105 75#define __S011 PAGE_SHARED
106#define __S000 __pgprot(0) 76#define __S100 PAGE_READONLY
107#define __S001 __pgprot(0) 77#define __S101 PAGE_READONLY
108#define __S010 __pgprot(0) 78#define __S110 PAGE_SHARED
109#define __S011 __pgprot(0) 79#define __S111 PAGE_SHARED
110#define __S100 __pgprot(0)
111#define __S101 __pgprot(0)
112#define __S110 __pgprot(0)
113#define __S111 __pgprot(0)
114 80
115extern int num_contexts; 81extern int num_contexts;
116 82
@@ -137,82 +103,137 @@ extern unsigned long empty_zero_page;
137#define ZERO_PAGE(vaddr) (virt_to_page(&empty_zero_page)) 103#define ZERO_PAGE(vaddr) (virt_to_page(&empty_zero_page))
138 104
139/* 105/*
106 * In general all page table modifications should use the V8 atomic
107 * swap instruction. This insures the mmu and the cpu are in sync
108 * with respect to ref/mod bits in the page tables.
109 */
110static inline unsigned long srmmu_swap(unsigned long *addr, unsigned long value)
111{
112 __asm__ __volatile__("swap [%2], %0" : "=&r" (value) : "0" (value), "r" (addr));
113 return value;
114}
115
116/* Certain architectures need to do special things when pte's
117 * within a page table are directly modified. Thus, the following
118 * hook is made available.
140 */ 119 */
141BTFIXUPDEF_CALL_CONST(struct page *, pmd_page, pmd_t)
142BTFIXUPDEF_CALL_CONST(unsigned long, pgd_page_vaddr, pgd_t)
143 120
144#define pmd_page(pmd) BTFIXUP_CALL(pmd_page)(pmd) 121static inline void set_pte(pte_t *ptep, pte_t pteval)
145#define pgd_page_vaddr(pgd) BTFIXUP_CALL(pgd_page_vaddr)(pgd) 122{
123 srmmu_swap((unsigned long *)ptep, pte_val(pteval));
124}
125
126#define set_pte_at(mm,addr,ptep,pteval) set_pte(ptep,pteval)
127
128static inline int srmmu_device_memory(unsigned long x)
129{
130 return ((x & 0xF0000000) != 0);
131}
132
133static inline struct page *pmd_page(pmd_t pmd)
134{
135 if (srmmu_device_memory(pmd_val(pmd)))
136 BUG();
137 return pfn_to_page((pmd_val(pmd) & SRMMU_PTD_PMASK) >> (PAGE_SHIFT-4));
138}
139
140static inline unsigned long pgd_page_vaddr(pgd_t pgd)
141{
142 if (srmmu_device_memory(pgd_val(pgd))) {
143 return ~0;
144 } else {
145 unsigned long v = pgd_val(pgd) & SRMMU_PTD_PMASK;
146 return (unsigned long)__nocache_va(v << 4);
147 }
148}
146 149
147BTFIXUPDEF_CALL_CONST(int, pte_present, pte_t) 150static inline int pte_present(pte_t pte)
148BTFIXUPDEF_CALL(void, pte_clear, pte_t *) 151{
152 return ((pte_val(pte) & SRMMU_ET_MASK) == SRMMU_ET_PTE);
153}
149 154
150static inline int pte_none(pte_t pte) 155static inline int pte_none(pte_t pte)
151{ 156{
152 return !pte_val(pte); 157 return !pte_val(pte);
153} 158}
154 159
155#define pte_present(pte) BTFIXUP_CALL(pte_present)(pte) 160static inline void __pte_clear(pte_t *ptep)
156#define pte_clear(mm,addr,pte) BTFIXUP_CALL(pte_clear)(pte) 161{
162 set_pte(ptep, __pte(0));
163}
164
165static inline void pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
166{
167 __pte_clear(ptep);
168}
169
170static inline int pmd_bad(pmd_t pmd)
171{
172 return (pmd_val(pmd) & SRMMU_ET_MASK) != SRMMU_ET_PTD;
173}
157 174
158BTFIXUPDEF_CALL_CONST(int, pmd_bad, pmd_t) 175static inline int pmd_present(pmd_t pmd)
159BTFIXUPDEF_CALL_CONST(int, pmd_present, pmd_t) 176{
160BTFIXUPDEF_CALL(void, pmd_clear, pmd_t *) 177 return ((pmd_val(pmd) & SRMMU_ET_MASK) == SRMMU_ET_PTD);
178}
161 179
162static inline int pmd_none(pmd_t pmd) 180static inline int pmd_none(pmd_t pmd)
163{ 181{
164 return !pmd_val(pmd); 182 return !pmd_val(pmd);
165} 183}
166 184
167#define pmd_bad(pmd) BTFIXUP_CALL(pmd_bad)(pmd) 185static inline void pmd_clear(pmd_t *pmdp)
168#define pmd_present(pmd) BTFIXUP_CALL(pmd_present)(pmd) 186{
169#define pmd_clear(pmd) BTFIXUP_CALL(pmd_clear)(pmd) 187 int i;
188 for (i = 0; i < PTRS_PER_PTE/SRMMU_REAL_PTRS_PER_PTE; i++)
189 set_pte((pte_t *)&pmdp->pmdv[i], __pte(0));
190}
170 191
171BTFIXUPDEF_CALL_CONST(int, pgd_none, pgd_t) 192static inline int pgd_none(pgd_t pgd)
172BTFIXUPDEF_CALL_CONST(int, pgd_bad, pgd_t) 193{
173BTFIXUPDEF_CALL_CONST(int, pgd_present, pgd_t) 194 return !(pgd_val(pgd) & 0xFFFFFFF);
174BTFIXUPDEF_CALL(void, pgd_clear, pgd_t *) 195}
175 196
176#define pgd_none(pgd) BTFIXUP_CALL(pgd_none)(pgd) 197static inline int pgd_bad(pgd_t pgd)
177#define pgd_bad(pgd) BTFIXUP_CALL(pgd_bad)(pgd) 198{
178#define pgd_present(pgd) BTFIXUP_CALL(pgd_present)(pgd) 199 return (pgd_val(pgd) & SRMMU_ET_MASK) != SRMMU_ET_PTD;
179#define pgd_clear(pgd) BTFIXUP_CALL(pgd_clear)(pgd) 200}
201
202static inline int pgd_present(pgd_t pgd)
203{
204 return ((pgd_val(pgd) & SRMMU_ET_MASK) == SRMMU_ET_PTD);
205}
206
207static inline void pgd_clear(pgd_t *pgdp)
208{
209 set_pte((pte_t *)pgdp, __pte(0));
210}
180 211
181/* 212/*
182 * The following only work if pte_present() is true. 213 * The following only work if pte_present() is true.
183 * Undefined behaviour if not.. 214 * Undefined behaviour if not..
184 */ 215 */
185BTFIXUPDEF_HALF(pte_writei)
186BTFIXUPDEF_HALF(pte_dirtyi)
187BTFIXUPDEF_HALF(pte_youngi)
188
189static int pte_write(pte_t pte) __attribute_const__;
190static inline int pte_write(pte_t pte) 216static inline int pte_write(pte_t pte)
191{ 217{
192 return pte_val(pte) & BTFIXUP_HALF(pte_writei); 218 return pte_val(pte) & SRMMU_WRITE;
193} 219}
194 220
195static int pte_dirty(pte_t pte) __attribute_const__;
196static inline int pte_dirty(pte_t pte) 221static inline int pte_dirty(pte_t pte)
197{ 222{
198 return pte_val(pte) & BTFIXUP_HALF(pte_dirtyi); 223 return pte_val(pte) & SRMMU_DIRTY;
199} 224}
200 225
201static int pte_young(pte_t pte) __attribute_const__;
202static inline int pte_young(pte_t pte) 226static inline int pte_young(pte_t pte)
203{ 227{
204 return pte_val(pte) & BTFIXUP_HALF(pte_youngi); 228 return pte_val(pte) & SRMMU_REF;
205} 229}
206 230
207/* 231/*
208 * The following only work if pte_present() is not true. 232 * The following only work if pte_present() is not true.
209 */ 233 */
210BTFIXUPDEF_HALF(pte_filei)
211
212static int pte_file(pte_t pte) __attribute_const__;
213static inline int pte_file(pte_t pte) 234static inline int pte_file(pte_t pte)
214{ 235{
215 return pte_val(pte) & BTFIXUP_HALF(pte_filei); 236 return pte_val(pte) & SRMMU_FILE;
216} 237}
217 238
218static inline int pte_special(pte_t pte) 239static inline int pte_special(pte_t pte)
@@ -220,68 +241,85 @@ static inline int pte_special(pte_t pte)
220 return 0; 241 return 0;
221} 242}
222 243
223/*
224 */
225BTFIXUPDEF_HALF(pte_wrprotecti)
226BTFIXUPDEF_HALF(pte_mkcleani)
227BTFIXUPDEF_HALF(pte_mkoldi)
228
229static pte_t pte_wrprotect(pte_t pte) __attribute_const__;
230static inline pte_t pte_wrprotect(pte_t pte) 244static inline pte_t pte_wrprotect(pte_t pte)
231{ 245{
232 return __pte(pte_val(pte) & ~BTFIXUP_HALF(pte_wrprotecti)); 246 return __pte(pte_val(pte) & ~SRMMU_WRITE);
233} 247}
234 248
235static pte_t pte_mkclean(pte_t pte) __attribute_const__;
236static inline pte_t pte_mkclean(pte_t pte) 249static inline pte_t pte_mkclean(pte_t pte)
237{ 250{
238 return __pte(pte_val(pte) & ~BTFIXUP_HALF(pte_mkcleani)); 251 return __pte(pte_val(pte) & ~SRMMU_DIRTY);
239} 252}
240 253
241static pte_t pte_mkold(pte_t pte) __attribute_const__;
242static inline pte_t pte_mkold(pte_t pte) 254static inline pte_t pte_mkold(pte_t pte)
243{ 255{
244 return __pte(pte_val(pte) & ~BTFIXUP_HALF(pte_mkoldi)); 256 return __pte(pte_val(pte) & ~SRMMU_REF);
245} 257}
246 258
247BTFIXUPDEF_CALL_CONST(pte_t, pte_mkwrite, pte_t) 259static inline pte_t pte_mkwrite(pte_t pte)
248BTFIXUPDEF_CALL_CONST(pte_t, pte_mkdirty, pte_t) 260{
249BTFIXUPDEF_CALL_CONST(pte_t, pte_mkyoung, pte_t) 261 return __pte(pte_val(pte) | SRMMU_WRITE);
262}
263
264static inline pte_t pte_mkdirty(pte_t pte)
265{
266 return __pte(pte_val(pte) | SRMMU_DIRTY);
267}
250 268
251#define pte_mkwrite(pte) BTFIXUP_CALL(pte_mkwrite)(pte) 269static inline pte_t pte_mkyoung(pte_t pte)
252#define pte_mkdirty(pte) BTFIXUP_CALL(pte_mkdirty)(pte) 270{
253#define pte_mkyoung(pte) BTFIXUP_CALL(pte_mkyoung)(pte) 271 return __pte(pte_val(pte) | SRMMU_REF);
272}
254 273
255#define pte_mkspecial(pte) (pte) 274#define pte_mkspecial(pte) (pte)
256 275
257#define pfn_pte(pfn, prot) mk_pte(pfn_to_page(pfn), prot) 276#define pfn_pte(pfn, prot) mk_pte(pfn_to_page(pfn), prot)
258 277
259BTFIXUPDEF_CALL(unsigned long, pte_pfn, pte_t) 278static inline unsigned long pte_pfn(pte_t pte)
260#define pte_pfn(pte) BTFIXUP_CALL(pte_pfn)(pte) 279{
280 if (srmmu_device_memory(pte_val(pte))) {
281 /* Just return something that will cause
282 * pfn_valid() to return false. This makes
283 * copy_one_pte() to just directly copy to
284 * PTE over.
285 */
286 return ~0UL;
287 }
288 return (pte_val(pte) & SRMMU_PTE_PMASK) >> (PAGE_SHIFT-4);
289}
290
261#define pte_page(pte) pfn_to_page(pte_pfn(pte)) 291#define pte_page(pte) pfn_to_page(pte_pfn(pte))
262 292
263/* 293/*
264 * Conversion functions: convert a page and protection to a page entry, 294 * Conversion functions: convert a page and protection to a page entry,
265 * and a page entry and page directory to the page they refer to. 295 * and a page entry and page directory to the page they refer to.
266 */ 296 */
267BTFIXUPDEF_CALL_CONST(pte_t, mk_pte, struct page *, pgprot_t) 297static inline pte_t mk_pte(struct page *page, pgprot_t pgprot)
268 298{
269BTFIXUPDEF_CALL_CONST(pte_t, mk_pte_phys, unsigned long, pgprot_t) 299 return __pte((page_to_pfn(page) << (PAGE_SHIFT-4)) | pgprot_val(pgprot));
270BTFIXUPDEF_CALL_CONST(pte_t, mk_pte_io, unsigned long, pgprot_t, int) 300}
271BTFIXUPDEF_CALL_CONST(pgprot_t, pgprot_noncached, pgprot_t)
272 301
273#define mk_pte(page,pgprot) BTFIXUP_CALL(mk_pte)(page,pgprot) 302static inline pte_t mk_pte_phys(unsigned long page, pgprot_t pgprot)
274#define mk_pte_phys(page,pgprot) BTFIXUP_CALL(mk_pte_phys)(page,pgprot) 303{
275#define mk_pte_io(page,pgprot,space) BTFIXUP_CALL(mk_pte_io)(page,pgprot,space) 304 return __pte(((page) >> 4) | pgprot_val(pgprot));
305}
276 306
277#define pgprot_noncached(pgprot) BTFIXUP_CALL(pgprot_noncached)(pgprot) 307static inline pte_t mk_pte_io(unsigned long page, pgprot_t pgprot, int space)
308{
309 return __pte(((page) >> 4) | (space << 28) | pgprot_val(pgprot));
310}
278 311
279BTFIXUPDEF_INT(pte_modify_mask) 312#define pgprot_noncached pgprot_noncached
313static inline pgprot_t pgprot_noncached(pgprot_t prot)
314{
315 prot &= ~__pgprot(SRMMU_CACHE);
316 return prot;
317}
280 318
281static pte_t pte_modify(pte_t pte, pgprot_t newprot) __attribute_const__; 319static pte_t pte_modify(pte_t pte, pgprot_t newprot) __attribute_const__;
282static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) 320static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
283{ 321{
284 return __pte((pte_val(pte) & BTFIXUP_INT(pte_modify_mask)) | 322 return __pte((pte_val(pte) & SRMMU_CHG_MASK) |
285 pgprot_val(newprot)); 323 pgprot_val(newprot));
286} 324}
287 325
@@ -294,74 +332,69 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
294#define pgd_offset_k(address) pgd_offset(&init_mm, address) 332#define pgd_offset_k(address) pgd_offset(&init_mm, address)
295 333
296/* Find an entry in the second-level page table.. */ 334/* Find an entry in the second-level page table.. */
297BTFIXUPDEF_CALL(pmd_t *, pmd_offset, pgd_t *, unsigned long) 335static inline pmd_t *pmd_offset(pgd_t * dir, unsigned long address)
298#define pmd_offset(dir,addr) BTFIXUP_CALL(pmd_offset)(dir,addr) 336{
337 return (pmd_t *) pgd_page_vaddr(*dir) +
338 ((address >> PMD_SHIFT) & (PTRS_PER_PMD - 1));
339}
299 340
300/* Find an entry in the third-level page table.. */ 341/* Find an entry in the third-level page table.. */
301BTFIXUPDEF_CALL(pte_t *, pte_offset_kernel, pmd_t *, unsigned long) 342pte_t *pte_offset_kernel(pmd_t * dir, unsigned long address);
302#define pte_offset_kernel(dir,addr) BTFIXUP_CALL(pte_offset_kernel)(dir,addr)
303 343
304/* 344/*
305 * This shortcut works on sun4m (and sun4d) because the nocache area is static, 345 * This shortcut works on sun4m (and sun4d) because the nocache area is static.
306 * and sun4c is guaranteed to have no highmem anyway.
307 */ 346 */
308#define pte_offset_map(d, a) pte_offset_kernel(d,a) 347#define pte_offset_map(d, a) pte_offset_kernel(d,a)
309#define pte_unmap(pte) do{}while(0) 348#define pte_unmap(pte) do{}while(0)
310 349
311/* Certain architectures need to do special things when pte's
312 * within a page table are directly modified. Thus, the following
313 * hook is made available.
314 */
315
316BTFIXUPDEF_CALL(void, set_pte, pte_t *, pte_t)
317
318#define set_pte(ptep,pteval) BTFIXUP_CALL(set_pte)(ptep,pteval)
319#define set_pte_at(mm,addr,ptep,pteval) set_pte(ptep,pteval)
320
321struct seq_file; 350struct seq_file;
322BTFIXUPDEF_CALL(void, mmu_info, struct seq_file *) 351void mmu_info(struct seq_file *m);
323
324#define mmu_info(p) BTFIXUP_CALL(mmu_info)(p)
325 352
326/* Fault handler stuff... */ 353/* Fault handler stuff... */
327#define FAULT_CODE_PROT 0x1 354#define FAULT_CODE_PROT 0x1
328#define FAULT_CODE_WRITE 0x2 355#define FAULT_CODE_WRITE 0x2
329#define FAULT_CODE_USER 0x4 356#define FAULT_CODE_USER 0x4
330 357
331BTFIXUPDEF_CALL(void, update_mmu_cache, struct vm_area_struct *, unsigned long, pte_t *) 358#define update_mmu_cache(vma, address, ptep) do { } while (0)
332
333#define update_mmu_cache(vma,addr,ptep) BTFIXUP_CALL(update_mmu_cache)(vma,addr,ptep)
334
335BTFIXUPDEF_CALL(void, sparc_mapiorange, unsigned int, unsigned long,
336 unsigned long, unsigned int)
337BTFIXUPDEF_CALL(void, sparc_unmapiorange, unsigned long, unsigned int)
338#define sparc_mapiorange(bus,pa,va,len) BTFIXUP_CALL(sparc_mapiorange)(bus,pa,va,len)
339#define sparc_unmapiorange(va,len) BTFIXUP_CALL(sparc_unmapiorange)(va,len)
340 359
341extern int invalid_segment; 360void srmmu_mapiorange(unsigned int bus, unsigned long xpa,
361 unsigned long xva, unsigned int len);
362void srmmu_unmapiorange(unsigned long virt_addr, unsigned int len);
342 363
343/* Encode and de-code a swap entry */ 364/* Encode and de-code a swap entry */
344BTFIXUPDEF_CALL(unsigned long, __swp_type, swp_entry_t) 365static inline unsigned long __swp_type(swp_entry_t entry)
345BTFIXUPDEF_CALL(unsigned long, __swp_offset, swp_entry_t) 366{
346BTFIXUPDEF_CALL(swp_entry_t, __swp_entry, unsigned long, unsigned long) 367 return (entry.val >> SRMMU_SWP_TYPE_SHIFT) & SRMMU_SWP_TYPE_MASK;
368}
369
370static inline unsigned long __swp_offset(swp_entry_t entry)
371{
372 return (entry.val >> SRMMU_SWP_OFF_SHIFT) & SRMMU_SWP_OFF_MASK;
373}
347 374
348#define __swp_type(__x) BTFIXUP_CALL(__swp_type)(__x) 375static inline swp_entry_t __swp_entry(unsigned long type, unsigned long offset)
349#define __swp_offset(__x) BTFIXUP_CALL(__swp_offset)(__x) 376{
350#define __swp_entry(__type,__off) BTFIXUP_CALL(__swp_entry)(__type,__off) 377 return (swp_entry_t) {
378 (type & SRMMU_SWP_TYPE_MASK) << SRMMU_SWP_TYPE_SHIFT
379 | (offset & SRMMU_SWP_OFF_MASK) << SRMMU_SWP_OFF_SHIFT };
380}
351 381
352#define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) }) 382#define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) })
353#define __swp_entry_to_pte(x) ((pte_t) { (x).val }) 383#define __swp_entry_to_pte(x) ((pte_t) { (x).val })
354 384
355/* file-offset-in-pte helpers */ 385/* file-offset-in-pte helpers */
356BTFIXUPDEF_CALL(unsigned long, pte_to_pgoff, pte_t pte); 386static inline unsigned long pte_to_pgoff(pte_t pte)
357BTFIXUPDEF_CALL(pte_t, pgoff_to_pte, unsigned long pgoff); 387{
388 return pte_val(pte) >> SRMMU_PTE_FILE_SHIFT;
389}
358 390
359#define pte_to_pgoff(pte) BTFIXUP_CALL(pte_to_pgoff)(pte) 391static inline pte_t pgoff_to_pte(unsigned long pgoff)
360#define pgoff_to_pte(off) BTFIXUP_CALL(pgoff_to_pte)(off) 392{
393 return __pte((pgoff << SRMMU_PTE_FILE_SHIFT) | SRMMU_FILE);
394}
361 395
362/* 396/*
363 * This is made a constant because mm/fremap.c required a constant. 397 * This is made a constant because mm/fremap.c required a constant.
364 * Note that layout of these bits is different between sun4c.c and srmmu.c.
365 */ 398 */
366#define PTE_FILE_MAX_BITS 24 399#define PTE_FILE_MAX_BITS 24
367 400
@@ -399,9 +432,6 @@ static inline unsigned long
399__get_phys (unsigned long addr) 432__get_phys (unsigned long addr)
400{ 433{
401 switch (sparc_cpu_model){ 434 switch (sparc_cpu_model){
402 case sun4:
403 case sun4c:
404 return sun4c_get_pte (addr) << PAGE_SHIFT;
405 case sun4m: 435 case sun4m:
406 case sun4d: 436 case sun4d:
407 return ((srmmu_get_pte (addr) & 0xffffff00) << 4); 437 return ((srmmu_get_pte (addr) & 0xffffff00) << 4);
@@ -414,9 +444,6 @@ static inline int
414__get_iospace (unsigned long addr) 444__get_iospace (unsigned long addr)
415{ 445{
416 switch (sparc_cpu_model){ 446 switch (sparc_cpu_model){
417 case sun4:
418 case sun4c:
419 return -1; /* Don't check iospace on sun4c */
420 case sun4m: 447 case sun4m:
421 case sun4d: 448 case sun4d:
422 return (srmmu_get_pte (addr) >> 28); 449 return (srmmu_get_pte (addr) >> 28);
@@ -463,7 +490,7 @@ static inline int io_remap_pfn_range(struct vm_area_struct *vma,
463 set_pte_at((__vma)->vm_mm, (__address), __ptep, __entry); \ 490 set_pte_at((__vma)->vm_mm, (__address), __ptep, __entry); \
464 flush_tlb_page(__vma, __address); \ 491 flush_tlb_page(__vma, __address); \
465 } \ 492 } \
466 (sparc_cpu_model == sun4c) || __changed; \ 493 __changed; \
467}) 494})
468 495
469#include <asm-generic/pgtable.h> 496#include <asm-generic/pgtable.h>
@@ -471,10 +498,8 @@ static inline int io_remap_pfn_range(struct vm_area_struct *vma,
471#endif /* !(__ASSEMBLY__) */ 498#endif /* !(__ASSEMBLY__) */
472 499
473#define VMALLOC_START _AC(0xfe600000,UL) 500#define VMALLOC_START _AC(0xfe600000,UL)
474/* XXX Alter this when I get around to fixing sun4c - Anton */
475#define VMALLOC_END _AC(0xffc00000,UL) 501#define VMALLOC_END _AC(0xffc00000,UL)
476 502
477
478/* We provide our own get_unmapped_area to cope with VA holes for userland */ 503/* We provide our own get_unmapped_area to cope with VA holes for userland */
479#define HAVE_ARCH_UNMAPPED_AREA 504#define HAVE_ARCH_UNMAPPED_AREA
480 505
diff --git a/arch/sparc/include/asm/pgtable_64.h b/arch/sparc/include/asm/pgtable_64.h
index 76e4a52aa85e..61210db139fb 100644
--- a/arch/sparc/include/asm/pgtable_64.h
+++ b/arch/sparc/include/asm/pgtable_64.h
@@ -717,10 +717,6 @@ extern unsigned long find_ecache_flush_span(unsigned long size);
717struct seq_file; 717struct seq_file;
718extern void mmu_info(struct seq_file *); 718extern void mmu_info(struct seq_file *);
719 719
720/* These do nothing with the way I have things setup. */
721#define mmu_lockarea(vaddr, len) (vaddr)
722#define mmu_unlockarea(vaddr, len) do { } while(0)
723
724struct vm_area_struct; 720struct vm_area_struct;
725extern void update_mmu_cache(struct vm_area_struct *, unsigned long, pte_t *); 721extern void update_mmu_cache(struct vm_area_struct *, unsigned long, pte_t *);
726 722
diff --git a/arch/sparc/include/asm/pgtsrmmu.h b/arch/sparc/include/asm/pgtsrmmu.h
index f6ae2b2b6870..cb828703a63a 100644
--- a/arch/sparc/include/asm/pgtsrmmu.h
+++ b/arch/sparc/include/asm/pgtsrmmu.h
@@ -173,17 +173,6 @@ static inline void srmmu_set_ctable_ptr(unsigned long paddr)
173 "memory"); 173 "memory");
174} 174}
175 175
176static inline unsigned long srmmu_get_ctable_ptr(void)
177{
178 unsigned int retval;
179
180 __asm__ __volatile__("lda [%1] %2, %0\n\t" :
181 "=r" (retval) :
182 "r" (SRMMU_CTXTBL_PTR),
183 "i" (ASI_M_MMUREGS));
184 return (retval & SRMMU_CTX_PMASK) << 4;
185}
186
187static inline void srmmu_set_context(int context) 176static inline void srmmu_set_context(int context)
188{ 177{
189 __asm__ __volatile__("sta %0, [%1] %2\n\t" : : 178 __asm__ __volatile__("sta %0, [%1] %2\n\t" : :
@@ -231,42 +220,6 @@ static inline void srmmu_flush_whole_tlb(void)
231} 220}
232 221
233/* These flush types are not available on all chips... */ 222/* These flush types are not available on all chips... */
234static inline void srmmu_flush_tlb_ctx(void)
235{
236 __asm__ __volatile__("sta %%g0, [%0] %1\n\t": :
237 "r" (0x300), /* Flush TLB ctx.. */
238 "i" (ASI_M_FLUSH_PROBE) : "memory");
239
240}
241
242static inline void srmmu_flush_tlb_region(unsigned long addr)
243{
244 addr &= SRMMU_PGDIR_MASK;
245 __asm__ __volatile__("sta %%g0, [%0] %1\n\t": :
246 "r" (addr | 0x200), /* Flush TLB region.. */
247 "i" (ASI_M_FLUSH_PROBE) : "memory");
248
249}
250
251
252static inline void srmmu_flush_tlb_segment(unsigned long addr)
253{
254 addr &= SRMMU_REAL_PMD_MASK;
255 __asm__ __volatile__("sta %%g0, [%0] %1\n\t": :
256 "r" (addr | 0x100), /* Flush TLB segment.. */
257 "i" (ASI_M_FLUSH_PROBE) : "memory");
258
259}
260
261static inline void srmmu_flush_tlb_page(unsigned long page)
262{
263 page &= PAGE_MASK;
264 __asm__ __volatile__("sta %%g0, [%0] %1\n\t": :
265 "r" (page), /* Flush TLB page.. */
266 "i" (ASI_M_FLUSH_PROBE) : "memory");
267
268}
269
270#ifndef CONFIG_SPARC_LEON 223#ifndef CONFIG_SPARC_LEON
271static inline unsigned long srmmu_hwprobe(unsigned long vaddr) 224static inline unsigned long srmmu_hwprobe(unsigned long vaddr)
272{ 225{
@@ -294,9 +247,6 @@ srmmu_get_pte (unsigned long addr)
294 return entry; 247 return entry;
295} 248}
296 249
297extern unsigned long (*srmmu_read_physical)(unsigned long paddr);
298extern void (*srmmu_write_physical)(unsigned long paddr, unsigned long word);
299
300#endif /* !(__ASSEMBLY__) */ 250#endif /* !(__ASSEMBLY__) */
301 251
302#endif /* !(_SPARC_PGTSRMMU_H) */ 252#endif /* !(_SPARC_PGTSRMMU_H) */
diff --git a/arch/sparc/include/asm/pgtsun4c.h b/arch/sparc/include/asm/pgtsun4c.h
deleted file mode 100644
index aeb25e912179..000000000000
--- a/arch/sparc/include/asm/pgtsun4c.h
+++ /dev/null
@@ -1,172 +0,0 @@
1/*
2 * pgtsun4c.h: Sun4c specific pgtable.h defines and code.
3 *
4 * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
5 */
6#ifndef _SPARC_PGTSUN4C_H
7#define _SPARC_PGTSUN4C_H
8
9#include <asm/contregs.h>
10
11/* PMD_SHIFT determines the size of the area a second-level page table can map */
12#define SUN4C_PMD_SHIFT 22
13
14/* PGDIR_SHIFT determines what a third-level page table entry can map */
15#define SUN4C_PGDIR_SHIFT 22
16#define SUN4C_PGDIR_SIZE (1UL << SUN4C_PGDIR_SHIFT)
17#define SUN4C_PGDIR_MASK (~(SUN4C_PGDIR_SIZE-1))
18#define SUN4C_PGDIR_ALIGN(addr) (((addr)+SUN4C_PGDIR_SIZE-1)&SUN4C_PGDIR_MASK)
19
20/* To represent how the sun4c mmu really lays things out. */
21#define SUN4C_REAL_PGDIR_SHIFT 18
22#define SUN4C_REAL_PGDIR_SIZE (1UL << SUN4C_REAL_PGDIR_SHIFT)
23#define SUN4C_REAL_PGDIR_MASK (~(SUN4C_REAL_PGDIR_SIZE-1))
24#define SUN4C_REAL_PGDIR_ALIGN(addr) (((addr)+SUN4C_REAL_PGDIR_SIZE-1)&SUN4C_REAL_PGDIR_MASK)
25
26/* 16 bit PFN on sun4c */
27#define SUN4C_PFN_MASK 0xffff
28
29/* Don't increase these unless the structures in sun4c.c are fixed */
30#define SUN4C_MAX_SEGMAPS 256
31#define SUN4C_MAX_CONTEXTS 16
32
33/*
34 * To be efficient, and not have to worry about allocating such
35 * a huge pgd, we make the kernel sun4c tables each hold 1024
36 * entries and the pgd similarly just like the i386 tables.
37 */
38#define SUN4C_PTRS_PER_PTE 1024
39#define SUN4C_PTRS_PER_PMD 1
40#define SUN4C_PTRS_PER_PGD 1024
41
42/*
43 * Sparc SUN4C pte fields.
44 */
45#define _SUN4C_PAGE_VALID 0x80000000
46#define _SUN4C_PAGE_SILENT_READ 0x80000000 /* synonym */
47#define _SUN4C_PAGE_DIRTY 0x40000000
48#define _SUN4C_PAGE_SILENT_WRITE 0x40000000 /* synonym */
49#define _SUN4C_PAGE_PRIV 0x20000000 /* privileged page */
50#define _SUN4C_PAGE_NOCACHE 0x10000000 /* non-cacheable page */
51#define _SUN4C_PAGE_PRESENT 0x08000000 /* implemented in software */
52#define _SUN4C_PAGE_IO 0x04000000 /* I/O page */
53#define _SUN4C_PAGE_FILE 0x02000000 /* implemented in software */
54#define _SUN4C_PAGE_READ 0x00800000 /* implemented in software */
55#define _SUN4C_PAGE_WRITE 0x00400000 /* implemented in software */
56#define _SUN4C_PAGE_ACCESSED 0x00200000 /* implemented in software */
57#define _SUN4C_PAGE_MODIFIED 0x00100000 /* implemented in software */
58
59#define _SUN4C_READABLE (_SUN4C_PAGE_READ|_SUN4C_PAGE_SILENT_READ|\
60 _SUN4C_PAGE_ACCESSED)
61#define _SUN4C_WRITEABLE (_SUN4C_PAGE_WRITE|_SUN4C_PAGE_SILENT_WRITE|\
62 _SUN4C_PAGE_MODIFIED)
63
64#define _SUN4C_PAGE_CHG_MASK (0xffff|_SUN4C_PAGE_ACCESSED|_SUN4C_PAGE_MODIFIED)
65
66#define SUN4C_PAGE_NONE __pgprot(_SUN4C_PAGE_PRESENT)
67#define SUN4C_PAGE_SHARED __pgprot(_SUN4C_PAGE_PRESENT|_SUN4C_READABLE|\
68 _SUN4C_PAGE_WRITE)
69#define SUN4C_PAGE_COPY __pgprot(_SUN4C_PAGE_PRESENT|_SUN4C_READABLE)
70#define SUN4C_PAGE_READONLY __pgprot(_SUN4C_PAGE_PRESENT|_SUN4C_READABLE)
71#define SUN4C_PAGE_KERNEL __pgprot(_SUN4C_READABLE|_SUN4C_WRITEABLE|\
72 _SUN4C_PAGE_DIRTY|_SUN4C_PAGE_PRIV)
73
74/* SUN4C swap entry encoding
75 *
76 * We use 5 bits for the type and 19 for the offset. This gives us
77 * 32 swapfiles of 4GB each. Encoding looks like:
78 *
79 * RRRRRRRRooooooooooooooooooottttt
80 * fedcba9876543210fedcba9876543210
81 *
82 * The top 8 bits are reserved for protection and status bits, especially
83 * FILE and PRESENT.
84 */
85#define SUN4C_SWP_TYPE_MASK 0x1f
86#define SUN4C_SWP_OFF_MASK 0x7ffff
87#define SUN4C_SWP_OFF_SHIFT 5
88
89#ifndef __ASSEMBLY__
90
91static inline unsigned long sun4c_get_synchronous_error(void)
92{
93 unsigned long sync_err;
94
95 __asm__ __volatile__("lda [%1] %2, %0\n\t" :
96 "=r" (sync_err) :
97 "r" (AC_SYNC_ERR), "i" (ASI_CONTROL));
98 return sync_err;
99}
100
101static inline unsigned long sun4c_get_synchronous_address(void)
102{
103 unsigned long sync_addr;
104
105 __asm__ __volatile__("lda [%1] %2, %0\n\t" :
106 "=r" (sync_addr) :
107 "r" (AC_SYNC_VA), "i" (ASI_CONTROL));
108 return sync_addr;
109}
110
111/* SUN4C pte, segmap, and context manipulation */
112static inline unsigned long sun4c_get_segmap(unsigned long addr)
113{
114 register unsigned long entry;
115
116 __asm__ __volatile__("\n\tlduba [%1] %2, %0\n\t" :
117 "=r" (entry) :
118 "r" (addr), "i" (ASI_SEGMAP));
119
120 return entry;
121}
122
123static inline void sun4c_put_segmap(unsigned long addr, unsigned long entry)
124{
125
126 __asm__ __volatile__("\n\tstba %1, [%0] %2; nop; nop; nop;\n\t" : :
127 "r" (addr), "r" (entry),
128 "i" (ASI_SEGMAP)
129 : "memory");
130}
131
132static inline unsigned long sun4c_get_pte(unsigned long addr)
133{
134 register unsigned long entry;
135
136 __asm__ __volatile__("\n\tlda [%1] %2, %0\n\t" :
137 "=r" (entry) :
138 "r" (addr), "i" (ASI_PTE));
139 return entry;
140}
141
142static inline void sun4c_put_pte(unsigned long addr, unsigned long entry)
143{
144 __asm__ __volatile__("\n\tsta %1, [%0] %2; nop; nop; nop;\n\t" : :
145 "r" (addr),
146 "r" ((entry & ~(_SUN4C_PAGE_PRESENT))), "i" (ASI_PTE)
147 : "memory");
148}
149
150static inline int sun4c_get_context(void)
151{
152 register int ctx;
153
154 __asm__ __volatile__("\n\tlduba [%1] %2, %0\n\t" :
155 "=r" (ctx) :
156 "r" (AC_CONTEXT), "i" (ASI_CONTROL));
157
158 return ctx;
159}
160
161static inline int sun4c_set_context(int ctx)
162{
163 __asm__ __volatile__("\n\tstba %0, [%1] %2; nop; nop; nop;\n\t" : :
164 "r" (ctx), "r" (AC_CONTEXT), "i" (ASI_CONTROL)
165 : "memory");
166
167 return ctx;
168}
169
170#endif /* !(__ASSEMBLY__) */
171
172#endif /* !(_SPARC_PGTSUN4C_H) */
diff --git a/arch/sparc/include/asm/processor_32.h b/arch/sparc/include/asm/processor_32.h
index 09521c6a5edb..9cbd854fdfdd 100644
--- a/arch/sparc/include/asm/processor_32.h
+++ b/arch/sparc/include/asm/processor_32.h
@@ -16,7 +16,6 @@
16#include <asm/ptrace.h> 16#include <asm/ptrace.h>
17#include <asm/head.h> 17#include <asm/head.h>
18#include <asm/signal.h> 18#include <asm/signal.h>
19#include <asm/btfixup.h>
20#include <asm/page.h> 19#include <asm/page.h>
21 20
22/* 21/*
diff --git a/arch/sparc/include/asm/setup.h b/arch/sparc/include/asm/setup.h
index 00497abec996..8a83699a5507 100644
--- a/arch/sparc/include/asm/setup.h
+++ b/arch/sparc/include/asm/setup.h
@@ -20,10 +20,7 @@ extern char reboot_command[];
20 * Only sun4d + leon may have boot_cpu_id != 0 20 * Only sun4d + leon may have boot_cpu_id != 0
21 */ 21 */
22extern unsigned char boot_cpu_id; 22extern unsigned char boot_cpu_id;
23extern unsigned char boot_cpu_id4;
24 23
25extern unsigned long empty_bad_page;
26extern unsigned long empty_bad_page_table;
27extern unsigned long empty_zero_page; 24extern unsigned long empty_zero_page;
28 25
29extern int serial_console; 26extern int serial_console;
diff --git a/arch/sparc/include/asm/shmparam_32.h b/arch/sparc/include/asm/shmparam_32.h
index 59a1243c12f3..142825c8d3ac 100644
--- a/arch/sparc/include/asm/shmparam_32.h
+++ b/arch/sparc/include/asm/shmparam_32.h
@@ -4,8 +4,6 @@
4#define __ARCH_FORCE_SHMLBA 1 4#define __ARCH_FORCE_SHMLBA 1
5 5
6extern int vac_cache_size; 6extern int vac_cache_size;
7#define SHMLBA (vac_cache_size ? vac_cache_size : \ 7#define SHMLBA (vac_cache_size ? vac_cache_size : PAGE_SIZE)
8 (sparc_cpu_model == sun4c ? (64 * 1024) : \
9 (sparc_cpu_model == sun4 ? (128 * 1024) : PAGE_SIZE)))
10 8
11#endif /* _ASMSPARC_SHMPARAM_H */ 9#endif /* _ASMSPARC_SHMPARAM_H */
diff --git a/arch/sparc/include/asm/smp_32.h b/arch/sparc/include/asm/smp_32.h
index 01c51c704341..b73da3c5f10a 100644
--- a/arch/sparc/include/asm/smp_32.h
+++ b/arch/sparc/include/asm/smp_32.h
@@ -8,7 +8,6 @@
8 8
9#include <linux/threads.h> 9#include <linux/threads.h>
10#include <asm/head.h> 10#include <asm/head.h>
11#include <asm/btfixup.h>
12 11
13#ifndef __ASSEMBLY__ 12#ifndef __ASSEMBLY__
14 13
@@ -58,104 +57,53 @@ struct seq_file;
58void smp_bogo(struct seq_file *); 57void smp_bogo(struct seq_file *);
59void smp_info(struct seq_file *); 58void smp_info(struct seq_file *);
60 59
61BTFIXUPDEF_CALL(void, smp_cross_call, smpfunc_t, cpumask_t, unsigned long, unsigned long, unsigned long, unsigned long) 60struct sparc32_ipi_ops {
62BTFIXUPDEF_CALL(int, __hard_smp_processor_id, void) 61 void (*cross_call)(smpfunc_t func, cpumask_t mask, unsigned long arg1,
63BTFIXUPDEF_CALL(void, smp_ipi_resched, int); 62 unsigned long arg2, unsigned long arg3,
64BTFIXUPDEF_CALL(void, smp_ipi_single, int); 63 unsigned long arg4);
65BTFIXUPDEF_CALL(void, smp_ipi_mask_one, int); 64 void (*resched)(int cpu);
66BTFIXUPDEF_BLACKBOX(hard_smp_processor_id) 65 void (*single)(int cpu);
67BTFIXUPDEF_BLACKBOX(load_current) 66 void (*mask_one)(int cpu);
68 67};
69#define smp_cross_call(func,mask,arg1,arg2,arg3,arg4) BTFIXUP_CALL(smp_cross_call)(func,mask,arg1,arg2,arg3,arg4) 68extern const struct sparc32_ipi_ops *sparc32_ipi_ops;
69
70static inline void xc0(smpfunc_t func)
71{
72 sparc32_ipi_ops->cross_call(func, *cpu_online_mask, 0, 0, 0, 0);
73}
70 74
71static inline void xc0(smpfunc_t func) { smp_cross_call(func, *cpu_online_mask, 0, 0, 0, 0); }
72static inline void xc1(smpfunc_t func, unsigned long arg1) 75static inline void xc1(smpfunc_t func, unsigned long arg1)
73{ smp_cross_call(func, *cpu_online_mask, arg1, 0, 0, 0); }
74static inline void xc2(smpfunc_t func, unsigned long arg1, unsigned long arg2)
75{ smp_cross_call(func, *cpu_online_mask, arg1, arg2, 0, 0); }
76static inline void xc3(smpfunc_t func, unsigned long arg1, unsigned long arg2,
77 unsigned long arg3)
78{ smp_cross_call(func, *cpu_online_mask, arg1, arg2, arg3, 0); }
79static inline void xc4(smpfunc_t func, unsigned long arg1, unsigned long arg2,
80 unsigned long arg3, unsigned long arg4)
81{ smp_cross_call(func, *cpu_online_mask, arg1, arg2, arg3, arg4); }
82
83extern void arch_send_call_function_single_ipi(int cpu);
84extern void arch_send_call_function_ipi_mask(const struct cpumask *mask);
85
86static inline int cpu_logical_map(int cpu)
87{ 76{
88 return cpu; 77 sparc32_ipi_ops->cross_call(func, *cpu_online_mask, arg1, 0, 0, 0);
89} 78}
90 79static inline void xc2(smpfunc_t func, unsigned long arg1, unsigned long arg2)
91static inline int hard_smp4m_processor_id(void)
92{ 80{
93 int cpuid; 81 sparc32_ipi_ops->cross_call(func, *cpu_online_mask, arg1, arg2, 0, 0);
94
95 __asm__ __volatile__("rd %%tbr, %0\n\t"
96 "srl %0, 12, %0\n\t"
97 "and %0, 3, %0\n\t" :
98 "=&r" (cpuid));
99 return cpuid;
100} 82}
101 83
102static inline int hard_smp4d_processor_id(void) 84static inline void xc3(smpfunc_t func, unsigned long arg1, unsigned long arg2,
85 unsigned long arg3)
103{ 86{
104 int cpuid; 87 sparc32_ipi_ops->cross_call(func, *cpu_online_mask,
105 88 arg1, arg2, arg3, 0);
106 __asm__ __volatile__("lda [%%g0] %1, %0\n\t" :
107 "=&r" (cpuid) : "i" (ASI_M_VIKING_TMP1));
108 return cpuid;
109} 89}
110 90
111extern inline int hard_smpleon_processor_id(void) 91static inline void xc4(smpfunc_t func, unsigned long arg1, unsigned long arg2,
92 unsigned long arg3, unsigned long arg4)
112{ 93{
113 int cpuid; 94 sparc32_ipi_ops->cross_call(func, *cpu_online_mask,
114 __asm__ __volatile__("rd %%asr17,%0\n\t" 95 arg1, arg2, arg3, arg4);
115 "srl %0,28,%0" :
116 "=&r" (cpuid) : );
117 return cpuid;
118} 96}
119 97
120#ifndef MODULE 98extern void arch_send_call_function_single_ipi(int cpu);
121static inline int hard_smp_processor_id(void) 99extern void arch_send_call_function_ipi_mask(const struct cpumask *mask);
100
101static inline int cpu_logical_map(int cpu)
122{ 102{
123 int cpuid; 103 return cpu;
124
125 /* Black box - sun4m
126 __asm__ __volatile__("rd %%tbr, %0\n\t"
127 "srl %0, 12, %0\n\t"
128 "and %0, 3, %0\n\t" :
129 "=&r" (cpuid));
130 - sun4d
131 __asm__ __volatile__("lda [%g0] ASI_M_VIKING_TMP1, %0\n\t"
132 "nop; nop" :
133 "=&r" (cpuid));
134 - leon
135 __asm__ __volatile__( "rd %asr17, %0\n\t"
136 "srl %0, 0x1c, %0\n\t"
137 "nop\n\t" :
138 "=&r" (cpuid));
139 See btfixup.h and btfixupprep.c to understand how a blackbox works.
140 */
141 __asm__ __volatile__("sethi %%hi(___b_hard_smp_processor_id), %0\n\t"
142 "sethi %%hi(boot_cpu_id), %0\n\t"
143 "ldub [%0 + %%lo(boot_cpu_id)], %0\n\t" :
144 "=&r" (cpuid));
145 return cpuid;
146} 104}
147#else
148static inline int hard_smp_processor_id(void)
149{
150 int cpuid;
151 105
152 __asm__ __volatile__("mov %%o7, %%g1\n\t" 106extern int hard_smp_processor_id(void);
153 "call ___f___hard_smp_processor_id\n\t"
154 " nop\n\t"
155 "mov %%g2, %0\n\t" : "=r"(cpuid) : : "g1", "g2");
156 return cpuid;
157}
158#endif
159 107
160#define raw_smp_processor_id() (current_thread_info()->cpu) 108#define raw_smp_processor_id() (current_thread_info()->cpu)
161 109
diff --git a/arch/sparc/include/asm/smpprim.h b/arch/sparc/include/asm/smpprim.h
deleted file mode 100644
index eb849d862c64..000000000000
--- a/arch/sparc/include/asm/smpprim.h
+++ /dev/null
@@ -1,54 +0,0 @@
1/*
2 * smpprim.h: SMP locking primitives on the Sparc
3 *
4 * God knows we won't be actually using this code for some time
5 * but I thought I'd write it since I knew how.
6 *
7 * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
8 */
9
10#ifndef __SPARC_SMPPRIM_H
11#define __SPARC_SMPPRIM_H
12
13/* Test and set the unsigned byte at ADDR to 1. Returns the previous
14 * value. On the Sparc we use the ldstub instruction since it is
15 * atomic.
16 */
17
18static inline __volatile__ char test_and_set(void *addr)
19{
20 char state = 0;
21
22 __asm__ __volatile__("ldstub [%0], %1 ! test_and_set\n\t"
23 "=r" (addr), "=r" (state) :
24 "0" (addr), "1" (state) : "memory");
25
26 return state;
27}
28
29/* Initialize a spin-lock. */
30static inline __volatile__ smp_initlock(void *spinlock)
31{
32 /* Unset the lock. */
33 *((unsigned char *) spinlock) = 0;
34
35 return;
36}
37
38/* This routine spins until it acquires the lock at ADDR. */
39static inline __volatile__ smp_lock(void *addr)
40{
41 while(test_and_set(addr) == 0xff)
42 ;
43
44 /* We now have the lock */
45 return;
46}
47
48/* This routine releases the lock at ADDR. */
49static inline __volatile__ smp_unlock(void *addr)
50{
51 *((unsigned char *) addr) = 0;
52}
53
54#endif /* !(__SPARC_SMPPRIM_H) */
diff --git a/arch/sparc/include/asm/string_32.h b/arch/sparc/include/asm/string_32.h
index edf196ee4ef8..12f67857152e 100644
--- a/arch/sparc/include/asm/string_32.h
+++ b/arch/sparc/include/asm/string_32.h
@@ -61,68 +61,7 @@ extern int memcmp(const void *,const void *,__kernel_size_t);
61extern __kernel_size_t strlen(const char *); 61extern __kernel_size_t strlen(const char *);
62 62
63#define __HAVE_ARCH_STRNCMP 63#define __HAVE_ARCH_STRNCMP
64 64extern int strncmp(const char *, const char *, __kernel_size_t);
65extern int __strncmp(const char *, const char *, __kernel_size_t);
66
67static inline int __constant_strncmp(const char *src, const char *dest, __kernel_size_t count)
68{
69 register int retval;
70 switch(count) {
71 case 0: return 0;
72 case 1: return (src[0] - dest[0]);
73 case 2: retval = (src[0] - dest[0]);
74 if(!retval && src[0])
75 retval = (src[1] - dest[1]);
76 return retval;
77 case 3: retval = (src[0] - dest[0]);
78 if(!retval && src[0]) {
79 retval = (src[1] - dest[1]);
80 if(!retval && src[1])
81 retval = (src[2] - dest[2]);
82 }
83 return retval;
84 case 4: retval = (src[0] - dest[0]);
85 if(!retval && src[0]) {
86 retval = (src[1] - dest[1]);
87 if(!retval && src[1]) {
88 retval = (src[2] - dest[2]);
89 if (!retval && src[2])
90 retval = (src[3] - dest[3]);
91 }
92 }
93 return retval;
94 case 5: retval = (src[0] - dest[0]);
95 if(!retval && src[0]) {
96 retval = (src[1] - dest[1]);
97 if(!retval && src[1]) {
98 retval = (src[2] - dest[2]);
99 if (!retval && src[2]) {
100 retval = (src[3] - dest[3]);
101 if (!retval && src[3])
102 retval = (src[4] - dest[4]);
103 }
104 }
105 }
106 return retval;
107 default:
108 retval = (src[0] - dest[0]);
109 if(!retval && src[0]) {
110 retval = (src[1] - dest[1]);
111 if(!retval && src[1]) {
112 retval = (src[2] - dest[2]);
113 if(!retval && src[2])
114 retval = __strncmp(src+3,dest+3,count-3);
115 }
116 }
117 return retval;
118 }
119}
120
121#undef strncmp
122#define strncmp(__arg0, __arg1, __arg2) \
123(__builtin_constant_p(__arg2) ? \
124 __constant_strncmp(__arg0, __arg1, __arg2) : \
125 __strncmp(__arg0, __arg1, __arg2))
126 65
127#endif /* !EXPORT_SYMTAB_STROPS */ 66#endif /* !EXPORT_SYMTAB_STROPS */
128 67
diff --git a/arch/sparc/include/asm/sysen.h b/arch/sparc/include/asm/sysen.h
deleted file mode 100644
index 6af34abde6e7..000000000000
--- a/arch/sparc/include/asm/sysen.h
+++ /dev/null
@@ -1,15 +0,0 @@
1/*
2 * sysen.h: Bit fields within the "System Enable" register accessed via
3 * the ASI_CONTROL address space at address AC_SYSENABLE.
4 *
5 * Copyright (C) 1994 David S. Miller (davem@caip.rutgers.edu)
6 */
7
8#ifndef _SPARC_SYSEN_H
9#define _SPARC_SYSEN_H
10
11#define SENABLE_DVMA 0x20 /* enable dvma transfers */
12#define SENABLE_CACHE 0x10 /* enable VAC cache */
13#define SENABLE_RESET 0x04 /* reset whole machine, danger Will Robinson */
14
15#endif /* _SPARC_SYSEN_H */
diff --git a/arch/sparc/include/asm/thread_info_32.h b/arch/sparc/include/asm/thread_info_32.h
index c2a1080cdd3b..cd0b2dc8fab9 100644
--- a/arch/sparc/include/asm/thread_info_32.h
+++ b/arch/sparc/include/asm/thread_info_32.h
@@ -15,7 +15,6 @@
15 15
16#ifndef __ASSEMBLY__ 16#ifndef __ASSEMBLY__
17 17
18#include <asm/btfixup.h>
19#include <asm/ptrace.h> 18#include <asm/ptrace.h>
20#include <asm/page.h> 19#include <asm/page.h>
21 20
@@ -82,11 +81,8 @@ register struct thread_info *current_thread_info_reg asm("g6");
82 81
83#define __HAVE_ARCH_THREAD_INFO_ALLOCATOR 82#define __HAVE_ARCH_THREAD_INFO_ALLOCATOR
84 83
85BTFIXUPDEF_CALL(struct thread_info *, alloc_thread_info_node, int) 84struct thread_info * alloc_thread_info_node(struct task_struct *tsk, int node);
86#define alloc_thread_info_node(tsk, node) BTFIXUP_CALL(alloc_thread_info_node)(node) 85void free_thread_info(struct thread_info *);
87
88BTFIXUPDEF_CALL(void, free_thread_info, struct thread_info *)
89#define free_thread_info(ti) BTFIXUP_CALL(free_thread_info)(ti)
90 86
91#endif /* __ASSEMBLY__ */ 87#endif /* __ASSEMBLY__ */
92 88
diff --git a/arch/sparc/include/asm/timer_32.h b/arch/sparc/include/asm/timer_32.h
index 1a91e11dd104..72f40a546de3 100644
--- a/arch/sparc/include/asm/timer_32.h
+++ b/arch/sparc/include/asm/timer_32.h
@@ -8,14 +8,37 @@
8#ifndef _SPARC_TIMER_H 8#ifndef _SPARC_TIMER_H
9#define _SPARC_TIMER_H 9#define _SPARC_TIMER_H
10 10
11#include <linux/clocksource.h>
12#include <linux/irqreturn.h>
13
14#include <asm-generic/percpu.h>
15
11#include <asm/cpu_type.h> /* For SUN4M_NCPUS */ 16#include <asm/cpu_type.h> /* For SUN4M_NCPUS */
12#include <asm/btfixup.h> 17
18#define SBUS_CLOCK_RATE 2000000 /* 2MHz */
19#define TIMER_VALUE_SHIFT 9
20#define TIMER_VALUE_MASK 0x3fffff
21#define TIMER_LIMIT_BIT (1 << 31) /* Bit 31 in Counter-Timer register */
22
23/* The counter timer register has the value offset by 9 bits.
24 * From sun4m manual:
25 * When a counter reaches the value in the corresponding limit register,
26 * the Limit bit is set and the counter is set to 500 nS (i.e. 0x00000200).
27 *
28 * To compensate for this add one to the value.
29 */
30static inline unsigned int timer_value(unsigned int value)
31{
32 return (value + 1) << TIMER_VALUE_SHIFT;
33}
13 34
14extern __volatile__ unsigned int *master_l10_counter; 35extern __volatile__ unsigned int *master_l10_counter;
15 36
16/* FIXME: Make do_[gs]ettimeofday btfixup calls */ 37extern irqreturn_t notrace timer_interrupt(int dummy, void *dev_id);
17struct timespec; 38
18BTFIXUPDEF_CALL(int, bus_do_settimeofday, struct timespec *tv) 39#ifdef CONFIG_SMP
19#define bus_do_settimeofday(tv) BTFIXUP_CALL(bus_do_settimeofday)(tv) 40DECLARE_PER_CPU(struct clock_event_device, sparc32_clockevent);
41extern void register_percpu_ce(int cpu);
42#endif
20 43
21#endif /* !(_SPARC_TIMER_H) */ 44#endif /* !(_SPARC_TIMER_H) */
diff --git a/arch/sparc/include/asm/timex_32.h b/arch/sparc/include/asm/timex_32.h
index a254750e4c03..b6ccdb0d6f7d 100644
--- a/arch/sparc/include/asm/timex_32.h
+++ b/arch/sparc/include/asm/timex_32.h
@@ -12,5 +12,4 @@
12typedef unsigned long cycles_t; 12typedef unsigned long cycles_t;
13#define get_cycles() (0) 13#define get_cycles() (0)
14 14
15extern u32 (*do_arch_gettimeoffset)(void);
16#endif 15#endif
diff --git a/arch/sparc/include/asm/tlbflush_32.h b/arch/sparc/include/asm/tlbflush_32.h
index fe0a71abc9bb..a5c4142130f5 100644
--- a/arch/sparc/include/asm/tlbflush_32.h
+++ b/arch/sparc/include/asm/tlbflush_32.h
@@ -1,52 +1,16 @@
1#ifndef _SPARC_TLBFLUSH_H 1#ifndef _SPARC_TLBFLUSH_H
2#define _SPARC_TLBFLUSH_H 2#define _SPARC_TLBFLUSH_H
3 3
4#include <linux/mm.h> 4#include <asm/cachetlb_32.h>
5// #include <asm/processor.h> 5
6 6#define flush_tlb_all() \
7/* 7 sparc32_cachetlb_ops->tlb_all()
8 * TLB flushing: 8#define flush_tlb_mm(mm) \
9 * 9 sparc32_cachetlb_ops->tlb_mm(mm)
10 * - flush_tlb() flushes the current mm struct TLBs XXX Exists? 10#define flush_tlb_range(vma, start, end) \
11 * - flush_tlb_all() flushes all processes TLBs 11 sparc32_cachetlb_ops->tlb_range(vma, start, end)
12 * - flush_tlb_mm(mm) flushes the specified mm context TLB's 12#define flush_tlb_page(vma, addr) \
13 * - flush_tlb_page(vma, vmaddr) flushes one page 13 sparc32_cachetlb_ops->tlb_page(vma, addr)
14 * - flush_tlb_range(vma, start, end) flushes a range of pages
15 * - flush_tlb_kernel_range(start, end) flushes a range of kernel pages
16 */
17
18#ifdef CONFIG_SMP
19
20BTFIXUPDEF_CALL(void, local_flush_tlb_all, void)
21BTFIXUPDEF_CALL(void, local_flush_tlb_mm, struct mm_struct *)
22BTFIXUPDEF_CALL(void, local_flush_tlb_range, struct vm_area_struct *, unsigned long, unsigned long)
23BTFIXUPDEF_CALL(void, local_flush_tlb_page, struct vm_area_struct *, unsigned long)
24
25#define local_flush_tlb_all() BTFIXUP_CALL(local_flush_tlb_all)()
26#define local_flush_tlb_mm(mm) BTFIXUP_CALL(local_flush_tlb_mm)(mm)
27#define local_flush_tlb_range(vma,start,end) BTFIXUP_CALL(local_flush_tlb_range)(vma,start,end)
28#define local_flush_tlb_page(vma,addr) BTFIXUP_CALL(local_flush_tlb_page)(vma,addr)
29
30extern void smp_flush_tlb_all(void);
31extern void smp_flush_tlb_mm(struct mm_struct *mm);
32extern void smp_flush_tlb_range(struct vm_area_struct *vma,
33 unsigned long start,
34 unsigned long end);
35extern void smp_flush_tlb_page(struct vm_area_struct *mm, unsigned long page);
36
37#endif /* CONFIG_SMP */
38
39BTFIXUPDEF_CALL(void, flush_tlb_all, void)
40BTFIXUPDEF_CALL(void, flush_tlb_mm, struct mm_struct *)
41BTFIXUPDEF_CALL(void, flush_tlb_range, struct vm_area_struct *, unsigned long, unsigned long)
42BTFIXUPDEF_CALL(void, flush_tlb_page, struct vm_area_struct *, unsigned long)
43
44#define flush_tlb_all() BTFIXUP_CALL(flush_tlb_all)()
45#define flush_tlb_mm(mm) BTFIXUP_CALL(flush_tlb_mm)(mm)
46#define flush_tlb_range(vma,start,end) BTFIXUP_CALL(flush_tlb_range)(vma,start,end)
47#define flush_tlb_page(vma,addr) BTFIXUP_CALL(flush_tlb_page)(vma,addr)
48
49// #define flush_tlb() flush_tlb_mm(current->active_mm) /* XXX Sure? */
50 14
51/* 15/*
52 * This is a kludge, until I know better. --zaitcev XXX 16 * This is a kludge, until I know better. --zaitcev XXX
diff --git a/arch/sparc/include/asm/uaccess_32.h b/arch/sparc/include/asm/uaccess_32.h
index 8303ac481034..d50c310f5d38 100644
--- a/arch/sparc/include/asm/uaccess_32.h
+++ b/arch/sparc/include/asm/uaccess_32.h
@@ -12,7 +12,6 @@
12#include <linux/sched.h> 12#include <linux/sched.h>
13#include <linux/string.h> 13#include <linux/string.h>
14#include <linux/errno.h> 14#include <linux/errno.h>
15#include <asm/vac-ops.h>
16#endif 15#endif
17 16
18#ifndef __ASSEMBLY__ 17#ifndef __ASSEMBLY__
diff --git a/arch/sparc/include/asm/vac-ops.h b/arch/sparc/include/asm/vac-ops.h
deleted file mode 100644
index a63e88ef0426..000000000000
--- a/arch/sparc/include/asm/vac-ops.h
+++ /dev/null
@@ -1,127 +0,0 @@
1#ifndef _SPARC_VAC_OPS_H
2#define _SPARC_VAC_OPS_H
3
4/* vac-ops.h: Inline assembly routines to do operations on the Sparc
5 * VAC (virtual address cache) for the sun4c.
6 *
7 * Copyright (C) 1994, David S. Miller (davem@caip.rutgers.edu)
8 */
9
10#include <asm/sysen.h>
11#include <asm/contregs.h>
12#include <asm/asi.h>
13
14/* The SUN4C models have a virtually addressed write-through
15 * cache.
16 *
17 * The cache tags are directly accessible through an ASI and
18 * each have the form:
19 *
20 * ------------------------------------------------------------
21 * | MBZ | CONTEXT | WRITE | PRIV | VALID | MBZ | TagID | MBZ |
22 * ------------------------------------------------------------
23 * 31 25 24 22 21 20 19 18 16 15 2 1 0
24 *
25 * MBZ: These bits are either unused and/or reserved and should
26 * be written as zeroes.
27 *
28 * CONTEXT: Records the context to which this cache line belongs.
29 *
30 * WRITE: A copy of the writable bit from the mmu pte access bits.
31 *
32 * PRIV: A copy of the privileged bit from the pte access bits.
33 *
34 * VALID: If set, this line is valid, else invalid.
35 *
36 * TagID: Fourteen bits of tag ID.
37 *
38 * Every virtual address is seen by the cache like this:
39 *
40 * ----------------------------------------
41 * | RESV | TagID | LINE | BYTE-in-LINE |
42 * ----------------------------------------
43 * 31 30 29 16 15 4 3 0
44 *
45 * RESV: Unused/reserved.
46 *
47 * TagID: Used to match the Tag-ID in that vac tags.
48 *
49 * LINE: Which line within the cache
50 *
51 * BYTE-in-LINE: Which byte within the cache line.
52 */
53
54/* Sun4c VAC Tags */
55#define S4CVACTAG_CID 0x01c00000
56#define S4CVACTAG_W 0x00200000
57#define S4CVACTAG_P 0x00100000
58#define S4CVACTAG_V 0x00080000
59#define S4CVACTAG_TID 0x0000fffc
60
61/* Sun4c VAC Virtual Address */
62/* These aren't used, why bother? (Anton) */
63#if 0
64#define S4CVACVA_TID 0x3fff0000
65#define S4CVACVA_LINE 0x0000fff0
66#define S4CVACVA_BIL 0x0000000f
67#endif
68
69/* The indexing of cache lines creates a problem. Because the line
70 * field of a virtual address extends past the page offset within
71 * the virtual address it is possible to have what are called
72 * 'bad aliases' which will create inconsistencies. So we must make
73 * sure that within a context that if a physical page is mapped
74 * more than once, that 'extra' line bits are the same. If this is
75 * not the case, and thus is a 'bad alias' we must turn off the
76 * cacheable bit in the pte's of all such pages.
77 */
78
79#define S4CVAC_BADBITS 0x0000f000
80
81/* The following is true if vaddr1 and vaddr2 would cause
82 * a 'bad alias'.
83 */
84#define S4CVAC_BADALIAS(vaddr1, vaddr2) \
85 ((((unsigned long) (vaddr1)) ^ ((unsigned long) (vaddr2))) & \
86 (S4CVAC_BADBITS))
87
88/* The following structure describes the characteristics of a sun4c
89 * VAC as probed from the prom during boot time.
90 */
91struct sun4c_vac_props {
92 unsigned int num_bytes; /* Size of the cache */
93 unsigned int do_hwflushes; /* Hardware flushing available? */
94 unsigned int linesize; /* Size of each line in bytes */
95 unsigned int log2lsize; /* log2(linesize) */
96 unsigned int on; /* VAC is enabled */
97};
98
99extern struct sun4c_vac_props sun4c_vacinfo;
100
101/* sun4c_enable_vac() enables the sun4c virtual address cache. */
102static inline void sun4c_enable_vac(void)
103{
104 __asm__ __volatile__("lduba [%0] %1, %%g1\n\t"
105 "or %%g1, %2, %%g1\n\t"
106 "stba %%g1, [%0] %1\n\t"
107 : /* no outputs */
108 : "r" ((unsigned int) AC_SENABLE),
109 "i" (ASI_CONTROL), "i" (SENABLE_CACHE)
110 : "g1", "memory");
111 sun4c_vacinfo.on = 1;
112}
113
114/* sun4c_disable_vac() disables the virtual address cache. */
115static inline void sun4c_disable_vac(void)
116{
117 __asm__ __volatile__("lduba [%0] %1, %%g1\n\t"
118 "andn %%g1, %2, %%g1\n\t"
119 "stba %%g1, [%0] %1\n\t"
120 : /* no outputs */
121 : "r" ((unsigned int) AC_SENABLE),
122 "i" (ASI_CONTROL), "i" (SENABLE_CACHE)
123 : "g1", "memory");
124 sun4c_vacinfo.on = 0;
125}
126
127#endif /* !(_SPARC_VAC_OPS_H) */
diff --git a/arch/sparc/include/asm/vaddrs.h b/arch/sparc/include/asm/vaddrs.h
index 541e13755cec..da6535d88a72 100644
--- a/arch/sparc/include/asm/vaddrs.h
+++ b/arch/sparc/include/asm/vaddrs.h
@@ -34,22 +34,6 @@
34#define IOBASE_VADDR 0xfe000000 34#define IOBASE_VADDR 0xfe000000
35#define IOBASE_END 0xfe600000 35#define IOBASE_END 0xfe600000
36 36
37/*
38 * On the sun4/4c we need a place
39 * to reliably map locked down kernel data. This includes the
40 * task_struct and kernel stack pages of each process plus the
41 * scsi buffers during dvma IO transfers, also the floppy buffers
42 * during pseudo dma which runs with traps off (no faults allowed).
43 * Some quick calculations yield:
44 * NR_TASKS <512> * (3 * PAGE_SIZE) == 0x600000
45 * Subtract this from 0xc00000 and you get 0x927C0 of vm left
46 * over to map SCSI dvma + floppy pseudo-dma buffers. So be
47 * careful if you change NR_TASKS or else there won't be enough
48 * room for it all.
49 */
50#define SUN4C_LOCK_VADDR 0xff000000
51#define SUN4C_LOCK_END 0xffc00000
52
53#define KADB_DEBUGGER_BEGVM 0xffc00000 /* Where kern debugger is in virt-mem */ 37#define KADB_DEBUGGER_BEGVM 0xffc00000 /* Where kern debugger is in virt-mem */
54#define KADB_DEBUGGER_ENDVM 0xffd00000 38#define KADB_DEBUGGER_ENDVM 0xffd00000
55#define DEBUG_FIRSTVADDR KADB_DEBUGGER_BEGVM 39#define DEBUG_FIRSTVADDR KADB_DEBUGGER_BEGVM
diff --git a/arch/sparc/include/asm/winmacro.h b/arch/sparc/include/asm/winmacro.h
index a9be04b0d049..9b7b21764cde 100644
--- a/arch/sparc/include/asm/winmacro.h
+++ b/arch/sparc/include/asm/winmacro.h
@@ -103,37 +103,24 @@
103 st %scratch, [%cur_reg + TI_W_SAVED]; 103 st %scratch, [%cur_reg + TI_W_SAVED];
104 104
105#ifdef CONFIG_SMP 105#ifdef CONFIG_SMP
106/* Results of LOAD_CURRENT() after BTFIXUP for SUN4M, SUN4D & LEON (comments) */ 106#define LOAD_CURRENT(dest_reg, idreg) \
107#define LOAD_CURRENT4M(dest_reg, idreg) \ 107661: rd %tbr, %idreg; \
108 rd %tbr, %idreg; \ 108 srl %idreg, 10, %idreg; \
109 sethi %hi(current_set), %dest_reg; \ 109 and %idreg, 0xc, %idreg; \
110 srl %idreg, 10, %idreg; \ 110 .section .cpuid_patch, "ax"; \
111 or %dest_reg, %lo(current_set), %dest_reg; \ 111 /* Instruction location. */ \
112 and %idreg, 0xc, %idreg; \ 112 .word 661b; \
113 ld [%idreg + %dest_reg], %dest_reg; 113 /* SUN4D implementation. */ \
114 114 lda [%g0] ASI_M_VIKING_TMP1, %idreg; \
115#define LOAD_CURRENT4D(dest_reg, idreg) \ 115 sll %idreg, 2, %idreg; \
116 lda [%g0] ASI_M_VIKING_TMP1, %idreg; \ 116 nop; \
117 sethi %hi(C_LABEL(current_set)), %dest_reg; \ 117 /* LEON implementation. */ \
118 sll %idreg, 2, %idreg; \ 118 rd %asr17, %idreg; \
119 or %dest_reg, %lo(C_LABEL(current_set)), %dest_reg; \ 119 srl %idreg, 0x1c, %idreg; \
120 ld [%idreg + %dest_reg], %dest_reg; 120 sll %idreg, 0x02, %idreg; \
121 121 .previous; \
122#define LOAD_CURRENT_LEON(dest_reg, idreg) \ 122 sethi %hi(current_set), %dest_reg; \
123 rd %asr17, %idreg; \ 123 or %dest_reg, %lo(current_set), %dest_reg;\
124 sethi %hi(current_set), %dest_reg; \
125 srl %idreg, 0x1c, %idreg; \
126 or %dest_reg, %lo(current_set), %dest_reg; \
127 sll %idreg, 0x2, %idreg; \
128 ld [%idreg + %dest_reg], %dest_reg;
129
130/* Blackbox - take care with this... - check smp4m and smp4d before changing this. */
131#define LOAD_CURRENT(dest_reg, idreg) \
132 sethi %hi(___b_load_current), %idreg; \
133 sethi %hi(current_set), %dest_reg; \
134 sethi %hi(boot_cpu_id4), %idreg; \
135 or %dest_reg, %lo(current_set), %dest_reg; \
136 ldub [%idreg + %lo(boot_cpu_id4)], %idreg; \
137 ld [%idreg + %dest_reg], %dest_reg; 124 ld [%idreg + %dest_reg], %dest_reg;
138#else 125#else
139#define LOAD_CURRENT(dest_reg, idreg) \ 126#define LOAD_CURRENT(dest_reg, idreg) \
diff --git a/arch/sparc/kernel/Makefile b/arch/sparc/kernel/Makefile
index cb85458f89d2..c19dd022b9cb 100644
--- a/arch/sparc/kernel/Makefile
+++ b/arch/sparc/kernel/Makefile
@@ -28,7 +28,7 @@ obj-y += traps_$(BITS).o
28 28
29# IRQ 29# IRQ
30obj-y += irq_$(BITS).o 30obj-y += irq_$(BITS).o
31obj-$(CONFIG_SPARC32) += sun4m_irq.o sun4c_irq.o sun4d_irq.o 31obj-$(CONFIG_SPARC32) += sun4m_irq.o sun4d_irq.o
32 32
33obj-y += process_$(BITS).o 33obj-y += process_$(BITS).o
34obj-y += signal_$(BITS).o 34obj-y += signal_$(BITS).o
@@ -46,7 +46,6 @@ obj-$(CONFIG_SPARC32) += tadpole.o
46obj-y += ptrace_$(BITS).o 46obj-y += ptrace_$(BITS).o
47obj-y += unaligned_$(BITS).o 47obj-y += unaligned_$(BITS).o
48obj-y += una_asm_$(BITS).o 48obj-y += una_asm_$(BITS).o
49obj-$(CONFIG_SPARC32) += muldiv.o
50obj-y += prom_common.o 49obj-y += prom_common.o
51obj-y += prom_$(BITS).o 50obj-y += prom_$(BITS).o
52obj-y += of_device_common.o 51obj-y += of_device_common.o
diff --git a/arch/sparc/kernel/auxio_32.c b/arch/sparc/kernel/auxio_32.c
index 56d0f52c3e62..e20cc55fb768 100644
--- a/arch/sparc/kernel/auxio_32.c
+++ b/arch/sparc/kernel/auxio_32.c
@@ -32,7 +32,6 @@ void __init auxio_probe(void)
32 switch (sparc_cpu_model) { 32 switch (sparc_cpu_model) {
33 case sparc_leon: 33 case sparc_leon:
34 case sun4d: 34 case sun4d:
35 case sun4:
36 return; 35 return;
37 default: 36 default:
38 break; 37 break;
@@ -65,9 +64,8 @@ void __init auxio_probe(void)
65 r.start = auxregs[0].phys_addr; 64 r.start = auxregs[0].phys_addr;
66 r.end = auxregs[0].phys_addr + auxregs[0].reg_size - 1; 65 r.end = auxregs[0].phys_addr + auxregs[0].reg_size - 1;
67 auxio_register = of_ioremap(&r, 0, auxregs[0].reg_size, "auxio"); 66 auxio_register = of_ioremap(&r, 0, auxregs[0].reg_size, "auxio");
68 /* Fix the address on sun4m and sun4c. */ 67 /* Fix the address on sun4m. */
69 if((((unsigned long) auxregs[0].phys_addr) & 3) == 3 || 68 if ((((unsigned long) auxregs[0].phys_addr) & 3) == 3)
70 sparc_cpu_model == sun4c)
71 auxio_register += (3 - ((unsigned long)auxio_register & 3)); 69 auxio_register += (3 - ((unsigned long)auxio_register & 3));
72 70
73 set_auxio(AUXIO_LED, 0); 71 set_auxio(AUXIO_LED, 0);
@@ -86,12 +84,7 @@ void set_auxio(unsigned char bits_on, unsigned char bits_off)
86 unsigned char regval; 84 unsigned char regval;
87 unsigned long flags; 85 unsigned long flags;
88 spin_lock_irqsave(&auxio_lock, flags); 86 spin_lock_irqsave(&auxio_lock, flags);
89 switch(sparc_cpu_model) { 87 switch (sparc_cpu_model) {
90 case sun4c:
91 regval = sbus_readb(auxio_register);
92 sbus_writeb(((regval | bits_on) & ~bits_off) | AUXIO_ORMEIN,
93 auxio_register);
94 break;
95 case sun4m: 88 case sun4m:
96 if(!auxio_register) 89 if(!auxio_register)
97 break; /* VME chassis sun4m, no auxio. */ 90 break; /* VME chassis sun4m, no auxio. */
diff --git a/arch/sparc/kernel/devices.c b/arch/sparc/kernel/devices.c
index 6b2f56a6f8af..3d465e87f7e2 100644
--- a/arch/sparc/kernel/devices.c
+++ b/arch/sparc/kernel/devices.c
@@ -21,7 +21,6 @@
21#include <asm/cpu_type.h> 21#include <asm/cpu_type.h>
22 22
23extern void clock_stop_probe(void); /* tadpole.c */ 23extern void clock_stop_probe(void); /* tadpole.c */
24extern void sun4c_probe_memerr_reg(void);
25 24
26static char *cpu_mid_prop(void) 25static char *cpu_mid_prop(void)
27{ 26{
@@ -139,7 +138,4 @@ void __init device_scan(void)
139 auxio_power_probe(); 138 auxio_power_probe();
140 } 139 }
141 clock_stop_probe(); 140 clock_stop_probe();
142
143 if (ARCH_SUN4C)
144 sun4c_probe_memerr_reg();
145} 141}
diff --git a/arch/sparc/kernel/ds.c b/arch/sparc/kernel/ds.c
index b93c2c9ccb1d..f09257c86107 100644
--- a/arch/sparc/kernel/ds.c
+++ b/arch/sparc/kernel/ds.c
@@ -868,7 +868,7 @@ void ldom_power_off(void)
868 868
869static void ds_conn_reset(struct ds_info *dp) 869static void ds_conn_reset(struct ds_info *dp)
870{ 870{
871 printk(KERN_ERR "ds-%llu: ds_conn_reset() from %p\n", 871 printk(KERN_ERR "ds-%llu: ds_conn_reset() from %pf\n",
872 dp->id, __builtin_return_address(0)); 872 dp->id, __builtin_return_address(0));
873} 873}
874 874
diff --git a/arch/sparc/kernel/entry.S b/arch/sparc/kernel/entry.S
index f445e98463e6..2dbe1806e530 100644
--- a/arch/sparc/kernel/entry.S
+++ b/arch/sparc/kernel/entry.S
@@ -7,6 +7,7 @@
7 * Copyright (C) 1997 Anton Blanchard (anton@progsoc.uts.edu.au) 7 * Copyright (C) 1997 Anton Blanchard (anton@progsoc.uts.edu.au)
8 */ 8 */
9 9
10#include <linux/linkage.h>
10#include <linux/errno.h> 11#include <linux/errno.h>
11 12
12#include <asm/head.h> 13#include <asm/head.h>
@@ -17,10 +18,8 @@
17#include <asm/asm-offsets.h> 18#include <asm/asm-offsets.h>
18#include <asm/psr.h> 19#include <asm/psr.h>
19#include <asm/vaddrs.h> 20#include <asm/vaddrs.h>
20#include <asm/memreg.h>
21#include <asm/page.h> 21#include <asm/page.h>
22#include <asm/pgtable.h> 22#include <asm/pgtable.h>
23#include <asm/pgtsun4c.h>
24#include <asm/winmacro.h> 23#include <asm/winmacro.h>
25#include <asm/signal.h> 24#include <asm/signal.h>
26#include <asm/obio.h> 25#include <asm/obio.h>
@@ -125,22 +124,11 @@ floppy_tdone:
125 set auxio_register, %l7 124 set auxio_register, %l7
126 ld [%l7], %l7 125 ld [%l7], %l7
127 126
128 set sparc_cpu_model, %l5 127 ldub [%l7], %l5
129 ld [%l5], %l5
130 subcc %l5, 1, %g0 /* enum { sun4c = 1 }; */
131 be 1f
132 ldub [%l7], %l5
133 128
134 or %l5, 0xc2, %l5 129 or %l5, 0xc2, %l5
135 stb %l5, [%l7] 130 stb %l5, [%l7]
136 andn %l5, 0x02, %l5 131 andn %l5, 0x02, %l5
137 b 2f
138 nop
139
1401:
141 or %l5, 0xf4, %l5
142 stb %l5, [%l7]
143 andn %l5, 0x04, %l5
144 132
1452: 1332:
146 /* Kill some time so the bits set */ 134 /* Kill some time so the bits set */
@@ -266,6 +254,11 @@ smp4m_ticker:
266 WRITE_PAUSE 254 WRITE_PAUSE
267 RESTORE_ALL 255 RESTORE_ALL
268 256
257#define GET_PROCESSOR4M_ID(reg) \
258 rd %tbr, %reg; \
259 srl %reg, 12, %reg; \
260 and %reg, 3, %reg;
261
269 /* Here is where we check for possible SMP IPI passed to us 262 /* Here is where we check for possible SMP IPI passed to us
270 * on some level other than 15 which is the NMI and only used 263 * on some level other than 15 which is the NMI and only used
271 * for cross calls. That has a separate entry point below. 264 * for cross calls. That has a separate entry point below.
@@ -328,7 +321,7 @@ linux_trap_ipi15_sun4m:
328 ld [%o5 + %o0], %o5 321 ld [%o5 + %o0], %o5
329 ld [%o5 + 0x00], %o3 ! sun4m_irq_percpu[cpu]->pending 322 ld [%o5 + 0x00], %o3 ! sun4m_irq_percpu[cpu]->pending
330 andcc %o3, %o2, %g0 323 andcc %o3, %o2, %g0
331 be 1f ! Must be an NMI async memory error 324 be sun4m_nmi_error ! Must be an NMI async memory error
332 st %o2, [%o5 + 0x04] ! sun4m_irq_percpu[cpu]->clear=0x80000000 325 st %o2, [%o5 + 0x04] ! sun4m_irq_percpu[cpu]->clear=0x80000000
333 WRITE_PAUSE 326 WRITE_PAUSE
334 ld [%o5 + 0x00], %g0 ! sun4m_irq_percpu[cpu]->pending 327 ld [%o5 + 0x00], %g0 ! sun4m_irq_percpu[cpu]->pending
@@ -342,27 +335,6 @@ linux_trap_ipi15_sun4m:
342 nop 335 nop
343 b ret_trap_lockless_ipi 336 b ret_trap_lockless_ipi
344 clr %l6 337 clr %l6
3451:
346 /* NMI async memory error handling. */
347 sethi %hi(0x80000000), %l4
348 sethi %hi(sun4m_irq_global), %o5
349 ld [%o5 + %lo(sun4m_irq_global)], %l5
350 st %l4, [%l5 + 0x0c] ! sun4m_irq_global->mask_set=0x80000000
351 WRITE_PAUSE
352 ld [%l5 + 0x00], %g0 ! sun4m_irq_global->pending
353 WRITE_PAUSE
354 or %l0, PSR_PIL, %l4
355 wr %l4, 0x0, %psr
356 WRITE_PAUSE
357 wr %l4, PSR_ET, %psr
358 WRITE_PAUSE
359 call sun4m_nmi
360 nop
361 st %l4, [%l5 + 0x08] ! sun4m_irq_global->mask_clear=0x80000000
362 WRITE_PAUSE
363 ld [%l5 + 0x00], %g0 ! sun4m_irq_global->pending
364 WRITE_PAUSE
365 RESTORE_ALL
366 338
367 .globl smp4d_ticker 339 .globl smp4d_ticker
368 /* SMP per-cpu ticker interrupts are handled specially. */ 340 /* SMP per-cpu ticker interrupts are handled specially. */
@@ -760,326 +732,37 @@ setcc_trap_handler:
760 jmp %l2 ! advance over trap instruction 732 jmp %l2 ! advance over trap instruction
761 rett %l2 + 0x4 ! like this... 733 rett %l2 + 0x4 ! like this...
762 734
763 .align 4 735sun4m_nmi_error:
764 .globl linux_trap_nmi_sun4c 736 /* NMI async memory error handling. */
765linux_trap_nmi_sun4c: 737 sethi %hi(0x80000000), %l4
766 SAVE_ALL 738 sethi %hi(sun4m_irq_global), %o5
767 739 ld [%o5 + %lo(sun4m_irq_global)], %l5
768 /* Ugh, we need to clear the IRQ line. This is now 740 st %l4, [%l5 + 0x0c] ! sun4m_irq_global->mask_set=0x80000000
769 * a very sun4c specific trap handler...
770 */
771 sethi %hi(interrupt_enable), %l5
772 ld [%l5 + %lo(interrupt_enable)], %l5
773 ldub [%l5], %l6
774 andn %l6, INTS_ENAB, %l6
775 stb %l6, [%l5]
776
777 /* Now it is safe to re-enable traps without recursion. */
778 or %l0, PSR_PIL, %l0
779 wr %l0, PSR_ET, %psr
780 WRITE_PAUSE 741 WRITE_PAUSE
781 742 ld [%l5 + 0x00], %g0 ! sun4m_irq_global->pending
782 /* Now call the c-code with the pt_regs frame ptr and the
783 * memory error registers as arguments. The ordering chosen
784 * here is due to unlatching semantics.
785 */
786 sethi %hi(AC_SYNC_ERR), %o0
787 add %o0, 0x4, %o0
788 lda [%o0] ASI_CONTROL, %o2 ! sync vaddr
789 sub %o0, 0x4, %o0
790 lda [%o0] ASI_CONTROL, %o1 ! sync error
791 add %o0, 0xc, %o0
792 lda [%o0] ASI_CONTROL, %o4 ! async vaddr
793 sub %o0, 0x4, %o0
794 lda [%o0] ASI_CONTROL, %o3 ! async error
795 call sparc_lvl15_nmi
796 add %sp, STACKFRAME_SZ, %o0
797
798 RESTORE_ALL
799
800 .align 4
801 .globl invalid_segment_patch1_ff
802 .globl invalid_segment_patch2_ff
803invalid_segment_patch1_ff: cmp %l4, 0xff
804invalid_segment_patch2_ff: mov 0xff, %l3
805
806 .align 4
807 .globl invalid_segment_patch1_1ff
808 .globl invalid_segment_patch2_1ff
809invalid_segment_patch1_1ff: cmp %l4, 0x1ff
810invalid_segment_patch2_1ff: mov 0x1ff, %l3
811
812 .align 4
813 .globl num_context_patch1_16, num_context_patch2_16
814num_context_patch1_16: mov 0x10, %l7
815num_context_patch2_16: mov 0x10, %l7
816
817 .align 4
818 .globl vac_linesize_patch_32
819vac_linesize_patch_32: subcc %l7, 32, %l7
820
821 .align 4
822 .globl vac_hwflush_patch1_on, vac_hwflush_patch2_on
823
824/*
825 * Ugly, but we can't use hardware flushing on the sun4 and we'd require
826 * two instructions (Anton)
827 */
828vac_hwflush_patch1_on: addcc %l7, -PAGE_SIZE, %l7
829
830vac_hwflush_patch2_on: sta %g0, [%l3 + %l7] ASI_HWFLUSHSEG
831
832 .globl invalid_segment_patch1, invalid_segment_patch2
833 .globl num_context_patch1
834 .globl vac_linesize_patch, vac_hwflush_patch1
835 .globl vac_hwflush_patch2
836
837 .align 4
838 .globl sun4c_fault
839
840! %l0 = %psr
841! %l1 = %pc
842! %l2 = %npc
843! %l3 = %wim
844! %l7 = 1 for textfault
845! We want error in %l5, vaddr in %l6
846sun4c_fault:
847 sethi %hi(AC_SYNC_ERR), %l4
848 add %l4, 0x4, %l6 ! AC_SYNC_VA in %l6
849 lda [%l6] ASI_CONTROL, %l5 ! Address
850 lda [%l4] ASI_CONTROL, %l6 ! Error, retained for a bit
851
852 andn %l5, 0xfff, %l5 ! Encode all info into l7
853 srl %l6, 14, %l4
854
855 and %l4, 2, %l4
856 or %l5, %l4, %l4
857
858 or %l4, %l7, %l7 ! l7 = [addr,write,txtfault]
859
860 andcc %l0, PSR_PS, %g0
861 be sun4c_fault_fromuser
862 andcc %l7, 1, %g0 ! Text fault?
863
864 be 1f
865 sethi %hi(KERNBASE), %l4
866
867 mov %l1, %l5 ! PC
868
8691:
870 cmp %l5, %l4
871 blu sun4c_fault_fromuser
872 sethi %hi(~((1 << SUN4C_REAL_PGDIR_SHIFT) - 1)), %l4
873
874 /* If the kernel references a bum kernel pointer, or a pte which
875 * points to a non existent page in ram, we will run this code
876 * _forever_ and lock up the machine!!!!! So we must check for
877 * this condition, the AC_SYNC_ERR bits are what we must examine.
878 * Also a parity error would make this happen as well. So we just
879 * check that we are in fact servicing a tlb miss and not some
880 * other type of fault for the kernel.
881 */
882 andcc %l6, 0x80, %g0
883 be sun4c_fault_fromuser
884 and %l5, %l4, %l5
885
886 /* Test for NULL pte_t * in vmalloc area. */
887 sethi %hi(VMALLOC_START), %l4
888 cmp %l5, %l4
889 blu,a invalid_segment_patch1
890 lduXa [%l5] ASI_SEGMAP, %l4
891
892 sethi %hi(swapper_pg_dir), %l4
893 srl %l5, SUN4C_PGDIR_SHIFT, %l6
894 or %l4, %lo(swapper_pg_dir), %l4
895 sll %l6, 2, %l6
896 ld [%l4 + %l6], %l4
897 andcc %l4, PAGE_MASK, %g0
898 be sun4c_fault_fromuser
899 lduXa [%l5] ASI_SEGMAP, %l4
900
901invalid_segment_patch1:
902 cmp %l4, 0x7f
903 bne 1f
904 sethi %hi(sun4c_kfree_ring), %l4
905 or %l4, %lo(sun4c_kfree_ring), %l4
906 ld [%l4 + 0x18], %l3
907 deccc %l3 ! do we have a free entry?
908 bcs,a 2f ! no, unmap one.
909 sethi %hi(sun4c_kernel_ring), %l4
910
911 st %l3, [%l4 + 0x18] ! sun4c_kfree_ring.num_entries--
912
913 ld [%l4 + 0x00], %l6 ! entry = sun4c_kfree_ring.ringhd.next
914 st %l5, [%l6 + 0x08] ! entry->vaddr = address
915
916 ld [%l6 + 0x00], %l3 ! next = entry->next
917 ld [%l6 + 0x04], %l7 ! entry->prev
918
919 st %l7, [%l3 + 0x04] ! next->prev = entry->prev
920 st %l3, [%l7 + 0x00] ! entry->prev->next = next
921
922 sethi %hi(sun4c_kernel_ring), %l4
923 or %l4, %lo(sun4c_kernel_ring), %l4
924 ! head = &sun4c_kernel_ring.ringhd
925
926 ld [%l4 + 0x00], %l7 ! head->next
927
928 st %l4, [%l6 + 0x04] ! entry->prev = head
929 st %l7, [%l6 + 0x00] ! entry->next = head->next
930 st %l6, [%l7 + 0x04] ! head->next->prev = entry
931
932 st %l6, [%l4 + 0x00] ! head->next = entry
933
934 ld [%l4 + 0x18], %l3
935 inc %l3 ! sun4c_kernel_ring.num_entries++
936 st %l3, [%l4 + 0x18]
937 b 4f
938 ld [%l6 + 0x08], %l5
939
9402:
941 or %l4, %lo(sun4c_kernel_ring), %l4
942 ! head = &sun4c_kernel_ring.ringhd
943
944 ld [%l4 + 0x04], %l6 ! entry = head->prev
945
946 ld [%l6 + 0x08], %l3 ! tmp = entry->vaddr
947
948 ! Flush segment from the cache.
949 sethi %hi((64 * 1024)), %l7
9509:
951vac_hwflush_patch1:
952vac_linesize_patch:
953 subcc %l7, 16, %l7
954 bne 9b
955vac_hwflush_patch2:
956 sta %g0, [%l3 + %l7] ASI_FLUSHSEG
957
958 st %l5, [%l6 + 0x08] ! entry->vaddr = address
959
960 ld [%l6 + 0x00], %l5 ! next = entry->next
961 ld [%l6 + 0x04], %l7 ! entry->prev
962
963 st %l7, [%l5 + 0x04] ! next->prev = entry->prev
964 st %l5, [%l7 + 0x00] ! entry->prev->next = next
965 st %l4, [%l6 + 0x04] ! entry->prev = head
966
967 ld [%l4 + 0x00], %l7 ! head->next
968
969 st %l7, [%l6 + 0x00] ! entry->next = head->next
970 st %l6, [%l7 + 0x04] ! head->next->prev = entry
971 st %l6, [%l4 + 0x00] ! head->next = entry
972
973 mov %l3, %l5 ! address = tmp
974
9754:
976num_context_patch1:
977 mov 0x08, %l7
978
979 ld [%l6 + 0x08], %l4
980 ldub [%l6 + 0x0c], %l3
981 or %l4, %l3, %l4 ! encode new vaddr/pseg into l4
982
983 sethi %hi(AC_CONTEXT), %l3
984 lduba [%l3] ASI_CONTROL, %l6
985
986 /* Invalidate old mapping, instantiate new mapping,
987 * for each context. Registers l6/l7 are live across
988 * this loop.
989 */
9903: deccc %l7
991 sethi %hi(AC_CONTEXT), %l3
992 stba %l7, [%l3] ASI_CONTROL
993invalid_segment_patch2:
994 mov 0x7f, %l3
995 stXa %l3, [%l5] ASI_SEGMAP
996 andn %l4, 0x1ff, %l3
997 bne 3b
998 stXa %l4, [%l3] ASI_SEGMAP
999
1000 sethi %hi(AC_CONTEXT), %l3
1001 stba %l6, [%l3] ASI_CONTROL
1002
1003 andn %l4, 0x1ff, %l5
1004
10051:
1006 sethi %hi(VMALLOC_START), %l4
1007 cmp %l5, %l4
1008
1009 bgeu 1f
1010 mov 1 << (SUN4C_REAL_PGDIR_SHIFT - PAGE_SHIFT), %l7
1011
1012 sethi %hi(KERNBASE), %l6
1013
1014 sub %l5, %l6, %l4
1015 srl %l4, PAGE_SHIFT, %l4
1016 sethi %hi((SUN4C_PAGE_KERNEL & 0xf4000000)), %l3
1017 or %l3, %l4, %l3
1018
1019 sethi %hi(PAGE_SIZE), %l4
1020
10212:
1022 sta %l3, [%l5] ASI_PTE
1023 deccc %l7
1024 inc %l3
1025 bne 2b
1026 add %l5, %l4, %l5
1027
1028 b 7f
1029 sethi %hi(sun4c_kernel_faults), %l4
1030
10311:
1032 srl %l5, SUN4C_PGDIR_SHIFT, %l3
1033 sethi %hi(swapper_pg_dir), %l4
1034 or %l4, %lo(swapper_pg_dir), %l4
1035 sll %l3, 2, %l3
1036 ld [%l4 + %l3], %l4
1037 and %l4, PAGE_MASK, %l4
1038
1039 srl %l5, (PAGE_SHIFT - 2), %l6
1040 and %l6, ((SUN4C_PTRS_PER_PTE - 1) << 2), %l6
1041 add %l6, %l4, %l6
1042
1043 sethi %hi(PAGE_SIZE), %l4
1044
10452:
1046 ld [%l6], %l3
1047 deccc %l7
1048 sta %l3, [%l5] ASI_PTE
1049 add %l6, 0x4, %l6
1050 bne 2b
1051 add %l5, %l4, %l5
1052
1053 sethi %hi(sun4c_kernel_faults), %l4
10547:
1055 ld [%l4 + %lo(sun4c_kernel_faults)], %l3
1056 inc %l3
1057 st %l3, [%l4 + %lo(sun4c_kernel_faults)]
1058
1059 /* Restore condition codes */
1060 wr %l0, 0x0, %psr
1061 WRITE_PAUSE 743 WRITE_PAUSE
1062 jmp %l1 744 or %l0, PSR_PIL, %l4
1063 rett %l2 745 wr %l4, 0x0, %psr
1064 746 WRITE_PAUSE
1065sun4c_fault_fromuser: 747 wr %l4, PSR_ET, %psr
1066 SAVE_ALL 748 WRITE_PAUSE
749 call sun4m_nmi
1067 nop 750 nop
1068 751 st %l4, [%l5 + 0x08] ! sun4m_irq_global->mask_clear=0x80000000
1069 mov %l7, %o1 ! Decode the info from %l7
1070 mov %l7, %o2
1071 and %o1, 1, %o1 ! arg2 = text_faultp
1072 mov %l7, %o3
1073 and %o2, 2, %o2 ! arg3 = writep
1074 andn %o3, 0xfff, %o3 ! arg4 = faulting address
1075
1076 wr %l0, PSR_ET, %psr
1077 WRITE_PAUSE 752 WRITE_PAUSE
753 ld [%l5 + 0x00], %g0 ! sun4m_irq_global->pending
754 WRITE_PAUSE
755 RESTORE_ALL
1078 756
1079 call do_sun4c_fault 757#ifndef CONFIG_SMP
1080 add %sp, STACKFRAME_SZ, %o0 ! arg1 = pt_regs ptr 758 .align 4
759 .globl linux_trap_ipi15_sun4m
760linux_trap_ipi15_sun4m:
761 SAVE_ALL
1081 762
1082 RESTORE_ALL 763 ba sun4m_nmi_error
764 nop
765#endif /* CONFIG_SMP */
1083 766
1084 .align 4 767 .align 4
1085 .globl srmmu_fault 768 .globl srmmu_fault
@@ -1483,11 +1166,13 @@ fpload:
1483 .globl __ndelay 1166 .globl __ndelay
1484__ndelay: 1167__ndelay:
1485 save %sp, -STACKFRAME_SZ, %sp 1168 save %sp, -STACKFRAME_SZ, %sp
1486 mov %i0, %o0 1169 mov %i0, %o0 ! round multiplier up so large ns ok
1487 call .umul ! round multiplier up so large ns ok 1170 mov 0x1ae, %o1 ! 2**32 / (1 000 000 000 / HZ)
1488 mov 0x1ae, %o1 ! 2**32 / (1 000 000 000 / HZ) 1171 umul %o0, %o1, %o0
1489 call .umul 1172 rd %y, %o1
1490 mov %i1, %o1 ! udelay_val 1173 mov %i1, %o1 ! udelay_val
1174 umul %o0, %o1, %o0
1175 rd %y, %o1
1491 ba delay_continue 1176 ba delay_continue
1492 mov %o1, %o0 ! >>32 later for better resolution 1177 mov %o1, %o0 ! >>32 later for better resolution
1493 1178
@@ -1496,18 +1181,21 @@ __udelay:
1496 save %sp, -STACKFRAME_SZ, %sp 1181 save %sp, -STACKFRAME_SZ, %sp
1497 mov %i0, %o0 1182 mov %i0, %o0
1498 sethi %hi(0x10c7), %o1 ! round multiplier up so large us ok 1183 sethi %hi(0x10c7), %o1 ! round multiplier up so large us ok
1499 call .umul 1184 or %o1, %lo(0x10c7), %o1 ! 2**32 / 1 000 000
1500 or %o1, %lo(0x10c7), %o1 ! 2**32 / 1 000 000 1185 umul %o0, %o1, %o0
1501 call .umul 1186 rd %y, %o1
1502 mov %i1, %o1 ! udelay_val 1187 mov %i1, %o1 ! udelay_val
1188 umul %o0, %o1, %o0
1189 rd %y, %o1
1503 sethi %hi(0x028f4b62), %l0 ! Add in rounding constant * 2**32, 1190 sethi %hi(0x028f4b62), %l0 ! Add in rounding constant * 2**32,
1504 or %g0, %lo(0x028f4b62), %l0 1191 or %g0, %lo(0x028f4b62), %l0
1505 addcc %o0, %l0, %o0 ! 2**32 * 0.009 999 1192 addcc %o0, %l0, %o0 ! 2**32 * 0.009 999
1506 bcs,a 3f 1193 bcs,a 3f
1507 add %o1, 0x01, %o1 1194 add %o1, 0x01, %o1
15083: 11953:
1509 call .umul 1196 mov HZ, %o0 ! >>32 earlier for wider range
1510 mov HZ, %o0 ! >>32 earlier for wider range 1197 umul %o0, %o1, %o0
1198 rd %y, %o1
1511 1199
1512delay_continue: 1200delay_continue:
1513 cmp %o0, 0x0 1201 cmp %o0, 0x0
@@ -1670,4 +1358,26 @@ flushw_all:
1670 ret 1358 ret
1671 restore 1359 restore
1672 1360
1361#ifdef CONFIG_SMP
1362ENTRY(hard_smp_processor_id)
1363661: rd %tbr, %g1
1364 srl %g1, 12, %o0
1365 and %o0, 3, %o0
1366 .section .cpuid_patch, "ax"
1367 /* Instruction location. */
1368 .word 661b
1369 /* SUN4D implementation. */
1370 lda [%g0] ASI_M_VIKING_TMP1, %o0
1371 nop
1372 nop
1373 /* LEON implementation. */
1374 rd %asr17, %o0
1375 srl %o0, 0x1c, %o0
1376 nop
1377 .previous
1378 retl
1379 nop
1380ENDPROC(hard_smp_processor_id)
1381#endif
1382
1673/* End of entry.S */ 1383/* End of entry.S */
diff --git a/arch/sparc/kernel/etrap_32.S b/arch/sparc/kernel/etrap_32.S
index e806fcdc46db..84b5f0d2afde 100644
--- a/arch/sparc/kernel/etrap_32.S
+++ b/arch/sparc/kernel/etrap_32.S
@@ -216,9 +216,7 @@ tsetup_patch6:
216 /* Call MMU-architecture dependent stack checking 216 /* Call MMU-architecture dependent stack checking
217 * routine. 217 * routine.
218 */ 218 */
219 .globl tsetup_mmu_patchme 219 b tsetup_srmmu_stackchk
220tsetup_mmu_patchme:
221 b tsetup_sun4c_stackchk
222 andcc %sp, 0x7, %g0 220 andcc %sp, 0x7, %g0
223 221
224 /* Architecture specific stack checking routines. When either 222 /* Architecture specific stack checking routines. When either
@@ -228,52 +226,6 @@ tsetup_mmu_patchme:
228 */ 226 */
229#define glob_tmp g1 227#define glob_tmp g1
230 228
231tsetup_sun4c_stackchk:
232 /* Done by caller: andcc %sp, 0x7, %g0 */
233 bne trap_setup_user_stack_is_bolixed
234 sra %sp, 29, %glob_tmp
235
236 add %glob_tmp, 0x1, %glob_tmp
237 andncc %glob_tmp, 0x1, %g0
238 bne trap_setup_user_stack_is_bolixed
239 and %sp, 0xfff, %glob_tmp ! delay slot
240
241 /* See if our dump area will be on more than one
242 * page.
243 */
244 add %glob_tmp, 0x38, %glob_tmp
245 andncc %glob_tmp, 0xff8, %g0
246 be tsetup_sun4c_onepage ! only one page to check
247 lda [%sp] ASI_PTE, %glob_tmp ! have to check first page anyways
248
249tsetup_sun4c_twopages:
250 /* Is first page ok permission wise? */
251 srl %glob_tmp, 29, %glob_tmp
252 cmp %glob_tmp, 0x6
253 bne trap_setup_user_stack_is_bolixed
254 add %sp, 0x38, %glob_tmp /* Is second page in vma hole? */
255
256 sra %glob_tmp, 29, %glob_tmp
257 add %glob_tmp, 0x1, %glob_tmp
258 andncc %glob_tmp, 0x1, %g0
259 bne trap_setup_user_stack_is_bolixed
260 add %sp, 0x38, %glob_tmp
261
262 lda [%glob_tmp] ASI_PTE, %glob_tmp
263
264tsetup_sun4c_onepage:
265 srl %glob_tmp, 29, %glob_tmp
266 cmp %glob_tmp, 0x6 ! can user write to it?
267 bne trap_setup_user_stack_is_bolixed ! failure
268 nop
269
270 STORE_WINDOW(sp)
271
272 restore %g0, %g0, %g0
273
274 jmpl %t_retpc + 0x8, %g0
275 mov %t_kstack, %sp
276
277 .globl tsetup_srmmu_stackchk 229 .globl tsetup_srmmu_stackchk
278tsetup_srmmu_stackchk: 230tsetup_srmmu_stackchk:
279 /* Check results of callers andcc %sp, 0x7, %g0 */ 231 /* Check results of callers andcc %sp, 0x7, %g0 */
diff --git a/arch/sparc/kernel/head_32.S b/arch/sparc/kernel/head_32.S
index 587785759838..a0f5c20e4b9c 100644
--- a/arch/sparc/kernel/head_32.S
+++ b/arch/sparc/kernel/head_32.S
@@ -26,11 +26,9 @@
26#include <asm/pgtsrmmu.h> /* SRMMU_PGDIR_SHIFT */ 26#include <asm/pgtsrmmu.h> /* SRMMU_PGDIR_SHIFT */
27 27
28 .data 28 .data
29/* 29/* The following are used with the prom_vector node-ops to figure out
30 * The following are used with the prom_vector node-ops to figure out 30 * the cpu-type
31 * the cpu-type
32 */ 31 */
33
34 .align 4 32 .align 4
35cputyp: 33cputyp:
36 .word 1 34 .word 1
@@ -38,384 +36,35 @@ cputyp:
38 .align 4 36 .align 4
39 .globl cputypval 37 .globl cputypval
40cputypval: 38cputypval:
41 .asciz "sun4c" 39 .asciz "sun4m"
42 .ascii " " 40 .ascii " "
43 41
44cputypvalend: 42/* Tested on SS-5, SS-10 */
45cputypvallen = cputypvar - cputypval
46
47 .align 4 43 .align 4
48/*
49 * Sun people can't spell worth damn. "compatability" indeed.
50 * At least we *know* we can't spell, and use a spell-checker.
51 */
52
53/* Uh, actually Linus it is I who cannot spell. Too much murky
54 * Sparc assembly will do this to ya.
55 */
56cputypvar: 44cputypvar:
57 .asciz "compatability"
58
59/* Tested on SS-5, SS-10. Probably someone at Sun applied a spell-checker. */
60 .align 4
61cputypvar_sun4m:
62 .asciz "compatible" 45 .asciz "compatible"
63 46
64 .align 4 47 .align 4
65 48
66sun4_notsup: 49sun4c_notsup:
67 .asciz "Sparc-Linux sun4 support does no longer exist.\n\n" 50 .asciz "Sparc-Linux sun4/sun4c support does no longer exist.\n\n"
68 .align 4 51 .align 4
69 52
70sun4e_notsup: 53sun4e_notsup:
71 .asciz "Sparc-Linux sun4e support does not exist\n\n" 54 .asciz "Sparc-Linux sun4e support does not exist\n\n"
72 .align 4 55 .align 4
73 56
74 /* The Sparc trap table, bootloader gives us control at _start. */ 57/* The trap-table - located in the __HEAD section */
75 __HEAD 58#include "ttable_32.S"
76 .globl _stext, _start, __stext
77 .globl trapbase
78_start: /* danger danger */
79__stext:
80_stext:
81trapbase:
82#ifdef CONFIG_SMP
83trapbase_cpu0:
84#endif
85/* We get control passed to us here at t_zero. */
86t_zero: b gokernel; nop; nop; nop;
87t_tflt: SPARC_TFAULT /* Inst. Access Exception */
88t_bins: TRAP_ENTRY(0x2, bad_instruction) /* Illegal Instruction */
89t_pins: TRAP_ENTRY(0x3, priv_instruction) /* Privileged Instruction */
90t_fpd: TRAP_ENTRY(0x4, fpd_trap_handler) /* Floating Point Disabled */
91t_wovf: WINDOW_SPILL /* Window Overflow */
92t_wunf: WINDOW_FILL /* Window Underflow */
93t_mna: TRAP_ENTRY(0x7, mna_handler) /* Memory Address Not Aligned */
94t_fpe: TRAP_ENTRY(0x8, fpe_trap_handler) /* Floating Point Exception */
95t_dflt: SPARC_DFAULT /* Data Miss Exception */
96t_tio: TRAP_ENTRY(0xa, do_tag_overflow) /* Tagged Instruction Ovrflw */
97t_wpt: TRAP_ENTRY(0xb, do_watchpoint) /* Watchpoint Detected */
98t_badc: BAD_TRAP(0xc) BAD_TRAP(0xd) BAD_TRAP(0xe) BAD_TRAP(0xf) BAD_TRAP(0x10)
99t_irq1: TRAP_ENTRY_INTERRUPT(1) /* IRQ Software/SBUS Level 1 */
100t_irq2: TRAP_ENTRY_INTERRUPT(2) /* IRQ SBUS Level 2 */
101t_irq3: TRAP_ENTRY_INTERRUPT(3) /* IRQ SCSI/DMA/SBUS Level 3 */
102t_irq4: TRAP_ENTRY_INTERRUPT(4) /* IRQ Software Level 4 */
103t_irq5: TRAP_ENTRY_INTERRUPT(5) /* IRQ SBUS/Ethernet Level 5 */
104t_irq6: TRAP_ENTRY_INTERRUPT(6) /* IRQ Software Level 6 */
105t_irq7: TRAP_ENTRY_INTERRUPT(7) /* IRQ Video/SBUS Level 5 */
106t_irq8: TRAP_ENTRY_INTERRUPT(8) /* IRQ SBUS Level 6 */
107t_irq9: TRAP_ENTRY_INTERRUPT(9) /* IRQ SBUS Level 7 */
108t_irq10:TRAP_ENTRY_INTERRUPT(10) /* IRQ Timer #1 (one we use) */
109t_irq11:TRAP_ENTRY_INTERRUPT(11) /* IRQ Floppy Intr. */
110t_irq12:TRAP_ENTRY_INTERRUPT(12) /* IRQ Zilog serial chip */
111t_irq13:TRAP_ENTRY_INTERRUPT(13) /* IRQ Audio Intr. */
112t_irq14:TRAP_ENTRY_INTERRUPT(14) /* IRQ Timer #2 */
113 .globl t_nmi
114#ifndef CONFIG_SMP
115t_nmi: NMI_TRAP /* Level 15 (NMI) */
116#else
117t_nmi: TRAP_ENTRY(0x1f, linux_trap_ipi15_sun4m)
118#endif
119t_racc: TRAP_ENTRY(0x20, do_reg_access) /* General Register Access Error */
120t_iacce:BAD_TRAP(0x21) /* Instr Access Error */
121t_bad22:BAD_TRAP(0x22) BAD_TRAP(0x23)
122t_cpdis:TRAP_ENTRY(0x24, do_cp_disabled) /* Co-Processor Disabled */
123t_uflsh:SKIP_TRAP(0x25, unimp_flush) /* Unimplemented FLUSH inst. */
124t_bad26:BAD_TRAP(0x26) BAD_TRAP(0x27)
125t_cpexc:TRAP_ENTRY(0x28, do_cp_exception) /* Co-Processor Exception */
126t_dacce:SPARC_DFAULT /* Data Access Error */
127t_hwdz: TRAP_ENTRY(0x2a, do_hw_divzero) /* Division by zero, you lose... */
128t_dserr:BAD_TRAP(0x2b) /* Data Store Error */
129t_daccm:BAD_TRAP(0x2c) /* Data Access MMU-Miss */
130t_bad2d:BAD_TRAP(0x2d) BAD_TRAP(0x2e) BAD_TRAP(0x2f) BAD_TRAP(0x30) BAD_TRAP(0x31)
131t_bad32:BAD_TRAP(0x32) BAD_TRAP(0x33) BAD_TRAP(0x34) BAD_TRAP(0x35) BAD_TRAP(0x36)
132t_bad37:BAD_TRAP(0x37) BAD_TRAP(0x38) BAD_TRAP(0x39) BAD_TRAP(0x3a) BAD_TRAP(0x3b)
133t_iaccm:BAD_TRAP(0x3c) /* Instr Access MMU-Miss */
134t_bad3d:BAD_TRAP(0x3d) BAD_TRAP(0x3e) BAD_TRAP(0x3f) BAD_TRAP(0x40) BAD_TRAP(0x41)
135t_bad42:BAD_TRAP(0x42) BAD_TRAP(0x43) BAD_TRAP(0x44) BAD_TRAP(0x45) BAD_TRAP(0x46)
136t_bad47:BAD_TRAP(0x47) BAD_TRAP(0x48) BAD_TRAP(0x49) BAD_TRAP(0x4a) BAD_TRAP(0x4b)
137t_bad4c:BAD_TRAP(0x4c) BAD_TRAP(0x4d) BAD_TRAP(0x4e) BAD_TRAP(0x4f) BAD_TRAP(0x50)
138t_bad51:BAD_TRAP(0x51) BAD_TRAP(0x52) BAD_TRAP(0x53) BAD_TRAP(0x54) BAD_TRAP(0x55)
139t_bad56:BAD_TRAP(0x56) BAD_TRAP(0x57) BAD_TRAP(0x58) BAD_TRAP(0x59) BAD_TRAP(0x5a)
140t_bad5b:BAD_TRAP(0x5b) BAD_TRAP(0x5c) BAD_TRAP(0x5d) BAD_TRAP(0x5e) BAD_TRAP(0x5f)
141t_bad60:BAD_TRAP(0x60) BAD_TRAP(0x61) BAD_TRAP(0x62) BAD_TRAP(0x63) BAD_TRAP(0x64)
142t_bad65:BAD_TRAP(0x65) BAD_TRAP(0x66) BAD_TRAP(0x67) BAD_TRAP(0x68) BAD_TRAP(0x69)
143t_bad6a:BAD_TRAP(0x6a) BAD_TRAP(0x6b) BAD_TRAP(0x6c) BAD_TRAP(0x6d) BAD_TRAP(0x6e)
144t_bad6f:BAD_TRAP(0x6f) BAD_TRAP(0x70) BAD_TRAP(0x71) BAD_TRAP(0x72) BAD_TRAP(0x73)
145t_bad74:BAD_TRAP(0x74) BAD_TRAP(0x75) BAD_TRAP(0x76) BAD_TRAP(0x77) BAD_TRAP(0x78)
146t_bad79:BAD_TRAP(0x79) BAD_TRAP(0x7a) BAD_TRAP(0x7b) BAD_TRAP(0x7c) BAD_TRAP(0x7d)
147t_bad7e:BAD_TRAP(0x7e) BAD_TRAP(0x7f)
148t_bad80:BAD_TRAP(0x80) /* SunOS System Call */
149t_sbkpt:BREAKPOINT_TRAP /* Software Breakpoint/KGDB */
150t_divz: TRAP_ENTRY(0x82, do_hw_divzero) /* Divide by zero trap */
151t_flwin:TRAP_ENTRY(0x83, do_flush_windows) /* Flush Windows Trap */
152t_clwin:BAD_TRAP(0x84) /* Clean Windows Trap */
153t_rchk: BAD_TRAP(0x85) /* Range Check */
154t_funal:BAD_TRAP(0x86) /* Fix Unaligned Access Trap */
155t_iovf: BAD_TRAP(0x87) /* Integer Overflow Trap */
156t_bad88:BAD_TRAP(0x88) /* Slowaris System Call */
157t_bad89:BAD_TRAP(0x89) /* Net-B.S. System Call */
158t_bad8a:BAD_TRAP(0x8a) BAD_TRAP(0x8b) BAD_TRAP(0x8c) BAD_TRAP(0x8d) BAD_TRAP(0x8e)
159t_bad8f:BAD_TRAP(0x8f)
160t_linux:LINUX_SYSCALL_TRAP /* Linux System Call */
161t_bad91:BAD_TRAP(0x91) BAD_TRAP(0x92) BAD_TRAP(0x93) BAD_TRAP(0x94) BAD_TRAP(0x95)
162t_bad96:BAD_TRAP(0x96) BAD_TRAP(0x97) BAD_TRAP(0x98) BAD_TRAP(0x99) BAD_TRAP(0x9a)
163t_bad9b:BAD_TRAP(0x9b) BAD_TRAP(0x9c) BAD_TRAP(0x9d) BAD_TRAP(0x9e) BAD_TRAP(0x9f)
164t_getcc:GETCC_TRAP /* Get Condition Codes */
165t_setcc:SETCC_TRAP /* Set Condition Codes */
166t_getpsr:GETPSR_TRAP /* Get PSR Register */
167t_bada3:BAD_TRAP(0xa3) BAD_TRAP(0xa4) BAD_TRAP(0xa5) BAD_TRAP(0xa6)
168t_bada7:BAD_TRAP(0xa7)
169t_bada8:BAD_TRAP(0xa8) BAD_TRAP(0xa9) BAD_TRAP(0xaa) BAD_TRAP(0xab)
170t_badac:BAD_TRAP(0xac) BAD_TRAP(0xad) BAD_TRAP(0xae) BAD_TRAP(0xaf) BAD_TRAP(0xb0)
171t_badb1:BAD_TRAP(0xb1) BAD_TRAP(0xb2) BAD_TRAP(0xb3) BAD_TRAP(0xb4) BAD_TRAP(0xb5)
172t_badb6:BAD_TRAP(0xb6) BAD_TRAP(0xb7) BAD_TRAP(0xb8) BAD_TRAP(0xb9) BAD_TRAP(0xba)
173t_badbb:BAD_TRAP(0xbb) BAD_TRAP(0xbc) BAD_TRAP(0xbd) BAD_TRAP(0xbe) BAD_TRAP(0xbf)
174t_badc0:BAD_TRAP(0xc0) BAD_TRAP(0xc1) BAD_TRAP(0xc2) BAD_TRAP(0xc3) BAD_TRAP(0xc4)
175t_badc5:BAD_TRAP(0xc5) BAD_TRAP(0xc6) BAD_TRAP(0xc7) BAD_TRAP(0xc8) BAD_TRAP(0xc9)
176t_badca:BAD_TRAP(0xca) BAD_TRAP(0xcb) BAD_TRAP(0xcc) BAD_TRAP(0xcd) BAD_TRAP(0xce)
177t_badcf:BAD_TRAP(0xcf) BAD_TRAP(0xd0) BAD_TRAP(0xd1) BAD_TRAP(0xd2) BAD_TRAP(0xd3)
178t_badd4:BAD_TRAP(0xd4) BAD_TRAP(0xd5) BAD_TRAP(0xd6) BAD_TRAP(0xd7) BAD_TRAP(0xd8)
179t_badd9:BAD_TRAP(0xd9) BAD_TRAP(0xda) BAD_TRAP(0xdb) BAD_TRAP(0xdc) BAD_TRAP(0xdd)
180t_badde:BAD_TRAP(0xde) BAD_TRAP(0xdf) BAD_TRAP(0xe0) BAD_TRAP(0xe1) BAD_TRAP(0xe2)
181t_bade3:BAD_TRAP(0xe3) BAD_TRAP(0xe4) BAD_TRAP(0xe5) BAD_TRAP(0xe6) BAD_TRAP(0xe7)
182t_bade8:BAD_TRAP(0xe8) BAD_TRAP(0xe9) BAD_TRAP(0xea) BAD_TRAP(0xeb) BAD_TRAP(0xec)
183t_baded:BAD_TRAP(0xed) BAD_TRAP(0xee) BAD_TRAP(0xef) BAD_TRAP(0xf0) BAD_TRAP(0xf1)
184t_badf2:BAD_TRAP(0xf2) BAD_TRAP(0xf3) BAD_TRAP(0xf4) BAD_TRAP(0xf5) BAD_TRAP(0xf6)
185t_badf7:BAD_TRAP(0xf7) BAD_TRAP(0xf8) BAD_TRAP(0xf9) BAD_TRAP(0xfa) BAD_TRAP(0xfb)
186t_badfc:BAD_TRAP(0xfc)
187t_kgdb: KGDB_TRAP(0xfd)
188dbtrap: BAD_TRAP(0xfe) /* Debugger/PROM breakpoint #1 */
189dbtrap2:BAD_TRAP(0xff) /* Debugger/PROM breakpoint #2 */
190
191 .globl end_traptable
192end_traptable:
193
194#ifdef CONFIG_SMP
195 /* Trap tables for the other cpus. */
196 .globl trapbase_cpu1, trapbase_cpu2, trapbase_cpu3
197trapbase_cpu1:
198 BAD_TRAP(0x0) SRMMU_TFAULT TRAP_ENTRY(0x2, bad_instruction)
199 TRAP_ENTRY(0x3, priv_instruction) TRAP_ENTRY(0x4, fpd_trap_handler)
200 WINDOW_SPILL WINDOW_FILL TRAP_ENTRY(0x7, mna_handler)
201 TRAP_ENTRY(0x8, fpe_trap_handler) SRMMU_DFAULT
202 TRAP_ENTRY(0xa, do_tag_overflow) TRAP_ENTRY(0xb, do_watchpoint)
203 BAD_TRAP(0xc) BAD_TRAP(0xd) BAD_TRAP(0xe) BAD_TRAP(0xf) BAD_TRAP(0x10)
204 TRAP_ENTRY_INTERRUPT(1) TRAP_ENTRY_INTERRUPT(2)
205 TRAP_ENTRY_INTERRUPT(3) TRAP_ENTRY_INTERRUPT(4)
206 TRAP_ENTRY_INTERRUPT(5) TRAP_ENTRY_INTERRUPT(6)
207 TRAP_ENTRY_INTERRUPT(7) TRAP_ENTRY_INTERRUPT(8)
208 TRAP_ENTRY_INTERRUPT(9) TRAP_ENTRY_INTERRUPT(10)
209 TRAP_ENTRY_INTERRUPT(11) TRAP_ENTRY_INTERRUPT(12)
210 TRAP_ENTRY_INTERRUPT(13) TRAP_ENTRY_INTERRUPT(14)
211 TRAP_ENTRY(0x1f, linux_trap_ipi15_sun4m)
212 TRAP_ENTRY(0x20, do_reg_access) BAD_TRAP(0x21) BAD_TRAP(0x22)
213 BAD_TRAP(0x23) TRAP_ENTRY(0x24, do_cp_disabled) SKIP_TRAP(0x25, unimp_flush)
214 BAD_TRAP(0x26) BAD_TRAP(0x27) TRAP_ENTRY(0x28, do_cp_exception)
215 SRMMU_DFAULT TRAP_ENTRY(0x2a, do_hw_divzero) BAD_TRAP(0x2b) BAD_TRAP(0x2c)
216 BAD_TRAP(0x2d) BAD_TRAP(0x2e) BAD_TRAP(0x2f) BAD_TRAP(0x30) BAD_TRAP(0x31)
217 BAD_TRAP(0x32) BAD_TRAP(0x33) BAD_TRAP(0x34) BAD_TRAP(0x35) BAD_TRAP(0x36)
218 BAD_TRAP(0x37) BAD_TRAP(0x38) BAD_TRAP(0x39) BAD_TRAP(0x3a) BAD_TRAP(0x3b)
219 BAD_TRAP(0x3c) BAD_TRAP(0x3d) BAD_TRAP(0x3e) BAD_TRAP(0x3f) BAD_TRAP(0x40)
220 BAD_TRAP(0x41) BAD_TRAP(0x42) BAD_TRAP(0x43) BAD_TRAP(0x44) BAD_TRAP(0x45)
221 BAD_TRAP(0x46) BAD_TRAP(0x47) BAD_TRAP(0x48) BAD_TRAP(0x49) BAD_TRAP(0x4a)
222 BAD_TRAP(0x4b) BAD_TRAP(0x4c) BAD_TRAP(0x4d) BAD_TRAP(0x4e) BAD_TRAP(0x4f)
223 BAD_TRAP(0x50)
224 BAD_TRAP(0x51) BAD_TRAP(0x52) BAD_TRAP(0x53) BAD_TRAP(0x54) BAD_TRAP(0x55)
225 BAD_TRAP(0x56) BAD_TRAP(0x57) BAD_TRAP(0x58) BAD_TRAP(0x59) BAD_TRAP(0x5a)
226 BAD_TRAP(0x5b) BAD_TRAP(0x5c) BAD_TRAP(0x5d) BAD_TRAP(0x5e) BAD_TRAP(0x5f)
227 BAD_TRAP(0x60) BAD_TRAP(0x61) BAD_TRAP(0x62) BAD_TRAP(0x63) BAD_TRAP(0x64)
228 BAD_TRAP(0x65) BAD_TRAP(0x66) BAD_TRAP(0x67) BAD_TRAP(0x68) BAD_TRAP(0x69)
229 BAD_TRAP(0x6a) BAD_TRAP(0x6b) BAD_TRAP(0x6c) BAD_TRAP(0x6d) BAD_TRAP(0x6e)
230 BAD_TRAP(0x6f) BAD_TRAP(0x70) BAD_TRAP(0x71) BAD_TRAP(0x72) BAD_TRAP(0x73)
231 BAD_TRAP(0x74) BAD_TRAP(0x75) BAD_TRAP(0x76) BAD_TRAP(0x77) BAD_TRAP(0x78)
232 BAD_TRAP(0x79) BAD_TRAP(0x7a) BAD_TRAP(0x7b) BAD_TRAP(0x7c) BAD_TRAP(0x7d)
233 BAD_TRAP(0x7e) BAD_TRAP(0x7f)
234 BAD_TRAP(0x80)
235 BREAKPOINT_TRAP
236 TRAP_ENTRY(0x82, do_hw_divzero)
237 TRAP_ENTRY(0x83, do_flush_windows) BAD_TRAP(0x84) BAD_TRAP(0x85)
238 BAD_TRAP(0x86) BAD_TRAP(0x87) BAD_TRAP(0x88)
239 BAD_TRAP(0x89) BAD_TRAP(0x8a) BAD_TRAP(0x8b) BAD_TRAP(0x8c)
240 BAD_TRAP(0x8d) BAD_TRAP(0x8e) BAD_TRAP(0x8f)
241 LINUX_SYSCALL_TRAP BAD_TRAP(0x91) BAD_TRAP(0x92) BAD_TRAP(0x93) BAD_TRAP(0x94)
242 BAD_TRAP(0x95) BAD_TRAP(0x96) BAD_TRAP(0x97) BAD_TRAP(0x98) BAD_TRAP(0x99)
243 BAD_TRAP(0x9a) BAD_TRAP(0x9b) BAD_TRAP(0x9c) BAD_TRAP(0x9d) BAD_TRAP(0x9e)
244 BAD_TRAP(0x9f) GETCC_TRAP SETCC_TRAP GETPSR_TRAP
245 BAD_TRAP(0xa3) BAD_TRAP(0xa4) BAD_TRAP(0xa5) BAD_TRAP(0xa6)
246 BAD_TRAP(0xa7) BAD_TRAP(0xa8) BAD_TRAP(0xa9) BAD_TRAP(0xaa) BAD_TRAP(0xab)
247 BAD_TRAP(0xac) BAD_TRAP(0xad) BAD_TRAP(0xae) BAD_TRAP(0xaf) BAD_TRAP(0xb0)
248 BAD_TRAP(0xb1) BAD_TRAP(0xb2) BAD_TRAP(0xb3) BAD_TRAP(0xb4) BAD_TRAP(0xb5)
249 BAD_TRAP(0xb6) BAD_TRAP(0xb7) BAD_TRAP(0xb8) BAD_TRAP(0xb9) BAD_TRAP(0xba)
250 BAD_TRAP(0xbb) BAD_TRAP(0xbc) BAD_TRAP(0xbd) BAD_TRAP(0xbe) BAD_TRAP(0xbf)
251 BAD_TRAP(0xc0) BAD_TRAP(0xc1) BAD_TRAP(0xc2) BAD_TRAP(0xc3) BAD_TRAP(0xc4)
252 BAD_TRAP(0xc5) BAD_TRAP(0xc6) BAD_TRAP(0xc7) BAD_TRAP(0xc8) BAD_TRAP(0xc9)
253 BAD_TRAP(0xca) BAD_TRAP(0xcb) BAD_TRAP(0xcc) BAD_TRAP(0xcd) BAD_TRAP(0xce)
254 BAD_TRAP(0xcf) BAD_TRAP(0xd0) BAD_TRAP(0xd1) BAD_TRAP(0xd2) BAD_TRAP(0xd3)
255 BAD_TRAP(0xd4) BAD_TRAP(0xd5) BAD_TRAP(0xd6) BAD_TRAP(0xd7) BAD_TRAP(0xd8)
256 BAD_TRAP(0xd9) BAD_TRAP(0xda) BAD_TRAP(0xdb) BAD_TRAP(0xdc) BAD_TRAP(0xdd)
257 BAD_TRAP(0xde) BAD_TRAP(0xdf) BAD_TRAP(0xe0) BAD_TRAP(0xe1) BAD_TRAP(0xe2)
258 BAD_TRAP(0xe3) BAD_TRAP(0xe4) BAD_TRAP(0xe5) BAD_TRAP(0xe6) BAD_TRAP(0xe7)
259 BAD_TRAP(0xe8) BAD_TRAP(0xe9) BAD_TRAP(0xea) BAD_TRAP(0xeb) BAD_TRAP(0xec)
260 BAD_TRAP(0xed) BAD_TRAP(0xee) BAD_TRAP(0xef) BAD_TRAP(0xf0) BAD_TRAP(0xf1)
261 BAD_TRAP(0xf2) BAD_TRAP(0xf3) BAD_TRAP(0xf4) BAD_TRAP(0xf5) BAD_TRAP(0xf6)
262 BAD_TRAP(0xf7) BAD_TRAP(0xf8) BAD_TRAP(0xf9) BAD_TRAP(0xfa) BAD_TRAP(0xfb)
263 BAD_TRAP(0xfc) KGDB_TRAP(0xfd) BAD_TRAP(0xfe) BAD_TRAP(0xff)
264
265trapbase_cpu2:
266 BAD_TRAP(0x0) SRMMU_TFAULT TRAP_ENTRY(0x2, bad_instruction)
267 TRAP_ENTRY(0x3, priv_instruction) TRAP_ENTRY(0x4, fpd_trap_handler)
268 WINDOW_SPILL WINDOW_FILL TRAP_ENTRY(0x7, mna_handler)
269 TRAP_ENTRY(0x8, fpe_trap_handler) SRMMU_DFAULT
270 TRAP_ENTRY(0xa, do_tag_overflow) TRAP_ENTRY(0xb, do_watchpoint)
271 BAD_TRAP(0xc) BAD_TRAP(0xd) BAD_TRAP(0xe) BAD_TRAP(0xf) BAD_TRAP(0x10)
272 TRAP_ENTRY_INTERRUPT(1) TRAP_ENTRY_INTERRUPT(2)
273 TRAP_ENTRY_INTERRUPT(3) TRAP_ENTRY_INTERRUPT(4)
274 TRAP_ENTRY_INTERRUPT(5) TRAP_ENTRY_INTERRUPT(6)
275 TRAP_ENTRY_INTERRUPT(7) TRAP_ENTRY_INTERRUPT(8)
276 TRAP_ENTRY_INTERRUPT(9) TRAP_ENTRY_INTERRUPT(10)
277 TRAP_ENTRY_INTERRUPT(11) TRAP_ENTRY_INTERRUPT(12)
278 TRAP_ENTRY_INTERRUPT(13) TRAP_ENTRY_INTERRUPT(14)
279 TRAP_ENTRY(0x1f, linux_trap_ipi15_sun4m)
280 TRAP_ENTRY(0x20, do_reg_access) BAD_TRAP(0x21) BAD_TRAP(0x22)
281 BAD_TRAP(0x23) TRAP_ENTRY(0x24, do_cp_disabled) SKIP_TRAP(0x25, unimp_flush)
282 BAD_TRAP(0x26) BAD_TRAP(0x27) TRAP_ENTRY(0x28, do_cp_exception)
283 SRMMU_DFAULT TRAP_ENTRY(0x2a, do_hw_divzero) BAD_TRAP(0x2b) BAD_TRAP(0x2c)
284 BAD_TRAP(0x2d) BAD_TRAP(0x2e) BAD_TRAP(0x2f) BAD_TRAP(0x30) BAD_TRAP(0x31)
285 BAD_TRAP(0x32) BAD_TRAP(0x33) BAD_TRAP(0x34) BAD_TRAP(0x35) BAD_TRAP(0x36)
286 BAD_TRAP(0x37) BAD_TRAP(0x38) BAD_TRAP(0x39) BAD_TRAP(0x3a) BAD_TRAP(0x3b)
287 BAD_TRAP(0x3c) BAD_TRAP(0x3d) BAD_TRAP(0x3e) BAD_TRAP(0x3f) BAD_TRAP(0x40)
288 BAD_TRAP(0x41) BAD_TRAP(0x42) BAD_TRAP(0x43) BAD_TRAP(0x44) BAD_TRAP(0x45)
289 BAD_TRAP(0x46) BAD_TRAP(0x47) BAD_TRAP(0x48) BAD_TRAP(0x49) BAD_TRAP(0x4a)
290 BAD_TRAP(0x4b) BAD_TRAP(0x4c) BAD_TRAP(0x4d) BAD_TRAP(0x4e) BAD_TRAP(0x4f)
291 BAD_TRAP(0x50)
292 BAD_TRAP(0x51) BAD_TRAP(0x52) BAD_TRAP(0x53) BAD_TRAP(0x54) BAD_TRAP(0x55)
293 BAD_TRAP(0x56) BAD_TRAP(0x57) BAD_TRAP(0x58) BAD_TRAP(0x59) BAD_TRAP(0x5a)
294 BAD_TRAP(0x5b) BAD_TRAP(0x5c) BAD_TRAP(0x5d) BAD_TRAP(0x5e) BAD_TRAP(0x5f)
295 BAD_TRAP(0x60) BAD_TRAP(0x61) BAD_TRAP(0x62) BAD_TRAP(0x63) BAD_TRAP(0x64)
296 BAD_TRAP(0x65) BAD_TRAP(0x66) BAD_TRAP(0x67) BAD_TRAP(0x68) BAD_TRAP(0x69)
297 BAD_TRAP(0x6a) BAD_TRAP(0x6b) BAD_TRAP(0x6c) BAD_TRAP(0x6d) BAD_TRAP(0x6e)
298 BAD_TRAP(0x6f) BAD_TRAP(0x70) BAD_TRAP(0x71) BAD_TRAP(0x72) BAD_TRAP(0x73)
299 BAD_TRAP(0x74) BAD_TRAP(0x75) BAD_TRAP(0x76) BAD_TRAP(0x77) BAD_TRAP(0x78)
300 BAD_TRAP(0x79) BAD_TRAP(0x7a) BAD_TRAP(0x7b) BAD_TRAP(0x7c) BAD_TRAP(0x7d)
301 BAD_TRAP(0x7e) BAD_TRAP(0x7f)
302 BAD_TRAP(0x80)
303 BREAKPOINT_TRAP
304 TRAP_ENTRY(0x82, do_hw_divzero)
305 TRAP_ENTRY(0x83, do_flush_windows) BAD_TRAP(0x84) BAD_TRAP(0x85)
306 BAD_TRAP(0x86) BAD_TRAP(0x87) BAD_TRAP(0x88)
307 BAD_TRAP(0x89) BAD_TRAP(0x8a) BAD_TRAP(0x8b) BAD_TRAP(0x8c)
308 BAD_TRAP(0x8d) BAD_TRAP(0x8e) BAD_TRAP(0x8f)
309 LINUX_SYSCALL_TRAP BAD_TRAP(0x91) BAD_TRAP(0x92) BAD_TRAP(0x93) BAD_TRAP(0x94)
310 BAD_TRAP(0x95) BAD_TRAP(0x96) BAD_TRAP(0x97) BAD_TRAP(0x98) BAD_TRAP(0x99)
311 BAD_TRAP(0x9a) BAD_TRAP(0x9b) BAD_TRAP(0x9c) BAD_TRAP(0x9d) BAD_TRAP(0x9e)
312 BAD_TRAP(0x9f) GETCC_TRAP SETCC_TRAP GETPSR_TRAP
313 BAD_TRAP(0xa3) BAD_TRAP(0xa4) BAD_TRAP(0xa5) BAD_TRAP(0xa6)
314 BAD_TRAP(0xa7) BAD_TRAP(0xa8) BAD_TRAP(0xa9) BAD_TRAP(0xaa) BAD_TRAP(0xab)
315 BAD_TRAP(0xac) BAD_TRAP(0xad) BAD_TRAP(0xae) BAD_TRAP(0xaf) BAD_TRAP(0xb0)
316 BAD_TRAP(0xb1) BAD_TRAP(0xb2) BAD_TRAP(0xb3) BAD_TRAP(0xb4) BAD_TRAP(0xb5)
317 BAD_TRAP(0xb6) BAD_TRAP(0xb7) BAD_TRAP(0xb8) BAD_TRAP(0xb9) BAD_TRAP(0xba)
318 BAD_TRAP(0xbb) BAD_TRAP(0xbc) BAD_TRAP(0xbd) BAD_TRAP(0xbe) BAD_TRAP(0xbf)
319 BAD_TRAP(0xc0) BAD_TRAP(0xc1) BAD_TRAP(0xc2) BAD_TRAP(0xc3) BAD_TRAP(0xc4)
320 BAD_TRAP(0xc5) BAD_TRAP(0xc6) BAD_TRAP(0xc7) BAD_TRAP(0xc8) BAD_TRAP(0xc9)
321 BAD_TRAP(0xca) BAD_TRAP(0xcb) BAD_TRAP(0xcc) BAD_TRAP(0xcd) BAD_TRAP(0xce)
322 BAD_TRAP(0xcf) BAD_TRAP(0xd0) BAD_TRAP(0xd1) BAD_TRAP(0xd2) BAD_TRAP(0xd3)
323 BAD_TRAP(0xd4) BAD_TRAP(0xd5) BAD_TRAP(0xd6) BAD_TRAP(0xd7) BAD_TRAP(0xd8)
324 BAD_TRAP(0xd9) BAD_TRAP(0xda) BAD_TRAP(0xdb) BAD_TRAP(0xdc) BAD_TRAP(0xdd)
325 BAD_TRAP(0xde) BAD_TRAP(0xdf) BAD_TRAP(0xe0) BAD_TRAP(0xe1) BAD_TRAP(0xe2)
326 BAD_TRAP(0xe3) BAD_TRAP(0xe4) BAD_TRAP(0xe5) BAD_TRAP(0xe6) BAD_TRAP(0xe7)
327 BAD_TRAP(0xe8) BAD_TRAP(0xe9) BAD_TRAP(0xea) BAD_TRAP(0xeb) BAD_TRAP(0xec)
328 BAD_TRAP(0xed) BAD_TRAP(0xee) BAD_TRAP(0xef) BAD_TRAP(0xf0) BAD_TRAP(0xf1)
329 BAD_TRAP(0xf2) BAD_TRAP(0xf3) BAD_TRAP(0xf4) BAD_TRAP(0xf5) BAD_TRAP(0xf6)
330 BAD_TRAP(0xf7) BAD_TRAP(0xf8) BAD_TRAP(0xf9) BAD_TRAP(0xfa) BAD_TRAP(0xfb)
331 BAD_TRAP(0xfc) KGDB_TRAP(0xfd) BAD_TRAP(0xfe) BAD_TRAP(0xff)
332
333trapbase_cpu3:
334 BAD_TRAP(0x0) SRMMU_TFAULT TRAP_ENTRY(0x2, bad_instruction)
335 TRAP_ENTRY(0x3, priv_instruction) TRAP_ENTRY(0x4, fpd_trap_handler)
336 WINDOW_SPILL WINDOW_FILL TRAP_ENTRY(0x7, mna_handler)
337 TRAP_ENTRY(0x8, fpe_trap_handler) SRMMU_DFAULT
338 TRAP_ENTRY(0xa, do_tag_overflow) TRAP_ENTRY(0xb, do_watchpoint)
339 BAD_TRAP(0xc) BAD_TRAP(0xd) BAD_TRAP(0xe) BAD_TRAP(0xf) BAD_TRAP(0x10)
340 TRAP_ENTRY_INTERRUPT(1) TRAP_ENTRY_INTERRUPT(2)
341 TRAP_ENTRY_INTERRUPT(3) TRAP_ENTRY_INTERRUPT(4)
342 TRAP_ENTRY_INTERRUPT(5) TRAP_ENTRY_INTERRUPT(6)
343 TRAP_ENTRY_INTERRUPT(7) TRAP_ENTRY_INTERRUPT(8)
344 TRAP_ENTRY_INTERRUPT(9) TRAP_ENTRY_INTERRUPT(10)
345 TRAP_ENTRY_INTERRUPT(11) TRAP_ENTRY_INTERRUPT(12)
346 TRAP_ENTRY_INTERRUPT(13) TRAP_ENTRY_INTERRUPT(14)
347 TRAP_ENTRY(0x1f, linux_trap_ipi15_sun4m)
348 TRAP_ENTRY(0x20, do_reg_access) BAD_TRAP(0x21) BAD_TRAP(0x22)
349 BAD_TRAP(0x23) TRAP_ENTRY(0x24, do_cp_disabled) SKIP_TRAP(0x25, unimp_flush)
350 BAD_TRAP(0x26) BAD_TRAP(0x27) TRAP_ENTRY(0x28, do_cp_exception)
351 SRMMU_DFAULT TRAP_ENTRY(0x2a, do_hw_divzero) BAD_TRAP(0x2b) BAD_TRAP(0x2c)
352 BAD_TRAP(0x2d) BAD_TRAP(0x2e) BAD_TRAP(0x2f) BAD_TRAP(0x30) BAD_TRAP(0x31)
353 BAD_TRAP(0x32) BAD_TRAP(0x33) BAD_TRAP(0x34) BAD_TRAP(0x35) BAD_TRAP(0x36)
354 BAD_TRAP(0x37) BAD_TRAP(0x38) BAD_TRAP(0x39) BAD_TRAP(0x3a) BAD_TRAP(0x3b)
355 BAD_TRAP(0x3c) BAD_TRAP(0x3d) BAD_TRAP(0x3e) BAD_TRAP(0x3f) BAD_TRAP(0x40)
356 BAD_TRAP(0x41) BAD_TRAP(0x42) BAD_TRAP(0x43) BAD_TRAP(0x44) BAD_TRAP(0x45)
357 BAD_TRAP(0x46) BAD_TRAP(0x47) BAD_TRAP(0x48) BAD_TRAP(0x49) BAD_TRAP(0x4a)
358 BAD_TRAP(0x4b) BAD_TRAP(0x4c) BAD_TRAP(0x4d) BAD_TRAP(0x4e) BAD_TRAP(0x4f)
359 BAD_TRAP(0x50)
360 BAD_TRAP(0x51) BAD_TRAP(0x52) BAD_TRAP(0x53) BAD_TRAP(0x54) BAD_TRAP(0x55)
361 BAD_TRAP(0x56) BAD_TRAP(0x57) BAD_TRAP(0x58) BAD_TRAP(0x59) BAD_TRAP(0x5a)
362 BAD_TRAP(0x5b) BAD_TRAP(0x5c) BAD_TRAP(0x5d) BAD_TRAP(0x5e) BAD_TRAP(0x5f)
363 BAD_TRAP(0x60) BAD_TRAP(0x61) BAD_TRAP(0x62) BAD_TRAP(0x63) BAD_TRAP(0x64)
364 BAD_TRAP(0x65) BAD_TRAP(0x66) BAD_TRAP(0x67) BAD_TRAP(0x68) BAD_TRAP(0x69)
365 BAD_TRAP(0x6a) BAD_TRAP(0x6b) BAD_TRAP(0x6c) BAD_TRAP(0x6d) BAD_TRAP(0x6e)
366 BAD_TRAP(0x6f) BAD_TRAP(0x70) BAD_TRAP(0x71) BAD_TRAP(0x72) BAD_TRAP(0x73)
367 BAD_TRAP(0x74) BAD_TRAP(0x75) BAD_TRAP(0x76) BAD_TRAP(0x77) BAD_TRAP(0x78)
368 BAD_TRAP(0x79) BAD_TRAP(0x7a) BAD_TRAP(0x7b) BAD_TRAP(0x7c) BAD_TRAP(0x7d)
369 BAD_TRAP(0x7e) BAD_TRAP(0x7f)
370 BAD_TRAP(0x80)
371 BREAKPOINT_TRAP
372 TRAP_ENTRY(0x82, do_hw_divzero)
373 TRAP_ENTRY(0x83, do_flush_windows) BAD_TRAP(0x84) BAD_TRAP(0x85)
374 BAD_TRAP(0x86) BAD_TRAP(0x87) BAD_TRAP(0x88)
375 BAD_TRAP(0x89) BAD_TRAP(0x8a) BAD_TRAP(0x8b) BAD_TRAP(0x8c)
376 BAD_TRAP(0x8d) BAD_TRAP(0x8e) BAD_TRAP(0x8f)
377 LINUX_SYSCALL_TRAP BAD_TRAP(0x91) BAD_TRAP(0x92) BAD_TRAP(0x93) BAD_TRAP(0x94)
378 BAD_TRAP(0x95) BAD_TRAP(0x96) BAD_TRAP(0x97) BAD_TRAP(0x98) BAD_TRAP(0x99)
379 BAD_TRAP(0x9a) BAD_TRAP(0x9b) BAD_TRAP(0x9c) BAD_TRAP(0x9d) BAD_TRAP(0x9e)
380 BAD_TRAP(0x9f) GETCC_TRAP SETCC_TRAP GETPSR_TRAP
381 BAD_TRAP(0xa3) BAD_TRAP(0xa4) BAD_TRAP(0xa5) BAD_TRAP(0xa6)
382 BAD_TRAP(0xa7) BAD_TRAP(0xa8) BAD_TRAP(0xa9) BAD_TRAP(0xaa) BAD_TRAP(0xab)
383 BAD_TRAP(0xac) BAD_TRAP(0xad) BAD_TRAP(0xae) BAD_TRAP(0xaf) BAD_TRAP(0xb0)
384 BAD_TRAP(0xb1) BAD_TRAP(0xb2) BAD_TRAP(0xb3) BAD_TRAP(0xb4) BAD_TRAP(0xb5)
385 BAD_TRAP(0xb6) BAD_TRAP(0xb7) BAD_TRAP(0xb8) BAD_TRAP(0xb9) BAD_TRAP(0xba)
386 BAD_TRAP(0xbb) BAD_TRAP(0xbc) BAD_TRAP(0xbd) BAD_TRAP(0xbe) BAD_TRAP(0xbf)
387 BAD_TRAP(0xc0) BAD_TRAP(0xc1) BAD_TRAP(0xc2) BAD_TRAP(0xc3) BAD_TRAP(0xc4)
388 BAD_TRAP(0xc5) BAD_TRAP(0xc6) BAD_TRAP(0xc7) BAD_TRAP(0xc8) BAD_TRAP(0xc9)
389 BAD_TRAP(0xca) BAD_TRAP(0xcb) BAD_TRAP(0xcc) BAD_TRAP(0xcd) BAD_TRAP(0xce)
390 BAD_TRAP(0xcf) BAD_TRAP(0xd0) BAD_TRAP(0xd1) BAD_TRAP(0xd2) BAD_TRAP(0xd3)
391 BAD_TRAP(0xd4) BAD_TRAP(0xd5) BAD_TRAP(0xd6) BAD_TRAP(0xd7) BAD_TRAP(0xd8)
392 BAD_TRAP(0xd9) BAD_TRAP(0xda) BAD_TRAP(0xdb) BAD_TRAP(0xdc) BAD_TRAP(0xdd)
393 BAD_TRAP(0xde) BAD_TRAP(0xdf) BAD_TRAP(0xe0) BAD_TRAP(0xe1) BAD_TRAP(0xe2)
394 BAD_TRAP(0xe3) BAD_TRAP(0xe4) BAD_TRAP(0xe5) BAD_TRAP(0xe6) BAD_TRAP(0xe7)
395 BAD_TRAP(0xe8) BAD_TRAP(0xe9) BAD_TRAP(0xea) BAD_TRAP(0xeb) BAD_TRAP(0xec)
396 BAD_TRAP(0xed) BAD_TRAP(0xee) BAD_TRAP(0xef) BAD_TRAP(0xf0) BAD_TRAP(0xf1)
397 BAD_TRAP(0xf2) BAD_TRAP(0xf3) BAD_TRAP(0xf4) BAD_TRAP(0xf5) BAD_TRAP(0xf6)
398 BAD_TRAP(0xf7) BAD_TRAP(0xf8) BAD_TRAP(0xf9) BAD_TRAP(0xfa) BAD_TRAP(0xfb)
399 BAD_TRAP(0xfc) KGDB_TRAP(0xfd) BAD_TRAP(0xfe) BAD_TRAP(0xff)
400 59
401#endif
402 .align PAGE_SIZE 60 .align PAGE_SIZE
403 61
404/* This was the only reasonable way I could think of to properly align 62/* This was the only reasonable way I could think of to properly align
405 * these page-table data structures. 63 * these page-table data structures.
406 */ 64 */
407 .globl pg0, pg1, pg2, pg3
408 .globl empty_bad_page
409 .globl empty_bad_page_table
410 .globl empty_zero_page
411 .globl swapper_pg_dir 65 .globl swapper_pg_dir
412swapper_pg_dir: .skip PAGE_SIZE 66swapper_pg_dir: .skip PAGE_SIZE
413pg0: .skip PAGE_SIZE 67 .globl empty_zero_page
414pg1: .skip PAGE_SIZE
415pg2: .skip PAGE_SIZE
416pg3: .skip PAGE_SIZE
417empty_bad_page: .skip PAGE_SIZE
418empty_bad_page_table: .skip PAGE_SIZE
419empty_zero_page: .skip PAGE_SIZE 68empty_zero_page: .skip PAGE_SIZE
420 69
421 .global root_flags 70 .global root_flags
@@ -523,10 +172,10 @@ copy_prom_lvl14:
523 ldd [%g2 + 0x8], %g4 172 ldd [%g2 + 0x8], %g4
524 std %g4, [%g3 + 0x8] ! Copy proms handler 173 std %g4, [%g3 + 0x8] ! Copy proms handler
525 174
526/* Must determine whether we are on a sun4c MMU, SRMMU, or SUN4/400 MUTANT 175/* DON'T TOUCH %l0 thru %l5 in these remapping routines,
527 * MMU so we can remap ourselves properly. DON'T TOUCH %l0 thru %l5 in these 176 * we need their values afterwards!
528 * remapping routines, we need their values afterwards!
529 */ 177 */
178
530 /* Now check whether we are already mapped, if we 179 /* Now check whether we are already mapped, if we
531 * are we can skip all this garbage coming up. 180 * are we can skip all this garbage coming up.
532 */ 181 */
@@ -535,26 +184,29 @@ copy_prom_done:
535 be go_to_highmem ! this will be a nop then 184 be go_to_highmem ! this will be a nop then
536 nop 185 nop
537 186
538 set LOAD_ADDR, %g6 187 /* Validate that we are in fact running on an
188 * SRMMU based cpu.
189 */
190 set 0x4000, %g6
539 cmp %g7, %g6 191 cmp %g7, %g6
540 bne remap_not_a_sun4 ! This is not a Sun4 192 bne not_a_sun4
541 nop 193 nop
542 194
543 or %g0, 0x1, %g1 195halt_sun4_or_sun4c:
544 lduba [%g1] ASI_CONTROL, %g1 ! Only safe to try on Sun4. 196 ld [%g7 + 0x68], %o1
545 subcc %g1, 0x24, %g0 ! Is this a mutant Sun4/400??? 197 set sun4c_notsup, %o0
546 be sun4_mutant_remap ! Ugh, it is... 198 sub %o0, %l6, %o0
199 call %o1
547 nop 200 nop
548 201 ba halt_me
549 b sun4_normal_remap ! regular sun4, 2 level mmu
550 nop 202 nop
551 203
552remap_not_a_sun4: 204not_a_sun4:
553 lda [%g0] ASI_M_MMUREGS, %g1 ! same as ASI_PTE on sun4c 205 lda [%g0] ASI_M_MMUREGS, %g1
554 and %g1, 0x1, %g1 ! Test SRMMU Enable bit ;-) 206 andcc %g1, 1, %g0
555 cmp %g1, 0x0 207 be halt_sun4_or_sun4c
556 be sun4c_remap ! A sun4c MMU or normal Sun4
557 nop 208 nop
209
558srmmu_remap: 210srmmu_remap:
559 /* First, check for a viking (TI) module. */ 211 /* First, check for a viking (TI) module. */
560 set 0x40000000, %g2 212 set 0x40000000, %g2
@@ -660,72 +312,6 @@ srmmu_nviking:
660 b go_to_highmem 312 b go_to_highmem
661 nop ! wheee.... 313 nop ! wheee....
662 314
663 /* This remaps the kernel on Sun4/4xx machines
664 * that have the Sun Mutant Three Level MMU.
665 * It's like a platypus, Sun didn't have the
666 * SRMMU in conception so they kludged the three
667 * level logic in the regular Sun4 MMU probably.
668 *
669 * Basically, you take each entry in the top level
670 * directory that maps the low 3MB starting at
671 * address zero and put the mapping in the KERNBASE
672 * slots. These top level pgd's are called regmaps.
673 */
674sun4_mutant_remap:
675 or %g0, %g0, %g3 ! source base
676 sethi %hi(KERNBASE), %g4 ! destination base
677 or %g4, %lo(KERNBASE), %g4
678 sethi %hi(0x300000), %g5
679 or %g5, %lo(0x300000), %g5 ! upper bound 3MB
680 or %g0, 0x1, %l6
681 sll %l6, 24, %l6 ! Regmap mapping size
682 add %g3, 0x2, %g3 ! Base magic
683 add %g4, 0x2, %g4 ! Base magic
684
685 /* Main remapping loop on Sun4-Mutant-MMU.
686 * "I am not an animal..." -Famous Mutant Person
687 */
688sun4_mutant_loop:
689 lduha [%g3] ASI_REGMAP, %g2 ! Get lower entry
690 stha %g2, [%g4] ASI_REGMAP ! Store in high entry
691 add %g4, %l6, %g4 ! Move up high memory ptr
692 subcc %g3, %g5, %g0 ! Reached our limit?
693 blu sun4_mutant_loop ! Nope, loop again
694 add %g3, %l6, %g3 ! delay, Move up low ptr
695 b go_to_highmem ! Jump to high memory.
696 nop
697
698 /* The following is for non-4/4xx sun4 MMU's. */
699sun4_normal_remap:
700 mov 0, %g3 ! source base
701 set KERNBASE, %g4 ! destination base
702 set 0x300000, %g5 ! upper bound 3MB
703 mov 1, %l6
704 sll %l6, 18, %l6 ! sun4 mmu segmap size
705sun4_normal_loop:
706 lduha [%g3] ASI_SEGMAP, %g6 ! load phys_seg
707 stha %g6, [%g4] ASI_SEGMAP ! stort new virt mapping
708 add %g3, %l6, %g3 ! increment source pointer
709 subcc %g3, %g5, %g0 ! reached limit?
710 blu sun4_normal_loop ! nope, loop again
711 add %g4, %l6, %g4 ! delay, increment dest ptr
712 b go_to_highmem
713 nop
714
715 /* The following works for Sun4c MMU's */
716sun4c_remap:
717 mov 0, %g3 ! source base
718 set KERNBASE, %g4 ! destination base
719 set 0x300000, %g5 ! upper bound 3MB
720 mov 1, %l6
721 sll %l6, 18, %l6 ! sun4c mmu segmap size
722sun4c_remap_loop:
723 lda [%g3] ASI_SEGMAP, %g6 ! load phys_seg
724 sta %g6, [%g4] ASI_SEGMAP ! store new virt mapping
725 add %g3, %l6, %g3 ! Increment source ptr
726 subcc %g3, %g5, %g0 ! Reached limit?
727 bl sun4c_remap_loop ! Nope, loop again
728 add %g4, %l6, %g4 ! delay, Increment dest ptr
729 315
730/* Now do a non-relative jump so that PC is in high-memory */ 316/* Now do a non-relative jump so that PC is in high-memory */
731go_to_highmem: 317go_to_highmem:
@@ -750,35 +336,12 @@ execute_in_high_mem:
750 sethi %hi(linux_dbvec), %g1 336 sethi %hi(linux_dbvec), %g1
751 st %o1, [%g1 + %lo(linux_dbvec)] 337 st %o1, [%g1 + %lo(linux_dbvec)]
752 338
753 ld [%o0 + 0x4], %o3
754 and %o3, 0x3, %o5 ! get the version
755
756 cmp %o3, 0x2 ! a v2 prom?
757 be found_version
758 nop
759
760 /* paul@sfe.com.au */
761 cmp %o3, 0x3 ! a v3 prom?
762 be found_version
763 nop
764
765/* Old sun4's pass our load address into %o0 instead of the prom
766 * pointer. On sun4's you have to hard code the romvec pointer into
767 * your code. Sun probably still does that because they don't even
768 * trust their own "OpenBoot" specifications.
769 */
770 set LOAD_ADDR, %g6
771 cmp %o0, %g6 ! an old sun4?
772 be sun4_init
773 nop
774
775found_version:
776/* Get the machine type via the mysterious romvec node operations. */ 339/* Get the machine type via the mysterious romvec node operations. */
777 340
778 add %g7, 0x1c, %l1 341 add %g7, 0x1c, %l1
779 ld [%l1], %l0 342 ld [%l1], %l0
780 ld [%l0], %l0 343 ld [%l0], %l0
781 call %l0 344 call %l0
782 or %g0, %g0, %o0 ! next_node(0) = first_node 345 or %g0, %g0, %o0 ! next_node(0) = first_node
783 or %o0, %g0, %g6 346 or %o0, %g0, %g6
784 347
@@ -786,28 +349,13 @@ found_version:
786 or %o1, %lo(cputypvar), %o1 349 or %o1, %lo(cputypvar), %o1
787 sethi %hi(cputypval), %o2 ! information, the string 350 sethi %hi(cputypval), %o2 ! information, the string
788 or %o2, %lo(cputypval), %o2 351 or %o2, %lo(cputypval), %o2
789 ld [%l1], %l0 ! 'compatibility' tells 352 ld [%l1], %l0 ! 'compatible' tells
790 ld [%l0 + 0xc], %l0 ! that we want 'sun4x' where 353 ld [%l0 + 0xc], %l0 ! that we want 'sun4x' where
791 call %l0 ! x is one of '', 'c', 'm', 354 call %l0 ! x is one of 'm', 'd' or 'e'.
792 nop ! 'd' or 'e'. %o2 holds pointer 355 nop ! %o2 holds pointer
793 ! to a buf where above string 356 ! to a buf where above string
794 ! will get stored by the prom. 357 ! will get stored by the prom.
795 358
796 subcc %o0, %g0, %g0
797 bpos got_prop ! Got the property
798 nop
799
800 or %g6, %g0, %o0
801 sethi %hi(cputypvar_sun4m), %o1
802 or %o1, %lo(cputypvar_sun4m), %o1
803 sethi %hi(cputypval), %o2
804 or %o2, %lo(cputypval), %o2
805 ld [%l1], %l0
806 ld [%l0 + 0xc], %l0
807 call %l0
808 nop
809
810got_prop:
811#ifdef CONFIG_SPARC_LEON 359#ifdef CONFIG_SPARC_LEON
812 /* no cpu-type check is needed, it is a SPARC-LEON */ 360 /* no cpu-type check is needed, it is a SPARC-LEON */
813 361
@@ -826,45 +374,29 @@ got_prop:
826 /* Update boot_cpu_id only on boot cpu */ 374 /* Update boot_cpu_id only on boot cpu */
827 stub %g1, [%g2 + %lo(boot_cpu_id)] 375 stub %g1, [%g2 + %lo(boot_cpu_id)]
828 376
829 ba sun4c_continue_boot 377 ba continue_boot
830 nop 378 nop
831#endif 379#endif
380
381/* Check to cputype. We may be booted on a sun4u (64 bit box),
382 * and sun4d needs special treatment.
383 */
384
832 set cputypval, %o2 385 set cputypval, %o2
833 ldub [%o2 + 0x4], %l1 386 ldub [%o2 + 0x4], %l1
834 387
835 cmp %l1, ' ' 388 cmp %l1, 'm'
836 be 1f 389 be sun4m_init
837 cmp %l1, 'c'
838 be 1f
839 cmp %l1, 'm'
840 be 1f
841 cmp %l1, 's' 390 cmp %l1, 's'
842 be 1f 391 be sun4m_init
843 cmp %l1, 'd' 392 cmp %l1, 'd'
844 be 1f 393 be sun4d_init
845 cmp %l1, 'e' 394 cmp %l1, 'e'
846 be no_sun4e_here ! Could be a sun4e. 395 be no_sun4e_here ! Could be a sun4e.
847 nop 396 nop
848 b no_sun4u_here ! AIEEE, a V9 sun4u... Get our BIG BROTHER kernel :)) 397 b no_sun4u_here ! AIEEE, a V9 sun4u... Get our BIG BROTHER kernel :))
849 nop 398 nop
850 399
8511: set cputypval, %l1
852 ldub [%l1 + 0x4], %l1
853 cmp %l1, 'm' ! Test for sun4d, sun4e ?
854 be sun4m_init
855 cmp %l1, 's' ! Treat sun4s as sun4m
856 be sun4m_init
857 cmp %l1, 'd' ! Let us see how the beast will die
858 be sun4d_init
859 nop
860
861 /* Jump into mmu context zero. */
862 set AC_CONTEXT, %g1
863 stba %g0, [%g1] ASI_CONTROL
864
865 b sun4c_continue_boot
866 nop
867
868/* CPUID in bootbus can be found at PA 0xff0140000 */ 400/* CPUID in bootbus can be found at PA 0xff0140000 */
869#define SUN4D_BOOTBUS_CPUID 0xf0140000 401#define SUN4D_BOOTBUS_CPUID 0xf0140000
870 402
@@ -892,66 +424,6 @@ sun4d_init:
892 /* Fall through to sun4m_init */ 424 /* Fall through to sun4m_init */
893 425
894sun4m_init: 426sun4m_init:
895 /* XXX Fucking Cypress... */
896 lda [%g0] ASI_M_MMUREGS, %g5
897 srl %g5, 28, %g4
898
899 cmp %g4, 1
900 bne 1f
901 srl %g5, 24, %g4
902
903 and %g4, 0xf, %g4
904 cmp %g4, 7 /* This would be a HyperSparc. */
905
906 bne 2f
907 nop
908
9091:
910
911#define PATCH_IT(dst, src) \
912 set (dst), %g5; \
913 set (src), %g4; \
914 ld [%g4], %g3; \
915 st %g3, [%g5]; \
916 ld [%g4+0x4], %g3; \
917 st %g3, [%g5+0x4];
918
919 /* Signed multiply. */
920 PATCH_IT(.mul, .mul_patch)
921 PATCH_IT(.mul+0x08, .mul_patch+0x08)
922
923 /* Signed remainder. */
924 PATCH_IT(.rem, .rem_patch)
925 PATCH_IT(.rem+0x08, .rem_patch+0x08)
926 PATCH_IT(.rem+0x10, .rem_patch+0x10)
927 PATCH_IT(.rem+0x18, .rem_patch+0x18)
928 PATCH_IT(.rem+0x20, .rem_patch+0x20)
929 PATCH_IT(.rem+0x28, .rem_patch+0x28)
930
931 /* Signed division. */
932 PATCH_IT(.div, .div_patch)
933 PATCH_IT(.div+0x08, .div_patch+0x08)
934 PATCH_IT(.div+0x10, .div_patch+0x10)
935 PATCH_IT(.div+0x18, .div_patch+0x18)
936 PATCH_IT(.div+0x20, .div_patch+0x20)
937
938 /* Unsigned multiply. */
939 PATCH_IT(.umul, .umul_patch)
940 PATCH_IT(.umul+0x08, .umul_patch+0x08)
941
942 /* Unsigned remainder. */
943 PATCH_IT(.urem, .urem_patch)
944 PATCH_IT(.urem+0x08, .urem_patch+0x08)
945 PATCH_IT(.urem+0x10, .urem_patch+0x10)
946 PATCH_IT(.urem+0x18, .urem_patch+0x18)
947
948 /* Unsigned division. */
949 PATCH_IT(.udiv, .udiv_patch)
950 PATCH_IT(.udiv+0x08, .udiv_patch+0x08)
951 PATCH_IT(.udiv+0x10, .udiv_patch+0x10)
952
953#undef PATCH_IT
954
955/* Ok, the PROM could have done funny things and apple cider could still 427/* Ok, the PROM could have done funny things and apple cider could still
956 * be sitting in the fault status/address registers. Read them all to 428 * be sitting in the fault status/address registers. Read them all to
957 * clear them so we don't get magic faults later on. 429 * clear them so we don't get magic faults later on.
@@ -962,7 +434,7 @@ sun4m_init:
962 srl %o1, 28, %o1 ! Get a type of the CPU 434 srl %o1, 28, %o1 ! Get a type of the CPU
963 435
964 subcc %o1, 4, %g0 ! TI: Viking or MicroSPARC 436 subcc %o1, 4, %g0 ! TI: Viking or MicroSPARC
965 be sun4c_continue_boot 437 be continue_boot
966 nop 438 nop
967 439
968 set AC_M_SFSR, %o0 440 set AC_M_SFSR, %o0
@@ -972,7 +444,7 @@ sun4m_init:
972 444
973 /* Fujitsu MicroSPARC-II has no asynchronous flavors of FARs */ 445 /* Fujitsu MicroSPARC-II has no asynchronous flavors of FARs */
974 subcc %o1, 0, %g0 446 subcc %o1, 0, %g0
975 be sun4c_continue_boot 447 be continue_boot
976 nop 448 nop
977 449
978 set AC_M_AFSR, %o0 450 set AC_M_AFSR, %o0
@@ -982,8 +454,7 @@ sun4m_init:
982 nop 454 nop
983 455
984 456
985sun4c_continue_boot: 457continue_boot:
986
987 458
988/* Aieee, now set PC and nPC, enable traps, give ourselves a stack and it's 459/* Aieee, now set PC and nPC, enable traps, give ourselves a stack and it's
989 * show-time! 460 * show-time!
@@ -1026,10 +497,7 @@ sun4c_continue_boot:
1026 mov %g0, %g3 497 mov %g0, %g3
1027 stub %g3, [%g2 + %lo(boot_cpu_id)] 498 stub %g3, [%g2 + %lo(boot_cpu_id)]
1028 499
10291: /* boot_cpu_id set. calculate boot_cpu_id4 = boot_cpu_id*4 */ 5001: sll %g3, 2, %g3
1030 sll %g3, 2, %g3
1031 sethi %hi(boot_cpu_id4), %g2
1032 stub %g3, [%g2 + %lo(boot_cpu_id4)]
1033 501
1034 /* Initialize the uwinmask value for init task just in case. 502 /* Initialize the uwinmask value for init task just in case.
1035 * But first make current_set[boot_cpu_id] point to something useful. 503 * But first make current_set[boot_cpu_id] point to something useful.
@@ -1165,19 +633,6 @@ sun4c_continue_boot:
1165 call halt_me 633 call halt_me
1166 nop 634 nop
1167 635
1168sun4_init:
1169 sethi %hi(SUN4_PROM_VECTOR+0x84), %o1
1170 ld [%o1 + %lo(SUN4_PROM_VECTOR+0x84)], %o1
1171 set sun4_notsup, %o0
1172 call %o1 /* printf */
1173 nop
1174 sethi %hi(SUN4_PROM_VECTOR+0xc4), %o1
1175 ld [%o1 + %lo(SUN4_PROM_VECTOR+0xc4)], %o1
1176 call %o1 /* exittomon */
1177 nop
11781: ba 1b ! Cannot exit into KMON
1179 nop
1180
1181no_sun4e_here: 636no_sun4e_here:
1182 ld [%g7 + 0x68], %o1 637 ld [%g7 + 0x68], %o1
1183 set sun4e_notsup, %o0 638 set sun4e_notsup, %o0
diff --git a/arch/sparc/kernel/head_64.S b/arch/sparc/kernel/head_64.S
index 0d810c2f1d00..b42ddbf9651e 100644
--- a/arch/sparc/kernel/head_64.S
+++ b/arch/sparc/kernel/head_64.S
@@ -906,7 +906,7 @@ swapper_4m_tsb:
906 * error and will instead write junk into the relocation and 906 * error and will instead write junk into the relocation and
907 * you'll have an unbootable kernel. 907 * you'll have an unbootable kernel.
908 */ 908 */
909#include "ttable.S" 909#include "ttable_64.S"
910 910
911! 0x0000000000428000 911! 0x0000000000428000
912 912
diff --git a/arch/sparc/kernel/idprom.c b/arch/sparc/kernel/idprom.c
index 9167db40720e..6bd75012109d 100644
--- a/arch/sparc/kernel/idprom.c
+++ b/arch/sparc/kernel/idprom.c
@@ -25,22 +25,9 @@ static struct idprom idprom_buffer;
25 * of the Sparc CPU and have a meaningful IDPROM machtype value that we 25 * of the Sparc CPU and have a meaningful IDPROM machtype value that we
26 * know about. See asm-sparc/machines.h for empirical constants. 26 * know about. See asm-sparc/machines.h for empirical constants.
27 */ 27 */
28static struct Sun_Machine_Models Sun_Machines[NUM_SUN_MACHINES] = { 28static struct Sun_Machine_Models Sun_Machines[] = {
29/* First, Sun4's */ 29/* First, Leon */
30{ .name = "Sun 4/100 Series", .id_machtype = (SM_SUN4 | SM_4_110) },
31{ .name = "Sun 4/200 Series", .id_machtype = (SM_SUN4 | SM_4_260) },
32{ .name = "Sun 4/300 Series", .id_machtype = (SM_SUN4 | SM_4_330) },
33{ .name = "Sun 4/400 Series", .id_machtype = (SM_SUN4 | SM_4_470) },
34/* Now Leon */
35{ .name = "Leon3 System-on-a-Chip", .id_machtype = (M_LEON | M_LEON3_SOC) }, 30{ .name = "Leon3 System-on-a-Chip", .id_machtype = (M_LEON | M_LEON3_SOC) },
36/* Now, Sun4c's */
37{ .name = "Sun4c SparcStation 1", .id_machtype = (SM_SUN4C | SM_4C_SS1) },
38{ .name = "Sun4c SparcStation IPC", .id_machtype = (SM_SUN4C | SM_4C_IPC) },
39{ .name = "Sun4c SparcStation 1+", .id_machtype = (SM_SUN4C | SM_4C_SS1PLUS) },
40{ .name = "Sun4c SparcStation SLC", .id_machtype = (SM_SUN4C | SM_4C_SLC) },
41{ .name = "Sun4c SparcStation 2", .id_machtype = (SM_SUN4C | SM_4C_SS2) },
42{ .name = "Sun4c SparcStation ELC", .id_machtype = (SM_SUN4C | SM_4C_ELC) },
43{ .name = "Sun4c SparcStation IPX", .id_machtype = (SM_SUN4C | SM_4C_IPX) },
44/* Finally, early Sun4m's */ 31/* Finally, early Sun4m's */
45{ .name = "Sun4m SparcSystem600", .id_machtype = (SM_SUN4M | SM_4M_SS60) }, 32{ .name = "Sun4m SparcSystem600", .id_machtype = (SM_SUN4M | SM_4M_SS60) },
46{ .name = "Sun4m SparcStation10/20", .id_machtype = (SM_SUN4M | SM_4M_SS50) }, 33{ .name = "Sun4m SparcStation10/20", .id_machtype = (SM_SUN4M | SM_4M_SS50) },
@@ -53,7 +40,7 @@ static void __init display_system_type(unsigned char machtype)
53 char sysname[128]; 40 char sysname[128];
54 register int i; 41 register int i;
55 42
56 for (i = 0; i < NUM_SUN_MACHINES; i++) { 43 for (i = 0; i < ARRAY_SIZE(Sun_Machines); i++) {
57 if (Sun_Machines[i].id_machtype == machtype) { 44 if (Sun_Machines[i].id_machtype == machtype) {
58 if (machtype != (SM_SUN4M_OBP | 0x00) || 45 if (machtype != (SM_SUN4M_OBP | 0x00) ||
59 prom_getproperty(prom_root_node, "banner-name", 46 prom_getproperty(prom_root_node, "banner-name",
diff --git a/arch/sparc/kernel/ioport.c b/arch/sparc/kernel/ioport.c
index 21bd73943f7f..a2846f5e32d8 100644
--- a/arch/sparc/kernel/ioport.c
+++ b/arch/sparc/kernel/ioport.c
@@ -50,6 +50,8 @@
50#include <asm/io-unit.h> 50#include <asm/io-unit.h>
51#include <asm/leon.h> 51#include <asm/leon.h>
52 52
53const struct sparc32_dma_ops *sparc32_dma_ops;
54
53/* This function must make sure that caches and memory are coherent after DMA 55/* This function must make sure that caches and memory are coherent after DMA
54 * On LEON systems without cache snooping it flushes the entire D-CACHE. 56 * On LEON systems without cache snooping it flushes the entire D-CACHE.
55 */ 57 */
@@ -229,7 +231,7 @@ _sparc_ioremap(struct resource *res, u32 bus, u32 pa, int sz)
229 } 231 }
230 232
231 pa &= PAGE_MASK; 233 pa &= PAGE_MASK;
232 sparc_mapiorange(bus, pa, res->start, resource_size(res)); 234 srmmu_mapiorange(bus, pa, res->start, resource_size(res));
233 235
234 return (void __iomem *)(unsigned long)(res->start + offset); 236 return (void __iomem *)(unsigned long)(res->start + offset);
235} 237}
@@ -243,7 +245,7 @@ static void _sparc_free_io(struct resource *res)
243 245
244 plen = resource_size(res); 246 plen = resource_size(res);
245 BUG_ON((plen & (PAGE_SIZE-1)) != 0); 247 BUG_ON((plen & (PAGE_SIZE-1)) != 0);
246 sparc_unmapiorange(res->start, plen); 248 srmmu_unmapiorange(res->start, plen);
247 release_resource(res); 249 release_resource(res);
248} 250}
249 251
@@ -292,13 +294,13 @@ static void *sbus_alloc_coherent(struct device *dev, size_t len,
292 goto err_nova; 294 goto err_nova;
293 } 295 }
294 296
295 // XXX The mmu_map_dma_area does this for us below, see comments. 297 // XXX The sbus_map_dma_area does this for us below, see comments.
296 // sparc_mapiorange(0, virt_to_phys(va), res->start, len_total); 298 // srmmu_mapiorange(0, virt_to_phys(va), res->start, len_total);
297 /* 299 /*
298 * XXX That's where sdev would be used. Currently we load 300 * XXX That's where sdev would be used. Currently we load
299 * all iommu tables with the same translations. 301 * all iommu tables with the same translations.
300 */ 302 */
301 if (mmu_map_dma_area(dev, dma_addrp, va, res->start, len_total) != 0) 303 if (sbus_map_dma_area(dev, dma_addrp, va, res->start, len_total) != 0)
302 goto err_noiommu; 304 goto err_noiommu;
303 305
304 res->name = op->dev.of_node->name; 306 res->name = op->dev.of_node->name;
@@ -343,7 +345,7 @@ static void sbus_free_coherent(struct device *dev, size_t n, void *p,
343 kfree(res); 345 kfree(res);
344 346
345 pgv = virt_to_page(p); 347 pgv = virt_to_page(p);
346 mmu_unmap_dma_area(dev, ba, n); 348 sbus_unmap_dma_area(dev, ba, n);
347 349
348 __free_pages(pgv, get_order(n)); 350 __free_pages(pgv, get_order(n));
349} 351}
@@ -381,11 +383,6 @@ static int sbus_map_sg(struct device *dev, struct scatterlist *sg, int n,
381 enum dma_data_direction dir, struct dma_attrs *attrs) 383 enum dma_data_direction dir, struct dma_attrs *attrs)
382{ 384{
383 mmu_get_scsi_sgl(dev, sg, n); 385 mmu_get_scsi_sgl(dev, sg, n);
384
385 /*
386 * XXX sparc64 can return a partial length here. sun4c should do this
387 * but it currently panics if it can't fulfill the request - Anton
388 */
389 return n; 386 return n;
390} 387}
391 388
@@ -469,7 +466,7 @@ static void *pci32_alloc_coherent(struct device *dev, size_t len,
469 printk("pci_alloc_consistent: cannot occupy 0x%lx", len_total); 466 printk("pci_alloc_consistent: cannot occupy 0x%lx", len_total);
470 goto err_nova; 467 goto err_nova;
471 } 468 }
472 sparc_mapiorange(0, virt_to_phys(va), res->start, len_total); 469 srmmu_mapiorange(0, virt_to_phys(va), res->start, len_total);
473 470
474 *pba = virt_to_phys(va); /* equals virt_to_bus (R.I.P.) for us. */ 471 *pba = virt_to_phys(va); /* equals virt_to_bus (R.I.P.) for us. */
475 return (void *) res->start; 472 return (void *) res->start;
@@ -514,7 +511,7 @@ static void pci32_free_coherent(struct device *dev, size_t n, void *p,
514 } 511 }
515 512
516 dma_make_coherent(ba, n); 513 dma_make_coherent(ba, n);
517 sparc_unmapiorange((unsigned long)p, n); 514 srmmu_unmapiorange((unsigned long)p, n);
518 515
519 release_resource(res); 516 release_resource(res);
520 kfree(res); 517 kfree(res);
diff --git a/arch/sparc/kernel/irq.h b/arch/sparc/kernel/irq.h
index 5a021dd2f854..b66b6aad1d6d 100644
--- a/arch/sparc/kernel/irq.h
+++ b/arch/sparc/kernel/irq.h
@@ -1,6 +1,5 @@
1#include <linux/platform_device.h> 1#include <linux/platform_device.h>
2 2
3#include <asm/btfixup.h>
4#include <asm/cpu_type.h> 3#include <asm/cpu_type.h>
5 4
6struct irq_bucket { 5struct irq_bucket {
@@ -10,6 +9,9 @@ struct irq_bucket {
10 unsigned int pil; 9 unsigned int pil;
11}; 10};
12 11
12#define SUN4M_HARD_INT(x) (0x000000001 << (x))
13#define SUN4M_SOFT_INT(x) (0x000010000 << (x))
14
13#define SUN4D_MAX_BOARD 10 15#define SUN4D_MAX_BOARD 10
14#define SUN4D_MAX_IRQ ((SUN4D_MAX_BOARD + 2) << 5) 16#define SUN4D_MAX_IRQ ((SUN4D_MAX_BOARD + 2) << 5)
15 17
@@ -41,52 +43,46 @@ struct sun4m_irq_global {
41extern struct sun4m_irq_percpu __iomem *sun4m_irq_percpu[SUN4M_NCPUS]; 43extern struct sun4m_irq_percpu __iomem *sun4m_irq_percpu[SUN4M_NCPUS];
42extern struct sun4m_irq_global __iomem *sun4m_irq_global; 44extern struct sun4m_irq_global __iomem *sun4m_irq_global;
43 45
46/* The following definitions describe the individual platform features: */
47#define FEAT_L10_CLOCKSOURCE (1 << 0) /* L10 timer is used as a clocksource */
48#define FEAT_L10_CLOCKEVENT (1 << 1) /* L10 timer is used as a clockevent */
49#define FEAT_L14_ONESHOT (1 << 2) /* L14 timer clockevent can oneshot */
50
44/* 51/*
45 * Platform specific irq configuration 52 * Platform specific configuration
46 * The individual platforms assign their platform 53 * The individual platforms assign their platform
47 * specifics in their init functions. 54 * specifics in their init functions.
48 */ 55 */
49struct sparc_irq_config { 56struct sparc_config {
50 void (*init_timers)(irq_handler_t); 57 void (*init_timers)(void);
51 unsigned int (*build_device_irq)(struct platform_device *op, 58 unsigned int (*build_device_irq)(struct platform_device *op,
52 unsigned int real_irq); 59 unsigned int real_irq);
60
61 /* generic clockevent features - see FEAT_* above */
62 int features;
63
64 /* clock rate used for clock event timer */
65 int clock_rate;
66
67 /* one period for clock source timer */
68 unsigned int cs_period;
69
70 /* function to obtain offsett for cs period */
71 unsigned int (*get_cycles_offset)(void);
72
73 void (*clear_clock_irq)(void);
74 void (*load_profile_irq)(int cpu, unsigned int limit);
53}; 75};
54extern struct sparc_irq_config sparc_irq_config; 76extern struct sparc_config sparc_config;
55 77
56unsigned int irq_alloc(unsigned int real_irq, unsigned int pil); 78unsigned int irq_alloc(unsigned int real_irq, unsigned int pil);
57void irq_link(unsigned int irq); 79void irq_link(unsigned int irq);
58void irq_unlink(unsigned int irq); 80void irq_unlink(unsigned int irq);
59void handler_irq(unsigned int pil, struct pt_regs *regs); 81void handler_irq(unsigned int pil, struct pt_regs *regs);
60 82
61/* Dave Redman (djhr@tadpole.co.uk) 83unsigned long leon_get_irqmask(unsigned int irq);
62 * changed these to function pointers.. it saves cycles and will allow
63 * the irq dependencies to be split into different files at a later date
64 * sun4c_irq.c, sun4m_irq.c etc so we could reduce the kernel size.
65 * Jakub Jelinek (jj@sunsite.mff.cuni.cz)
66 * Changed these to btfixup entities... It saves cycles :)
67 */
68
69BTFIXUPDEF_CALL(void, clear_clock_irq, void)
70BTFIXUPDEF_CALL(void, load_profile_irq, int, unsigned int)
71
72static inline void clear_clock_irq(void)
73{
74 BTFIXUP_CALL(clear_clock_irq)();
75}
76
77static inline void load_profile_irq(int cpu, int limit)
78{
79 BTFIXUP_CALL(load_profile_irq)(cpu, limit);
80}
81 84
82#ifdef CONFIG_SMP 85#ifdef CONFIG_SMP
83BTFIXUPDEF_CALL(void, set_cpu_int, int, int)
84BTFIXUPDEF_CALL(void, clear_cpu_int, int, int)
85BTFIXUPDEF_CALL(void, set_irq_udt, int)
86
87#define set_cpu_int(cpu,level) BTFIXUP_CALL(set_cpu_int)(cpu,level)
88#define clear_cpu_int(cpu,level) BTFIXUP_CALL(clear_cpu_int)(cpu,level)
89#define set_irq_udt(cpu) BTFIXUP_CALL(set_irq_udt)(cpu)
90 86
91/* All SUN4D IPIs are sent on this IRQ, may be shared with hard IRQs */ 87/* All SUN4D IPIs are sent on this IRQ, may be shared with hard IRQs */
92#define SUN4D_IPI_IRQ 13 88#define SUN4D_IPI_IRQ 13
diff --git a/arch/sparc/kernel/irq_32.c b/arch/sparc/kernel/irq_32.c
index b2668afd1c34..ae04914f7774 100644
--- a/arch/sparc/kernel/irq_32.c
+++ b/arch/sparc/kernel/irq_32.c
@@ -23,16 +23,8 @@
23#include "kernel.h" 23#include "kernel.h"
24#include "irq.h" 24#include "irq.h"
25 25
26#ifdef CONFIG_SMP
27#define SMP_NOP2 "nop; nop;\n\t"
28#define SMP_NOP3 "nop; nop; nop;\n\t"
29#else
30#define SMP_NOP2
31#define SMP_NOP3
32#endif /* SMP */
33
34/* platform specific irq setup */ 26/* platform specific irq setup */
35struct sparc_irq_config sparc_irq_config; 27struct sparc_config sparc_config;
36 28
37unsigned long arch_local_irq_save(void) 29unsigned long arch_local_irq_save(void)
38{ 30{
@@ -41,7 +33,6 @@ unsigned long arch_local_irq_save(void)
41 33
42 __asm__ __volatile__( 34 __asm__ __volatile__(
43 "rd %%psr, %0\n\t" 35 "rd %%psr, %0\n\t"
44 SMP_NOP3 /* Sun4m + Cypress + SMP bug */
45 "or %0, %2, %1\n\t" 36 "or %0, %2, %1\n\t"
46 "wr %1, 0, %%psr\n\t" 37 "wr %1, 0, %%psr\n\t"
47 "nop; nop; nop\n" 38 "nop; nop; nop\n"
@@ -59,7 +50,6 @@ void arch_local_irq_enable(void)
59 50
60 __asm__ __volatile__( 51 __asm__ __volatile__(
61 "rd %%psr, %0\n\t" 52 "rd %%psr, %0\n\t"
62 SMP_NOP3 /* Sun4m + Cypress + SMP bug */
63 "andn %0, %1, %0\n\t" 53 "andn %0, %1, %0\n\t"
64 "wr %0, 0, %%psr\n\t" 54 "wr %0, 0, %%psr\n\t"
65 "nop; nop; nop\n" 55 "nop; nop; nop\n"
@@ -76,7 +66,6 @@ void arch_local_irq_restore(unsigned long old_psr)
76 __asm__ __volatile__( 66 __asm__ __volatile__(
77 "rd %%psr, %0\n\t" 67 "rd %%psr, %0\n\t"
78 "and %2, %1, %2\n\t" 68 "and %2, %1, %2\n\t"
79 SMP_NOP2 /* Sun4m + Cypress + SMP bug */
80 "andn %0, %1, %0\n\t" 69 "andn %0, %1, %0\n\t"
81 "wr %0, %2, %%psr\n\t" 70 "wr %0, %2, %%psr\n\t"
82 "nop; nop; nop\n" 71 "nop; nop; nop\n"
@@ -346,11 +335,6 @@ void sparc_floppy_irq(int irq, void *dev_id, struct pt_regs *regs)
346void __init init_IRQ(void) 335void __init init_IRQ(void)
347{ 336{
348 switch (sparc_cpu_model) { 337 switch (sparc_cpu_model) {
349 case sun4c:
350 case sun4:
351 sun4c_init_IRQ();
352 break;
353
354 case sun4m: 338 case sun4m:
355 pcic_probe(); 339 pcic_probe();
356 if (pcic_present()) 340 if (pcic_present())
@@ -371,6 +355,5 @@ void __init init_IRQ(void)
371 prom_printf("Cannot initialize IRQs on this Sun machine..."); 355 prom_printf("Cannot initialize IRQs on this Sun machine...");
372 break; 356 break;
373 } 357 }
374 btfixup();
375} 358}
376 359
diff --git a/arch/sparc/kernel/irq_64.c b/arch/sparc/kernel/irq_64.c
index dff2c3d7d370..9bcbbe2c4e7e 100644
--- a/arch/sparc/kernel/irq_64.c
+++ b/arch/sparc/kernel/irq_64.c
@@ -799,7 +799,7 @@ static void kill_prom_timer(void)
799 prom_limit0 = prom_timers->limit0; 799 prom_limit0 = prom_timers->limit0;
800 prom_limit1 = prom_timers->limit1; 800 prom_limit1 = prom_timers->limit1;
801 801
802 /* Just as in sun4c/sun4m PROM uses timer which ticks at IRQ 14. 802 /* Just as in sun4c PROM uses timer which ticks at IRQ 14.
803 * We turn both off here just to be paranoid. 803 * We turn both off here just to be paranoid.
804 */ 804 */
805 prom_timers->limit0 = 0; 805 prom_timers->limit0 = 0;
diff --git a/arch/sparc/kernel/kernel.h b/arch/sparc/kernel/kernel.h
index fd6c36b1df74..a86372d34587 100644
--- a/arch/sparc/kernel/kernel.h
+++ b/arch/sparc/kernel/kernel.h
@@ -32,9 +32,6 @@ extern void cpu_probe(void);
32/* traps_32.c */ 32/* traps_32.c */
33extern void handle_hw_divzero(struct pt_regs *regs, unsigned long pc, 33extern void handle_hw_divzero(struct pt_regs *regs, unsigned long pc,
34 unsigned long npc, unsigned long psr); 34 unsigned long npc, unsigned long psr);
35/* muldiv.c */
36extern int do_user_muldiv (struct pt_regs *, unsigned long);
37
38/* irq_32.c */ 35/* irq_32.c */
39extern struct irqaction static_irqaction[]; 36extern struct irqaction static_irqaction[];
40extern int static_irq_count; 37extern int static_irq_count;
@@ -43,12 +40,7 @@ extern spinlock_t irq_action_lock;
43extern void unexpected_irq(int irq, void *dev_id, struct pt_regs * regs); 40extern void unexpected_irq(int irq, void *dev_id, struct pt_regs * regs);
44extern void init_IRQ(void); 41extern void init_IRQ(void);
45 42
46/* sun4c_irq.c */
47extern void sun4c_init_IRQ(void);
48
49/* sun4m_irq.c */ 43/* sun4m_irq.c */
50extern unsigned int lvl14_resolution;
51
52extern void sun4m_init_IRQ(void); 44extern void sun4m_init_IRQ(void);
53extern void sun4m_unmask_profile_irq(void); 45extern void sun4m_unmask_profile_irq(void);
54extern void sun4m_clear_profile_irq(int cpu); 46extern void sun4m_clear_profile_irq(int cpu);
@@ -85,8 +77,6 @@ extern unsigned int patchme_maybe_smp_msg[];
85extern void floppy_hardint(void); 77extern void floppy_hardint(void);
86 78
87/* trampoline_32.S */ 79/* trampoline_32.S */
88extern int __smp4m_processor_id(void);
89extern int __smp4d_processor_id(void);
90extern unsigned long sun4m_cpu_startup; 80extern unsigned long sun4m_cpu_startup;
91extern unsigned long sun4d_cpu_startup; 81extern unsigned long sun4d_cpu_startup;
92 82
diff --git a/arch/sparc/kernel/leon_kernel.c b/arch/sparc/kernel/leon_kernel.c
index 35e43673c453..77c1b916e4dd 100644
--- a/arch/sparc/kernel/leon_kernel.c
+++ b/arch/sparc/kernel/leon_kernel.c
@@ -10,6 +10,8 @@
10#include <linux/of_platform.h> 10#include <linux/of_platform.h>
11#include <linux/interrupt.h> 11#include <linux/interrupt.h>
12#include <linux/of_device.h> 12#include <linux/of_device.h>
13#include <linux/clocksource.h>
14#include <linux/clockchips.h>
13 15
14#include <asm/oplib.h> 16#include <asm/oplib.h>
15#include <asm/timer.h> 17#include <asm/timer.h>
@@ -84,7 +86,7 @@ void leon_eirq_setup(unsigned int eirq)
84 sparc_leon_eirq = eirq; 86 sparc_leon_eirq = eirq;
85} 87}
86 88
87static inline unsigned long get_irqmask(unsigned int irq) 89unsigned long leon_get_irqmask(unsigned int irq)
88{ 90{
89 unsigned long mask; 91 unsigned long mask;
90 92
@@ -210,7 +212,7 @@ unsigned int leon_build_device_irq(unsigned int real_irq,
210 unsigned long mask; 212 unsigned long mask;
211 213
212 irq = 0; 214 irq = 0;
213 mask = get_irqmask(real_irq); 215 mask = leon_get_irqmask(real_irq);
214 if (mask == 0) 216 if (mask == 0)
215 goto out; 217 goto out;
216 218
@@ -250,7 +252,38 @@ void leon_update_virq_handling(unsigned int virq,
250 irq_set_chip_data(virq, (void *)mask); 252 irq_set_chip_data(virq, (void *)mask);
251} 253}
252 254
253void __init leon_init_timers(irq_handler_t counter_fn) 255static u32 leon_cycles_offset(void)
256{
257 u32 rld, val, off;
258 rld = LEON3_BYPASS_LOAD_PA(&leon3_gptimer_regs->e[leon3_gptimer_idx].rld);
259 val = LEON3_BYPASS_LOAD_PA(&leon3_gptimer_regs->e[leon3_gptimer_idx].val);
260 off = rld - val;
261 return rld - val;
262}
263
264#ifdef CONFIG_SMP
265
266/* smp clockevent irq */
267irqreturn_t leon_percpu_timer_ce_interrupt(int irq, void *unused)
268{
269 struct clock_event_device *ce;
270 int cpu = smp_processor_id();
271
272 leon_clear_profile_irq(cpu);
273
274 ce = &per_cpu(sparc32_clockevent, cpu);
275
276 irq_enter();
277 if (ce->event_handler)
278 ce->event_handler(ce);
279 irq_exit();
280
281 return IRQ_HANDLED;
282}
283
284#endif /* CONFIG_SMP */
285
286void __init leon_init_timers(void)
254{ 287{
255 int irq, eirq; 288 int irq, eirq;
256 struct device_node *rootnp, *np, *nnp; 289 struct device_node *rootnp, *np, *nnp;
@@ -260,6 +293,14 @@ void __init leon_init_timers(irq_handler_t counter_fn)
260 int ampopts; 293 int ampopts;
261 int err; 294 int err;
262 295
296 sparc_config.get_cycles_offset = leon_cycles_offset;
297 sparc_config.cs_period = 1000000 / HZ;
298 sparc_config.features |= FEAT_L10_CLOCKSOURCE;
299
300#ifndef CONFIG_SMP
301 sparc_config.features |= FEAT_L10_CLOCKEVENT;
302#endif
303
263 leondebug_irq_disable = 0; 304 leondebug_irq_disable = 0;
264 leon_debug_irqout = 0; 305 leon_debug_irqout = 0;
265 master_l10_counter = (unsigned int *)&dummy_master_l10_counter; 306 master_l10_counter = (unsigned int *)&dummy_master_l10_counter;
@@ -369,7 +410,7 @@ void __init leon_init_timers(irq_handler_t counter_fn)
369 leon_eirq_setup(eirq); 410 leon_eirq_setup(eirq);
370 411
371 irq = _leon_build_device_irq(NULL, leon3_gptimer_irq+leon3_gptimer_idx); 412 irq = _leon_build_device_irq(NULL, leon3_gptimer_irq+leon3_gptimer_idx);
372 err = request_irq(irq, counter_fn, IRQF_TIMER, "timer", NULL); 413 err = request_irq(irq, timer_interrupt, IRQF_TIMER, "timer", NULL);
373 if (err) { 414 if (err) {
374 printk(KERN_ERR "unable to attach timer IRQ%d\n", irq); 415 printk(KERN_ERR "unable to attach timer IRQ%d\n", irq);
375 prom_halt(); 416 prom_halt();
@@ -386,7 +427,7 @@ void __init leon_init_timers(irq_handler_t counter_fn)
386 */ 427 */
387 local_irq_save(flags); 428 local_irq_save(flags);
388 patchme_maybe_smp_msg[0] = 0x01000000; /* NOP out the branch */ 429 patchme_maybe_smp_msg[0] = 0x01000000; /* NOP out the branch */
389 local_flush_cache_all(); 430 local_ops->cache_all();
390 local_irq_restore(flags); 431 local_irq_restore(flags);
391 } 432 }
392#endif 433#endif
@@ -401,7 +442,7 @@ void __init leon_init_timers(irq_handler_t counter_fn)
401 /* Install per-cpu IRQ handler for broadcasted ticker */ 442 /* Install per-cpu IRQ handler for broadcasted ticker */
402 irq = leon_build_device_irq(leon3_ticker_irq, handle_percpu_irq, 443 irq = leon_build_device_irq(leon3_ticker_irq, handle_percpu_irq,
403 "per-cpu", 0); 444 "per-cpu", 0);
404 err = request_irq(irq, leon_percpu_timer_interrupt, 445 err = request_irq(irq, leon_percpu_timer_ce_interrupt,
405 IRQF_PERCPU | IRQF_TIMER, "ticker", 446 IRQF_PERCPU | IRQF_TIMER, "ticker",
406 NULL); 447 NULL);
407 if (err) { 448 if (err) {
@@ -422,13 +463,12 @@ bad:
422 return; 463 return;
423} 464}
424 465
425void leon_clear_clock_irq(void) 466static void leon_clear_clock_irq(void)
426{ 467{
427} 468}
428 469
429void leon_load_profile_irq(int cpu, unsigned int limit) 470static void leon_load_profile_irq(int cpu, unsigned int limit)
430{ 471{
431 BUG();
432} 472}
433 473
434void __init leon_trans_init(struct device_node *dp) 474void __init leon_trans_init(struct device_node *dp)
@@ -457,25 +497,6 @@ void __init leon_node_init(struct device_node *dp, struct device_node ***nextp)
457} 497}
458 498
459#ifdef CONFIG_SMP 499#ifdef CONFIG_SMP
460
461void leon_set_cpu_int(int cpu, int level)
462{
463 unsigned long mask;
464 mask = get_irqmask(level);
465 LEON3_BYPASS_STORE_PA(&leon3_irqctrl_regs->force[cpu], mask);
466}
467
468static void leon_clear_ipi(int cpu, int level)
469{
470 unsigned long mask;
471 mask = get_irqmask(level);
472 LEON3_BYPASS_STORE_PA(&leon3_irqctrl_regs->force[cpu], mask<<16);
473}
474
475static void leon_set_udt(int cpu)
476{
477}
478
479void leon_clear_profile_irq(int cpu) 500void leon_clear_profile_irq(int cpu)
480{ 501{
481} 502}
@@ -483,7 +504,7 @@ void leon_clear_profile_irq(int cpu)
483void leon_enable_irq_cpu(unsigned int irq_nr, unsigned int cpu) 504void leon_enable_irq_cpu(unsigned int irq_nr, unsigned int cpu)
484{ 505{
485 unsigned long mask, flags, *addr; 506 unsigned long mask, flags, *addr;
486 mask = get_irqmask(irq_nr); 507 mask = leon_get_irqmask(irq_nr);
487 spin_lock_irqsave(&leon_irq_lock, flags); 508 spin_lock_irqsave(&leon_irq_lock, flags);
488 addr = (unsigned long *)LEON_IMASK(cpu); 509 addr = (unsigned long *)LEON_IMASK(cpu);
489 LEON3_BYPASS_STORE_PA(addr, (LEON3_BYPASS_LOAD_PA(addr) | mask)); 510 LEON3_BYPASS_STORE_PA(addr, (LEON3_BYPASS_LOAD_PA(addr) | mask));
@@ -494,20 +515,11 @@ void leon_enable_irq_cpu(unsigned int irq_nr, unsigned int cpu)
494 515
495void __init leon_init_IRQ(void) 516void __init leon_init_IRQ(void)
496{ 517{
497 sparc_irq_config.init_timers = leon_init_timers; 518 sparc_config.init_timers = leon_init_timers;
498 sparc_irq_config.build_device_irq = _leon_build_device_irq; 519 sparc_config.build_device_irq = _leon_build_device_irq;
499 520 sparc_config.clock_rate = 1000000;
500 BTFIXUPSET_CALL(clear_clock_irq, leon_clear_clock_irq, 521 sparc_config.clear_clock_irq = leon_clear_clock_irq;
501 BTFIXUPCALL_NORM); 522 sparc_config.load_profile_irq = leon_load_profile_irq;
502 BTFIXUPSET_CALL(load_profile_irq, leon_load_profile_irq,
503 BTFIXUPCALL_NOP);
504
505#ifdef CONFIG_SMP
506 BTFIXUPSET_CALL(set_cpu_int, leon_set_cpu_int, BTFIXUPCALL_NORM);
507 BTFIXUPSET_CALL(clear_cpu_int, leon_clear_ipi, BTFIXUPCALL_NORM);
508 BTFIXUPSET_CALL(set_irq_udt, leon_set_udt, BTFIXUPCALL_NORM);
509#endif
510
511} 523}
512 524
513void __init leon_init(void) 525void __init leon_init(void)
diff --git a/arch/sparc/kernel/leon_smp.c b/arch/sparc/kernel/leon_smp.c
index 160cac9c4036..29325bacba6f 100644
--- a/arch/sparc/kernel/leon_smp.c
+++ b/arch/sparc/kernel/leon_smp.c
@@ -24,6 +24,7 @@
24#include <linux/delay.h> 24#include <linux/delay.h>
25#include <linux/gfp.h> 25#include <linux/gfp.h>
26#include <linux/cpu.h> 26#include <linux/cpu.h>
27#include <linux/clockchips.h>
27 28
28#include <asm/cacheflush.h> 29#include <asm/cacheflush.h>
29#include <asm/tlbflush.h> 30#include <asm/tlbflush.h>
@@ -43,6 +44,7 @@
43#include <asm/asi.h> 44#include <asm/asi.h>
44#include <asm/leon.h> 45#include <asm/leon.h>
45#include <asm/leon_amba.h> 46#include <asm/leon_amba.h>
47#include <asm/timer.h>
46 48
47#include "kernel.h" 49#include "kernel.h"
48 50
@@ -69,26 +71,24 @@ static inline unsigned long do_swap(volatile unsigned long *ptr,
69 return val; 71 return val;
70} 72}
71 73
72static void smp_setup_percpu_timer(void);
73
74void __cpuinit leon_callin(void) 74void __cpuinit leon_callin(void)
75{ 75{
76 int cpuid = hard_smpleon_processor_id(); 76 int cpuid = hard_smp_processor_id();
77 77
78 local_flush_cache_all(); 78 local_ops->cache_all();
79 local_flush_tlb_all(); 79 local_ops->tlb_all();
80 leon_configure_cache_smp(); 80 leon_configure_cache_smp();
81 81
82 notify_cpu_starting(cpuid); 82 notify_cpu_starting(cpuid);
83 83
84 /* Get our local ticker going. */ 84 /* Get our local ticker going. */
85 smp_setup_percpu_timer(); 85 register_percpu_ce(cpuid);
86 86
87 calibrate_delay(); 87 calibrate_delay();
88 smp_store_cpu_info(cpuid); 88 smp_store_cpu_info(cpuid);
89 89
90 local_flush_cache_all(); 90 local_ops->cache_all();
91 local_flush_tlb_all(); 91 local_ops->tlb_all();
92 92
93 /* 93 /*
94 * Unblock the master CPU _only_ when the scheduler state 94 * Unblock the master CPU _only_ when the scheduler state
@@ -99,8 +99,8 @@ void __cpuinit leon_callin(void)
99 */ 99 */
100 do_swap(&cpu_callin_map[cpuid], 1); 100 do_swap(&cpu_callin_map[cpuid], 1);
101 101
102 local_flush_cache_all(); 102 local_ops->cache_all();
103 local_flush_tlb_all(); 103 local_ops->tlb_all();
104 104
105 /* Fix idle thread fields. */ 105 /* Fix idle thread fields. */
106 __asm__ __volatile__("ld [%0], %%g6\n\t" : : "r"(&current_set[cpuid]) 106 __asm__ __volatile__("ld [%0], %%g6\n\t" : : "r"(&current_set[cpuid])
@@ -143,8 +143,8 @@ void __init leon_configure_cache_smp(void)
143 } 143 }
144 } 144 }
145 145
146 local_flush_cache_all(); 146 local_ops->cache_all();
147 local_flush_tlb_all(); 147 local_ops->tlb_all();
148} 148}
149 149
150void leon_smp_setbroadcast(unsigned int mask) 150void leon_smp_setbroadcast(unsigned int mask)
@@ -199,8 +199,7 @@ void __init leon_boot_cpus(void)
199 leon_smp_setbroadcast(1 << LEON3_IRQ_TICKER); 199 leon_smp_setbroadcast(1 << LEON3_IRQ_TICKER);
200 200
201 leon_configure_cache_smp(); 201 leon_configure_cache_smp();
202 smp_setup_percpu_timer(); 202 local_ops->cache_all();
203 local_flush_cache_all();
204 203
205} 204}
206 205
@@ -227,7 +226,7 @@ int __cpuinit leon_boot_one_cpu(int i)
227 /* whirrr, whirrr, whirrrrrrrrr... */ 226 /* whirrr, whirrr, whirrrrrrrrr... */
228 printk(KERN_INFO "Starting CPU %d : (irqmp: 0x%x)\n", (unsigned int)i, 227 printk(KERN_INFO "Starting CPU %d : (irqmp: 0x%x)\n", (unsigned int)i,
229 (unsigned int)&leon3_irqctrl_regs->mpstatus); 228 (unsigned int)&leon3_irqctrl_regs->mpstatus);
230 local_flush_cache_all(); 229 local_ops->cache_all();
231 230
232 /* Make sure all IRQs are of from the start for this new CPU */ 231 /* Make sure all IRQs are of from the start for this new CPU */
233 LEON_BYPASS_STORE_PA(&leon3_irqctrl_regs->mask[i], 0); 232 LEON_BYPASS_STORE_PA(&leon3_irqctrl_regs->mask[i], 0);
@@ -252,7 +251,7 @@ int __cpuinit leon_boot_one_cpu(int i)
252 leon_enable_irq_cpu(leon_ipi_irq, i); 251 leon_enable_irq_cpu(leon_ipi_irq, i);
253 } 252 }
254 253
255 local_flush_cache_all(); 254 local_ops->cache_all();
256 return 0; 255 return 0;
257} 256}
258 257
@@ -272,7 +271,7 @@ void __init leon_smp_done(void)
272 } 271 }
273 } 272 }
274 *prev = first; 273 *prev = first;
275 local_flush_cache_all(); 274 local_ops->cache_all();
276 275
277 /* Free unneeded trap tables */ 276 /* Free unneeded trap tables */
278 if (!cpu_present(1)) { 277 if (!cpu_present(1)) {
@@ -338,7 +337,7 @@ static void __init leon_ipi_init(void)
338 local_irq_save(flags); 337 local_irq_save(flags);
339 trap_table = &sparc_ttable[SP_TRAP_IRQ1 + (leon_ipi_irq - 1)]; 338 trap_table = &sparc_ttable[SP_TRAP_IRQ1 + (leon_ipi_irq - 1)];
340 trap_table->inst_three += smpleon_ipi - real_irq_entry; 339 trap_table->inst_three += smpleon_ipi - real_irq_entry;
341 local_flush_cache_all(); 340 local_ops->cache_all();
342 local_irq_restore(flags); 341 local_irq_restore(flags);
343 342
344 for_each_possible_cpu(cpu) { 343 for_each_possible_cpu(cpu) {
@@ -347,6 +346,13 @@ static void __init leon_ipi_init(void)
347 } 346 }
348} 347}
349 348
349static void leon_send_ipi(int cpu, int level)
350{
351 unsigned long mask;
352 mask = leon_get_irqmask(level);
353 LEON3_BYPASS_STORE_PA(&leon3_irqctrl_regs->force[cpu], mask);
354}
355
350static void leon_ipi_single(int cpu) 356static void leon_ipi_single(int cpu)
351{ 357{
352 struct leon_ipi_work *work = &per_cpu(leon_ipi_work, cpu); 358 struct leon_ipi_work *work = &per_cpu(leon_ipi_work, cpu);
@@ -355,7 +361,7 @@ static void leon_ipi_single(int cpu)
355 work->single = 1; 361 work->single = 1;
356 362
357 /* Generate IRQ on the CPU */ 363 /* Generate IRQ on the CPU */
358 set_cpu_int(cpu, leon_ipi_irq); 364 leon_send_ipi(cpu, leon_ipi_irq);
359} 365}
360 366
361static void leon_ipi_mask_one(int cpu) 367static void leon_ipi_mask_one(int cpu)
@@ -366,7 +372,7 @@ static void leon_ipi_mask_one(int cpu)
366 work->msk = 1; 372 work->msk = 1;
367 373
368 /* Generate IRQ on the CPU */ 374 /* Generate IRQ on the CPU */
369 set_cpu_int(cpu, leon_ipi_irq); 375 leon_send_ipi(cpu, leon_ipi_irq);
370} 376}
371 377
372static void leon_ipi_resched(int cpu) 378static void leon_ipi_resched(int cpu)
@@ -377,7 +383,7 @@ static void leon_ipi_resched(int cpu)
377 work->resched = 1; 383 work->resched = 1;
378 384
379 /* Generate IRQ on the CPU (any IRQ will cause resched) */ 385 /* Generate IRQ on the CPU (any IRQ will cause resched) */
380 set_cpu_int(cpu, leon_ipi_irq); 386 leon_send_ipi(cpu, leon_ipi_irq);
381} 387}
382 388
383void leonsmp_ipi_interrupt(void) 389void leonsmp_ipi_interrupt(void)
@@ -449,7 +455,7 @@ static void leon_cross_call(smpfunc_t func, cpumask_t mask, unsigned long arg1,
449 if (cpumask_test_cpu(i, &mask)) { 455 if (cpumask_test_cpu(i, &mask)) {
450 ccall_info.processors_in[i] = 0; 456 ccall_info.processors_in[i] = 0;
451 ccall_info.processors_out[i] = 0; 457 ccall_info.processors_out[i] = 0;
452 set_cpu_int(i, LEON3_IRQ_CROSS_CALL); 458 leon_send_ipi(i, LEON3_IRQ_CROSS_CALL);
453 459
454 } 460 }
455 } 461 }
@@ -492,68 +498,19 @@ void leon_cross_call_irq(void)
492 ccall_info.processors_out[i] = 1; 498 ccall_info.processors_out[i] = 1;
493} 499}
494 500
495irqreturn_t leon_percpu_timer_interrupt(int irq, void *unused) 501static const struct sparc32_ipi_ops leon_ipi_ops = {
496{ 502 .cross_call = leon_cross_call,
497 int cpu = smp_processor_id(); 503 .resched = leon_ipi_resched,
498 504 .single = leon_ipi_single,
499 leon_clear_profile_irq(cpu); 505 .mask_one = leon_ipi_mask_one,
500 506};
501 profile_tick(CPU_PROFILING);
502
503 if (!--prof_counter(cpu)) {
504 int user = user_mode(get_irq_regs());
505
506 update_process_times(user);
507
508 prof_counter(cpu) = prof_multiplier(cpu);
509 }
510
511 return IRQ_HANDLED;
512}
513
514static void __init smp_setup_percpu_timer(void)
515{
516 int cpu = smp_processor_id();
517
518 prof_counter(cpu) = prof_multiplier(cpu) = 1;
519}
520
521void __init leon_blackbox_id(unsigned *addr)
522{
523 int rd = *addr & 0x3e000000;
524 int rs1 = rd >> 11;
525
526 /* patch places where ___b_hard_smp_processor_id appears */
527 addr[0] = 0x81444000 | rd; /* rd %asr17, reg */
528 addr[1] = 0x8130201c | rd | rs1; /* srl reg, 0x1c, reg */
529 addr[2] = 0x01000000; /* nop */
530}
531
532void __init leon_blackbox_current(unsigned *addr)
533{
534 int rd = *addr & 0x3e000000;
535 int rs1 = rd >> 11;
536
537 /* patch LOAD_CURRENT macro where ___b_load_current appears */
538 addr[0] = 0x81444000 | rd; /* rd %asr17, reg */
539 addr[2] = 0x8130201c | rd | rs1; /* srl reg, 0x1c, reg */
540 addr[4] = 0x81282002 | rd | rs1; /* sll reg, 0x2, reg */
541
542}
543 507
544void __init leon_init_smp(void) 508void __init leon_init_smp(void)
545{ 509{
546 /* Patch ipi15 trap table */ 510 /* Patch ipi15 trap table */
547 t_nmi[1] = t_nmi[1] + (linux_trap_ipi15_leon - linux_trap_ipi15_sun4m); 511 t_nmi[1] = t_nmi[1] + (linux_trap_ipi15_leon - linux_trap_ipi15_sun4m);
548 512
549 BTFIXUPSET_BLACKBOX(hard_smp_processor_id, leon_blackbox_id); 513 sparc32_ipi_ops = &leon_ipi_ops;
550 BTFIXUPSET_BLACKBOX(load_current, leon_blackbox_current);
551 BTFIXUPSET_CALL(smp_cross_call, leon_cross_call, BTFIXUPCALL_NORM);
552 BTFIXUPSET_CALL(__hard_smp_processor_id, __leon_processor_id,
553 BTFIXUPCALL_NORM);
554 BTFIXUPSET_CALL(smp_ipi_resched, leon_ipi_resched, BTFIXUPCALL_NORM);
555 BTFIXUPSET_CALL(smp_ipi_single, leon_ipi_single, BTFIXUPCALL_NORM);
556 BTFIXUPSET_CALL(smp_ipi_mask_one, leon_ipi_mask_one, BTFIXUPCALL_NORM);
557} 514}
558 515
559#endif /* CONFIG_SPARC_LEON */ 516#endif /* CONFIG_SPARC_LEON */
diff --git a/arch/sparc/kernel/module.c b/arch/sparc/kernel/module.c
index 276359e1ff56..15e0a1693976 100644
--- a/arch/sparc/kernel/module.c
+++ b/arch/sparc/kernel/module.c
@@ -32,26 +32,11 @@ static void *module_map(unsigned long size)
32 GFP_KERNEL, PAGE_KERNEL, -1, 32 GFP_KERNEL, PAGE_KERNEL, -1,
33 __builtin_return_address(0)); 33 __builtin_return_address(0));
34} 34}
35
36static char *dot2underscore(char *name)
37{
38 return name;
39}
40#else 35#else
41static void *module_map(unsigned long size) 36static void *module_map(unsigned long size)
42{ 37{
43 return vmalloc(size); 38 return vmalloc(size);
44} 39}
45
46/* Replace references to .func with _Func */
47static char *dot2underscore(char *name)
48{
49 if (name[0] == '.') {
50 name[0] = '_';
51 name[1] = toupper(name[1]);
52 }
53 return name;
54}
55#endif /* CONFIG_SPARC64 */ 40#endif /* CONFIG_SPARC64 */
56 41
57void *module_alloc(unsigned long size) 42void *module_alloc(unsigned long size)
@@ -93,12 +78,8 @@ int module_frob_arch_sections(Elf_Ehdr *hdr,
93 78
94 for (i = 1; i < sechdrs[symidx].sh_size / sizeof(Elf_Sym); i++) { 79 for (i = 1; i < sechdrs[symidx].sh_size / sizeof(Elf_Sym); i++) {
95 if (sym[i].st_shndx == SHN_UNDEF) { 80 if (sym[i].st_shndx == SHN_UNDEF) {
96 if (ELF_ST_TYPE(sym[i].st_info) == STT_REGISTER) { 81 if (ELF_ST_TYPE(sym[i].st_info) == STT_REGISTER)
97 sym[i].st_shndx = SHN_ABS; 82 sym[i].st_shndx = SHN_ABS;
98 } else {
99 char *name = strtab + sym[i].st_name;
100 dot2underscore(name);
101 }
102 } 83 }
103 } 84 }
104 return 0; 85 return 0;
diff --git a/arch/sparc/kernel/muldiv.c b/arch/sparc/kernel/muldiv.c
deleted file mode 100644
index f7db516b07d8..000000000000
--- a/arch/sparc/kernel/muldiv.c
+++ /dev/null
@@ -1,238 +0,0 @@
1/*
2 * muldiv.c: Hardware multiply/division illegal instruction trap
3 * for sun4c/sun4 (which do not have those instructions)
4 *
5 * Copyright (C) 1996 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
6 * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
7 *
8 * 2004-12-25 Krzysztof Helt (krzysztof.h1@wp.pl)
9 * - fixed registers constrains in inline assembly declarations
10 */
11
12#include <linux/kernel.h>
13#include <linux/sched.h>
14#include <linux/mm.h>
15#include <asm/ptrace.h>
16#include <asm/processor.h>
17#include <asm/uaccess.h>
18
19#include "kernel.h"
20
21/* #define DEBUG_MULDIV */
22
23static inline int has_imm13(int insn)
24{
25 return (insn & 0x2000);
26}
27
28static inline int is_foocc(int insn)
29{
30 return (insn & 0x800000);
31}
32
33static inline int sign_extend_imm13(int imm)
34{
35 return imm << 19 >> 19;
36}
37
38static inline void advance(struct pt_regs *regs)
39{
40 regs->pc = regs->npc;
41 regs->npc += 4;
42}
43
44static inline void maybe_flush_windows(unsigned int rs1, unsigned int rs2,
45 unsigned int rd)
46{
47 if(rs2 >= 16 || rs1 >= 16 || rd >= 16) {
48 /* Wheee... */
49 __asm__ __volatile__("save %sp, -0x40, %sp\n\t"
50 "save %sp, -0x40, %sp\n\t"
51 "save %sp, -0x40, %sp\n\t"
52 "save %sp, -0x40, %sp\n\t"
53 "save %sp, -0x40, %sp\n\t"
54 "save %sp, -0x40, %sp\n\t"
55 "save %sp, -0x40, %sp\n\t"
56 "restore; restore; restore; restore;\n\t"
57 "restore; restore; restore;\n\t");
58 }
59}
60
61#define fetch_reg(reg, regs) ({ \
62 struct reg_window32 __user *win; \
63 register unsigned long ret; \
64 \
65 if (!(reg)) ret = 0; \
66 else if ((reg) < 16) { \
67 ret = regs->u_regs[(reg)]; \
68 } else { \
69 /* Ho hum, the slightly complicated case. */ \
70 win = (struct reg_window32 __user *)regs->u_regs[UREG_FP];\
71 if (get_user (ret, &win->locals[(reg) - 16])) return -1;\
72 } \
73 ret; \
74})
75
76static inline int
77store_reg(unsigned int result, unsigned int reg, struct pt_regs *regs)
78{
79 struct reg_window32 __user *win;
80
81 if (!reg)
82 return 0;
83 if (reg < 16) {
84 regs->u_regs[reg] = result;
85 return 0;
86 } else {
87 /* need to use put_user() in this case: */
88 win = (struct reg_window32 __user *) regs->u_regs[UREG_FP];
89 return (put_user(result, &win->locals[reg - 16]));
90 }
91}
92
93/* Should return 0 if mul/div emulation succeeded and SIGILL should
94 * not be issued.
95 */
96int do_user_muldiv(struct pt_regs *regs, unsigned long pc)
97{
98 unsigned int insn;
99 int inst;
100 unsigned int rs1, rs2, rdv;
101
102 if (!pc)
103 return -1; /* This happens to often, I think */
104 if (get_user (insn, (unsigned int __user *)pc))
105 return -1;
106 if ((insn & 0xc1400000) != 0x80400000)
107 return -1;
108 inst = ((insn >> 19) & 0xf);
109 if ((inst & 0xe) != 10 && (inst & 0xe) != 14)
110 return -1;
111
112 /* Now we know we have to do something with umul, smul, udiv or sdiv */
113 rs1 = (insn >> 14) & 0x1f;
114 rs2 = insn & 0x1f;
115 rdv = (insn >> 25) & 0x1f;
116 if (has_imm13(insn)) {
117 maybe_flush_windows(rs1, 0, rdv);
118 rs2 = sign_extend_imm13(insn);
119 } else {
120 maybe_flush_windows(rs1, rs2, rdv);
121 rs2 = fetch_reg(rs2, regs);
122 }
123 rs1 = fetch_reg(rs1, regs);
124 switch (inst) {
125 case 10: /* umul */
126#ifdef DEBUG_MULDIV
127 printk ("unsigned muldiv: 0x%x * 0x%x = ", rs1, rs2);
128#endif
129 __asm__ __volatile__ ("\n\t"
130 "mov %0, %%o0\n\t"
131 "call .umul\n\t"
132 " mov %1, %%o1\n\t"
133 "mov %%o0, %0\n\t"
134 "mov %%o1, %1\n\t"
135 : "=r" (rs1), "=r" (rs2)
136 : "0" (rs1), "1" (rs2)
137 : "o0", "o1", "o2", "o3", "o4", "o5", "o7", "cc");
138#ifdef DEBUG_MULDIV
139 printk ("0x%x%08x\n", rs2, rs1);
140#endif
141 if (store_reg(rs1, rdv, regs))
142 return -1;
143 regs->y = rs2;
144 break;
145 case 11: /* smul */
146#ifdef DEBUG_MULDIV
147 printk ("signed muldiv: 0x%x * 0x%x = ", rs1, rs2);
148#endif
149 __asm__ __volatile__ ("\n\t"
150 "mov %0, %%o0\n\t"
151 "call .mul\n\t"
152 " mov %1, %%o1\n\t"
153 "mov %%o0, %0\n\t"
154 "mov %%o1, %1\n\t"
155 : "=r" (rs1), "=r" (rs2)
156 : "0" (rs1), "1" (rs2)
157 : "o0", "o1", "o2", "o3", "o4", "o5", "o7", "cc");
158#ifdef DEBUG_MULDIV
159 printk ("0x%x%08x\n", rs2, rs1);
160#endif
161 if (store_reg(rs1, rdv, regs))
162 return -1;
163 regs->y = rs2;
164 break;
165 case 14: /* udiv */
166#ifdef DEBUG_MULDIV
167 printk ("unsigned muldiv: 0x%x%08x / 0x%x = ", regs->y, rs1, rs2);
168#endif
169 if (!rs2) {
170#ifdef DEBUG_MULDIV
171 printk ("DIVISION BY ZERO\n");
172#endif
173 handle_hw_divzero (regs, pc, regs->npc, regs->psr);
174 return 0;
175 }
176 __asm__ __volatile__ ("\n\t"
177 "mov %2, %%o0\n\t"
178 "mov %0, %%o1\n\t"
179 "mov %%g0, %%o2\n\t"
180 "call __udivdi3\n\t"
181 " mov %1, %%o3\n\t"
182 "mov %%o1, %0\n\t"
183 "mov %%o0, %1\n\t"
184 : "=r" (rs1), "=r" (rs2)
185 : "r" (regs->y), "0" (rs1), "1" (rs2)
186 : "o0", "o1", "o2", "o3", "o4", "o5", "o7",
187 "g1", "g2", "g3", "cc");
188#ifdef DEBUG_MULDIV
189 printk ("0x%x\n", rs1);
190#endif
191 if (store_reg(rs1, rdv, regs))
192 return -1;
193 break;
194 case 15: /* sdiv */
195#ifdef DEBUG_MULDIV
196 printk ("signed muldiv: 0x%x%08x / 0x%x = ", regs->y, rs1, rs2);
197#endif
198 if (!rs2) {
199#ifdef DEBUG_MULDIV
200 printk ("DIVISION BY ZERO\n");
201#endif
202 handle_hw_divzero (regs, pc, regs->npc, regs->psr);
203 return 0;
204 }
205 __asm__ __volatile__ ("\n\t"
206 "mov %2, %%o0\n\t"
207 "mov %0, %%o1\n\t"
208 "mov %%g0, %%o2\n\t"
209 "call __divdi3\n\t"
210 " mov %1, %%o3\n\t"
211 "mov %%o1, %0\n\t"
212 "mov %%o0, %1\n\t"
213 : "=r" (rs1), "=r" (rs2)
214 : "r" (regs->y), "0" (rs1), "1" (rs2)
215 : "o0", "o1", "o2", "o3", "o4", "o5", "o7",
216 "g1", "g2", "g3", "cc");
217#ifdef DEBUG_MULDIV
218 printk ("0x%x\n", rs1);
219#endif
220 if (store_reg(rs1, rdv, regs))
221 return -1;
222 break;
223 }
224 if (is_foocc (insn)) {
225 regs->psr &= ~PSR_ICC;
226 if ((inst & 0xe) == 14) {
227 /* ?div */
228 if (rs2) regs->psr |= PSR_V;
229 }
230 if (!rs1) regs->psr |= PSR_Z;
231 if (((int)rs1) < 0) regs->psr |= PSR_N;
232#ifdef DEBUG_MULDIV
233 printk ("psr muldiv: %08x\n", regs->psr);
234#endif
235 }
236 advance(regs);
237 return 0;
238}
diff --git a/arch/sparc/kernel/of_device_32.c b/arch/sparc/kernel/of_device_32.c
index 4ee8ce0d5d8d..185aa96fa5be 100644
--- a/arch/sparc/kernel/of_device_32.c
+++ b/arch/sparc/kernel/of_device_32.c
@@ -356,7 +356,7 @@ static struct platform_device * __init scan_one_device(struct device_node *dp,
356 op->archdata.num_irqs = len / sizeof(struct linux_prom_irqs); 356 op->archdata.num_irqs = len / sizeof(struct linux_prom_irqs);
357 for (i = 0; i < op->archdata.num_irqs; i++) 357 for (i = 0; i < op->archdata.num_irqs; i++)
358 op->archdata.irqs[i] = 358 op->archdata.irqs[i] =
359 sparc_irq_config.build_device_irq(op, intr[i].pri); 359 sparc_config.build_device_irq(op, intr[i].pri);
360 } else { 360 } else {
361 const unsigned int *irq = 361 const unsigned int *irq =
362 of_get_property(dp, "interrupts", &len); 362 of_get_property(dp, "interrupts", &len);
@@ -365,7 +365,7 @@ static struct platform_device * __init scan_one_device(struct device_node *dp,
365 op->archdata.num_irqs = len / sizeof(unsigned int); 365 op->archdata.num_irqs = len / sizeof(unsigned int);
366 for (i = 0; i < op->archdata.num_irqs; i++) 366 for (i = 0; i < op->archdata.num_irqs; i++)
367 op->archdata.irqs[i] = 367 op->archdata.irqs[i] =
368 sparc_irq_config.build_device_irq(op, irq[i]); 368 sparc_config.build_device_irq(op, irq[i]);
369 } else { 369 } else {
370 op->archdata.num_irqs = 0; 370 op->archdata.num_irqs = 0;
371 } 371 }
diff --git a/arch/sparc/kernel/pcic.c b/arch/sparc/kernel/pcic.c
index fcc148effaac..ded3f6090c3f 100644
--- a/arch/sparc/kernel/pcic.c
+++ b/arch/sparc/kernel/pcic.c
@@ -703,31 +703,28 @@ static void pcic_clear_clock_irq(void)
703 pcic_timer_dummy = readl(pcic0.pcic_regs+PCI_SYS_LIMIT); 703 pcic_timer_dummy = readl(pcic0.pcic_regs+PCI_SYS_LIMIT);
704} 704}
705 705
706static irqreturn_t pcic_timer_handler (int irq, void *h) 706/* CPU frequency is 100 MHz, timer increments every 4 CPU clocks */
707#define USECS_PER_JIFFY (1000000 / HZ)
708#define TICK_TIMER_LIMIT ((100 * 1000000 / 4) / HZ)
709
710static unsigned int pcic_cycles_offset(void)
707{ 711{
708 pcic_clear_clock_irq(); 712 u32 value, count;
709 xtime_update(1);
710#ifndef CONFIG_SMP
711 update_process_times(user_mode(get_irq_regs()));
712#endif
713 return IRQ_HANDLED;
714}
715 713
716#define USECS_PER_JIFFY 10000 /* We have 100HZ "standard" timer for sparc */ 714 value = readl(pcic0.pcic_regs + PCI_SYS_COUNTER);
717#define TICK_TIMER_LIMIT ((100*1000000/4)/100) 715 count = value & ~PCI_SYS_COUNTER_OVERFLOW;
718 716
719u32 pci_gettimeoffset(void) 717 if (value & PCI_SYS_COUNTER_OVERFLOW)
720{ 718 count += TICK_TIMER_LIMIT;
721 /* 719 /*
722 * We divide all by 100 720 * We divide all by HZ
723 * to have microsecond resolution and to avoid overflow 721 * to have microsecond resolution and to avoid overflow
724 */ 722 */
725 unsigned long count = 723 count = ((count / HZ) * USECS_PER_JIFFY) / (TICK_TIMER_LIMIT / HZ);
726 readl(pcic0.pcic_regs+PCI_SYS_COUNTER) & ~PCI_SYS_COUNTER_OVERFLOW;
727 count = ((count/100)*USECS_PER_JIFFY) / (TICK_TIMER_LIMIT/100);
728 return count * 1000;
729}
730 724
725 /* Coordinate with the sparc_config.clock_rate setting */
726 return count * 2;
727}
731 728
732void __init pci_time_init(void) 729void __init pci_time_init(void)
733{ 730{
@@ -736,9 +733,16 @@ void __init pci_time_init(void)
736 int timer_irq, irq; 733 int timer_irq, irq;
737 int err; 734 int err;
738 735
739 do_arch_gettimeoffset = pci_gettimeoffset; 736#ifndef CONFIG_SMP
740 737 /*
741 btfixup(); 738 * The clock_rate is in SBUS dimension.
739 * We take into account this in pcic_cycles_offset()
740 */
741 sparc_config.clock_rate = SBUS_CLOCK_RATE / HZ;
742 sparc_config.features |= FEAT_L10_CLOCKEVENT;
743#endif
744 sparc_config.features |= FEAT_L10_CLOCKSOURCE;
745 sparc_config.get_cycles_offset = pcic_cycles_offset;
742 746
743 writel (TICK_TIMER_LIMIT, pcic->pcic_regs+PCI_SYS_LIMIT); 747 writel (TICK_TIMER_LIMIT, pcic->pcic_regs+PCI_SYS_LIMIT);
744 /* PROM should set appropriate irq */ 748 /* PROM should set appropriate irq */
@@ -747,7 +751,7 @@ void __init pci_time_init(void)
747 writel (PCI_COUNTER_IRQ_SET(timer_irq, 0), 751 writel (PCI_COUNTER_IRQ_SET(timer_irq, 0),
748 pcic->pcic_regs+PCI_COUNTER_IRQ); 752 pcic->pcic_regs+PCI_COUNTER_IRQ);
749 irq = pcic_build_device_irq(NULL, timer_irq); 753 irq = pcic_build_device_irq(NULL, timer_irq);
750 err = request_irq(irq, pcic_timer_handler, 754 err = request_irq(irq, timer_interrupt,
751 IRQF_TIMER, "timer", NULL); 755 IRQF_TIMER, "timer", NULL);
752 if (err) { 756 if (err) {
753 prom_printf("time_init: unable to attach IRQ%d\n", timer_irq); 757 prom_printf("time_init: unable to attach IRQ%d\n", timer_irq);
@@ -875,10 +879,9 @@ static void pcic_load_profile_irq(int cpu, unsigned int limit)
875 879
876void __init sun4m_pci_init_IRQ(void) 880void __init sun4m_pci_init_IRQ(void)
877{ 881{
878 sparc_irq_config.build_device_irq = pcic_build_device_irq; 882 sparc_config.build_device_irq = pcic_build_device_irq;
879 883 sparc_config.clear_clock_irq = pcic_clear_clock_irq;
880 BTFIXUPSET_CALL(clear_clock_irq, pcic_clear_clock_irq, BTFIXUPCALL_NORM); 884 sparc_config.load_profile_irq = pcic_load_profile_irq;
881 BTFIXUPSET_CALL(load_profile_irq, pcic_load_profile_irq, BTFIXUPCALL_NORM);
882} 885}
883 886
884int pcibios_assign_resource(struct pci_dev *pdev, int resource) 887int pcibios_assign_resource(struct pci_dev *pdev, int resource)
diff --git a/arch/sparc/kernel/process_32.c b/arch/sparc/kernel/process_32.c
index efa07542e85f..fe6787cc62fc 100644
--- a/arch/sparc/kernel/process_32.c
+++ b/arch/sparc/kernel/process_32.c
@@ -67,8 +67,6 @@ struct thread_info *current_set[NR_CPUS];
67 67
68#ifndef CONFIG_SMP 68#ifndef CONFIG_SMP
69 69
70#define SUN4C_FAULT_HIGH 100
71
72/* 70/*
73 * the idle loop on a Sparc... ;) 71 * the idle loop on a Sparc... ;)
74 */ 72 */
@@ -76,36 +74,6 @@ void cpu_idle(void)
76{ 74{
77 /* endless idle loop with no priority at all */ 75 /* endless idle loop with no priority at all */
78 for (;;) { 76 for (;;) {
79 if (ARCH_SUN4C) {
80 static int count = HZ;
81 static unsigned long last_jiffies;
82 static unsigned long last_faults;
83 static unsigned long fps;
84 unsigned long now;
85 unsigned long faults;
86
87 extern unsigned long sun4c_kernel_faults;
88 extern void sun4c_grow_kernel_ring(void);
89
90 local_irq_disable();
91 now = jiffies;
92 count -= (now - last_jiffies);
93 last_jiffies = now;
94 if (count < 0) {
95 count += HZ;
96 faults = sun4c_kernel_faults;
97 fps = (fps + (faults - last_faults)) >> 1;
98 last_faults = faults;
99#if 0
100 printk("kernel faults / second = %ld\n", fps);
101#endif
102 if (fps >= SUN4C_FAULT_HIGH) {
103 sun4c_grow_kernel_ring();
104 }
105 }
106 local_irq_enable();
107 }
108
109 if (pm_idle) { 77 if (pm_idle) {
110 while (!need_resched()) 78 while (!need_resched())
111 (*pm_idle)(); 79 (*pm_idle)();
@@ -114,7 +82,6 @@ void cpu_idle(void)
114 cpu_relax(); 82 cpu_relax();
115 } 83 }
116 schedule_preempt_disabled(); 84 schedule_preempt_disabled();
117 check_pgt_cache();
118 } 85 }
119} 86}
120 87
@@ -137,7 +104,6 @@ void cpu_idle(void)
137 cpu_relax(); 104 cpu_relax();
138 } 105 }
139 schedule_preempt_disabled(); 106 schedule_preempt_disabled();
140 check_pgt_cache();
141 } 107 }
142} 108}
143 109
@@ -179,88 +145,6 @@ void machine_power_off(void)
179 machine_halt(); 145 machine_halt();
180} 146}
181 147
182#if 0
183
184static DEFINE_SPINLOCK(sparc_backtrace_lock);
185
186void __show_backtrace(unsigned long fp)
187{
188 struct reg_window32 *rw;
189 unsigned long flags;
190 int cpu = smp_processor_id();
191
192 spin_lock_irqsave(&sparc_backtrace_lock, flags);
193
194 rw = (struct reg_window32 *)fp;
195 while(rw && (((unsigned long) rw) >= PAGE_OFFSET) &&
196 !(((unsigned long) rw) & 0x7)) {
197 printk("CPU[%d]: ARGS[%08lx,%08lx,%08lx,%08lx,%08lx,%08lx] "
198 "FP[%08lx] CALLER[%08lx]: ", cpu,
199 rw->ins[0], rw->ins[1], rw->ins[2], rw->ins[3],
200 rw->ins[4], rw->ins[5],
201 rw->ins[6],
202 rw->ins[7]);
203 printk("%pS\n", (void *) rw->ins[7]);
204 rw = (struct reg_window32 *) rw->ins[6];
205 }
206 spin_unlock_irqrestore(&sparc_backtrace_lock, flags);
207}
208
209#define __SAVE __asm__ __volatile__("save %sp, -0x40, %sp\n\t")
210#define __RESTORE __asm__ __volatile__("restore %g0, %g0, %g0\n\t")
211#define __GET_FP(fp) __asm__ __volatile__("mov %%i6, %0" : "=r" (fp))
212
213void show_backtrace(void)
214{
215 unsigned long fp;
216
217 __SAVE; __SAVE; __SAVE; __SAVE;
218 __SAVE; __SAVE; __SAVE; __SAVE;
219 __RESTORE; __RESTORE; __RESTORE; __RESTORE;
220 __RESTORE; __RESTORE; __RESTORE; __RESTORE;
221
222 __GET_FP(fp);
223
224 __show_backtrace(fp);
225}
226
227#ifdef CONFIG_SMP
228void smp_show_backtrace_all_cpus(void)
229{
230 xc0((smpfunc_t) show_backtrace);
231 show_backtrace();
232}
233#endif
234
235void show_stackframe(struct sparc_stackf *sf)
236{
237 unsigned long size;
238 unsigned long *stk;
239 int i;
240
241 printk("l0: %08lx l1: %08lx l2: %08lx l3: %08lx "
242 "l4: %08lx l5: %08lx l6: %08lx l7: %08lx\n",
243 sf->locals[0], sf->locals[1], sf->locals[2], sf->locals[3],
244 sf->locals[4], sf->locals[5], sf->locals[6], sf->locals[7]);
245 printk("i0: %08lx i1: %08lx i2: %08lx i3: %08lx "
246 "i4: %08lx i5: %08lx fp: %08lx i7: %08lx\n",
247 sf->ins[0], sf->ins[1], sf->ins[2], sf->ins[3],
248 sf->ins[4], sf->ins[5], (unsigned long)sf->fp, sf->callers_pc);
249 printk("sp: %08lx x0: %08lx x1: %08lx x2: %08lx "
250 "x3: %08lx x4: %08lx x5: %08lx xx: %08lx\n",
251 (unsigned long)sf->structptr, sf->xargs[0], sf->xargs[1],
252 sf->xargs[2], sf->xargs[3], sf->xargs[4], sf->xargs[5],
253 sf->xxargs[0]);
254 size = ((unsigned long)sf->fp) - ((unsigned long)sf);
255 size -= STACKFRAME_SZ;
256 stk = (unsigned long *)((unsigned long)sf + STACKFRAME_SZ);
257 i = 0;
258 do {
259 printk("s%d: %08lx\n", i++, *stk++);
260 } while ((size -= sizeof(unsigned long)));
261}
262#endif
263
264void show_regs(struct pt_regs *r) 148void show_regs(struct pt_regs *r)
265{ 149{
266 struct reg_window32 *rw = (struct reg_window32 *) r->u_regs[14]; 150 struct reg_window32 *rw = (struct reg_window32 *) r->u_regs[14];
diff --git a/arch/sparc/kernel/rtrap_32.S b/arch/sparc/kernel/rtrap_32.S
index 5f5f74c2c2ca..7abc24e2bf1a 100644
--- a/arch/sparc/kernel/rtrap_32.S
+++ b/arch/sparc/kernel/rtrap_32.S
@@ -128,13 +128,12 @@ rtrap_patch2: and %glob_tmp, 0xff, %glob_tmp
128 128
129 wr %glob_tmp, 0x0, %wim 129 wr %glob_tmp, 0x0, %wim
130 130
131 /* Here comes the architecture specific 131 /* Here comes the architecture specific
132 * branch to the user stack checking routine 132 * branch to the user stack checking routine
133 * for return from traps. 133 * for return from traps.
134 */ 134 */
135 .globl rtrap_mmu_patchme 135 b srmmu_rett_stackchk
136rtrap_mmu_patchme: b sun4c_rett_stackchk 136 andcc %fp, 0x7, %g0
137 andcc %fp, 0x7, %g0
138 137
139ret_trap_userwins_ok: 138ret_trap_userwins_ok:
140 LOAD_PT_PRIV(sp, t_psr, t_pc, t_npc) 139 LOAD_PT_PRIV(sp, t_psr, t_pc, t_npc)
@@ -225,69 +224,6 @@ ret_trap_user_stack_is_bolixed:
225 b signal_p 224 b signal_p
226 ld [%curptr + TI_FLAGS], %g2 225 ld [%curptr + TI_FLAGS], %g2
227 226
228sun4c_rett_stackchk:
229 be 1f
230 and %fp, 0xfff, %g1 ! delay slot
231
232 b ret_trap_user_stack_is_bolixed + 0x4
233 wr %t_wim, 0x0, %wim
234
235 /* See if we have to check the sanity of one page or two */
2361:
237 add %g1, 0x38, %g1
238 sra %fp, 29, %g2
239 add %g2, 0x1, %g2
240 andncc %g2, 0x1, %g0
241 be 1f
242 andncc %g1, 0xff8, %g0
243
244 /* %sp is in vma hole, yuck */
245 b ret_trap_user_stack_is_bolixed + 0x4
246 wr %t_wim, 0x0, %wim
247
2481:
249 be sun4c_rett_onepage /* Only one page to check */
250 lda [%fp] ASI_PTE, %g2
251
252sun4c_rett_twopages:
253 add %fp, 0x38, %g1
254 sra %g1, 29, %g2
255 add %g2, 0x1, %g2
256 andncc %g2, 0x1, %g0
257 be 1f
258 lda [%g1] ASI_PTE, %g2
259
260 /* Second page is in vma hole */
261 b ret_trap_user_stack_is_bolixed + 0x4
262 wr %t_wim, 0x0, %wim
263
2641:
265 srl %g2, 29, %g2
266 andcc %g2, 0x4, %g0
267 bne sun4c_rett_onepage
268 lda [%fp] ASI_PTE, %g2
269
270 /* Second page has bad perms */
271 b ret_trap_user_stack_is_bolixed + 0x4
272 wr %t_wim, 0x0, %wim
273
274sun4c_rett_onepage:
275 srl %g2, 29, %g2
276 andcc %g2, 0x4, %g0
277 bne,a 1f
278 restore %g0, %g0, %g0
279
280 /* A page had bad page permissions, losing... */
281 b ret_trap_user_stack_is_bolixed + 0x4
282 wr %t_wim, 0x0, %wim
283
284 /* Whee, things are ok, load the window and continue. */
2851:
286 LOAD_WINDOW(sp)
287
288 b ret_trap_userwins_ok
289 save %g0, %g0, %g0
290
291 .globl srmmu_rett_stackchk 227 .globl srmmu_rett_stackchk
292srmmu_rett_stackchk: 228srmmu_rett_stackchk:
293 bne ret_trap_user_stack_is_bolixed 229 bne ret_trap_user_stack_is_bolixed
diff --git a/arch/sparc/kernel/rtrap_64.S b/arch/sparc/kernel/rtrap_64.S
index 9171fc238def..afa2a9e3d0a0 100644
--- a/arch/sparc/kernel/rtrap_64.S
+++ b/arch/sparc/kernel/rtrap_64.S
@@ -73,18 +73,8 @@ rtrap_nmi: ldx [%sp + PTREGS_OFF + PT_V9_TSTATE], %l1
73 .globl rtrap_irq, rtrap, irqsz_patchme, rtrap_xcall 73 .globl rtrap_irq, rtrap, irqsz_patchme, rtrap_xcall
74rtrap_irq: 74rtrap_irq:
75rtrap: 75rtrap:
76#ifndef CONFIG_SMP
77 sethi %hi(__cpu_data), %l0
78 lduw [%l0 + %lo(__cpu_data)], %l1
79#else
80 sethi %hi(__cpu_data), %l0
81 or %l0, %lo(__cpu_data), %l0
82 lduw [%l0 + %g5], %l1
83#endif
84 cmp %l1, 0
85
86 /* mm/ultra.S:xcall_report_regs KNOWS about this load. */ 76 /* mm/ultra.S:xcall_report_regs KNOWS about this load. */
87 ldx [%sp + PTREGS_OFF + PT_V9_TSTATE], %l1 77 ldx [%sp + PTREGS_OFF + PT_V9_TSTATE], %l1
88rtrap_xcall: 78rtrap_xcall:
89 sethi %hi(0xf << 20), %l4 79 sethi %hi(0xf << 20), %l4
90 and %l1, %l4, %l4 80 and %l1, %l4, %l4
diff --git a/arch/sparc/kernel/setup_32.c b/arch/sparc/kernel/setup_32.c
index d444468b27f6..c052313f4dc5 100644
--- a/arch/sparc/kernel/setup_32.c
+++ b/arch/sparc/kernel/setup_32.c
@@ -42,7 +42,6 @@
42#include <asm/vaddrs.h> 42#include <asm/vaddrs.h>
43#include <asm/mbus.h> 43#include <asm/mbus.h>
44#include <asm/idprom.h> 44#include <asm/idprom.h>
45#include <asm/machines.h>
46#include <asm/cpudata.h> 45#include <asm/cpudata.h>
47#include <asm/setup.h> 46#include <asm/setup.h>
48#include <asm/cacheflush.h> 47#include <asm/cacheflush.h>
@@ -106,7 +105,6 @@ unsigned long cmdline_memory_size __initdata = 0;
106 105
107/* which CPU booted us (0xff = not set) */ 106/* which CPU booted us (0xff = not set) */
108unsigned char boot_cpu_id = 0xff; /* 0xff will make it into DATA section... */ 107unsigned char boot_cpu_id = 0xff; /* 0xff will make it into DATA section... */
109unsigned char boot_cpu_id4; /* boot_cpu_id << 2 */
110 108
111static void 109static void
112prom_console_write(struct console *con, const char *s, unsigned n) 110prom_console_write(struct console *con, const char *s, unsigned n)
@@ -182,13 +180,6 @@ static void __init boot_flags_init(char *commands)
182 } 180 }
183} 181}
184 182
185/* This routine will in the future do all the nasty prom stuff
186 * to probe for the mmu type and its parameters, etc. This will
187 * also be where SMP things happen.
188 */
189
190extern void sun4c_probe_vac(void);
191
192extern unsigned short root_flags; 183extern unsigned short root_flags;
193extern unsigned short root_dev; 184extern unsigned short root_dev;
194extern unsigned short ram_flags; 185extern unsigned short ram_flags;
@@ -200,6 +191,52 @@ extern int root_mountflags;
200 191
201char reboot_command[COMMAND_LINE_SIZE]; 192char reboot_command[COMMAND_LINE_SIZE];
202 193
194struct cpuid_patch_entry {
195 unsigned int addr;
196 unsigned int sun4d[3];
197 unsigned int leon[3];
198};
199extern struct cpuid_patch_entry __cpuid_patch, __cpuid_patch_end;
200
201static void __init per_cpu_patch(void)
202{
203 struct cpuid_patch_entry *p;
204
205 if (sparc_cpu_model == sun4m) {
206 /* Nothing to do, this is what the unpatched code
207 * targets.
208 */
209 return;
210 }
211
212 p = &__cpuid_patch;
213 while (p < &__cpuid_patch_end) {
214 unsigned long addr = p->addr;
215 unsigned int *insns;
216
217 switch (sparc_cpu_model) {
218 case sun4d:
219 insns = &p->sun4d[0];
220 break;
221
222 case sparc_leon:
223 insns = &p->leon[0];
224 break;
225 default:
226 prom_printf("Unknown cpu type, halting.\n");
227 prom_halt();
228 }
229 *(unsigned int *) (addr + 0) = insns[0];
230 flushi(addr + 0);
231 *(unsigned int *) (addr + 4) = insns[1];
232 flushi(addr + 4);
233 *(unsigned int *) (addr + 8) = insns[2];
234 flushi(addr + 8);
235
236 p++;
237 }
238}
239
203enum sparc_cpu sparc_cpu_model; 240enum sparc_cpu sparc_cpu_model;
204EXPORT_SYMBOL(sparc_cpu_model); 241EXPORT_SYMBOL(sparc_cpu_model);
205 242
@@ -225,10 +262,6 @@ void __init setup_arch(char **cmdline_p)
225 262
226 /* Set sparc_cpu_model */ 263 /* Set sparc_cpu_model */
227 sparc_cpu_model = sun_unknown; 264 sparc_cpu_model = sun_unknown;
228 if (!strcmp(&cputypval[0], "sun4 "))
229 sparc_cpu_model = sun4;
230 if (!strcmp(&cputypval[0], "sun4c"))
231 sparc_cpu_model = sun4c;
232 if (!strcmp(&cputypval[0], "sun4m")) 265 if (!strcmp(&cputypval[0], "sun4m"))
233 sparc_cpu_model = sun4m; 266 sparc_cpu_model = sun4m;
234 if (!strcmp(&cputypval[0], "sun4s")) 267 if (!strcmp(&cputypval[0], "sun4s"))
@@ -244,12 +277,6 @@ void __init setup_arch(char **cmdline_p)
244 277
245 printk("ARCH: "); 278 printk("ARCH: ");
246 switch(sparc_cpu_model) { 279 switch(sparc_cpu_model) {
247 case sun4:
248 printk("SUN4\n");
249 break;
250 case sun4c:
251 printk("SUN4C\n");
252 break;
253 case sun4m: 280 case sun4m:
254 printk("SUN4M\n"); 281 printk("SUN4M\n");
255 break; 282 break;
@@ -275,8 +302,6 @@ void __init setup_arch(char **cmdline_p)
275#endif 302#endif
276 303
277 idprom_init(); 304 idprom_init();
278 if (ARCH_SUN4C)
279 sun4c_probe_vac();
280 load_mmu(); 305 load_mmu();
281 306
282 phys_base = 0xffffffffUL; 307 phys_base = 0xffffffffUL;
@@ -313,6 +338,9 @@ void __init setup_arch(char **cmdline_p)
313 init_mm.context = (unsigned long) NO_CONTEXT; 338 init_mm.context = (unsigned long) NO_CONTEXT;
314 init_task.thread.kregs = &fake_swapper_regs; 339 init_task.thread.kregs = &fake_swapper_regs;
315 340
341 /* Run-time patch instructions to match the cpu model */
342 per_cpu_patch();
343
316 paging_init(); 344 paging_init();
317 345
318 smp_setup_cpu_possible_map(); 346 smp_setup_cpu_possible_map();
diff --git a/arch/sparc/kernel/signal_32.c b/arch/sparc/kernel/signal_32.c
index 1e750e415d7a..ac8e66b50f07 100644
--- a/arch/sparc/kernel/signal_32.c
+++ b/arch/sparc/kernel/signal_32.c
@@ -217,12 +217,9 @@ segv:
217/* Checks if the fp is valid */ 217/* Checks if the fp is valid */
218static inline int invalid_frame_pointer(void __user *fp, int fplen) 218static inline int invalid_frame_pointer(void __user *fp, int fplen)
219{ 219{
220 if ((((unsigned long) fp) & 7) || 220 if ((((unsigned long) fp) & 7) || !__access_ok((unsigned long)fp, fplen))
221 !__access_ok((unsigned long)fp, fplen) ||
222 ((sparc_cpu_model == sun4 || sparc_cpu_model == sun4c) &&
223 ((unsigned long) fp < 0xe0000000 && (unsigned long) fp >= 0x20000000)))
224 return 1; 221 return 1;
225 222
226 return 0; 223 return 0;
227} 224}
228 225
diff --git a/arch/sparc/kernel/smp_32.c b/arch/sparc/kernel/smp_32.c
index f671e7fd6ddc..57713758079e 100644
--- a/arch/sparc/kernel/smp_32.c
+++ b/arch/sparc/kernel/smp_32.c
@@ -40,6 +40,8 @@ volatile unsigned long cpu_callin_map[NR_CPUS] __cpuinitdata = {0,};
40 40
41cpumask_t smp_commenced_mask = CPU_MASK_NONE; 41cpumask_t smp_commenced_mask = CPU_MASK_NONE;
42 42
43const struct sparc32_ipi_ops *sparc32_ipi_ops;
44
43/* The only guaranteed locking primitive available on all Sparc 45/* The only guaranteed locking primitive available on all Sparc
44 * processors is 'ldstub [%reg + immediate], %dest_reg' which atomically 46 * processors is 'ldstub [%reg + immediate], %dest_reg' which atomically
45 * places the current byte at the effective address into dest_reg and 47 * places the current byte at the effective address into dest_reg and
@@ -85,14 +87,6 @@ void __init smp_cpus_done(unsigned int max_cpus)
85 (bogosum/(5000/HZ))%100); 87 (bogosum/(5000/HZ))%100);
86 88
87 switch(sparc_cpu_model) { 89 switch(sparc_cpu_model) {
88 case sun4:
89 printk("SUN4\n");
90 BUG();
91 break;
92 case sun4c:
93 printk("SUN4C\n");
94 BUG();
95 break;
96 case sun4m: 90 case sun4m:
97 smp4m_smp_done(); 91 smp4m_smp_done();
98 break; 92 break;
@@ -132,7 +126,7 @@ void smp_send_reschedule(int cpu)
132 * a single CPU. The trap handler needs only to do trap entry/return 126 * a single CPU. The trap handler needs only to do trap entry/return
133 * to call schedule. 127 * to call schedule.
134 */ 128 */
135 BTFIXUP_CALL(smp_ipi_resched)(cpu); 129 sparc32_ipi_ops->resched(cpu);
136} 130}
137 131
138void smp_send_stop(void) 132void smp_send_stop(void)
@@ -142,7 +136,7 @@ void smp_send_stop(void)
142void arch_send_call_function_single_ipi(int cpu) 136void arch_send_call_function_single_ipi(int cpu)
143{ 137{
144 /* trigger one IPI single call on one CPU */ 138 /* trigger one IPI single call on one CPU */
145 BTFIXUP_CALL(smp_ipi_single)(cpu); 139 sparc32_ipi_ops->single(cpu);
146} 140}
147 141
148void arch_send_call_function_ipi_mask(const struct cpumask *mask) 142void arch_send_call_function_ipi_mask(const struct cpumask *mask)
@@ -151,7 +145,7 @@ void arch_send_call_function_ipi_mask(const struct cpumask *mask)
151 145
152 /* trigger IPI mask call on each CPU */ 146 /* trigger IPI mask call on each CPU */
153 for_each_cpu(cpu, mask) 147 for_each_cpu(cpu, mask)
154 BTFIXUP_CALL(smp_ipi_mask_one)(cpu); 148 sparc32_ipi_ops->mask_one(cpu);
155} 149}
156 150
157void smp_resched_interrupt(void) 151void smp_resched_interrupt(void)
@@ -179,150 +173,9 @@ void smp_call_function_interrupt(void)
179 irq_exit(); 173 irq_exit();
180} 174}
181 175
182void smp_flush_cache_all(void)
183{
184 xc0((smpfunc_t) BTFIXUP_CALL(local_flush_cache_all));
185 local_flush_cache_all();
186}
187
188void smp_flush_tlb_all(void)
189{
190 xc0((smpfunc_t) BTFIXUP_CALL(local_flush_tlb_all));
191 local_flush_tlb_all();
192}
193
194void smp_flush_cache_mm(struct mm_struct *mm)
195{
196 if(mm->context != NO_CONTEXT) {
197 cpumask_t cpu_mask;
198 cpumask_copy(&cpu_mask, mm_cpumask(mm));
199 cpumask_clear_cpu(smp_processor_id(), &cpu_mask);
200 if (!cpumask_empty(&cpu_mask))
201 xc1((smpfunc_t) BTFIXUP_CALL(local_flush_cache_mm), (unsigned long) mm);
202 local_flush_cache_mm(mm);
203 }
204}
205
206void smp_flush_tlb_mm(struct mm_struct *mm)
207{
208 if(mm->context != NO_CONTEXT) {
209 cpumask_t cpu_mask;
210 cpumask_copy(&cpu_mask, mm_cpumask(mm));
211 cpumask_clear_cpu(smp_processor_id(), &cpu_mask);
212 if (!cpumask_empty(&cpu_mask)) {
213 xc1((smpfunc_t) BTFIXUP_CALL(local_flush_tlb_mm), (unsigned long) mm);
214 if(atomic_read(&mm->mm_users) == 1 && current->active_mm == mm)
215 cpumask_copy(mm_cpumask(mm),
216 cpumask_of(smp_processor_id()));
217 }
218 local_flush_tlb_mm(mm);
219 }
220}
221
222void smp_flush_cache_range(struct vm_area_struct *vma, unsigned long start,
223 unsigned long end)
224{
225 struct mm_struct *mm = vma->vm_mm;
226
227 if (mm->context != NO_CONTEXT) {
228 cpumask_t cpu_mask;
229 cpumask_copy(&cpu_mask, mm_cpumask(mm));
230 cpumask_clear_cpu(smp_processor_id(), &cpu_mask);
231 if (!cpumask_empty(&cpu_mask))
232 xc3((smpfunc_t) BTFIXUP_CALL(local_flush_cache_range), (unsigned long) vma, start, end);
233 local_flush_cache_range(vma, start, end);
234 }
235}
236
237void smp_flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
238 unsigned long end)
239{
240 struct mm_struct *mm = vma->vm_mm;
241
242 if (mm->context != NO_CONTEXT) {
243 cpumask_t cpu_mask;
244 cpumask_copy(&cpu_mask, mm_cpumask(mm));
245 cpumask_clear_cpu(smp_processor_id(), &cpu_mask);
246 if (!cpumask_empty(&cpu_mask))
247 xc3((smpfunc_t) BTFIXUP_CALL(local_flush_tlb_range), (unsigned long) vma, start, end);
248 local_flush_tlb_range(vma, start, end);
249 }
250}
251
252void smp_flush_cache_page(struct vm_area_struct *vma, unsigned long page)
253{
254 struct mm_struct *mm = vma->vm_mm;
255
256 if(mm->context != NO_CONTEXT) {
257 cpumask_t cpu_mask;
258 cpumask_copy(&cpu_mask, mm_cpumask(mm));
259 cpumask_clear_cpu(smp_processor_id(), &cpu_mask);
260 if (!cpumask_empty(&cpu_mask))
261 xc2((smpfunc_t) BTFIXUP_CALL(local_flush_cache_page), (unsigned long) vma, page);
262 local_flush_cache_page(vma, page);
263 }
264}
265
266void smp_flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
267{
268 struct mm_struct *mm = vma->vm_mm;
269
270 if(mm->context != NO_CONTEXT) {
271 cpumask_t cpu_mask;
272 cpumask_copy(&cpu_mask, mm_cpumask(mm));
273 cpumask_clear_cpu(smp_processor_id(), &cpu_mask);
274 if (!cpumask_empty(&cpu_mask))
275 xc2((smpfunc_t) BTFIXUP_CALL(local_flush_tlb_page), (unsigned long) vma, page);
276 local_flush_tlb_page(vma, page);
277 }
278}
279
280void smp_flush_page_to_ram(unsigned long page)
281{
282 /* Current theory is that those who call this are the one's
283 * who have just dirtied their cache with the pages contents
284 * in kernel space, therefore we only run this on local cpu.
285 *
286 * XXX This experiment failed, research further... -DaveM
287 */
288#if 1
289 xc1((smpfunc_t) BTFIXUP_CALL(local_flush_page_to_ram), page);
290#endif
291 local_flush_page_to_ram(page);
292}
293
294void smp_flush_sig_insns(struct mm_struct *mm, unsigned long insn_addr)
295{
296 cpumask_t cpu_mask;
297 cpumask_copy(&cpu_mask, mm_cpumask(mm));
298 cpumask_clear_cpu(smp_processor_id(), &cpu_mask);
299 if (!cpumask_empty(&cpu_mask))
300 xc2((smpfunc_t) BTFIXUP_CALL(local_flush_sig_insns), (unsigned long) mm, insn_addr);
301 local_flush_sig_insns(mm, insn_addr);
302}
303
304extern unsigned int lvl14_resolution;
305
306/* /proc/profile writes can call this, don't __init it please. */
307static DEFINE_SPINLOCK(prof_setup_lock);
308
309int setup_profiling_timer(unsigned int multiplier) 176int setup_profiling_timer(unsigned int multiplier)
310{ 177{
311 int i; 178 return -EINVAL;
312 unsigned long flags;
313
314 /* Prevent level14 ticker IRQ flooding. */
315 if((!multiplier) || (lvl14_resolution / multiplier) < 500)
316 return -EINVAL;
317
318 spin_lock_irqsave(&prof_setup_lock, flags);
319 for_each_possible_cpu(i) {
320 load_profile_irq(i, lvl14_resolution / multiplier);
321 prof_multiplier(i) = multiplier;
322 }
323 spin_unlock_irqrestore(&prof_setup_lock, flags);
324
325 return 0;
326} 179}
327 180
328void __init smp_prepare_cpus(unsigned int max_cpus) 181void __init smp_prepare_cpus(unsigned int max_cpus)
@@ -345,14 +198,6 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
345 smp_store_cpu_info(boot_cpu_id); 198 smp_store_cpu_info(boot_cpu_id);
346 199
347 switch(sparc_cpu_model) { 200 switch(sparc_cpu_model) {
348 case sun4:
349 printk("SUN4\n");
350 BUG();
351 break;
352 case sun4c:
353 printk("SUN4C\n");
354 BUG();
355 break;
356 case sun4m: 201 case sun4m:
357 smp4m_boot_cpus(); 202 smp4m_boot_cpus();
358 break; 203 break;
@@ -418,14 +263,6 @@ int __cpuinit __cpu_up(unsigned int cpu)
418 int ret=0; 263 int ret=0;
419 264
420 switch(sparc_cpu_model) { 265 switch(sparc_cpu_model) {
421 case sun4:
422 printk("SUN4\n");
423 BUG();
424 break;
425 case sun4c:
426 printk("SUN4C\n");
427 BUG();
428 break;
429 case sun4m: 266 case sun4m:
430 ret = smp4m_boot_one_cpu(cpu); 267 ret = smp4m_boot_one_cpu(cpu);
431 break; 268 break;
diff --git a/arch/sparc/kernel/sparc_ksyms_32.c b/arch/sparc/kernel/sparc_ksyms_32.c
index baeab8720237..e521c54560f9 100644
--- a/arch/sparc/kernel/sparc_ksyms_32.c
+++ b/arch/sparc/kernel/sparc_ksyms_32.c
@@ -28,19 +28,5 @@ EXPORT_SYMBOL(__ndelay);
28EXPORT_SYMBOL(__ret_efault); 28EXPORT_SYMBOL(__ret_efault);
29EXPORT_SYMBOL(empty_zero_page); 29EXPORT_SYMBOL(empty_zero_page);
30 30
31/* Defined using magic */
32#ifndef CONFIG_SMP
33EXPORT_SYMBOL(BTFIXUP_CALL(___xchg32));
34#else
35EXPORT_SYMBOL(BTFIXUP_CALL(__hard_smp_processor_id));
36#endif
37EXPORT_SYMBOL(BTFIXUP_CALL(mmu_unlockarea));
38EXPORT_SYMBOL(BTFIXUP_CALL(mmu_lockarea));
39EXPORT_SYMBOL(BTFIXUP_CALL(mmu_get_scsi_sgl));
40EXPORT_SYMBOL(BTFIXUP_CALL(mmu_get_scsi_one));
41EXPORT_SYMBOL(BTFIXUP_CALL(mmu_release_scsi_sgl));
42EXPORT_SYMBOL(BTFIXUP_CALL(mmu_release_scsi_one));
43EXPORT_SYMBOL(BTFIXUP_CALL(pgprot_noncached));
44
45/* Exporting a symbol from /init/main.c */ 31/* Exporting a symbol from /init/main.c */
46EXPORT_SYMBOL(saved_command_line); 32EXPORT_SYMBOL(saved_command_line);
diff --git a/arch/sparc/kernel/sun4c_irq.c b/arch/sparc/kernel/sun4c_irq.c
deleted file mode 100644
index f6bf25a2ff80..000000000000
--- a/arch/sparc/kernel/sun4c_irq.c
+++ /dev/null
@@ -1,264 +0,0 @@
1/*
2 * sun4c irq support
3 *
4 * djhr: Hacked out of irq.c into a CPU dependent version.
5 *
6 * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
7 * Copyright (C) 1995 Miguel de Icaza (miguel@nuclecu.unam.mx)
8 * Copyright (C) 1995 Pete A. Zaitcev (zaitcev@yahoo.com)
9 * Copyright (C) 1996 Dave Redman (djhr@tadpole.co.uk)
10 */
11
12#include <linux/init.h>
13
14#include <asm/oplib.h>
15#include <asm/timer.h>
16#include <asm/irq.h>
17#include <asm/io.h>
18
19#include "irq.h"
20
21/* Sun4c interrupts are typically laid out as follows:
22 *
23 * 1 - Software interrupt, SBUS level 1
24 * 2 - SBUS level 2
25 * 3 - ESP SCSI, SBUS level 3
26 * 4 - Software interrupt
27 * 5 - Lance ethernet, SBUS level 4
28 * 6 - Software interrupt
29 * 7 - Graphics card, SBUS level 5
30 * 8 - SBUS level 6
31 * 9 - SBUS level 7
32 * 10 - Counter timer
33 * 11 - Floppy
34 * 12 - Zilog uart
35 * 13 - CS4231 audio
36 * 14 - Profiling timer
37 * 15 - NMI
38 *
39 * The interrupt enable bits in the interrupt mask register are
40 * really only used to enable/disable the timer interrupts, and
41 * for signalling software interrupts. There is also a master
42 * interrupt enable bit in this register.
43 *
44 * Interrupts are enabled by setting the SUN4C_INT_* bits, they
45 * are disabled by clearing those bits.
46 */
47
48/*
49 * Bit field defines for the interrupt registers on various
50 * Sparc machines.
51 */
52
53/* The sun4c interrupt register. */
54#define SUN4C_INT_ENABLE 0x01 /* Allow interrupts. */
55#define SUN4C_INT_E14 0x80 /* Enable level 14 IRQ. */
56#define SUN4C_INT_E10 0x20 /* Enable level 10 IRQ. */
57#define SUN4C_INT_E8 0x10 /* Enable level 8 IRQ. */
58#define SUN4C_INT_E6 0x08 /* Enable level 6 IRQ. */
59#define SUN4C_INT_E4 0x04 /* Enable level 4 IRQ. */
60#define SUN4C_INT_E1 0x02 /* Enable level 1 IRQ. */
61
62/*
63 * Pointer to the interrupt enable byte
64 * Used by entry.S
65 */
66unsigned char __iomem *interrupt_enable;
67
68static void sun4c_mask_irq(struct irq_data *data)
69{
70 unsigned long mask = (unsigned long)data->chip_data;
71
72 if (mask) {
73 unsigned long flags;
74
75 local_irq_save(flags);
76 mask = sbus_readb(interrupt_enable) & ~mask;
77 sbus_writeb(mask, interrupt_enable);
78 local_irq_restore(flags);
79 }
80}
81
82static void sun4c_unmask_irq(struct irq_data *data)
83{
84 unsigned long mask = (unsigned long)data->chip_data;
85
86 if (mask) {
87 unsigned long flags;
88
89 local_irq_save(flags);
90 mask = sbus_readb(interrupt_enable) | mask;
91 sbus_writeb(mask, interrupt_enable);
92 local_irq_restore(flags);
93 }
94}
95
96static unsigned int sun4c_startup_irq(struct irq_data *data)
97{
98 irq_link(data->irq);
99 sun4c_unmask_irq(data);
100
101 return 0;
102}
103
104static void sun4c_shutdown_irq(struct irq_data *data)
105{
106 sun4c_mask_irq(data);
107 irq_unlink(data->irq);
108}
109
110static struct irq_chip sun4c_irq = {
111 .name = "sun4c",
112 .irq_startup = sun4c_startup_irq,
113 .irq_shutdown = sun4c_shutdown_irq,
114 .irq_mask = sun4c_mask_irq,
115 .irq_unmask = sun4c_unmask_irq,
116};
117
118static unsigned int sun4c_build_device_irq(struct platform_device *op,
119 unsigned int real_irq)
120{
121 unsigned int irq;
122
123 if (real_irq >= 16) {
124 prom_printf("Bogus sun4c IRQ %u\n", real_irq);
125 prom_halt();
126 }
127
128 irq = irq_alloc(real_irq, real_irq);
129 if (irq) {
130 unsigned long mask = 0UL;
131
132 switch (real_irq) {
133 case 1:
134 mask = SUN4C_INT_E1;
135 break;
136 case 8:
137 mask = SUN4C_INT_E8;
138 break;
139 case 10:
140 mask = SUN4C_INT_E10;
141 break;
142 case 14:
143 mask = SUN4C_INT_E14;
144 break;
145 default:
146 /* All the rest are either always enabled,
147 * or are for signalling software interrupts.
148 */
149 break;
150 }
151 irq_set_chip_and_handler_name(irq, &sun4c_irq,
152 handle_level_irq, "level");
153 irq_set_chip_data(irq, (void *)mask);
154 }
155 return irq;
156}
157
158struct sun4c_timer_info {
159 u32 l10_count;
160 u32 l10_limit;
161 u32 l14_count;
162 u32 l14_limit;
163};
164
165static struct sun4c_timer_info __iomem *sun4c_timers;
166
167static void sun4c_clear_clock_irq(void)
168{
169 sbus_readl(&sun4c_timers->l10_limit);
170}
171
172static void sun4c_load_profile_irq(int cpu, unsigned int limit)
173{
174 /* Errm.. not sure how to do this.. */
175}
176
177static void __init sun4c_init_timers(irq_handler_t counter_fn)
178{
179 const struct linux_prom_irqs *prom_irqs;
180 struct device_node *dp;
181 unsigned int irq;
182 const u32 *addr;
183 int err;
184
185 dp = of_find_node_by_name(NULL, "counter-timer");
186 if (!dp) {
187 prom_printf("sun4c_init_timers: Unable to find counter-timer\n");
188 prom_halt();
189 }
190
191 addr = of_get_property(dp, "address", NULL);
192 if (!addr) {
193 prom_printf("sun4c_init_timers: No address property\n");
194 prom_halt();
195 }
196
197 sun4c_timers = (void __iomem *) (unsigned long) addr[0];
198
199 prom_irqs = of_get_property(dp, "intr", NULL);
200 of_node_put(dp);
201 if (!prom_irqs) {
202 prom_printf("sun4c_init_timers: No intr property\n");
203 prom_halt();
204 }
205
206 /* Have the level 10 timer tick at 100HZ. We don't touch the
207 * level 14 timer limit since we are letting the prom handle
208 * them until we have a real console driver so L1-A works.
209 */
210 sbus_writel((((1000000/HZ) + 1) << 10), &sun4c_timers->l10_limit);
211
212 master_l10_counter = &sun4c_timers->l10_count;
213
214 irq = sun4c_build_device_irq(NULL, prom_irqs[0].pri);
215 err = request_irq(irq, counter_fn, IRQF_TIMER, "timer", NULL);
216 if (err) {
217 prom_printf("sun4c_init_timers: request_irq() fails with %d\n", err);
218 prom_halt();
219 }
220
221 /* disable timer interrupt */
222 sun4c_mask_irq(irq_get_irq_data(irq));
223}
224
225#ifdef CONFIG_SMP
226static void sun4c_nop(void)
227{
228}
229#endif
230
231void __init sun4c_init_IRQ(void)
232{
233 struct device_node *dp;
234 const u32 *addr;
235
236 dp = of_find_node_by_name(NULL, "interrupt-enable");
237 if (!dp) {
238 prom_printf("sun4c_init_IRQ: Unable to find interrupt-enable\n");
239 prom_halt();
240 }
241
242 addr = of_get_property(dp, "address", NULL);
243 of_node_put(dp);
244 if (!addr) {
245 prom_printf("sun4c_init_IRQ: No address property\n");
246 prom_halt();
247 }
248
249 interrupt_enable = (void __iomem *) (unsigned long) addr[0];
250
251 BTFIXUPSET_CALL(clear_clock_irq, sun4c_clear_clock_irq, BTFIXUPCALL_NORM);
252 BTFIXUPSET_CALL(load_profile_irq, sun4c_load_profile_irq, BTFIXUPCALL_NOP);
253
254 sparc_irq_config.init_timers = sun4c_init_timers;
255 sparc_irq_config.build_device_irq = sun4c_build_device_irq;
256
257#ifdef CONFIG_SMP
258 BTFIXUPSET_CALL(set_cpu_int, sun4c_nop, BTFIXUPCALL_NOP);
259 BTFIXUPSET_CALL(clear_cpu_int, sun4c_nop, BTFIXUPCALL_NOP);
260 BTFIXUPSET_CALL(set_irq_udt, sun4c_nop, BTFIXUPCALL_NOP);
261#endif
262 sbus_writeb(SUN4C_INT_ENABLE, interrupt_enable);
263 /* Cannot enable interrupts until OBP ticker is disabled. */
264}
diff --git a/arch/sparc/kernel/sun4d_irq.c b/arch/sparc/kernel/sun4d_irq.c
index 1d13c5bda0b1..e490ac9327c7 100644
--- a/arch/sparc/kernel/sun4d_irq.c
+++ b/arch/sparc/kernel/sun4d_irq.c
@@ -15,6 +15,7 @@
15#include <asm/sbi.h> 15#include <asm/sbi.h>
16#include <asm/cacheflush.h> 16#include <asm/cacheflush.h>
17#include <asm/setup.h> 17#include <asm/setup.h>
18#include <asm/oplib.h>
18 19
19#include "kernel.h" 20#include "kernel.h"
20#include "irq.h" 21#include "irq.h"
@@ -243,19 +244,6 @@ struct irq_chip sun4d_irq = {
243}; 244};
244 245
245#ifdef CONFIG_SMP 246#ifdef CONFIG_SMP
246static void sun4d_set_cpu_int(int cpu, int level)
247{
248 sun4d_send_ipi(cpu, level);
249}
250
251static void sun4d_clear_ipi(int cpu, int level)
252{
253}
254
255static void sun4d_set_udt(int cpu)
256{
257}
258
259/* Setup IRQ distribution scheme. */ 247/* Setup IRQ distribution scheme. */
260void __init sun4d_distribute_irqs(void) 248void __init sun4d_distribute_irqs(void)
261{ 249{
@@ -282,7 +270,8 @@ static void sun4d_clear_clock_irq(void)
282 270
283static void sun4d_load_profile_irq(int cpu, unsigned int limit) 271static void sun4d_load_profile_irq(int cpu, unsigned int limit)
284{ 272{
285 bw_set_prof_limit(cpu, limit); 273 unsigned int value = limit ? timer_value(limit) : 0;
274 bw_set_prof_limit(cpu, value);
286} 275}
287 276
288static void __init sun4d_load_profile_irqs(void) 277static void __init sun4d_load_profile_irqs(void)
@@ -418,12 +407,12 @@ static void __init sun4d_fixup_trap_table(void)
418 trap_table->inst_two = lvl14_save[1]; 407 trap_table->inst_two = lvl14_save[1];
419 trap_table->inst_three = lvl14_save[2]; 408 trap_table->inst_three = lvl14_save[2];
420 trap_table->inst_four = lvl14_save[3]; 409 trap_table->inst_four = lvl14_save[3];
421 local_flush_cache_all(); 410 local_ops->cache_all();
422 local_irq_restore(flags); 411 local_irq_restore(flags);
423#endif 412#endif
424} 413}
425 414
426static void __init sun4d_init_timers(irq_handler_t counter_fn) 415static void __init sun4d_init_timers(void)
427{ 416{
428 struct device_node *dp; 417 struct device_node *dp;
429 struct resource res; 418 struct resource res;
@@ -466,12 +455,20 @@ static void __init sun4d_init_timers(irq_handler_t counter_fn)
466 prom_halt(); 455 prom_halt();
467 } 456 }
468 457
469 sbus_writel((((1000000/HZ) + 1) << 10), &sun4d_timers->l10_timer_limit); 458#ifdef CONFIG_SMP
459 sparc_config.cs_period = SBUS_CLOCK_RATE * 2; /* 2 seconds */
460#else
461 sparc_config.cs_period = SBUS_CLOCK_RATE / HZ; /* 1/HZ sec */
462 sparc_config.features |= FEAT_L10_CLOCKEVENT;
463#endif
464 sparc_config.features |= FEAT_L10_CLOCKSOURCE;
465 sbus_writel(timer_value(sparc_config.cs_period),
466 &sun4d_timers->l10_timer_limit);
470 467
471 master_l10_counter = &sun4d_timers->l10_cur_count; 468 master_l10_counter = &sun4d_timers->l10_cur_count;
472 469
473 irq = sun4d_build_timer_irq(board, SUN4D_TIMER_IRQ); 470 irq = sun4d_build_timer_irq(board, SUN4D_TIMER_IRQ);
474 err = request_irq(irq, counter_fn, IRQF_TIMER, "timer", NULL); 471 err = request_irq(irq, timer_interrupt, IRQF_TIMER, "timer", NULL);
475 if (err) { 472 if (err) {
476 prom_printf("sun4d_init_timers: request_irq() failed with %d\n", 473 prom_printf("sun4d_init_timers: request_irq() failed with %d\n",
477 err); 474 err);
@@ -509,16 +506,11 @@ void __init sun4d_init_IRQ(void)
509{ 506{
510 local_irq_disable(); 507 local_irq_disable();
511 508
512 BTFIXUPSET_CALL(clear_clock_irq, sun4d_clear_clock_irq, BTFIXUPCALL_NORM); 509 sparc_config.init_timers = sun4d_init_timers;
513 BTFIXUPSET_CALL(load_profile_irq, sun4d_load_profile_irq, BTFIXUPCALL_NORM); 510 sparc_config.build_device_irq = sun4d_build_device_irq;
511 sparc_config.clock_rate = SBUS_CLOCK_RATE;
512 sparc_config.clear_clock_irq = sun4d_clear_clock_irq;
513 sparc_config.load_profile_irq = sun4d_load_profile_irq;
514 514
515 sparc_irq_config.init_timers = sun4d_init_timers;
516 sparc_irq_config.build_device_irq = sun4d_build_device_irq;
517
518#ifdef CONFIG_SMP
519 BTFIXUPSET_CALL(set_cpu_int, sun4d_set_cpu_int, BTFIXUPCALL_NORM);
520 BTFIXUPSET_CALL(clear_cpu_int, sun4d_clear_ipi, BTFIXUPCALL_NOP);
521 BTFIXUPSET_CALL(set_irq_udt, sun4d_set_udt, BTFIXUPCALL_NOP);
522#endif
523 /* Cannot enable interrupts until OBP ticker is disabled. */ 515 /* Cannot enable interrupts until OBP ticker is disabled. */
524} 516}
diff --git a/arch/sparc/kernel/sun4d_smp.c b/arch/sparc/kernel/sun4d_smp.c
index 540b2fec09f0..f9a1a33cbb2c 100644
--- a/arch/sparc/kernel/sun4d_smp.c
+++ b/arch/sparc/kernel/sun4d_smp.c
@@ -6,16 +6,20 @@
6 * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) 6 * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
7 */ 7 */
8 8
9#include <linux/clockchips.h>
9#include <linux/interrupt.h> 10#include <linux/interrupt.h>
10#include <linux/profile.h> 11#include <linux/profile.h>
11#include <linux/delay.h> 12#include <linux/delay.h>
13#include <linux/sched.h>
12#include <linux/cpu.h> 14#include <linux/cpu.h>
13 15
16#include <asm/cacheflush.h>
17#include <asm/switch_to.h>
18#include <asm/tlbflush.h>
19#include <asm/timer.h>
20#include <asm/oplib.h>
14#include <asm/sbi.h> 21#include <asm/sbi.h>
15#include <asm/mmu.h> 22#include <asm/mmu.h>
16#include <asm/tlbflush.h>
17#include <asm/switch_to.h>
18#include <asm/cacheflush.h>
19 23
20#include "kernel.h" 24#include "kernel.h"
21#include "irq.h" 25#include "irq.h"
@@ -34,7 +38,6 @@ static inline unsigned long sun4d_swap(volatile unsigned long *ptr, unsigned lon
34} 38}
35 39
36static void smp4d_ipi_init(void); 40static void smp4d_ipi_init(void);
37static void smp_setup_percpu_timer(void);
38 41
39static unsigned char cpu_leds[32]; 42static unsigned char cpu_leds[32];
40 43
@@ -49,7 +52,7 @@ static inline void show_leds(int cpuid)
49 52
50void __cpuinit smp4d_callin(void) 53void __cpuinit smp4d_callin(void)
51{ 54{
52 int cpuid = hard_smp4d_processor_id(); 55 int cpuid = hard_smp_processor_id();
53 unsigned long flags; 56 unsigned long flags;
54 57
55 /* Show we are alive */ 58 /* Show we are alive */
@@ -59,8 +62,8 @@ void __cpuinit smp4d_callin(void)
59 /* Enable level15 interrupt, disable level14 interrupt for now */ 62 /* Enable level15 interrupt, disable level14 interrupt for now */
60 cc_set_imsk((cc_get_imsk() & ~0x8000) | 0x4000); 63 cc_set_imsk((cc_get_imsk() & ~0x8000) | 0x4000);
61 64
62 local_flush_cache_all(); 65 local_ops->cache_all();
63 local_flush_tlb_all(); 66 local_ops->tlb_all();
64 67
65 notify_cpu_starting(cpuid); 68 notify_cpu_starting(cpuid);
66 /* 69 /*
@@ -70,17 +73,17 @@ void __cpuinit smp4d_callin(void)
70 * to call the scheduler code. 73 * to call the scheduler code.
71 */ 74 */
72 /* Get our local ticker going. */ 75 /* Get our local ticker going. */
73 smp_setup_percpu_timer(); 76 register_percpu_ce(cpuid);
74 77
75 calibrate_delay(); 78 calibrate_delay();
76 smp_store_cpu_info(cpuid); 79 smp_store_cpu_info(cpuid);
77 local_flush_cache_all(); 80 local_ops->cache_all();
78 local_flush_tlb_all(); 81 local_ops->tlb_all();
79 82
80 /* Allow master to continue. */ 83 /* Allow master to continue. */
81 sun4d_swap((unsigned long *)&cpu_callin_map[cpuid], 1); 84 sun4d_swap((unsigned long *)&cpu_callin_map[cpuid], 1);
82 local_flush_cache_all(); 85 local_ops->cache_all();
83 local_flush_tlb_all(); 86 local_ops->tlb_all();
84 87
85 while ((unsigned long)current_set[cpuid] < PAGE_OFFSET) 88 while ((unsigned long)current_set[cpuid] < PAGE_OFFSET)
86 barrier(); 89 barrier();
@@ -100,8 +103,8 @@ void __cpuinit smp4d_callin(void)
100 atomic_inc(&init_mm.mm_count); 103 atomic_inc(&init_mm.mm_count);
101 current->active_mm = &init_mm; 104 current->active_mm = &init_mm;
102 105
103 local_flush_cache_all(); 106 local_ops->cache_all();
104 local_flush_tlb_all(); 107 local_ops->tlb_all();
105 108
106 local_irq_enable(); /* We don't allow PIL 14 yet */ 109 local_irq_enable(); /* We don't allow PIL 14 yet */
107 110
@@ -123,8 +126,7 @@ void __init smp4d_boot_cpus(void)
123 smp4d_ipi_init(); 126 smp4d_ipi_init();
124 if (boot_cpu_id) 127 if (boot_cpu_id)
125 current_set[0] = NULL; 128 current_set[0] = NULL;
126 smp_setup_percpu_timer(); 129 local_ops->cache_all();
127 local_flush_cache_all();
128} 130}
129 131
130int __cpuinit smp4d_boot_one_cpu(int i) 132int __cpuinit smp4d_boot_one_cpu(int i)
@@ -150,7 +152,7 @@ int __cpuinit smp4d_boot_one_cpu(int i)
150 152
151 /* whirrr, whirrr, whirrrrrrrrr... */ 153 /* whirrr, whirrr, whirrrrrrrrr... */
152 printk(KERN_INFO "Starting CPU %d at %p\n", i, entry); 154 printk(KERN_INFO "Starting CPU %d at %p\n", i, entry);
153 local_flush_cache_all(); 155 local_ops->cache_all();
154 prom_startcpu(cpu_node, 156 prom_startcpu(cpu_node,
155 &smp_penguin_ctable, 0, (char *)entry); 157 &smp_penguin_ctable, 0, (char *)entry);
156 158
@@ -168,7 +170,7 @@ int __cpuinit smp4d_boot_one_cpu(int i)
168 return -ENODEV; 170 return -ENODEV;
169 171
170 } 172 }
171 local_flush_cache_all(); 173 local_ops->cache_all();
172 return 0; 174 return 0;
173} 175}
174 176
@@ -185,7 +187,7 @@ void __init smp4d_smp_done(void)
185 prev = &cpu_data(i).next; 187 prev = &cpu_data(i).next;
186 } 188 }
187 *prev = first; 189 *prev = first;
188 local_flush_cache_all(); 190 local_ops->cache_all();
189 191
190 /* Ok, they are spinning and ready to go. */ 192 /* Ok, they are spinning and ready to go. */
191 smp_processors_ready = 1; 193 smp_processors_ready = 1;
@@ -233,7 +235,20 @@ void sun4d_ipi_interrupt(void)
233 } 235 }
234} 236}
235 237
236static void smp4d_ipi_single(int cpu) 238/* +-------+-------------+-----------+------------------------------------+
239 * | bcast | devid | sid | levels mask |
240 * +-------+-------------+-----------+------------------------------------+
241 * 31 30 23 22 15 14 0
242 */
243#define IGEN_MESSAGE(bcast, devid, sid, levels) \
244 (((bcast) << 31) | ((devid) << 23) | ((sid) << 15) | (levels))
245
246static void sun4d_send_ipi(int cpu, int level)
247{
248 cc_set_igen(IGEN_MESSAGE(0, cpu << 3, 6 + ((level >> 1) & 7), 1 << (level - 1)));
249}
250
251static void sun4d_ipi_single(int cpu)
237{ 252{
238 struct sun4d_ipi_work *work = &per_cpu(sun4d_ipi_work, cpu); 253 struct sun4d_ipi_work *work = &per_cpu(sun4d_ipi_work, cpu);
239 254
@@ -244,7 +259,7 @@ static void smp4d_ipi_single(int cpu)
244 sun4d_send_ipi(cpu, SUN4D_IPI_IRQ); 259 sun4d_send_ipi(cpu, SUN4D_IPI_IRQ);
245} 260}
246 261
247static void smp4d_ipi_mask_one(int cpu) 262static void sun4d_ipi_mask_one(int cpu)
248{ 263{
249 struct sun4d_ipi_work *work = &per_cpu(sun4d_ipi_work, cpu); 264 struct sun4d_ipi_work *work = &per_cpu(sun4d_ipi_work, cpu);
250 265
@@ -255,7 +270,7 @@ static void smp4d_ipi_mask_one(int cpu)
255 sun4d_send_ipi(cpu, SUN4D_IPI_IRQ); 270 sun4d_send_ipi(cpu, SUN4D_IPI_IRQ);
256} 271}
257 272
258static void smp4d_ipi_resched(int cpu) 273static void sun4d_ipi_resched(int cpu)
259{ 274{
260 struct sun4d_ipi_work *work = &per_cpu(sun4d_ipi_work, cpu); 275 struct sun4d_ipi_work *work = &per_cpu(sun4d_ipi_work, cpu);
261 276
@@ -280,7 +295,7 @@ static struct smp_funcall {
280static DEFINE_SPINLOCK(cross_call_lock); 295static DEFINE_SPINLOCK(cross_call_lock);
281 296
282/* Cross calls must be serialized, at least currently. */ 297/* Cross calls must be serialized, at least currently. */
283static void smp4d_cross_call(smpfunc_t func, cpumask_t mask, unsigned long arg1, 298static void sun4d_cross_call(smpfunc_t func, cpumask_t mask, unsigned long arg1,
284 unsigned long arg2, unsigned long arg3, 299 unsigned long arg2, unsigned long arg3,
285 unsigned long arg4) 300 unsigned long arg4)
286{ 301{
@@ -352,7 +367,7 @@ static void smp4d_cross_call(smpfunc_t func, cpumask_t mask, unsigned long arg1,
352/* Running cross calls. */ 367/* Running cross calls. */
353void smp4d_cross_call_irq(void) 368void smp4d_cross_call_irq(void)
354{ 369{
355 int i = hard_smp4d_processor_id(); 370 int i = hard_smp_processor_id();
356 371
357 ccall_info.processors_in[i] = 1; 372 ccall_info.processors_in[i] = 1;
358 ccall_info.func(ccall_info.arg1, ccall_info.arg2, ccall_info.arg3, 373 ccall_info.func(ccall_info.arg1, ccall_info.arg2, ccall_info.arg3,
@@ -363,7 +378,8 @@ void smp4d_cross_call_irq(void)
363void smp4d_percpu_timer_interrupt(struct pt_regs *regs) 378void smp4d_percpu_timer_interrupt(struct pt_regs *regs)
364{ 379{
365 struct pt_regs *old_regs; 380 struct pt_regs *old_regs;
366 int cpu = hard_smp4d_processor_id(); 381 int cpu = hard_smp_processor_id();
382 struct clock_event_device *ce;
367 static int cpu_tick[NR_CPUS]; 383 static int cpu_tick[NR_CPUS];
368 static char led_mask[] = { 0xe, 0xd, 0xb, 0x7, 0xb, 0xd }; 384 static char led_mask[] = { 0xe, 0xd, 0xb, 0x7, 0xb, 0xd };
369 385
@@ -379,45 +395,21 @@ void smp4d_percpu_timer_interrupt(struct pt_regs *regs)
379 show_leds(cpu); 395 show_leds(cpu);
380 } 396 }
381 397
382 profile_tick(CPU_PROFILING); 398 ce = &per_cpu(sparc32_clockevent, cpu);
383
384 if (!--prof_counter(cpu)) {
385 int user = user_mode(regs);
386 399
387 irq_enter(); 400 irq_enter();
388 update_process_times(user); 401 ce->event_handler(ce);
389 irq_exit(); 402 irq_exit();
390 403
391 prof_counter(cpu) = prof_multiplier(cpu);
392 }
393 set_irq_regs(old_regs); 404 set_irq_regs(old_regs);
394} 405}
395 406
396static void __cpuinit smp_setup_percpu_timer(void) 407static const struct sparc32_ipi_ops sun4d_ipi_ops = {
397{ 408 .cross_call = sun4d_cross_call,
398 int cpu = hard_smp4d_processor_id(); 409 .resched = sun4d_ipi_resched,
399 410 .single = sun4d_ipi_single,
400 prof_counter(cpu) = prof_multiplier(cpu) = 1; 411 .mask_one = sun4d_ipi_mask_one,
401 load_profile_irq(cpu, lvl14_resolution); 412};
402}
403
404void __init smp4d_blackbox_id(unsigned *addr)
405{
406 int rd = *addr & 0x3e000000;
407
408 addr[0] = 0xc0800800 | rd; /* lda [%g0] ASI_M_VIKING_TMP1, reg */
409 addr[1] = 0x01000000; /* nop */
410 addr[2] = 0x01000000; /* nop */
411}
412
413void __init smp4d_blackbox_current(unsigned *addr)
414{
415 int rd = *addr & 0x3e000000;
416
417 addr[0] = 0xc0800800 | rd; /* lda [%g0] ASI_M_VIKING_TMP1, reg */
418 addr[2] = 0x81282002 | rd | (rd >> 11); /* sll reg, 2, reg */
419 addr[4] = 0x01000000; /* nop */
420}
421 413
422void __init sun4d_init_smp(void) 414void __init sun4d_init_smp(void)
423{ 415{
@@ -426,14 +418,7 @@ void __init sun4d_init_smp(void)
426 /* Patch ipi15 trap table */ 418 /* Patch ipi15 trap table */
427 t_nmi[1] = t_nmi[1] + (linux_trap_ipi15_sun4d - linux_trap_ipi15_sun4m); 419 t_nmi[1] = t_nmi[1] + (linux_trap_ipi15_sun4d - linux_trap_ipi15_sun4m);
428 420
429 /* And set btfixup... */ 421 sparc32_ipi_ops = &sun4d_ipi_ops;
430 BTFIXUPSET_BLACKBOX(hard_smp_processor_id, smp4d_blackbox_id);
431 BTFIXUPSET_BLACKBOX(load_current, smp4d_blackbox_current);
432 BTFIXUPSET_CALL(smp_cross_call, smp4d_cross_call, BTFIXUPCALL_NORM);
433 BTFIXUPSET_CALL(__hard_smp_processor_id, __smp4d_processor_id, BTFIXUPCALL_NORM);
434 BTFIXUPSET_CALL(smp_ipi_resched, smp4d_ipi_resched, BTFIXUPCALL_NORM);
435 BTFIXUPSET_CALL(smp_ipi_single, smp4d_ipi_single, BTFIXUPCALL_NORM);
436 BTFIXUPSET_CALL(smp_ipi_mask_one, smp4d_ipi_mask_one, BTFIXUPCALL_NORM);
437 422
438 for (i = 0; i < NR_CPUS; i++) { 423 for (i = 0; i < NR_CPUS; i++) {
439 ccall_info.processors_in[i] = 1; 424 ccall_info.processors_in[i] = 1;
diff --git a/arch/sparc/kernel/sun4m_irq.c b/arch/sparc/kernel/sun4m_irq.c
index e61165161dd3..c5ade9d27a1d 100644
--- a/arch/sparc/kernel/sun4m_irq.c
+++ b/arch/sparc/kernel/sun4m_irq.c
@@ -112,9 +112,6 @@ struct sun4m_handler_data {
112#define SUN4M_INT_E14 0x00000080 112#define SUN4M_INT_E14 0x00000080
113#define SUN4M_INT_E10 0x00080000 113#define SUN4M_INT_E10 0x00080000
114 114
115#define SUN4M_HARD_INT(x) (0x000000001 << (x))
116#define SUN4M_SOFT_INT(x) (0x000010000 << (x))
117
118#define SUN4M_INT_MASKALL 0x80000000 /* mask all interrupts */ 115#define SUN4M_INT_MASKALL 0x80000000 /* mask all interrupts */
119#define SUN4M_INT_MODULE_ERR 0x40000000 /* module error */ 116#define SUN4M_INT_MODULE_ERR 0x40000000 /* module error */
120#define SUN4M_INT_M2S_WRITE_ERR 0x20000000 /* write buffer error */ 117#define SUN4M_INT_M2S_WRITE_ERR 0x20000000 /* write buffer error */
@@ -282,23 +279,6 @@ out:
282 return irq; 279 return irq;
283} 280}
284 281
285#ifdef CONFIG_SMP
286static void sun4m_send_ipi(int cpu, int level)
287{
288 sbus_writel(SUN4M_SOFT_INT(level), &sun4m_irq_percpu[cpu]->set);
289}
290
291static void sun4m_clear_ipi(int cpu, int level)
292{
293 sbus_writel(SUN4M_SOFT_INT(level), &sun4m_irq_percpu[cpu]->clear);
294}
295
296static void sun4m_set_udt(int cpu)
297{
298 sbus_writel(cpu, &sun4m_irq_global->interrupt_target);
299}
300#endif
301
302struct sun4m_timer_percpu { 282struct sun4m_timer_percpu {
303 u32 l14_limit; 283 u32 l14_limit;
304 u32 l14_count; 284 u32 l14_count;
@@ -318,9 +298,6 @@ struct sun4m_timer_global {
318 298
319static struct sun4m_timer_global __iomem *timers_global; 299static struct sun4m_timer_global __iomem *timers_global;
320 300
321
322unsigned int lvl14_resolution = (((1000000/HZ) + 1) << 10);
323
324static void sun4m_clear_clock_irq(void) 301static void sun4m_clear_clock_irq(void)
325{ 302{
326 sbus_readl(&timers_global->l10_limit); 303 sbus_readl(&timers_global->l10_limit);
@@ -369,10 +346,11 @@ void sun4m_clear_profile_irq(int cpu)
369 346
370static void sun4m_load_profile_irq(int cpu, unsigned int limit) 347static void sun4m_load_profile_irq(int cpu, unsigned int limit)
371{ 348{
372 sbus_writel(limit, &timers_percpu[cpu]->l14_limit); 349 unsigned int value = limit ? timer_value(limit) : 0;
350 sbus_writel(value, &timers_percpu[cpu]->l14_limit);
373} 351}
374 352
375static void __init sun4m_init_timers(irq_handler_t counter_fn) 353static void __init sun4m_init_timers(void)
376{ 354{
377 struct device_node *dp = of_find_node_by_name(NULL, "counter"); 355 struct device_node *dp = of_find_node_by_name(NULL, "counter");
378 int i, err, len, num_cpu_timers; 356 int i, err, len, num_cpu_timers;
@@ -402,13 +380,22 @@ static void __init sun4m_init_timers(irq_handler_t counter_fn)
402 /* Every per-cpu timer works in timer mode */ 380 /* Every per-cpu timer works in timer mode */
403 sbus_writel(0x00000000, &timers_global->timer_config); 381 sbus_writel(0x00000000, &timers_global->timer_config);
404 382
405 sbus_writel((((1000000/HZ) + 1) << 10), &timers_global->l10_limit); 383#ifdef CONFIG_SMP
384 sparc_config.cs_period = SBUS_CLOCK_RATE * 2; /* 2 seconds */
385 sparc_config.features |= FEAT_L14_ONESHOT;
386#else
387 sparc_config.cs_period = SBUS_CLOCK_RATE / HZ; /* 1/HZ sec */
388 sparc_config.features |= FEAT_L10_CLOCKEVENT;
389#endif
390 sparc_config.features |= FEAT_L10_CLOCKSOURCE;
391 sbus_writel(timer_value(sparc_config.cs_period),
392 &timers_global->l10_limit);
406 393
407 master_l10_counter = &timers_global->l10_count; 394 master_l10_counter = &timers_global->l10_count;
408 395
409 irq = sun4m_build_device_irq(NULL, SUN4M_TIMER_IRQ); 396 irq = sun4m_build_device_irq(NULL, SUN4M_TIMER_IRQ);
410 397
411 err = request_irq(irq, counter_fn, IRQF_TIMER, "timer", NULL); 398 err = request_irq(irq, timer_interrupt, IRQF_TIMER, "timer", NULL);
412 if (err) { 399 if (err) {
413 printk(KERN_ERR "sun4m_init_timers: Register IRQ error %d.\n", 400 printk(KERN_ERR "sun4m_init_timers: Register IRQ error %d.\n",
414 err); 401 err);
@@ -434,7 +421,7 @@ static void __init sun4m_init_timers(irq_handler_t counter_fn)
434 trap_table->inst_two = lvl14_save[1]; 421 trap_table->inst_two = lvl14_save[1];
435 trap_table->inst_three = lvl14_save[2]; 422 trap_table->inst_three = lvl14_save[2];
436 trap_table->inst_four = lvl14_save[3]; 423 trap_table->inst_four = lvl14_save[3];
437 local_flush_cache_all(); 424 local_ops->cache_all();
438 local_irq_restore(flags); 425 local_irq_restore(flags);
439 } 426 }
440#endif 427#endif
@@ -475,17 +462,12 @@ void __init sun4m_init_IRQ(void)
475 if (num_cpu_iregs == 4) 462 if (num_cpu_iregs == 4)
476 sbus_writel(0, &sun4m_irq_global->interrupt_target); 463 sbus_writel(0, &sun4m_irq_global->interrupt_target);
477 464
478 BTFIXUPSET_CALL(clear_clock_irq, sun4m_clear_clock_irq, BTFIXUPCALL_NORM); 465 sparc_config.init_timers = sun4m_init_timers;
479 BTFIXUPSET_CALL(load_profile_irq, sun4m_load_profile_irq, BTFIXUPCALL_NORM); 466 sparc_config.build_device_irq = sun4m_build_device_irq;
480 467 sparc_config.clock_rate = SBUS_CLOCK_RATE;
481 sparc_irq_config.init_timers = sun4m_init_timers; 468 sparc_config.clear_clock_irq = sun4m_clear_clock_irq;
482 sparc_irq_config.build_device_irq = sun4m_build_device_irq; 469 sparc_config.load_profile_irq = sun4m_load_profile_irq;
483 470
484#ifdef CONFIG_SMP
485 BTFIXUPSET_CALL(set_cpu_int, sun4m_send_ipi, BTFIXUPCALL_NORM);
486 BTFIXUPSET_CALL(clear_cpu_int, sun4m_clear_ipi, BTFIXUPCALL_NORM);
487 BTFIXUPSET_CALL(set_irq_udt, sun4m_set_udt, BTFIXUPCALL_NORM);
488#endif
489 471
490 /* Cannot enable interrupts until OBP ticker is disabled. */ 472 /* Cannot enable interrupts until OBP ticker is disabled. */
491} 473}
diff --git a/arch/sparc/kernel/sun4m_smp.c b/arch/sparc/kernel/sun4m_smp.c
index 02db9a0412ce..960e8ab47b12 100644
--- a/arch/sparc/kernel/sun4m_smp.c
+++ b/arch/sparc/kernel/sun4m_smp.c
@@ -4,14 +4,18 @@
4 * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) 4 * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
5 */ 5 */
6 6
7#include <linux/clockchips.h>
7#include <linux/interrupt.h> 8#include <linux/interrupt.h>
8#include <linux/profile.h> 9#include <linux/profile.h>
9#include <linux/delay.h> 10#include <linux/delay.h>
11#include <linux/sched.h>
10#include <linux/cpu.h> 12#include <linux/cpu.h>
11 13
12#include <asm/cacheflush.h> 14#include <asm/cacheflush.h>
13#include <asm/switch_to.h> 15#include <asm/switch_to.h>
14#include <asm/tlbflush.h> 16#include <asm/tlbflush.h>
17#include <asm/timer.h>
18#include <asm/oplib.h>
15 19
16#include "irq.h" 20#include "irq.h"
17#include "kernel.h" 21#include "kernel.h"
@@ -30,26 +34,22 @@ swap_ulong(volatile unsigned long *ptr, unsigned long val)
30 return val; 34 return val;
31} 35}
32 36
33static void smp4m_ipi_init(void);
34static void smp_setup_percpu_timer(void);
35
36void __cpuinit smp4m_callin(void) 37void __cpuinit smp4m_callin(void)
37{ 38{
38 int cpuid = hard_smp_processor_id(); 39 int cpuid = hard_smp_processor_id();
39 40
40 local_flush_cache_all(); 41 local_ops->cache_all();
41 local_flush_tlb_all(); 42 local_ops->tlb_all();
42 43
43 notify_cpu_starting(cpuid); 44 notify_cpu_starting(cpuid);
44 45
45 /* Get our local ticker going. */ 46 register_percpu_ce(cpuid);
46 smp_setup_percpu_timer();
47 47
48 calibrate_delay(); 48 calibrate_delay();
49 smp_store_cpu_info(cpuid); 49 smp_store_cpu_info(cpuid);
50 50
51 local_flush_cache_all(); 51 local_ops->cache_all();
52 local_flush_tlb_all(); 52 local_ops->tlb_all();
53 53
54 /* 54 /*
55 * Unblock the master CPU _only_ when the scheduler state 55 * Unblock the master CPU _only_ when the scheduler state
@@ -61,8 +61,8 @@ void __cpuinit smp4m_callin(void)
61 swap_ulong(&cpu_callin_map[cpuid], 1); 61 swap_ulong(&cpu_callin_map[cpuid], 1);
62 62
63 /* XXX: What's up with all the flushes? */ 63 /* XXX: What's up with all the flushes? */
64 local_flush_cache_all(); 64 local_ops->cache_all();
65 local_flush_tlb_all(); 65 local_ops->tlb_all();
66 66
67 /* Fix idle thread fields. */ 67 /* Fix idle thread fields. */
68 __asm__ __volatile__("ld [%0], %%g6\n\t" 68 __asm__ __volatile__("ld [%0], %%g6\n\t"
@@ -86,9 +86,8 @@ void __cpuinit smp4m_callin(void)
86 */ 86 */
87void __init smp4m_boot_cpus(void) 87void __init smp4m_boot_cpus(void)
88{ 88{
89 smp4m_ipi_init(); 89 sun4m_unmask_profile_irq();
90 smp_setup_percpu_timer(); 90 local_ops->cache_all();
91 local_flush_cache_all();
92} 91}
93 92
94int __cpuinit smp4m_boot_one_cpu(int i) 93int __cpuinit smp4m_boot_one_cpu(int i)
@@ -117,7 +116,7 @@ int __cpuinit smp4m_boot_one_cpu(int i)
117 116
118 /* whirrr, whirrr, whirrrrrrrrr... */ 117 /* whirrr, whirrr, whirrrrrrrrr... */
119 printk(KERN_INFO "Starting CPU %d at %p\n", i, entry); 118 printk(KERN_INFO "Starting CPU %d at %p\n", i, entry);
120 local_flush_cache_all(); 119 local_ops->cache_all();
121 prom_startcpu(cpu_node, &smp_penguin_ctable, 0, (char *)entry); 120 prom_startcpu(cpu_node, &smp_penguin_ctable, 0, (char *)entry);
122 121
123 /* wheee... it's going... */ 122 /* wheee... it's going... */
@@ -132,7 +131,7 @@ int __cpuinit smp4m_boot_one_cpu(int i)
132 return -ENODEV; 131 return -ENODEV;
133 } 132 }
134 133
135 local_flush_cache_all(); 134 local_ops->cache_all();
136 return 0; 135 return 0;
137} 136}
138 137
@@ -149,30 +148,29 @@ void __init smp4m_smp_done(void)
149 prev = &cpu_data(i).next; 148 prev = &cpu_data(i).next;
150 } 149 }
151 *prev = first; 150 *prev = first;
152 local_flush_cache_all(); 151 local_ops->cache_all();
153 152
154 /* Ok, they are spinning and ready to go. */ 153 /* Ok, they are spinning and ready to go. */
155} 154}
156 155
157 156static void sun4m_send_ipi(int cpu, int level)
158/* Initialize IPIs on the SUN4M SMP machine */
159static void __init smp4m_ipi_init(void)
160{ 157{
158 sbus_writel(SUN4M_SOFT_INT(level), &sun4m_irq_percpu[cpu]->set);
161} 159}
162 160
163static void smp4m_ipi_resched(int cpu) 161static void sun4m_ipi_resched(int cpu)
164{ 162{
165 set_cpu_int(cpu, IRQ_IPI_RESCHED); 163 sun4m_send_ipi(cpu, IRQ_IPI_RESCHED);
166} 164}
167 165
168static void smp4m_ipi_single(int cpu) 166static void sun4m_ipi_single(int cpu)
169{ 167{
170 set_cpu_int(cpu, IRQ_IPI_SINGLE); 168 sun4m_send_ipi(cpu, IRQ_IPI_SINGLE);
171} 169}
172 170
173static void smp4m_ipi_mask_one(int cpu) 171static void sun4m_ipi_mask_one(int cpu)
174{ 172{
175 set_cpu_int(cpu, IRQ_IPI_MASK); 173 sun4m_send_ipi(cpu, IRQ_IPI_MASK);
176} 174}
177 175
178static struct smp_funcall { 176static struct smp_funcall {
@@ -189,7 +187,7 @@ static struct smp_funcall {
189static DEFINE_SPINLOCK(cross_call_lock); 187static DEFINE_SPINLOCK(cross_call_lock);
190 188
191/* Cross calls must be serialized, at least currently. */ 189/* Cross calls must be serialized, at least currently. */
192static void smp4m_cross_call(smpfunc_t func, cpumask_t mask, unsigned long arg1, 190static void sun4m_cross_call(smpfunc_t func, cpumask_t mask, unsigned long arg1,
193 unsigned long arg2, unsigned long arg3, 191 unsigned long arg2, unsigned long arg3,
194 unsigned long arg4) 192 unsigned long arg4)
195{ 193{
@@ -216,7 +214,7 @@ static void smp4m_cross_call(smpfunc_t func, cpumask_t mask, unsigned long arg1,
216 if (cpumask_test_cpu(i, &mask)) { 214 if (cpumask_test_cpu(i, &mask)) {
217 ccall_info.processors_in[i] = 0; 215 ccall_info.processors_in[i] = 0;
218 ccall_info.processors_out[i] = 0; 216 ccall_info.processors_out[i] = 0;
219 set_cpu_int(i, IRQ_CROSS_CALL); 217 sun4m_send_ipi(i, IRQ_CROSS_CALL);
220 } else { 218 } else {
221 ccall_info.processors_in[i] = 1; 219 ccall_info.processors_in[i] = 1;
222 ccall_info.processors_out[i] = 1; 220 ccall_info.processors_out[i] = 1;
@@ -260,64 +258,33 @@ void smp4m_cross_call_irq(void)
260void smp4m_percpu_timer_interrupt(struct pt_regs *regs) 258void smp4m_percpu_timer_interrupt(struct pt_regs *regs)
261{ 259{
262 struct pt_regs *old_regs; 260 struct pt_regs *old_regs;
261 struct clock_event_device *ce;
263 int cpu = smp_processor_id(); 262 int cpu = smp_processor_id();
264 263
265 old_regs = set_irq_regs(regs); 264 old_regs = set_irq_regs(regs);
266 265
267 sun4m_clear_profile_irq(cpu); 266 ce = &per_cpu(sparc32_clockevent, cpu);
268
269 profile_tick(CPU_PROFILING);
270 267
271 if (!--prof_counter(cpu)) { 268 if (ce->mode & CLOCK_EVT_MODE_PERIODIC)
272 int user = user_mode(regs); 269 sun4m_clear_profile_irq(cpu);
270 else
271 sparc_config.load_profile_irq(cpu, 0); /* Is this needless? */
273 272
274 irq_enter(); 273 irq_enter();
275 update_process_times(user); 274 ce->event_handler(ce);
276 irq_exit(); 275 irq_exit();
277 276
278 prof_counter(cpu) = prof_multiplier(cpu);
279 }
280 set_irq_regs(old_regs); 277 set_irq_regs(old_regs);
281} 278}
282 279
283static void __cpuinit smp_setup_percpu_timer(void) 280static const struct sparc32_ipi_ops sun4m_ipi_ops = {
284{ 281 .cross_call = sun4m_cross_call,
285 int cpu = smp_processor_id(); 282 .resched = sun4m_ipi_resched,
286 283 .single = sun4m_ipi_single,
287 prof_counter(cpu) = prof_multiplier(cpu) = 1; 284 .mask_one = sun4m_ipi_mask_one,
288 load_profile_irq(cpu, lvl14_resolution); 285};
289
290 if (cpu == boot_cpu_id)
291 sun4m_unmask_profile_irq();
292}
293
294static void __init smp4m_blackbox_id(unsigned *addr)
295{
296 int rd = *addr & 0x3e000000;
297 int rs1 = rd >> 11;
298
299 addr[0] = 0x81580000 | rd; /* rd %tbr, reg */
300 addr[1] = 0x8130200c | rd | rs1; /* srl reg, 0xc, reg */
301 addr[2] = 0x80082003 | rd | rs1; /* and reg, 3, reg */
302}
303
304static void __init smp4m_blackbox_current(unsigned *addr)
305{
306 int rd = *addr & 0x3e000000;
307 int rs1 = rd >> 11;
308
309 addr[0] = 0x81580000 | rd; /* rd %tbr, reg */
310 addr[2] = 0x8130200a | rd | rs1; /* srl reg, 0xa, reg */
311 addr[4] = 0x8008200c | rd | rs1; /* and reg, 0xc, reg */
312}
313 286
314void __init sun4m_init_smp(void) 287void __init sun4m_init_smp(void)
315{ 288{
316 BTFIXUPSET_BLACKBOX(hard_smp_processor_id, smp4m_blackbox_id); 289 sparc32_ipi_ops = &sun4m_ipi_ops;
317 BTFIXUPSET_BLACKBOX(load_current, smp4m_blackbox_current);
318 BTFIXUPSET_CALL(smp_cross_call, smp4m_cross_call, BTFIXUPCALL_NORM);
319 BTFIXUPSET_CALL(__hard_smp_processor_id, __smp4m_processor_id, BTFIXUPCALL_NORM);
320 BTFIXUPSET_CALL(smp_ipi_resched, smp4m_ipi_resched, BTFIXUPCALL_NORM);
321 BTFIXUPSET_CALL(smp_ipi_single, smp4m_ipi_single, BTFIXUPCALL_NORM);
322 BTFIXUPSET_CALL(smp_ipi_mask_one, smp4m_ipi_mask_one, BTFIXUPCALL_NORM);
323} 290}
diff --git a/arch/sparc/kernel/sys_sparc_32.c b/arch/sparc/kernel/sys_sparc_32.c
index 42b282fa6112..627e89af1d71 100644
--- a/arch/sparc/kernel/sys_sparc_32.c
+++ b/arch/sparc/kernel/sys_sparc_32.c
@@ -53,8 +53,6 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, unsi
53 /* See asm-sparc/uaccess.h */ 53 /* See asm-sparc/uaccess.h */
54 if (len > TASK_SIZE - PAGE_SIZE) 54 if (len > TASK_SIZE - PAGE_SIZE)
55 return -ENOMEM; 55 return -ENOMEM;
56 if (ARCH_SUN4C && len > 0x20000000)
57 return -ENOMEM;
58 if (!addr) 56 if (!addr)
59 addr = TASK_UNMAPPED_BASE; 57 addr = TASK_UNMAPPED_BASE;
60 58
@@ -65,10 +63,6 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, unsi
65 63
66 for (vmm = find_vma(current->mm, addr); ; vmm = vmm->vm_next) { 64 for (vmm = find_vma(current->mm, addr); ; vmm = vmm->vm_next) {
67 /* At this point: (!vmm || addr < vmm->vm_end). */ 65 /* At this point: (!vmm || addr < vmm->vm_end). */
68 if (ARCH_SUN4C && addr < 0xe0000000 && 0x20000000 - len < addr) {
69 addr = PAGE_OFFSET;
70 vmm = find_vma(current->mm, PAGE_OFFSET);
71 }
72 if (TASK_SIZE - PAGE_SIZE - len < addr) 66 if (TASK_SIZE - PAGE_SIZE - len < addr)
73 return -ENOMEM; 67 return -ENOMEM;
74 if (!vmm || addr + len <= vmm->vm_start) 68 if (!vmm || addr + len <= vmm->vm_start)
@@ -99,11 +93,6 @@ out:
99 93
100int sparc_mmap_check(unsigned long addr, unsigned long len) 94int sparc_mmap_check(unsigned long addr, unsigned long len)
101{ 95{
102 if (ARCH_SUN4C &&
103 (len > 0x20000000 ||
104 (addr < 0xe0000000 && addr + len > 0x20000000)))
105 return -EINVAL;
106
107 /* See asm-sparc/uaccess.h */ 96 /* See asm-sparc/uaccess.h */
108 if (len > TASK_SIZE - PAGE_SIZE || addr + len > TASK_SIZE - PAGE_SIZE) 97 if (len > TASK_SIZE - PAGE_SIZE || addr + len > TASK_SIZE - PAGE_SIZE)
109 return -EINVAL; 98 return -EINVAL;
diff --git a/arch/sparc/kernel/time_32.c b/arch/sparc/kernel/time_32.c
index 7d0c088e8aba..953641549e82 100644
--- a/arch/sparc/kernel/time_32.c
+++ b/arch/sparc/kernel/time_32.c
@@ -26,6 +26,8 @@
26#include <linux/rtc.h> 26#include <linux/rtc.h>
27#include <linux/rtc/m48t59.h> 27#include <linux/rtc/m48t59.h>
28#include <linux/timex.h> 28#include <linux/timex.h>
29#include <linux/clocksource.h>
30#include <linux/clockchips.h>
29#include <linux/init.h> 31#include <linux/init.h>
30#include <linux/pci.h> 32#include <linux/pci.h>
31#include <linux/ioport.h> 33#include <linux/ioport.h>
@@ -40,13 +42,24 @@
40#include <asm/irq.h> 42#include <asm/irq.h>
41#include <asm/io.h> 43#include <asm/io.h>
42#include <asm/idprom.h> 44#include <asm/idprom.h>
43#include <asm/machines.h>
44#include <asm/page.h> 45#include <asm/page.h>
45#include <asm/pcic.h> 46#include <asm/pcic.h>
46#include <asm/irq_regs.h> 47#include <asm/irq_regs.h>
48#include <asm/setup.h>
47 49
48#include "irq.h" 50#include "irq.h"
49 51
52static __cacheline_aligned_in_smp DEFINE_SEQLOCK(timer_cs_lock);
53static __volatile__ u64 timer_cs_internal_counter = 0;
54static char timer_cs_enabled = 0;
55
56static struct clock_event_device timer_ce;
57static char timer_ce_enabled = 0;
58
59#ifdef CONFIG_SMP
60DEFINE_PER_CPU(struct clock_event_device, sparc32_clockevent);
61#endif
62
50DEFINE_SPINLOCK(rtc_lock); 63DEFINE_SPINLOCK(rtc_lock);
51EXPORT_SYMBOL(rtc_lock); 64EXPORT_SYMBOL(rtc_lock);
52 65
@@ -55,7 +68,6 @@ static int set_rtc_mmss(unsigned long);
55unsigned long profile_pc(struct pt_regs *regs) 68unsigned long profile_pc(struct pt_regs *regs)
56{ 69{
57 extern char __copy_user_begin[], __copy_user_end[]; 70 extern char __copy_user_begin[], __copy_user_end[];
58 extern char __atomic_begin[], __atomic_end[];
59 extern char __bzero_begin[], __bzero_end[]; 71 extern char __bzero_begin[], __bzero_end[];
60 72
61 unsigned long pc = regs->pc; 73 unsigned long pc = regs->pc;
@@ -63,8 +75,6 @@ unsigned long profile_pc(struct pt_regs *regs)
63 if (in_lock_functions(pc) || 75 if (in_lock_functions(pc) ||
64 (pc >= (unsigned long) __copy_user_begin && 76 (pc >= (unsigned long) __copy_user_begin &&
65 pc < (unsigned long) __copy_user_end) || 77 pc < (unsigned long) __copy_user_end) ||
66 (pc >= (unsigned long) __atomic_begin &&
67 pc < (unsigned long) __atomic_end) ||
68 (pc >= (unsigned long) __bzero_begin && 78 (pc >= (unsigned long) __bzero_begin &&
69 pc < (unsigned long) __bzero_end)) 79 pc < (unsigned long) __bzero_end))
70 pc = regs->u_regs[UREG_RETPC]; 80 pc = regs->u_regs[UREG_RETPC];
@@ -75,36 +85,168 @@ EXPORT_SYMBOL(profile_pc);
75 85
76__volatile__ unsigned int *master_l10_counter; 86__volatile__ unsigned int *master_l10_counter;
77 87
78u32 (*do_arch_gettimeoffset)(void);
79
80int update_persistent_clock(struct timespec now) 88int update_persistent_clock(struct timespec now)
81{ 89{
82 return set_rtc_mmss(now.tv_sec); 90 return set_rtc_mmss(now.tv_sec);
83} 91}
84 92
85/* 93irqreturn_t notrace timer_interrupt(int dummy, void *dev_id)
86 * timer_interrupt() needs to keep up the real-time clock, 94{
87 * as well as call the "xtime_update()" routine every clocktick 95 if (timer_cs_enabled) {
88 */ 96 write_seqlock(&timer_cs_lock);
97 timer_cs_internal_counter++;
98 sparc_config.clear_clock_irq();
99 write_sequnlock(&timer_cs_lock);
100 } else {
101 sparc_config.clear_clock_irq();
102 }
89 103
90#define TICK_SIZE (tick_nsec / 1000) 104 if (timer_ce_enabled)
105 timer_ce.event_handler(&timer_ce);
91 106
92static irqreturn_t timer_interrupt(int dummy, void *dev_id) 107 return IRQ_HANDLED;
108}
109
110static void timer_ce_set_mode(enum clock_event_mode mode,
111 struct clock_event_device *evt)
93{ 112{
94#ifndef CONFIG_SMP 113 switch (mode) {
95 profile_tick(CPU_PROFILING); 114 case CLOCK_EVT_MODE_PERIODIC:
96#endif 115 case CLOCK_EVT_MODE_RESUME:
116 timer_ce_enabled = 1;
117 break;
118 case CLOCK_EVT_MODE_SHUTDOWN:
119 timer_ce_enabled = 0;
120 break;
121 default:
122 break;
123 }
124 smp_mb();
125}
97 126
98 clear_clock_irq(); 127static __init void setup_timer_ce(void)
128{
129 struct clock_event_device *ce = &timer_ce;
130
131 BUG_ON(smp_processor_id() != boot_cpu_id);
132
133 ce->name = "timer_ce";
134 ce->rating = 100;
135 ce->features = CLOCK_EVT_FEAT_PERIODIC;
136 ce->set_mode = timer_ce_set_mode;
137 ce->cpumask = cpu_possible_mask;
138 ce->shift = 32;
139 ce->mult = div_sc(sparc_config.clock_rate, NSEC_PER_SEC,
140 ce->shift);
141 clockevents_register_device(ce);
142}
99 143
100 xtime_update(1); 144static unsigned int sbus_cycles_offset(void)
145{
146 unsigned int val, offset;
101 147
102#ifndef CONFIG_SMP 148 val = *master_l10_counter;
103 update_process_times(user_mode(get_irq_regs())); 149 offset = (val >> TIMER_VALUE_SHIFT) & TIMER_VALUE_MASK;
104#endif 150
105 return IRQ_HANDLED; 151 /* Limit hit? */
152 if (val & TIMER_LIMIT_BIT)
153 offset += sparc_config.cs_period;
154
155 return offset;
156}
157
158static cycle_t timer_cs_read(struct clocksource *cs)
159{
160 unsigned int seq, offset;
161 u64 cycles;
162
163 do {
164 seq = read_seqbegin(&timer_cs_lock);
165
166 cycles = timer_cs_internal_counter;
167 offset = sparc_config.get_cycles_offset();
168 } while (read_seqretry(&timer_cs_lock, seq));
169
170 /* Count absolute cycles */
171 cycles *= sparc_config.cs_period;
172 cycles += offset;
173
174 return cycles;
175}
176
177static struct clocksource timer_cs = {
178 .name = "timer_cs",
179 .rating = 100,
180 .read = timer_cs_read,
181 .mask = CLOCKSOURCE_MASK(64),
182 .shift = 2,
183 .flags = CLOCK_SOURCE_IS_CONTINUOUS,
184};
185
186static __init int setup_timer_cs(void)
187{
188 timer_cs_enabled = 1;
189 timer_cs.mult = clocksource_hz2mult(sparc_config.clock_rate,
190 timer_cs.shift);
191
192 return clocksource_register(&timer_cs);
106} 193}
107 194
195#ifdef CONFIG_SMP
196static void percpu_ce_setup(enum clock_event_mode mode,
197 struct clock_event_device *evt)
198{
199 int cpu = __first_cpu(evt->cpumask);
200
201 switch (mode) {
202 case CLOCK_EVT_MODE_PERIODIC:
203 sparc_config.load_profile_irq(cpu,
204 SBUS_CLOCK_RATE / HZ);
205 break;
206 case CLOCK_EVT_MODE_ONESHOT:
207 case CLOCK_EVT_MODE_SHUTDOWN:
208 case CLOCK_EVT_MODE_UNUSED:
209 sparc_config.load_profile_irq(cpu, 0);
210 break;
211 default:
212 break;
213 }
214}
215
216static int percpu_ce_set_next_event(unsigned long delta,
217 struct clock_event_device *evt)
218{
219 int cpu = __first_cpu(evt->cpumask);
220 unsigned int next = (unsigned int)delta;
221
222 sparc_config.load_profile_irq(cpu, next);
223 return 0;
224}
225
226void register_percpu_ce(int cpu)
227{
228 struct clock_event_device *ce = &per_cpu(sparc32_clockevent, cpu);
229 unsigned int features = CLOCK_EVT_FEAT_PERIODIC;
230
231 if (sparc_config.features & FEAT_L14_ONESHOT)
232 features |= CLOCK_EVT_FEAT_ONESHOT;
233
234 ce->name = "percpu_ce";
235 ce->rating = 200;
236 ce->features = features;
237 ce->set_mode = percpu_ce_setup;
238 ce->set_next_event = percpu_ce_set_next_event;
239 ce->cpumask = cpumask_of(cpu);
240 ce->shift = 32;
241 ce->mult = div_sc(sparc_config.clock_rate, NSEC_PER_SEC,
242 ce->shift);
243 ce->max_delta_ns = clockevent_delta2ns(sparc_config.clock_rate, ce);
244 ce->min_delta_ns = clockevent_delta2ns(100, ce);
245
246 clockevents_register_device(ce);
247}
248#endif
249
108static unsigned char mostek_read_byte(struct device *dev, u32 ofs) 250static unsigned char mostek_read_byte(struct device *dev, u32 ofs)
109{ 251{
110 struct platform_device *pdev = to_platform_device(dev); 252 struct platform_device *pdev = to_platform_device(dev);
@@ -195,38 +337,28 @@ static int __init clock_init(void)
195 */ 337 */
196fs_initcall(clock_init); 338fs_initcall(clock_init);
197 339
198 340static void __init sparc32_late_time_init(void)
199u32 sbus_do_gettimeoffset(void)
200{
201 unsigned long val = *master_l10_counter;
202 unsigned long usec = (val >> 10) & 0x1fffff;
203
204 /* Limit hit? */
205 if (val & 0x80000000)
206 usec += 1000000 / HZ;
207
208 return usec * 1000;
209}
210
211
212u32 arch_gettimeoffset(void)
213{ 341{
214 if (unlikely(!do_arch_gettimeoffset)) 342 if (sparc_config.features & FEAT_L10_CLOCKEVENT)
215 return 0; 343 setup_timer_ce();
216 return do_arch_gettimeoffset(); 344 if (sparc_config.features & FEAT_L10_CLOCKSOURCE)
345 setup_timer_cs();
346#ifdef CONFIG_SMP
347 register_percpu_ce(smp_processor_id());
348#endif
217} 349}
218 350
219static void __init sbus_time_init(void) 351static void __init sbus_time_init(void)
220{ 352{
221 do_arch_gettimeoffset = sbus_do_gettimeoffset; 353 sparc_config.get_cycles_offset = sbus_cycles_offset;
222 354 sparc_config.init_timers();
223 btfixup();
224
225 sparc_irq_config.init_timers(timer_interrupt);
226} 355}
227 356
228void __init time_init(void) 357void __init time_init(void)
229{ 358{
359 sparc_config.features = 0;
360 late_time_init = sparc32_late_time_init;
361
230 if (pcic_present()) 362 if (pcic_present())
231 pci_time_init(); 363 pci_time_init();
232 else 364 else
diff --git a/arch/sparc/kernel/trampoline_32.S b/arch/sparc/kernel/trampoline_32.S
index 691f484e03b3..7364ddc9e5aa 100644
--- a/arch/sparc/kernel/trampoline_32.S
+++ b/arch/sparc/kernel/trampoline_32.S
@@ -15,8 +15,8 @@
15#include <asm/contregs.h> 15#include <asm/contregs.h>
16#include <asm/thread_info.h> 16#include <asm/thread_info.h>
17 17
18 .globl sun4m_cpu_startup, __smp4m_processor_id, __leon_processor_id 18 .globl sun4m_cpu_startup
19 .globl sun4d_cpu_startup, __smp4d_processor_id 19 .globl sun4d_cpu_startup
20 20
21 __CPUINIT 21 __CPUINIT
22 .align 4 22 .align 4
@@ -94,24 +94,6 @@ smp_do_cpu_idle:
94 call cpu_panic 94 call cpu_panic
95 nop 95 nop
96 96
97__smp4m_processor_id:
98 rd %tbr, %g2
99 srl %g2, 12, %g2
100 and %g2, 3, %g2
101 retl
102 mov %g1, %o7
103
104__smp4d_processor_id:
105 lda [%g0] ASI_M_VIKING_TMP1, %g2
106 retl
107 mov %g1, %o7
108
109__leon_processor_id:
110 rd %asr17,%g2
111 srl %g2,28,%g2
112 retl
113 mov %g1, %o7
114
115/* CPUID in bootbus can be found at PA 0xff0140000 */ 97/* CPUID in bootbus can be found at PA 0xff0140000 */
116#define SUN4D_BOOTBUS_CPUID 0xf0140000 98#define SUN4D_BOOTBUS_CPUID 0xf0140000
117 99
diff --git a/arch/sparc/kernel/traps_32.c b/arch/sparc/kernel/traps_32.c
index d2de21333146..a5785ea2a85d 100644
--- a/arch/sparc/kernel/traps_32.c
+++ b/arch/sparc/kernel/traps_32.c
@@ -120,8 +120,6 @@ void do_illegal_instruction(struct pt_regs *regs, unsigned long pc, unsigned lon
120 printk("Ill instr. at pc=%08lx instruction is %08lx\n", 120 printk("Ill instr. at pc=%08lx instruction is %08lx\n",
121 regs->pc, *(unsigned long *)regs->pc); 121 regs->pc, *(unsigned long *)regs->pc);
122#endif 122#endif
123 if (!do_user_muldiv (regs, pc))
124 return;
125 123
126 info.si_signo = SIGILL; 124 info.si_signo = SIGILL;
127 info.si_errno = 0; 125 info.si_errno = 0;
diff --git a/arch/sparc/kernel/ttable_32.S b/arch/sparc/kernel/ttable_32.S
new file mode 100644
index 000000000000..8a7a96ca676f
--- /dev/null
+++ b/arch/sparc/kernel/ttable_32.S
@@ -0,0 +1,417 @@
1/* The Sparc trap table, bootloader gives us control at _start. */
2 __HEAD
3
4 .globl _start
5_start:
6
7 .globl _stext
8_stext:
9
10 .globl trapbase
11trapbase:
12
13#ifdef CONFIG_SMP
14trapbase_cpu0:
15#endif
16/* We get control passed to us here at t_zero. */
17t_zero: b gokernel; nop; nop; nop;
18t_tflt: SRMMU_TFAULT /* Inst. Access Exception */
19t_bins: TRAP_ENTRY(0x2, bad_instruction) /* Illegal Instruction */
20t_pins: TRAP_ENTRY(0x3, priv_instruction) /* Privileged Instruction */
21t_fpd: TRAP_ENTRY(0x4, fpd_trap_handler) /* Floating Point Disabled */
22t_wovf: WINDOW_SPILL /* Window Overflow */
23t_wunf: WINDOW_FILL /* Window Underflow */
24t_mna: TRAP_ENTRY(0x7, mna_handler) /* Memory Address Not Aligned */
25t_fpe: TRAP_ENTRY(0x8, fpe_trap_handler) /* Floating Point Exception */
26t_dflt: SRMMU_DFAULT /* Data Miss Exception */
27t_tio: TRAP_ENTRY(0xa, do_tag_overflow) /* Tagged Instruction Ovrflw */
28t_wpt: TRAP_ENTRY(0xb, do_watchpoint) /* Watchpoint Detected */
29t_badc: BAD_TRAP(0xc) BAD_TRAP(0xd) BAD_TRAP(0xe) BAD_TRAP(0xf) BAD_TRAP(0x10)
30t_irq1: TRAP_ENTRY_INTERRUPT(1) /* IRQ Software/SBUS Level 1 */
31t_irq2: TRAP_ENTRY_INTERRUPT(2) /* IRQ SBUS Level 2 */
32t_irq3: TRAP_ENTRY_INTERRUPT(3) /* IRQ SCSI/DMA/SBUS Level 3 */
33t_irq4: TRAP_ENTRY_INTERRUPT(4) /* IRQ Software Level 4 */
34t_irq5: TRAP_ENTRY_INTERRUPT(5) /* IRQ SBUS/Ethernet Level 5 */
35t_irq6: TRAP_ENTRY_INTERRUPT(6) /* IRQ Software Level 6 */
36t_irq7: TRAP_ENTRY_INTERRUPT(7) /* IRQ Video/SBUS Level 5 */
37t_irq8: TRAP_ENTRY_INTERRUPT(8) /* IRQ SBUS Level 6 */
38t_irq9: TRAP_ENTRY_INTERRUPT(9) /* IRQ SBUS Level 7 */
39t_irq10:TRAP_ENTRY_INTERRUPT(10) /* IRQ Timer #1 (one we use) */
40t_irq11:TRAP_ENTRY_INTERRUPT(11) /* IRQ Floppy Intr. */
41t_irq12:TRAP_ENTRY_INTERRUPT(12) /* IRQ Zilog serial chip */
42t_irq13:TRAP_ENTRY_INTERRUPT(13) /* IRQ Audio Intr. */
43t_irq14:TRAP_ENTRY_INTERRUPT(14) /* IRQ Timer #2 */
44
45 .globl t_nmi
46t_nmi: TRAP_ENTRY(0x1f, linux_trap_ipi15_sun4m)
47
48t_racc: TRAP_ENTRY(0x20, do_reg_access) /* General Register Access Error */
49t_iacce:BAD_TRAP(0x21) /* Instr Access Error */
50t_bad22:BAD_TRAP(0x22)
51 BAD_TRAP(0x23)
52t_cpdis:TRAP_ENTRY(0x24, do_cp_disabled) /* Co-Processor Disabled */
53t_uflsh:SKIP_TRAP(0x25, unimp_flush) /* Unimplemented FLUSH inst. */
54t_bad26:BAD_TRAP(0x26) BAD_TRAP(0x27)
55t_cpexc:TRAP_ENTRY(0x28, do_cp_exception) /* Co-Processor Exception */
56t_dacce:SRMMU_DFAULT /* Data Access Error */
57t_hwdz: TRAP_ENTRY(0x2a, do_hw_divzero) /* Division by zero, you lose... */
58t_dserr:BAD_TRAP(0x2b) /* Data Store Error */
59t_daccm:BAD_TRAP(0x2c) /* Data Access MMU-Miss */
60t_bad2d:BAD_TRAP(0x2d) BAD_TRAP(0x2e) BAD_TRAP(0x2f) BAD_TRAP(0x30) BAD_TRAP(0x31)
61t_bad32:BAD_TRAP(0x32) BAD_TRAP(0x33) BAD_TRAP(0x34) BAD_TRAP(0x35) BAD_TRAP(0x36)
62t_bad37:BAD_TRAP(0x37) BAD_TRAP(0x38) BAD_TRAP(0x39) BAD_TRAP(0x3a) BAD_TRAP(0x3b)
63t_iaccm:BAD_TRAP(0x3c) /* Instr Access MMU-Miss */
64t_bad3d:BAD_TRAP(0x3d) BAD_TRAP(0x3e) BAD_TRAP(0x3f) BAD_TRAP(0x40) BAD_TRAP(0x41)
65t_bad42:BAD_TRAP(0x42) BAD_TRAP(0x43) BAD_TRAP(0x44) BAD_TRAP(0x45) BAD_TRAP(0x46)
66t_bad47:BAD_TRAP(0x47) BAD_TRAP(0x48) BAD_TRAP(0x49) BAD_TRAP(0x4a) BAD_TRAP(0x4b)
67t_bad4c:BAD_TRAP(0x4c) BAD_TRAP(0x4d) BAD_TRAP(0x4e) BAD_TRAP(0x4f) BAD_TRAP(0x50)
68t_bad51:BAD_TRAP(0x51) BAD_TRAP(0x52) BAD_TRAP(0x53) BAD_TRAP(0x54) BAD_TRAP(0x55)
69t_bad56:BAD_TRAP(0x56) BAD_TRAP(0x57) BAD_TRAP(0x58) BAD_TRAP(0x59) BAD_TRAP(0x5a)
70t_bad5b:BAD_TRAP(0x5b) BAD_TRAP(0x5c) BAD_TRAP(0x5d) BAD_TRAP(0x5e) BAD_TRAP(0x5f)
71t_bad60:BAD_TRAP(0x60) BAD_TRAP(0x61) BAD_TRAP(0x62) BAD_TRAP(0x63) BAD_TRAP(0x64)
72t_bad65:BAD_TRAP(0x65) BAD_TRAP(0x66) BAD_TRAP(0x67) BAD_TRAP(0x68) BAD_TRAP(0x69)
73t_bad6a:BAD_TRAP(0x6a) BAD_TRAP(0x6b) BAD_TRAP(0x6c) BAD_TRAP(0x6d) BAD_TRAP(0x6e)
74t_bad6f:BAD_TRAP(0x6f) BAD_TRAP(0x70) BAD_TRAP(0x71) BAD_TRAP(0x72) BAD_TRAP(0x73)
75t_bad74:BAD_TRAP(0x74) BAD_TRAP(0x75) BAD_TRAP(0x76) BAD_TRAP(0x77) BAD_TRAP(0x78)
76t_bad79:BAD_TRAP(0x79) BAD_TRAP(0x7a) BAD_TRAP(0x7b) BAD_TRAP(0x7c) BAD_TRAP(0x7d)
77t_bad7e:BAD_TRAP(0x7e) BAD_TRAP(0x7f)
78t_bad80:BAD_TRAP(0x80) /* SunOS System Call */
79t_sbkpt:BREAKPOINT_TRAP /* Software Breakpoint/KGDB */
80t_divz: TRAP_ENTRY(0x82, do_hw_divzero) /* Divide by zero trap */
81t_flwin:TRAP_ENTRY(0x83, do_flush_windows) /* Flush Windows Trap */
82t_clwin:BAD_TRAP(0x84) /* Clean Windows Trap */
83t_rchk: BAD_TRAP(0x85) /* Range Check */
84t_funal:BAD_TRAP(0x86) /* Fix Unaligned Access Trap */
85t_iovf: BAD_TRAP(0x87) /* Integer Overflow Trap */
86t_bad88:BAD_TRAP(0x88) /* Slowaris System Call */
87t_bad89:BAD_TRAP(0x89) /* Net-B.S. System Call */
88t_bad8a:BAD_TRAP(0x8a) BAD_TRAP(0x8b) BAD_TRAP(0x8c) BAD_TRAP(0x8d) BAD_TRAP(0x8e)
89t_bad8f:BAD_TRAP(0x8f)
90t_linux:LINUX_SYSCALL_TRAP /* Linux System Call */
91t_bad91:BAD_TRAP(0x91) BAD_TRAP(0x92) BAD_TRAP(0x93) BAD_TRAP(0x94) BAD_TRAP(0x95)
92t_bad96:BAD_TRAP(0x96) BAD_TRAP(0x97) BAD_TRAP(0x98) BAD_TRAP(0x99) BAD_TRAP(0x9a)
93t_bad9b:BAD_TRAP(0x9b) BAD_TRAP(0x9c) BAD_TRAP(0x9d) BAD_TRAP(0x9e) BAD_TRAP(0x9f)
94t_getcc:GETCC_TRAP /* Get Condition Codes */
95t_setcc:SETCC_TRAP /* Set Condition Codes */
96t_getpsr:GETPSR_TRAP /* Get PSR Register */
97t_bada3:BAD_TRAP(0xa3) BAD_TRAP(0xa4) BAD_TRAP(0xa5) BAD_TRAP(0xa6)
98t_bada7:BAD_TRAP(0xa7)
99t_bada8:BAD_TRAP(0xa8) BAD_TRAP(0xa9) BAD_TRAP(0xaa) BAD_TRAP(0xab)
100t_badac:BAD_TRAP(0xac) BAD_TRAP(0xad) BAD_TRAP(0xae) BAD_TRAP(0xaf) BAD_TRAP(0xb0)
101t_badb1:BAD_TRAP(0xb1) BAD_TRAP(0xb2) BAD_TRAP(0xb3) BAD_TRAP(0xb4) BAD_TRAP(0xb5)
102t_badb6:BAD_TRAP(0xb6) BAD_TRAP(0xb7) BAD_TRAP(0xb8) BAD_TRAP(0xb9) BAD_TRAP(0xba)
103t_badbb:BAD_TRAP(0xbb) BAD_TRAP(0xbc) BAD_TRAP(0xbd) BAD_TRAP(0xbe) BAD_TRAP(0xbf)
104t_badc0:BAD_TRAP(0xc0) BAD_TRAP(0xc1) BAD_TRAP(0xc2) BAD_TRAP(0xc3) BAD_TRAP(0xc4)
105t_badc5:BAD_TRAP(0xc5) BAD_TRAP(0xc6) BAD_TRAP(0xc7) BAD_TRAP(0xc8) BAD_TRAP(0xc9)
106t_badca:BAD_TRAP(0xca) BAD_TRAP(0xcb) BAD_TRAP(0xcc) BAD_TRAP(0xcd) BAD_TRAP(0xce)
107t_badcf:BAD_TRAP(0xcf) BAD_TRAP(0xd0) BAD_TRAP(0xd1) BAD_TRAP(0xd2) BAD_TRAP(0xd3)
108t_badd4:BAD_TRAP(0xd4) BAD_TRAP(0xd5) BAD_TRAP(0xd6) BAD_TRAP(0xd7) BAD_TRAP(0xd8)
109t_badd9:BAD_TRAP(0xd9) BAD_TRAP(0xda) BAD_TRAP(0xdb) BAD_TRAP(0xdc) BAD_TRAP(0xdd)
110t_badde:BAD_TRAP(0xde) BAD_TRAP(0xdf) BAD_TRAP(0xe0) BAD_TRAP(0xe1) BAD_TRAP(0xe2)
111t_bade3:BAD_TRAP(0xe3) BAD_TRAP(0xe4) BAD_TRAP(0xe5) BAD_TRAP(0xe6) BAD_TRAP(0xe7)
112t_bade8:BAD_TRAP(0xe8) BAD_TRAP(0xe9) BAD_TRAP(0xea) BAD_TRAP(0xeb) BAD_TRAP(0xec)
113t_baded:BAD_TRAP(0xed) BAD_TRAP(0xee) BAD_TRAP(0xef) BAD_TRAP(0xf0) BAD_TRAP(0xf1)
114t_badf2:BAD_TRAP(0xf2) BAD_TRAP(0xf3) BAD_TRAP(0xf4) BAD_TRAP(0xf5) BAD_TRAP(0xf6)
115t_badf7:BAD_TRAP(0xf7) BAD_TRAP(0xf8) BAD_TRAP(0xf9) BAD_TRAP(0xfa) BAD_TRAP(0xfb)
116t_badfc:BAD_TRAP(0xfc)
117t_kgdb: KGDB_TRAP(0xfd)
118dbtrap: BAD_TRAP(0xfe) /* Debugger/PROM breakpoint #1 */
119dbtrap2:BAD_TRAP(0xff) /* Debugger/PROM breakpoint #2 */
120
121 .globl end_traptable
122end_traptable:
123
124#ifdef CONFIG_SMP
125 /* Trap tables for the other cpus. */
126 .globl trapbase_cpu1, trapbase_cpu2, trapbase_cpu3
127trapbase_cpu1:
128 BAD_TRAP(0x0)
129 SRMMU_TFAULT
130 TRAP_ENTRY(0x2, bad_instruction)
131 TRAP_ENTRY(0x3, priv_instruction)
132 TRAP_ENTRY(0x4, fpd_trap_handler)
133 WINDOW_SPILL
134 WINDOW_FILL
135 TRAP_ENTRY(0x7, mna_handler)
136 TRAP_ENTRY(0x8, fpe_trap_handler)
137 SRMMU_DFAULT
138 TRAP_ENTRY(0xa, do_tag_overflow)
139 TRAP_ENTRY(0xb, do_watchpoint)
140 BAD_TRAP(0xc) BAD_TRAP(0xd) BAD_TRAP(0xe) BAD_TRAP(0xf) BAD_TRAP(0x10)
141 TRAP_ENTRY_INTERRUPT(1) TRAP_ENTRY_INTERRUPT(2)
142 TRAP_ENTRY_INTERRUPT(3) TRAP_ENTRY_INTERRUPT(4)
143 TRAP_ENTRY_INTERRUPT(5) TRAP_ENTRY_INTERRUPT(6)
144 TRAP_ENTRY_INTERRUPT(7) TRAP_ENTRY_INTERRUPT(8)
145 TRAP_ENTRY_INTERRUPT(9) TRAP_ENTRY_INTERRUPT(10)
146 TRAP_ENTRY_INTERRUPT(11) TRAP_ENTRY_INTERRUPT(12)
147 TRAP_ENTRY_INTERRUPT(13) TRAP_ENTRY_INTERRUPT(14)
148 TRAP_ENTRY(0x1f, linux_trap_ipi15_sun4m)
149 TRAP_ENTRY(0x20, do_reg_access)
150 BAD_TRAP(0x21)
151 BAD_TRAP(0x22)
152 BAD_TRAP(0x23)
153 TRAP_ENTRY(0x24, do_cp_disabled)
154 SKIP_TRAP(0x25, unimp_flush)
155 BAD_TRAP(0x26)
156 BAD_TRAP(0x27)
157 TRAP_ENTRY(0x28, do_cp_exception)
158 SRMMU_DFAULT
159 TRAP_ENTRY(0x2a, do_hw_divzero)
160 BAD_TRAP(0x2b)
161 BAD_TRAP(0x2c)
162 BAD_TRAP(0x2d) BAD_TRAP(0x2e) BAD_TRAP(0x2f) BAD_TRAP(0x30) BAD_TRAP(0x31)
163 BAD_TRAP(0x32) BAD_TRAP(0x33) BAD_TRAP(0x34) BAD_TRAP(0x35) BAD_TRAP(0x36)
164 BAD_TRAP(0x37) BAD_TRAP(0x38) BAD_TRAP(0x39) BAD_TRAP(0x3a) BAD_TRAP(0x3b)
165 BAD_TRAP(0x3c) BAD_TRAP(0x3d) BAD_TRAP(0x3e) BAD_TRAP(0x3f) BAD_TRAP(0x40)
166 BAD_TRAP(0x41) BAD_TRAP(0x42) BAD_TRAP(0x43) BAD_TRAP(0x44) BAD_TRAP(0x45)
167 BAD_TRAP(0x46) BAD_TRAP(0x47) BAD_TRAP(0x48) BAD_TRAP(0x49) BAD_TRAP(0x4a)
168 BAD_TRAP(0x4b) BAD_TRAP(0x4c) BAD_TRAP(0x4d) BAD_TRAP(0x4e) BAD_TRAP(0x4f)
169 BAD_TRAP(0x50)
170 BAD_TRAP(0x51) BAD_TRAP(0x52) BAD_TRAP(0x53) BAD_TRAP(0x54) BAD_TRAP(0x55)
171 BAD_TRAP(0x56) BAD_TRAP(0x57) BAD_TRAP(0x58) BAD_TRAP(0x59) BAD_TRAP(0x5a)
172 BAD_TRAP(0x5b) BAD_TRAP(0x5c) BAD_TRAP(0x5d) BAD_TRAP(0x5e) BAD_TRAP(0x5f)
173 BAD_TRAP(0x60) BAD_TRAP(0x61) BAD_TRAP(0x62) BAD_TRAP(0x63) BAD_TRAP(0x64)
174 BAD_TRAP(0x65) BAD_TRAP(0x66) BAD_TRAP(0x67) BAD_TRAP(0x68) BAD_TRAP(0x69)
175 BAD_TRAP(0x6a) BAD_TRAP(0x6b) BAD_TRAP(0x6c) BAD_TRAP(0x6d) BAD_TRAP(0x6e)
176 BAD_TRAP(0x6f) BAD_TRAP(0x70) BAD_TRAP(0x71) BAD_TRAP(0x72) BAD_TRAP(0x73)
177 BAD_TRAP(0x74) BAD_TRAP(0x75) BAD_TRAP(0x76) BAD_TRAP(0x77) BAD_TRAP(0x78)
178 BAD_TRAP(0x79) BAD_TRAP(0x7a) BAD_TRAP(0x7b) BAD_TRAP(0x7c) BAD_TRAP(0x7d)
179 BAD_TRAP(0x7e) BAD_TRAP(0x7f)
180 BAD_TRAP(0x80)
181 BREAKPOINT_TRAP
182 TRAP_ENTRY(0x82, do_hw_divzero)
183 TRAP_ENTRY(0x83, do_flush_windows)
184 BAD_TRAP(0x84) BAD_TRAP(0x85) BAD_TRAP(0x86)
185 BAD_TRAP(0x87) BAD_TRAP(0x88) BAD_TRAP(0x89)
186 BAD_TRAP(0x8a) BAD_TRAP(0x8b) BAD_TRAP(0x8c)
187 BAD_TRAP(0x8d) BAD_TRAP(0x8e) BAD_TRAP(0x8f)
188 LINUX_SYSCALL_TRAP BAD_TRAP(0x91)
189 BAD_TRAP(0x92) BAD_TRAP(0x93) BAD_TRAP(0x94)
190 BAD_TRAP(0x95) BAD_TRAP(0x96) BAD_TRAP(0x97) BAD_TRAP(0x98) BAD_TRAP(0x99)
191 BAD_TRAP(0x9a) BAD_TRAP(0x9b) BAD_TRAP(0x9c) BAD_TRAP(0x9d) BAD_TRAP(0x9e)
192 BAD_TRAP(0x9f)
193 GETCC_TRAP
194 SETCC_TRAP
195 GETPSR_TRAP
196 BAD_TRAP(0xa3) BAD_TRAP(0xa4) BAD_TRAP(0xa5) BAD_TRAP(0xa6)
197 BAD_TRAP(0xa7) BAD_TRAP(0xa8) BAD_TRAP(0xa9) BAD_TRAP(0xaa) BAD_TRAP(0xab)
198 BAD_TRAP(0xac) BAD_TRAP(0xad) BAD_TRAP(0xae) BAD_TRAP(0xaf) BAD_TRAP(0xb0)
199 BAD_TRAP(0xb1) BAD_TRAP(0xb2) BAD_TRAP(0xb3) BAD_TRAP(0xb4) BAD_TRAP(0xb5)
200 BAD_TRAP(0xb6) BAD_TRAP(0xb7) BAD_TRAP(0xb8) BAD_TRAP(0xb9) BAD_TRAP(0xba)
201 BAD_TRAP(0xbb) BAD_TRAP(0xbc) BAD_TRAP(0xbd) BAD_TRAP(0xbe) BAD_TRAP(0xbf)
202 BAD_TRAP(0xc0) BAD_TRAP(0xc1) BAD_TRAP(0xc2) BAD_TRAP(0xc3) BAD_TRAP(0xc4)
203 BAD_TRAP(0xc5) BAD_TRAP(0xc6) BAD_TRAP(0xc7) BAD_TRAP(0xc8) BAD_TRAP(0xc9)
204 BAD_TRAP(0xca) BAD_TRAP(0xcb) BAD_TRAP(0xcc) BAD_TRAP(0xcd) BAD_TRAP(0xce)
205 BAD_TRAP(0xcf) BAD_TRAP(0xd0) BAD_TRAP(0xd1) BAD_TRAP(0xd2) BAD_TRAP(0xd3)
206 BAD_TRAP(0xd4) BAD_TRAP(0xd5) BAD_TRAP(0xd6) BAD_TRAP(0xd7) BAD_TRAP(0xd8)
207 BAD_TRAP(0xd9) BAD_TRAP(0xda) BAD_TRAP(0xdb) BAD_TRAP(0xdc) BAD_TRAP(0xdd)
208 BAD_TRAP(0xde) BAD_TRAP(0xdf) BAD_TRAP(0xe0) BAD_TRAP(0xe1) BAD_TRAP(0xe2)
209 BAD_TRAP(0xe3) BAD_TRAP(0xe4) BAD_TRAP(0xe5) BAD_TRAP(0xe6) BAD_TRAP(0xe7)
210 BAD_TRAP(0xe8) BAD_TRAP(0xe9) BAD_TRAP(0xea) BAD_TRAP(0xeb) BAD_TRAP(0xec)
211 BAD_TRAP(0xed) BAD_TRAP(0xee) BAD_TRAP(0xef) BAD_TRAP(0xf0) BAD_TRAP(0xf1)
212 BAD_TRAP(0xf2) BAD_TRAP(0xf3) BAD_TRAP(0xf4) BAD_TRAP(0xf5) BAD_TRAP(0xf6)
213 BAD_TRAP(0xf7) BAD_TRAP(0xf8) BAD_TRAP(0xf9) BAD_TRAP(0xfa) BAD_TRAP(0xfb)
214 BAD_TRAP(0xfc)
215 KGDB_TRAP(0xfd)
216 BAD_TRAP(0xfe)
217 BAD_TRAP(0xff)
218
219trapbase_cpu2:
220 BAD_TRAP(0x0)
221 SRMMU_TFAULT
222 TRAP_ENTRY(0x2, bad_instruction)
223 TRAP_ENTRY(0x3, priv_instruction)
224 TRAP_ENTRY(0x4, fpd_trap_handler)
225 WINDOW_SPILL
226 WINDOW_FILL
227 TRAP_ENTRY(0x7, mna_handler)
228 TRAP_ENTRY(0x8, fpe_trap_handler)
229 SRMMU_DFAULT
230 TRAP_ENTRY(0xa, do_tag_overflow)
231 TRAP_ENTRY(0xb, do_watchpoint)
232 BAD_TRAP(0xc) BAD_TRAP(0xd) BAD_TRAP(0xe) BAD_TRAP(0xf) BAD_TRAP(0x10)
233 TRAP_ENTRY_INTERRUPT(1)
234 TRAP_ENTRY_INTERRUPT(2)
235 TRAP_ENTRY_INTERRUPT(3)
236 TRAP_ENTRY_INTERRUPT(4)
237 TRAP_ENTRY_INTERRUPT(5)
238 TRAP_ENTRY_INTERRUPT(6)
239 TRAP_ENTRY_INTERRUPT(7)
240 TRAP_ENTRY_INTERRUPT(8)
241 TRAP_ENTRY_INTERRUPT(9)
242 TRAP_ENTRY_INTERRUPT(10)
243 TRAP_ENTRY_INTERRUPT(11)
244 TRAP_ENTRY_INTERRUPT(12)
245 TRAP_ENTRY_INTERRUPT(13)
246 TRAP_ENTRY_INTERRUPT(14)
247 TRAP_ENTRY(0x1f, linux_trap_ipi15_sun4m)
248 TRAP_ENTRY(0x20, do_reg_access)
249 BAD_TRAP(0x21)
250 BAD_TRAP(0x22)
251 BAD_TRAP(0x23)
252 TRAP_ENTRY(0x24, do_cp_disabled)
253 SKIP_TRAP(0x25, unimp_flush)
254 BAD_TRAP(0x26)
255 BAD_TRAP(0x27)
256 TRAP_ENTRY(0x28, do_cp_exception)
257 SRMMU_DFAULT
258 TRAP_ENTRY(0x2a, do_hw_divzero)
259 BAD_TRAP(0x2b)
260 BAD_TRAP(0x2c)
261 BAD_TRAP(0x2d) BAD_TRAP(0x2e) BAD_TRAP(0x2f) BAD_TRAP(0x30) BAD_TRAP(0x31)
262 BAD_TRAP(0x32) BAD_TRAP(0x33) BAD_TRAP(0x34) BAD_TRAP(0x35) BAD_TRAP(0x36)
263 BAD_TRAP(0x37) BAD_TRAP(0x38) BAD_TRAP(0x39) BAD_TRAP(0x3a) BAD_TRAP(0x3b)
264 BAD_TRAP(0x3c) BAD_TRAP(0x3d) BAD_TRAP(0x3e) BAD_TRAP(0x3f) BAD_TRAP(0x40)
265 BAD_TRAP(0x41) BAD_TRAP(0x42) BAD_TRAP(0x43) BAD_TRAP(0x44) BAD_TRAP(0x45)
266 BAD_TRAP(0x46) BAD_TRAP(0x47) BAD_TRAP(0x48) BAD_TRAP(0x49) BAD_TRAP(0x4a)
267 BAD_TRAP(0x4b) BAD_TRAP(0x4c) BAD_TRAP(0x4d) BAD_TRAP(0x4e) BAD_TRAP(0x4f)
268 BAD_TRAP(0x50)
269 BAD_TRAP(0x51) BAD_TRAP(0x52) BAD_TRAP(0x53) BAD_TRAP(0x54) BAD_TRAP(0x55)
270 BAD_TRAP(0x56) BAD_TRAP(0x57) BAD_TRAP(0x58) BAD_TRAP(0x59) BAD_TRAP(0x5a)
271 BAD_TRAP(0x5b) BAD_TRAP(0x5c) BAD_TRAP(0x5d) BAD_TRAP(0x5e) BAD_TRAP(0x5f)
272 BAD_TRAP(0x60) BAD_TRAP(0x61) BAD_TRAP(0x62) BAD_TRAP(0x63) BAD_TRAP(0x64)
273 BAD_TRAP(0x65) BAD_TRAP(0x66) BAD_TRAP(0x67) BAD_TRAP(0x68) BAD_TRAP(0x69)
274 BAD_TRAP(0x6a) BAD_TRAP(0x6b) BAD_TRAP(0x6c) BAD_TRAP(0x6d) BAD_TRAP(0x6e)
275 BAD_TRAP(0x6f) BAD_TRAP(0x70) BAD_TRAP(0x71) BAD_TRAP(0x72) BAD_TRAP(0x73)
276 BAD_TRAP(0x74) BAD_TRAP(0x75) BAD_TRAP(0x76) BAD_TRAP(0x77) BAD_TRAP(0x78)
277 BAD_TRAP(0x79) BAD_TRAP(0x7a) BAD_TRAP(0x7b) BAD_TRAP(0x7c) BAD_TRAP(0x7d)
278 BAD_TRAP(0x7e) BAD_TRAP(0x7f)
279 BAD_TRAP(0x80)
280 BREAKPOINT_TRAP
281 TRAP_ENTRY(0x82, do_hw_divzero)
282 TRAP_ENTRY(0x83, do_flush_windows)
283 BAD_TRAP(0x84)
284 BAD_TRAP(0x85)
285 BAD_TRAP(0x86) BAD_TRAP(0x87) BAD_TRAP(0x88)
286 BAD_TRAP(0x89) BAD_TRAP(0x8a) BAD_TRAP(0x8b) BAD_TRAP(0x8c)
287 BAD_TRAP(0x8d) BAD_TRAP(0x8e) BAD_TRAP(0x8f)
288 LINUX_SYSCALL_TRAP BAD_TRAP(0x91)
289 BAD_TRAP(0x92) BAD_TRAP(0x93) BAD_TRAP(0x94)
290 BAD_TRAP(0x95) BAD_TRAP(0x96) BAD_TRAP(0x97) BAD_TRAP(0x98) BAD_TRAP(0x99)
291 BAD_TRAP(0x9a) BAD_TRAP(0x9b) BAD_TRAP(0x9c) BAD_TRAP(0x9d) BAD_TRAP(0x9e)
292 BAD_TRAP(0x9f)
293 GETCC_TRAP
294 SETCC_TRAP
295 GETPSR_TRAP
296 BAD_TRAP(0xa3) BAD_TRAP(0xa4) BAD_TRAP(0xa5) BAD_TRAP(0xa6)
297 BAD_TRAP(0xa7) BAD_TRAP(0xa8) BAD_TRAP(0xa9) BAD_TRAP(0xaa) BAD_TRAP(0xab)
298 BAD_TRAP(0xac) BAD_TRAP(0xad) BAD_TRAP(0xae) BAD_TRAP(0xaf) BAD_TRAP(0xb0)
299 BAD_TRAP(0xb1) BAD_TRAP(0xb2) BAD_TRAP(0xb3) BAD_TRAP(0xb4) BAD_TRAP(0xb5)
300 BAD_TRAP(0xb6) BAD_TRAP(0xb7) BAD_TRAP(0xb8) BAD_TRAP(0xb9) BAD_TRAP(0xba)
301 BAD_TRAP(0xbb) BAD_TRAP(0xbc) BAD_TRAP(0xbd) BAD_TRAP(0xbe) BAD_TRAP(0xbf)
302 BAD_TRAP(0xc0) BAD_TRAP(0xc1) BAD_TRAP(0xc2) BAD_TRAP(0xc3) BAD_TRAP(0xc4)
303 BAD_TRAP(0xc5) BAD_TRAP(0xc6) BAD_TRAP(0xc7) BAD_TRAP(0xc8) BAD_TRAP(0xc9)
304 BAD_TRAP(0xca) BAD_TRAP(0xcb) BAD_TRAP(0xcc) BAD_TRAP(0xcd) BAD_TRAP(0xce)
305 BAD_TRAP(0xcf) BAD_TRAP(0xd0) BAD_TRAP(0xd1) BAD_TRAP(0xd2) BAD_TRAP(0xd3)
306 BAD_TRAP(0xd4) BAD_TRAP(0xd5) BAD_TRAP(0xd6) BAD_TRAP(0xd7) BAD_TRAP(0xd8)
307 BAD_TRAP(0xd9) BAD_TRAP(0xda) BAD_TRAP(0xdb) BAD_TRAP(0xdc) BAD_TRAP(0xdd)
308 BAD_TRAP(0xde) BAD_TRAP(0xdf) BAD_TRAP(0xe0) BAD_TRAP(0xe1) BAD_TRAP(0xe2)
309 BAD_TRAP(0xe3) BAD_TRAP(0xe4) BAD_TRAP(0xe5) BAD_TRAP(0xe6) BAD_TRAP(0xe7)
310 BAD_TRAP(0xe8) BAD_TRAP(0xe9) BAD_TRAP(0xea) BAD_TRAP(0xeb) BAD_TRAP(0xec)
311 BAD_TRAP(0xed) BAD_TRAP(0xee) BAD_TRAP(0xef) BAD_TRAP(0xf0) BAD_TRAP(0xf1)
312 BAD_TRAP(0xf2) BAD_TRAP(0xf3) BAD_TRAP(0xf4) BAD_TRAP(0xf5) BAD_TRAP(0xf6)
313 BAD_TRAP(0xf7) BAD_TRAP(0xf8) BAD_TRAP(0xf9) BAD_TRAP(0xfa) BAD_TRAP(0xfb)
314 BAD_TRAP(0xfc)
315 KGDB_TRAP(0xfd)
316 BAD_TRAP(0xfe)
317 BAD_TRAP(0xff)
318
319trapbase_cpu3:
320 BAD_TRAP(0x0)
321 SRMMU_TFAULT
322 TRAP_ENTRY(0x2, bad_instruction)
323 TRAP_ENTRY(0x3, priv_instruction)
324 TRAP_ENTRY(0x4, fpd_trap_handler)
325 WINDOW_SPILL
326 WINDOW_FILL
327 TRAP_ENTRY(0x7, mna_handler)
328 TRAP_ENTRY(0x8, fpe_trap_handler)
329 SRMMU_DFAULT
330 TRAP_ENTRY(0xa, do_tag_overflow)
331 TRAP_ENTRY(0xb, do_watchpoint)
332 BAD_TRAP(0xc) BAD_TRAP(0xd) BAD_TRAP(0xe) BAD_TRAP(0xf) BAD_TRAP(0x10)
333 TRAP_ENTRY_INTERRUPT(1)
334 TRAP_ENTRY_INTERRUPT(2)
335 TRAP_ENTRY_INTERRUPT(3)
336 TRAP_ENTRY_INTERRUPT(4)
337 TRAP_ENTRY_INTERRUPT(5)
338 TRAP_ENTRY_INTERRUPT(6)
339 TRAP_ENTRY_INTERRUPT(7)
340 TRAP_ENTRY_INTERRUPT(8)
341 TRAP_ENTRY_INTERRUPT(9)
342 TRAP_ENTRY_INTERRUPT(10)
343 TRAP_ENTRY_INTERRUPT(11)
344 TRAP_ENTRY_INTERRUPT(12)
345 TRAP_ENTRY_INTERRUPT(13)
346 TRAP_ENTRY_INTERRUPT(14)
347 TRAP_ENTRY(0x1f, linux_trap_ipi15_sun4m)
348 TRAP_ENTRY(0x20, do_reg_access)
349 BAD_TRAP(0x21)
350 BAD_TRAP(0x22)
351 BAD_TRAP(0x23)
352 TRAP_ENTRY(0x24, do_cp_disabled)
353 SKIP_TRAP(0x25, unimp_flush)
354 BAD_TRAP(0x26)
355 BAD_TRAP(0x27)
356 TRAP_ENTRY(0x28, do_cp_exception)
357 SRMMU_DFAULT
358 TRAP_ENTRY(0x2a, do_hw_divzero)
359 BAD_TRAP(0x2b) BAD_TRAP(0x2c)
360 BAD_TRAP(0x2d) BAD_TRAP(0x2e) BAD_TRAP(0x2f) BAD_TRAP(0x30) BAD_TRAP(0x31)
361 BAD_TRAP(0x32) BAD_TRAP(0x33) BAD_TRAP(0x34) BAD_TRAP(0x35) BAD_TRAP(0x36)
362 BAD_TRAP(0x37) BAD_TRAP(0x38) BAD_TRAP(0x39) BAD_TRAP(0x3a) BAD_TRAP(0x3b)
363 BAD_TRAP(0x3c) BAD_TRAP(0x3d) BAD_TRAP(0x3e) BAD_TRAP(0x3f) BAD_TRAP(0x40)
364 BAD_TRAP(0x41) BAD_TRAP(0x42) BAD_TRAP(0x43) BAD_TRAP(0x44) BAD_TRAP(0x45)
365 BAD_TRAP(0x46) BAD_TRAP(0x47) BAD_TRAP(0x48) BAD_TRAP(0x49) BAD_TRAP(0x4a)
366 BAD_TRAP(0x4b) BAD_TRAP(0x4c) BAD_TRAP(0x4d) BAD_TRAP(0x4e) BAD_TRAP(0x4f)
367 BAD_TRAP(0x50)
368 BAD_TRAP(0x51) BAD_TRAP(0x52) BAD_TRAP(0x53) BAD_TRAP(0x54) BAD_TRAP(0x55)
369 BAD_TRAP(0x56) BAD_TRAP(0x57) BAD_TRAP(0x58) BAD_TRAP(0x59) BAD_TRAP(0x5a)
370 BAD_TRAP(0x5b) BAD_TRAP(0x5c) BAD_TRAP(0x5d) BAD_TRAP(0x5e) BAD_TRAP(0x5f)
371 BAD_TRAP(0x60) BAD_TRAP(0x61) BAD_TRAP(0x62) BAD_TRAP(0x63) BAD_TRAP(0x64)
372 BAD_TRAP(0x65) BAD_TRAP(0x66) BAD_TRAP(0x67) BAD_TRAP(0x68) BAD_TRAP(0x69)
373 BAD_TRAP(0x6a) BAD_TRAP(0x6b) BAD_TRAP(0x6c) BAD_TRAP(0x6d) BAD_TRAP(0x6e)
374 BAD_TRAP(0x6f) BAD_TRAP(0x70) BAD_TRAP(0x71) BAD_TRAP(0x72) BAD_TRAP(0x73)
375 BAD_TRAP(0x74) BAD_TRAP(0x75) BAD_TRAP(0x76) BAD_TRAP(0x77) BAD_TRAP(0x78)
376 BAD_TRAP(0x79) BAD_TRAP(0x7a) BAD_TRAP(0x7b) BAD_TRAP(0x7c) BAD_TRAP(0x7d)
377 BAD_TRAP(0x7e) BAD_TRAP(0x7f)
378 BAD_TRAP(0x80)
379 BREAKPOINT_TRAP
380 TRAP_ENTRY(0x82, do_hw_divzero)
381 TRAP_ENTRY(0x83, do_flush_windows)
382 BAD_TRAP(0x84) BAD_TRAP(0x85)
383 BAD_TRAP(0x86) BAD_TRAP(0x87) BAD_TRAP(0x88)
384 BAD_TRAP(0x89) BAD_TRAP(0x8a) BAD_TRAP(0x8b) BAD_TRAP(0x8c)
385 BAD_TRAP(0x8d) BAD_TRAP(0x8e) BAD_TRAP(0x8f)
386 LINUX_SYSCALL_TRAP
387 BAD_TRAP(0x91) BAD_TRAP(0x92) BAD_TRAP(0x93) BAD_TRAP(0x94)
388 BAD_TRAP(0x95) BAD_TRAP(0x96) BAD_TRAP(0x97) BAD_TRAP(0x98) BAD_TRAP(0x99)
389 BAD_TRAP(0x9a) BAD_TRAP(0x9b) BAD_TRAP(0x9c) BAD_TRAP(0x9d) BAD_TRAP(0x9e)
390 BAD_TRAP(0x9f)
391 GETCC_TRAP
392 SETCC_TRAP
393 GETPSR_TRAP
394 BAD_TRAP(0xa3) BAD_TRAP(0xa4) BAD_TRAP(0xa5) BAD_TRAP(0xa6)
395 BAD_TRAP(0xa7) BAD_TRAP(0xa8) BAD_TRAP(0xa9) BAD_TRAP(0xaa) BAD_TRAP(0xab)
396 BAD_TRAP(0xac) BAD_TRAP(0xad) BAD_TRAP(0xae) BAD_TRAP(0xaf) BAD_TRAP(0xb0)
397 BAD_TRAP(0xb1) BAD_TRAP(0xb2) BAD_TRAP(0xb3) BAD_TRAP(0xb4) BAD_TRAP(0xb5)
398 BAD_TRAP(0xb6) BAD_TRAP(0xb7) BAD_TRAP(0xb8) BAD_TRAP(0xb9) BAD_TRAP(0xba)
399 BAD_TRAP(0xbb) BAD_TRAP(0xbc) BAD_TRAP(0xbd) BAD_TRAP(0xbe) BAD_TRAP(0xbf)
400 BAD_TRAP(0xc0) BAD_TRAP(0xc1) BAD_TRAP(0xc2) BAD_TRAP(0xc3) BAD_TRAP(0xc4)
401 BAD_TRAP(0xc5) BAD_TRAP(0xc6) BAD_TRAP(0xc7) BAD_TRAP(0xc8) BAD_TRAP(0xc9)
402 BAD_TRAP(0xca) BAD_TRAP(0xcb) BAD_TRAP(0xcc) BAD_TRAP(0xcd) BAD_TRAP(0xce)
403 BAD_TRAP(0xcf) BAD_TRAP(0xd0) BAD_TRAP(0xd1) BAD_TRAP(0xd2) BAD_TRAP(0xd3)
404 BAD_TRAP(0xd4) BAD_TRAP(0xd5) BAD_TRAP(0xd6) BAD_TRAP(0xd7) BAD_TRAP(0xd8)
405 BAD_TRAP(0xd9) BAD_TRAP(0xda) BAD_TRAP(0xdb) BAD_TRAP(0xdc) BAD_TRAP(0xdd)
406 BAD_TRAP(0xde) BAD_TRAP(0xdf) BAD_TRAP(0xe0) BAD_TRAP(0xe1) BAD_TRAP(0xe2)
407 BAD_TRAP(0xe3) BAD_TRAP(0xe4) BAD_TRAP(0xe5) BAD_TRAP(0xe6) BAD_TRAP(0xe7)
408 BAD_TRAP(0xe8) BAD_TRAP(0xe9) BAD_TRAP(0xea) BAD_TRAP(0xeb) BAD_TRAP(0xec)
409 BAD_TRAP(0xed) BAD_TRAP(0xee) BAD_TRAP(0xef) BAD_TRAP(0xf0) BAD_TRAP(0xf1)
410 BAD_TRAP(0xf2) BAD_TRAP(0xf3) BAD_TRAP(0xf4) BAD_TRAP(0xf5) BAD_TRAP(0xf6)
411 BAD_TRAP(0xf7) BAD_TRAP(0xf8) BAD_TRAP(0xf9) BAD_TRAP(0xfa) BAD_TRAP(0xfb)
412 BAD_TRAP(0xfc)
413 KGDB_TRAP(0xfd)
414 BAD_TRAP(0xfe)
415 BAD_TRAP(0xff)
416
417#endif
diff --git a/arch/sparc/kernel/ttable.S b/arch/sparc/kernel/ttable_64.S
index c6dfdaa29e20..c6dfdaa29e20 100644
--- a/arch/sparc/kernel/ttable.S
+++ b/arch/sparc/kernel/ttable_64.S
diff --git a/arch/sparc/kernel/unaligned_64.c b/arch/sparc/kernel/unaligned_64.c
index dae85bc2eda5..f81d038f7340 100644
--- a/arch/sparc/kernel/unaligned_64.c
+++ b/arch/sparc/kernel/unaligned_64.c
@@ -21,7 +21,6 @@
21#include <linux/bitops.h> 21#include <linux/bitops.h>
22#include <linux/perf_event.h> 22#include <linux/perf_event.h>
23#include <linux/ratelimit.h> 23#include <linux/ratelimit.h>
24#include <linux/bitops.h>
25#include <asm/fpumacro.h> 24#include <asm/fpumacro.h>
26#include <asm/cacheflush.h> 25#include <asm/cacheflush.h>
27 26
diff --git a/arch/sparc/kernel/wof.S b/arch/sparc/kernel/wof.S
index 3bbcd8dc9abf..4c2de3cf309b 100644
--- a/arch/sparc/kernel/wof.S
+++ b/arch/sparc/kernel/wof.S
@@ -163,9 +163,8 @@ spwin_fromuser:
163 * the label 'spwin_user_stack_is_bolixed' which will take 163 * the label 'spwin_user_stack_is_bolixed' which will take
164 * care of things at that point. 164 * care of things at that point.
165 */ 165 */
166 .globl spwin_mmu_patchme 166 b spwin_srmmu_stackchk
167spwin_mmu_patchme: b spwin_sun4c_stackchk 167 andcc %sp, 0x7, %g0
168 andcc %sp, 0x7, %g0
169 168
170spwin_good_ustack: 169spwin_good_ustack:
171 /* LOCATION: Window to be saved */ 170 /* LOCATION: Window to be saved */
@@ -306,73 +305,6 @@ spwin_bad_ustack_from_kernel:
306 * As noted above %curptr cannot be touched by this routine at all. 305 * As noted above %curptr cannot be touched by this routine at all.
307 */ 306 */
308 307
309spwin_sun4c_stackchk:
310 /* LOCATION: Window to be saved on the stack */
311
312 /* See if the stack is in the address space hole but first,
313 * check results of callers andcc %sp, 0x7, %g0
314 */
315 be 1f
316 sra %sp, 29, %glob_tmp
317
318 rd %psr, %glob_tmp
319 b spwin_user_stack_is_bolixed + 0x4
320 nop
321
3221:
323 add %glob_tmp, 0x1, %glob_tmp
324 andncc %glob_tmp, 0x1, %g0
325 be 1f
326 and %sp, 0xfff, %glob_tmp ! delay slot
327
328 rd %psr, %glob_tmp
329 b spwin_user_stack_is_bolixed + 0x4
330 nop
331
332 /* See if our dump area will be on more than one
333 * page.
334 */
3351:
336 add %glob_tmp, 0x38, %glob_tmp
337 andncc %glob_tmp, 0xff8, %g0
338 be spwin_sun4c_onepage ! only one page to check
339 lda [%sp] ASI_PTE, %glob_tmp ! have to check first page anyways
340
341spwin_sun4c_twopages:
342 /* Is first page ok permission wise? */
343 srl %glob_tmp, 29, %glob_tmp
344 cmp %glob_tmp, 0x6
345 be 1f
346 add %sp, 0x38, %glob_tmp /* Is second page in vma hole? */
347
348 rd %psr, %glob_tmp
349 b spwin_user_stack_is_bolixed + 0x4
350 nop
351
3521:
353 sra %glob_tmp, 29, %glob_tmp
354 add %glob_tmp, 0x1, %glob_tmp
355 andncc %glob_tmp, 0x1, %g0
356 be 1f
357 add %sp, 0x38, %glob_tmp
358
359 rd %psr, %glob_tmp
360 b spwin_user_stack_is_bolixed + 0x4
361 nop
362
3631:
364 lda [%glob_tmp] ASI_PTE, %glob_tmp
365
366spwin_sun4c_onepage:
367 srl %glob_tmp, 29, %glob_tmp
368 cmp %glob_tmp, 0x6 ! can user write to it?
369 be spwin_good_ustack ! success
370 nop
371
372 rd %psr, %glob_tmp
373 b spwin_user_stack_is_bolixed + 0x4
374 nop
375
376 /* This is a generic SRMMU routine. As far as I know this 308 /* This is a generic SRMMU routine. As far as I know this
377 * works for all current v8/srmmu implementations, we'll 309 * works for all current v8/srmmu implementations, we'll
378 * see... 310 * see...
diff --git a/arch/sparc/kernel/wuf.S b/arch/sparc/kernel/wuf.S
index 779ff750603d..9fde91a249e0 100644
--- a/arch/sparc/kernel/wuf.S
+++ b/arch/sparc/kernel/wuf.S
@@ -131,12 +131,9 @@ fwin_from_user:
131 131
132 /* LOCATION: Window 'W' */ 132 /* LOCATION: Window 'W' */
133 133
134 /* Branch to the architecture specific stack validation 134 /* Branch to the stack validation routine */
135 * routine. They can be found below... 135 b srmmu_fwin_stackchk
136 */ 136 andcc %sp, 0x7, %g0
137 .globl fwin_mmu_patchme
138fwin_mmu_patchme: b sun4c_fwin_stackchk
139 andcc %sp, 0x7, %g0
140 137
141#define STACK_OFFSET (THREAD_SIZE - TRACEREG_SZ - STACKFRAME_SZ) 138#define STACK_OFFSET (THREAD_SIZE - TRACEREG_SZ - STACKFRAME_SZ)
142 139
@@ -242,57 +239,6 @@ fwin_user_finish_up:
242 * 'someone elses' window possibly. 239 * 'someone elses' window possibly.
243 */ 240 */
244 241
245 .align 4
246sun4c_fwin_stackchk:
247 /* LOCATION: Window 'W' */
248
249 /* Caller did 'andcc %sp, 0x7, %g0' */
250 be 1f
251 and %sp, 0xfff, %l0 ! delay slot
252
253 b,a fwin_user_stack_is_bolixed
254
255 /* See if we have to check the sanity of one page or two */
2561:
257 add %l0, 0x38, %l0
258 sra %sp, 29, %l5
259 add %l5, 0x1, %l5
260 andncc %l5, 0x1, %g0
261 be 1f
262 andncc %l0, 0xff8, %g0
263
264 b,a fwin_user_stack_is_bolixed /* %sp is in vma hole, yuck */
265
2661:
267 be sun4c_fwin_onepage /* Only one page to check */
268 lda [%sp] ASI_PTE, %l1
269sun4c_fwin_twopages:
270 add %sp, 0x38, %l0
271 sra %l0, 29, %l5
272 add %l5, 0x1, %l5
273 andncc %l5, 0x1, %g0
274 be 1f
275 lda [%l0] ASI_PTE, %l1
276
277 b,a fwin_user_stack_is_bolixed /* Second page in vma hole */
278
2791:
280 srl %l1, 29, %l1
281 andcc %l1, 0x4, %g0
282 bne sun4c_fwin_onepage
283 lda [%sp] ASI_PTE, %l1
284
285 b,a fwin_user_stack_is_bolixed /* Second page has bad perms */
286
287sun4c_fwin_onepage:
288 srl %l1, 29, %l1
289 andcc %l1, 0x4, %g0
290 bne fwin_user_stack_is_ok
291 nop
292
293 /* A page had bad page permissions, losing... */
294 b,a fwin_user_stack_is_bolixed
295
296 .globl srmmu_fwin_stackchk 242 .globl srmmu_fwin_stackchk
297srmmu_fwin_stackchk: 243srmmu_fwin_stackchk:
298 /* LOCATION: Window 'W' */ 244 /* LOCATION: Window 'W' */
diff --git a/arch/sparc/lib/Makefile b/arch/sparc/lib/Makefile
index a3fc4375a150..389628f50a15 100644
--- a/arch/sparc/lib/Makefile
+++ b/arch/sparc/lib/Makefile
@@ -4,7 +4,7 @@
4asflags-y := -ansi -DST_DIV0=0x02 4asflags-y := -ansi -DST_DIV0=0x02
5ccflags-y := -Werror 5ccflags-y := -Werror
6 6
7lib-$(CONFIG_SPARC32) += mul.o rem.o sdiv.o udiv.o umul.o urem.o ashrdi3.o 7lib-$(CONFIG_SPARC32) += ashrdi3.o
8lib-$(CONFIG_SPARC32) += memcpy.o memset.o 8lib-$(CONFIG_SPARC32) += memcpy.o memset.o
9lib-y += strlen.o 9lib-y += strlen.o
10lib-y += checksum_$(BITS).o 10lib-y += checksum_$(BITS).o
@@ -13,7 +13,7 @@ lib-y += memscan_$(BITS).o memcmp.o strncmp_$(BITS).o
13lib-y += strncpy_from_user_$(BITS).o strlen_user_$(BITS).o 13lib-y += strncpy_from_user_$(BITS).o strlen_user_$(BITS).o
14lib-$(CONFIG_SPARC32) += divdi3.o udivdi3.o 14lib-$(CONFIG_SPARC32) += divdi3.o udivdi3.o
15lib-$(CONFIG_SPARC32) += copy_user.o locks.o 15lib-$(CONFIG_SPARC32) += copy_user.o locks.o
16lib-y += atomic_$(BITS).o 16lib-$(CONFIG_SPARC64) += atomic_64.o
17lib-$(CONFIG_SPARC32) += lshrdi3.o ashldi3.o 17lib-$(CONFIG_SPARC32) += lshrdi3.o ashldi3.o
18lib-$(CONFIG_SPARC32) += muldi3.o bitext.o cmpdi2.o 18lib-$(CONFIG_SPARC32) += muldi3.o bitext.o cmpdi2.o
19 19
@@ -40,7 +40,7 @@ lib-$(CONFIG_SPARC64) += copy_in_user.o user_fixup.o memmove.o
40lib-$(CONFIG_SPARC64) += mcount.o ipcsum.o xor.o hweight.o ffs.o 40lib-$(CONFIG_SPARC64) += mcount.o ipcsum.o xor.o hweight.o ffs.o
41 41
42obj-y += iomap.o 42obj-y += iomap.o
43obj-$(CONFIG_SPARC32) += atomic32.o 43obj-$(CONFIG_SPARC32) += atomic32.o ucmpdi2.o
44obj-y += ksyms.o 44obj-y += ksyms.o
45obj-$(CONFIG_SPARC64) += PeeCeeI.o 45obj-$(CONFIG_SPARC64) += PeeCeeI.o
46obj-y += usercopy.o 46obj-y += usercopy.o
diff --git a/arch/sparc/lib/ashldi3.S b/arch/sparc/lib/ashldi3.S
index 17912e608716..86f60de07b0a 100644
--- a/arch/sparc/lib/ashldi3.S
+++ b/arch/sparc/lib/ashldi3.S
@@ -5,10 +5,10 @@
5 * Copyright (C) 1999 David S. Miller (davem@redhat.com) 5 * Copyright (C) 1999 David S. Miller (davem@redhat.com)
6 */ 6 */
7 7
8#include <linux/linkage.h>
9
8 .text 10 .text
9 .align 4 11ENTRY(__ashldi3)
10 .globl __ashldi3
11__ashldi3:
12 cmp %o2, 0 12 cmp %o2, 0
13 be 9f 13 be 9f
14 mov 0x20, %g2 14 mov 0x20, %g2
@@ -32,3 +32,4 @@ __ashldi3:
329: 329:
33 retl 33 retl
34 nop 34 nop
35ENDPROC(__ashldi3)
diff --git a/arch/sparc/lib/ashrdi3.S b/arch/sparc/lib/ashrdi3.S
index 85398fd6dcc9..6eb8ba2dd50e 100644
--- a/arch/sparc/lib/ashrdi3.S
+++ b/arch/sparc/lib/ashrdi3.S
@@ -5,10 +5,10 @@
5 * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) 5 * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
6 */ 6 */
7 7
8#include <linux/linkage.h>
9
8 .text 10 .text
9 .align 4 11ENTRY(__ashrdi3)
10 .globl __ashrdi3
11__ashrdi3:
12 tst %o2 12 tst %o2
13 be 3f 13 be 3f
14 or %g0, 32, %g2 14 or %g0, 32, %g2
@@ -34,3 +34,4 @@ __ashrdi3:
343: 343:
35 jmpl %o7 + 8, %g0 35 jmpl %o7 + 8, %g0
36 nop 36 nop
37ENDPROC(__ashrdi3)
diff --git a/arch/sparc/lib/atomic_32.S b/arch/sparc/lib/atomic_32.S
deleted file mode 100644
index eb6c7359cbd1..000000000000
--- a/arch/sparc/lib/atomic_32.S
+++ /dev/null
@@ -1,44 +0,0 @@
1/* atomic.S: Move this stuff here for better ICACHE hit rates.
2 *
3 * Copyright (C) 1996 David S. Miller (davem@caipfs.rutgers.edu)
4 */
5
6#include <asm/ptrace.h>
7#include <asm/psr.h>
8
9 .text
10 .align 4
11
12 .globl __atomic_begin
13__atomic_begin:
14
15#ifndef CONFIG_SMP
16 .globl ___xchg32_sun4c
17___xchg32_sun4c:
18 rd %psr, %g3
19 andcc %g3, PSR_PIL, %g0
20 bne 1f
21 nop
22 wr %g3, PSR_PIL, %psr
23 nop; nop; nop
241:
25 andcc %g3, PSR_PIL, %g0
26 ld [%g1], %g7
27 bne 1f
28 st %g2, [%g1]
29 wr %g3, 0x0, %psr
30 nop; nop; nop
311:
32 mov %g7, %g2
33 jmpl %o7 + 8, %g0
34 mov %g4, %o7
35
36 .globl ___xchg32_sun4md
37___xchg32_sun4md:
38 swap [%g1], %g2
39 jmpl %o7 + 8, %g0
40 mov %g4, %o7
41#endif
42
43 .globl __atomic_end
44__atomic_end:
diff --git a/arch/sparc/lib/atomic_64.S b/arch/sparc/lib/atomic_64.S
index 59186e0fcf39..4d502da3de78 100644
--- a/arch/sparc/lib/atomic_64.S
+++ b/arch/sparc/lib/atomic_64.S
@@ -3,6 +3,7 @@
3 * Copyright (C) 1999, 2007 David S. Miller (davem@davemloft.net) 3 * Copyright (C) 1999, 2007 David S. Miller (davem@davemloft.net)
4 */ 4 */
5 5
6#include <linux/linkage.h>
6#include <asm/asi.h> 7#include <asm/asi.h>
7#include <asm/backoff.h> 8#include <asm/backoff.h>
8 9
@@ -13,9 +14,7 @@
13 * memory barriers, and a second which returns 14 * memory barriers, and a second which returns
14 * a value and does the barriers. 15 * a value and does the barriers.
15 */ 16 */
16 .globl atomic_add 17ENTRY(atomic_add) /* %o0 = increment, %o1 = atomic_ptr */
17 .type atomic_add,#function
18atomic_add: /* %o0 = increment, %o1 = atomic_ptr */
19 BACKOFF_SETUP(%o2) 18 BACKOFF_SETUP(%o2)
201: lduw [%o1], %g1 191: lduw [%o1], %g1
21 add %g1, %o0, %g7 20 add %g1, %o0, %g7
@@ -26,11 +25,9 @@ atomic_add: /* %o0 = increment, %o1 = atomic_ptr */
26 retl 25 retl
27 nop 26 nop
282: BACKOFF_SPIN(%o2, %o3, 1b) 272: BACKOFF_SPIN(%o2, %o3, 1b)
29 .size atomic_add, .-atomic_add 28ENDPROC(atomic_add)
30 29
31 .globl atomic_sub 30ENTRY(atomic_sub) /* %o0 = decrement, %o1 = atomic_ptr */
32 .type atomic_sub,#function
33atomic_sub: /* %o0 = decrement, %o1 = atomic_ptr */
34 BACKOFF_SETUP(%o2) 31 BACKOFF_SETUP(%o2)
351: lduw [%o1], %g1 321: lduw [%o1], %g1
36 sub %g1, %o0, %g7 33 sub %g1, %o0, %g7
@@ -41,11 +38,9 @@ atomic_sub: /* %o0 = decrement, %o1 = atomic_ptr */
41 retl 38 retl
42 nop 39 nop
432: BACKOFF_SPIN(%o2, %o3, 1b) 402: BACKOFF_SPIN(%o2, %o3, 1b)
44 .size atomic_sub, .-atomic_sub 41ENDPROC(atomic_sub)
45 42
46 .globl atomic_add_ret 43ENTRY(atomic_add_ret) /* %o0 = increment, %o1 = atomic_ptr */
47 .type atomic_add_ret,#function
48atomic_add_ret: /* %o0 = increment, %o1 = atomic_ptr */
49 BACKOFF_SETUP(%o2) 44 BACKOFF_SETUP(%o2)
501: lduw [%o1], %g1 451: lduw [%o1], %g1
51 add %g1, %o0, %g7 46 add %g1, %o0, %g7
@@ -56,11 +51,9 @@ atomic_add_ret: /* %o0 = increment, %o1 = atomic_ptr */
56 retl 51 retl
57 sra %g1, 0, %o0 52 sra %g1, 0, %o0
582: BACKOFF_SPIN(%o2, %o3, 1b) 532: BACKOFF_SPIN(%o2, %o3, 1b)
59 .size atomic_add_ret, .-atomic_add_ret 54ENDPROC(atomic_add_ret)
60 55
61 .globl atomic_sub_ret 56ENTRY(atomic_sub_ret) /* %o0 = decrement, %o1 = atomic_ptr */
62 .type atomic_sub_ret,#function
63atomic_sub_ret: /* %o0 = decrement, %o1 = atomic_ptr */
64 BACKOFF_SETUP(%o2) 57 BACKOFF_SETUP(%o2)
651: lduw [%o1], %g1 581: lduw [%o1], %g1
66 sub %g1, %o0, %g7 59 sub %g1, %o0, %g7
@@ -71,11 +64,9 @@ atomic_sub_ret: /* %o0 = decrement, %o1 = atomic_ptr */
71 retl 64 retl
72 sra %g1, 0, %o0 65 sra %g1, 0, %o0
732: BACKOFF_SPIN(%o2, %o3, 1b) 662: BACKOFF_SPIN(%o2, %o3, 1b)
74 .size atomic_sub_ret, .-atomic_sub_ret 67ENDPROC(atomic_sub_ret)
75 68
76 .globl atomic64_add 69ENTRY(atomic64_add) /* %o0 = increment, %o1 = atomic_ptr */
77 .type atomic64_add,#function
78atomic64_add: /* %o0 = increment, %o1 = atomic_ptr */
79 BACKOFF_SETUP(%o2) 70 BACKOFF_SETUP(%o2)
801: ldx [%o1], %g1 711: ldx [%o1], %g1
81 add %g1, %o0, %g7 72 add %g1, %o0, %g7
@@ -86,11 +77,9 @@ atomic64_add: /* %o0 = increment, %o1 = atomic_ptr */
86 retl 77 retl
87 nop 78 nop
882: BACKOFF_SPIN(%o2, %o3, 1b) 792: BACKOFF_SPIN(%o2, %o3, 1b)
89 .size atomic64_add, .-atomic64_add 80ENDPROC(atomic64_add)
90 81
91 .globl atomic64_sub 82ENTRY(atomic64_sub) /* %o0 = decrement, %o1 = atomic_ptr */
92 .type atomic64_sub,#function
93atomic64_sub: /* %o0 = decrement, %o1 = atomic_ptr */
94 BACKOFF_SETUP(%o2) 83 BACKOFF_SETUP(%o2)
951: ldx [%o1], %g1 841: ldx [%o1], %g1
96 sub %g1, %o0, %g7 85 sub %g1, %o0, %g7
@@ -101,11 +90,9 @@ atomic64_sub: /* %o0 = decrement, %o1 = atomic_ptr */
101 retl 90 retl
102 nop 91 nop
1032: BACKOFF_SPIN(%o2, %o3, 1b) 922: BACKOFF_SPIN(%o2, %o3, 1b)
104 .size atomic64_sub, .-atomic64_sub 93ENDPROC(atomic64_sub)
105 94
106 .globl atomic64_add_ret 95ENTRY(atomic64_add_ret) /* %o0 = increment, %o1 = atomic_ptr */
107 .type atomic64_add_ret,#function
108atomic64_add_ret: /* %o0 = increment, %o1 = atomic_ptr */
109 BACKOFF_SETUP(%o2) 96 BACKOFF_SETUP(%o2)
1101: ldx [%o1], %g1 971: ldx [%o1], %g1
111 add %g1, %o0, %g7 98 add %g1, %o0, %g7
@@ -116,11 +103,9 @@ atomic64_add_ret: /* %o0 = increment, %o1 = atomic_ptr */
116 retl 103 retl
117 add %g1, %o0, %o0 104 add %g1, %o0, %o0
1182: BACKOFF_SPIN(%o2, %o3, 1b) 1052: BACKOFF_SPIN(%o2, %o3, 1b)
119 .size atomic64_add_ret, .-atomic64_add_ret 106ENDPROC(atomic64_add_ret)
120 107
121 .globl atomic64_sub_ret 108ENTRY(atomic64_sub_ret) /* %o0 = decrement, %o1 = atomic_ptr */
122 .type atomic64_sub_ret,#function
123atomic64_sub_ret: /* %o0 = decrement, %o1 = atomic_ptr */
124 BACKOFF_SETUP(%o2) 109 BACKOFF_SETUP(%o2)
1251: ldx [%o1], %g1 1101: ldx [%o1], %g1
126 sub %g1, %o0, %g7 111 sub %g1, %o0, %g7
@@ -131,4 +116,4 @@ atomic64_sub_ret: /* %o0 = decrement, %o1 = atomic_ptr */
131 retl 116 retl
132 sub %g1, %o0, %o0 117 sub %g1, %o0, %o0
1332: BACKOFF_SPIN(%o2, %o3, 1b) 1182: BACKOFF_SPIN(%o2, %o3, 1b)
134 .size atomic64_sub_ret, .-atomic64_sub_ret 119ENDPROC(atomic64_sub_ret)
diff --git a/arch/sparc/lib/bitops.S b/arch/sparc/lib/bitops.S
index 3dc61d5537c0..36f72cc0e67e 100644
--- a/arch/sparc/lib/bitops.S
+++ b/arch/sparc/lib/bitops.S
@@ -3,14 +3,13 @@
3 * Copyright (C) 2000, 2007 David S. Miller (davem@davemloft.net) 3 * Copyright (C) 2000, 2007 David S. Miller (davem@davemloft.net)
4 */ 4 */
5 5
6#include <linux/linkage.h>
6#include <asm/asi.h> 7#include <asm/asi.h>
7#include <asm/backoff.h> 8#include <asm/backoff.h>
8 9
9 .text 10 .text
10 11
11 .globl test_and_set_bit 12ENTRY(test_and_set_bit) /* %o0=nr, %o1=addr */
12 .type test_and_set_bit,#function
13test_and_set_bit: /* %o0=nr, %o1=addr */
14 BACKOFF_SETUP(%o3) 13 BACKOFF_SETUP(%o3)
15 srlx %o0, 6, %g1 14 srlx %o0, 6, %g1
16 mov 1, %o2 15 mov 1, %o2
@@ -29,11 +28,9 @@ test_and_set_bit: /* %o0=nr, %o1=addr */
29 retl 28 retl
30 nop 29 nop
312: BACKOFF_SPIN(%o3, %o4, 1b) 302: BACKOFF_SPIN(%o3, %o4, 1b)
32 .size test_and_set_bit, .-test_and_set_bit 31ENDPROC(test_and_set_bit)
33 32
34 .globl test_and_clear_bit 33ENTRY(test_and_clear_bit) /* %o0=nr, %o1=addr */
35 .type test_and_clear_bit,#function
36test_and_clear_bit: /* %o0=nr, %o1=addr */
37 BACKOFF_SETUP(%o3) 34 BACKOFF_SETUP(%o3)
38 srlx %o0, 6, %g1 35 srlx %o0, 6, %g1
39 mov 1, %o2 36 mov 1, %o2
@@ -52,11 +49,9 @@ test_and_clear_bit: /* %o0=nr, %o1=addr */
52 retl 49 retl
53 nop 50 nop
542: BACKOFF_SPIN(%o3, %o4, 1b) 512: BACKOFF_SPIN(%o3, %o4, 1b)
55 .size test_and_clear_bit, .-test_and_clear_bit 52ENDPROC(test_and_clear_bit)
56 53
57 .globl test_and_change_bit 54ENTRY(test_and_change_bit) /* %o0=nr, %o1=addr */
58 .type test_and_change_bit,#function
59test_and_change_bit: /* %o0=nr, %o1=addr */
60 BACKOFF_SETUP(%o3) 55 BACKOFF_SETUP(%o3)
61 srlx %o0, 6, %g1 56 srlx %o0, 6, %g1
62 mov 1, %o2 57 mov 1, %o2
@@ -75,11 +70,9 @@ test_and_change_bit: /* %o0=nr, %o1=addr */
75 retl 70 retl
76 nop 71 nop
772: BACKOFF_SPIN(%o3, %o4, 1b) 722: BACKOFF_SPIN(%o3, %o4, 1b)
78 .size test_and_change_bit, .-test_and_change_bit 73ENDPROC(test_and_change_bit)
79 74
80 .globl set_bit 75ENTRY(set_bit) /* %o0=nr, %o1=addr */
81 .type set_bit,#function
82set_bit: /* %o0=nr, %o1=addr */
83 BACKOFF_SETUP(%o3) 76 BACKOFF_SETUP(%o3)
84 srlx %o0, 6, %g1 77 srlx %o0, 6, %g1
85 mov 1, %o2 78 mov 1, %o2
@@ -96,11 +89,9 @@ set_bit: /* %o0=nr, %o1=addr */
96 retl 89 retl
97 nop 90 nop
982: BACKOFF_SPIN(%o3, %o4, 1b) 912: BACKOFF_SPIN(%o3, %o4, 1b)
99 .size set_bit, .-set_bit 92ENDPROC(set_bit)
100 93
101 .globl clear_bit 94ENTRY(clear_bit) /* %o0=nr, %o1=addr */
102 .type clear_bit,#function
103clear_bit: /* %o0=nr, %o1=addr */
104 BACKOFF_SETUP(%o3) 95 BACKOFF_SETUP(%o3)
105 srlx %o0, 6, %g1 96 srlx %o0, 6, %g1
106 mov 1, %o2 97 mov 1, %o2
@@ -117,11 +108,9 @@ clear_bit: /* %o0=nr, %o1=addr */
117 retl 108 retl
118 nop 109 nop
1192: BACKOFF_SPIN(%o3, %o4, 1b) 1102: BACKOFF_SPIN(%o3, %o4, 1b)
120 .size clear_bit, .-clear_bit 111ENDPROC(clear_bit)
121 112
122 .globl change_bit 113ENTRY(change_bit) /* %o0=nr, %o1=addr */
123 .type change_bit,#function
124change_bit: /* %o0=nr, %o1=addr */
125 BACKOFF_SETUP(%o3) 114 BACKOFF_SETUP(%o3)
126 srlx %o0, 6, %g1 115 srlx %o0, 6, %g1
127 mov 1, %o2 116 mov 1, %o2
@@ -138,4 +127,4 @@ change_bit: /* %o0=nr, %o1=addr */
138 retl 127 retl
139 nop 128 nop
1402: BACKOFF_SPIN(%o3, %o4, 1b) 1292: BACKOFF_SPIN(%o3, %o4, 1b)
141 .size change_bit, .-change_bit 130ENDPROC(change_bit)
diff --git a/arch/sparc/lib/blockops.S b/arch/sparc/lib/blockops.S
index 804be87f9a42..3c771011ff4b 100644
--- a/arch/sparc/lib/blockops.S
+++ b/arch/sparc/lib/blockops.S
@@ -4,6 +4,7 @@
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/linkage.h>
7#include <asm/page.h> 8#include <asm/page.h>
8 9
9 /* Zero out 64 bytes of memory at (buf + offset). 10 /* Zero out 64 bytes of memory at (buf + offset).
@@ -44,10 +45,7 @@
44 */ 45 */
45 46
46 .text 47 .text
47 .align 4 48ENTRY(bzero_1page)
48 .globl bzero_1page, __copy_1page
49
50bzero_1page:
51/* NOTE: If you change the number of insns of this routine, please check 49/* NOTE: If you change the number of insns of this routine, please check
52 * arch/sparc/mm/hypersparc.S */ 50 * arch/sparc/mm/hypersparc.S */
53 /* %o0 = buf */ 51 /* %o0 = buf */
@@ -65,8 +63,9 @@ bzero_1page:
65 63
66 retl 64 retl
67 nop 65 nop
66ENDPROC(bzero_1page)
68 67
69__copy_1page: 68ENTRY(__copy_1page)
70/* NOTE: If you change the number of insns of this routine, please check 69/* NOTE: If you change the number of insns of this routine, please check
71 * arch/sparc/mm/hypersparc.S */ 70 * arch/sparc/mm/hypersparc.S */
72 /* %o0 = dst, %o1 = src */ 71 /* %o0 = dst, %o1 = src */
@@ -87,3 +86,4 @@ __copy_1page:
87 86
88 retl 87 retl
89 nop 88 nop
89ENDPROC(__copy_1page)
diff --git a/arch/sparc/lib/bzero.S b/arch/sparc/lib/bzero.S
index 615f401edf69..8c058114b649 100644
--- a/arch/sparc/lib/bzero.S
+++ b/arch/sparc/lib/bzero.S
@@ -4,11 +4,11 @@
4 * Copyright (C) 2005 David S. Miller <davem@davemloft.net> 4 * Copyright (C) 2005 David S. Miller <davem@davemloft.net>
5 */ 5 */
6 6
7#include <linux/linkage.h>
8
7 .text 9 .text
8 10
9 .globl memset 11ENTRY(memset) /* %o0=buf, %o1=pat, %o2=len */
10 .type memset, #function
11memset: /* %o0=buf, %o1=pat, %o2=len */
12 and %o1, 0xff, %o3 12 and %o1, 0xff, %o3
13 mov %o2, %o1 13 mov %o2, %o1
14 sllx %o3, 8, %g1 14 sllx %o3, 8, %g1
@@ -19,9 +19,7 @@ memset: /* %o0=buf, %o1=pat, %o2=len */
19 ba,pt %xcc, 1f 19 ba,pt %xcc, 1f
20 or %g1, %o2, %o2 20 or %g1, %o2, %o2
21 21
22 .globl __bzero 22ENTRY(__bzero) /* %o0=buf, %o1=len */
23 .type __bzero, #function
24__bzero: /* %o0=buf, %o1=len */
25 clr %o2 23 clr %o2
261: mov %o0, %o3 241: mov %o0, %o3
27 brz,pn %o1, __bzero_done 25 brz,pn %o1, __bzero_done
@@ -78,8 +76,8 @@ __bzero_tiny:
78__bzero_done: 76__bzero_done:
79 retl 77 retl
80 mov %o3, %o0 78 mov %o3, %o0
81 .size __bzero, .-__bzero 79ENDPROC(__bzero)
82 .size memset, .-memset 80ENDPROC(memset)
83 81
84#define EX_ST(x,y) \ 82#define EX_ST(x,y) \
8598: x,y; \ 8398: x,y; \
@@ -89,9 +87,7 @@ __bzero_done:
89 .text; \ 87 .text; \
90 .align 4; 88 .align 4;
91 89
92 .globl __clear_user 90ENTRY(__clear_user) /* %o0=buf, %o1=len */
93 .type __clear_user, #function
94__clear_user: /* %o0=buf, %o1=len */
95 brz,pn %o1, __clear_user_done 91 brz,pn %o1, __clear_user_done
96 cmp %o1, 16 92 cmp %o1, 16
97 bl,pn %icc, __clear_user_tiny 93 bl,pn %icc, __clear_user_tiny
@@ -146,4 +142,4 @@ __clear_user_tiny:
146__clear_user_done: 142__clear_user_done:
147 retl 143 retl
148 clr %o0 144 clr %o0
149 .size __clear_user, .-__clear_user 145ENDPROC(__clear_user)
diff --git a/arch/sparc/lib/divdi3.S b/arch/sparc/lib/divdi3.S
index d74bc0925f2d..9614b48b6ef8 100644
--- a/arch/sparc/lib/divdi3.S
+++ b/arch/sparc/lib/divdi3.S
@@ -19,7 +19,6 @@ Boston, MA 02111-1307, USA. */
19 19
20 .text 20 .text
21 .align 4 21 .align 4
22 .global .udiv
23 .globl __divdi3 22 .globl __divdi3
24__divdi3: 23__divdi3:
25 save %sp,-104,%sp 24 save %sp,-104,%sp
@@ -83,8 +82,9 @@ __divdi3:
83 bne .LL85 82 bne .LL85
84 mov %i0,%o2 83 mov %i0,%o2
85 mov 1,%o0 84 mov 1,%o0
86 call .udiv,0
87 mov 0,%o1 85 mov 0,%o1
86 wr %g0, 0, %y
87 udiv %o0, %o1, %o0
88 mov %o0,%o4 88 mov %o0,%o4
89 mov %i0,%o2 89 mov %i0,%o2
90.LL85: 90.LL85:
diff --git a/arch/sparc/lib/ipcsum.S b/arch/sparc/lib/ipcsum.S
index 58ca5b9a8778..4742d59029ee 100644
--- a/arch/sparc/lib/ipcsum.S
+++ b/arch/sparc/lib/ipcsum.S
@@ -1,8 +1,7 @@
1#include <linux/linkage.h>
2
1 .text 3 .text
2 .align 32 4ENTRY(ip_fast_csum) /* %o0 = iph, %o1 = ihl */
3 .globl ip_fast_csum
4 .type ip_fast_csum,#function
5ip_fast_csum: /* %o0 = iph, %o1 = ihl */
6 sub %o1, 4, %g7 5 sub %o1, 4, %g7
7 lduw [%o0 + 0x00], %o2 6 lduw [%o0 + 0x00], %o2
8 lduw [%o0 + 0x04], %g2 7 lduw [%o0 + 0x04], %g2
@@ -31,4 +30,4 @@ ip_fast_csum: /* %o0 = iph, %o1 = ihl */
31 set 0xffff, %o1 30 set 0xffff, %o1
32 retl 31 retl
33 and %o2, %o1, %o0 32 and %o2, %o1, %o0
34 .size ip_fast_csum, .-ip_fast_csum 33ENDPROC(ip_fast_csum)
diff --git a/arch/sparc/lib/ksyms.c b/arch/sparc/lib/ksyms.c
index f73c2240fe60..2dc30875c8bc 100644
--- a/arch/sparc/lib/ksyms.c
+++ b/arch/sparc/lib/ksyms.c
@@ -56,23 +56,11 @@ extern int __divdi3(int, int);
56extern void (*__copy_1page)(void *, const void *); 56extern void (*__copy_1page)(void *, const void *);
57extern void (*bzero_1page)(void *); 57extern void (*bzero_1page)(void *);
58 58
59extern int __strncmp(const char *, const char *, __kernel_size_t);
60
61extern void ___rw_read_enter(void); 59extern void ___rw_read_enter(void);
62extern void ___rw_read_try(void); 60extern void ___rw_read_try(void);
63extern void ___rw_read_exit(void); 61extern void ___rw_read_exit(void);
64extern void ___rw_write_enter(void); 62extern void ___rw_write_enter(void);
65 63
66/* Alias functions whose names begin with "." and export the aliases.
67 * The module references will be fixed up by module_frob_arch_sections.
68 */
69extern int _Div(int, int);
70extern int _Mul(int, int);
71extern int _Rem(int, int);
72extern unsigned _Udiv(unsigned, unsigned);
73extern unsigned _Umul(unsigned, unsigned);
74extern unsigned _Urem(unsigned, unsigned);
75
76/* Networking helper routines. */ 64/* Networking helper routines. */
77EXPORT_SYMBOL(__csum_partial_copy_sparc_generic); 65EXPORT_SYMBOL(__csum_partial_copy_sparc_generic);
78 66
@@ -81,9 +69,6 @@ EXPORT_SYMBOL(__copy_1page);
81EXPORT_SYMBOL(__memmove); 69EXPORT_SYMBOL(__memmove);
82EXPORT_SYMBOL(bzero_1page); 70EXPORT_SYMBOL(bzero_1page);
83 71
84/* string functions */
85EXPORT_SYMBOL(__strncmp);
86
87/* Moving data to/from/in userspace. */ 72/* Moving data to/from/in userspace. */
88EXPORT_SYMBOL(__copy_user); 73EXPORT_SYMBOL(__copy_user);
89 74
@@ -100,13 +85,6 @@ EXPORT_SYMBOL(__ashldi3);
100EXPORT_SYMBOL(__lshrdi3); 85EXPORT_SYMBOL(__lshrdi3);
101EXPORT_SYMBOL(__muldi3); 86EXPORT_SYMBOL(__muldi3);
102EXPORT_SYMBOL(__divdi3); 87EXPORT_SYMBOL(__divdi3);
103
104EXPORT_SYMBOL(_Rem);
105EXPORT_SYMBOL(_Urem);
106EXPORT_SYMBOL(_Mul);
107EXPORT_SYMBOL(_Umul);
108EXPORT_SYMBOL(_Div);
109EXPORT_SYMBOL(_Udiv);
110#endif 88#endif
111 89
112/* 90/*
diff --git a/arch/sparc/lib/lshrdi3.S b/arch/sparc/lib/lshrdi3.S
index 47a1354c1602..60ebc7cdbee0 100644
--- a/arch/sparc/lib/lshrdi3.S
+++ b/arch/sparc/lib/lshrdi3.S
@@ -1,6 +1,6 @@
1#include <linux/linkage.h>
1 2
2 .globl __lshrdi3 3ENTRY(__lshrdi3)
3__lshrdi3:
4 cmp %o2, 0 4 cmp %o2, 0
5 be 3f 5 be 3f
6 mov 0x20, %g2 6 mov 0x20, %g2
@@ -24,3 +24,4 @@ __lshrdi3:
243: 243:
25 retl 25 retl
26 nop 26 nop
27ENDPROC(__lshrdi3)
diff --git a/arch/sparc/lib/memmove.S b/arch/sparc/lib/memmove.S
index 97395802c23c..b7f6334e159f 100644
--- a/arch/sparc/lib/memmove.S
+++ b/arch/sparc/lib/memmove.S
@@ -4,11 +4,10 @@
4 * Copyright (C) 1996, 1997, 1998, 1999 Jakub Jelinek (jj@ultra.linux.cz) 4 * Copyright (C) 1996, 1997, 1998, 1999 Jakub Jelinek (jj@ultra.linux.cz)
5 */ 5 */
6 6
7#include <linux/linkage.h>
8
7 .text 9 .text
8 .align 32 10ENTRY(memmove) /* o0=dst o1=src o2=len */
9 .globl memmove
10 .type memmove,#function
11memmove: /* o0=dst o1=src o2=len */
12 mov %o0, %g1 11 mov %o0, %g1
13 cmp %o0, %o1 12 cmp %o0, %o1
14 bleu,pt %xcc, memcpy 13 bleu,pt %xcc, memcpy
@@ -28,4 +27,4 @@ memmove: /* o0=dst o1=src o2=len */
28 27
29 retl 28 retl
30 mov %g1, %o0 29 mov %g1, %o0
31 .size memmove, .-memmove 30ENDPROC(memmove)
diff --git a/arch/sparc/lib/mul.S b/arch/sparc/lib/mul.S
deleted file mode 100644
index c45470d0b0ce..000000000000
--- a/arch/sparc/lib/mul.S
+++ /dev/null
@@ -1,137 +0,0 @@
1/*
2 * mul.S: This routine was taken from glibc-1.09 and is covered
3 * by the GNU Library General Public License Version 2.
4 */
5
6/*
7 * Signed multiply, from Appendix E of the Sparc Version 8
8 * Architecture Manual.
9 */
10
11/*
12 * Returns %o0 * %o1 in %o1%o0 (i.e., %o1 holds the upper 32 bits of
13 * the 64-bit product).
14 *
15 * This code optimizes short (less than 13-bit) multiplies.
16 */
17
18 .globl .mul
19 .globl _Mul
20.mul:
21_Mul: /* needed for export */
22 mov %o0, %y ! multiplier -> Y
23 andncc %o0, 0xfff, %g0 ! test bits 12..31
24 be Lmul_shortway ! if zero, can do it the short way
25 andcc %g0, %g0, %o4 ! zero the partial product and clear N and V
26
27 /*
28 * Long multiply. 32 steps, followed by a final shift step.
29 */
30 mulscc %o4, %o1, %o4 ! 1
31 mulscc %o4, %o1, %o4 ! 2
32 mulscc %o4, %o1, %o4 ! 3
33 mulscc %o4, %o1, %o4 ! 4
34 mulscc %o4, %o1, %o4 ! 5
35 mulscc %o4, %o1, %o4 ! 6
36 mulscc %o4, %o1, %o4 ! 7
37 mulscc %o4, %o1, %o4 ! 8
38 mulscc %o4, %o1, %o4 ! 9
39 mulscc %o4, %o1, %o4 ! 10
40 mulscc %o4, %o1, %o4 ! 11
41 mulscc %o4, %o1, %o4 ! 12
42 mulscc %o4, %o1, %o4 ! 13
43 mulscc %o4, %o1, %o4 ! 14
44 mulscc %o4, %o1, %o4 ! 15
45 mulscc %o4, %o1, %o4 ! 16
46 mulscc %o4, %o1, %o4 ! 17
47 mulscc %o4, %o1, %o4 ! 18
48 mulscc %o4, %o1, %o4 ! 19
49 mulscc %o4, %o1, %o4 ! 20
50 mulscc %o4, %o1, %o4 ! 21
51 mulscc %o4, %o1, %o4 ! 22
52 mulscc %o4, %o1, %o4 ! 23
53 mulscc %o4, %o1, %o4 ! 24
54 mulscc %o4, %o1, %o4 ! 25
55 mulscc %o4, %o1, %o4 ! 26
56 mulscc %o4, %o1, %o4 ! 27
57 mulscc %o4, %o1, %o4 ! 28
58 mulscc %o4, %o1, %o4 ! 29
59 mulscc %o4, %o1, %o4 ! 30
60 mulscc %o4, %o1, %o4 ! 31
61 mulscc %o4, %o1, %o4 ! 32
62 mulscc %o4, %g0, %o4 ! final shift
63
64 ! If %o0 was negative, the result is
65 ! (%o0 * %o1) + (%o1 << 32))
66 ! We fix that here.
67
68#if 0
69 tst %o0
70 bge 1f
71 rd %y, %o0
72
73 ! %o0 was indeed negative; fix upper 32 bits of result by subtracting
74 ! %o1 (i.e., return %o4 - %o1 in %o1).
75 retl
76 sub %o4, %o1, %o1
77
781:
79 retl
80 mov %o4, %o1
81#else
82 /* Faster code adapted from tege@sics.se's code for umul.S. */
83 sra %o0, 31, %o2 ! make mask from sign bit
84 and %o1, %o2, %o2 ! %o2 = 0 or %o1, depending on sign of %o0
85 rd %y, %o0 ! get lower half of product
86 retl
87 sub %o4, %o2, %o1 ! subtract compensation
88 ! and put upper half in place
89#endif
90
91Lmul_shortway:
92 /*
93 * Short multiply. 12 steps, followed by a final shift step.
94 * The resulting bits are off by 12 and (32-12) = 20 bit positions,
95 * but there is no problem with %o0 being negative (unlike above).
96 */
97 mulscc %o4, %o1, %o4 ! 1
98 mulscc %o4, %o1, %o4 ! 2
99 mulscc %o4, %o1, %o4 ! 3
100 mulscc %o4, %o1, %o4 ! 4
101 mulscc %o4, %o1, %o4 ! 5
102 mulscc %o4, %o1, %o4 ! 6
103 mulscc %o4, %o1, %o4 ! 7
104 mulscc %o4, %o1, %o4 ! 8
105 mulscc %o4, %o1, %o4 ! 9
106 mulscc %o4, %o1, %o4 ! 10
107 mulscc %o4, %o1, %o4 ! 11
108 mulscc %o4, %o1, %o4 ! 12
109 mulscc %o4, %g0, %o4 ! final shift
110
111 /*
112 * %o4 has 20 of the bits that should be in the low part of the
113 * result; %y has the bottom 12 (as %y's top 12). That is:
114 *
115 * %o4 %y
116 * +----------------+----------------+
117 * | -12- | -20- | -12- | -20- |
118 * +------(---------+------)---------+
119 * --hi-- ----low-part----
120 *
121 * The upper 12 bits of %o4 should be sign-extended to form the
122 * high part of the product (i.e., highpart = %o4 >> 20).
123 */
124
125 rd %y, %o5
126 sll %o4, 12, %o0 ! shift middle bits left 12
127 srl %o5, 20, %o5 ! shift low bits right 20, zero fill at left
128 or %o5, %o0, %o0 ! construct low part of result
129 retl
130 sra %o4, 20, %o1 ! ... and extract high part of result
131
132 .globl .mul_patch
133.mul_patch:
134 smul %o0, %o1, %o0
135 retl
136 rd %y, %o1
137 nop
diff --git a/arch/sparc/lib/muldi3.S b/arch/sparc/lib/muldi3.S
index 7f17872d0603..9794939d1c12 100644
--- a/arch/sparc/lib/muldi3.S
+++ b/arch/sparc/lib/muldi3.S
@@ -63,12 +63,12 @@ __muldi3:
63 rd %y, %o1 63 rd %y, %o1
64 mov %o1, %l3 64 mov %o1, %l3
65 mov %i1, %o0 65 mov %i1, %o0
66 call .umul
67 mov %i2, %o1 66 mov %i2, %o1
67 umul %o0, %o1, %o0
68 mov %o0, %l0 68 mov %o0, %l0
69 mov %i0, %o0 69 mov %i0, %o0
70 call .umul
71 mov %i3, %o1 70 mov %i3, %o1
71 umul %o0, %o1, %o0
72 add %l0, %o0, %l0 72 add %l0, %o0, %l0
73 mov %l2, %i0 73 mov %l2, %i0
74 add %l2, %l0, %i0 74 add %l2, %l0, %i0
diff --git a/arch/sparc/lib/rem.S b/arch/sparc/lib/rem.S
deleted file mode 100644
index 42fb86252815..000000000000
--- a/arch/sparc/lib/rem.S
+++ /dev/null
@@ -1,384 +0,0 @@
1/*
2 * rem.S: This routine was taken from glibc-1.09 and is covered
3 * by the GNU Library General Public License Version 2.
4 */
5
6
7/* This file is generated from divrem.m4; DO NOT EDIT! */
8/*
9 * Division and remainder, from Appendix E of the Sparc Version 8
10 * Architecture Manual, with fixes from Gordon Irlam.
11 */
12
13/*
14 * Input: dividend and divisor in %o0 and %o1 respectively.
15 *
16 * m4 parameters:
17 * .rem name of function to generate
18 * rem rem=div => %o0 / %o1; rem=rem => %o0 % %o1
19 * true true=true => signed; true=false => unsigned
20 *
21 * Algorithm parameters:
22 * N how many bits per iteration we try to get (4)
23 * WORDSIZE total number of bits (32)
24 *
25 * Derived constants:
26 * TOPBITS number of bits in the top decade of a number
27 *
28 * Important variables:
29 * Q the partial quotient under development (initially 0)
30 * R the remainder so far, initially the dividend
31 * ITER number of main division loop iterations required;
32 * equal to ceil(log2(quotient) / N). Note that this
33 * is the log base (2^N) of the quotient.
34 * V the current comparand, initially divisor*2^(ITER*N-1)
35 *
36 * Cost:
37 * Current estimate for non-large dividend is
38 * ceil(log2(quotient) / N) * (10 + 7N/2) + C
39 * A large dividend is one greater than 2^(31-TOPBITS) and takes a
40 * different path, as the upper bits of the quotient must be developed
41 * one bit at a time.
42 */
43
44
45 .globl .rem
46 .globl _Rem
47.rem:
48_Rem: /* needed for export */
49 ! compute sign of result; if neither is negative, no problem
50 orcc %o1, %o0, %g0 ! either negative?
51 bge 2f ! no, go do the divide
52 mov %o0, %g2 ! compute sign in any case
53
54 tst %o1
55 bge 1f
56 tst %o0
57 ! %o1 is definitely negative; %o0 might also be negative
58 bge 2f ! if %o0 not negative...
59 sub %g0, %o1, %o1 ! in any case, make %o1 nonneg
601: ! %o0 is negative, %o1 is nonnegative
61 sub %g0, %o0, %o0 ! make %o0 nonnegative
622:
63
64 ! Ready to divide. Compute size of quotient; scale comparand.
65 orcc %o1, %g0, %o5
66 bne 1f
67 mov %o0, %o3
68
69 ! Divide by zero trap. If it returns, return 0 (about as
70 ! wrong as possible, but that is what SunOS does...).
71 ta ST_DIV0
72 retl
73 clr %o0
74
751:
76 cmp %o3, %o5 ! if %o1 exceeds %o0, done
77 blu Lgot_result ! (and algorithm fails otherwise)
78 clr %o2
79
80 sethi %hi(1 << (32 - 4 - 1)), %g1
81
82 cmp %o3, %g1
83 blu Lnot_really_big
84 clr %o4
85
86 ! Here the dividend is >= 2**(31-N) or so. We must be careful here,
87 ! as our usual N-at-a-shot divide step will cause overflow and havoc.
88 ! The number of bits in the result here is N*ITER+SC, where SC <= N.
89 ! Compute ITER in an unorthodox manner: know we need to shift V into
90 ! the top decade: so do not even bother to compare to R.
91 1:
92 cmp %o5, %g1
93 bgeu 3f
94 mov 1, %g7
95
96 sll %o5, 4, %o5
97
98 b 1b
99 add %o4, 1, %o4
100
101 ! Now compute %g7.
102 2:
103 addcc %o5, %o5, %o5
104
105 bcc Lnot_too_big
106 add %g7, 1, %g7
107
108 ! We get here if the %o1 overflowed while shifting.
109 ! This means that %o3 has the high-order bit set.
110 ! Restore %o5 and subtract from %o3.
111 sll %g1, 4, %g1 ! high order bit
112 srl %o5, 1, %o5 ! rest of %o5
113 add %o5, %g1, %o5
114
115 b Ldo_single_div
116 sub %g7, 1, %g7
117
118 Lnot_too_big:
119 3:
120 cmp %o5, %o3
121 blu 2b
122 nop
123
124 be Ldo_single_div
125 nop
126 /* NB: these are commented out in the V8-Sparc manual as well */
127 /* (I do not understand this) */
128 ! %o5 > %o3: went too far: back up 1 step
129 ! srl %o5, 1, %o5
130 ! dec %g7
131 ! do single-bit divide steps
132 !
133 ! We have to be careful here. We know that %o3 >= %o5, so we can do the
134 ! first divide step without thinking. BUT, the others are conditional,
135 ! and are only done if %o3 >= 0. Because both %o3 and %o5 may have the high-
136 ! order bit set in the first step, just falling into the regular
137 ! division loop will mess up the first time around.
138 ! So we unroll slightly...
139 Ldo_single_div:
140 subcc %g7, 1, %g7
141 bl Lend_regular_divide
142 nop
143
144 sub %o3, %o5, %o3
145 mov 1, %o2
146
147 b Lend_single_divloop
148 nop
149 Lsingle_divloop:
150 sll %o2, 1, %o2
151
152 bl 1f
153 srl %o5, 1, %o5
154 ! %o3 >= 0
155 sub %o3, %o5, %o3
156
157 b 2f
158 add %o2, 1, %o2
159 1: ! %o3 < 0
160 add %o3, %o5, %o3
161 sub %o2, 1, %o2
162 2:
163 Lend_single_divloop:
164 subcc %g7, 1, %g7
165 bge Lsingle_divloop
166 tst %o3
167
168 b,a Lend_regular_divide
169
170Lnot_really_big:
1711:
172 sll %o5, 4, %o5
173 cmp %o5, %o3
174 bleu 1b
175 addcc %o4, 1, %o4
176 be Lgot_result
177 sub %o4, 1, %o4
178
179 tst %o3 ! set up for initial iteration
180Ldivloop:
181 sll %o2, 4, %o2
182 ! depth 1, accumulated bits 0
183 bl L.1.16
184 srl %o5,1,%o5
185 ! remainder is positive
186 subcc %o3,%o5,%o3
187 ! depth 2, accumulated bits 1
188 bl L.2.17
189 srl %o5,1,%o5
190 ! remainder is positive
191 subcc %o3,%o5,%o3
192 ! depth 3, accumulated bits 3
193 bl L.3.19
194 srl %o5,1,%o5
195 ! remainder is positive
196 subcc %o3,%o5,%o3
197 ! depth 4, accumulated bits 7
198 bl L.4.23
199 srl %o5,1,%o5
200 ! remainder is positive
201 subcc %o3,%o5,%o3
202
203 b 9f
204 add %o2, (7*2+1), %o2
205
206L.4.23:
207 ! remainder is negative
208 addcc %o3,%o5,%o3
209 b 9f
210 add %o2, (7*2-1), %o2
211
212L.3.19:
213 ! remainder is negative
214 addcc %o3,%o5,%o3
215 ! depth 4, accumulated bits 5
216 bl L.4.21
217 srl %o5,1,%o5
218 ! remainder is positive
219 subcc %o3,%o5,%o3
220 b 9f
221 add %o2, (5*2+1), %o2
222
223L.4.21:
224 ! remainder is negative
225 addcc %o3,%o5,%o3
226 b 9f
227 add %o2, (5*2-1), %o2
228
229L.2.17:
230 ! remainder is negative
231 addcc %o3,%o5,%o3
232 ! depth 3, accumulated bits 1
233 bl L.3.17
234 srl %o5,1,%o5
235 ! remainder is positive
236 subcc %o3,%o5,%o3
237 ! depth 4, accumulated bits 3
238 bl L.4.19
239 srl %o5,1,%o5
240 ! remainder is positive
241 subcc %o3,%o5,%o3
242 b 9f
243 add %o2, (3*2+1), %o2
244
245L.4.19:
246 ! remainder is negative
247 addcc %o3,%o5,%o3
248 b 9f
249 add %o2, (3*2-1), %o2
250
251L.3.17:
252 ! remainder is negative
253 addcc %o3,%o5,%o3
254 ! depth 4, accumulated bits 1
255 bl L.4.17
256 srl %o5,1,%o5
257 ! remainder is positive
258 subcc %o3,%o5,%o3
259 b 9f
260 add %o2, (1*2+1), %o2
261
262L.4.17:
263 ! remainder is negative
264 addcc %o3,%o5,%o3
265 b 9f
266 add %o2, (1*2-1), %o2
267
268L.1.16:
269 ! remainder is negative
270 addcc %o3,%o5,%o3
271 ! depth 2, accumulated bits -1
272 bl L.2.15
273 srl %o5,1,%o5
274 ! remainder is positive
275 subcc %o3,%o5,%o3
276 ! depth 3, accumulated bits -1
277 bl L.3.15
278 srl %o5,1,%o5
279 ! remainder is positive
280 subcc %o3,%o5,%o3
281 ! depth 4, accumulated bits -1
282 bl L.4.15
283 srl %o5,1,%o5
284 ! remainder is positive
285 subcc %o3,%o5,%o3
286 b 9f
287 add %o2, (-1*2+1), %o2
288
289L.4.15:
290 ! remainder is negative
291 addcc %o3,%o5,%o3
292 b 9f
293 add %o2, (-1*2-1), %o2
294
295L.3.15:
296 ! remainder is negative
297 addcc %o3,%o5,%o3
298 ! depth 4, accumulated bits -3
299 bl L.4.13
300 srl %o5,1,%o5
301 ! remainder is positive
302 subcc %o3,%o5,%o3
303 b 9f
304 add %o2, (-3*2+1), %o2
305
306L.4.13:
307 ! remainder is negative
308 addcc %o3,%o5,%o3
309 b 9f
310 add %o2, (-3*2-1), %o2
311
312L.2.15:
313 ! remainder is negative
314 addcc %o3,%o5,%o3
315 ! depth 3, accumulated bits -3
316 bl L.3.13
317 srl %o5,1,%o5
318 ! remainder is positive
319 subcc %o3,%o5,%o3
320 ! depth 4, accumulated bits -5
321 bl L.4.11
322 srl %o5,1,%o5
323 ! remainder is positive
324 subcc %o3,%o5,%o3
325 b 9f
326 add %o2, (-5*2+1), %o2
327
328L.4.11:
329 ! remainder is negative
330 addcc %o3,%o5,%o3
331 b 9f
332 add %o2, (-5*2-1), %o2
333
334
335L.3.13:
336 ! remainder is negative
337 addcc %o3,%o5,%o3
338 ! depth 4, accumulated bits -7
339 bl L.4.9
340 srl %o5,1,%o5
341 ! remainder is positive
342 subcc %o3,%o5,%o3
343 b 9f
344 add %o2, (-7*2+1), %o2
345
346L.4.9:
347 ! remainder is negative
348 addcc %o3,%o5,%o3
349 b 9f
350 add %o2, (-7*2-1), %o2
351
352 9:
353Lend_regular_divide:
354 subcc %o4, 1, %o4
355 bge Ldivloop
356 tst %o3
357
358 bl,a Lgot_result
359 ! non-restoring fixup here (one instruction only!)
360 add %o3, %o1, %o3
361
362Lgot_result:
363 ! check to see if answer should be < 0
364 tst %g2
365 bl,a 1f
366 sub %g0, %o3, %o3
3671:
368 retl
369 mov %o3, %o0
370
371 .globl .rem_patch
372.rem_patch:
373 sra %o0, 0x1f, %o4
374 wr %o4, 0x0, %y
375 nop
376 nop
377 nop
378 sdivcc %o0, %o1, %o2
379 bvs,a 1f
380 xnor %o2, %g0, %o2
3811: smul %o2, %o1, %o2
382 retl
383 sub %o0, %o2, %o0
384 nop
diff --git a/arch/sparc/lib/sdiv.S b/arch/sparc/lib/sdiv.S
deleted file mode 100644
index f0a0d4e4db78..000000000000
--- a/arch/sparc/lib/sdiv.S
+++ /dev/null
@@ -1,381 +0,0 @@
1/*
2 * sdiv.S: This routine was taken from glibc-1.09 and is covered
3 * by the GNU Library General Public License Version 2.
4 */
5
6
7/* This file is generated from divrem.m4; DO NOT EDIT! */
8/*
9 * Division and remainder, from Appendix E of the Sparc Version 8
10 * Architecture Manual, with fixes from Gordon Irlam.
11 */
12
13/*
14 * Input: dividend and divisor in %o0 and %o1 respectively.
15 *
16 * m4 parameters:
17 * .div name of function to generate
18 * div div=div => %o0 / %o1; div=rem => %o0 % %o1
19 * true true=true => signed; true=false => unsigned
20 *
21 * Algorithm parameters:
22 * N how many bits per iteration we try to get (4)
23 * WORDSIZE total number of bits (32)
24 *
25 * Derived constants:
26 * TOPBITS number of bits in the top decade of a number
27 *
28 * Important variables:
29 * Q the partial quotient under development (initially 0)
30 * R the remainder so far, initially the dividend
31 * ITER number of main division loop iterations required;
32 * equal to ceil(log2(quotient) / N). Note that this
33 * is the log base (2^N) of the quotient.
34 * V the current comparand, initially divisor*2^(ITER*N-1)
35 *
36 * Cost:
37 * Current estimate for non-large dividend is
38 * ceil(log2(quotient) / N) * (10 + 7N/2) + C
39 * A large dividend is one greater than 2^(31-TOPBITS) and takes a
40 * different path, as the upper bits of the quotient must be developed
41 * one bit at a time.
42 */
43
44
45 .globl .div
46 .globl _Div
47.div:
48_Div: /* needed for export */
49 ! compute sign of result; if neither is negative, no problem
50 orcc %o1, %o0, %g0 ! either negative?
51 bge 2f ! no, go do the divide
52 xor %o1, %o0, %g2 ! compute sign in any case
53
54 tst %o1
55 bge 1f
56 tst %o0
57 ! %o1 is definitely negative; %o0 might also be negative
58 bge 2f ! if %o0 not negative...
59 sub %g0, %o1, %o1 ! in any case, make %o1 nonneg
601: ! %o0 is negative, %o1 is nonnegative
61 sub %g0, %o0, %o0 ! make %o0 nonnegative
622:
63
64 ! Ready to divide. Compute size of quotient; scale comparand.
65 orcc %o1, %g0, %o5
66 bne 1f
67 mov %o0, %o3
68
69 ! Divide by zero trap. If it returns, return 0 (about as
70 ! wrong as possible, but that is what SunOS does...).
71 ta ST_DIV0
72 retl
73 clr %o0
74
751:
76 cmp %o3, %o5 ! if %o1 exceeds %o0, done
77 blu Lgot_result ! (and algorithm fails otherwise)
78 clr %o2
79
80 sethi %hi(1 << (32 - 4 - 1)), %g1
81
82 cmp %o3, %g1
83 blu Lnot_really_big
84 clr %o4
85
86 ! Here the dividend is >= 2**(31-N) or so. We must be careful here,
87 ! as our usual N-at-a-shot divide step will cause overflow and havoc.
88 ! The number of bits in the result here is N*ITER+SC, where SC <= N.
89 ! Compute ITER in an unorthodox manner: know we need to shift V into
90 ! the top decade: so do not even bother to compare to R.
91 1:
92 cmp %o5, %g1
93 bgeu 3f
94 mov 1, %g7
95
96 sll %o5, 4, %o5
97
98 b 1b
99 add %o4, 1, %o4
100
101 ! Now compute %g7.
102 2:
103 addcc %o5, %o5, %o5
104 bcc Lnot_too_big
105 add %g7, 1, %g7
106
107 ! We get here if the %o1 overflowed while shifting.
108 ! This means that %o3 has the high-order bit set.
109 ! Restore %o5 and subtract from %o3.
110 sll %g1, 4, %g1 ! high order bit
111 srl %o5, 1, %o5 ! rest of %o5
112 add %o5, %g1, %o5
113
114 b Ldo_single_div
115 sub %g7, 1, %g7
116
117 Lnot_too_big:
118 3:
119 cmp %o5, %o3
120 blu 2b
121 nop
122
123 be Ldo_single_div
124 nop
125 /* NB: these are commented out in the V8-Sparc manual as well */
126 /* (I do not understand this) */
127 ! %o5 > %o3: went too far: back up 1 step
128 ! srl %o5, 1, %o5
129 ! dec %g7
130 ! do single-bit divide steps
131 !
132 ! We have to be careful here. We know that %o3 >= %o5, so we can do the
133 ! first divide step without thinking. BUT, the others are conditional,
134 ! and are only done if %o3 >= 0. Because both %o3 and %o5 may have the high-
135 ! order bit set in the first step, just falling into the regular
136 ! division loop will mess up the first time around.
137 ! So we unroll slightly...
138 Ldo_single_div:
139 subcc %g7, 1, %g7
140 bl Lend_regular_divide
141 nop
142
143 sub %o3, %o5, %o3
144 mov 1, %o2
145
146 b Lend_single_divloop
147 nop
148 Lsingle_divloop:
149 sll %o2, 1, %o2
150
151 bl 1f
152 srl %o5, 1, %o5
153 ! %o3 >= 0
154 sub %o3, %o5, %o3
155
156 b 2f
157 add %o2, 1, %o2
158 1: ! %o3 < 0
159 add %o3, %o5, %o3
160 sub %o2, 1, %o2
161 2:
162 Lend_single_divloop:
163 subcc %g7, 1, %g7
164 bge Lsingle_divloop
165 tst %o3
166
167 b,a Lend_regular_divide
168
169Lnot_really_big:
1701:
171 sll %o5, 4, %o5
172 cmp %o5, %o3
173 bleu 1b
174 addcc %o4, 1, %o4
175
176 be Lgot_result
177 sub %o4, 1, %o4
178
179 tst %o3 ! set up for initial iteration
180Ldivloop:
181 sll %o2, 4, %o2
182 ! depth 1, accumulated bits 0
183 bl L.1.16
184 srl %o5,1,%o5
185 ! remainder is positive
186 subcc %o3,%o5,%o3
187 ! depth 2, accumulated bits 1
188 bl L.2.17
189 srl %o5,1,%o5
190 ! remainder is positive
191 subcc %o3,%o5,%o3
192 ! depth 3, accumulated bits 3
193 bl L.3.19
194 srl %o5,1,%o5
195 ! remainder is positive
196 subcc %o3,%o5,%o3
197 ! depth 4, accumulated bits 7
198 bl L.4.23
199 srl %o5,1,%o5
200 ! remainder is positive
201 subcc %o3,%o5,%o3
202 b 9f
203 add %o2, (7*2+1), %o2
204
205L.4.23:
206 ! remainder is negative
207 addcc %o3,%o5,%o3
208 b 9f
209 add %o2, (7*2-1), %o2
210
211L.3.19:
212 ! remainder is negative
213 addcc %o3,%o5,%o3
214 ! depth 4, accumulated bits 5
215 bl L.4.21
216 srl %o5,1,%o5
217 ! remainder is positive
218 subcc %o3,%o5,%o3
219 b 9f
220 add %o2, (5*2+1), %o2
221
222L.4.21:
223 ! remainder is negative
224 addcc %o3,%o5,%o3
225 b 9f
226 add %o2, (5*2-1), %o2
227
228L.2.17:
229 ! remainder is negative
230 addcc %o3,%o5,%o3
231 ! depth 3, accumulated bits 1
232 bl L.3.17
233 srl %o5,1,%o5
234 ! remainder is positive
235 subcc %o3,%o5,%o3
236 ! depth 4, accumulated bits 3
237 bl L.4.19
238 srl %o5,1,%o5
239 ! remainder is positive
240 subcc %o3,%o5,%o3
241 b 9f
242 add %o2, (3*2+1), %o2
243
244L.4.19:
245 ! remainder is negative
246 addcc %o3,%o5,%o3
247 b 9f
248 add %o2, (3*2-1), %o2
249
250
251L.3.17:
252 ! remainder is negative
253 addcc %o3,%o5,%o3
254 ! depth 4, accumulated bits 1
255 bl L.4.17
256 srl %o5,1,%o5
257 ! remainder is positive
258 subcc %o3,%o5,%o3
259 b 9f
260 add %o2, (1*2+1), %o2
261
262L.4.17:
263 ! remainder is negative
264 addcc %o3,%o5,%o3
265 b 9f
266 add %o2, (1*2-1), %o2
267
268L.1.16:
269 ! remainder is negative
270 addcc %o3,%o5,%o3
271 ! depth 2, accumulated bits -1
272 bl L.2.15
273 srl %o5,1,%o5
274 ! remainder is positive
275 subcc %o3,%o5,%o3
276 ! depth 3, accumulated bits -1
277 bl L.3.15
278 srl %o5,1,%o5
279 ! remainder is positive
280 subcc %o3,%o5,%o3
281 ! depth 4, accumulated bits -1
282 bl L.4.15
283 srl %o5,1,%o5
284 ! remainder is positive
285 subcc %o3,%o5,%o3
286 b 9f
287 add %o2, (-1*2+1), %o2
288
289L.4.15:
290 ! remainder is negative
291 addcc %o3,%o5,%o3
292 b 9f
293 add %o2, (-1*2-1), %o2
294
295L.3.15:
296 ! remainder is negative
297 addcc %o3,%o5,%o3
298 ! depth 4, accumulated bits -3
299 bl L.4.13
300 srl %o5,1,%o5
301 ! remainder is positive
302 subcc %o3,%o5,%o3
303 b 9f
304 add %o2, (-3*2+1), %o2
305
306L.4.13:
307 ! remainder is negative
308 addcc %o3,%o5,%o3
309 b 9f
310 add %o2, (-3*2-1), %o2
311
312L.2.15:
313 ! remainder is negative
314 addcc %o3,%o5,%o3
315 ! depth 3, accumulated bits -3
316 bl L.3.13
317 srl %o5,1,%o5
318 ! remainder is positive
319 subcc %o3,%o5,%o3
320 ! depth 4, accumulated bits -5
321 bl L.4.11
322 srl %o5,1,%o5
323 ! remainder is positive
324 subcc %o3,%o5,%o3
325 b 9f
326 add %o2, (-5*2+1), %o2
327
328L.4.11:
329 ! remainder is negative
330 addcc %o3,%o5,%o3
331 b 9f
332 add %o2, (-5*2-1), %o2
333
334L.3.13:
335 ! remainder is negative
336 addcc %o3,%o5,%o3
337 ! depth 4, accumulated bits -7
338 bl L.4.9
339 srl %o5,1,%o5
340 ! remainder is positive
341 subcc %o3,%o5,%o3
342 b 9f
343 add %o2, (-7*2+1), %o2
344
345L.4.9:
346 ! remainder is negative
347 addcc %o3,%o5,%o3
348 b 9f
349 add %o2, (-7*2-1), %o2
350
351 9:
352Lend_regular_divide:
353 subcc %o4, 1, %o4
354 bge Ldivloop
355 tst %o3
356
357 bl,a Lgot_result
358 ! non-restoring fixup here (one instruction only!)
359 sub %o2, 1, %o2
360
361Lgot_result:
362 ! check to see if answer should be < 0
363 tst %g2
364 bl,a 1f
365 sub %g0, %o2, %o2
3661:
367 retl
368 mov %o2, %o0
369
370 .globl .div_patch
371.div_patch:
372 sra %o0, 0x1f, %o2
373 wr %o2, 0x0, %y
374 nop
375 nop
376 nop
377 sdivcc %o0, %o1, %o0
378 bvs,a 1f
379 xnor %o0, %g0, %o0
3801: retl
381 nop
diff --git a/arch/sparc/lib/strlen_user_64.S b/arch/sparc/lib/strlen_user_64.S
index 114ed111e251..c3df71fa4928 100644
--- a/arch/sparc/lib/strlen_user_64.S
+++ b/arch/sparc/lib/strlen_user_64.S
@@ -8,16 +8,16 @@
8 * Copyright (C) 1996,1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz) 8 * Copyright (C) 1996,1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
9 */ 9 */
10 10
11#include <linux/linkage.h>
11#include <asm/asi.h> 12#include <asm/asi.h>
12 13
13#define LO_MAGIC 0x01010101 14#define LO_MAGIC 0x01010101
14#define HI_MAGIC 0x80808080 15#define HI_MAGIC 0x80808080
15 16
16 .align 4 17 .align 4
17 .global __strlen_user, __strnlen_user 18ENTRY(__strlen_user)
18__strlen_user:
19 sethi %hi(32768), %o1 19 sethi %hi(32768), %o1
20__strnlen_user: 20ENTRY(__strnlen_user)
21 mov %o1, %g1 21 mov %o1, %g1
22 mov %o0, %o1 22 mov %o0, %o1
23 andcc %o0, 3, %g0 23 andcc %o0, 3, %g0
@@ -78,6 +78,8 @@ __strnlen_user:
78 mov 2, %o0 78 mov 2, %o0
7923: retl 7923: retl
80 mov 3, %o0 80 mov 3, %o0
81ENDPROC(__strlen_user)
82ENDPROC(__strnlen_user)
81 83
82 .section .fixup,#alloc,#execinstr 84 .section .fixup,#alloc,#execinstr
83 .align 4 85 .align 4
diff --git a/arch/sparc/lib/strncmp_32.S b/arch/sparc/lib/strncmp_32.S
index 494ec664537a..c0d1b568c1c5 100644
--- a/arch/sparc/lib/strncmp_32.S
+++ b/arch/sparc/lib/strncmp_32.S
@@ -3,11 +3,10 @@
3 * generic strncmp routine. 3 * generic strncmp routine.
4 */ 4 */
5 5
6#include <linux/linkage.h>
7
6 .text 8 .text
7 .align 4 9ENTRY(strncmp)
8 .global __strncmp, strncmp
9__strncmp:
10strncmp:
11 mov %o0, %g3 10 mov %o0, %g3
12 mov 0, %o3 11 mov 0, %o3
13 12
@@ -116,3 +115,4 @@ strncmp:
116 and %g2, 0xff, %o0 115 and %g2, 0xff, %o0
117 retl 116 retl
118 sub %o3, %o0, %o0 117 sub %o3, %o0, %o0
118ENDPROC(strncmp)
diff --git a/arch/sparc/lib/strncmp_64.S b/arch/sparc/lib/strncmp_64.S
index 980e83751556..0656627166f3 100644
--- a/arch/sparc/lib/strncmp_64.S
+++ b/arch/sparc/lib/strncmp_64.S
@@ -4,13 +4,11 @@
4 * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz) 4 * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
5 */ 5 */
6 6
7#include <linux/linkage.h>
7#include <asm/asi.h> 8#include <asm/asi.h>
8 9
9 .text 10 .text
10 .align 32 11ENTRY(strncmp)
11 .globl strncmp
12 .type strncmp,#function
13strncmp:
14 brlez,pn %o2, 3f 12 brlez,pn %o2, 3f
15 lduba [%o0] (ASI_PNF), %o3 13 lduba [%o0] (ASI_PNF), %o3
161: 141:
@@ -29,4 +27,4 @@ strncmp:
293: 273:
30 retl 28 retl
31 clr %o0 29 clr %o0
32 .size strncmp, .-strncmp 30ENDPROC(strncmp)
diff --git a/arch/sparc/lib/strncpy_from_user_32.S b/arch/sparc/lib/strncpy_from_user_32.S
index d77198976a66..db0ed2964bdb 100644
--- a/arch/sparc/lib/strncpy_from_user_32.S
+++ b/arch/sparc/lib/strncpy_from_user_32.S
@@ -3,11 +3,11 @@
3 * Copyright(C) 1996 David S. Miller 3 * Copyright(C) 1996 David S. Miller
4 */ 4 */
5 5
6#include <linux/linkage.h>
6#include <asm/ptrace.h> 7#include <asm/ptrace.h>
7#include <asm/errno.h> 8#include <asm/errno.h>
8 9
9 .text 10 .text
10 .align 4
11 11
12 /* Must return: 12 /* Must return:
13 * 13 *
@@ -16,8 +16,7 @@
16 * bytes copied if we hit a null byte 16 * bytes copied if we hit a null byte
17 */ 17 */
18 18
19 .globl __strncpy_from_user 19ENTRY(__strncpy_from_user)
20__strncpy_from_user:
21 /* %o0=dest, %o1=src, %o2=count */ 20 /* %o0=dest, %o1=src, %o2=count */
22 mov %o2, %o3 21 mov %o2, %o3
231: 221:
@@ -35,6 +34,7 @@ __strncpy_from_user:
35 add %o2, 1, %o0 34 add %o2, 1, %o0
36 retl 35 retl
37 sub %o3, %o0, %o0 36 sub %o3, %o0, %o0
37ENDPROC(__strncpy_from_user)
38 38
39 .section .fixup,#alloc,#execinstr 39 .section .fixup,#alloc,#execinstr
40 .align 4 40 .align 4
diff --git a/arch/sparc/lib/strncpy_from_user_64.S b/arch/sparc/lib/strncpy_from_user_64.S
index 511c8f136f95..d1246b713077 100644
--- a/arch/sparc/lib/strncpy_from_user_64.S
+++ b/arch/sparc/lib/strncpy_from_user_64.S
@@ -4,6 +4,7 @@
4 * Copyright (C) 1997, 1999 Jakub Jelinek (jj@ultra.linux.cz) 4 * Copyright (C) 1997, 1999 Jakub Jelinek (jj@ultra.linux.cz)
5 */ 5 */
6 6
7#include <linux/linkage.h>
7#include <asm/asi.h> 8#include <asm/asi.h>
8#include <asm/errno.h> 9#include <asm/errno.h>
9 10
@@ -12,7 +13,6 @@
120: .xword 0x0101010101010101 130: .xword 0x0101010101010101
13 14
14 .text 15 .text
15 .align 32
16 16
17 /* Must return: 17 /* Must return:
18 * 18 *
@@ -30,9 +30,7 @@
30 * and average length is 18 or so. 30 * and average length is 18 or so.
31 */ 31 */
32 32
33 .globl __strncpy_from_user 33ENTRY(__strncpy_from_user)
34 .type __strncpy_from_user,#function
35__strncpy_from_user:
36 /* %o0=dest, %o1=src, %o2=count */ 34 /* %o0=dest, %o1=src, %o2=count */
37 andcc %o1, 7, %g0 ! IEU1 Group 35 andcc %o1, 7, %g0 ! IEU1 Group
38 bne,pn %icc, 30f ! CTI 36 bne,pn %icc, 30f ! CTI
@@ -123,7 +121,7 @@ __strncpy_from_user:
123 mov %o2, %o0 121 mov %o2, %o0
1242: retl 1222: retl
125 add %o2, %o3, %o0 123 add %o2, %o3, %o0
126 .size __strncpy_from_user, .-__strncpy_from_user 124ENDPROC(__strncpy_from_user)
127 125
128 .section __ex_table,"a" 126 .section __ex_table,"a"
129 .align 4 127 .align 4
diff --git a/arch/sparc/lib/ucmpdi2.c b/arch/sparc/lib/ucmpdi2.c
new file mode 100644
index 000000000000..1e06ed500682
--- /dev/null
+++ b/arch/sparc/lib/ucmpdi2.c
@@ -0,0 +1,19 @@
1#include <linux/module.h>
2#include "libgcc.h"
3
4word_type __ucmpdi2(unsigned long long a, unsigned long long b)
5{
6 const DWunion au = {.ll = a};
7 const DWunion bu = {.ll = b};
8
9 if ((unsigned int) au.s.high < (unsigned int) bu.s.high)
10 return 0;
11 else if ((unsigned int) au.s.high > (unsigned int) bu.s.high)
12 return 2;
13 if ((unsigned int) au.s.low < (unsigned int) bu.s.low)
14 return 0;
15 else if ((unsigned int) au.s.low > (unsigned int) bu.s.low)
16 return 2;
17 return 1;
18}
19EXPORT_SYMBOL(__ucmpdi2);
diff --git a/arch/sparc/lib/udiv.S b/arch/sparc/lib/udiv.S
deleted file mode 100644
index 2101405bdfcb..000000000000
--- a/arch/sparc/lib/udiv.S
+++ /dev/null
@@ -1,357 +0,0 @@
1/*
2 * udiv.S: This routine was taken from glibc-1.09 and is covered
3 * by the GNU Library General Public License Version 2.
4 */
5
6
7/* This file is generated from divrem.m4; DO NOT EDIT! */
8/*
9 * Division and remainder, from Appendix E of the Sparc Version 8
10 * Architecture Manual, with fixes from Gordon Irlam.
11 */
12
13/*
14 * Input: dividend and divisor in %o0 and %o1 respectively.
15 *
16 * m4 parameters:
17 * .udiv name of function to generate
18 * div div=div => %o0 / %o1; div=rem => %o0 % %o1
19 * false false=true => signed; false=false => unsigned
20 *
21 * Algorithm parameters:
22 * N how many bits per iteration we try to get (4)
23 * WORDSIZE total number of bits (32)
24 *
25 * Derived constants:
26 * TOPBITS number of bits in the top decade of a number
27 *
28 * Important variables:
29 * Q the partial quotient under development (initially 0)
30 * R the remainder so far, initially the dividend
31 * ITER number of main division loop iterations required;
32 * equal to ceil(log2(quotient) / N). Note that this
33 * is the log base (2^N) of the quotient.
34 * V the current comparand, initially divisor*2^(ITER*N-1)
35 *
36 * Cost:
37 * Current estimate for non-large dividend is
38 * ceil(log2(quotient) / N) * (10 + 7N/2) + C
39 * A large dividend is one greater than 2^(31-TOPBITS) and takes a
40 * different path, as the upper bits of the quotient must be developed
41 * one bit at a time.
42 */
43
44
45 .globl .udiv
46 .globl _Udiv
47.udiv:
48_Udiv: /* needed for export */
49
50 ! Ready to divide. Compute size of quotient; scale comparand.
51 orcc %o1, %g0, %o5
52 bne 1f
53 mov %o0, %o3
54
55 ! Divide by zero trap. If it returns, return 0 (about as
56 ! wrong as possible, but that is what SunOS does...).
57 ta ST_DIV0
58 retl
59 clr %o0
60
611:
62 cmp %o3, %o5 ! if %o1 exceeds %o0, done
63 blu Lgot_result ! (and algorithm fails otherwise)
64 clr %o2
65
66 sethi %hi(1 << (32 - 4 - 1)), %g1
67
68 cmp %o3, %g1
69 blu Lnot_really_big
70 clr %o4
71
72 ! Here the dividend is >= 2**(31-N) or so. We must be careful here,
73 ! as our usual N-at-a-shot divide step will cause overflow and havoc.
74 ! The number of bits in the result here is N*ITER+SC, where SC <= N.
75 ! Compute ITER in an unorthodox manner: know we need to shift V into
76 ! the top decade: so do not even bother to compare to R.
77 1:
78 cmp %o5, %g1
79 bgeu 3f
80 mov 1, %g7
81
82 sll %o5, 4, %o5
83
84 b 1b
85 add %o4, 1, %o4
86
87 ! Now compute %g7.
88 2:
89 addcc %o5, %o5, %o5
90 bcc Lnot_too_big
91 add %g7, 1, %g7
92
93 ! We get here if the %o1 overflowed while shifting.
94 ! This means that %o3 has the high-order bit set.
95 ! Restore %o5 and subtract from %o3.
96 sll %g1, 4, %g1 ! high order bit
97 srl %o5, 1, %o5 ! rest of %o5
98 add %o5, %g1, %o5
99
100 b Ldo_single_div
101 sub %g7, 1, %g7
102
103 Lnot_too_big:
104 3:
105 cmp %o5, %o3
106 blu 2b
107 nop
108
109 be Ldo_single_div
110 nop
111 /* NB: these are commented out in the V8-Sparc manual as well */
112 /* (I do not understand this) */
113 ! %o5 > %o3: went too far: back up 1 step
114 ! srl %o5, 1, %o5
115 ! dec %g7
116 ! do single-bit divide steps
117 !
118 ! We have to be careful here. We know that %o3 >= %o5, so we can do the
119 ! first divide step without thinking. BUT, the others are conditional,
120 ! and are only done if %o3 >= 0. Because both %o3 and %o5 may have the high-
121 ! order bit set in the first step, just falling into the regular
122 ! division loop will mess up the first time around.
123 ! So we unroll slightly...
124 Ldo_single_div:
125 subcc %g7, 1, %g7
126 bl Lend_regular_divide
127 nop
128
129 sub %o3, %o5, %o3
130 mov 1, %o2
131
132 b Lend_single_divloop
133 nop
134 Lsingle_divloop:
135 sll %o2, 1, %o2
136 bl 1f
137 srl %o5, 1, %o5
138 ! %o3 >= 0
139 sub %o3, %o5, %o3
140 b 2f
141 add %o2, 1, %o2
142 1: ! %o3 < 0
143 add %o3, %o5, %o3
144 sub %o2, 1, %o2
145 2:
146 Lend_single_divloop:
147 subcc %g7, 1, %g7
148 bge Lsingle_divloop
149 tst %o3
150
151 b,a Lend_regular_divide
152
153Lnot_really_big:
1541:
155 sll %o5, 4, %o5
156
157 cmp %o5, %o3
158 bleu 1b
159 addcc %o4, 1, %o4
160
161 be Lgot_result
162 sub %o4, 1, %o4
163
164 tst %o3 ! set up for initial iteration
165Ldivloop:
166 sll %o2, 4, %o2
167 ! depth 1, accumulated bits 0
168 bl L.1.16
169 srl %o5,1,%o5
170 ! remainder is positive
171 subcc %o3,%o5,%o3
172 ! depth 2, accumulated bits 1
173 bl L.2.17
174 srl %o5,1,%o5
175 ! remainder is positive
176 subcc %o3,%o5,%o3
177 ! depth 3, accumulated bits 3
178 bl L.3.19
179 srl %o5,1,%o5
180 ! remainder is positive
181 subcc %o3,%o5,%o3
182 ! depth 4, accumulated bits 7
183 bl L.4.23
184 srl %o5,1,%o5
185 ! remainder is positive
186 subcc %o3,%o5,%o3
187 b 9f
188 add %o2, (7*2+1), %o2
189
190L.4.23:
191 ! remainder is negative
192 addcc %o3,%o5,%o3
193 b 9f
194 add %o2, (7*2-1), %o2
195
196L.3.19:
197 ! remainder is negative
198 addcc %o3,%o5,%o3
199 ! depth 4, accumulated bits 5
200 bl L.4.21
201 srl %o5,1,%o5
202 ! remainder is positive
203 subcc %o3,%o5,%o3
204 b 9f
205 add %o2, (5*2+1), %o2
206
207L.4.21:
208 ! remainder is negative
209 addcc %o3,%o5,%o3
210 b 9f
211 add %o2, (5*2-1), %o2
212
213L.2.17:
214 ! remainder is negative
215 addcc %o3,%o5,%o3
216 ! depth 3, accumulated bits 1
217 bl L.3.17
218 srl %o5,1,%o5
219 ! remainder is positive
220 subcc %o3,%o5,%o3
221 ! depth 4, accumulated bits 3
222 bl L.4.19
223 srl %o5,1,%o5
224 ! remainder is positive
225 subcc %o3,%o5,%o3
226 b 9f
227 add %o2, (3*2+1), %o2
228
229L.4.19:
230 ! remainder is negative
231 addcc %o3,%o5,%o3
232 b 9f
233 add %o2, (3*2-1), %o2
234
235L.3.17:
236 ! remainder is negative
237 addcc %o3,%o5,%o3
238 ! depth 4, accumulated bits 1
239 bl L.4.17
240 srl %o5,1,%o5
241 ! remainder is positive
242 subcc %o3,%o5,%o3
243 b 9f
244 add %o2, (1*2+1), %o2
245
246L.4.17:
247 ! remainder is negative
248 addcc %o3,%o5,%o3
249 b 9f
250 add %o2, (1*2-1), %o2
251
252L.1.16:
253 ! remainder is negative
254 addcc %o3,%o5,%o3
255 ! depth 2, accumulated bits -1
256 bl L.2.15
257 srl %o5,1,%o5
258 ! remainder is positive
259 subcc %o3,%o5,%o3
260 ! depth 3, accumulated bits -1
261 bl L.3.15
262 srl %o5,1,%o5
263 ! remainder is positive
264 subcc %o3,%o5,%o3
265 ! depth 4, accumulated bits -1
266 bl L.4.15
267 srl %o5,1,%o5
268 ! remainder is positive
269 subcc %o3,%o5,%o3
270 b 9f
271 add %o2, (-1*2+1), %o2
272
273L.4.15:
274 ! remainder is negative
275 addcc %o3,%o5,%o3
276 b 9f
277 add %o2, (-1*2-1), %o2
278
279L.3.15:
280 ! remainder is negative
281 addcc %o3,%o5,%o3
282 ! depth 4, accumulated bits -3
283 bl L.4.13
284 srl %o5,1,%o5
285 ! remainder is positive
286 subcc %o3,%o5,%o3
287 b 9f
288 add %o2, (-3*2+1), %o2
289
290L.4.13:
291 ! remainder is negative
292 addcc %o3,%o5,%o3
293 b 9f
294 add %o2, (-3*2-1), %o2
295
296L.2.15:
297 ! remainder is negative
298 addcc %o3,%o5,%o3
299 ! depth 3, accumulated bits -3
300 bl L.3.13
301 srl %o5,1,%o5
302 ! remainder is positive
303 subcc %o3,%o5,%o3
304 ! depth 4, accumulated bits -5
305 bl L.4.11
306 srl %o5,1,%o5
307 ! remainder is positive
308 subcc %o3,%o5,%o3
309 b 9f
310 add %o2, (-5*2+1), %o2
311
312L.4.11:
313 ! remainder is negative
314 addcc %o3,%o5,%o3
315 b 9f
316 add %o2, (-5*2-1), %o2
317
318L.3.13:
319 ! remainder is negative
320 addcc %o3,%o5,%o3
321 ! depth 4, accumulated bits -7
322 bl L.4.9
323 srl %o5,1,%o5
324 ! remainder is positive
325 subcc %o3,%o5,%o3
326 b 9f
327 add %o2, (-7*2+1), %o2
328
329L.4.9:
330 ! remainder is negative
331 addcc %o3,%o5,%o3
332 b 9f
333 add %o2, (-7*2-1), %o2
334
335 9:
336Lend_regular_divide:
337 subcc %o4, 1, %o4
338 bge Ldivloop
339 tst %o3
340
341 bl,a Lgot_result
342 ! non-restoring fixup here (one instruction only!)
343 sub %o2, 1, %o2
344
345Lgot_result:
346
347 retl
348 mov %o2, %o0
349
350 .globl .udiv_patch
351.udiv_patch:
352 wr %g0, 0x0, %y
353 nop
354 nop
355 retl
356 udiv %o0, %o1, %o0
357 nop
diff --git a/arch/sparc/lib/udivdi3.S b/arch/sparc/lib/udivdi3.S
index b430f1f0ef62..24e0a355e2e8 100644
--- a/arch/sparc/lib/udivdi3.S
+++ b/arch/sparc/lib/udivdi3.S
@@ -60,8 +60,9 @@ __udivdi3:
60 bne .LL77 60 bne .LL77
61 mov %i0,%o2 61 mov %i0,%o2
62 mov 1,%o0 62 mov 1,%o0
63 call .udiv,0
64 mov 0,%o1 63 mov 0,%o1
64 wr %g0, 0, %y
65 udiv %o0, %o1, %o0
65 mov %o0,%o3 66 mov %o0,%o3
66 mov %i0,%o2 67 mov %i0,%o2
67.LL77: 68.LL77:
diff --git a/arch/sparc/lib/umul.S b/arch/sparc/lib/umul.S
deleted file mode 100644
index 1f36ae682529..000000000000
--- a/arch/sparc/lib/umul.S
+++ /dev/null
@@ -1,171 +0,0 @@
1/*
2 * umul.S: This routine was taken from glibc-1.09 and is covered
3 * by the GNU Library General Public License Version 2.
4 */
5
6
7/*
8 * Unsigned multiply. Returns %o0 * %o1 in %o1%o0 (i.e., %o1 holds the
9 * upper 32 bits of the 64-bit product).
10 *
11 * This code optimizes short (less than 13-bit) multiplies. Short
12 * multiplies require 25 instruction cycles, and long ones require
13 * 45 instruction cycles.
14 *
15 * On return, overflow has occurred (%o1 is not zero) if and only if
16 * the Z condition code is clear, allowing, e.g., the following:
17 *
18 * call .umul
19 * nop
20 * bnz overflow (or tnz)
21 */
22
23 .globl .umul
24 .globl _Umul
25.umul:
26_Umul: /* needed for export */
27 or %o0, %o1, %o4
28 mov %o0, %y ! multiplier -> Y
29
30 andncc %o4, 0xfff, %g0 ! test bits 12..31 of *both* args
31 be Lmul_shortway ! if zero, can do it the short way
32 andcc %g0, %g0, %o4 ! zero the partial product and clear N and V
33
34 /*
35 * Long multiply. 32 steps, followed by a final shift step.
36 */
37 mulscc %o4, %o1, %o4 ! 1
38 mulscc %o4, %o1, %o4 ! 2
39 mulscc %o4, %o1, %o4 ! 3
40 mulscc %o4, %o1, %o4 ! 4
41 mulscc %o4, %o1, %o4 ! 5
42 mulscc %o4, %o1, %o4 ! 6
43 mulscc %o4, %o1, %o4 ! 7
44 mulscc %o4, %o1, %o4 ! 8
45 mulscc %o4, %o1, %o4 ! 9
46 mulscc %o4, %o1, %o4 ! 10
47 mulscc %o4, %o1, %o4 ! 11
48 mulscc %o4, %o1, %o4 ! 12
49 mulscc %o4, %o1, %o4 ! 13
50 mulscc %o4, %o1, %o4 ! 14
51 mulscc %o4, %o1, %o4 ! 15
52 mulscc %o4, %o1, %o4 ! 16
53 mulscc %o4, %o1, %o4 ! 17
54 mulscc %o4, %o1, %o4 ! 18
55 mulscc %o4, %o1, %o4 ! 19
56 mulscc %o4, %o1, %o4 ! 20
57 mulscc %o4, %o1, %o4 ! 21
58 mulscc %o4, %o1, %o4 ! 22
59 mulscc %o4, %o1, %o4 ! 23
60 mulscc %o4, %o1, %o4 ! 24
61 mulscc %o4, %o1, %o4 ! 25
62 mulscc %o4, %o1, %o4 ! 26
63 mulscc %o4, %o1, %o4 ! 27
64 mulscc %o4, %o1, %o4 ! 28
65 mulscc %o4, %o1, %o4 ! 29
66 mulscc %o4, %o1, %o4 ! 30
67 mulscc %o4, %o1, %o4 ! 31
68 mulscc %o4, %o1, %o4 ! 32
69 mulscc %o4, %g0, %o4 ! final shift
70
71
72 /*
73 * Normally, with the shift-and-add approach, if both numbers are
74 * positive you get the correct result. With 32-bit two's-complement
75 * numbers, -x is represented as
76 *
77 * x 32
78 * ( 2 - ------ ) mod 2 * 2
79 * 32
80 * 2
81 *
82 * (the `mod 2' subtracts 1 from 1.bbbb). To avoid lots of 2^32s,
83 * we can treat this as if the radix point were just to the left
84 * of the sign bit (multiply by 2^32), and get
85 *
86 * -x = (2 - x) mod 2
87 *
88 * Then, ignoring the `mod 2's for convenience:
89 *
90 * x * y = xy
91 * -x * y = 2y - xy
92 * x * -y = 2x - xy
93 * -x * -y = 4 - 2x - 2y + xy
94 *
95 * For signed multiplies, we subtract (x << 32) from the partial
96 * product to fix this problem for negative multipliers (see mul.s).
97 * Because of the way the shift into the partial product is calculated
98 * (N xor V), this term is automatically removed for the multiplicand,
99 * so we don't have to adjust.
100 *
101 * But for unsigned multiplies, the high order bit wasn't a sign bit,
102 * and the correction is wrong. So for unsigned multiplies where the
103 * high order bit is one, we end up with xy - (y << 32). To fix it
104 * we add y << 32.
105 */
106#if 0
107 tst %o1
108 bl,a 1f ! if %o1 < 0 (high order bit = 1),
109 add %o4, %o0, %o4 ! %o4 += %o0 (add y to upper half)
110
1111:
112 rd %y, %o0 ! get lower half of product
113 retl
114 addcc %o4, %g0, %o1 ! put upper half in place and set Z for %o1==0
115#else
116 /* Faster code from tege@sics.se. */
117 sra %o1, 31, %o2 ! make mask from sign bit
118 and %o0, %o2, %o2 ! %o2 = 0 or %o0, depending on sign of %o1
119 rd %y, %o0 ! get lower half of product
120 retl
121 addcc %o4, %o2, %o1 ! add compensation and put upper half in place
122#endif
123
124Lmul_shortway:
125 /*
126 * Short multiply. 12 steps, followed by a final shift step.
127 * The resulting bits are off by 12 and (32-12) = 20 bit positions,
128 * but there is no problem with %o0 being negative (unlike above),
129 * and overflow is impossible (the answer is at most 24 bits long).
130 */
131 mulscc %o4, %o1, %o4 ! 1
132 mulscc %o4, %o1, %o4 ! 2
133 mulscc %o4, %o1, %o4 ! 3
134 mulscc %o4, %o1, %o4 ! 4
135 mulscc %o4, %o1, %o4 ! 5
136 mulscc %o4, %o1, %o4 ! 6
137 mulscc %o4, %o1, %o4 ! 7
138 mulscc %o4, %o1, %o4 ! 8
139 mulscc %o4, %o1, %o4 ! 9
140 mulscc %o4, %o1, %o4 ! 10
141 mulscc %o4, %o1, %o4 ! 11
142 mulscc %o4, %o1, %o4 ! 12
143 mulscc %o4, %g0, %o4 ! final shift
144
145 /*
146 * %o4 has 20 of the bits that should be in the result; %y has
147 * the bottom 12 (as %y's top 12). That is:
148 *
149 * %o4 %y
150 * +----------------+----------------+
151 * | -12- | -20- | -12- | -20- |
152 * +------(---------+------)---------+
153 * -----result-----
154 *
155 * The 12 bits of %o4 left of the `result' area are all zero;
156 * in fact, all top 20 bits of %o4 are zero.
157 */
158
159 rd %y, %o5
160 sll %o4, 12, %o0 ! shift middle bits left 12
161 srl %o5, 20, %o5 ! shift low bits right 20
162 or %o5, %o0, %o0
163 retl
164 addcc %g0, %g0, %o1 ! %o1 = zero, and set Z
165
166 .globl .umul_patch
167.umul_patch:
168 umul %o0, %o1, %o0
169 retl
170 rd %y, %o1
171 nop
diff --git a/arch/sparc/lib/urem.S b/arch/sparc/lib/urem.S
deleted file mode 100644
index 77123eb83c44..000000000000
--- a/arch/sparc/lib/urem.S
+++ /dev/null
@@ -1,357 +0,0 @@
1/*
2 * urem.S: This routine was taken from glibc-1.09 and is covered
3 * by the GNU Library General Public License Version 2.
4 */
5
6/* This file is generated from divrem.m4; DO NOT EDIT! */
7/*
8 * Division and remainder, from Appendix E of the Sparc Version 8
9 * Architecture Manual, with fixes from Gordon Irlam.
10 */
11
12/*
13 * Input: dividend and divisor in %o0 and %o1 respectively.
14 *
15 * m4 parameters:
16 * .urem name of function to generate
17 * rem rem=div => %o0 / %o1; rem=rem => %o0 % %o1
18 * false false=true => signed; false=false => unsigned
19 *
20 * Algorithm parameters:
21 * N how many bits per iteration we try to get (4)
22 * WORDSIZE total number of bits (32)
23 *
24 * Derived constants:
25 * TOPBITS number of bits in the top decade of a number
26 *
27 * Important variables:
28 * Q the partial quotient under development (initially 0)
29 * R the remainder so far, initially the dividend
30 * ITER number of main division loop iterations required;
31 * equal to ceil(log2(quotient) / N). Note that this
32 * is the log base (2^N) of the quotient.
33 * V the current comparand, initially divisor*2^(ITER*N-1)
34 *
35 * Cost:
36 * Current estimate for non-large dividend is
37 * ceil(log2(quotient) / N) * (10 + 7N/2) + C
38 * A large dividend is one greater than 2^(31-TOPBITS) and takes a
39 * different path, as the upper bits of the quotient must be developed
40 * one bit at a time.
41 */
42
43 .globl .urem
44 .globl _Urem
45.urem:
46_Urem: /* needed for export */
47
48 ! Ready to divide. Compute size of quotient; scale comparand.
49 orcc %o1, %g0, %o5
50 bne 1f
51 mov %o0, %o3
52
53 ! Divide by zero trap. If it returns, return 0 (about as
54 ! wrong as possible, but that is what SunOS does...).
55 ta ST_DIV0
56 retl
57 clr %o0
58
591:
60 cmp %o3, %o5 ! if %o1 exceeds %o0, done
61 blu Lgot_result ! (and algorithm fails otherwise)
62 clr %o2
63
64 sethi %hi(1 << (32 - 4 - 1)), %g1
65
66 cmp %o3, %g1
67 blu Lnot_really_big
68 clr %o4
69
70 ! Here the dividend is >= 2**(31-N) or so. We must be careful here,
71 ! as our usual N-at-a-shot divide step will cause overflow and havoc.
72 ! The number of bits in the result here is N*ITER+SC, where SC <= N.
73 ! Compute ITER in an unorthodox manner: know we need to shift V into
74 ! the top decade: so do not even bother to compare to R.
75 1:
76 cmp %o5, %g1
77 bgeu 3f
78 mov 1, %g7
79
80 sll %o5, 4, %o5
81
82 b 1b
83 add %o4, 1, %o4
84
85 ! Now compute %g7.
86 2:
87 addcc %o5, %o5, %o5
88 bcc Lnot_too_big
89 add %g7, 1, %g7
90
91 ! We get here if the %o1 overflowed while shifting.
92 ! This means that %o3 has the high-order bit set.
93 ! Restore %o5 and subtract from %o3.
94 sll %g1, 4, %g1 ! high order bit
95 srl %o5, 1, %o5 ! rest of %o5
96 add %o5, %g1, %o5
97
98 b Ldo_single_div
99 sub %g7, 1, %g7
100
101 Lnot_too_big:
102 3:
103 cmp %o5, %o3
104 blu 2b
105 nop
106
107 be Ldo_single_div
108 nop
109 /* NB: these are commented out in the V8-Sparc manual as well */
110 /* (I do not understand this) */
111 ! %o5 > %o3: went too far: back up 1 step
112 ! srl %o5, 1, %o5
113 ! dec %g7
114 ! do single-bit divide steps
115 !
116 ! We have to be careful here. We know that %o3 >= %o5, so we can do the
117 ! first divide step without thinking. BUT, the others are conditional,
118 ! and are only done if %o3 >= 0. Because both %o3 and %o5 may have the high-
119 ! order bit set in the first step, just falling into the regular
120 ! division loop will mess up the first time around.
121 ! So we unroll slightly...
122 Ldo_single_div:
123 subcc %g7, 1, %g7
124 bl Lend_regular_divide
125 nop
126
127 sub %o3, %o5, %o3
128 mov 1, %o2
129
130 b Lend_single_divloop
131 nop
132 Lsingle_divloop:
133 sll %o2, 1, %o2
134 bl 1f
135 srl %o5, 1, %o5
136 ! %o3 >= 0
137 sub %o3, %o5, %o3
138 b 2f
139 add %o2, 1, %o2
140 1: ! %o3 < 0
141 add %o3, %o5, %o3
142 sub %o2, 1, %o2
143 2:
144 Lend_single_divloop:
145 subcc %g7, 1, %g7
146 bge Lsingle_divloop
147 tst %o3
148
149 b,a Lend_regular_divide
150
151Lnot_really_big:
1521:
153 sll %o5, 4, %o5
154
155 cmp %o5, %o3
156 bleu 1b
157 addcc %o4, 1, %o4
158
159 be Lgot_result
160 sub %o4, 1, %o4
161
162 tst %o3 ! set up for initial iteration
163Ldivloop:
164 sll %o2, 4, %o2
165 ! depth 1, accumulated bits 0
166 bl L.1.16
167 srl %o5,1,%o5
168 ! remainder is positive
169 subcc %o3,%o5,%o3
170 ! depth 2, accumulated bits 1
171 bl L.2.17
172 srl %o5,1,%o5
173 ! remainder is positive
174 subcc %o3,%o5,%o3
175 ! depth 3, accumulated bits 3
176 bl L.3.19
177 srl %o5,1,%o5
178 ! remainder is positive
179 subcc %o3,%o5,%o3
180 ! depth 4, accumulated bits 7
181 bl L.4.23
182 srl %o5,1,%o5
183 ! remainder is positive
184 subcc %o3,%o5,%o3
185 b 9f
186 add %o2, (7*2+1), %o2
187
188L.4.23:
189 ! remainder is negative
190 addcc %o3,%o5,%o3
191 b 9f
192 add %o2, (7*2-1), %o2
193
194L.3.19:
195 ! remainder is negative
196 addcc %o3,%o5,%o3
197 ! depth 4, accumulated bits 5
198 bl L.4.21
199 srl %o5,1,%o5
200 ! remainder is positive
201 subcc %o3,%o5,%o3
202 b 9f
203 add %o2, (5*2+1), %o2
204
205L.4.21:
206 ! remainder is negative
207 addcc %o3,%o5,%o3
208 b 9f
209 add %o2, (5*2-1), %o2
210
211L.2.17:
212 ! remainder is negative
213 addcc %o3,%o5,%o3
214 ! depth 3, accumulated bits 1
215 bl L.3.17
216 srl %o5,1,%o5
217 ! remainder is positive
218 subcc %o3,%o5,%o3
219 ! depth 4, accumulated bits 3
220 bl L.4.19
221 srl %o5,1,%o5
222 ! remainder is positive
223 subcc %o3,%o5,%o3
224 b 9f
225 add %o2, (3*2+1), %o2
226
227L.4.19:
228 ! remainder is negative
229 addcc %o3,%o5,%o3
230 b 9f
231 add %o2, (3*2-1), %o2
232
233L.3.17:
234 ! remainder is negative
235 addcc %o3,%o5,%o3
236 ! depth 4, accumulated bits 1
237 bl L.4.17
238 srl %o5,1,%o5
239 ! remainder is positive
240 subcc %o3,%o5,%o3
241 b 9f
242 add %o2, (1*2+1), %o2
243
244L.4.17:
245 ! remainder is negative
246 addcc %o3,%o5,%o3
247 b 9f
248 add %o2, (1*2-1), %o2
249
250L.1.16:
251 ! remainder is negative
252 addcc %o3,%o5,%o3
253 ! depth 2, accumulated bits -1
254 bl L.2.15
255 srl %o5,1,%o5
256 ! remainder is positive
257 subcc %o3,%o5,%o3
258 ! depth 3, accumulated bits -1
259 bl L.3.15
260 srl %o5,1,%o5
261 ! remainder is positive
262 subcc %o3,%o5,%o3
263 ! depth 4, accumulated bits -1
264 bl L.4.15
265 srl %o5,1,%o5
266 ! remainder is positive
267 subcc %o3,%o5,%o3
268 b 9f
269 add %o2, (-1*2+1), %o2
270
271L.4.15:
272 ! remainder is negative
273 addcc %o3,%o5,%o3
274 b 9f
275 add %o2, (-1*2-1), %o2
276
277L.3.15:
278 ! remainder is negative
279 addcc %o3,%o5,%o3
280 ! depth 4, accumulated bits -3
281 bl L.4.13
282 srl %o5,1,%o5
283 ! remainder is positive
284 subcc %o3,%o5,%o3
285 b 9f
286 add %o2, (-3*2+1), %o2
287
288L.4.13:
289 ! remainder is negative
290 addcc %o3,%o5,%o3
291 b 9f
292 add %o2, (-3*2-1), %o2
293
294L.2.15:
295 ! remainder is negative
296 addcc %o3,%o5,%o3
297 ! depth 3, accumulated bits -3
298 bl L.3.13
299 srl %o5,1,%o5
300 ! remainder is positive
301 subcc %o3,%o5,%o3
302 ! depth 4, accumulated bits -5
303 bl L.4.11
304 srl %o5,1,%o5
305 ! remainder is positive
306 subcc %o3,%o5,%o3
307 b 9f
308 add %o2, (-5*2+1), %o2
309
310L.4.11:
311 ! remainder is negative
312 addcc %o3,%o5,%o3
313 b 9f
314 add %o2, (-5*2-1), %o2
315
316L.3.13:
317 ! remainder is negative
318 addcc %o3,%o5,%o3
319 ! depth 4, accumulated bits -7
320 bl L.4.9
321 srl %o5,1,%o5
322 ! remainder is positive
323 subcc %o3,%o5,%o3
324 b 9f
325 add %o2, (-7*2+1), %o2
326
327L.4.9:
328 ! remainder is negative
329 addcc %o3,%o5,%o3
330 b 9f
331 add %o2, (-7*2-1), %o2
332
333 9:
334Lend_regular_divide:
335 subcc %o4, 1, %o4
336 bge Ldivloop
337 tst %o3
338
339 bl,a Lgot_result
340 ! non-restoring fixup here (one instruction only!)
341 add %o3, %o1, %o3
342
343Lgot_result:
344
345 retl
346 mov %o3, %o0
347
348 .globl .urem_patch
349.urem_patch:
350 wr %g0, 0x0, %y
351 nop
352 nop
353 nop
354 udiv %o0, %o1, %o2
355 umul %o2, %o1, %o2
356 retl
357 sub %o0, %o2, %o0
diff --git a/arch/sparc/lib/xor.S b/arch/sparc/lib/xor.S
index f44f58f40234..2c05641c3263 100644
--- a/arch/sparc/lib/xor.S
+++ b/arch/sparc/lib/xor.S
@@ -8,6 +8,7 @@
8 * Copyright (C) 2006 David S. Miller <davem@davemloft.net> 8 * Copyright (C) 2006 David S. Miller <davem@davemloft.net>
9 */ 9 */
10 10
11#include <linux/linkage.h>
11#include <asm/visasm.h> 12#include <asm/visasm.h>
12#include <asm/asi.h> 13#include <asm/asi.h>
13#include <asm/dcu.h> 14#include <asm/dcu.h>
@@ -19,12 +20,9 @@
19 * !(len & 127) && len >= 256 20 * !(len & 127) && len >= 256
20 */ 21 */
21 .text 22 .text
22 .align 32
23 23
24 /* VIS versions. */ 24 /* VIS versions. */
25 .globl xor_vis_2 25ENTRY(xor_vis_2)
26 .type xor_vis_2,#function
27xor_vis_2:
28 rd %fprs, %o5 26 rd %fprs, %o5
29 andcc %o5, FPRS_FEF|FPRS_DU, %g0 27 andcc %o5, FPRS_FEF|FPRS_DU, %g0
30 be,pt %icc, 0f 28 be,pt %icc, 0f
@@ -91,11 +89,9 @@ xor_vis_2:
91 wr %g1, %g0, %asi 89 wr %g1, %g0, %asi
92 retl 90 retl
93 wr %g0, 0, %fprs 91 wr %g0, 0, %fprs
94 .size xor_vis_2, .-xor_vis_2 92ENDPROC(xor_vis_2)
95 93
96 .globl xor_vis_3 94ENTRY(xor_vis_3)
97 .type xor_vis_3,#function
98xor_vis_3:
99 rd %fprs, %o5 95 rd %fprs, %o5
100 andcc %o5, FPRS_FEF|FPRS_DU, %g0 96 andcc %o5, FPRS_FEF|FPRS_DU, %g0
101 be,pt %icc, 0f 97 be,pt %icc, 0f
@@ -159,11 +155,9 @@ xor_vis_3:
159 wr %g1, %g0, %asi 155 wr %g1, %g0, %asi
160 retl 156 retl
161 wr %g0, 0, %fprs 157 wr %g0, 0, %fprs
162 .size xor_vis_3, .-xor_vis_3 158ENDPROC(xor_vis_3)
163 159
164 .globl xor_vis_4 160ENTRY(xor_vis_4)
165 .type xor_vis_4,#function
166xor_vis_4:
167 rd %fprs, %o5 161 rd %fprs, %o5
168 andcc %o5, FPRS_FEF|FPRS_DU, %g0 162 andcc %o5, FPRS_FEF|FPRS_DU, %g0
169 be,pt %icc, 0f 163 be,pt %icc, 0f
@@ -246,11 +240,9 @@ xor_vis_4:
246 wr %g1, %g0, %asi 240 wr %g1, %g0, %asi
247 retl 241 retl
248 wr %g0, 0, %fprs 242 wr %g0, 0, %fprs
249 .size xor_vis_4, .-xor_vis_4 243ENDPROC(xor_vis_4)
250 244
251 .globl xor_vis_5 245ENTRY(xor_vis_5)
252 .type xor_vis_5,#function
253xor_vis_5:
254 save %sp, -192, %sp 246 save %sp, -192, %sp
255 rd %fprs, %o5 247 rd %fprs, %o5
256 andcc %o5, FPRS_FEF|FPRS_DU, %g0 248 andcc %o5, FPRS_FEF|FPRS_DU, %g0
@@ -354,12 +346,10 @@ xor_vis_5:
354 wr %g0, 0, %fprs 346 wr %g0, 0, %fprs
355 ret 347 ret
356 restore 348 restore
357 .size xor_vis_5, .-xor_vis_5 349ENDPROC(xor_vis_5)
358 350
359 /* Niagara versions. */ 351 /* Niagara versions. */
360 .globl xor_niagara_2 352ENTRY(xor_niagara_2) /* %o0=bytes, %o1=dest, %o2=src */
361 .type xor_niagara_2,#function
362xor_niagara_2: /* %o0=bytes, %o1=dest, %o2=src */
363 save %sp, -192, %sp 353 save %sp, -192, %sp
364 prefetch [%i1], #n_writes 354 prefetch [%i1], #n_writes
365 prefetch [%i2], #one_read 355 prefetch [%i2], #one_read
@@ -402,11 +392,9 @@ xor_niagara_2: /* %o0=bytes, %o1=dest, %o2=src */
402 wr %g7, 0x0, %asi 392 wr %g7, 0x0, %asi
403 ret 393 ret
404 restore 394 restore
405 .size xor_niagara_2, .-xor_niagara_2 395ENDPROC(xor_niagara_2)
406 396
407 .globl xor_niagara_3 397ENTRY(xor_niagara_3) /* %o0=bytes, %o1=dest, %o2=src1, %o3=src2 */
408 .type xor_niagara_3,#function
409xor_niagara_3: /* %o0=bytes, %o1=dest, %o2=src1, %o3=src2 */
410 save %sp, -192, %sp 398 save %sp, -192, %sp
411 prefetch [%i1], #n_writes 399 prefetch [%i1], #n_writes
412 prefetch [%i2], #one_read 400 prefetch [%i2], #one_read
@@ -465,11 +453,9 @@ xor_niagara_3: /* %o0=bytes, %o1=dest, %o2=src1, %o3=src2 */
465 wr %g7, 0x0, %asi 453 wr %g7, 0x0, %asi
466 ret 454 ret
467 restore 455 restore
468 .size xor_niagara_3, .-xor_niagara_3 456ENDPROC(xor_niagara_3)
469 457
470 .globl xor_niagara_4 458ENTRY(xor_niagara_4) /* %o0=bytes, %o1=dest, %o2=src1, %o3=src2, %o4=src3 */
471 .type xor_niagara_4,#function
472xor_niagara_4: /* %o0=bytes, %o1=dest, %o2=src1, %o3=src2, %o4=src3 */
473 save %sp, -192, %sp 459 save %sp, -192, %sp
474 prefetch [%i1], #n_writes 460 prefetch [%i1], #n_writes
475 prefetch [%i2], #one_read 461 prefetch [%i2], #one_read
@@ -549,11 +535,9 @@ xor_niagara_4: /* %o0=bytes, %o1=dest, %o2=src1, %o3=src2, %o4=src3 */
549 wr %g7, 0x0, %asi 535 wr %g7, 0x0, %asi
550 ret 536 ret
551 restore 537 restore
552 .size xor_niagara_4, .-xor_niagara_4 538ENDPROC(xor_niagara_4)
553 539
554 .globl xor_niagara_5 540ENTRY(xor_niagara_5) /* %o0=bytes, %o1=dest, %o2=src1, %o3=src2, %o4=src3, %o5=src4 */
555 .type xor_niagara_5,#function
556xor_niagara_5: /* %o0=bytes, %o1=dest, %o2=src1, %o3=src2, %o4=src3, %o5=src4 */
557 save %sp, -192, %sp 541 save %sp, -192, %sp
558 prefetch [%i1], #n_writes 542 prefetch [%i1], #n_writes
559 prefetch [%i2], #one_read 543 prefetch [%i2], #one_read
@@ -649,4 +633,4 @@ xor_niagara_5: /* %o0=bytes, %o1=dest, %o2=src1, %o3=src2, %o4=src3, %o5=src4 *
649 wr %g7, 0x0, %asi 633 wr %g7, 0x0, %asi
650 ret 634 ret
651 restore 635 restore
652 .size xor_niagara_5, .-xor_niagara_5 636ENDPROC(xor_niagara_5)
diff --git a/arch/sparc/mm/Makefile b/arch/sparc/mm/Makefile
index 301421c11291..69ffd3112fed 100644
--- a/arch/sparc/mm/Makefile
+++ b/arch/sparc/mm/Makefile
@@ -7,8 +7,7 @@ ccflags-y := -Werror
7obj-$(CONFIG_SPARC64) += ultra.o tlb.o tsb.o gup.o 7obj-$(CONFIG_SPARC64) += ultra.o tlb.o tsb.o gup.o
8obj-y += fault_$(BITS).o 8obj-y += fault_$(BITS).o
9obj-y += init_$(BITS).o 9obj-y += init_$(BITS).o
10obj-$(CONFIG_SPARC32) += loadmmu.o 10obj-$(CONFIG_SPARC32) += extable.o srmmu.o iommu.o io-unit.o
11obj-$(CONFIG_SPARC32) += extable.o btfixup.o srmmu.o iommu.o io-unit.o
12obj-$(CONFIG_SPARC32) += hypersparc.o viking.o tsunami.o swift.o 11obj-$(CONFIG_SPARC32) += hypersparc.o viking.o tsunami.o swift.o
13obj-$(CONFIG_SPARC_LEON)+= leon_mm.o 12obj-$(CONFIG_SPARC_LEON)+= leon_mm.o
14 13
@@ -17,9 +16,3 @@ obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o
17 16
18# Only used by sparc32 17# Only used by sparc32
19obj-$(CONFIG_HIGHMEM) += highmem.o 18obj-$(CONFIG_HIGHMEM) += highmem.o
20
21ifdef CONFIG_SMP
22obj-$(CONFIG_SPARC32) += nosun4c.o
23else
24obj-$(CONFIG_SPARC32) += sun4c.o
25endif
diff --git a/arch/sparc/mm/btfixup.c b/arch/sparc/mm/btfixup.c
deleted file mode 100644
index 09d6af22db2d..000000000000
--- a/arch/sparc/mm/btfixup.c
+++ /dev/null
@@ -1,328 +0,0 @@
1/* btfixup.c: Boot time code fixup and relocator, so that
2 * we can get rid of most indirect calls to achieve single
3 * image sun4c and srmmu kernel.
4 *
5 * Copyright (C) 1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
6 */
7
8#include <linux/kernel.h>
9#include <linux/init.h>
10#include <asm/btfixup.h>
11#include <asm/page.h>
12#include <asm/pgalloc.h>
13#include <asm/pgtable.h>
14#include <asm/oplib.h>
15#include <asm/cacheflush.h>
16
17#define BTFIXUP_OPTIMIZE_NOP
18#define BTFIXUP_OPTIMIZE_OTHER
19
20extern char *srmmu_name;
21static char version[] __initdata = "Boot time fixup v1.6. 4/Mar/98 Jakub Jelinek (jj@ultra.linux.cz). Patching kernel for ";
22static char str_sun4c[] __initdata = "sun4c\n";
23static char str_srmmu[] __initdata = "srmmu[%s]/";
24static char str_iommu[] __initdata = "iommu\n";
25static char str_iounit[] __initdata = "io-unit\n";
26
27static int visited __initdata = 0;
28extern unsigned int ___btfixup_start[], ___btfixup_end[], __init_begin[], __init_end[], __init_text_end[];
29extern unsigned int _stext[], _end[], __start___ksymtab[], __stop___ksymtab[];
30static char wrong_f[] __initdata = "Trying to set f fixup %p to invalid function %08x\n";
31static char wrong_b[] __initdata = "Trying to set b fixup %p to invalid function %08x\n";
32static char wrong_s[] __initdata = "Trying to set s fixup %p to invalid value %08x\n";
33static char wrong_h[] __initdata = "Trying to set h fixup %p to invalid value %08x\n";
34static char wrong_a[] __initdata = "Trying to set a fixup %p to invalid value %08x\n";
35static char wrong[] __initdata = "Wrong address for %c fixup %p\n";
36static char insn_f[] __initdata = "Fixup f %p refers to weird instructions at %p[%08x,%08x]\n";
37static char insn_b[] __initdata = "Fixup b %p doesn't refer to a SETHI at %p[%08x]\n";
38static char insn_s[] __initdata = "Fixup s %p doesn't refer to an OR at %p[%08x]\n";
39static char insn_h[] __initdata = "Fixup h %p doesn't refer to a SETHI at %p[%08x]\n";
40static char insn_a[] __initdata = "Fixup a %p doesn't refer to a SETHI nor OR at %p[%08x]\n";
41static char insn_i[] __initdata = "Fixup i %p doesn't refer to a valid instruction at %p[%08x]\n";
42static char fca_und[] __initdata = "flush_cache_all undefined in btfixup()\n";
43static char wrong_setaddr[] __initdata = "Garbled CALL/INT patch at %p[%08x,%08x,%08x]=%08x\n";
44
45#ifdef BTFIXUP_OPTIMIZE_OTHER
46static void __init set_addr(unsigned int *addr, unsigned int q1, int fmangled, unsigned int value)
47{
48 if (!fmangled)
49 *addr = value;
50 else {
51 unsigned int *q = (unsigned int *)q1;
52 if (*addr == 0x01000000) {
53 /* Noped */
54 *q = value;
55 } else if (addr[-1] == *q) {
56 /* Moved */
57 addr[-1] = value;
58 *q = value;
59 } else {
60 prom_printf(wrong_setaddr, addr-1, addr[-1], *addr, *q, value);
61 prom_halt();
62 }
63 }
64}
65#else
66static inline void set_addr(unsigned int *addr, unsigned int q1, int fmangled, unsigned int value)
67{
68 *addr = value;
69}
70#endif
71
72void __init btfixup(void)
73{
74 unsigned int *p, *q;
75 int type, count;
76 unsigned insn;
77 unsigned *addr;
78 int fmangled = 0;
79 void (*flush_cacheall)(void);
80
81 if (!visited) {
82 visited++;
83 printk(version);
84 if (ARCH_SUN4C)
85 printk(str_sun4c);
86 else {
87 printk(str_srmmu, srmmu_name);
88 if (sparc_cpu_model == sun4d)
89 printk(str_iounit);
90 else
91 printk(str_iommu);
92 }
93 }
94 for (p = ___btfixup_start; p < ___btfixup_end; ) {
95 count = p[2];
96 q = p + 3;
97 switch (type = *(unsigned char *)p) {
98 case 'f':
99 count = p[3];
100 q = p + 4;
101 if (((p[0] & 1) || p[1])
102 && ((p[1] & 3) || (unsigned *)(p[1]) < _stext || (unsigned *)(p[1]) >= _end)) {
103 prom_printf(wrong_f, p, p[1]);
104 prom_halt();
105 }
106 break;
107 case 'b':
108 if (p[1] < (unsigned long)__init_begin || p[1] >= (unsigned long)__init_text_end || (p[1] & 3)) {
109 prom_printf(wrong_b, p, p[1]);
110 prom_halt();
111 }
112 break;
113 case 's':
114 if (p[1] + 0x1000 >= 0x2000) {
115 prom_printf(wrong_s, p, p[1]);
116 prom_halt();
117 }
118 break;
119 case 'h':
120 if (p[1] & 0x3ff) {
121 prom_printf(wrong_h, p, p[1]);
122 prom_halt();
123 }
124 break;
125 case 'a':
126 if (p[1] + 0x1000 >= 0x2000 && (p[1] & 0x3ff)) {
127 prom_printf(wrong_a, p, p[1]);
128 prom_halt();
129 }
130 break;
131 }
132 if (p[0] & 1) {
133 p[0] &= ~1;
134 while (count) {
135 fmangled = 0;
136 addr = (unsigned *)*q;
137 if (addr < _stext || addr >= _end) {
138 prom_printf(wrong, type, p);
139 prom_halt();
140 }
141 insn = *addr;
142#ifdef BTFIXUP_OPTIMIZE_OTHER
143 if (type != 'f' && q[1]) {
144 insn = *(unsigned int *)q[1];
145 if (!insn || insn == 1)
146 insn = *addr;
147 else
148 fmangled = 1;
149 }
150#endif
151 switch (type) {
152 case 'f': /* CALL */
153 if (addr >= __start___ksymtab && addr < __stop___ksymtab) {
154 *addr = p[1];
155 break;
156 } else if (!q[1]) {
157 if ((insn & 0xc1c00000) == 0x01000000) { /* SETHI */
158 *addr = (insn & 0xffc00000) | (p[1] >> 10); break;
159 } else if ((insn & 0xc1f82000) == 0x80102000) { /* OR X, %LO(i), Y */
160 *addr = (insn & 0xffffe000) | (p[1] & 0x3ff); break;
161 } else if ((insn & 0xc0000000) != 0x40000000) { /* !CALL */
162 bad_f:
163 prom_printf(insn_f, p, addr, insn, addr[1]);
164 prom_halt();
165 }
166 } else if (q[1] != 1)
167 addr[1] = q[1];
168 if (p[2] == BTFIXUPCALL_NORM) {
169 norm_f:
170 *addr = 0x40000000 | ((p[1] - (unsigned)addr) >> 2);
171 q[1] = 0;
172 break;
173 }
174#ifndef BTFIXUP_OPTIMIZE_NOP
175 goto norm_f;
176#else
177 if (!(addr[1] & 0x80000000)) {
178 if ((addr[1] & 0xc1c00000) != 0x01000000) /* !SETHI */
179 goto bad_f; /* CALL, Bicc, FBfcc, CBccc are weird in delay slot, aren't they? */
180 } else {
181 if ((addr[1] & 0x01800000) == 0x01800000) {
182 if ((addr[1] & 0x01f80000) == 0x01e80000) {
183 /* RESTORE */
184 goto norm_f; /* It is dangerous to patch that */
185 }
186 goto bad_f;
187 }
188 if ((addr[1] & 0xffffe003) == 0x9e03e000) {
189 /* ADD %O7, XX, %o7 */
190 int displac = (addr[1] << 19);
191
192 displac = (displac >> 21) + 2;
193 *addr = (0x10800000) + (displac & 0x3fffff);
194 q[1] = addr[1];
195 addr[1] = p[2];
196 break;
197 }
198 if ((addr[1] & 0x201f) == 0x200f || (addr[1] & 0x7c000) == 0x3c000)
199 goto norm_f; /* Someone is playing bad tricks with us: rs1 or rs2 is o7 */
200 if ((addr[1] & 0x3e000000) == 0x1e000000)
201 goto norm_f; /* rd is %o7. We'd better take care. */
202 }
203 if (p[2] == BTFIXUPCALL_NOP) {
204 *addr = 0x01000000;
205 q[1] = 1;
206 break;
207 }
208#ifndef BTFIXUP_OPTIMIZE_OTHER
209 goto norm_f;
210#else
211 if (addr[1] == 0x01000000) { /* NOP in the delay slot */
212 q[1] = addr[1];
213 *addr = p[2];
214 break;
215 }
216 if ((addr[1] & 0xc0000000) != 0xc0000000) {
217 /* Not a memory operation */
218 if ((addr[1] & 0x30000000) == 0x10000000) {
219 /* Ok, non-memory op with rd %oX */
220 if ((addr[1] & 0x3e000000) == 0x1c000000)
221 goto bad_f; /* Aiee. Someone is playing strange %sp tricks */
222 if ((addr[1] & 0x3e000000) > 0x12000000 ||
223 ((addr[1] & 0x3e000000) == 0x12000000 &&
224 p[2] != BTFIXUPCALL_STO1O0 && p[2] != BTFIXUPCALL_SWAPO0O1) ||
225 ((p[2] & 0xffffe000) == BTFIXUPCALL_RETINT(0))) {
226 /* Nobody uses the result. We can nop it out. */
227 *addr = p[2];
228 q[1] = addr[1];
229 addr[1] = 0x01000000;
230 break;
231 }
232 if ((addr[1] & 0xf1ffffe0) == 0x90100000) {
233 /* MOV %reg, %Ox */
234 if ((addr[1] & 0x3e000000) == 0x10000000 &&
235 (p[2] & 0x7c000) == 0x20000) {
236 /* Ok, it is call xx; mov reg, %o0 and call optimizes
237 to doing something on %o0. Patch the patch. */
238 *addr = (p[2] & ~0x7c000) | ((addr[1] & 0x1f) << 14);
239 q[1] = addr[1];
240 addr[1] = 0x01000000;
241 break;
242 }
243 if ((addr[1] & 0x3e000000) == 0x12000000 &&
244 p[2] == BTFIXUPCALL_STO1O0) {
245 *addr = (p[2] & ~0x3e000000) | ((addr[1] & 0x1f) << 25);
246 q[1] = addr[1];
247 addr[1] = 0x01000000;
248 break;
249 }
250 }
251 }
252 }
253 *addr = addr[1];
254 q[1] = addr[1];
255 addr[1] = p[2];
256 break;
257#endif /* BTFIXUP_OPTIMIZE_OTHER */
258#endif /* BTFIXUP_OPTIMIZE_NOP */
259 case 'b': /* BLACKBOX */
260 /* Has to be sethi i, xx */
261 if ((insn & 0xc1c00000) != 0x01000000) {
262 prom_printf(insn_b, p, addr, insn);
263 prom_halt();
264 } else {
265 void (*do_fixup)(unsigned *);
266
267 do_fixup = (void (*)(unsigned *))p[1];
268 do_fixup(addr);
269 }
270 break;
271 case 's': /* SIMM13 */
272 /* Has to be or %g0, i, xx */
273 if ((insn & 0xc1ffe000) != 0x80102000) {
274 prom_printf(insn_s, p, addr, insn);
275 prom_halt();
276 }
277 set_addr(addr, q[1], fmangled, (insn & 0xffffe000) | (p[1] & 0x1fff));
278 break;
279 case 'h': /* SETHI */
280 /* Has to be sethi i, xx */
281 if ((insn & 0xc1c00000) != 0x01000000) {
282 prom_printf(insn_h, p, addr, insn);
283 prom_halt();
284 }
285 set_addr(addr, q[1], fmangled, (insn & 0xffc00000) | (p[1] >> 10));
286 break;
287 case 'a': /* HALF */
288 /* Has to be sethi i, xx or or %g0, i, xx */
289 if ((insn & 0xc1c00000) != 0x01000000 &&
290 (insn & 0xc1ffe000) != 0x80102000) {
291 prom_printf(insn_a, p, addr, insn);
292 prom_halt();
293 }
294 if (p[1] & 0x3ff)
295 set_addr(addr, q[1], fmangled,
296 (insn & 0x3e000000) | 0x80102000 | (p[1] & 0x1fff));
297 else
298 set_addr(addr, q[1], fmangled,
299 (insn & 0x3e000000) | 0x01000000 | (p[1] >> 10));
300 break;
301 case 'i': /* INT */
302 if ((insn & 0xc1c00000) == 0x01000000) /* %HI */
303 set_addr(addr, q[1], fmangled, (insn & 0xffc00000) | (p[1] >> 10));
304 else if ((insn & 0x80002000) == 0x80002000) /* %LO */
305 set_addr(addr, q[1], fmangled, (insn & 0xffffe000) | (p[1] & 0x3ff));
306 else {
307 prom_printf(insn_i, p, addr, insn);
308 prom_halt();
309 }
310 break;
311 }
312 count -= 2;
313 q += 2;
314 }
315 } else
316 p = q + count;
317 }
318#ifdef CONFIG_SMP
319 flush_cacheall = (void (*)(void))BTFIXUPVAL_CALL(local_flush_cache_all);
320#else
321 flush_cacheall = (void (*)(void))BTFIXUPVAL_CALL(flush_cache_all);
322#endif
323 if (!flush_cacheall) {
324 prom_printf(fca_und);
325 prom_halt();
326 }
327 (*flush_cacheall)();
328}
diff --git a/arch/sparc/mm/fault_32.c b/arch/sparc/mm/fault_32.c
index df3155a17991..f46cf6be3370 100644
--- a/arch/sparc/mm/fault_32.c
+++ b/arch/sparc/mm/fault_32.c
@@ -24,29 +24,19 @@
24 24
25#include <asm/page.h> 25#include <asm/page.h>
26#include <asm/pgtable.h> 26#include <asm/pgtable.h>
27#include <asm/memreg.h>
28#include <asm/openprom.h> 27#include <asm/openprom.h>
29#include <asm/oplib.h> 28#include <asm/oplib.h>
30#include <asm/smp.h> 29#include <asm/smp.h>
31#include <asm/traps.h> 30#include <asm/traps.h>
32#include <asm/uaccess.h> 31#include <asm/uaccess.h>
33 32
34extern int prom_node_root;
35
36int show_unhandled_signals = 1; 33int show_unhandled_signals = 1;
37 34
38/* At boot time we determine these two values necessary for setting 35/* At boot time we determine these two values necessary for setting
39 * up the segment maps and page table entries (pte's). 36 * up the segment maps and page table entries (pte's).
40 */ 37 */
41 38
42int num_segmaps, num_contexts; 39int num_contexts;
43int invalid_segment;
44
45/* various Virtual Address Cache parameters we find at boot time... */
46
47int vac_size, vac_linesize, vac_do_hw_vac_flushes;
48int vac_entries_per_context, vac_entries_per_segment;
49int vac_entries_per_page;
50 40
51/* Return how much physical memory we have. */ 41/* Return how much physical memory we have. */
52unsigned long probe_memory(void) 42unsigned long probe_memory(void)
@@ -60,55 +50,36 @@ unsigned long probe_memory(void)
60 return total; 50 return total;
61} 51}
62 52
63extern void sun4c_complete_all_stores(void);
64
65/* Whee, a level 15 NMI interrupt memory error. Let's have fun... */
66asmlinkage void sparc_lvl15_nmi(struct pt_regs *regs, unsigned long serr,
67 unsigned long svaddr, unsigned long aerr,
68 unsigned long avaddr)
69{
70 sun4c_complete_all_stores();
71 printk("FAULT: NMI received\n");
72 printk("SREGS: Synchronous Error %08lx\n", serr);
73 printk(" Synchronous Vaddr %08lx\n", svaddr);
74 printk(" Asynchronous Error %08lx\n", aerr);
75 printk(" Asynchronous Vaddr %08lx\n", avaddr);
76 if (sun4c_memerr_reg)
77 printk(" Memory Parity Error %08lx\n", *sun4c_memerr_reg);
78 printk("REGISTER DUMP:\n");
79 show_regs(regs);
80 prom_halt();
81}
82
83static void unhandled_fault(unsigned long, struct task_struct *, 53static void unhandled_fault(unsigned long, struct task_struct *,
84 struct pt_regs *) __attribute__ ((noreturn)); 54 struct pt_regs *) __attribute__ ((noreturn));
85 55
86static void unhandled_fault(unsigned long address, struct task_struct *tsk, 56static void __noreturn unhandled_fault(unsigned long address,
87 struct pt_regs *regs) 57 struct task_struct *tsk,
58 struct pt_regs *regs)
88{ 59{
89 if((unsigned long) address < PAGE_SIZE) { 60 if ((unsigned long) address < PAGE_SIZE) {
90 printk(KERN_ALERT 61 printk(KERN_ALERT
91 "Unable to handle kernel NULL pointer dereference\n"); 62 "Unable to handle kernel NULL pointer dereference\n");
92 } else { 63 } else {
93 printk(KERN_ALERT "Unable to handle kernel paging request " 64 printk(KERN_ALERT "Unable to handle kernel paging request at virtual address %08lx\n",
94 "at virtual address %08lx\n", address); 65 address);
95 } 66 }
96 printk(KERN_ALERT "tsk->{mm,active_mm}->context = %08lx\n", 67 printk(KERN_ALERT "tsk->{mm,active_mm}->context = %08lx\n",
97 (tsk->mm ? tsk->mm->context : tsk->active_mm->context)); 68 (tsk->mm ? tsk->mm->context : tsk->active_mm->context));
98 printk(KERN_ALERT "tsk->{mm,active_mm}->pgd = %08lx\n", 69 printk(KERN_ALERT "tsk->{mm,active_mm}->pgd = %08lx\n",
99 (tsk->mm ? (unsigned long) tsk->mm->pgd : 70 (tsk->mm ? (unsigned long) tsk->mm->pgd :
100 (unsigned long) tsk->active_mm->pgd)); 71 (unsigned long) tsk->active_mm->pgd));
101 die_if_kernel("Oops", regs); 72 die_if_kernel("Oops", regs);
102} 73}
103 74
104asmlinkage int lookup_fault(unsigned long pc, unsigned long ret_pc, 75asmlinkage int lookup_fault(unsigned long pc, unsigned long ret_pc,
105 unsigned long address) 76 unsigned long address)
106{ 77{
107 struct pt_regs regs; 78 struct pt_regs regs;
108 unsigned long g2; 79 unsigned long g2;
109 unsigned int insn; 80 unsigned int insn;
110 int i; 81 int i;
111 82
112 i = search_extables_range(ret_pc, &g2); 83 i = search_extables_range(ret_pc, &g2);
113 switch (i) { 84 switch (i) {
114 case 3: 85 case 3:
@@ -128,14 +99,14 @@ asmlinkage int lookup_fault(unsigned long pc, unsigned long ret_pc,
128 /* for _from_ macros */ 99 /* for _from_ macros */
129 insn = *((unsigned int *) pc); 100 insn = *((unsigned int *) pc);
130 if (!((insn >> 21) & 1) || ((insn>>19)&0x3f) == 15) 101 if (!((insn >> 21) & 1) || ((insn>>19)&0x3f) == 15)
131 return 2; 102 return 2;
132 break; 103 break;
133 104
134 default: 105 default:
135 break; 106 break;
136 } 107 }
137 108
138 memset(&regs, 0, sizeof (regs)); 109 memset(&regs, 0, sizeof(regs));
139 regs.pc = pc; 110 regs.pc = pc;
140 regs.npc = pc + 4; 111 regs.npc = pc + 4;
141 __asm__ __volatile__( 112 __asm__ __volatile__(
@@ -198,11 +169,10 @@ static unsigned long compute_si_addr(struct pt_regs *regs, int text_fault)
198 if (text_fault) 169 if (text_fault)
199 return regs->pc; 170 return regs->pc;
200 171
201 if (regs->psr & PSR_PS) { 172 if (regs->psr & PSR_PS)
202 insn = *(unsigned int *) regs->pc; 173 insn = *(unsigned int *) regs->pc;
203 } else { 174 else
204 __get_user(insn, (unsigned int *) regs->pc); 175 __get_user(insn, (unsigned int *) regs->pc);
205 }
206 176
207 return safe_compute_effective_address(regs, insn); 177 return safe_compute_effective_address(regs, insn);
208} 178}
@@ -228,7 +198,7 @@ asmlinkage void do_sparc_fault(struct pt_regs *regs, int text_fault, int write,
228 unsigned int flags = (FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE | 198 unsigned int flags = (FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE |
229 (write ? FAULT_FLAG_WRITE : 0)); 199 (write ? FAULT_FLAG_WRITE : 0));
230 200
231 if(text_fault) 201 if (text_fault)
232 address = regs->pc; 202 address = regs->pc;
233 203
234 /* 204 /*
@@ -241,36 +211,32 @@ asmlinkage void do_sparc_fault(struct pt_regs *regs, int text_fault, int write,
241 * nothing more. 211 * nothing more.
242 */ 212 */
243 code = SEGV_MAPERR; 213 code = SEGV_MAPERR;
244 if (!ARCH_SUN4C && address >= TASK_SIZE) 214 if (address >= TASK_SIZE)
245 goto vmalloc_fault; 215 goto vmalloc_fault;
246 216
247 /* 217 /*
248 * If we're in an interrupt or have no user 218 * If we're in an interrupt or have no user
249 * context, we must not take the fault.. 219 * context, we must not take the fault..
250 */ 220 */
251 if (in_atomic() || !mm) 221 if (in_atomic() || !mm)
252 goto no_context; 222 goto no_context;
253 223
254 perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, regs, address); 224 perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, regs, address);
255 225
256retry: 226retry:
257 down_read(&mm->mmap_sem); 227 down_read(&mm->mmap_sem);
258 228
259 /* 229 if (!from_user && address >= PAGE_OFFSET)
260 * The kernel referencing a bad kernel pointer can lock up
261 * a sun4c machine completely, so we must attempt recovery.
262 */
263 if(!from_user && address >= PAGE_OFFSET)
264 goto bad_area; 230 goto bad_area;
265 231
266 vma = find_vma(mm, address); 232 vma = find_vma(mm, address);
267 if(!vma) 233 if (!vma)
268 goto bad_area; 234 goto bad_area;
269 if(vma->vm_start <= address) 235 if (vma->vm_start <= address)
270 goto good_area; 236 goto good_area;
271 if(!(vma->vm_flags & VM_GROWSDOWN)) 237 if (!(vma->vm_flags & VM_GROWSDOWN))
272 goto bad_area; 238 goto bad_area;
273 if(expand_stack(vma, address)) 239 if (expand_stack(vma, address))
274 goto bad_area; 240 goto bad_area;
275 /* 241 /*
276 * Ok, we have a good vm_area for this memory access, so 242 * Ok, we have a good vm_area for this memory access, so
@@ -278,12 +244,12 @@ retry:
278 */ 244 */
279good_area: 245good_area:
280 code = SEGV_ACCERR; 246 code = SEGV_ACCERR;
281 if(write) { 247 if (write) {
282 if(!(vma->vm_flags & VM_WRITE)) 248 if (!(vma->vm_flags & VM_WRITE))
283 goto bad_area; 249 goto bad_area;
284 } else { 250 } else {
285 /* Allow reads even for write-only mappings */ 251 /* Allow reads even for write-only mappings */
286 if(!(vma->vm_flags & (VM_READ | VM_EXEC))) 252 if (!(vma->vm_flags & (VM_READ | VM_EXEC)))
287 goto bad_area; 253 goto bad_area;
288 } 254 }
289 255
@@ -349,14 +315,16 @@ no_context:
349 g2 = regs->u_regs[UREG_G2]; 315 g2 = regs->u_regs[UREG_G2];
350 if (!from_user) { 316 if (!from_user) {
351 fixup = search_extables_range(regs->pc, &g2); 317 fixup = search_extables_range(regs->pc, &g2);
352 if (fixup > 10) { /* Values below are reserved for other things */ 318 /* Values below 10 are reserved for other things */
319 if (fixup > 10) {
353 extern const unsigned __memset_start[]; 320 extern const unsigned __memset_start[];
354 extern const unsigned __memset_end[]; 321 extern const unsigned __memset_end[];
355 extern const unsigned __csum_partial_copy_start[]; 322 extern const unsigned __csum_partial_copy_start[];
356 extern const unsigned __csum_partial_copy_end[]; 323 extern const unsigned __csum_partial_copy_end[];
357 324
358#ifdef DEBUG_EXCEPTIONS 325#ifdef DEBUG_EXCEPTIONS
359 printk("Exception: PC<%08lx> faddr<%08lx>\n", regs->pc, address); 326 printk("Exception: PC<%08lx> faddr<%08lx>\n",
327 regs->pc, address);
360 printk("EX_TABLE: insn<%08lx> fixup<%08x> g2<%08lx>\n", 328 printk("EX_TABLE: insn<%08lx> fixup<%08x> g2<%08lx>\n",
361 regs->pc, fixup, g2); 329 regs->pc, fixup, g2);
362#endif 330#endif
@@ -364,7 +332,7 @@ no_context:
364 regs->pc < (unsigned long)__memset_end) || 332 regs->pc < (unsigned long)__memset_end) ||
365 (regs->pc >= (unsigned long)__csum_partial_copy_start && 333 (regs->pc >= (unsigned long)__csum_partial_copy_start &&
366 regs->pc < (unsigned long)__csum_partial_copy_end)) { 334 regs->pc < (unsigned long)__csum_partial_copy_end)) {
367 regs->u_regs[UREG_I4] = address; 335 regs->u_regs[UREG_I4] = address;
368 regs->u_regs[UREG_I5] = regs->pc; 336 regs->u_regs[UREG_I5] = regs->pc;
369 } 337 }
370 regs->u_regs[UREG_G2] = g2; 338 regs->u_regs[UREG_G2] = g2;
@@ -373,8 +341,8 @@ no_context:
373 return; 341 return;
374 } 342 }
375 } 343 }
376 344
377 unhandled_fault (address, tsk, regs); 345 unhandled_fault(address, tsk, regs);
378 do_exit(SIGKILL); 346 do_exit(SIGKILL);
379 347
380/* 348/*
@@ -420,97 +388,12 @@ vmalloc_fault:
420 388
421 if (pmd_present(*pmd) || !pmd_present(*pmd_k)) 389 if (pmd_present(*pmd) || !pmd_present(*pmd_k))
422 goto bad_area_nosemaphore; 390 goto bad_area_nosemaphore;
391
423 *pmd = *pmd_k; 392 *pmd = *pmd_k;
424 return; 393 return;
425 } 394 }
426} 395}
427 396
428asmlinkage void do_sun4c_fault(struct pt_regs *regs, int text_fault, int write,
429 unsigned long address)
430{
431 extern void sun4c_update_mmu_cache(struct vm_area_struct *,
432 unsigned long,pte_t *);
433 extern pte_t *sun4c_pte_offset_kernel(pmd_t *,unsigned long);
434 struct task_struct *tsk = current;
435 struct mm_struct *mm = tsk->mm;
436 pgd_t *pgdp;
437 pte_t *ptep;
438
439 if (text_fault) {
440 address = regs->pc;
441 } else if (!write &&
442 !(regs->psr & PSR_PS)) {
443 unsigned int insn, __user *ip;
444
445 ip = (unsigned int __user *)regs->pc;
446 if (!get_user(insn, ip)) {
447 if ((insn & 0xc1680000) == 0xc0680000)
448 write = 1;
449 }
450 }
451
452 if (!mm) {
453 /* We are oopsing. */
454 do_sparc_fault(regs, text_fault, write, address);
455 BUG(); /* P3 Oops already, you bitch */
456 }
457
458 pgdp = pgd_offset(mm, address);
459 ptep = sun4c_pte_offset_kernel((pmd_t *) pgdp, address);
460
461 if (pgd_val(*pgdp)) {
462 if (write) {
463 if ((pte_val(*ptep) & (_SUN4C_PAGE_WRITE|_SUN4C_PAGE_PRESENT))
464 == (_SUN4C_PAGE_WRITE|_SUN4C_PAGE_PRESENT)) {
465 unsigned long flags;
466
467 *ptep = __pte(pte_val(*ptep) | _SUN4C_PAGE_ACCESSED |
468 _SUN4C_PAGE_MODIFIED |
469 _SUN4C_PAGE_VALID |
470 _SUN4C_PAGE_DIRTY);
471
472 local_irq_save(flags);
473 if (sun4c_get_segmap(address) != invalid_segment) {
474 sun4c_put_pte(address, pte_val(*ptep));
475 local_irq_restore(flags);
476 return;
477 }
478 local_irq_restore(flags);
479 }
480 } else {
481 if ((pte_val(*ptep) & (_SUN4C_PAGE_READ|_SUN4C_PAGE_PRESENT))
482 == (_SUN4C_PAGE_READ|_SUN4C_PAGE_PRESENT)) {
483 unsigned long flags;
484
485 *ptep = __pte(pte_val(*ptep) | _SUN4C_PAGE_ACCESSED |
486 _SUN4C_PAGE_VALID);
487
488 local_irq_save(flags);
489 if (sun4c_get_segmap(address) != invalid_segment) {
490 sun4c_put_pte(address, pte_val(*ptep));
491 local_irq_restore(flags);
492 return;
493 }
494 local_irq_restore(flags);
495 }
496 }
497 }
498
499 /* This conditional is 'interesting'. */
500 if (pgd_val(*pgdp) && !(write && !(pte_val(*ptep) & _SUN4C_PAGE_WRITE))
501 && (pte_val(*ptep) & _SUN4C_PAGE_VALID))
502 /* Note: It is safe to not grab the MMAP semaphore here because
503 * we know that update_mmu_cache() will not sleep for
504 * any reason (at least not in the current implementation)
505 * and therefore there is no danger of another thread getting
506 * on the CPU and doing a shrink_mmap() on this vma.
507 */
508 sun4c_update_mmu_cache (find_vma(current->mm, address), address,
509 ptep);
510 else
511 do_sparc_fault(regs, text_fault, write, address);
512}
513
514/* This always deals with user addresses. */ 397/* This always deals with user addresses. */
515static void force_user_fault(unsigned long address, int write) 398static void force_user_fault(unsigned long address, int write)
516{ 399{
@@ -523,21 +406,21 @@ static void force_user_fault(unsigned long address, int write)
523 406
524 down_read(&mm->mmap_sem); 407 down_read(&mm->mmap_sem);
525 vma = find_vma(mm, address); 408 vma = find_vma(mm, address);
526 if(!vma) 409 if (!vma)
527 goto bad_area; 410 goto bad_area;
528 if(vma->vm_start <= address) 411 if (vma->vm_start <= address)
529 goto good_area; 412 goto good_area;
530 if(!(vma->vm_flags & VM_GROWSDOWN)) 413 if (!(vma->vm_flags & VM_GROWSDOWN))
531 goto bad_area; 414 goto bad_area;
532 if(expand_stack(vma, address)) 415 if (expand_stack(vma, address))
533 goto bad_area; 416 goto bad_area;
534good_area: 417good_area:
535 code = SEGV_ACCERR; 418 code = SEGV_ACCERR;
536 if(write) { 419 if (write) {
537 if(!(vma->vm_flags & VM_WRITE)) 420 if (!(vma->vm_flags & VM_WRITE))
538 goto bad_area; 421 goto bad_area;
539 } else { 422 } else {
540 if(!(vma->vm_flags & (VM_READ | VM_EXEC))) 423 if (!(vma->vm_flags & (VM_READ | VM_EXEC)))
541 goto bad_area; 424 goto bad_area;
542 } 425 }
543 switch (handle_mm_fault(mm, vma, address, write ? FAULT_FLAG_WRITE : 0)) { 426 switch (handle_mm_fault(mm, vma, address, write ? FAULT_FLAG_WRITE : 0)) {
@@ -568,7 +451,7 @@ void window_overflow_fault(void)
568 unsigned long sp; 451 unsigned long sp;
569 452
570 sp = current_thread_info()->rwbuf_stkptrs[0]; 453 sp = current_thread_info()->rwbuf_stkptrs[0];
571 if(((sp + 0x38) & PAGE_MASK) != (sp & PAGE_MASK)) 454 if (((sp + 0x38) & PAGE_MASK) != (sp & PAGE_MASK))
572 force_user_fault(sp + 0x38, 1); 455 force_user_fault(sp + 0x38, 1);
573 force_user_fault(sp, 1); 456 force_user_fault(sp, 1);
574 457
@@ -577,7 +460,7 @@ void window_overflow_fault(void)
577 460
578void window_underflow_fault(unsigned long sp) 461void window_underflow_fault(unsigned long sp)
579{ 462{
580 if(((sp + 0x38) & PAGE_MASK) != (sp & PAGE_MASK)) 463 if (((sp + 0x38) & PAGE_MASK) != (sp & PAGE_MASK))
581 force_user_fault(sp + 0x38, 0); 464 force_user_fault(sp + 0x38, 0);
582 force_user_fault(sp, 0); 465 force_user_fault(sp, 0);
583 466
@@ -589,7 +472,7 @@ void window_ret_fault(struct pt_regs *regs)
589 unsigned long sp; 472 unsigned long sp;
590 473
591 sp = regs->u_regs[UREG_FP]; 474 sp = regs->u_regs[UREG_FP];
592 if(((sp + 0x38) & PAGE_MASK) != (sp & PAGE_MASK)) 475 if (((sp + 0x38) & PAGE_MASK) != (sp & PAGE_MASK))
593 force_user_fault(sp + 0x38, 0); 476 force_user_fault(sp + 0x38, 0);
594 force_user_fault(sp, 0); 477 force_user_fault(sp, 0);
595 478
diff --git a/arch/sparc/mm/init_32.c b/arch/sparc/mm/init_32.c
index c5f9021b1a01..ef5c779ec855 100644
--- a/arch/sparc/mm/init_32.c
+++ b/arch/sparc/mm/init_32.c
@@ -27,7 +27,6 @@
27#include <linux/gfp.h> 27#include <linux/gfp.h>
28 28
29#include <asm/sections.h> 29#include <asm/sections.h>
30#include <asm/vac-ops.h>
31#include <asm/page.h> 30#include <asm/page.h>
32#include <asm/pgtable.h> 31#include <asm/pgtable.h>
33#include <asm/vaddrs.h> 32#include <asm/vaddrs.h>
@@ -45,9 +44,6 @@ EXPORT_SYMBOL(phys_base);
45unsigned long pfn_base; 44unsigned long pfn_base;
46EXPORT_SYMBOL(pfn_base); 45EXPORT_SYMBOL(pfn_base);
47 46
48unsigned long page_kernel;
49EXPORT_SYMBOL(page_kernel);
50
51struct sparc_phys_banks sp_banks[SPARC_PHYS_BANKS+1]; 47struct sparc_phys_banks sp_banks[SPARC_PHYS_BANKS+1];
52unsigned long sparc_unmapped_base; 48unsigned long sparc_unmapped_base;
53 49
@@ -287,44 +283,16 @@ unsigned long __init bootmem_init(unsigned long *pages_avail)
287} 283}
288 284
289/* 285/*
290 * check_pgt_cache
291 *
292 * This is called at the end of unmapping of VMA (zap_page_range),
293 * to rescan the page cache for architecture specific things,
294 * presumably something like sun4/sun4c PMEGs. Most architectures
295 * define check_pgt_cache empty.
296 *
297 * We simply copy the 2.4 implementation for now.
298 */
299static int pgt_cache_water[2] = { 25, 50 };
300
301void check_pgt_cache(void)
302{
303 do_check_pgt_cache(pgt_cache_water[0], pgt_cache_water[1]);
304}
305
306/*
307 * paging_init() sets up the page tables: We call the MMU specific 286 * paging_init() sets up the page tables: We call the MMU specific
308 * init routine based upon the Sun model type on the Sparc. 287 * init routine based upon the Sun model type on the Sparc.
309 * 288 *
310 */ 289 */
311extern void sun4c_paging_init(void);
312extern void srmmu_paging_init(void); 290extern void srmmu_paging_init(void);
313extern void device_scan(void); 291extern void device_scan(void);
314 292
315pgprot_t PAGE_SHARED __read_mostly;
316EXPORT_SYMBOL(PAGE_SHARED);
317
318void __init paging_init(void) 293void __init paging_init(void)
319{ 294{
320 switch(sparc_cpu_model) { 295 switch(sparc_cpu_model) {
321 case sun4c:
322 case sun4e:
323 case sun4:
324 sun4c_paging_init();
325 sparc_unmapped_base = 0xe0000000;
326 BTFIXUPSET_SETHI(sparc_unmapped_base, 0xe0000000);
327 break;
328 case sparc_leon: 296 case sparc_leon:
329 leon_init(); 297 leon_init();
330 /* fall through */ 298 /* fall through */
@@ -332,7 +300,6 @@ void __init paging_init(void)
332 case sun4d: 300 case sun4d:
333 srmmu_paging_init(); 301 srmmu_paging_init();
334 sparc_unmapped_base = 0x50000000; 302 sparc_unmapped_base = 0x50000000;
335 BTFIXUPSET_SETHI(sparc_unmapped_base, 0x50000000);
336 break; 303 break;
337 default: 304 default:
338 prom_printf("paging_init: Cannot init paging on this Sparc\n"); 305 prom_printf("paging_init: Cannot init paging on this Sparc\n");
@@ -341,24 +308,6 @@ void __init paging_init(void)
341 prom_halt(); 308 prom_halt();
342 } 309 }
343 310
344 /* Initialize the protection map with non-constant, MMU dependent values. */
345 protection_map[0] = PAGE_NONE;
346 protection_map[1] = PAGE_READONLY;
347 protection_map[2] = PAGE_COPY;
348 protection_map[3] = PAGE_COPY;
349 protection_map[4] = PAGE_READONLY;
350 protection_map[5] = PAGE_READONLY;
351 protection_map[6] = PAGE_COPY;
352 protection_map[7] = PAGE_COPY;
353 protection_map[8] = PAGE_NONE;
354 protection_map[9] = PAGE_READONLY;
355 protection_map[10] = PAGE_SHARED;
356 protection_map[11] = PAGE_SHARED;
357 protection_map[12] = PAGE_READONLY;
358 protection_map[13] = PAGE_READONLY;
359 protection_map[14] = PAGE_SHARED;
360 protection_map[15] = PAGE_SHARED;
361 btfixup();
362 prom_build_devicetree(); 311 prom_build_devicetree();
363 of_fill_in_cpu_data(); 312 of_fill_in_cpu_data();
364 device_scan(); 313 device_scan();
diff --git a/arch/sparc/mm/init_64.c b/arch/sparc/mm/init_64.c
index 21faaeea85de..6026fdd1b2ed 100644
--- a/arch/sparc/mm/init_64.c
+++ b/arch/sparc/mm/init_64.c
@@ -741,7 +741,6 @@ static void __init find_ramdisk(unsigned long phys_base)
741struct node_mem_mask { 741struct node_mem_mask {
742 unsigned long mask; 742 unsigned long mask;
743 unsigned long val; 743 unsigned long val;
744 unsigned long bootmem_paddr;
745}; 744};
746static struct node_mem_mask node_masks[MAX_NUMNODES]; 745static struct node_mem_mask node_masks[MAX_NUMNODES];
747static int num_node_masks; 746static int num_node_masks;
@@ -806,12 +805,6 @@ static u64 memblock_nid_range(u64 start, u64 end, int *nid)
806 805
807 return start; 806 return start;
808} 807}
809#else
810static u64 memblock_nid_range(u64 start, u64 end, int *nid)
811{
812 *nid = 0;
813 return end;
814}
815#endif 808#endif
816 809
817/* This must be invoked after performing all of the necessary 810/* This must be invoked after performing all of the necessary
@@ -820,10 +813,11 @@ static u64 memblock_nid_range(u64 start, u64 end, int *nid)
820 */ 813 */
821static void __init allocate_node_data(int nid) 814static void __init allocate_node_data(int nid)
822{ 815{
823 unsigned long paddr, num_pages, start_pfn, end_pfn;
824 struct pglist_data *p; 816 struct pglist_data *p;
825 817 unsigned long start_pfn, end_pfn;
826#ifdef CONFIG_NEED_MULTIPLE_NODES 818#ifdef CONFIG_NEED_MULTIPLE_NODES
819 unsigned long paddr;
820
827 paddr = memblock_alloc_try_nid(sizeof(struct pglist_data), SMP_CACHE_BYTES, nid); 821 paddr = memblock_alloc_try_nid(sizeof(struct pglist_data), SMP_CACHE_BYTES, nid);
828 if (!paddr) { 822 if (!paddr) {
829 prom_printf("Cannot allocate pglist_data for nid[%d]\n", nid); 823 prom_printf("Cannot allocate pglist_data for nid[%d]\n", nid);
@@ -832,7 +826,7 @@ static void __init allocate_node_data(int nid)
832 NODE_DATA(nid) = __va(paddr); 826 NODE_DATA(nid) = __va(paddr);
833 memset(NODE_DATA(nid), 0, sizeof(struct pglist_data)); 827 memset(NODE_DATA(nid), 0, sizeof(struct pglist_data));
834 828
835 NODE_DATA(nid)->bdata = &bootmem_node_data[nid]; 829 NODE_DATA(nid)->node_id = nid;
836#endif 830#endif
837 831
838 p = NODE_DATA(nid); 832 p = NODE_DATA(nid);
@@ -840,18 +834,6 @@ static void __init allocate_node_data(int nid)
840 get_pfn_range_for_nid(nid, &start_pfn, &end_pfn); 834 get_pfn_range_for_nid(nid, &start_pfn, &end_pfn);
841 p->node_start_pfn = start_pfn; 835 p->node_start_pfn = start_pfn;
842 p->node_spanned_pages = end_pfn - start_pfn; 836 p->node_spanned_pages = end_pfn - start_pfn;
843
844 if (p->node_spanned_pages) {
845 num_pages = bootmem_bootmap_pages(p->node_spanned_pages);
846
847 paddr = memblock_alloc_try_nid(num_pages << PAGE_SHIFT, PAGE_SIZE, nid);
848 if (!paddr) {
849 prom_printf("Cannot allocate bootmap for nid[%d]\n",
850 nid);
851 prom_halt();
852 }
853 node_masks[nid].bootmem_paddr = paddr;
854 }
855} 837}
856 838
857static void init_node_masks_nonnuma(void) 839static void init_node_masks_nonnuma(void)
@@ -1292,75 +1274,9 @@ static void __init bootmem_init_nonnuma(void)
1292 node_set_online(0); 1274 node_set_online(0);
1293} 1275}
1294 1276
1295static void __init reserve_range_in_node(int nid, unsigned long start,
1296 unsigned long end)
1297{
1298 numadbg(" reserve_range_in_node(nid[%d],start[%lx],end[%lx]\n",
1299 nid, start, end);
1300 while (start < end) {
1301 unsigned long this_end;
1302 int n;
1303
1304 this_end = memblock_nid_range(start, end, &n);
1305 if (n == nid) {
1306 numadbg(" MATCH reserving range [%lx:%lx]\n",
1307 start, this_end);
1308 reserve_bootmem_node(NODE_DATA(nid), start,
1309 (this_end - start), BOOTMEM_DEFAULT);
1310 } else
1311 numadbg(" NO MATCH, advancing start to %lx\n",
1312 this_end);
1313
1314 start = this_end;
1315 }
1316}
1317
1318static void __init trim_reserved_in_node(int nid)
1319{
1320 struct memblock_region *reg;
1321
1322 numadbg(" trim_reserved_in_node(%d)\n", nid);
1323
1324 for_each_memblock(reserved, reg)
1325 reserve_range_in_node(nid, reg->base, reg->base + reg->size);
1326}
1327
1328static void __init bootmem_init_one_node(int nid)
1329{
1330 struct pglist_data *p;
1331
1332 numadbg("bootmem_init_one_node(%d)\n", nid);
1333
1334 p = NODE_DATA(nid);
1335
1336 if (p->node_spanned_pages) {
1337 unsigned long paddr = node_masks[nid].bootmem_paddr;
1338 unsigned long end_pfn;
1339
1340 end_pfn = p->node_start_pfn + p->node_spanned_pages;
1341
1342 numadbg(" init_bootmem_node(%d, %lx, %lx, %lx)\n",
1343 nid, paddr >> PAGE_SHIFT, p->node_start_pfn, end_pfn);
1344
1345 init_bootmem_node(p, paddr >> PAGE_SHIFT,
1346 p->node_start_pfn, end_pfn);
1347
1348 numadbg(" free_bootmem_with_active_regions(%d, %lx)\n",
1349 nid, end_pfn);
1350 free_bootmem_with_active_regions(nid, end_pfn);
1351
1352 trim_reserved_in_node(nid);
1353
1354 numadbg(" sparse_memory_present_with_active_regions(%d)\n",
1355 nid);
1356 sparse_memory_present_with_active_regions(nid);
1357 }
1358}
1359
1360static unsigned long __init bootmem_init(unsigned long phys_base) 1277static unsigned long __init bootmem_init(unsigned long phys_base)
1361{ 1278{
1362 unsigned long end_pfn; 1279 unsigned long end_pfn;
1363 int nid;
1364 1280
1365 end_pfn = memblock_end_of_DRAM() >> PAGE_SHIFT; 1281 end_pfn = memblock_end_of_DRAM() >> PAGE_SHIFT;
1366 max_pfn = max_low_pfn = end_pfn; 1282 max_pfn = max_low_pfn = end_pfn;
@@ -1369,11 +1285,12 @@ static unsigned long __init bootmem_init(unsigned long phys_base)
1369 if (bootmem_init_numa() < 0) 1285 if (bootmem_init_numa() < 0)
1370 bootmem_init_nonnuma(); 1286 bootmem_init_nonnuma();
1371 1287
1372 /* XXX cpu notifier XXX */ 1288 /* Dump memblock with node info. */
1289 memblock_dump_all();
1373 1290
1374 for_each_online_node(nid) 1291 /* XXX cpu notifier XXX */
1375 bootmem_init_one_node(nid);
1376 1292
1293 sparse_memory_present_with_active_regions(MAX_NUMNODES);
1377 sparse_init(); 1294 sparse_init();
1378 1295
1379 return end_pfn; 1296 return end_pfn;
@@ -1701,6 +1618,7 @@ void __init paging_init(void)
1701{ 1618{
1702 unsigned long end_pfn, shift, phys_base; 1619 unsigned long end_pfn, shift, phys_base;
1703 unsigned long real_end, i; 1620 unsigned long real_end, i;
1621 int node;
1704 1622
1705 /* These build time checkes make sure that the dcache_dirty_cpu() 1623 /* These build time checkes make sure that the dcache_dirty_cpu()
1706 * page->flags usage will work. 1624 * page->flags usage will work.
@@ -1826,22 +1744,24 @@ void __init paging_init(void)
1826#endif 1744#endif
1827 } 1745 }
1828 1746
1747 /* Setup bootmem... */
1748 last_valid_pfn = end_pfn = bootmem_init(phys_base);
1749
1829 /* Once the OF device tree and MDESC have been setup, we know 1750 /* Once the OF device tree and MDESC have been setup, we know
1830 * the list of possible cpus. Therefore we can allocate the 1751 * the list of possible cpus. Therefore we can allocate the
1831 * IRQ stacks. 1752 * IRQ stacks.
1832 */ 1753 */
1833 for_each_possible_cpu(i) { 1754 for_each_possible_cpu(i) {
1834 /* XXX Use node local allocations... XXX */ 1755 node = cpu_to_node(i);
1835 softirq_stack[i] = __va(memblock_alloc(THREAD_SIZE, THREAD_SIZE));
1836 hardirq_stack[i] = __va(memblock_alloc(THREAD_SIZE, THREAD_SIZE));
1837 }
1838 1756
1839 /* Setup bootmem... */ 1757 softirq_stack[i] = __alloc_bootmem_node(NODE_DATA(node),
1840 last_valid_pfn = end_pfn = bootmem_init(phys_base); 1758 THREAD_SIZE,
1759 THREAD_SIZE, 0);
1760 hardirq_stack[i] = __alloc_bootmem_node(NODE_DATA(node),
1761 THREAD_SIZE,
1762 THREAD_SIZE, 0);
1763 }
1841 1764
1842#ifndef CONFIG_NEED_MULTIPLE_NODES
1843 max_mapnr = last_valid_pfn;
1844#endif
1845 kernel_physical_mapping_init(); 1765 kernel_physical_mapping_init();
1846 1766
1847 { 1767 {
@@ -1973,6 +1893,7 @@ void __init mem_init(void)
1973 free_all_bootmem_node(NODE_DATA(i)); 1893 free_all_bootmem_node(NODE_DATA(i));
1974 } 1894 }
1975 } 1895 }
1896 totalram_pages += free_low_memory_core_early(MAX_NUMNODES);
1976 } 1897 }
1977#else 1898#else
1978 totalram_pages = free_all_bootmem(); 1899 totalram_pages = free_all_bootmem();
diff --git a/arch/sparc/mm/io-unit.c b/arch/sparc/mm/io-unit.c
index fc58c3e917df..eb99862e9654 100644
--- a/arch/sparc/mm/io-unit.c
+++ b/arch/sparc/mm/io-unit.c
@@ -197,7 +197,7 @@ static void iounit_release_scsi_sgl(struct device *dev, struct scatterlist *sg,
197} 197}
198 198
199#ifdef CONFIG_SBUS 199#ifdef CONFIG_SBUS
200static int iounit_map_dma_area(struct device *dev, dma_addr_t *pba, unsigned long va, __u32 addr, int len) 200static int iounit_map_dma_area(struct device *dev, dma_addr_t *pba, unsigned long va, unsigned long addr, int len)
201{ 201{
202 struct iounit_struct *iounit = dev->archdata.iommu; 202 struct iounit_struct *iounit = dev->archdata.iommu;
203 unsigned long page, end; 203 unsigned long page, end;
@@ -242,29 +242,18 @@ static void iounit_unmap_dma_area(struct device *dev, unsigned long addr, int le
242} 242}
243#endif 243#endif
244 244
245static char *iounit_lockarea(char *vaddr, unsigned long len) 245static const struct sparc32_dma_ops iounit_dma_ops = {
246{ 246 .get_scsi_one = iounit_get_scsi_one,
247/* FIXME: Write this */ 247 .get_scsi_sgl = iounit_get_scsi_sgl,
248 return vaddr; 248 .release_scsi_one = iounit_release_scsi_one,
249} 249 .release_scsi_sgl = iounit_release_scsi_sgl,
250 250#ifdef CONFIG_SBUS
251static void iounit_unlockarea(char *vaddr, unsigned long len) 251 .map_dma_area = iounit_map_dma_area,
252{ 252 .unmap_dma_area = iounit_unmap_dma_area,
253/* FIXME: Write this */ 253#endif
254} 254};
255 255
256void __init ld_mmu_iounit(void) 256void __init ld_mmu_iounit(void)
257{ 257{
258 BTFIXUPSET_CALL(mmu_lockarea, iounit_lockarea, BTFIXUPCALL_RETO0); 258 sparc32_dma_ops = &iounit_dma_ops;
259 BTFIXUPSET_CALL(mmu_unlockarea, iounit_unlockarea, BTFIXUPCALL_NOP);
260
261 BTFIXUPSET_CALL(mmu_get_scsi_one, iounit_get_scsi_one, BTFIXUPCALL_NORM);
262 BTFIXUPSET_CALL(mmu_get_scsi_sgl, iounit_get_scsi_sgl, BTFIXUPCALL_NORM);
263 BTFIXUPSET_CALL(mmu_release_scsi_one, iounit_release_scsi_one, BTFIXUPCALL_NORM);
264 BTFIXUPSET_CALL(mmu_release_scsi_sgl, iounit_release_scsi_sgl, BTFIXUPCALL_NORM);
265
266#ifdef CONFIG_SBUS
267 BTFIXUPSET_CALL(mmu_map_dma_area, iounit_map_dma_area, BTFIXUPCALL_NORM);
268 BTFIXUPSET_CALL(mmu_unmap_dma_area, iounit_unmap_dma_area, BTFIXUPCALL_NORM);
269#endif
270} 259}
diff --git a/arch/sparc/mm/iommu.c b/arch/sparc/mm/iommu.c
index 07fc6a65d9b6..a8a58cad9d2b 100644
--- a/arch/sparc/mm/iommu.c
+++ b/arch/sparc/mm/iommu.c
@@ -39,8 +39,6 @@
39 39
40/* srmmu.c */ 40/* srmmu.c */
41extern int viking_mxcc_present; 41extern int viking_mxcc_present;
42BTFIXUPDEF_CALL(void, flush_page_for_dma, unsigned long)
43#define flush_page_for_dma(page) BTFIXUP_CALL(flush_page_for_dma)(page)
44extern int flush_page_for_dma_global; 42extern int flush_page_for_dma_global;
45static int viking_flush; 43static int viking_flush;
46/* viking.S */ 44/* viking.S */
@@ -143,7 +141,6 @@ static int __init iommu_init(void)
143 141
144subsys_initcall(iommu_init); 142subsys_initcall(iommu_init);
145 143
146/* This begs to be btfixup-ed by srmmu. */
147/* Flush the iotlb entries to ram. */ 144/* Flush the iotlb entries to ram. */
148/* This could be better if we didn't have to flush whole pages. */ 145/* This could be better if we didn't have to flush whole pages. */
149static void iommu_flush_iotlb(iopte_t *iopte, unsigned int niopte) 146static void iommu_flush_iotlb(iopte_t *iopte, unsigned int niopte)
@@ -216,11 +213,6 @@ static u32 iommu_get_scsi_one(struct device *dev, char *vaddr, unsigned int len)
216 return busa + off; 213 return busa + off;
217} 214}
218 215
219static __u32 iommu_get_scsi_one_noflush(struct device *dev, char *vaddr, unsigned long len)
220{
221 return iommu_get_scsi_one(dev, vaddr, len);
222}
223
224static __u32 iommu_get_scsi_one_gflush(struct device *dev, char *vaddr, unsigned long len) 216static __u32 iommu_get_scsi_one_gflush(struct device *dev, char *vaddr, unsigned long len)
225{ 217{
226 flush_page_for_dma(0); 218 flush_page_for_dma(0);
@@ -238,19 +230,6 @@ static __u32 iommu_get_scsi_one_pflush(struct device *dev, char *vaddr, unsigned
238 return iommu_get_scsi_one(dev, vaddr, len); 230 return iommu_get_scsi_one(dev, vaddr, len);
239} 231}
240 232
241static void iommu_get_scsi_sgl_noflush(struct device *dev, struct scatterlist *sg, int sz)
242{
243 int n;
244
245 while (sz != 0) {
246 --sz;
247 n = (sg->length + sg->offset + PAGE_SIZE-1) >> PAGE_SHIFT;
248 sg->dma_address = iommu_get_one(dev, sg_page(sg), n) + sg->offset;
249 sg->dma_length = sg->length;
250 sg = sg_next(sg);
251 }
252}
253
254static void iommu_get_scsi_sgl_gflush(struct device *dev, struct scatterlist *sg, int sz) 233static void iommu_get_scsi_sgl_gflush(struct device *dev, struct scatterlist *sg, int sz)
255{ 234{
256 int n; 235 int n;
@@ -426,40 +405,36 @@ static void iommu_unmap_dma_area(struct device *dev, unsigned long busa, int len
426} 405}
427#endif 406#endif
428 407
429static char *iommu_lockarea(char *vaddr, unsigned long len) 408static const struct sparc32_dma_ops iommu_dma_gflush_ops = {
430{ 409 .get_scsi_one = iommu_get_scsi_one_gflush,
431 return vaddr; 410 .get_scsi_sgl = iommu_get_scsi_sgl_gflush,
432} 411 .release_scsi_one = iommu_release_scsi_one,
412 .release_scsi_sgl = iommu_release_scsi_sgl,
413#ifdef CONFIG_SBUS
414 .map_dma_area = iommu_map_dma_area,
415 .unmap_dma_area = iommu_unmap_dma_area,
416#endif
417};
433 418
434static void iommu_unlockarea(char *vaddr, unsigned long len) 419static const struct sparc32_dma_ops iommu_dma_pflush_ops = {
435{ 420 .get_scsi_one = iommu_get_scsi_one_pflush,
436} 421 .get_scsi_sgl = iommu_get_scsi_sgl_pflush,
422 .release_scsi_one = iommu_release_scsi_one,
423 .release_scsi_sgl = iommu_release_scsi_sgl,
424#ifdef CONFIG_SBUS
425 .map_dma_area = iommu_map_dma_area,
426 .unmap_dma_area = iommu_unmap_dma_area,
427#endif
428};
437 429
438void __init ld_mmu_iommu(void) 430void __init ld_mmu_iommu(void)
439{ 431{
440 viking_flush = (BTFIXUPVAL_CALL(flush_page_for_dma) == (unsigned long)viking_flush_page); 432 if (flush_page_for_dma_global) {
441 BTFIXUPSET_CALL(mmu_lockarea, iommu_lockarea, BTFIXUPCALL_RETO0);
442 BTFIXUPSET_CALL(mmu_unlockarea, iommu_unlockarea, BTFIXUPCALL_NOP);
443
444 if (!BTFIXUPVAL_CALL(flush_page_for_dma)) {
445 /* IO coherent chip */
446 BTFIXUPSET_CALL(mmu_get_scsi_one, iommu_get_scsi_one_noflush, BTFIXUPCALL_RETO0);
447 BTFIXUPSET_CALL(mmu_get_scsi_sgl, iommu_get_scsi_sgl_noflush, BTFIXUPCALL_NORM);
448 } else if (flush_page_for_dma_global) {
449 /* flush_page_for_dma flushes everything, no matter of what page is it */ 433 /* flush_page_for_dma flushes everything, no matter of what page is it */
450 BTFIXUPSET_CALL(mmu_get_scsi_one, iommu_get_scsi_one_gflush, BTFIXUPCALL_NORM); 434 sparc32_dma_ops = &iommu_dma_gflush_ops;
451 BTFIXUPSET_CALL(mmu_get_scsi_sgl, iommu_get_scsi_sgl_gflush, BTFIXUPCALL_NORM);
452 } else { 435 } else {
453 BTFIXUPSET_CALL(mmu_get_scsi_one, iommu_get_scsi_one_pflush, BTFIXUPCALL_NORM); 436 sparc32_dma_ops = &iommu_dma_pflush_ops;
454 BTFIXUPSET_CALL(mmu_get_scsi_sgl, iommu_get_scsi_sgl_pflush, BTFIXUPCALL_NORM);
455 } 437 }
456 BTFIXUPSET_CALL(mmu_release_scsi_one, iommu_release_scsi_one, BTFIXUPCALL_NORM);
457 BTFIXUPSET_CALL(mmu_release_scsi_sgl, iommu_release_scsi_sgl, BTFIXUPCALL_NORM);
458
459#ifdef CONFIG_SBUS
460 BTFIXUPSET_CALL(mmu_map_dma_area, iommu_map_dma_area, BTFIXUPCALL_NORM);
461 BTFIXUPSET_CALL(mmu_unmap_dma_area, iommu_unmap_dma_area, BTFIXUPCALL_NORM);
462#endif
463 438
464 if (viking_mxcc_present || srmmu_modtype == HyperSparc) { 439 if (viking_mxcc_present || srmmu_modtype == HyperSparc) {
465 dvma_prot = __pgprot(SRMMU_CACHE | SRMMU_ET_PTE | SRMMU_PRIV); 440 dvma_prot = __pgprot(SRMMU_CACHE | SRMMU_ET_PTE | SRMMU_PRIV);
diff --git a/arch/sparc/mm/leon_mm.c b/arch/sparc/mm/leon_mm.c
index 13c2169822a8..4c67ae6e5023 100644
--- a/arch/sparc/mm/leon_mm.c
+++ b/arch/sparc/mm/leon_mm.c
@@ -15,9 +15,23 @@
15#include <asm/leon.h> 15#include <asm/leon.h>
16#include <asm/tlbflush.h> 16#include <asm/tlbflush.h>
17 17
18#include "srmmu.h"
19
18int leon_flush_during_switch = 1; 20int leon_flush_during_switch = 1;
19int srmmu_swprobe_trace; 21int srmmu_swprobe_trace;
20 22
23static inline unsigned long leon_get_ctable_ptr(void)
24{
25 unsigned int retval;
26
27 __asm__ __volatile__("lda [%1] %2, %0\n\t" :
28 "=r" (retval) :
29 "r" (SRMMU_CTXTBL_PTR),
30 "i" (ASI_LEON_MMUREGS));
31 return (retval & SRMMU_CTX_PMASK) << 4;
32}
33
34
21unsigned long srmmu_swprobe(unsigned long vaddr, unsigned long *paddr) 35unsigned long srmmu_swprobe(unsigned long vaddr, unsigned long *paddr)
22{ 36{
23 37
@@ -33,10 +47,10 @@ unsigned long srmmu_swprobe(unsigned long vaddr, unsigned long *paddr)
33 if (srmmu_swprobe_trace) 47 if (srmmu_swprobe_trace)
34 printk(KERN_INFO "swprobe: trace on\n"); 48 printk(KERN_INFO "swprobe: trace on\n");
35 49
36 ctxtbl = srmmu_get_ctable_ptr(); 50 ctxtbl = leon_get_ctable_ptr();
37 if (!(ctxtbl)) { 51 if (!(ctxtbl)) {
38 if (srmmu_swprobe_trace) 52 if (srmmu_swprobe_trace)
39 printk(KERN_INFO "swprobe: srmmu_get_ctable_ptr returned 0=>0\n"); 53 printk(KERN_INFO "swprobe: leon_get_ctable_ptr returned 0=>0\n");
40 return 0; 54 return 0;
41 } 55 }
42 if (!_pfn_valid(PFN(ctxtbl))) { 56 if (!_pfn_valid(PFN(ctxtbl))) {
@@ -258,3 +272,80 @@ void leon_switch_mm(void)
258 if (leon_flush_during_switch) 272 if (leon_flush_during_switch)
259 leon_flush_cache_all(); 273 leon_flush_cache_all();
260} 274}
275
276static void leon_flush_cache_mm(struct mm_struct *mm)
277{
278 leon_flush_cache_all();
279}
280
281static void leon_flush_cache_page(struct vm_area_struct *vma, unsigned long page)
282{
283 leon_flush_pcache_all(vma, page);
284}
285
286static void leon_flush_cache_range(struct vm_area_struct *vma,
287 unsigned long start,
288 unsigned long end)
289{
290 leon_flush_cache_all();
291}
292
293static void leon_flush_tlb_mm(struct mm_struct *mm)
294{
295 leon_flush_tlb_all();
296}
297
298static void leon_flush_tlb_page(struct vm_area_struct *vma,
299 unsigned long page)
300{
301 leon_flush_tlb_all();
302}
303
304static void leon_flush_tlb_range(struct vm_area_struct *vma,
305 unsigned long start,
306 unsigned long end)
307{
308 leon_flush_tlb_all();
309}
310
311static void leon_flush_page_to_ram(unsigned long page)
312{
313 leon_flush_cache_all();
314}
315
316static void leon_flush_sig_insns(struct mm_struct *mm, unsigned long page)
317{
318 leon_flush_cache_all();
319}
320
321static void leon_flush_page_for_dma(unsigned long page)
322{
323 leon_flush_dcache_all();
324}
325
326void __init poke_leonsparc(void)
327{
328}
329
330static const struct sparc32_cachetlb_ops leon_ops = {
331 .cache_all = leon_flush_cache_all,
332 .cache_mm = leon_flush_cache_mm,
333 .cache_page = leon_flush_cache_page,
334 .cache_range = leon_flush_cache_range,
335 .tlb_all = leon_flush_tlb_all,
336 .tlb_mm = leon_flush_tlb_mm,
337 .tlb_page = leon_flush_tlb_page,
338 .tlb_range = leon_flush_tlb_range,
339 .page_to_ram = leon_flush_page_to_ram,
340 .sig_insns = leon_flush_sig_insns,
341 .page_for_dma = leon_flush_page_for_dma,
342};
343
344void __init init_leon(void)
345{
346 srmmu_name = "LEON";
347 sparc32_cachetlb_ops = &leon_ops;
348 poke_srmmu = poke_leonsparc;
349
350 leon_flush_during_switch = leon_flush_needed();
351}
diff --git a/arch/sparc/mm/loadmmu.c b/arch/sparc/mm/loadmmu.c
deleted file mode 100644
index c5bf2a6c3858..000000000000
--- a/arch/sparc/mm/loadmmu.c
+++ /dev/null
@@ -1,43 +0,0 @@
1/*
2 * loadmmu.c: This code loads up all the mm function pointers once the
3 * machine type has been determined. It also sets the static
4 * mmu values such as PAGE_NONE, etc.
5 *
6 * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
7 * Copyright (C) 1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
8 */
9
10#include <linux/kernel.h>
11#include <linux/mm.h>
12#include <linux/init.h>
13
14#include <asm/page.h>
15#include <asm/pgtable.h>
16#include <asm/mmu_context.h>
17#include <asm/oplib.h>
18
19struct ctx_list *ctx_list_pool;
20struct ctx_list ctx_free;
21struct ctx_list ctx_used;
22
23extern void ld_mmu_sun4c(void);
24extern void ld_mmu_srmmu(void);
25
26void __init load_mmu(void)
27{
28 switch(sparc_cpu_model) {
29 case sun4c:
30 case sun4:
31 ld_mmu_sun4c();
32 break;
33 case sun4m:
34 case sun4d:
35 case sparc_leon:
36 ld_mmu_srmmu();
37 break;
38 default:
39 prom_printf("load_mmu: %d unsupported\n", (int)sparc_cpu_model);
40 prom_halt();
41 }
42 btfixup();
43}
diff --git a/arch/sparc/mm/nosun4c.c b/arch/sparc/mm/nosun4c.c
deleted file mode 100644
index 4e62c27147c4..000000000000
--- a/arch/sparc/mm/nosun4c.c
+++ /dev/null
@@ -1,77 +0,0 @@
1/*
2 * nosun4c.c: This file is a bunch of dummies for SMP compiles,
3 * so that it does not need sun4c and avoid ifdefs.
4 *
5 * Copyright (C) 1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
6 */
7
8#include <linux/kernel.h>
9#include <linux/mm.h>
10#include <linux/init.h>
11#include <asm/pgtable.h>
12
13static char shouldnothappen[] __initdata = "32bit SMP kernel only supports sun4m and sun4d\n";
14
15/* Dummies */
16struct sun4c_mmu_ring {
17 unsigned long xxx1[3];
18 unsigned char xxx2[2];
19 int xxx3;
20};
21struct sun4c_mmu_ring sun4c_kernel_ring;
22struct sun4c_mmu_ring sun4c_kfree_ring;
23unsigned long sun4c_kernel_faults;
24unsigned long *sun4c_memerr_reg;
25
26static void __init should_not_happen(void)
27{
28 prom_printf(shouldnothappen);
29 prom_halt();
30}
31
32unsigned long __init sun4c_paging_init(unsigned long start_mem, unsigned long end_mem)
33{
34 should_not_happen();
35 return 0;
36}
37
38void __init ld_mmu_sun4c(void)
39{
40 should_not_happen();
41}
42
43void sun4c_mapioaddr(unsigned long physaddr, unsigned long virt_addr, int bus_type, int rdonly)
44{
45}
46
47void sun4c_unmapioaddr(unsigned long virt_addr)
48{
49}
50
51void sun4c_complete_all_stores(void)
52{
53}
54
55pte_t *sun4c_pte_offset(pmd_t * dir, unsigned long address)
56{
57 return NULL;
58}
59
60pte_t *sun4c_pte_offset_kernel(pmd_t *dir, unsigned long address)
61{
62 return NULL;
63}
64
65void sun4c_update_mmu_cache(struct vm_area_struct *vma, unsigned long address, pte_t *ptep)
66{
67}
68
69void __init sun4c_probe_vac(void)
70{
71 should_not_happen();
72}
73
74void __init sun4c_probe_memerr_reg(void)
75{
76 should_not_happen();
77}
diff --git a/arch/sparc/mm/srmmu.c b/arch/sparc/mm/srmmu.c
index cbef74e793b8..8e97e0305b01 100644
--- a/arch/sparc/mm/srmmu.c
+++ b/arch/sparc/mm/srmmu.c
@@ -48,39 +48,37 @@
48#include <asm/turbosparc.h> 48#include <asm/turbosparc.h>
49#include <asm/leon.h> 49#include <asm/leon.h>
50 50
51#include <asm/btfixup.h> 51#include "srmmu.h"
52 52
53enum mbus_module srmmu_modtype; 53enum mbus_module srmmu_modtype;
54static unsigned int hwbug_bitmask; 54static unsigned int hwbug_bitmask;
55int vac_cache_size; 55int vac_cache_size;
56int vac_line_size; 56int vac_line_size;
57 57
58struct ctx_list *ctx_list_pool;
59struct ctx_list ctx_free;
60struct ctx_list ctx_used;
61
58extern struct resource sparc_iomap; 62extern struct resource sparc_iomap;
59 63
60extern unsigned long last_valid_pfn; 64extern unsigned long last_valid_pfn;
61 65
62extern unsigned long page_kernel;
63
64static pgd_t *srmmu_swapper_pg_dir; 66static pgd_t *srmmu_swapper_pg_dir;
65 67
68const struct sparc32_cachetlb_ops *sparc32_cachetlb_ops;
69
66#ifdef CONFIG_SMP 70#ifdef CONFIG_SMP
71const struct sparc32_cachetlb_ops *local_ops;
72
67#define FLUSH_BEGIN(mm) 73#define FLUSH_BEGIN(mm)
68#define FLUSH_END 74#define FLUSH_END
69#else 75#else
70#define FLUSH_BEGIN(mm) if((mm)->context != NO_CONTEXT) { 76#define FLUSH_BEGIN(mm) if ((mm)->context != NO_CONTEXT) {
71#define FLUSH_END } 77#define FLUSH_END }
72#endif 78#endif
73 79
74BTFIXUPDEF_CALL(void, flush_page_for_dma, unsigned long)
75#define flush_page_for_dma(page) BTFIXUP_CALL(flush_page_for_dma)(page)
76
77int flush_page_for_dma_global = 1; 80int flush_page_for_dma_global = 1;
78 81
79#ifdef CONFIG_SMP
80BTFIXUPDEF_CALL(void, local_flush_page_for_dma, unsigned long)
81#define local_flush_page_for_dma(page) BTFIXUP_CALL(local_flush_page_for_dma)(page)
82#endif
83
84char *srmmu_name; 82char *srmmu_name;
85 83
86ctxd_t *srmmu_ctx_table_phys; 84ctxd_t *srmmu_ctx_table_phys;
@@ -91,28 +89,6 @@ static DEFINE_SPINLOCK(srmmu_context_spinlock);
91 89
92static int is_hypersparc; 90static int is_hypersparc;
93 91
94/*
95 * In general all page table modifications should use the V8 atomic
96 * swap instruction. This insures the mmu and the cpu are in sync
97 * with respect to ref/mod bits in the page tables.
98 */
99static inline unsigned long srmmu_swap(unsigned long *addr, unsigned long value)
100{
101 __asm__ __volatile__("swap [%2], %0" : "=&r" (value) : "0" (value), "r" (addr));
102 return value;
103}
104
105static inline void srmmu_set_pte(pte_t *ptep, pte_t pteval)
106{
107 srmmu_swap((unsigned long *)ptep, pte_val(pteval));
108}
109
110/* The very generic SRMMU page table operations. */
111static inline int srmmu_device_memory(unsigned long x)
112{
113 return ((x & 0xF0000000) != 0);
114}
115
116static int srmmu_cache_pagetables; 92static int srmmu_cache_pagetables;
117 93
118/* these will be initialized in srmmu_nocache_calcsize() */ 94/* these will be initialized in srmmu_nocache_calcsize() */
@@ -129,145 +105,39 @@ void *srmmu_nocache_pool;
129void *srmmu_nocache_bitmap; 105void *srmmu_nocache_bitmap;
130static struct bit_map srmmu_nocache_map; 106static struct bit_map srmmu_nocache_map;
131 107
132static unsigned long srmmu_pte_pfn(pte_t pte)
133{
134 if (srmmu_device_memory(pte_val(pte))) {
135 /* Just return something that will cause
136 * pfn_valid() to return false. This makes
137 * copy_one_pte() to just directly copy to
138 * PTE over.
139 */
140 return ~0UL;
141 }
142 return (pte_val(pte) & SRMMU_PTE_PMASK) >> (PAGE_SHIFT-4);
143}
144
145static struct page *srmmu_pmd_page(pmd_t pmd)
146{
147
148 if (srmmu_device_memory(pmd_val(pmd)))
149 BUG();
150 return pfn_to_page((pmd_val(pmd) & SRMMU_PTD_PMASK) >> (PAGE_SHIFT-4));
151}
152
153static inline unsigned long srmmu_pgd_page(pgd_t pgd)
154{ return srmmu_device_memory(pgd_val(pgd))?~0:(unsigned long)__nocache_va((pgd_val(pgd) & SRMMU_PTD_PMASK) << 4); }
155
156
157static inline int srmmu_pte_none(pte_t pte)
158{ return !(pte_val(pte) & 0xFFFFFFF); }
159
160static inline int srmmu_pte_present(pte_t pte)
161{ return ((pte_val(pte) & SRMMU_ET_MASK) == SRMMU_ET_PTE); }
162
163static inline void srmmu_pte_clear(pte_t *ptep)
164{ srmmu_set_pte(ptep, __pte(0)); }
165
166static inline int srmmu_pmd_none(pmd_t pmd) 108static inline int srmmu_pmd_none(pmd_t pmd)
167{ return !(pmd_val(pmd) & 0xFFFFFFF); } 109{ return !(pmd_val(pmd) & 0xFFFFFFF); }
168 110
169static inline int srmmu_pmd_bad(pmd_t pmd)
170{ return (pmd_val(pmd) & SRMMU_ET_MASK) != SRMMU_ET_PTD; }
171
172static inline int srmmu_pmd_present(pmd_t pmd)
173{ return ((pmd_val(pmd) & SRMMU_ET_MASK) == SRMMU_ET_PTD); }
174
175static inline void srmmu_pmd_clear(pmd_t *pmdp) {
176 int i;
177 for (i = 0; i < PTRS_PER_PTE/SRMMU_REAL_PTRS_PER_PTE; i++)
178 srmmu_set_pte((pte_t *)&pmdp->pmdv[i], __pte(0));
179}
180
181static inline int srmmu_pgd_none(pgd_t pgd)
182{ return !(pgd_val(pgd) & 0xFFFFFFF); }
183
184static inline int srmmu_pgd_bad(pgd_t pgd)
185{ return (pgd_val(pgd) & SRMMU_ET_MASK) != SRMMU_ET_PTD; }
186
187static inline int srmmu_pgd_present(pgd_t pgd)
188{ return ((pgd_val(pgd) & SRMMU_ET_MASK) == SRMMU_ET_PTD); }
189
190static inline void srmmu_pgd_clear(pgd_t * pgdp)
191{ srmmu_set_pte((pte_t *)pgdp, __pte(0)); }
192
193static inline pte_t srmmu_pte_wrprotect(pte_t pte)
194{ return __pte(pte_val(pte) & ~SRMMU_WRITE);}
195
196static inline pte_t srmmu_pte_mkclean(pte_t pte)
197{ return __pte(pte_val(pte) & ~SRMMU_DIRTY);}
198
199static inline pte_t srmmu_pte_mkold(pte_t pte)
200{ return __pte(pte_val(pte) & ~SRMMU_REF);}
201
202static inline pte_t srmmu_pte_mkwrite(pte_t pte)
203{ return __pte(pte_val(pte) | SRMMU_WRITE);}
204
205static inline pte_t srmmu_pte_mkdirty(pte_t pte)
206{ return __pte(pte_val(pte) | SRMMU_DIRTY);}
207
208static inline pte_t srmmu_pte_mkyoung(pte_t pte)
209{ return __pte(pte_val(pte) | SRMMU_REF);}
210
211/*
212 * Conversion functions: convert a page and protection to a page entry,
213 * and a page entry and page directory to the page they refer to.
214 */
215static pte_t srmmu_mk_pte(struct page *page, pgprot_t pgprot)
216{ return __pte((page_to_pfn(page) << (PAGE_SHIFT-4)) | pgprot_val(pgprot)); }
217
218static pte_t srmmu_mk_pte_phys(unsigned long page, pgprot_t pgprot)
219{ return __pte(((page) >> 4) | pgprot_val(pgprot)); }
220
221static pte_t srmmu_mk_pte_io(unsigned long page, pgprot_t pgprot, int space)
222{ return __pte(((page) >> 4) | (space << 28) | pgprot_val(pgprot)); }
223
224/* XXX should we hyper_flush_whole_icache here - Anton */ 111/* XXX should we hyper_flush_whole_icache here - Anton */
225static inline void srmmu_ctxd_set(ctxd_t *ctxp, pgd_t *pgdp) 112static inline void srmmu_ctxd_set(ctxd_t *ctxp, pgd_t *pgdp)
226{ srmmu_set_pte((pte_t *)ctxp, (SRMMU_ET_PTD | (__nocache_pa((unsigned long) pgdp) >> 4))); } 113{ set_pte((pte_t *)ctxp, (SRMMU_ET_PTD | (__nocache_pa((unsigned long) pgdp) >> 4))); }
227 114
228static inline void srmmu_pgd_set(pgd_t * pgdp, pmd_t * pmdp) 115void pmd_set(pmd_t *pmdp, pte_t *ptep)
229{ srmmu_set_pte((pte_t *)pgdp, (SRMMU_ET_PTD | (__nocache_pa((unsigned long) pmdp) >> 4))); }
230
231static void srmmu_pmd_set(pmd_t *pmdp, pte_t *ptep)
232{ 116{
233 unsigned long ptp; /* Physical address, shifted right by 4 */ 117 unsigned long ptp; /* Physical address, shifted right by 4 */
234 int i; 118 int i;
235 119
236 ptp = __nocache_pa((unsigned long) ptep) >> 4; 120 ptp = __nocache_pa((unsigned long) ptep) >> 4;
237 for (i = 0; i < PTRS_PER_PTE/SRMMU_REAL_PTRS_PER_PTE; i++) { 121 for (i = 0; i < PTRS_PER_PTE/SRMMU_REAL_PTRS_PER_PTE; i++) {
238 srmmu_set_pte((pte_t *)&pmdp->pmdv[i], SRMMU_ET_PTD | ptp); 122 set_pte((pte_t *)&pmdp->pmdv[i], SRMMU_ET_PTD | ptp);
239 ptp += (SRMMU_REAL_PTRS_PER_PTE*sizeof(pte_t) >> 4); 123 ptp += (SRMMU_REAL_PTRS_PER_PTE*sizeof(pte_t) >> 4);
240 } 124 }
241} 125}
242 126
243static void srmmu_pmd_populate(pmd_t *pmdp, struct page *ptep) 127void pmd_populate(struct mm_struct *mm, pmd_t *pmdp, struct page *ptep)
244{ 128{
245 unsigned long ptp; /* Physical address, shifted right by 4 */ 129 unsigned long ptp; /* Physical address, shifted right by 4 */
246 int i; 130 int i;
247 131
248 ptp = page_to_pfn(ptep) << (PAGE_SHIFT-4); /* watch for overflow */ 132 ptp = page_to_pfn(ptep) << (PAGE_SHIFT-4); /* watch for overflow */
249 for (i = 0; i < PTRS_PER_PTE/SRMMU_REAL_PTRS_PER_PTE; i++) { 133 for (i = 0; i < PTRS_PER_PTE/SRMMU_REAL_PTRS_PER_PTE; i++) {
250 srmmu_set_pte((pte_t *)&pmdp->pmdv[i], SRMMU_ET_PTD | ptp); 134 set_pte((pte_t *)&pmdp->pmdv[i], SRMMU_ET_PTD | ptp);
251 ptp += (SRMMU_REAL_PTRS_PER_PTE*sizeof(pte_t) >> 4); 135 ptp += (SRMMU_REAL_PTRS_PER_PTE*sizeof(pte_t) >> 4);
252 } 136 }
253} 137}
254 138
255static inline pte_t srmmu_pte_modify(pte_t pte, pgprot_t newprot)
256{ return __pte((pte_val(pte) & SRMMU_CHG_MASK) | pgprot_val(newprot)); }
257
258/* to find an entry in a top-level page table... */
259static inline pgd_t *srmmu_pgd_offset(struct mm_struct * mm, unsigned long address)
260{ return mm->pgd + (address >> SRMMU_PGDIR_SHIFT); }
261
262/* Find an entry in the second-level page table.. */
263static inline pmd_t *srmmu_pmd_offset(pgd_t * dir, unsigned long address)
264{
265 return (pmd_t *) srmmu_pgd_page(*dir) +
266 ((address >> PMD_SHIFT) & (PTRS_PER_PMD - 1));
267}
268
269/* Find an entry in the third-level page table.. */ 139/* Find an entry in the third-level page table.. */
270static inline pte_t *srmmu_pte_offset(pmd_t * dir, unsigned long address) 140pte_t *pte_offset_kernel(pmd_t * dir, unsigned long address)
271{ 141{
272 void *pte; 142 void *pte;
273 143
@@ -276,23 +146,6 @@ static inline pte_t *srmmu_pte_offset(pmd_t * dir, unsigned long address)
276 ((address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1)); 146 ((address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1));
277} 147}
278 148
279static unsigned long srmmu_swp_type(swp_entry_t entry)
280{
281 return (entry.val >> SRMMU_SWP_TYPE_SHIFT) & SRMMU_SWP_TYPE_MASK;
282}
283
284static unsigned long srmmu_swp_offset(swp_entry_t entry)
285{
286 return (entry.val >> SRMMU_SWP_OFF_SHIFT) & SRMMU_SWP_OFF_MASK;
287}
288
289static swp_entry_t srmmu_swp_entry(unsigned long type, unsigned long offset)
290{
291 return (swp_entry_t) {
292 (type & SRMMU_SWP_TYPE_MASK) << SRMMU_SWP_TYPE_SHIFT
293 | (offset & SRMMU_SWP_OFF_MASK) << SRMMU_SWP_OFF_SHIFT };
294}
295
296/* 149/*
297 * size: bytes to allocate in the nocache area. 150 * size: bytes to allocate in the nocache area.
298 * align: bytes, number to align at. 151 * align: bytes, number to align at.
@@ -325,7 +178,7 @@ static unsigned long __srmmu_get_nocache(int size, int align)
325 return (SRMMU_NOCACHE_VADDR + (offset << SRMMU_NOCACHE_BITMAP_SHIFT)); 178 return (SRMMU_NOCACHE_VADDR + (offset << SRMMU_NOCACHE_BITMAP_SHIFT));
326} 179}
327 180
328static unsigned long srmmu_get_nocache(int size, int align) 181unsigned long srmmu_get_nocache(int size, int align)
329{ 182{
330 unsigned long tmp; 183 unsigned long tmp;
331 184
@@ -337,7 +190,7 @@ static unsigned long srmmu_get_nocache(int size, int align)
337 return tmp; 190 return tmp;
338} 191}
339 192
340static void srmmu_free_nocache(unsigned long vaddr, int size) 193void srmmu_free_nocache(unsigned long vaddr, int size)
341{ 194{
342 int offset; 195 int offset;
343 196
@@ -429,15 +282,15 @@ static void __init srmmu_nocache_init(void)
429 282
430 while (vaddr < srmmu_nocache_end) { 283 while (vaddr < srmmu_nocache_end) {
431 pgd = pgd_offset_k(vaddr); 284 pgd = pgd_offset_k(vaddr);
432 pmd = srmmu_pmd_offset(__nocache_fix(pgd), vaddr); 285 pmd = pmd_offset(__nocache_fix(pgd), vaddr);
433 pte = srmmu_pte_offset(__nocache_fix(pmd), vaddr); 286 pte = pte_offset_kernel(__nocache_fix(pmd), vaddr);
434 287
435 pteval = ((paddr >> 4) | SRMMU_ET_PTE | SRMMU_PRIV); 288 pteval = ((paddr >> 4) | SRMMU_ET_PTE | SRMMU_PRIV);
436 289
437 if (srmmu_cache_pagetables) 290 if (srmmu_cache_pagetables)
438 pteval |= SRMMU_CACHE; 291 pteval |= SRMMU_CACHE;
439 292
440 srmmu_set_pte(__nocache_fix(pte), __pte(pteval)); 293 set_pte(__nocache_fix(pte), __pte(pteval));
441 294
442 vaddr += PAGE_SIZE; 295 vaddr += PAGE_SIZE;
443 paddr += PAGE_SIZE; 296 paddr += PAGE_SIZE;
@@ -447,7 +300,7 @@ static void __init srmmu_nocache_init(void)
447 flush_tlb_all(); 300 flush_tlb_all();
448} 301}
449 302
450static inline pgd_t *srmmu_get_pgd_fast(void) 303pgd_t *get_pgd_fast(void)
451{ 304{
452 pgd_t *pgd = NULL; 305 pgd_t *pgd = NULL;
453 306
@@ -462,21 +315,6 @@ static inline pgd_t *srmmu_get_pgd_fast(void)
462 return pgd; 315 return pgd;
463} 316}
464 317
465static void srmmu_free_pgd_fast(pgd_t *pgd)
466{
467 srmmu_free_nocache((unsigned long)pgd, SRMMU_PGD_TABLE_SIZE);
468}
469
470static pmd_t *srmmu_pmd_alloc_one(struct mm_struct *mm, unsigned long address)
471{
472 return (pmd_t *)srmmu_get_nocache(SRMMU_PMD_TABLE_SIZE, SRMMU_PMD_TABLE_SIZE);
473}
474
475static void srmmu_pmd_free(pmd_t * pmd)
476{
477 srmmu_free_nocache((unsigned long)pmd, SRMMU_PMD_TABLE_SIZE);
478}
479
480/* 318/*
481 * Hardware needs alignment to 256 only, but we align to whole page size 319 * Hardware needs alignment to 256 only, but we align to whole page size
482 * to reduce fragmentation problems due to the buddy principle. 320 * to reduce fragmentation problems due to the buddy principle.
@@ -485,31 +323,19 @@ static void srmmu_pmd_free(pmd_t * pmd)
485 * Alignments up to the page size are the same for physical and virtual 323 * Alignments up to the page size are the same for physical and virtual
486 * addresses of the nocache area. 324 * addresses of the nocache area.
487 */ 325 */
488static pte_t * 326pgtable_t pte_alloc_one(struct mm_struct *mm, unsigned long address)
489srmmu_pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address)
490{
491 return (pte_t *)srmmu_get_nocache(PTE_SIZE, PTE_SIZE);
492}
493
494static pgtable_t
495srmmu_pte_alloc_one(struct mm_struct *mm, unsigned long address)
496{ 327{
497 unsigned long pte; 328 unsigned long pte;
498 struct page *page; 329 struct page *page;
499 330
500 if ((pte = (unsigned long)srmmu_pte_alloc_one_kernel(mm, address)) == 0) 331 if ((pte = (unsigned long)pte_alloc_one_kernel(mm, address)) == 0)
501 return NULL; 332 return NULL;
502 page = pfn_to_page( __nocache_pa(pte) >> PAGE_SHIFT ); 333 page = pfn_to_page( __nocache_pa(pte) >> PAGE_SHIFT );
503 pgtable_page_ctor(page); 334 pgtable_page_ctor(page);
504 return page; 335 return page;
505} 336}
506 337
507static void srmmu_free_pte_fast(pte_t *pte) 338void pte_free(struct mm_struct *mm, pgtable_t pte)
508{
509 srmmu_free_nocache((unsigned long)pte, PTE_SIZE);
510}
511
512static void srmmu_pte_free(pgtable_t pte)
513{ 339{
514 unsigned long p; 340 unsigned long p;
515 341
@@ -560,8 +386,8 @@ static inline void free_context(int context)
560} 386}
561 387
562 388
563static void srmmu_switch_mm(struct mm_struct *old_mm, struct mm_struct *mm, 389void switch_mm(struct mm_struct *old_mm, struct mm_struct *mm,
564 struct task_struct *tsk, int cpu) 390 struct task_struct *tsk)
565{ 391{
566 if(mm->context == NO_CONTEXT) { 392 if(mm->context == NO_CONTEXT) {
567 spin_lock(&srmmu_context_spinlock); 393 spin_lock(&srmmu_context_spinlock);
@@ -590,8 +416,8 @@ static inline void srmmu_mapioaddr(unsigned long physaddr,
590 416
591 physaddr &= PAGE_MASK; 417 physaddr &= PAGE_MASK;
592 pgdp = pgd_offset_k(virt_addr); 418 pgdp = pgd_offset_k(virt_addr);
593 pmdp = srmmu_pmd_offset(pgdp, virt_addr); 419 pmdp = pmd_offset(pgdp, virt_addr);
594 ptep = srmmu_pte_offset(pmdp, virt_addr); 420 ptep = pte_offset_kernel(pmdp, virt_addr);
595 tmp = (physaddr >> 4) | SRMMU_ET_PTE; 421 tmp = (physaddr >> 4) | SRMMU_ET_PTE;
596 422
597 /* 423 /*
@@ -602,11 +428,11 @@ static inline void srmmu_mapioaddr(unsigned long physaddr,
602 tmp |= (bus_type << 28); 428 tmp |= (bus_type << 28);
603 tmp |= SRMMU_PRIV; 429 tmp |= SRMMU_PRIV;
604 __flush_page_to_ram(virt_addr); 430 __flush_page_to_ram(virt_addr);
605 srmmu_set_pte(ptep, __pte(tmp)); 431 set_pte(ptep, __pte(tmp));
606} 432}
607 433
608static void srmmu_mapiorange(unsigned int bus, unsigned long xpa, 434void srmmu_mapiorange(unsigned int bus, unsigned long xpa,
609 unsigned long xva, unsigned int len) 435 unsigned long xva, unsigned int len)
610{ 436{
611 while (len != 0) { 437 while (len != 0) {
612 len -= PAGE_SIZE; 438 len -= PAGE_SIZE;
@@ -624,14 +450,14 @@ static inline void srmmu_unmapioaddr(unsigned long virt_addr)
624 pte_t *ptep; 450 pte_t *ptep;
625 451
626 pgdp = pgd_offset_k(virt_addr); 452 pgdp = pgd_offset_k(virt_addr);
627 pmdp = srmmu_pmd_offset(pgdp, virt_addr); 453 pmdp = pmd_offset(pgdp, virt_addr);
628 ptep = srmmu_pte_offset(pmdp, virt_addr); 454 ptep = pte_offset_kernel(pmdp, virt_addr);
629 455
630 /* No need to flush uncacheable page. */ 456 /* No need to flush uncacheable page. */
631 srmmu_pte_clear(ptep); 457 __pte_clear(ptep);
632} 458}
633 459
634static void srmmu_unmapiorange(unsigned long virt_addr, unsigned int len) 460void srmmu_unmapiorange(unsigned long virt_addr, unsigned int len)
635{ 461{
636 while (len != 0) { 462 while (len != 0) {
637 len -= PAGE_SIZE; 463 len -= PAGE_SIZE;
@@ -647,10 +473,9 @@ static void srmmu_unmapiorange(unsigned long virt_addr, unsigned int len)
647 * pool. As a side effect we are putting a little too much pressure 473 * pool. As a side effect we are putting a little too much pressure
648 * on the gfp() subsystem. This setup also makes the logic of the 474 * on the gfp() subsystem. This setup also makes the logic of the
649 * iommu mapping code a lot easier as we can transparently handle 475 * iommu mapping code a lot easier as we can transparently handle
650 * mappings on the kernel stack without any special code as we did 476 * mappings on the kernel stack without any special code.
651 * need on the sun4c.
652 */ 477 */
653static struct thread_info *srmmu_alloc_thread_info_node(int node) 478struct thread_info *alloc_thread_info_node(struct task_struct *tsk, int node)
654{ 479{
655 struct thread_info *ret; 480 struct thread_info *ret;
656 481
@@ -664,7 +489,7 @@ static struct thread_info *srmmu_alloc_thread_info_node(int node)
664 return ret; 489 return ret;
665} 490}
666 491
667static void srmmu_free_thread_info(struct thread_info *ti) 492void free_thread_info(struct thread_info *ti)
668{ 493{
669 free_pages((unsigned long)ti, THREAD_INFO_ORDER); 494 free_pages((unsigned long)ti, THREAD_INFO_ORDER);
670} 495}
@@ -683,38 +508,6 @@ extern void tsunami_flush_tlb_range(struct vm_area_struct *vma, unsigned long st
683extern void tsunami_flush_tlb_page(struct vm_area_struct *vma, unsigned long page); 508extern void tsunami_flush_tlb_page(struct vm_area_struct *vma, unsigned long page);
684extern void tsunami_setup_blockops(void); 509extern void tsunami_setup_blockops(void);
685 510
686/*
687 * Workaround, until we find what's going on with Swift. When low on memory,
688 * it sometimes loops in fault/handle_mm_fault incl. flush_tlb_page to find
689 * out it is already in page tables/ fault again on the same instruction.
690 * I really don't understand it, have checked it and contexts
691 * are right, flush_tlb_all is done as well, and it faults again...
692 * Strange. -jj
693 *
694 * The following code is a deadwood that may be necessary when
695 * we start to make precise page flushes again. --zaitcev
696 */
697static void swift_update_mmu_cache(struct vm_area_struct * vma, unsigned long address, pte_t *ptep)
698{
699#if 0
700 static unsigned long last;
701 unsigned int val;
702 /* unsigned int n; */
703
704 if (address == last) {
705 val = srmmu_hwprobe(address);
706 if (val != 0 && pte_val(*ptep) != val) {
707 printk("swift_update_mmu_cache: "
708 "addr %lx put %08x probed %08x from %p\n",
709 address, pte_val(*ptep), val,
710 __builtin_return_address(0));
711 srmmu_flush_whole_tlb();
712 }
713 }
714 last = address;
715#endif
716}
717
718/* swift.S */ 511/* swift.S */
719extern void swift_flush_cache_all(void); 512extern void swift_flush_cache_all(void);
720extern void swift_flush_cache_mm(struct mm_struct *mm); 513extern void swift_flush_cache_mm(struct mm_struct *mm);
@@ -767,244 +560,6 @@ void swift_flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
767 * with respect to cache coherency. 560 * with respect to cache coherency.
768 */ 561 */
769 562
770/* Cypress flushes. */
771static void cypress_flush_cache_all(void)
772{
773 volatile unsigned long cypress_sucks;
774 unsigned long faddr, tagval;
775
776 flush_user_windows();
777 for(faddr = 0; faddr < 0x10000; faddr += 0x20) {
778 __asm__ __volatile__("lda [%1 + %2] %3, %0\n\t" :
779 "=r" (tagval) :
780 "r" (faddr), "r" (0x40000),
781 "i" (ASI_M_DATAC_TAG));
782
783 /* If modified and valid, kick it. */
784 if((tagval & 0x60) == 0x60)
785 cypress_sucks = *(unsigned long *)(0xf0020000 + faddr);
786 }
787}
788
789static void cypress_flush_cache_mm(struct mm_struct *mm)
790{
791 register unsigned long a, b, c, d, e, f, g;
792 unsigned long flags, faddr;
793 int octx;
794
795 FLUSH_BEGIN(mm)
796 flush_user_windows();
797 local_irq_save(flags);
798 octx = srmmu_get_context();
799 srmmu_set_context(mm->context);
800 a = 0x20; b = 0x40; c = 0x60;
801 d = 0x80; e = 0xa0; f = 0xc0; g = 0xe0;
802
803 faddr = (0x10000 - 0x100);
804 goto inside;
805 do {
806 faddr -= 0x100;
807 inside:
808 __asm__ __volatile__("sta %%g0, [%0] %1\n\t"
809 "sta %%g0, [%0 + %2] %1\n\t"
810 "sta %%g0, [%0 + %3] %1\n\t"
811 "sta %%g0, [%0 + %4] %1\n\t"
812 "sta %%g0, [%0 + %5] %1\n\t"
813 "sta %%g0, [%0 + %6] %1\n\t"
814 "sta %%g0, [%0 + %7] %1\n\t"
815 "sta %%g0, [%0 + %8] %1\n\t" : :
816 "r" (faddr), "i" (ASI_M_FLUSH_CTX),
817 "r" (a), "r" (b), "r" (c), "r" (d),
818 "r" (e), "r" (f), "r" (g));
819 } while(faddr);
820 srmmu_set_context(octx);
821 local_irq_restore(flags);
822 FLUSH_END
823}
824
825static void cypress_flush_cache_range(struct vm_area_struct *vma, unsigned long start, unsigned long end)
826{
827 struct mm_struct *mm = vma->vm_mm;
828 register unsigned long a, b, c, d, e, f, g;
829 unsigned long flags, faddr;
830 int octx;
831
832 FLUSH_BEGIN(mm)
833 flush_user_windows();
834 local_irq_save(flags);
835 octx = srmmu_get_context();
836 srmmu_set_context(mm->context);
837 a = 0x20; b = 0x40; c = 0x60;
838 d = 0x80; e = 0xa0; f = 0xc0; g = 0xe0;
839
840 start &= SRMMU_REAL_PMD_MASK;
841 while(start < end) {
842 faddr = (start + (0x10000 - 0x100));
843 goto inside;
844 do {
845 faddr -= 0x100;
846 inside:
847 __asm__ __volatile__("sta %%g0, [%0] %1\n\t"
848 "sta %%g0, [%0 + %2] %1\n\t"
849 "sta %%g0, [%0 + %3] %1\n\t"
850 "sta %%g0, [%0 + %4] %1\n\t"
851 "sta %%g0, [%0 + %5] %1\n\t"
852 "sta %%g0, [%0 + %6] %1\n\t"
853 "sta %%g0, [%0 + %7] %1\n\t"
854 "sta %%g0, [%0 + %8] %1\n\t" : :
855 "r" (faddr),
856 "i" (ASI_M_FLUSH_SEG),
857 "r" (a), "r" (b), "r" (c), "r" (d),
858 "r" (e), "r" (f), "r" (g));
859 } while (faddr != start);
860 start += SRMMU_REAL_PMD_SIZE;
861 }
862 srmmu_set_context(octx);
863 local_irq_restore(flags);
864 FLUSH_END
865}
866
867static void cypress_flush_cache_page(struct vm_area_struct *vma, unsigned long page)
868{
869 register unsigned long a, b, c, d, e, f, g;
870 struct mm_struct *mm = vma->vm_mm;
871 unsigned long flags, line;
872 int octx;
873
874 FLUSH_BEGIN(mm)
875 flush_user_windows();
876 local_irq_save(flags);
877 octx = srmmu_get_context();
878 srmmu_set_context(mm->context);
879 a = 0x20; b = 0x40; c = 0x60;
880 d = 0x80; e = 0xa0; f = 0xc0; g = 0xe0;
881
882 page &= PAGE_MASK;
883 line = (page + PAGE_SIZE) - 0x100;
884 goto inside;
885 do {
886 line -= 0x100;
887 inside:
888 __asm__ __volatile__("sta %%g0, [%0] %1\n\t"
889 "sta %%g0, [%0 + %2] %1\n\t"
890 "sta %%g0, [%0 + %3] %1\n\t"
891 "sta %%g0, [%0 + %4] %1\n\t"
892 "sta %%g0, [%0 + %5] %1\n\t"
893 "sta %%g0, [%0 + %6] %1\n\t"
894 "sta %%g0, [%0 + %7] %1\n\t"
895 "sta %%g0, [%0 + %8] %1\n\t" : :
896 "r" (line),
897 "i" (ASI_M_FLUSH_PAGE),
898 "r" (a), "r" (b), "r" (c), "r" (d),
899 "r" (e), "r" (f), "r" (g));
900 } while(line != page);
901 srmmu_set_context(octx);
902 local_irq_restore(flags);
903 FLUSH_END
904}
905
906/* Cypress is copy-back, at least that is how we configure it. */
907static void cypress_flush_page_to_ram(unsigned long page)
908{
909 register unsigned long a, b, c, d, e, f, g;
910 unsigned long line;
911
912 a = 0x20; b = 0x40; c = 0x60; d = 0x80; e = 0xa0; f = 0xc0; g = 0xe0;
913 page &= PAGE_MASK;
914 line = (page + PAGE_SIZE) - 0x100;
915 goto inside;
916 do {
917 line -= 0x100;
918 inside:
919 __asm__ __volatile__("sta %%g0, [%0] %1\n\t"
920 "sta %%g0, [%0 + %2] %1\n\t"
921 "sta %%g0, [%0 + %3] %1\n\t"
922 "sta %%g0, [%0 + %4] %1\n\t"
923 "sta %%g0, [%0 + %5] %1\n\t"
924 "sta %%g0, [%0 + %6] %1\n\t"
925 "sta %%g0, [%0 + %7] %1\n\t"
926 "sta %%g0, [%0 + %8] %1\n\t" : :
927 "r" (line),
928 "i" (ASI_M_FLUSH_PAGE),
929 "r" (a), "r" (b), "r" (c), "r" (d),
930 "r" (e), "r" (f), "r" (g));
931 } while(line != page);
932}
933
934/* Cypress is also IO cache coherent. */
935static void cypress_flush_page_for_dma(unsigned long page)
936{
937}
938
939/* Cypress has unified L2 VIPT, from which both instructions and data
940 * are stored. It does not have an onboard icache of any sort, therefore
941 * no flush is necessary.
942 */
943static void cypress_flush_sig_insns(struct mm_struct *mm, unsigned long insn_addr)
944{
945}
946
947static void cypress_flush_tlb_all(void)
948{
949 srmmu_flush_whole_tlb();
950}
951
952static void cypress_flush_tlb_mm(struct mm_struct *mm)
953{
954 FLUSH_BEGIN(mm)
955 __asm__ __volatile__(
956 "lda [%0] %3, %%g5\n\t"
957 "sta %2, [%0] %3\n\t"
958 "sta %%g0, [%1] %4\n\t"
959 "sta %%g5, [%0] %3\n"
960 : /* no outputs */
961 : "r" (SRMMU_CTX_REG), "r" (0x300), "r" (mm->context),
962 "i" (ASI_M_MMUREGS), "i" (ASI_M_FLUSH_PROBE)
963 : "g5");
964 FLUSH_END
965}
966
967static void cypress_flush_tlb_range(struct vm_area_struct *vma, unsigned long start, unsigned long end)
968{
969 struct mm_struct *mm = vma->vm_mm;
970 unsigned long size;
971
972 FLUSH_BEGIN(mm)
973 start &= SRMMU_PGDIR_MASK;
974 size = SRMMU_PGDIR_ALIGN(end) - start;
975 __asm__ __volatile__(
976 "lda [%0] %5, %%g5\n\t"
977 "sta %1, [%0] %5\n"
978 "1:\n\t"
979 "subcc %3, %4, %3\n\t"
980 "bne 1b\n\t"
981 " sta %%g0, [%2 + %3] %6\n\t"
982 "sta %%g5, [%0] %5\n"
983 : /* no outputs */
984 : "r" (SRMMU_CTX_REG), "r" (mm->context), "r" (start | 0x200),
985 "r" (size), "r" (SRMMU_PGDIR_SIZE), "i" (ASI_M_MMUREGS),
986 "i" (ASI_M_FLUSH_PROBE)
987 : "g5", "cc");
988 FLUSH_END
989}
990
991static void cypress_flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
992{
993 struct mm_struct *mm = vma->vm_mm;
994
995 FLUSH_BEGIN(mm)
996 __asm__ __volatile__(
997 "lda [%0] %3, %%g5\n\t"
998 "sta %1, [%0] %3\n\t"
999 "sta %%g0, [%2] %4\n\t"
1000 "sta %%g5, [%0] %3\n"
1001 : /* no outputs */
1002 : "r" (SRMMU_CTX_REG), "r" (mm->context), "r" (page & PAGE_MASK),
1003 "i" (ASI_M_MMUREGS), "i" (ASI_M_FLUSH_PROBE)
1004 : "g5");
1005 FLUSH_END
1006}
1007
1008/* viking.S */ 563/* viking.S */
1009extern void viking_flush_cache_all(void); 564extern void viking_flush_cache_all(void);
1010extern void viking_flush_cache_mm(struct mm_struct *mm); 565extern void viking_flush_cache_mm(struct mm_struct *mm);
@@ -1065,21 +620,21 @@ static void __init srmmu_early_allocate_ptable_skeleton(unsigned long start,
1065 620
1066 while(start < end) { 621 while(start < end) {
1067 pgdp = pgd_offset_k(start); 622 pgdp = pgd_offset_k(start);
1068 if(srmmu_pgd_none(*(pgd_t *)__nocache_fix(pgdp))) { 623 if (pgd_none(*(pgd_t *)__nocache_fix(pgdp))) {
1069 pmdp = (pmd_t *) __srmmu_get_nocache( 624 pmdp = (pmd_t *) __srmmu_get_nocache(
1070 SRMMU_PMD_TABLE_SIZE, SRMMU_PMD_TABLE_SIZE); 625 SRMMU_PMD_TABLE_SIZE, SRMMU_PMD_TABLE_SIZE);
1071 if (pmdp == NULL) 626 if (pmdp == NULL)
1072 early_pgtable_allocfail("pmd"); 627 early_pgtable_allocfail("pmd");
1073 memset(__nocache_fix(pmdp), 0, SRMMU_PMD_TABLE_SIZE); 628 memset(__nocache_fix(pmdp), 0, SRMMU_PMD_TABLE_SIZE);
1074 srmmu_pgd_set(__nocache_fix(pgdp), pmdp); 629 pgd_set(__nocache_fix(pgdp), pmdp);
1075 } 630 }
1076 pmdp = srmmu_pmd_offset(__nocache_fix(pgdp), start); 631 pmdp = pmd_offset(__nocache_fix(pgdp), start);
1077 if(srmmu_pmd_none(*(pmd_t *)__nocache_fix(pmdp))) { 632 if(srmmu_pmd_none(*(pmd_t *)__nocache_fix(pmdp))) {
1078 ptep = (pte_t *)__srmmu_get_nocache(PTE_SIZE, PTE_SIZE); 633 ptep = (pte_t *)__srmmu_get_nocache(PTE_SIZE, PTE_SIZE);
1079 if (ptep == NULL) 634 if (ptep == NULL)
1080 early_pgtable_allocfail("pte"); 635 early_pgtable_allocfail("pte");
1081 memset(__nocache_fix(ptep), 0, PTE_SIZE); 636 memset(__nocache_fix(ptep), 0, PTE_SIZE);
1082 srmmu_pmd_set(__nocache_fix(pmdp), ptep); 637 pmd_set(__nocache_fix(pmdp), ptep);
1083 } 638 }
1084 if (start > (0xffffffffUL - PMD_SIZE)) 639 if (start > (0xffffffffUL - PMD_SIZE))
1085 break; 640 break;
@@ -1096,21 +651,21 @@ static void __init srmmu_allocate_ptable_skeleton(unsigned long start,
1096 651
1097 while(start < end) { 652 while(start < end) {
1098 pgdp = pgd_offset_k(start); 653 pgdp = pgd_offset_k(start);
1099 if(srmmu_pgd_none(*pgdp)) { 654 if (pgd_none(*pgdp)) {
1100 pmdp = (pmd_t *)__srmmu_get_nocache(SRMMU_PMD_TABLE_SIZE, SRMMU_PMD_TABLE_SIZE); 655 pmdp = (pmd_t *)__srmmu_get_nocache(SRMMU_PMD_TABLE_SIZE, SRMMU_PMD_TABLE_SIZE);
1101 if (pmdp == NULL) 656 if (pmdp == NULL)
1102 early_pgtable_allocfail("pmd"); 657 early_pgtable_allocfail("pmd");
1103 memset(pmdp, 0, SRMMU_PMD_TABLE_SIZE); 658 memset(pmdp, 0, SRMMU_PMD_TABLE_SIZE);
1104 srmmu_pgd_set(pgdp, pmdp); 659 pgd_set(pgdp, pmdp);
1105 } 660 }
1106 pmdp = srmmu_pmd_offset(pgdp, start); 661 pmdp = pmd_offset(pgdp, start);
1107 if(srmmu_pmd_none(*pmdp)) { 662 if(srmmu_pmd_none(*pmdp)) {
1108 ptep = (pte_t *) __srmmu_get_nocache(PTE_SIZE, 663 ptep = (pte_t *) __srmmu_get_nocache(PTE_SIZE,
1109 PTE_SIZE); 664 PTE_SIZE);
1110 if (ptep == NULL) 665 if (ptep == NULL)
1111 early_pgtable_allocfail("pte"); 666 early_pgtable_allocfail("pte");
1112 memset(ptep, 0, PTE_SIZE); 667 memset(ptep, 0, PTE_SIZE);
1113 srmmu_pmd_set(pmdp, ptep); 668 pmd_set(pmdp, ptep);
1114 } 669 }
1115 if (start > (0xffffffffUL - PMD_SIZE)) 670 if (start > (0xffffffffUL - PMD_SIZE))
1116 break; 671 break;
@@ -1162,21 +717,21 @@ static void __init srmmu_inherit_prom_mappings(unsigned long start,
1162 start += SRMMU_PGDIR_SIZE; 717 start += SRMMU_PGDIR_SIZE;
1163 continue; 718 continue;
1164 } 719 }
1165 if(srmmu_pgd_none(*(pgd_t *)__nocache_fix(pgdp))) { 720 if (pgd_none(*(pgd_t *)__nocache_fix(pgdp))) {
1166 pmdp = (pmd_t *)__srmmu_get_nocache(SRMMU_PMD_TABLE_SIZE, SRMMU_PMD_TABLE_SIZE); 721 pmdp = (pmd_t *)__srmmu_get_nocache(SRMMU_PMD_TABLE_SIZE, SRMMU_PMD_TABLE_SIZE);
1167 if (pmdp == NULL) 722 if (pmdp == NULL)
1168 early_pgtable_allocfail("pmd"); 723 early_pgtable_allocfail("pmd");
1169 memset(__nocache_fix(pmdp), 0, SRMMU_PMD_TABLE_SIZE); 724 memset(__nocache_fix(pmdp), 0, SRMMU_PMD_TABLE_SIZE);
1170 srmmu_pgd_set(__nocache_fix(pgdp), pmdp); 725 pgd_set(__nocache_fix(pgdp), pmdp);
1171 } 726 }
1172 pmdp = srmmu_pmd_offset(__nocache_fix(pgdp), start); 727 pmdp = pmd_offset(__nocache_fix(pgdp), start);
1173 if(srmmu_pmd_none(*(pmd_t *)__nocache_fix(pmdp))) { 728 if(srmmu_pmd_none(*(pmd_t *)__nocache_fix(pmdp))) {
1174 ptep = (pte_t *) __srmmu_get_nocache(PTE_SIZE, 729 ptep = (pte_t *) __srmmu_get_nocache(PTE_SIZE,
1175 PTE_SIZE); 730 PTE_SIZE);
1176 if (ptep == NULL) 731 if (ptep == NULL)
1177 early_pgtable_allocfail("pte"); 732 early_pgtable_allocfail("pte");
1178 memset(__nocache_fix(ptep), 0, PTE_SIZE); 733 memset(__nocache_fix(ptep), 0, PTE_SIZE);
1179 srmmu_pmd_set(__nocache_fix(pmdp), ptep); 734 pmd_set(__nocache_fix(pmdp), ptep);
1180 } 735 }
1181 if(what == 1) { 736 if(what == 1) {
1182 /* 737 /*
@@ -1190,7 +745,7 @@ static void __init srmmu_inherit_prom_mappings(unsigned long start,
1190 start += SRMMU_REAL_PMD_SIZE; 745 start += SRMMU_REAL_PMD_SIZE;
1191 continue; 746 continue;
1192 } 747 }
1193 ptep = srmmu_pte_offset(__nocache_fix(pmdp), start); 748 ptep = pte_offset_kernel(__nocache_fix(pmdp), start);
1194 *(pte_t *)__nocache_fix(ptep) = __pte(prompte); 749 *(pte_t *)__nocache_fix(ptep) = __pte(prompte);
1195 start += PAGE_SIZE; 750 start += PAGE_SIZE;
1196 } 751 }
@@ -1231,13 +786,6 @@ static unsigned long __init map_spbank(unsigned long vbase, int sp_entry)
1231 return vstart; 786 return vstart;
1232} 787}
1233 788
1234static inline void memprobe_error(char *msg)
1235{
1236 prom_printf(msg);
1237 prom_printf("Halting now...\n");
1238 prom_halt();
1239}
1240
1241static inline void map_kernel(void) 789static inline void map_kernel(void)
1242{ 790{
1243 int i; 791 int i;
@@ -1249,8 +797,6 @@ static inline void map_kernel(void)
1249 for (i = 0; sp_banks[i].num_bytes != 0; i++) { 797 for (i = 0; sp_banks[i].num_bytes != 0; i++) {
1250 map_spbank((unsigned long)__va(sp_banks[i].base_addr), i); 798 map_spbank((unsigned long)__va(sp_banks[i].base_addr), i);
1251 } 799 }
1252
1253 BTFIXUPSET_SIMM13(user_ptrs_per_pgd, PAGE_OFFSET / SRMMU_PGDIR_SIZE);
1254} 800}
1255 801
1256/* Paging initialization on the Sparc Reference MMU. */ 802/* Paging initialization on the Sparc Reference MMU. */
@@ -1312,7 +858,7 @@ void __init srmmu_paging_init(void)
1312 srmmu_set_ctable_ptr((unsigned long)srmmu_ctx_table_phys); 858 srmmu_set_ctable_ptr((unsigned long)srmmu_ctx_table_phys);
1313#ifdef CONFIG_SMP 859#ifdef CONFIG_SMP
1314 /* Stop from hanging here... */ 860 /* Stop from hanging here... */
1315 local_flush_tlb_all(); 861 local_ops->tlb_all();
1316#else 862#else
1317 flush_tlb_all(); 863 flush_tlb_all();
1318#endif 864#endif
@@ -1326,8 +872,8 @@ void __init srmmu_paging_init(void)
1326 srmmu_allocate_ptable_skeleton(PKMAP_BASE, PKMAP_END); 872 srmmu_allocate_ptable_skeleton(PKMAP_BASE, PKMAP_END);
1327 873
1328 pgd = pgd_offset_k(PKMAP_BASE); 874 pgd = pgd_offset_k(PKMAP_BASE);
1329 pmd = srmmu_pmd_offset(pgd, PKMAP_BASE); 875 pmd = pmd_offset(pgd, PKMAP_BASE);
1330 pte = srmmu_pte_offset(pmd, PKMAP_BASE); 876 pte = pte_offset_kernel(pmd, PKMAP_BASE);
1331 pkmap_page_table = pte; 877 pkmap_page_table = pte;
1332 878
1333 flush_cache_all(); 879 flush_cache_all();
@@ -1359,7 +905,7 @@ void __init srmmu_paging_init(void)
1359 } 905 }
1360} 906}
1361 907
1362static void srmmu_mmu_info(struct seq_file *m) 908void mmu_info(struct seq_file *m)
1363{ 909{
1364 seq_printf(m, 910 seq_printf(m,
1365 "MMU type\t: %s\n" 911 "MMU type\t: %s\n"
@@ -1372,11 +918,7 @@ static void srmmu_mmu_info(struct seq_file *m)
1372 srmmu_nocache_map.used << SRMMU_NOCACHE_BITMAP_SHIFT); 918 srmmu_nocache_map.used << SRMMU_NOCACHE_BITMAP_SHIFT);
1373} 919}
1374 920
1375static void srmmu_update_mmu_cache(struct vm_area_struct * vma, unsigned long address, pte_t pte) 921void destroy_context(struct mm_struct *mm)
1376{
1377}
1378
1379static void srmmu_destroy_context(struct mm_struct *mm)
1380{ 922{
1381 923
1382 if(mm->context != NO_CONTEXT) { 924 if(mm->context != NO_CONTEXT) {
@@ -1474,6 +1016,20 @@ static void __cpuinit poke_hypersparc(void)
1474 clear = srmmu_get_fstatus(); 1016 clear = srmmu_get_fstatus();
1475} 1017}
1476 1018
1019static const struct sparc32_cachetlb_ops hypersparc_ops = {
1020 .cache_all = hypersparc_flush_cache_all,
1021 .cache_mm = hypersparc_flush_cache_mm,
1022 .cache_page = hypersparc_flush_cache_page,
1023 .cache_range = hypersparc_flush_cache_range,
1024 .tlb_all = hypersparc_flush_tlb_all,
1025 .tlb_mm = hypersparc_flush_tlb_mm,
1026 .tlb_page = hypersparc_flush_tlb_page,
1027 .tlb_range = hypersparc_flush_tlb_range,
1028 .page_to_ram = hypersparc_flush_page_to_ram,
1029 .sig_insns = hypersparc_flush_sig_insns,
1030 .page_for_dma = hypersparc_flush_page_for_dma,
1031};
1032
1477static void __init init_hypersparc(void) 1033static void __init init_hypersparc(void)
1478{ 1034{
1479 srmmu_name = "ROSS HyperSparc"; 1035 srmmu_name = "ROSS HyperSparc";
@@ -1482,118 +1038,13 @@ static void __init init_hypersparc(void)
1482 init_vac_layout(); 1038 init_vac_layout();
1483 1039
1484 is_hypersparc = 1; 1040 is_hypersparc = 1;
1485 1041 sparc32_cachetlb_ops = &hypersparc_ops;
1486 BTFIXUPSET_CALL(pte_clear, srmmu_pte_clear, BTFIXUPCALL_NORM);
1487 BTFIXUPSET_CALL(pmd_clear, srmmu_pmd_clear, BTFIXUPCALL_NORM);
1488 BTFIXUPSET_CALL(pgd_clear, srmmu_pgd_clear, BTFIXUPCALL_NORM);
1489 BTFIXUPSET_CALL(flush_cache_all, hypersparc_flush_cache_all, BTFIXUPCALL_NORM);
1490 BTFIXUPSET_CALL(flush_cache_mm, hypersparc_flush_cache_mm, BTFIXUPCALL_NORM);
1491 BTFIXUPSET_CALL(flush_cache_range, hypersparc_flush_cache_range, BTFIXUPCALL_NORM);
1492 BTFIXUPSET_CALL(flush_cache_page, hypersparc_flush_cache_page, BTFIXUPCALL_NORM);
1493
1494 BTFIXUPSET_CALL(flush_tlb_all, hypersparc_flush_tlb_all, BTFIXUPCALL_NORM);
1495 BTFIXUPSET_CALL(flush_tlb_mm, hypersparc_flush_tlb_mm, BTFIXUPCALL_NORM);
1496 BTFIXUPSET_CALL(flush_tlb_range, hypersparc_flush_tlb_range, BTFIXUPCALL_NORM);
1497 BTFIXUPSET_CALL(flush_tlb_page, hypersparc_flush_tlb_page, BTFIXUPCALL_NORM);
1498
1499 BTFIXUPSET_CALL(__flush_page_to_ram, hypersparc_flush_page_to_ram, BTFIXUPCALL_NORM);
1500 BTFIXUPSET_CALL(flush_sig_insns, hypersparc_flush_sig_insns, BTFIXUPCALL_NORM);
1501 BTFIXUPSET_CALL(flush_page_for_dma, hypersparc_flush_page_for_dma, BTFIXUPCALL_NOP);
1502
1503 1042
1504 poke_srmmu = poke_hypersparc; 1043 poke_srmmu = poke_hypersparc;
1505 1044
1506 hypersparc_setup_blockops(); 1045 hypersparc_setup_blockops();
1507} 1046}
1508 1047
1509static void __cpuinit poke_cypress(void)
1510{
1511 unsigned long mreg = srmmu_get_mmureg();
1512 unsigned long faddr, tagval;
1513 volatile unsigned long cypress_sucks;
1514 volatile unsigned long clear;
1515
1516 clear = srmmu_get_faddr();
1517 clear = srmmu_get_fstatus();
1518
1519 if (!(mreg & CYPRESS_CENABLE)) {
1520 for(faddr = 0x0; faddr < 0x10000; faddr += 20) {
1521 __asm__ __volatile__("sta %%g0, [%0 + %1] %2\n\t"
1522 "sta %%g0, [%0] %2\n\t" : :
1523 "r" (faddr), "r" (0x40000),
1524 "i" (ASI_M_DATAC_TAG));
1525 }
1526 } else {
1527 for(faddr = 0; faddr < 0x10000; faddr += 0x20) {
1528 __asm__ __volatile__("lda [%1 + %2] %3, %0\n\t" :
1529 "=r" (tagval) :
1530 "r" (faddr), "r" (0x40000),
1531 "i" (ASI_M_DATAC_TAG));
1532
1533 /* If modified and valid, kick it. */
1534 if((tagval & 0x60) == 0x60)
1535 cypress_sucks = *(unsigned long *)
1536 (0xf0020000 + faddr);
1537 }
1538 }
1539
1540 /* And one more, for our good neighbor, Mr. Broken Cypress. */
1541 clear = srmmu_get_faddr();
1542 clear = srmmu_get_fstatus();
1543
1544 mreg |= (CYPRESS_CENABLE | CYPRESS_CMODE);
1545 srmmu_set_mmureg(mreg);
1546}
1547
1548static void __init init_cypress_common(void)
1549{
1550 init_vac_layout();
1551
1552 BTFIXUPSET_CALL(pte_clear, srmmu_pte_clear, BTFIXUPCALL_NORM);
1553 BTFIXUPSET_CALL(pmd_clear, srmmu_pmd_clear, BTFIXUPCALL_NORM);
1554 BTFIXUPSET_CALL(pgd_clear, srmmu_pgd_clear, BTFIXUPCALL_NORM);
1555 BTFIXUPSET_CALL(flush_cache_all, cypress_flush_cache_all, BTFIXUPCALL_NORM);
1556 BTFIXUPSET_CALL(flush_cache_mm, cypress_flush_cache_mm, BTFIXUPCALL_NORM);
1557 BTFIXUPSET_CALL(flush_cache_range, cypress_flush_cache_range, BTFIXUPCALL_NORM);
1558 BTFIXUPSET_CALL(flush_cache_page, cypress_flush_cache_page, BTFIXUPCALL_NORM);
1559
1560 BTFIXUPSET_CALL(flush_tlb_all, cypress_flush_tlb_all, BTFIXUPCALL_NORM);
1561 BTFIXUPSET_CALL(flush_tlb_mm, cypress_flush_tlb_mm, BTFIXUPCALL_NORM);
1562 BTFIXUPSET_CALL(flush_tlb_page, cypress_flush_tlb_page, BTFIXUPCALL_NORM);
1563 BTFIXUPSET_CALL(flush_tlb_range, cypress_flush_tlb_range, BTFIXUPCALL_NORM);
1564
1565
1566 BTFIXUPSET_CALL(__flush_page_to_ram, cypress_flush_page_to_ram, BTFIXUPCALL_NORM);
1567 BTFIXUPSET_CALL(flush_sig_insns, cypress_flush_sig_insns, BTFIXUPCALL_NOP);
1568 BTFIXUPSET_CALL(flush_page_for_dma, cypress_flush_page_for_dma, BTFIXUPCALL_NOP);
1569
1570 poke_srmmu = poke_cypress;
1571}
1572
1573static void __init init_cypress_604(void)
1574{
1575 srmmu_name = "ROSS Cypress-604(UP)";
1576 srmmu_modtype = Cypress;
1577 init_cypress_common();
1578}
1579
1580static void __init init_cypress_605(unsigned long mrev)
1581{
1582 srmmu_name = "ROSS Cypress-605(MP)";
1583 if(mrev == 0xe) {
1584 srmmu_modtype = Cypress_vE;
1585 hwbug_bitmask |= HWBUG_COPYBACK_BROKEN;
1586 } else {
1587 if(mrev == 0xd) {
1588 srmmu_modtype = Cypress_vD;
1589 hwbug_bitmask |= HWBUG_ASIFLUSH_BROKEN;
1590 } else {
1591 srmmu_modtype = Cypress;
1592 }
1593 }
1594 init_cypress_common();
1595}
1596
1597static void __cpuinit poke_swift(void) 1048static void __cpuinit poke_swift(void)
1598{ 1049{
1599 unsigned long mreg; 1050 unsigned long mreg;
@@ -1617,6 +1068,20 @@ static void __cpuinit poke_swift(void)
1617 srmmu_set_mmureg(mreg); 1068 srmmu_set_mmureg(mreg);
1618} 1069}
1619 1070
1071static const struct sparc32_cachetlb_ops swift_ops = {
1072 .cache_all = swift_flush_cache_all,
1073 .cache_mm = swift_flush_cache_mm,
1074 .cache_page = swift_flush_cache_page,
1075 .cache_range = swift_flush_cache_range,
1076 .tlb_all = swift_flush_tlb_all,
1077 .tlb_mm = swift_flush_tlb_mm,
1078 .tlb_page = swift_flush_tlb_page,
1079 .tlb_range = swift_flush_tlb_range,
1080 .page_to_ram = swift_flush_page_to_ram,
1081 .sig_insns = swift_flush_sig_insns,
1082 .page_for_dma = swift_flush_page_for_dma,
1083};
1084
1620#define SWIFT_MASKID_ADDR 0x10003018 1085#define SWIFT_MASKID_ADDR 0x10003018
1621static void __init init_swift(void) 1086static void __init init_swift(void)
1622{ 1087{
@@ -1667,23 +1132,7 @@ static void __init init_swift(void)
1667 break; 1132 break;
1668 } 1133 }
1669 1134
1670 BTFIXUPSET_CALL(flush_cache_all, swift_flush_cache_all, BTFIXUPCALL_NORM); 1135 sparc32_cachetlb_ops = &swift_ops;
1671 BTFIXUPSET_CALL(flush_cache_mm, swift_flush_cache_mm, BTFIXUPCALL_NORM);
1672 BTFIXUPSET_CALL(flush_cache_page, swift_flush_cache_page, BTFIXUPCALL_NORM);
1673 BTFIXUPSET_CALL(flush_cache_range, swift_flush_cache_range, BTFIXUPCALL_NORM);
1674
1675
1676 BTFIXUPSET_CALL(flush_tlb_all, swift_flush_tlb_all, BTFIXUPCALL_NORM);
1677 BTFIXUPSET_CALL(flush_tlb_mm, swift_flush_tlb_mm, BTFIXUPCALL_NORM);
1678 BTFIXUPSET_CALL(flush_tlb_page, swift_flush_tlb_page, BTFIXUPCALL_NORM);
1679 BTFIXUPSET_CALL(flush_tlb_range, swift_flush_tlb_range, BTFIXUPCALL_NORM);
1680
1681 BTFIXUPSET_CALL(__flush_page_to_ram, swift_flush_page_to_ram, BTFIXUPCALL_NORM);
1682 BTFIXUPSET_CALL(flush_sig_insns, swift_flush_sig_insns, BTFIXUPCALL_NORM);
1683 BTFIXUPSET_CALL(flush_page_for_dma, swift_flush_page_for_dma, BTFIXUPCALL_NORM);
1684
1685 BTFIXUPSET_CALL(update_mmu_cache, swift_update_mmu_cache, BTFIXUPCALL_NORM);
1686
1687 flush_page_for_dma_global = 0; 1136 flush_page_for_dma_global = 0;
1688 1137
1689 /* 1138 /*
@@ -1816,26 +1265,25 @@ static void __cpuinit poke_turbosparc(void)
1816 srmmu_set_mmureg(mreg); 1265 srmmu_set_mmureg(mreg);
1817} 1266}
1818 1267
1268static const struct sparc32_cachetlb_ops turbosparc_ops = {
1269 .cache_all = turbosparc_flush_cache_all,
1270 .cache_mm = turbosparc_flush_cache_mm,
1271 .cache_page = turbosparc_flush_cache_page,
1272 .cache_range = turbosparc_flush_cache_range,
1273 .tlb_all = turbosparc_flush_tlb_all,
1274 .tlb_mm = turbosparc_flush_tlb_mm,
1275 .tlb_page = turbosparc_flush_tlb_page,
1276 .tlb_range = turbosparc_flush_tlb_range,
1277 .page_to_ram = turbosparc_flush_page_to_ram,
1278 .sig_insns = turbosparc_flush_sig_insns,
1279 .page_for_dma = turbosparc_flush_page_for_dma,
1280};
1281
1819static void __init init_turbosparc(void) 1282static void __init init_turbosparc(void)
1820{ 1283{
1821 srmmu_name = "Fujitsu TurboSparc"; 1284 srmmu_name = "Fujitsu TurboSparc";
1822 srmmu_modtype = TurboSparc; 1285 srmmu_modtype = TurboSparc;
1823 1286 sparc32_cachetlb_ops = &turbosparc_ops;
1824 BTFIXUPSET_CALL(flush_cache_all, turbosparc_flush_cache_all, BTFIXUPCALL_NORM);
1825 BTFIXUPSET_CALL(flush_cache_mm, turbosparc_flush_cache_mm, BTFIXUPCALL_NORM);
1826 BTFIXUPSET_CALL(flush_cache_page, turbosparc_flush_cache_page, BTFIXUPCALL_NORM);
1827 BTFIXUPSET_CALL(flush_cache_range, turbosparc_flush_cache_range, BTFIXUPCALL_NORM);
1828
1829 BTFIXUPSET_CALL(flush_tlb_all, turbosparc_flush_tlb_all, BTFIXUPCALL_NORM);
1830 BTFIXUPSET_CALL(flush_tlb_mm, turbosparc_flush_tlb_mm, BTFIXUPCALL_NORM);
1831 BTFIXUPSET_CALL(flush_tlb_page, turbosparc_flush_tlb_page, BTFIXUPCALL_NORM);
1832 BTFIXUPSET_CALL(flush_tlb_range, turbosparc_flush_tlb_range, BTFIXUPCALL_NORM);
1833
1834 BTFIXUPSET_CALL(__flush_page_to_ram, turbosparc_flush_page_to_ram, BTFIXUPCALL_NORM);
1835
1836 BTFIXUPSET_CALL(flush_sig_insns, turbosparc_flush_sig_insns, BTFIXUPCALL_NOP);
1837 BTFIXUPSET_CALL(flush_page_for_dma, turbosparc_flush_page_for_dma, BTFIXUPCALL_NORM);
1838
1839 poke_srmmu = poke_turbosparc; 1287 poke_srmmu = poke_turbosparc;
1840} 1288}
1841 1289
@@ -1850,6 +1298,20 @@ static void __cpuinit poke_tsunami(void)
1850 srmmu_set_mmureg(mreg); 1298 srmmu_set_mmureg(mreg);
1851} 1299}
1852 1300
1301static const struct sparc32_cachetlb_ops tsunami_ops = {
1302 .cache_all = tsunami_flush_cache_all,
1303 .cache_mm = tsunami_flush_cache_mm,
1304 .cache_page = tsunami_flush_cache_page,
1305 .cache_range = tsunami_flush_cache_range,
1306 .tlb_all = tsunami_flush_tlb_all,
1307 .tlb_mm = tsunami_flush_tlb_mm,
1308 .tlb_page = tsunami_flush_tlb_page,
1309 .tlb_range = tsunami_flush_tlb_range,
1310 .page_to_ram = tsunami_flush_page_to_ram,
1311 .sig_insns = tsunami_flush_sig_insns,
1312 .page_for_dma = tsunami_flush_page_for_dma,
1313};
1314
1853static void __init init_tsunami(void) 1315static void __init init_tsunami(void)
1854{ 1316{
1855 /* 1317 /*
@@ -1860,22 +1322,7 @@ static void __init init_tsunami(void)
1860 1322
1861 srmmu_name = "TI Tsunami"; 1323 srmmu_name = "TI Tsunami";
1862 srmmu_modtype = Tsunami; 1324 srmmu_modtype = Tsunami;
1863 1325 sparc32_cachetlb_ops = &tsunami_ops;
1864 BTFIXUPSET_CALL(flush_cache_all, tsunami_flush_cache_all, BTFIXUPCALL_NORM);
1865 BTFIXUPSET_CALL(flush_cache_mm, tsunami_flush_cache_mm, BTFIXUPCALL_NORM);
1866 BTFIXUPSET_CALL(flush_cache_page, tsunami_flush_cache_page, BTFIXUPCALL_NORM);
1867 BTFIXUPSET_CALL(flush_cache_range, tsunami_flush_cache_range, BTFIXUPCALL_NORM);
1868
1869
1870 BTFIXUPSET_CALL(flush_tlb_all, tsunami_flush_tlb_all, BTFIXUPCALL_NORM);
1871 BTFIXUPSET_CALL(flush_tlb_mm, tsunami_flush_tlb_mm, BTFIXUPCALL_NORM);
1872 BTFIXUPSET_CALL(flush_tlb_page, tsunami_flush_tlb_page, BTFIXUPCALL_NORM);
1873 BTFIXUPSET_CALL(flush_tlb_range, tsunami_flush_tlb_range, BTFIXUPCALL_NORM);
1874
1875 BTFIXUPSET_CALL(__flush_page_to_ram, tsunami_flush_page_to_ram, BTFIXUPCALL_NOP);
1876 BTFIXUPSET_CALL(flush_sig_insns, tsunami_flush_sig_insns, BTFIXUPCALL_NORM);
1877 BTFIXUPSET_CALL(flush_page_for_dma, tsunami_flush_page_for_dma, BTFIXUPCALL_NORM);
1878
1879 poke_srmmu = poke_tsunami; 1326 poke_srmmu = poke_tsunami;
1880 1327
1881 tsunami_setup_blockops(); 1328 tsunami_setup_blockops();
@@ -1886,7 +1333,7 @@ static void __cpuinit poke_viking(void)
1886 unsigned long mreg = srmmu_get_mmureg(); 1333 unsigned long mreg = srmmu_get_mmureg();
1887 static int smp_catch; 1334 static int smp_catch;
1888 1335
1889 if(viking_mxcc_present) { 1336 if (viking_mxcc_present) {
1890 unsigned long mxcc_control = mxcc_get_creg(); 1337 unsigned long mxcc_control = mxcc_get_creg();
1891 1338
1892 mxcc_control |= (MXCC_CTL_ECE | MXCC_CTL_PRE | MXCC_CTL_MCE); 1339 mxcc_control |= (MXCC_CTL_ECE | MXCC_CTL_PRE | MXCC_CTL_MCE);
@@ -1923,6 +1370,52 @@ static void __cpuinit poke_viking(void)
1923 srmmu_set_mmureg(mreg); 1370 srmmu_set_mmureg(mreg);
1924} 1371}
1925 1372
1373static struct sparc32_cachetlb_ops viking_ops = {
1374 .cache_all = viking_flush_cache_all,
1375 .cache_mm = viking_flush_cache_mm,
1376 .cache_page = viking_flush_cache_page,
1377 .cache_range = viking_flush_cache_range,
1378 .tlb_all = viking_flush_tlb_all,
1379 .tlb_mm = viking_flush_tlb_mm,
1380 .tlb_page = viking_flush_tlb_page,
1381 .tlb_range = viking_flush_tlb_range,
1382 .page_to_ram = viking_flush_page_to_ram,
1383 .sig_insns = viking_flush_sig_insns,
1384 .page_for_dma = viking_flush_page_for_dma,
1385};
1386
1387#ifdef CONFIG_SMP
1388/* On sun4d the cpu broadcasts local TLB flushes, so we can just
1389 * perform the local TLB flush and all the other cpus will see it.
1390 * But, unfortunately, there is a bug in the sun4d XBUS backplane
1391 * that requires that we add some synchronization to these flushes.
1392 *
1393 * The bug is that the fifo which keeps track of all the pending TLB
1394 * broadcasts in the system is an entry or two too small, so if we
1395 * have too many going at once we'll overflow that fifo and lose a TLB
1396 * flush resulting in corruption.
1397 *
1398 * Our workaround is to take a global spinlock around the TLB flushes,
1399 * which guarentees we won't ever have too many pending. It's a big
1400 * hammer, but a semaphore like system to make sure we only have N TLB
1401 * flushes going at once will require SMP locking anyways so there's
1402 * no real value in trying any harder than this.
1403 */
1404static struct sparc32_cachetlb_ops viking_sun4d_smp_ops = {
1405 .cache_all = viking_flush_cache_all,
1406 .cache_mm = viking_flush_cache_mm,
1407 .cache_page = viking_flush_cache_page,
1408 .cache_range = viking_flush_cache_range,
1409 .tlb_all = sun4dsmp_flush_tlb_all,
1410 .tlb_mm = sun4dsmp_flush_tlb_mm,
1411 .tlb_page = sun4dsmp_flush_tlb_page,
1412 .tlb_range = sun4dsmp_flush_tlb_range,
1413 .page_to_ram = viking_flush_page_to_ram,
1414 .sig_insns = viking_flush_sig_insns,
1415 .page_for_dma = viking_flush_page_for_dma,
1416};
1417#endif
1418
1926static void __init init_viking(void) 1419static void __init init_viking(void)
1927{ 1420{
1928 unsigned long mreg = srmmu_get_mmureg(); 1421 unsigned long mreg = srmmu_get_mmureg();
@@ -1933,10 +1426,6 @@ static void __init init_viking(void)
1933 viking_mxcc_present = 0; 1426 viking_mxcc_present = 0;
1934 msi_set_sync(); 1427 msi_set_sync();
1935 1428
1936 BTFIXUPSET_CALL(pte_clear, srmmu_pte_clear, BTFIXUPCALL_NORM);
1937 BTFIXUPSET_CALL(pmd_clear, srmmu_pmd_clear, BTFIXUPCALL_NORM);
1938 BTFIXUPSET_CALL(pgd_clear, srmmu_pgd_clear, BTFIXUPCALL_NORM);
1939
1940 /* 1429 /*
1941 * We need this to make sure old viking takes no hits 1430 * We need this to make sure old viking takes no hits
1942 * on it's cache for dma snoops to workaround the 1431 * on it's cache for dma snoops to workaround the
@@ -1944,84 +1433,28 @@ static void __init init_viking(void)
1944 * This is only necessary because of the new way in 1433 * This is only necessary because of the new way in
1945 * which we use the IOMMU. 1434 * which we use the IOMMU.
1946 */ 1435 */
1947 BTFIXUPSET_CALL(flush_page_for_dma, viking_flush_page, BTFIXUPCALL_NORM); 1436 viking_ops.page_for_dma = viking_flush_page;
1948 1437#ifdef CONFIG_SMP
1438 viking_sun4d_smp_ops.page_for_dma = viking_flush_page;
1439#endif
1949 flush_page_for_dma_global = 0; 1440 flush_page_for_dma_global = 0;
1950 } else { 1441 } else {
1951 srmmu_name = "TI Viking/MXCC"; 1442 srmmu_name = "TI Viking/MXCC";
1952 viking_mxcc_present = 1; 1443 viking_mxcc_present = 1;
1953
1954 srmmu_cache_pagetables = 1; 1444 srmmu_cache_pagetables = 1;
1955
1956 /* MXCC vikings lack the DMA snooping bug. */
1957 BTFIXUPSET_CALL(flush_page_for_dma, viking_flush_page_for_dma, BTFIXUPCALL_NOP);
1958 } 1445 }
1959 1446
1960 BTFIXUPSET_CALL(flush_cache_all, viking_flush_cache_all, BTFIXUPCALL_NORM); 1447 sparc32_cachetlb_ops = (const struct sparc32_cachetlb_ops *)
1961 BTFIXUPSET_CALL(flush_cache_mm, viking_flush_cache_mm, BTFIXUPCALL_NORM); 1448 &viking_ops;
1962 BTFIXUPSET_CALL(flush_cache_page, viking_flush_cache_page, BTFIXUPCALL_NORM);
1963 BTFIXUPSET_CALL(flush_cache_range, viking_flush_cache_range, BTFIXUPCALL_NORM);
1964
1965#ifdef CONFIG_SMP 1449#ifdef CONFIG_SMP
1966 if (sparc_cpu_model == sun4d) { 1450 if (sparc_cpu_model == sun4d)
1967 BTFIXUPSET_CALL(flush_tlb_all, sun4dsmp_flush_tlb_all, BTFIXUPCALL_NORM); 1451 sparc32_cachetlb_ops = (const struct sparc32_cachetlb_ops *)
1968 BTFIXUPSET_CALL(flush_tlb_mm, sun4dsmp_flush_tlb_mm, BTFIXUPCALL_NORM); 1452 &viking_sun4d_smp_ops;
1969 BTFIXUPSET_CALL(flush_tlb_page, sun4dsmp_flush_tlb_page, BTFIXUPCALL_NORM);
1970 BTFIXUPSET_CALL(flush_tlb_range, sun4dsmp_flush_tlb_range, BTFIXUPCALL_NORM);
1971 } else
1972#endif 1453#endif
1973 {
1974 BTFIXUPSET_CALL(flush_tlb_all, viking_flush_tlb_all, BTFIXUPCALL_NORM);
1975 BTFIXUPSET_CALL(flush_tlb_mm, viking_flush_tlb_mm, BTFIXUPCALL_NORM);
1976 BTFIXUPSET_CALL(flush_tlb_page, viking_flush_tlb_page, BTFIXUPCALL_NORM);
1977 BTFIXUPSET_CALL(flush_tlb_range, viking_flush_tlb_range, BTFIXUPCALL_NORM);
1978 }
1979
1980 BTFIXUPSET_CALL(__flush_page_to_ram, viking_flush_page_to_ram, BTFIXUPCALL_NOP);
1981 BTFIXUPSET_CALL(flush_sig_insns, viking_flush_sig_insns, BTFIXUPCALL_NOP);
1982 1454
1983 poke_srmmu = poke_viking; 1455 poke_srmmu = poke_viking;
1984} 1456}
1985 1457
1986#ifdef CONFIG_SPARC_LEON
1987
1988void __init poke_leonsparc(void)
1989{
1990}
1991
1992void __init init_leon(void)
1993{
1994
1995 srmmu_name = "LEON";
1996
1997 BTFIXUPSET_CALL(flush_cache_all, leon_flush_cache_all,
1998 BTFIXUPCALL_NORM);
1999 BTFIXUPSET_CALL(flush_cache_mm, leon_flush_cache_all,
2000 BTFIXUPCALL_NORM);
2001 BTFIXUPSET_CALL(flush_cache_page, leon_flush_pcache_all,
2002 BTFIXUPCALL_NORM);
2003 BTFIXUPSET_CALL(flush_cache_range, leon_flush_cache_all,
2004 BTFIXUPCALL_NORM);
2005 BTFIXUPSET_CALL(flush_page_for_dma, leon_flush_dcache_all,
2006 BTFIXUPCALL_NORM);
2007
2008 BTFIXUPSET_CALL(flush_tlb_all, leon_flush_tlb_all, BTFIXUPCALL_NORM);
2009 BTFIXUPSET_CALL(flush_tlb_mm, leon_flush_tlb_all, BTFIXUPCALL_NORM);
2010 BTFIXUPSET_CALL(flush_tlb_page, leon_flush_tlb_all, BTFIXUPCALL_NORM);
2011 BTFIXUPSET_CALL(flush_tlb_range, leon_flush_tlb_all, BTFIXUPCALL_NORM);
2012
2013 BTFIXUPSET_CALL(__flush_page_to_ram, leon_flush_cache_all,
2014 BTFIXUPCALL_NOP);
2015 BTFIXUPSET_CALL(flush_sig_insns, leon_flush_cache_all, BTFIXUPCALL_NOP);
2016
2017 poke_srmmu = poke_leonsparc;
2018
2019 srmmu_cache_pagetables = 0;
2020
2021 leon_flush_during_switch = leon_flush_needed();
2022}
2023#endif
2024
2025/* Probe for the srmmu chip version. */ 1458/* Probe for the srmmu chip version. */
2026static void __init get_srmmu_type(void) 1459static void __init get_srmmu_type(void)
2027{ 1460{
@@ -2052,22 +1485,15 @@ static void __init get_srmmu_type(void)
2052 break; 1485 break;
2053 case 0: 1486 case 0:
2054 case 2: 1487 case 2:
2055 /* Uniprocessor Cypress */
2056 init_cypress_604();
2057 break;
2058 case 10: 1488 case 10:
2059 case 11: 1489 case 11:
2060 case 12: 1490 case 12:
2061 /* _REALLY OLD_ Cypress MP chips... */
2062 case 13: 1491 case 13:
2063 case 14: 1492 case 14:
2064 case 15: 1493 case 15:
2065 /* MP Cypress mmu/cache-controller */
2066 init_cypress_605(mod_rev);
2067 break;
2068 default: 1494 default:
2069 /* Some other Cypress revision, assume a 605. */ 1495 prom_printf("Sparc-Linux Cypress support does not longer exit.\n");
2070 init_cypress_605(mod_rev); 1496 prom_halt();
2071 break; 1497 break;
2072 } 1498 }
2073 return; 1499 return;
@@ -2123,203 +1549,193 @@ static void __init get_srmmu_type(void)
2123 srmmu_is_bad(); 1549 srmmu_is_bad();
2124} 1550}
2125 1551
2126/* don't laugh, static pagetables */ 1552#ifdef CONFIG_SMP
2127static void srmmu_check_pgt_cache(int low, int high) 1553/* Local cross-calls. */
1554static void smp_flush_page_for_dma(unsigned long page)
2128{ 1555{
1556 xc1((smpfunc_t) local_ops->page_for_dma, page);
1557 local_ops->page_for_dma(page);
2129} 1558}
2130 1559
2131extern unsigned long spwin_mmu_patchme, fwin_mmu_patchme, 1560static void smp_flush_cache_all(void)
2132 tsetup_mmu_patchme, rtrap_mmu_patchme;
2133
2134extern unsigned long spwin_srmmu_stackchk, srmmu_fwin_stackchk,
2135 tsetup_srmmu_stackchk, srmmu_rett_stackchk;
2136
2137extern unsigned long srmmu_fault;
2138
2139#define PATCH_BRANCH(insn, dest) do { \
2140 iaddr = &(insn); \
2141 daddr = &(dest); \
2142 *iaddr = SPARC_BRANCH((unsigned long) daddr, (unsigned long) iaddr); \
2143 } while(0)
2144
2145static void __init patch_window_trap_handlers(void)
2146{ 1561{
2147 unsigned long *iaddr, *daddr; 1562 xc0((smpfunc_t) local_ops->cache_all);
2148 1563 local_ops->cache_all();
2149 PATCH_BRANCH(spwin_mmu_patchme, spwin_srmmu_stackchk);
2150 PATCH_BRANCH(fwin_mmu_patchme, srmmu_fwin_stackchk);
2151 PATCH_BRANCH(tsetup_mmu_patchme, tsetup_srmmu_stackchk);
2152 PATCH_BRANCH(rtrap_mmu_patchme, srmmu_rett_stackchk);
2153 PATCH_BRANCH(sparc_ttable[SP_TRAP_TFLT].inst_three, srmmu_fault);
2154 PATCH_BRANCH(sparc_ttable[SP_TRAP_DFLT].inst_three, srmmu_fault);
2155 PATCH_BRANCH(sparc_ttable[SP_TRAP_DACC].inst_three, srmmu_fault);
2156} 1564}
2157 1565
2158#ifdef CONFIG_SMP 1566static void smp_flush_tlb_all(void)
2159/* Local cross-calls. */
2160static void smp_flush_page_for_dma(unsigned long page)
2161{ 1567{
2162 xc1((smpfunc_t) BTFIXUP_CALL(local_flush_page_for_dma), page); 1568 xc0((smpfunc_t) local_ops->tlb_all);
2163 local_flush_page_for_dma(page); 1569 local_ops->tlb_all();
2164} 1570}
2165 1571
2166#endif 1572static void smp_flush_cache_mm(struct mm_struct *mm)
2167
2168static pte_t srmmu_pgoff_to_pte(unsigned long pgoff)
2169{ 1573{
2170 return __pte((pgoff << SRMMU_PTE_FILE_SHIFT) | SRMMU_FILE); 1574 if (mm->context != NO_CONTEXT) {
1575 cpumask_t cpu_mask;
1576 cpumask_copy(&cpu_mask, mm_cpumask(mm));
1577 cpumask_clear_cpu(smp_processor_id(), &cpu_mask);
1578 if (!cpumask_empty(&cpu_mask))
1579 xc1((smpfunc_t) local_ops->cache_mm, (unsigned long) mm);
1580 local_ops->cache_mm(mm);
1581 }
2171} 1582}
2172 1583
2173static unsigned long srmmu_pte_to_pgoff(pte_t pte) 1584static void smp_flush_tlb_mm(struct mm_struct *mm)
2174{ 1585{
2175 return pte_val(pte) >> SRMMU_PTE_FILE_SHIFT; 1586 if (mm->context != NO_CONTEXT) {
1587 cpumask_t cpu_mask;
1588 cpumask_copy(&cpu_mask, mm_cpumask(mm));
1589 cpumask_clear_cpu(smp_processor_id(), &cpu_mask);
1590 if (!cpumask_empty(&cpu_mask)) {
1591 xc1((smpfunc_t) local_ops->tlb_mm, (unsigned long) mm);
1592 if (atomic_read(&mm->mm_users) == 1 && current->active_mm == mm)
1593 cpumask_copy(mm_cpumask(mm),
1594 cpumask_of(smp_processor_id()));
1595 }
1596 local_ops->tlb_mm(mm);
1597 }
2176} 1598}
2177 1599
2178static pgprot_t srmmu_pgprot_noncached(pgprot_t prot) 1600static void smp_flush_cache_range(struct vm_area_struct *vma,
1601 unsigned long start,
1602 unsigned long end)
2179{ 1603{
2180 prot &= ~__pgprot(SRMMU_CACHE); 1604 struct mm_struct *mm = vma->vm_mm;
2181 1605
2182 return prot; 1606 if (mm->context != NO_CONTEXT) {
1607 cpumask_t cpu_mask;
1608 cpumask_copy(&cpu_mask, mm_cpumask(mm));
1609 cpumask_clear_cpu(smp_processor_id(), &cpu_mask);
1610 if (!cpumask_empty(&cpu_mask))
1611 xc3((smpfunc_t) local_ops->cache_range,
1612 (unsigned long) vma, start, end);
1613 local_ops->cache_range(vma, start, end);
1614 }
2183} 1615}
2184 1616
2185/* Load up routines and constants for sun4m and sun4d mmu */ 1617static void smp_flush_tlb_range(struct vm_area_struct *vma,
2186void __init ld_mmu_srmmu(void) 1618 unsigned long start,
1619 unsigned long end)
2187{ 1620{
2188 extern void ld_mmu_iommu(void); 1621 struct mm_struct *mm = vma->vm_mm;
2189 extern void ld_mmu_iounit(void);
2190 extern void ___xchg32_sun4md(void);
2191
2192 BTFIXUPSET_SIMM13(pgdir_shift, SRMMU_PGDIR_SHIFT);
2193 BTFIXUPSET_SETHI(pgdir_size, SRMMU_PGDIR_SIZE);
2194 BTFIXUPSET_SETHI(pgdir_mask, SRMMU_PGDIR_MASK);
2195
2196 BTFIXUPSET_SIMM13(ptrs_per_pmd, SRMMU_PTRS_PER_PMD);
2197 BTFIXUPSET_SIMM13(ptrs_per_pgd, SRMMU_PTRS_PER_PGD);
2198
2199 BTFIXUPSET_INT(page_none, pgprot_val(SRMMU_PAGE_NONE));
2200 PAGE_SHARED = pgprot_val(SRMMU_PAGE_SHARED);
2201 BTFIXUPSET_INT(page_copy, pgprot_val(SRMMU_PAGE_COPY));
2202 BTFIXUPSET_INT(page_readonly, pgprot_val(SRMMU_PAGE_RDONLY));
2203 BTFIXUPSET_INT(page_kernel, pgprot_val(SRMMU_PAGE_KERNEL));
2204 page_kernel = pgprot_val(SRMMU_PAGE_KERNEL);
2205 1622
2206 /* Functions */ 1623 if (mm->context != NO_CONTEXT) {
2207 BTFIXUPSET_CALL(pgprot_noncached, srmmu_pgprot_noncached, BTFIXUPCALL_NORM); 1624 cpumask_t cpu_mask;
2208#ifndef CONFIG_SMP 1625 cpumask_copy(&cpu_mask, mm_cpumask(mm));
2209 BTFIXUPSET_CALL(___xchg32, ___xchg32_sun4md, BTFIXUPCALL_SWAPG1G2); 1626 cpumask_clear_cpu(smp_processor_id(), &cpu_mask);
2210#endif 1627 if (!cpumask_empty(&cpu_mask))
2211 BTFIXUPSET_CALL(do_check_pgt_cache, srmmu_check_pgt_cache, BTFIXUPCALL_NOP); 1628 xc3((smpfunc_t) local_ops->tlb_range,
1629 (unsigned long) vma, start, end);
1630 local_ops->tlb_range(vma, start, end);
1631 }
1632}
2212 1633
2213 BTFIXUPSET_CALL(set_pte, srmmu_set_pte, BTFIXUPCALL_SWAPO0O1); 1634static void smp_flush_cache_page(struct vm_area_struct *vma, unsigned long page)
2214 BTFIXUPSET_CALL(switch_mm, srmmu_switch_mm, BTFIXUPCALL_NORM); 1635{
1636 struct mm_struct *mm = vma->vm_mm;
2215 1637
2216 BTFIXUPSET_CALL(pte_pfn, srmmu_pte_pfn, BTFIXUPCALL_NORM); 1638 if (mm->context != NO_CONTEXT) {
2217 BTFIXUPSET_CALL(pmd_page, srmmu_pmd_page, BTFIXUPCALL_NORM); 1639 cpumask_t cpu_mask;
2218 BTFIXUPSET_CALL(pgd_page_vaddr, srmmu_pgd_page, BTFIXUPCALL_NORM); 1640 cpumask_copy(&cpu_mask, mm_cpumask(mm));
1641 cpumask_clear_cpu(smp_processor_id(), &cpu_mask);
1642 if (!cpumask_empty(&cpu_mask))
1643 xc2((smpfunc_t) local_ops->cache_page,
1644 (unsigned long) vma, page);
1645 local_ops->cache_page(vma, page);
1646 }
1647}
2219 1648
2220 BTFIXUPSET_CALL(pte_present, srmmu_pte_present, BTFIXUPCALL_NORM); 1649static void smp_flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
2221 BTFIXUPSET_CALL(pte_clear, srmmu_pte_clear, BTFIXUPCALL_SWAPO0G0); 1650{
1651 struct mm_struct *mm = vma->vm_mm;
2222 1652
2223 BTFIXUPSET_CALL(pmd_bad, srmmu_pmd_bad, BTFIXUPCALL_NORM); 1653 if (mm->context != NO_CONTEXT) {
2224 BTFIXUPSET_CALL(pmd_present, srmmu_pmd_present, BTFIXUPCALL_NORM); 1654 cpumask_t cpu_mask;
2225 BTFIXUPSET_CALL(pmd_clear, srmmu_pmd_clear, BTFIXUPCALL_SWAPO0G0); 1655 cpumask_copy(&cpu_mask, mm_cpumask(mm));
1656 cpumask_clear_cpu(smp_processor_id(), &cpu_mask);
1657 if (!cpumask_empty(&cpu_mask))
1658 xc2((smpfunc_t) local_ops->tlb_page,
1659 (unsigned long) vma, page);
1660 local_ops->tlb_page(vma, page);
1661 }
1662}
2226 1663
2227 BTFIXUPSET_CALL(pgd_none, srmmu_pgd_none, BTFIXUPCALL_NORM); 1664static void smp_flush_page_to_ram(unsigned long page)
2228 BTFIXUPSET_CALL(pgd_bad, srmmu_pgd_bad, BTFIXUPCALL_NORM); 1665{
2229 BTFIXUPSET_CALL(pgd_present, srmmu_pgd_present, BTFIXUPCALL_NORM); 1666 /* Current theory is that those who call this are the one's
2230 BTFIXUPSET_CALL(pgd_clear, srmmu_pgd_clear, BTFIXUPCALL_SWAPO0G0); 1667 * who have just dirtied their cache with the pages contents
1668 * in kernel space, therefore we only run this on local cpu.
1669 *
1670 * XXX This experiment failed, research further... -DaveM
1671 */
1672#if 1
1673 xc1((smpfunc_t) local_ops->page_to_ram, page);
1674#endif
1675 local_ops->page_to_ram(page);
1676}
1677
1678static void smp_flush_sig_insns(struct mm_struct *mm, unsigned long insn_addr)
1679{
1680 cpumask_t cpu_mask;
1681 cpumask_copy(&cpu_mask, mm_cpumask(mm));
1682 cpumask_clear_cpu(smp_processor_id(), &cpu_mask);
1683 if (!cpumask_empty(&cpu_mask))
1684 xc2((smpfunc_t) local_ops->sig_insns,
1685 (unsigned long) mm, insn_addr);
1686 local_ops->sig_insns(mm, insn_addr);
1687}
1688
1689static struct sparc32_cachetlb_ops smp_cachetlb_ops = {
1690 .cache_all = smp_flush_cache_all,
1691 .cache_mm = smp_flush_cache_mm,
1692 .cache_page = smp_flush_cache_page,
1693 .cache_range = smp_flush_cache_range,
1694 .tlb_all = smp_flush_tlb_all,
1695 .tlb_mm = smp_flush_tlb_mm,
1696 .tlb_page = smp_flush_tlb_page,
1697 .tlb_range = smp_flush_tlb_range,
1698 .page_to_ram = smp_flush_page_to_ram,
1699 .sig_insns = smp_flush_sig_insns,
1700 .page_for_dma = smp_flush_page_for_dma,
1701};
1702#endif
2231 1703
2232 BTFIXUPSET_CALL(mk_pte, srmmu_mk_pte, BTFIXUPCALL_NORM); 1704/* Load up routines and constants for sun4m and sun4d mmu */
2233 BTFIXUPSET_CALL(mk_pte_phys, srmmu_mk_pte_phys, BTFIXUPCALL_NORM); 1705void __init load_mmu(void)
2234 BTFIXUPSET_CALL(mk_pte_io, srmmu_mk_pte_io, BTFIXUPCALL_NORM); 1706{
2235 BTFIXUPSET_CALL(pgd_set, srmmu_pgd_set, BTFIXUPCALL_NORM); 1707 extern void ld_mmu_iommu(void);
2236 BTFIXUPSET_CALL(pmd_set, srmmu_pmd_set, BTFIXUPCALL_NORM); 1708 extern void ld_mmu_iounit(void);
2237 BTFIXUPSET_CALL(pmd_populate, srmmu_pmd_populate, BTFIXUPCALL_NORM);
2238
2239 BTFIXUPSET_INT(pte_modify_mask, SRMMU_CHG_MASK);
2240 BTFIXUPSET_CALL(pmd_offset, srmmu_pmd_offset, BTFIXUPCALL_NORM);
2241 BTFIXUPSET_CALL(pte_offset_kernel, srmmu_pte_offset, BTFIXUPCALL_NORM);
2242
2243 BTFIXUPSET_CALL(free_pte_fast, srmmu_free_pte_fast, BTFIXUPCALL_NORM);
2244 BTFIXUPSET_CALL(pte_free, srmmu_pte_free, BTFIXUPCALL_NORM);
2245 BTFIXUPSET_CALL(pte_alloc_one_kernel, srmmu_pte_alloc_one_kernel, BTFIXUPCALL_NORM);
2246 BTFIXUPSET_CALL(pte_alloc_one, srmmu_pte_alloc_one, BTFIXUPCALL_NORM);
2247 BTFIXUPSET_CALL(free_pmd_fast, srmmu_pmd_free, BTFIXUPCALL_NORM);
2248 BTFIXUPSET_CALL(pmd_alloc_one, srmmu_pmd_alloc_one, BTFIXUPCALL_NORM);
2249 BTFIXUPSET_CALL(free_pgd_fast, srmmu_free_pgd_fast, BTFIXUPCALL_NORM);
2250 BTFIXUPSET_CALL(get_pgd_fast, srmmu_get_pgd_fast, BTFIXUPCALL_NORM);
2251
2252 BTFIXUPSET_HALF(pte_writei, SRMMU_WRITE);
2253 BTFIXUPSET_HALF(pte_dirtyi, SRMMU_DIRTY);
2254 BTFIXUPSET_HALF(pte_youngi, SRMMU_REF);
2255 BTFIXUPSET_HALF(pte_filei, SRMMU_FILE);
2256 BTFIXUPSET_HALF(pte_wrprotecti, SRMMU_WRITE);
2257 BTFIXUPSET_HALF(pte_mkcleani, SRMMU_DIRTY);
2258 BTFIXUPSET_HALF(pte_mkoldi, SRMMU_REF);
2259 BTFIXUPSET_CALL(pte_mkwrite, srmmu_pte_mkwrite, BTFIXUPCALL_ORINT(SRMMU_WRITE));
2260 BTFIXUPSET_CALL(pte_mkdirty, srmmu_pte_mkdirty, BTFIXUPCALL_ORINT(SRMMU_DIRTY));
2261 BTFIXUPSET_CALL(pte_mkyoung, srmmu_pte_mkyoung, BTFIXUPCALL_ORINT(SRMMU_REF));
2262 BTFIXUPSET_CALL(update_mmu_cache, srmmu_update_mmu_cache, BTFIXUPCALL_NOP);
2263 BTFIXUPSET_CALL(destroy_context, srmmu_destroy_context, BTFIXUPCALL_NORM);
2264
2265 BTFIXUPSET_CALL(sparc_mapiorange, srmmu_mapiorange, BTFIXUPCALL_NORM);
2266 BTFIXUPSET_CALL(sparc_unmapiorange, srmmu_unmapiorange, BTFIXUPCALL_NORM);
2267
2268 BTFIXUPSET_CALL(__swp_type, srmmu_swp_type, BTFIXUPCALL_NORM);
2269 BTFIXUPSET_CALL(__swp_offset, srmmu_swp_offset, BTFIXUPCALL_NORM);
2270 BTFIXUPSET_CALL(__swp_entry, srmmu_swp_entry, BTFIXUPCALL_NORM);
2271
2272 BTFIXUPSET_CALL(mmu_info, srmmu_mmu_info, BTFIXUPCALL_NORM);
2273
2274 BTFIXUPSET_CALL(alloc_thread_info_node, srmmu_alloc_thread_info_node, BTFIXUPCALL_NORM);
2275 BTFIXUPSET_CALL(free_thread_info, srmmu_free_thread_info, BTFIXUPCALL_NORM);
2276
2277 BTFIXUPSET_CALL(pte_to_pgoff, srmmu_pte_to_pgoff, BTFIXUPCALL_NORM);
2278 BTFIXUPSET_CALL(pgoff_to_pte, srmmu_pgoff_to_pte, BTFIXUPCALL_NORM);
2279 1709
1710 /* Functions */
2280 get_srmmu_type(); 1711 get_srmmu_type();
2281 patch_window_trap_handlers();
2282 1712
2283#ifdef CONFIG_SMP 1713#ifdef CONFIG_SMP
2284 /* El switcheroo... */ 1714 /* El switcheroo... */
1715 local_ops = sparc32_cachetlb_ops;
2285 1716
2286 BTFIXUPCOPY_CALL(local_flush_cache_all, flush_cache_all); 1717 if (sparc_cpu_model == sun4d || sparc_cpu_model == sparc_leon) {
2287 BTFIXUPCOPY_CALL(local_flush_cache_mm, flush_cache_mm); 1718 smp_cachetlb_ops.tlb_all = local_ops->tlb_all;
2288 BTFIXUPCOPY_CALL(local_flush_cache_range, flush_cache_range); 1719 smp_cachetlb_ops.tlb_mm = local_ops->tlb_mm;
2289 BTFIXUPCOPY_CALL(local_flush_cache_page, flush_cache_page); 1720 smp_cachetlb_ops.tlb_range = local_ops->tlb_range;
2290 BTFIXUPCOPY_CALL(local_flush_tlb_all, flush_tlb_all); 1721 smp_cachetlb_ops.tlb_page = local_ops->tlb_page;
2291 BTFIXUPCOPY_CALL(local_flush_tlb_mm, flush_tlb_mm);
2292 BTFIXUPCOPY_CALL(local_flush_tlb_range, flush_tlb_range);
2293 BTFIXUPCOPY_CALL(local_flush_tlb_page, flush_tlb_page);
2294 BTFIXUPCOPY_CALL(local_flush_page_to_ram, __flush_page_to_ram);
2295 BTFIXUPCOPY_CALL(local_flush_sig_insns, flush_sig_insns);
2296 BTFIXUPCOPY_CALL(local_flush_page_for_dma, flush_page_for_dma);
2297
2298 BTFIXUPSET_CALL(flush_cache_all, smp_flush_cache_all, BTFIXUPCALL_NORM);
2299 BTFIXUPSET_CALL(flush_cache_mm, smp_flush_cache_mm, BTFIXUPCALL_NORM);
2300 BTFIXUPSET_CALL(flush_cache_range, smp_flush_cache_range, BTFIXUPCALL_NORM);
2301 BTFIXUPSET_CALL(flush_cache_page, smp_flush_cache_page, BTFIXUPCALL_NORM);
2302 if (sparc_cpu_model != sun4d &&
2303 sparc_cpu_model != sparc_leon) {
2304 BTFIXUPSET_CALL(flush_tlb_all, smp_flush_tlb_all, BTFIXUPCALL_NORM);
2305 BTFIXUPSET_CALL(flush_tlb_mm, smp_flush_tlb_mm, BTFIXUPCALL_NORM);
2306 BTFIXUPSET_CALL(flush_tlb_range, smp_flush_tlb_range, BTFIXUPCALL_NORM);
2307 BTFIXUPSET_CALL(flush_tlb_page, smp_flush_tlb_page, BTFIXUPCALL_NORM);
2308 } 1722 }
2309 BTFIXUPSET_CALL(__flush_page_to_ram, smp_flush_page_to_ram, BTFIXUPCALL_NORM);
2310 BTFIXUPSET_CALL(flush_sig_insns, smp_flush_sig_insns, BTFIXUPCALL_NORM);
2311 BTFIXUPSET_CALL(flush_page_for_dma, smp_flush_page_for_dma, BTFIXUPCALL_NORM);
2312 1723
2313 if (poke_srmmu == poke_viking) { 1724 if (poke_srmmu == poke_viking) {
2314 /* Avoid unnecessary cross calls. */ 1725 /* Avoid unnecessary cross calls. */
2315 BTFIXUPCOPY_CALL(flush_cache_all, local_flush_cache_all); 1726 smp_cachetlb_ops.cache_all = local_ops->cache_all;
2316 BTFIXUPCOPY_CALL(flush_cache_mm, local_flush_cache_mm); 1727 smp_cachetlb_ops.cache_mm = local_ops->cache_mm;
2317 BTFIXUPCOPY_CALL(flush_cache_range, local_flush_cache_range); 1728 smp_cachetlb_ops.cache_range = local_ops->cache_range;
2318 BTFIXUPCOPY_CALL(flush_cache_page, local_flush_cache_page); 1729 smp_cachetlb_ops.cache_page = local_ops->cache_page;
2319 BTFIXUPCOPY_CALL(__flush_page_to_ram, local_flush_page_to_ram); 1730
2320 BTFIXUPCOPY_CALL(flush_sig_insns, local_flush_sig_insns); 1731 smp_cachetlb_ops.page_to_ram = local_ops->page_to_ram;
2321 BTFIXUPCOPY_CALL(flush_page_for_dma, local_flush_page_for_dma); 1732 smp_cachetlb_ops.sig_insns = local_ops->sig_insns;
1733 smp_cachetlb_ops.page_for_dma = local_ops->page_for_dma;
2322 } 1734 }
1735
1736 /* It really is const after this point. */
1737 sparc32_cachetlb_ops = (const struct sparc32_cachetlb_ops *)
1738 &smp_cachetlb_ops;
2323#endif 1739#endif
2324 1740
2325 if (sparc_cpu_model == sun4d) 1741 if (sparc_cpu_model == sun4d)
diff --git a/arch/sparc/mm/srmmu.h b/arch/sparc/mm/srmmu.h
new file mode 100644
index 000000000000..5703274ccf89
--- /dev/null
+++ b/arch/sparc/mm/srmmu.h
@@ -0,0 +1,4 @@
1/* srmmu.c */
2extern char *srmmu_name;
3
4extern void (*poke_srmmu)(void);
diff --git a/arch/sparc/mm/sun4c.c b/arch/sparc/mm/sun4c.c
deleted file mode 100644
index 1cf4f198709a..000000000000
--- a/arch/sparc/mm/sun4c.c
+++ /dev/null
@@ -1,2166 +0,0 @@
1/* sun4c.c: Doing in software what should be done in hardware.
2 *
3 * Copyright (C) 1996 David S. Miller (davem@davemloft.net)
4 * Copyright (C) 1996 Eddie C. Dost (ecd@skynet.be)
5 * Copyright (C) 1996 Andrew Tridgell (Andrew.Tridgell@anu.edu.au)
6 * Copyright (C) 1997-2000 Anton Blanchard (anton@samba.org)
7 * Copyright (C) 1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
8 */
9
10#define NR_TASK_BUCKETS 512
11
12#include <linux/kernel.h>
13#include <linux/mm.h>
14#include <linux/init.h>
15#include <linux/slab.h>
16#include <linux/bootmem.h>
17#include <linux/highmem.h>
18#include <linux/fs.h>
19#include <linux/seq_file.h>
20#include <linux/scatterlist.h>
21#include <linux/bitmap.h>
22
23#include <asm/sections.h>
24#include <asm/page.h>
25#include <asm/pgalloc.h>
26#include <asm/pgtable.h>
27#include <asm/vaddrs.h>
28#include <asm/idprom.h>
29#include <asm/machines.h>
30#include <asm/memreg.h>
31#include <asm/processor.h>
32#include <asm/auxio.h>
33#include <asm/io.h>
34#include <asm/oplib.h>
35#include <asm/openprom.h>
36#include <asm/mmu_context.h>
37#include <asm/highmem.h>
38#include <asm/btfixup.h>
39#include <asm/cacheflush.h>
40#include <asm/tlbflush.h>
41
42/* Because of our dynamic kernel TLB miss strategy, and how
43 * our DVMA mapping allocation works, you _MUST_:
44 *
45 * 1) Disable interrupts _and_ not touch any dynamic kernel
46 * memory while messing with kernel MMU state. By
47 * dynamic memory I mean any object which is not in
48 * the kernel image itself or a thread_union (both of
49 * which are locked into the MMU).
50 * 2) Disable interrupts while messing with user MMU state.
51 */
52
53extern int num_segmaps, num_contexts;
54
55extern unsigned long page_kernel;
56
57/* That's it, we prom_halt() on sun4c if the cache size is something other than 65536.
58 * So let's save some cycles and just use that everywhere except for that bootup
59 * sanity check.
60 */
61#define SUN4C_VAC_SIZE 65536
62
63#define SUN4C_KERNEL_BUCKETS 32
64
65/* Flushing the cache. */
66struct sun4c_vac_props sun4c_vacinfo;
67unsigned long sun4c_kernel_faults;
68
69/* Invalidate every sun4c cache line tag. */
70static void __init sun4c_flush_all(void)
71{
72 unsigned long begin, end;
73
74 if (sun4c_vacinfo.on)
75 panic("SUN4C: AIEEE, trying to invalidate vac while it is on.");
76
77 /* Clear 'valid' bit in all cache line tags */
78 begin = AC_CACHETAGS;
79 end = (AC_CACHETAGS + SUN4C_VAC_SIZE);
80 while (begin < end) {
81 __asm__ __volatile__("sta %%g0, [%0] %1\n\t" : :
82 "r" (begin), "i" (ASI_CONTROL));
83 begin += sun4c_vacinfo.linesize;
84 }
85}
86
87static void sun4c_flush_context_hw(void)
88{
89 unsigned long end = SUN4C_VAC_SIZE;
90
91 __asm__ __volatile__(
92 "1: addcc %0, -4096, %0\n\t"
93 " bne 1b\n\t"
94 " sta %%g0, [%0] %2"
95 : "=&r" (end)
96 : "0" (end), "i" (ASI_HWFLUSHCONTEXT)
97 : "cc");
98}
99
100/* Must be called minimally with IRQs disabled. */
101static void sun4c_flush_segment_hw(unsigned long addr)
102{
103 if (sun4c_get_segmap(addr) != invalid_segment) {
104 unsigned long vac_size = SUN4C_VAC_SIZE;
105
106 __asm__ __volatile__(
107 "1: addcc %0, -4096, %0\n\t"
108 " bne 1b\n\t"
109 " sta %%g0, [%2 + %0] %3"
110 : "=&r" (vac_size)
111 : "0" (vac_size), "r" (addr), "i" (ASI_HWFLUSHSEG)
112 : "cc");
113 }
114}
115
116/* File local boot time fixups. */
117BTFIXUPDEF_CALL(void, sun4c_flush_page, unsigned long)
118BTFIXUPDEF_CALL(void, sun4c_flush_segment, unsigned long)
119BTFIXUPDEF_CALL(void, sun4c_flush_context, void)
120
121#define sun4c_flush_page(addr) BTFIXUP_CALL(sun4c_flush_page)(addr)
122#define sun4c_flush_segment(addr) BTFIXUP_CALL(sun4c_flush_segment)(addr)
123#define sun4c_flush_context() BTFIXUP_CALL(sun4c_flush_context)()
124
125/* Must be called minimally with interrupts disabled. */
126static void sun4c_flush_page_hw(unsigned long addr)
127{
128 addr &= PAGE_MASK;
129 if ((int)sun4c_get_pte(addr) < 0)
130 __asm__ __volatile__("sta %%g0, [%0] %1"
131 : : "r" (addr), "i" (ASI_HWFLUSHPAGE));
132}
133
134/* Don't inline the software version as it eats too many cache lines if expanded. */
135static void sun4c_flush_context_sw(void)
136{
137 unsigned long nbytes = SUN4C_VAC_SIZE;
138 unsigned long lsize = sun4c_vacinfo.linesize;
139
140 __asm__ __volatile__(
141 "add %2, %2, %%g1\n\t"
142 "add %2, %%g1, %%g2\n\t"
143 "add %2, %%g2, %%g3\n\t"
144 "add %2, %%g3, %%g4\n\t"
145 "add %2, %%g4, %%g5\n\t"
146 "add %2, %%g5, %%o4\n\t"
147 "add %2, %%o4, %%o5\n"
148 "1:\n\t"
149 "subcc %0, %%o5, %0\n\t"
150 "sta %%g0, [%0] %3\n\t"
151 "sta %%g0, [%0 + %2] %3\n\t"
152 "sta %%g0, [%0 + %%g1] %3\n\t"
153 "sta %%g0, [%0 + %%g2] %3\n\t"
154 "sta %%g0, [%0 + %%g3] %3\n\t"
155 "sta %%g0, [%0 + %%g4] %3\n\t"
156 "sta %%g0, [%0 + %%g5] %3\n\t"
157 "bg 1b\n\t"
158 " sta %%g0, [%1 + %%o4] %3\n"
159 : "=&r" (nbytes)
160 : "0" (nbytes), "r" (lsize), "i" (ASI_FLUSHCTX)
161 : "g1", "g2", "g3", "g4", "g5", "o4", "o5", "cc");
162}
163
164/* Don't inline the software version as it eats too many cache lines if expanded. */
165static void sun4c_flush_segment_sw(unsigned long addr)
166{
167 if (sun4c_get_segmap(addr) != invalid_segment) {
168 unsigned long nbytes = SUN4C_VAC_SIZE;
169 unsigned long lsize = sun4c_vacinfo.linesize;
170
171 __asm__ __volatile__(
172 "add %2, %2, %%g1\n\t"
173 "add %2, %%g1, %%g2\n\t"
174 "add %2, %%g2, %%g3\n\t"
175 "add %2, %%g3, %%g4\n\t"
176 "add %2, %%g4, %%g5\n\t"
177 "add %2, %%g5, %%o4\n\t"
178 "add %2, %%o4, %%o5\n"
179 "1:\n\t"
180 "subcc %1, %%o5, %1\n\t"
181 "sta %%g0, [%0] %6\n\t"
182 "sta %%g0, [%0 + %2] %6\n\t"
183 "sta %%g0, [%0 + %%g1] %6\n\t"
184 "sta %%g0, [%0 + %%g2] %6\n\t"
185 "sta %%g0, [%0 + %%g3] %6\n\t"
186 "sta %%g0, [%0 + %%g4] %6\n\t"
187 "sta %%g0, [%0 + %%g5] %6\n\t"
188 "sta %%g0, [%0 + %%o4] %6\n\t"
189 "bg 1b\n\t"
190 " add %0, %%o5, %0\n"
191 : "=&r" (addr), "=&r" (nbytes), "=&r" (lsize)
192 : "0" (addr), "1" (nbytes), "2" (lsize),
193 "i" (ASI_FLUSHSEG)
194 : "g1", "g2", "g3", "g4", "g5", "o4", "o5", "cc");
195 }
196}
197
198/* Don't inline the software version as it eats too many cache lines if expanded. */
199static void sun4c_flush_page_sw(unsigned long addr)
200{
201 addr &= PAGE_MASK;
202 if ((sun4c_get_pte(addr) & (_SUN4C_PAGE_NOCACHE | _SUN4C_PAGE_VALID)) ==
203 _SUN4C_PAGE_VALID) {
204 unsigned long left = PAGE_SIZE;
205 unsigned long lsize = sun4c_vacinfo.linesize;
206
207 __asm__ __volatile__(
208 "add %2, %2, %%g1\n\t"
209 "add %2, %%g1, %%g2\n\t"
210 "add %2, %%g2, %%g3\n\t"
211 "add %2, %%g3, %%g4\n\t"
212 "add %2, %%g4, %%g5\n\t"
213 "add %2, %%g5, %%o4\n\t"
214 "add %2, %%o4, %%o5\n"
215 "1:\n\t"
216 "subcc %1, %%o5, %1\n\t"
217 "sta %%g0, [%0] %6\n\t"
218 "sta %%g0, [%0 + %2] %6\n\t"
219 "sta %%g0, [%0 + %%g1] %6\n\t"
220 "sta %%g0, [%0 + %%g2] %6\n\t"
221 "sta %%g0, [%0 + %%g3] %6\n\t"
222 "sta %%g0, [%0 + %%g4] %6\n\t"
223 "sta %%g0, [%0 + %%g5] %6\n\t"
224 "sta %%g0, [%0 + %%o4] %6\n\t"
225 "bg 1b\n\t"
226 " add %0, %%o5, %0\n"
227 : "=&r" (addr), "=&r" (left), "=&r" (lsize)
228 : "0" (addr), "1" (left), "2" (lsize),
229 "i" (ASI_FLUSHPG)
230 : "g1", "g2", "g3", "g4", "g5", "o4", "o5", "cc");
231 }
232}
233
234/* The sun4c's do have an on chip store buffer. And the way you
235 * clear them out isn't so obvious. The only way I can think of
236 * to accomplish this is to read the current context register,
237 * store the same value there, then read an external hardware
238 * register.
239 */
240void sun4c_complete_all_stores(void)
241{
242 volatile int _unused;
243
244 _unused = sun4c_get_context();
245 sun4c_set_context(_unused);
246 _unused = get_auxio();
247}
248
249/* Bootup utility functions. */
250static inline void sun4c_init_clean_segmap(unsigned char pseg)
251{
252 unsigned long vaddr;
253
254 sun4c_put_segmap(0, pseg);
255 for (vaddr = 0; vaddr < SUN4C_REAL_PGDIR_SIZE; vaddr += PAGE_SIZE)
256 sun4c_put_pte(vaddr, 0);
257 sun4c_put_segmap(0, invalid_segment);
258}
259
260static inline void sun4c_init_clean_mmu(unsigned long kernel_end)
261{
262 unsigned long vaddr;
263 unsigned char savectx, ctx;
264
265 savectx = sun4c_get_context();
266 for (ctx = 0; ctx < num_contexts; ctx++) {
267 sun4c_set_context(ctx);
268 for (vaddr = 0; vaddr < 0x20000000; vaddr += SUN4C_REAL_PGDIR_SIZE)
269 sun4c_put_segmap(vaddr, invalid_segment);
270 for (vaddr = 0xe0000000; vaddr < KERNBASE; vaddr += SUN4C_REAL_PGDIR_SIZE)
271 sun4c_put_segmap(vaddr, invalid_segment);
272 for (vaddr = kernel_end; vaddr < KADB_DEBUGGER_BEGVM; vaddr += SUN4C_REAL_PGDIR_SIZE)
273 sun4c_put_segmap(vaddr, invalid_segment);
274 for (vaddr = LINUX_OPPROM_ENDVM; vaddr; vaddr += SUN4C_REAL_PGDIR_SIZE)
275 sun4c_put_segmap(vaddr, invalid_segment);
276 }
277 sun4c_set_context(savectx);
278}
279
280void __init sun4c_probe_vac(void)
281{
282 sun4c_disable_vac();
283
284 if ((idprom->id_machtype == (SM_SUN4C | SM_4C_SS1)) ||
285 (idprom->id_machtype == (SM_SUN4C | SM_4C_SS1PLUS))) {
286 /* PROM on SS1 lacks this info, to be super safe we
287 * hard code it here since this arch is cast in stone.
288 */
289 sun4c_vacinfo.num_bytes = 65536;
290 sun4c_vacinfo.linesize = 16;
291 } else {
292 sun4c_vacinfo.num_bytes =
293 prom_getintdefault(prom_root_node, "vac-size", 65536);
294 sun4c_vacinfo.linesize =
295 prom_getintdefault(prom_root_node, "vac-linesize", 16);
296 }
297 sun4c_vacinfo.do_hwflushes =
298 prom_getintdefault(prom_root_node, "vac-hwflush", 0);
299
300 if (sun4c_vacinfo.do_hwflushes == 0)
301 sun4c_vacinfo.do_hwflushes =
302 prom_getintdefault(prom_root_node, "vac_hwflush", 0);
303
304 if (sun4c_vacinfo.num_bytes != 65536) {
305 prom_printf("WEIRD Sun4C VAC cache size, "
306 "tell sparclinux@vger.kernel.org");
307 prom_halt();
308 }
309
310 switch (sun4c_vacinfo.linesize) {
311 case 16:
312 sun4c_vacinfo.log2lsize = 4;
313 break;
314 case 32:
315 sun4c_vacinfo.log2lsize = 5;
316 break;
317 default:
318 prom_printf("probe_vac: Didn't expect vac-linesize of %d, halting\n",
319 sun4c_vacinfo.linesize);
320 prom_halt();
321 }
322
323 sun4c_flush_all();
324 sun4c_enable_vac();
325}
326
327/* Patch instructions for the low level kernel fault handler. */
328extern unsigned long invalid_segment_patch1, invalid_segment_patch1_ff;
329extern unsigned long invalid_segment_patch2, invalid_segment_patch2_ff;
330extern unsigned long invalid_segment_patch1_1ff, invalid_segment_patch2_1ff;
331extern unsigned long num_context_patch1, num_context_patch1_16;
332extern unsigned long num_context_patch2_16;
333extern unsigned long vac_linesize_patch, vac_linesize_patch_32;
334extern unsigned long vac_hwflush_patch1, vac_hwflush_patch1_on;
335extern unsigned long vac_hwflush_patch2, vac_hwflush_patch2_on;
336
337#define PATCH_INSN(src, dst) do { \
338 daddr = &(dst); \
339 iaddr = &(src); \
340 *daddr = *iaddr; \
341 } while (0)
342
343static void __init patch_kernel_fault_handler(void)
344{
345 unsigned long *iaddr, *daddr;
346
347 switch (num_segmaps) {
348 case 128:
349 /* Default, nothing to do. */
350 break;
351 case 256:
352 PATCH_INSN(invalid_segment_patch1_ff,
353 invalid_segment_patch1);
354 PATCH_INSN(invalid_segment_patch2_ff,
355 invalid_segment_patch2);
356 break;
357 case 512:
358 PATCH_INSN(invalid_segment_patch1_1ff,
359 invalid_segment_patch1);
360 PATCH_INSN(invalid_segment_patch2_1ff,
361 invalid_segment_patch2);
362 break;
363 default:
364 prom_printf("Unhandled number of segmaps: %d\n",
365 num_segmaps);
366 prom_halt();
367 }
368 switch (num_contexts) {
369 case 8:
370 /* Default, nothing to do. */
371 break;
372 case 16:
373 PATCH_INSN(num_context_patch1_16,
374 num_context_patch1);
375 break;
376 default:
377 prom_printf("Unhandled number of contexts: %d\n",
378 num_contexts);
379 prom_halt();
380 }
381
382 if (sun4c_vacinfo.do_hwflushes != 0) {
383 PATCH_INSN(vac_hwflush_patch1_on, vac_hwflush_patch1);
384 PATCH_INSN(vac_hwflush_patch2_on, vac_hwflush_patch2);
385 } else {
386 switch (sun4c_vacinfo.linesize) {
387 case 16:
388 /* Default, nothing to do. */
389 break;
390 case 32:
391 PATCH_INSN(vac_linesize_patch_32, vac_linesize_patch);
392 break;
393 default:
394 prom_printf("Impossible VAC linesize %d, halting...\n",
395 sun4c_vacinfo.linesize);
396 prom_halt();
397 }
398 }
399}
400
401static void __init sun4c_probe_mmu(void)
402{
403 if ((idprom->id_machtype == (SM_SUN4C | SM_4C_SS1)) ||
404 (idprom->id_machtype == (SM_SUN4C | SM_4C_SS1PLUS))) {
405 /* Hardcode these just to be safe, PROM on SS1 does
406 * not have this info available in the root node.
407 */
408 num_segmaps = 128;
409 num_contexts = 8;
410 } else {
411 num_segmaps =
412 prom_getintdefault(prom_root_node, "mmu-npmg", 128);
413 num_contexts =
414 prom_getintdefault(prom_root_node, "mmu-nctx", 0x8);
415 }
416 patch_kernel_fault_handler();
417}
418
419volatile unsigned long __iomem *sun4c_memerr_reg = NULL;
420
421void __init sun4c_probe_memerr_reg(void)
422{
423 phandle node;
424 struct linux_prom_registers regs[1];
425
426 node = prom_getchild(prom_root_node);
427 node = prom_searchsiblings(prom_root_node, "memory-error");
428 if (!node)
429 return;
430 if (prom_getproperty(node, "reg", (char *)regs, sizeof(regs)) <= 0)
431 return;
432 /* hmm I think regs[0].which_io is zero here anyways */
433 sun4c_memerr_reg = ioremap(regs[0].phys_addr, regs[0].reg_size);
434}
435
436static inline void sun4c_init_ss2_cache_bug(void)
437{
438 if ((idprom->id_machtype == (SM_SUN4C | SM_4C_SS2)) ||
439 (idprom->id_machtype == (SM_SUN4C | SM_4C_IPX)) ||
440 (idprom->id_machtype == (SM_SUN4C | SM_4C_ELC))) {
441 /* Whee.. */
442 printk("SS2 cache bug detected, uncaching trap table page\n");
443 sun4c_flush_page((unsigned int) &_start);
444 sun4c_put_pte(((unsigned long) &_start),
445 (sun4c_get_pte((unsigned long) &_start) | _SUN4C_PAGE_NOCACHE));
446 }
447}
448
449/* Addr is always aligned on a page boundary for us already. */
450static int sun4c_map_dma_area(struct device *dev, dma_addr_t *pba, unsigned long va,
451 unsigned long addr, int len)
452{
453 unsigned long page, end;
454
455 *pba = addr;
456
457 end = PAGE_ALIGN((addr + len));
458 while (addr < end) {
459 page = va;
460 sun4c_flush_page(page);
461 page -= PAGE_OFFSET;
462 page >>= PAGE_SHIFT;
463 page |= (_SUN4C_PAGE_VALID | _SUN4C_PAGE_DIRTY |
464 _SUN4C_PAGE_NOCACHE | _SUN4C_PAGE_PRIV);
465 sun4c_put_pte(addr, page);
466 addr += PAGE_SIZE;
467 va += PAGE_SIZE;
468 }
469
470 return 0;
471}
472
473static void sun4c_unmap_dma_area(struct device *dev, unsigned long busa, int len)
474{
475 /* Fortunately for us, bus_addr == uncached_virt in sun4c. */
476 /* XXX Implement this */
477}
478
479/* TLB management. */
480
481/* Don't change this struct without changing entry.S. This is used
482 * in the in-window kernel fault handler, and you don't want to mess
483 * with that. (See sun4c_fault in entry.S).
484 */
485struct sun4c_mmu_entry {
486 struct sun4c_mmu_entry *next;
487 struct sun4c_mmu_entry *prev;
488 unsigned long vaddr;
489 unsigned char pseg;
490 unsigned char locked;
491
492 /* For user mappings only, and completely hidden from kernel
493 * TLB miss code.
494 */
495 unsigned char ctx;
496 struct sun4c_mmu_entry *lru_next;
497 struct sun4c_mmu_entry *lru_prev;
498};
499
500static struct sun4c_mmu_entry mmu_entry_pool[SUN4C_MAX_SEGMAPS];
501
502static void __init sun4c_init_mmu_entry_pool(void)
503{
504 int i;
505
506 for (i=0; i < SUN4C_MAX_SEGMAPS; i++) {
507 mmu_entry_pool[i].pseg = i;
508 mmu_entry_pool[i].next = NULL;
509 mmu_entry_pool[i].prev = NULL;
510 mmu_entry_pool[i].vaddr = 0;
511 mmu_entry_pool[i].locked = 0;
512 mmu_entry_pool[i].ctx = 0;
513 mmu_entry_pool[i].lru_next = NULL;
514 mmu_entry_pool[i].lru_prev = NULL;
515 }
516 mmu_entry_pool[invalid_segment].locked = 1;
517}
518
519static inline void fix_permissions(unsigned long vaddr, unsigned long bits_on,
520 unsigned long bits_off)
521{
522 unsigned long start, end;
523
524 end = vaddr + SUN4C_REAL_PGDIR_SIZE;
525 for (start = vaddr; start < end; start += PAGE_SIZE)
526 if (sun4c_get_pte(start) & _SUN4C_PAGE_VALID)
527 sun4c_put_pte(start, (sun4c_get_pte(start) | bits_on) &
528 ~bits_off);
529}
530
531static inline void sun4c_init_map_kernelprom(unsigned long kernel_end)
532{
533 unsigned long vaddr;
534 unsigned char pseg, ctx;
535
536 for (vaddr = KADB_DEBUGGER_BEGVM;
537 vaddr < LINUX_OPPROM_ENDVM;
538 vaddr += SUN4C_REAL_PGDIR_SIZE) {
539 pseg = sun4c_get_segmap(vaddr);
540 if (pseg != invalid_segment) {
541 mmu_entry_pool[pseg].locked = 1;
542 for (ctx = 0; ctx < num_contexts; ctx++)
543 prom_putsegment(ctx, vaddr, pseg);
544 fix_permissions(vaddr, _SUN4C_PAGE_PRIV, 0);
545 }
546 }
547
548 for (vaddr = KERNBASE; vaddr < kernel_end; vaddr += SUN4C_REAL_PGDIR_SIZE) {
549 pseg = sun4c_get_segmap(vaddr);
550 mmu_entry_pool[pseg].locked = 1;
551 for (ctx = 0; ctx < num_contexts; ctx++)
552 prom_putsegment(ctx, vaddr, pseg);
553 fix_permissions(vaddr, _SUN4C_PAGE_PRIV, _SUN4C_PAGE_NOCACHE);
554 }
555}
556
557static void __init sun4c_init_lock_area(unsigned long start, unsigned long end)
558{
559 int i, ctx;
560
561 while (start < end) {
562 for (i = 0; i < invalid_segment; i++)
563 if (!mmu_entry_pool[i].locked)
564 break;
565 mmu_entry_pool[i].locked = 1;
566 sun4c_init_clean_segmap(i);
567 for (ctx = 0; ctx < num_contexts; ctx++)
568 prom_putsegment(ctx, start, mmu_entry_pool[i].pseg);
569 start += SUN4C_REAL_PGDIR_SIZE;
570 }
571}
572
573/* Don't change this struct without changing entry.S. This is used
574 * in the in-window kernel fault handler, and you don't want to mess
575 * with that. (See sun4c_fault in entry.S).
576 */
577struct sun4c_mmu_ring {
578 struct sun4c_mmu_entry ringhd;
579 int num_entries;
580};
581
582static struct sun4c_mmu_ring sun4c_context_ring[SUN4C_MAX_CONTEXTS]; /* used user entries */
583static struct sun4c_mmu_ring sun4c_ufree_ring; /* free user entries */
584static struct sun4c_mmu_ring sun4c_ulru_ring; /* LRU user entries */
585struct sun4c_mmu_ring sun4c_kernel_ring; /* used kernel entries */
586struct sun4c_mmu_ring sun4c_kfree_ring; /* free kernel entries */
587
588static inline void sun4c_init_rings(void)
589{
590 int i;
591
592 for (i = 0; i < SUN4C_MAX_CONTEXTS; i++) {
593 sun4c_context_ring[i].ringhd.next =
594 sun4c_context_ring[i].ringhd.prev =
595 &sun4c_context_ring[i].ringhd;
596 sun4c_context_ring[i].num_entries = 0;
597 }
598 sun4c_ufree_ring.ringhd.next = sun4c_ufree_ring.ringhd.prev =
599 &sun4c_ufree_ring.ringhd;
600 sun4c_ufree_ring.num_entries = 0;
601 sun4c_ulru_ring.ringhd.lru_next = sun4c_ulru_ring.ringhd.lru_prev =
602 &sun4c_ulru_ring.ringhd;
603 sun4c_ulru_ring.num_entries = 0;
604 sun4c_kernel_ring.ringhd.next = sun4c_kernel_ring.ringhd.prev =
605 &sun4c_kernel_ring.ringhd;
606 sun4c_kernel_ring.num_entries = 0;
607 sun4c_kfree_ring.ringhd.next = sun4c_kfree_ring.ringhd.prev =
608 &sun4c_kfree_ring.ringhd;
609 sun4c_kfree_ring.num_entries = 0;
610}
611
612static void add_ring(struct sun4c_mmu_ring *ring,
613 struct sun4c_mmu_entry *entry)
614{
615 struct sun4c_mmu_entry *head = &ring->ringhd;
616
617 entry->prev = head;
618 (entry->next = head->next)->prev = entry;
619 head->next = entry;
620 ring->num_entries++;
621}
622
623static inline void add_lru(struct sun4c_mmu_entry *entry)
624{
625 struct sun4c_mmu_ring *ring = &sun4c_ulru_ring;
626 struct sun4c_mmu_entry *head = &ring->ringhd;
627
628 entry->lru_next = head;
629 (entry->lru_prev = head->lru_prev)->lru_next = entry;
630 head->lru_prev = entry;
631}
632
633static void add_ring_ordered(struct sun4c_mmu_ring *ring,
634 struct sun4c_mmu_entry *entry)
635{
636 struct sun4c_mmu_entry *head = &ring->ringhd;
637 unsigned long addr = entry->vaddr;
638
639 while ((head->next != &ring->ringhd) && (head->next->vaddr < addr))
640 head = head->next;
641
642 entry->prev = head;
643 (entry->next = head->next)->prev = entry;
644 head->next = entry;
645 ring->num_entries++;
646
647 add_lru(entry);
648}
649
650static inline void remove_ring(struct sun4c_mmu_ring *ring,
651 struct sun4c_mmu_entry *entry)
652{
653 struct sun4c_mmu_entry *next = entry->next;
654
655 (next->prev = entry->prev)->next = next;
656 ring->num_entries--;
657}
658
659static void remove_lru(struct sun4c_mmu_entry *entry)
660{
661 struct sun4c_mmu_entry *next = entry->lru_next;
662
663 (next->lru_prev = entry->lru_prev)->lru_next = next;
664}
665
666static void free_user_entry(int ctx, struct sun4c_mmu_entry *entry)
667{
668 remove_ring(sun4c_context_ring+ctx, entry);
669 remove_lru(entry);
670 add_ring(&sun4c_ufree_ring, entry);
671}
672
673static void free_kernel_entry(struct sun4c_mmu_entry *entry,
674 struct sun4c_mmu_ring *ring)
675{
676 remove_ring(ring, entry);
677 add_ring(&sun4c_kfree_ring, entry);
678}
679
680static void __init sun4c_init_fill_kernel_ring(int howmany)
681{
682 int i;
683
684 while (howmany) {
685 for (i = 0; i < invalid_segment; i++)
686 if (!mmu_entry_pool[i].locked)
687 break;
688 mmu_entry_pool[i].locked = 1;
689 sun4c_init_clean_segmap(i);
690 add_ring(&sun4c_kfree_ring, &mmu_entry_pool[i]);
691 howmany--;
692 }
693}
694
695static void __init sun4c_init_fill_user_ring(void)
696{
697 int i;
698
699 for (i = 0; i < invalid_segment; i++) {
700 if (mmu_entry_pool[i].locked)
701 continue;
702 sun4c_init_clean_segmap(i);
703 add_ring(&sun4c_ufree_ring, &mmu_entry_pool[i]);
704 }
705}
706
707static void sun4c_kernel_unmap(struct sun4c_mmu_entry *kentry)
708{
709 int savectx, ctx;
710
711 savectx = sun4c_get_context();
712 for (ctx = 0; ctx < num_contexts; ctx++) {
713 sun4c_set_context(ctx);
714 sun4c_put_segmap(kentry->vaddr, invalid_segment);
715 }
716 sun4c_set_context(savectx);
717}
718
719static void sun4c_kernel_map(struct sun4c_mmu_entry *kentry)
720{
721 int savectx, ctx;
722
723 savectx = sun4c_get_context();
724 for (ctx = 0; ctx < num_contexts; ctx++) {
725 sun4c_set_context(ctx);
726 sun4c_put_segmap(kentry->vaddr, kentry->pseg);
727 }
728 sun4c_set_context(savectx);
729}
730
731#define sun4c_user_unmap(__entry) \
732 sun4c_put_segmap((__entry)->vaddr, invalid_segment)
733
734static void sun4c_demap_context(struct sun4c_mmu_ring *crp, unsigned char ctx)
735{
736 struct sun4c_mmu_entry *head = &crp->ringhd;
737 unsigned long flags;
738
739 local_irq_save(flags);
740 if (head->next != head) {
741 struct sun4c_mmu_entry *entry = head->next;
742 int savectx = sun4c_get_context();
743
744 flush_user_windows();
745 sun4c_set_context(ctx);
746 sun4c_flush_context();
747 do {
748 struct sun4c_mmu_entry *next = entry->next;
749
750 sun4c_user_unmap(entry);
751 free_user_entry(ctx, entry);
752
753 entry = next;
754 } while (entry != head);
755 sun4c_set_context(savectx);
756 }
757 local_irq_restore(flags);
758}
759
760static int sun4c_user_taken_entries; /* This is how much we have. */
761static int max_user_taken_entries; /* This limits us and prevents deadlock. */
762
763static struct sun4c_mmu_entry *sun4c_kernel_strategy(void)
764{
765 struct sun4c_mmu_entry *this_entry;
766
767 /* If some are free, return first one. */
768 if (sun4c_kfree_ring.num_entries) {
769 this_entry = sun4c_kfree_ring.ringhd.next;
770 return this_entry;
771 }
772
773 /* Else free one up. */
774 this_entry = sun4c_kernel_ring.ringhd.prev;
775 sun4c_flush_segment(this_entry->vaddr);
776 sun4c_kernel_unmap(this_entry);
777 free_kernel_entry(this_entry, &sun4c_kernel_ring);
778 this_entry = sun4c_kfree_ring.ringhd.next;
779
780 return this_entry;
781}
782
783/* Using this method to free up mmu entries eliminates a lot of
784 * potential races since we have a kernel that incurs tlb
785 * replacement faults. There may be performance penalties.
786 *
787 * NOTE: Must be called with interrupts disabled.
788 */
789static struct sun4c_mmu_entry *sun4c_user_strategy(void)
790{
791 struct sun4c_mmu_entry *entry;
792 unsigned char ctx;
793 int savectx;
794
795 /* If some are free, return first one. */
796 if (sun4c_ufree_ring.num_entries) {
797 entry = sun4c_ufree_ring.ringhd.next;
798 goto unlink_out;
799 }
800
801 if (sun4c_user_taken_entries) {
802 entry = sun4c_kernel_strategy();
803 sun4c_user_taken_entries--;
804 goto kunlink_out;
805 }
806
807 /* Grab from the beginning of the LRU list. */
808 entry = sun4c_ulru_ring.ringhd.lru_next;
809 ctx = entry->ctx;
810
811 savectx = sun4c_get_context();
812 flush_user_windows();
813 sun4c_set_context(ctx);
814 sun4c_flush_segment(entry->vaddr);
815 sun4c_user_unmap(entry);
816 remove_ring(sun4c_context_ring + ctx, entry);
817 remove_lru(entry);
818 sun4c_set_context(savectx);
819
820 return entry;
821
822unlink_out:
823 remove_ring(&sun4c_ufree_ring, entry);
824 return entry;
825kunlink_out:
826 remove_ring(&sun4c_kfree_ring, entry);
827 return entry;
828}
829
830/* NOTE: Must be called with interrupts disabled. */
831void sun4c_grow_kernel_ring(void)
832{
833 struct sun4c_mmu_entry *entry;
834
835 /* Prevent deadlock condition. */
836 if (sun4c_user_taken_entries >= max_user_taken_entries)
837 return;
838
839 if (sun4c_ufree_ring.num_entries) {
840 entry = sun4c_ufree_ring.ringhd.next;
841 remove_ring(&sun4c_ufree_ring, entry);
842 add_ring(&sun4c_kfree_ring, entry);
843 sun4c_user_taken_entries++;
844 }
845}
846
847/* 2 page buckets for task struct and kernel stack allocation.
848 *
849 * TASK_STACK_BEGIN
850 * bucket[0]
851 * bucket[1]
852 * [ ... ]
853 * bucket[NR_TASK_BUCKETS-1]
854 * TASK_STACK_BEGIN + (sizeof(struct task_bucket) * NR_TASK_BUCKETS)
855 *
856 * Each slot looks like:
857 *
858 * page 1 -- task struct + beginning of kernel stack
859 * page 2 -- rest of kernel stack
860 */
861
862union task_union *sun4c_bucket[NR_TASK_BUCKETS];
863
864static int sun4c_lowbucket_avail;
865
866#define BUCKET_EMPTY ((union task_union *) 0)
867#define BUCKET_SHIFT (PAGE_SHIFT + 1) /* log2(sizeof(struct task_bucket)) */
868#define BUCKET_SIZE (1 << BUCKET_SHIFT)
869#define BUCKET_NUM(addr) ((((addr) - SUN4C_LOCK_VADDR) >> BUCKET_SHIFT))
870#define BUCKET_ADDR(num) (((num) << BUCKET_SHIFT) + SUN4C_LOCK_VADDR)
871#define BUCKET_PTE(page) \
872 ((((page) - PAGE_OFFSET) >> PAGE_SHIFT) | pgprot_val(SUN4C_PAGE_KERNEL))
873#define BUCKET_PTE_PAGE(pte) \
874 (PAGE_OFFSET + (((pte) & SUN4C_PFN_MASK) << PAGE_SHIFT))
875
876static void get_locked_segment(unsigned long addr)
877{
878 struct sun4c_mmu_entry *stolen;
879 unsigned long flags;
880
881 local_irq_save(flags);
882 addr &= SUN4C_REAL_PGDIR_MASK;
883 stolen = sun4c_user_strategy();
884 max_user_taken_entries--;
885 stolen->vaddr = addr;
886 flush_user_windows();
887 sun4c_kernel_map(stolen);
888 local_irq_restore(flags);
889}
890
891static void free_locked_segment(unsigned long addr)
892{
893 struct sun4c_mmu_entry *entry;
894 unsigned long flags;
895 unsigned char pseg;
896
897 local_irq_save(flags);
898 addr &= SUN4C_REAL_PGDIR_MASK;
899 pseg = sun4c_get_segmap(addr);
900 entry = &mmu_entry_pool[pseg];
901
902 flush_user_windows();
903 sun4c_flush_segment(addr);
904 sun4c_kernel_unmap(entry);
905 add_ring(&sun4c_ufree_ring, entry);
906 max_user_taken_entries++;
907 local_irq_restore(flags);
908}
909
910static inline void garbage_collect(int entry)
911{
912 int start, end;
913
914 /* 32 buckets per segment... */
915 entry &= ~31;
916 start = entry;
917 for (end = (start + 32); start < end; start++)
918 if (sun4c_bucket[start] != BUCKET_EMPTY)
919 return;
920
921 /* Entire segment empty, release it. */
922 free_locked_segment(BUCKET_ADDR(entry));
923}
924
925static struct thread_info *sun4c_alloc_thread_info_node(int node)
926{
927 unsigned long addr, pages;
928 int entry;
929
930 pages = __get_free_pages(GFP_KERNEL, THREAD_INFO_ORDER);
931 if (!pages)
932 return NULL;
933
934 for (entry = sun4c_lowbucket_avail; entry < NR_TASK_BUCKETS; entry++)
935 if (sun4c_bucket[entry] == BUCKET_EMPTY)
936 break;
937 if (entry == NR_TASK_BUCKETS) {
938 free_pages(pages, THREAD_INFO_ORDER);
939 return NULL;
940 }
941 if (entry >= sun4c_lowbucket_avail)
942 sun4c_lowbucket_avail = entry + 1;
943
944 addr = BUCKET_ADDR(entry);
945 sun4c_bucket[entry] = (union task_union *) addr;
946 if(sun4c_get_segmap(addr) == invalid_segment)
947 get_locked_segment(addr);
948
949 /* We are changing the virtual color of the page(s)
950 * so we must flush the cache to guarantee consistency.
951 */
952 sun4c_flush_page(pages);
953 sun4c_flush_page(pages + PAGE_SIZE);
954
955 sun4c_put_pte(addr, BUCKET_PTE(pages));
956 sun4c_put_pte(addr + PAGE_SIZE, BUCKET_PTE(pages + PAGE_SIZE));
957
958#ifdef CONFIG_DEBUG_STACK_USAGE
959 memset((void *)addr, 0, PAGE_SIZE << THREAD_INFO_ORDER);
960#endif /* DEBUG_STACK_USAGE */
961
962 return (struct thread_info *) addr;
963}
964
965static void sun4c_free_thread_info(struct thread_info *ti)
966{
967 unsigned long tiaddr = (unsigned long) ti;
968 unsigned long pages = BUCKET_PTE_PAGE(sun4c_get_pte(tiaddr));
969 int entry = BUCKET_NUM(tiaddr);
970
971 /* We are deleting a mapping, so the flush here is mandatory. */
972 sun4c_flush_page(tiaddr);
973 sun4c_flush_page(tiaddr + PAGE_SIZE);
974
975 sun4c_put_pte(tiaddr, 0);
976 sun4c_put_pte(tiaddr + PAGE_SIZE, 0);
977
978 sun4c_bucket[entry] = BUCKET_EMPTY;
979 if (entry < sun4c_lowbucket_avail)
980 sun4c_lowbucket_avail = entry;
981
982 free_pages(pages, THREAD_INFO_ORDER);
983 garbage_collect(entry);
984}
985
986static void __init sun4c_init_buckets(void)
987{
988 int entry;
989
990 if (sizeof(union thread_union) != (PAGE_SIZE << THREAD_INFO_ORDER)) {
991 extern void thread_info_size_is_bolixed_pete(void);
992 thread_info_size_is_bolixed_pete();
993 }
994
995 for (entry = 0; entry < NR_TASK_BUCKETS; entry++)
996 sun4c_bucket[entry] = BUCKET_EMPTY;
997 sun4c_lowbucket_avail = 0;
998}
999
1000static unsigned long sun4c_iobuffer_start;
1001static unsigned long sun4c_iobuffer_end;
1002static unsigned long sun4c_iobuffer_high;
1003static unsigned long *sun4c_iobuffer_map;
1004static int iobuffer_map_size;
1005
1006/*
1007 * Alias our pages so they do not cause a trap.
1008 * Also one page may be aliased into several I/O areas and we may
1009 * finish these I/O separately.
1010 */
1011static char *sun4c_lockarea(char *vaddr, unsigned long size)
1012{
1013 unsigned long base, scan;
1014 unsigned long npages;
1015 unsigned long vpage;
1016 unsigned long pte;
1017 unsigned long apage;
1018 unsigned long high;
1019 unsigned long flags;
1020
1021 npages = (((unsigned long)vaddr & ~PAGE_MASK) +
1022 size + (PAGE_SIZE-1)) >> PAGE_SHIFT;
1023
1024 local_irq_save(flags);
1025 base = bitmap_find_next_zero_area(sun4c_iobuffer_map, iobuffer_map_size,
1026 0, npages, 0);
1027 if (base >= iobuffer_map_size)
1028 goto abend;
1029
1030 high = ((base + npages) << PAGE_SHIFT) + sun4c_iobuffer_start;
1031 high = SUN4C_REAL_PGDIR_ALIGN(high);
1032 while (high > sun4c_iobuffer_high) {
1033 get_locked_segment(sun4c_iobuffer_high);
1034 sun4c_iobuffer_high += SUN4C_REAL_PGDIR_SIZE;
1035 }
1036
1037 vpage = ((unsigned long) vaddr) & PAGE_MASK;
1038 for (scan = base; scan < base+npages; scan++) {
1039 pte = ((vpage-PAGE_OFFSET) >> PAGE_SHIFT);
1040 pte |= pgprot_val(SUN4C_PAGE_KERNEL);
1041 pte |= _SUN4C_PAGE_NOCACHE;
1042 set_bit(scan, sun4c_iobuffer_map);
1043 apage = (scan << PAGE_SHIFT) + sun4c_iobuffer_start;
1044
1045 /* Flush original mapping so we see the right things later. */
1046 sun4c_flush_page(vpage);
1047
1048 sun4c_put_pte(apage, pte);
1049 vpage += PAGE_SIZE;
1050 }
1051 local_irq_restore(flags);
1052 return (char *) ((base << PAGE_SHIFT) + sun4c_iobuffer_start +
1053 (((unsigned long) vaddr) & ~PAGE_MASK));
1054
1055abend:
1056 local_irq_restore(flags);
1057 printk("DMA vaddr=0x%p size=%08lx\n", vaddr, size);
1058 panic("Out of iobuffer table");
1059 return NULL;
1060}
1061
1062static void sun4c_unlockarea(char *vaddr, unsigned long size)
1063{
1064 unsigned long vpage, npages;
1065 unsigned long flags;
1066 int scan, high;
1067
1068 vpage = (unsigned long)vaddr & PAGE_MASK;
1069 npages = (((unsigned long)vaddr & ~PAGE_MASK) +
1070 size + (PAGE_SIZE-1)) >> PAGE_SHIFT;
1071
1072 local_irq_save(flags);
1073 while (npages != 0) {
1074 --npages;
1075
1076 /* This mapping is marked non-cachable, no flush necessary. */
1077 sun4c_put_pte(vpage, 0);
1078 clear_bit((vpage - sun4c_iobuffer_start) >> PAGE_SHIFT,
1079 sun4c_iobuffer_map);
1080 vpage += PAGE_SIZE;
1081 }
1082
1083 /* garbage collect */
1084 scan = (sun4c_iobuffer_high - sun4c_iobuffer_start) >> PAGE_SHIFT;
1085 while (scan >= 0 && !sun4c_iobuffer_map[scan >> 5])
1086 scan -= 32;
1087 scan += 32;
1088 high = sun4c_iobuffer_start + (scan << PAGE_SHIFT);
1089 high = SUN4C_REAL_PGDIR_ALIGN(high) + SUN4C_REAL_PGDIR_SIZE;
1090 while (high < sun4c_iobuffer_high) {
1091 sun4c_iobuffer_high -= SUN4C_REAL_PGDIR_SIZE;
1092 free_locked_segment(sun4c_iobuffer_high);
1093 }
1094 local_irq_restore(flags);
1095}
1096
1097/* Note the scsi code at init time passes to here buffers
1098 * which sit on the kernel stack, those are already locked
1099 * by implication and fool the page locking code above
1100 * if passed to by mistake.
1101 */
1102static __u32 sun4c_get_scsi_one(struct device *dev, char *bufptr, unsigned long len)
1103{
1104 unsigned long page;
1105
1106 page = ((unsigned long)bufptr) & PAGE_MASK;
1107 if (!virt_addr_valid(page)) {
1108 sun4c_flush_page(page);
1109 return (__u32)bufptr; /* already locked */
1110 }
1111 return (__u32)sun4c_lockarea(bufptr, len);
1112}
1113
1114static void sun4c_get_scsi_sgl(struct device *dev, struct scatterlist *sg, int sz)
1115{
1116 while (sz != 0) {
1117 --sz;
1118 sg->dma_address = (__u32)sun4c_lockarea(sg_virt(sg), sg->length);
1119 sg->dma_length = sg->length;
1120 sg = sg_next(sg);
1121 }
1122}
1123
1124static void sun4c_release_scsi_one(struct device *dev, __u32 bufptr, unsigned long len)
1125{
1126 if (bufptr < sun4c_iobuffer_start)
1127 return; /* On kernel stack or similar, see above */
1128 sun4c_unlockarea((char *)bufptr, len);
1129}
1130
1131static void sun4c_release_scsi_sgl(struct device *dev, struct scatterlist *sg, int sz)
1132{
1133 while (sz != 0) {
1134 --sz;
1135 sun4c_unlockarea((char *)sg->dma_address, sg->length);
1136 sg = sg_next(sg);
1137 }
1138}
1139
1140#define TASK_ENTRY_SIZE BUCKET_SIZE /* see above */
1141#define LONG_ALIGN(x) (((x)+(sizeof(long))-1)&~((sizeof(long))-1))
1142
1143struct vm_area_struct sun4c_kstack_vma;
1144
1145static void __init sun4c_init_lock_areas(void)
1146{
1147 unsigned long sun4c_taskstack_start;
1148 unsigned long sun4c_taskstack_end;
1149 int bitmap_size;
1150
1151 sun4c_init_buckets();
1152 sun4c_taskstack_start = SUN4C_LOCK_VADDR;
1153 sun4c_taskstack_end = (sun4c_taskstack_start +
1154 (TASK_ENTRY_SIZE * NR_TASK_BUCKETS));
1155 if (sun4c_taskstack_end >= SUN4C_LOCK_END) {
1156 prom_printf("Too many tasks, decrease NR_TASK_BUCKETS please.\n");
1157 prom_halt();
1158 }
1159
1160 sun4c_iobuffer_start = sun4c_iobuffer_high =
1161 SUN4C_REAL_PGDIR_ALIGN(sun4c_taskstack_end);
1162 sun4c_iobuffer_end = SUN4C_LOCK_END;
1163 bitmap_size = (sun4c_iobuffer_end - sun4c_iobuffer_start) >> PAGE_SHIFT;
1164 bitmap_size = (bitmap_size + 7) >> 3;
1165 bitmap_size = LONG_ALIGN(bitmap_size);
1166 iobuffer_map_size = bitmap_size << 3;
1167 sun4c_iobuffer_map = __alloc_bootmem(bitmap_size, SMP_CACHE_BYTES, 0UL);
1168 memset((void *) sun4c_iobuffer_map, 0, bitmap_size);
1169
1170 sun4c_kstack_vma.vm_mm = &init_mm;
1171 sun4c_kstack_vma.vm_start = sun4c_taskstack_start;
1172 sun4c_kstack_vma.vm_end = sun4c_taskstack_end;
1173 sun4c_kstack_vma.vm_page_prot = PAGE_SHARED;
1174 sun4c_kstack_vma.vm_flags = VM_READ | VM_WRITE | VM_EXEC;
1175 insert_vm_struct(&init_mm, &sun4c_kstack_vma);
1176}
1177
1178/* Cache flushing on the sun4c. */
1179static void sun4c_flush_cache_all(void)
1180{
1181 unsigned long begin, end;
1182
1183 flush_user_windows();
1184 begin = (KERNBASE + SUN4C_REAL_PGDIR_SIZE);
1185 end = (begin + SUN4C_VAC_SIZE);
1186
1187 if (sun4c_vacinfo.linesize == 32) {
1188 while (begin < end) {
1189 __asm__ __volatile__(
1190 "ld [%0 + 0x00], %%g0\n\t"
1191 "ld [%0 + 0x20], %%g0\n\t"
1192 "ld [%0 + 0x40], %%g0\n\t"
1193 "ld [%0 + 0x60], %%g0\n\t"
1194 "ld [%0 + 0x80], %%g0\n\t"
1195 "ld [%0 + 0xa0], %%g0\n\t"
1196 "ld [%0 + 0xc0], %%g0\n\t"
1197 "ld [%0 + 0xe0], %%g0\n\t"
1198 "ld [%0 + 0x100], %%g0\n\t"
1199 "ld [%0 + 0x120], %%g0\n\t"
1200 "ld [%0 + 0x140], %%g0\n\t"
1201 "ld [%0 + 0x160], %%g0\n\t"
1202 "ld [%0 + 0x180], %%g0\n\t"
1203 "ld [%0 + 0x1a0], %%g0\n\t"
1204 "ld [%0 + 0x1c0], %%g0\n\t"
1205 "ld [%0 + 0x1e0], %%g0\n"
1206 : : "r" (begin));
1207 begin += 512;
1208 }
1209 } else {
1210 while (begin < end) {
1211 __asm__ __volatile__(
1212 "ld [%0 + 0x00], %%g0\n\t"
1213 "ld [%0 + 0x10], %%g0\n\t"
1214 "ld [%0 + 0x20], %%g0\n\t"
1215 "ld [%0 + 0x30], %%g0\n\t"
1216 "ld [%0 + 0x40], %%g0\n\t"
1217 "ld [%0 + 0x50], %%g0\n\t"
1218 "ld [%0 + 0x60], %%g0\n\t"
1219 "ld [%0 + 0x70], %%g0\n\t"
1220 "ld [%0 + 0x80], %%g0\n\t"
1221 "ld [%0 + 0x90], %%g0\n\t"
1222 "ld [%0 + 0xa0], %%g0\n\t"
1223 "ld [%0 + 0xb0], %%g0\n\t"
1224 "ld [%0 + 0xc0], %%g0\n\t"
1225 "ld [%0 + 0xd0], %%g0\n\t"
1226 "ld [%0 + 0xe0], %%g0\n\t"
1227 "ld [%0 + 0xf0], %%g0\n"
1228 : : "r" (begin));
1229 begin += 256;
1230 }
1231 }
1232}
1233
1234static void sun4c_flush_cache_mm(struct mm_struct *mm)
1235{
1236 int new_ctx = mm->context;
1237
1238 if (new_ctx != NO_CONTEXT) {
1239 flush_user_windows();
1240
1241 if (sun4c_context_ring[new_ctx].num_entries) {
1242 struct sun4c_mmu_entry *head = &sun4c_context_ring[new_ctx].ringhd;
1243 unsigned long flags;
1244
1245 local_irq_save(flags);
1246 if (head->next != head) {
1247 struct sun4c_mmu_entry *entry = head->next;
1248 int savectx = sun4c_get_context();
1249
1250 sun4c_set_context(new_ctx);
1251 sun4c_flush_context();
1252 do {
1253 struct sun4c_mmu_entry *next = entry->next;
1254
1255 sun4c_user_unmap(entry);
1256 free_user_entry(new_ctx, entry);
1257
1258 entry = next;
1259 } while (entry != head);
1260 sun4c_set_context(savectx);
1261 }
1262 local_irq_restore(flags);
1263 }
1264 }
1265}
1266
1267static void sun4c_flush_cache_range(struct vm_area_struct *vma, unsigned long start, unsigned long end)
1268{
1269 struct mm_struct *mm = vma->vm_mm;
1270 int new_ctx = mm->context;
1271
1272 if (new_ctx != NO_CONTEXT) {
1273 struct sun4c_mmu_entry *head = &sun4c_context_ring[new_ctx].ringhd;
1274 struct sun4c_mmu_entry *entry;
1275 unsigned long flags;
1276
1277 flush_user_windows();
1278
1279 local_irq_save(flags);
1280 /* All user segmap chains are ordered on entry->vaddr. */
1281 for (entry = head->next;
1282 (entry != head) && ((entry->vaddr+SUN4C_REAL_PGDIR_SIZE) < start);
1283 entry = entry->next)
1284 ;
1285
1286 /* Tracing various job mixtures showed that this conditional
1287 * only passes ~35% of the time for most worse case situations,
1288 * therefore we avoid all of this gross overhead ~65% of the time.
1289 */
1290 if ((entry != head) && (entry->vaddr < end)) {
1291 int octx = sun4c_get_context();
1292 sun4c_set_context(new_ctx);
1293
1294 /* At this point, always, (start >= entry->vaddr) and
1295 * (entry->vaddr < end), once the latter condition
1296 * ceases to hold, or we hit the end of the list, we
1297 * exit the loop. The ordering of all user allocated
1298 * segmaps makes this all work out so beautifully.
1299 */
1300 do {
1301 struct sun4c_mmu_entry *next = entry->next;
1302 unsigned long realend;
1303
1304 /* "realstart" is always >= entry->vaddr */
1305 realend = entry->vaddr + SUN4C_REAL_PGDIR_SIZE;
1306 if (end < realend)
1307 realend = end;
1308 if ((realend - entry->vaddr) <= (PAGE_SIZE << 3)) {
1309 unsigned long page = entry->vaddr;
1310 while (page < realend) {
1311 sun4c_flush_page(page);
1312 page += PAGE_SIZE;
1313 }
1314 } else {
1315 sun4c_flush_segment(entry->vaddr);
1316 sun4c_user_unmap(entry);
1317 free_user_entry(new_ctx, entry);
1318 }
1319 entry = next;
1320 } while ((entry != head) && (entry->vaddr < end));
1321 sun4c_set_context(octx);
1322 }
1323 local_irq_restore(flags);
1324 }
1325}
1326
1327static void sun4c_flush_cache_page(struct vm_area_struct *vma, unsigned long page)
1328{
1329 struct mm_struct *mm = vma->vm_mm;
1330 int new_ctx = mm->context;
1331
1332 /* Sun4c has no separate I/D caches so cannot optimize for non
1333 * text page flushes.
1334 */
1335 if (new_ctx != NO_CONTEXT) {
1336 int octx = sun4c_get_context();
1337 unsigned long flags;
1338
1339 flush_user_windows();
1340 local_irq_save(flags);
1341 sun4c_set_context(new_ctx);
1342 sun4c_flush_page(page);
1343 sun4c_set_context(octx);
1344 local_irq_restore(flags);
1345 }
1346}
1347
1348static void sun4c_flush_page_to_ram(unsigned long page)
1349{
1350 unsigned long flags;
1351
1352 local_irq_save(flags);
1353 sun4c_flush_page(page);
1354 local_irq_restore(flags);
1355}
1356
1357/* Sun4c cache is unified, both instructions and data live there, so
1358 * no need to flush the on-stack instructions for new signal handlers.
1359 */
1360static void sun4c_flush_sig_insns(struct mm_struct *mm, unsigned long insn_addr)
1361{
1362}
1363
1364/* TLB flushing on the sun4c. These routines count on the cache
1365 * flushing code to flush the user register windows so that we need
1366 * not do so when we get here.
1367 */
1368
1369static void sun4c_flush_tlb_all(void)
1370{
1371 struct sun4c_mmu_entry *this_entry, *next_entry;
1372 unsigned long flags;
1373 int savectx, ctx;
1374
1375 local_irq_save(flags);
1376 this_entry = sun4c_kernel_ring.ringhd.next;
1377 savectx = sun4c_get_context();
1378 flush_user_windows();
1379 while (sun4c_kernel_ring.num_entries) {
1380 next_entry = this_entry->next;
1381 sun4c_flush_segment(this_entry->vaddr);
1382 for (ctx = 0; ctx < num_contexts; ctx++) {
1383 sun4c_set_context(ctx);
1384 sun4c_put_segmap(this_entry->vaddr, invalid_segment);
1385 }
1386 free_kernel_entry(this_entry, &sun4c_kernel_ring);
1387 this_entry = next_entry;
1388 }
1389 sun4c_set_context(savectx);
1390 local_irq_restore(flags);
1391}
1392
1393static void sun4c_flush_tlb_mm(struct mm_struct *mm)
1394{
1395 int new_ctx = mm->context;
1396
1397 if (new_ctx != NO_CONTEXT) {
1398 struct sun4c_mmu_entry *head = &sun4c_context_ring[new_ctx].ringhd;
1399 unsigned long flags;
1400
1401 local_irq_save(flags);
1402 if (head->next != head) {
1403 struct sun4c_mmu_entry *entry = head->next;
1404 int savectx = sun4c_get_context();
1405
1406 sun4c_set_context(new_ctx);
1407 sun4c_flush_context();
1408 do {
1409 struct sun4c_mmu_entry *next = entry->next;
1410
1411 sun4c_user_unmap(entry);
1412 free_user_entry(new_ctx, entry);
1413
1414 entry = next;
1415 } while (entry != head);
1416 sun4c_set_context(savectx);
1417 }
1418 local_irq_restore(flags);
1419 }
1420}
1421
1422static void sun4c_flush_tlb_range(struct vm_area_struct *vma, unsigned long start, unsigned long end)
1423{
1424 struct mm_struct *mm = vma->vm_mm;
1425 int new_ctx = mm->context;
1426
1427 if (new_ctx != NO_CONTEXT) {
1428 struct sun4c_mmu_entry *head = &sun4c_context_ring[new_ctx].ringhd;
1429 struct sun4c_mmu_entry *entry;
1430 unsigned long flags;
1431
1432 local_irq_save(flags);
1433 /* See commentary in sun4c_flush_cache_range(). */
1434 for (entry = head->next;
1435 (entry != head) && ((entry->vaddr+SUN4C_REAL_PGDIR_SIZE) < start);
1436 entry = entry->next)
1437 ;
1438
1439 if ((entry != head) && (entry->vaddr < end)) {
1440 int octx = sun4c_get_context();
1441
1442 sun4c_set_context(new_ctx);
1443 do {
1444 struct sun4c_mmu_entry *next = entry->next;
1445
1446 sun4c_flush_segment(entry->vaddr);
1447 sun4c_user_unmap(entry);
1448 free_user_entry(new_ctx, entry);
1449
1450 entry = next;
1451 } while ((entry != head) && (entry->vaddr < end));
1452 sun4c_set_context(octx);
1453 }
1454 local_irq_restore(flags);
1455 }
1456}
1457
1458static void sun4c_flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
1459{
1460 struct mm_struct *mm = vma->vm_mm;
1461 int new_ctx = mm->context;
1462
1463 if (new_ctx != NO_CONTEXT) {
1464 int savectx = sun4c_get_context();
1465 unsigned long flags;
1466
1467 local_irq_save(flags);
1468 sun4c_set_context(new_ctx);
1469 page &= PAGE_MASK;
1470 sun4c_flush_page(page);
1471 sun4c_put_pte(page, 0);
1472 sun4c_set_context(savectx);
1473 local_irq_restore(flags);
1474 }
1475}
1476
1477static inline void sun4c_mapioaddr(unsigned long physaddr, unsigned long virt_addr)
1478{
1479 unsigned long page_entry, pg_iobits;
1480
1481 pg_iobits = _SUN4C_PAGE_PRESENT | _SUN4C_READABLE | _SUN4C_WRITEABLE |
1482 _SUN4C_PAGE_IO | _SUN4C_PAGE_NOCACHE;
1483
1484 page_entry = ((physaddr >> PAGE_SHIFT) & SUN4C_PFN_MASK);
1485 page_entry |= ((pg_iobits | _SUN4C_PAGE_PRIV) & ~(_SUN4C_PAGE_PRESENT));
1486 sun4c_put_pte(virt_addr, page_entry);
1487}
1488
1489static void sun4c_mapiorange(unsigned int bus, unsigned long xpa,
1490 unsigned long xva, unsigned int len)
1491{
1492 while (len != 0) {
1493 len -= PAGE_SIZE;
1494 sun4c_mapioaddr(xpa, xva);
1495 xva += PAGE_SIZE;
1496 xpa += PAGE_SIZE;
1497 }
1498}
1499
1500static void sun4c_unmapiorange(unsigned long virt_addr, unsigned int len)
1501{
1502 while (len != 0) {
1503 len -= PAGE_SIZE;
1504 sun4c_put_pte(virt_addr, 0);
1505 virt_addr += PAGE_SIZE;
1506 }
1507}
1508
1509static void sun4c_alloc_context(struct mm_struct *old_mm, struct mm_struct *mm)
1510{
1511 struct ctx_list *ctxp;
1512
1513 ctxp = ctx_free.next;
1514 if (ctxp != &ctx_free) {
1515 remove_from_ctx_list(ctxp);
1516 add_to_used_ctxlist(ctxp);
1517 mm->context = ctxp->ctx_number;
1518 ctxp->ctx_mm = mm;
1519 return;
1520 }
1521 ctxp = ctx_used.next;
1522 if (ctxp->ctx_mm == old_mm)
1523 ctxp = ctxp->next;
1524 remove_from_ctx_list(ctxp);
1525 add_to_used_ctxlist(ctxp);
1526 ctxp->ctx_mm->context = NO_CONTEXT;
1527 ctxp->ctx_mm = mm;
1528 mm->context = ctxp->ctx_number;
1529 sun4c_demap_context(&sun4c_context_ring[ctxp->ctx_number],
1530 ctxp->ctx_number);
1531}
1532
1533/* Switch the current MM context. */
1534static void sun4c_switch_mm(struct mm_struct *old_mm, struct mm_struct *mm, struct task_struct *tsk, int cpu)
1535{
1536 struct ctx_list *ctx;
1537 int dirty = 0;
1538
1539 if (mm->context == NO_CONTEXT) {
1540 dirty = 1;
1541 sun4c_alloc_context(old_mm, mm);
1542 } else {
1543 /* Update the LRU ring of contexts. */
1544 ctx = ctx_list_pool + mm->context;
1545 remove_from_ctx_list(ctx);
1546 add_to_used_ctxlist(ctx);
1547 }
1548 if (dirty || old_mm != mm)
1549 sun4c_set_context(mm->context);
1550}
1551
1552static void sun4c_destroy_context(struct mm_struct *mm)
1553{
1554 struct ctx_list *ctx_old;
1555
1556 if (mm->context != NO_CONTEXT) {
1557 sun4c_demap_context(&sun4c_context_ring[mm->context], mm->context);
1558 ctx_old = ctx_list_pool + mm->context;
1559 remove_from_ctx_list(ctx_old);
1560 add_to_free_ctxlist(ctx_old);
1561 mm->context = NO_CONTEXT;
1562 }
1563}
1564
1565static void sun4c_mmu_info(struct seq_file *m)
1566{
1567 int used_user_entries, i;
1568
1569 used_user_entries = 0;
1570 for (i = 0; i < num_contexts; i++)
1571 used_user_entries += sun4c_context_ring[i].num_entries;
1572
1573 seq_printf(m,
1574 "vacsize\t\t: %d bytes\n"
1575 "vachwflush\t: %s\n"
1576 "vaclinesize\t: %d bytes\n"
1577 "mmuctxs\t\t: %d\n"
1578 "mmupsegs\t: %d\n"
1579 "kernelpsegs\t: %d\n"
1580 "kfreepsegs\t: %d\n"
1581 "usedpsegs\t: %d\n"
1582 "ufreepsegs\t: %d\n"
1583 "user_taken\t: %d\n"
1584 "max_taken\t: %d\n",
1585 sun4c_vacinfo.num_bytes,
1586 (sun4c_vacinfo.do_hwflushes ? "yes" : "no"),
1587 sun4c_vacinfo.linesize,
1588 num_contexts,
1589 (invalid_segment + 1),
1590 sun4c_kernel_ring.num_entries,
1591 sun4c_kfree_ring.num_entries,
1592 used_user_entries,
1593 sun4c_ufree_ring.num_entries,
1594 sun4c_user_taken_entries,
1595 max_user_taken_entries);
1596}
1597
1598/* Nothing below here should touch the mmu hardware nor the mmu_entry
1599 * data structures.
1600 */
1601
1602/* First the functions which the mid-level code uses to directly
1603 * manipulate the software page tables. Some defines since we are
1604 * emulating the i386 page directory layout.
1605 */
1606#define PGD_PRESENT 0x001
1607#define PGD_RW 0x002
1608#define PGD_USER 0x004
1609#define PGD_ACCESSED 0x020
1610#define PGD_DIRTY 0x040
1611#define PGD_TABLE (PGD_PRESENT | PGD_RW | PGD_USER | PGD_ACCESSED | PGD_DIRTY)
1612
1613static void sun4c_set_pte(pte_t *ptep, pte_t pte)
1614{
1615 *ptep = pte;
1616}
1617
1618static void sun4c_pgd_set(pgd_t * pgdp, pmd_t * pmdp)
1619{
1620}
1621
1622static void sun4c_pmd_set(pmd_t * pmdp, pte_t * ptep)
1623{
1624 pmdp->pmdv[0] = PGD_TABLE | (unsigned long) ptep;
1625}
1626
1627static void sun4c_pmd_populate(pmd_t * pmdp, struct page * ptep)
1628{
1629 if (page_address(ptep) == NULL) BUG(); /* No highmem on sun4c */
1630 pmdp->pmdv[0] = PGD_TABLE | (unsigned long) page_address(ptep);
1631}
1632
1633static int sun4c_pte_present(pte_t pte)
1634{
1635 return ((pte_val(pte) & (_SUN4C_PAGE_PRESENT | _SUN4C_PAGE_PRIV)) != 0);
1636}
1637static void sun4c_pte_clear(pte_t *ptep) { *ptep = __pte(0); }
1638
1639static int sun4c_pmd_bad(pmd_t pmd)
1640{
1641 return (((pmd_val(pmd) & ~PAGE_MASK) != PGD_TABLE) ||
1642 (!virt_addr_valid(pmd_val(pmd))));
1643}
1644
1645static int sun4c_pmd_present(pmd_t pmd)
1646{
1647 return ((pmd_val(pmd) & PGD_PRESENT) != 0);
1648}
1649
1650#if 0 /* if PMD takes one word */
1651static void sun4c_pmd_clear(pmd_t *pmdp) { *pmdp = __pmd(0); }
1652#else /* if pmd_t is a longish aggregate */
1653static void sun4c_pmd_clear(pmd_t *pmdp) {
1654 memset((void *)pmdp, 0, sizeof(pmd_t));
1655}
1656#endif
1657
1658static int sun4c_pgd_none(pgd_t pgd) { return 0; }
1659static int sun4c_pgd_bad(pgd_t pgd) { return 0; }
1660static int sun4c_pgd_present(pgd_t pgd) { return 1; }
1661static void sun4c_pgd_clear(pgd_t * pgdp) { }
1662
1663/*
1664 * The following only work if pte_present() is true.
1665 * Undefined behaviour if not..
1666 */
1667static pte_t sun4c_pte_mkwrite(pte_t pte)
1668{
1669 pte = __pte(pte_val(pte) | _SUN4C_PAGE_WRITE);
1670 if (pte_val(pte) & _SUN4C_PAGE_MODIFIED)
1671 pte = __pte(pte_val(pte) | _SUN4C_PAGE_SILENT_WRITE);
1672 return pte;
1673}
1674
1675static pte_t sun4c_pte_mkdirty(pte_t pte)
1676{
1677 pte = __pte(pte_val(pte) | _SUN4C_PAGE_MODIFIED);
1678 if (pte_val(pte) & _SUN4C_PAGE_WRITE)
1679 pte = __pte(pte_val(pte) | _SUN4C_PAGE_SILENT_WRITE);
1680 return pte;
1681}
1682
1683static pte_t sun4c_pte_mkyoung(pte_t pte)
1684{
1685 pte = __pte(pte_val(pte) | _SUN4C_PAGE_ACCESSED);
1686 if (pte_val(pte) & _SUN4C_PAGE_READ)
1687 pte = __pte(pte_val(pte) | _SUN4C_PAGE_SILENT_READ);
1688 return pte;
1689}
1690
1691/*
1692 * Conversion functions: convert a page and protection to a page entry,
1693 * and a page entry and page directory to the page they refer to.
1694 */
1695static pte_t sun4c_mk_pte(struct page *page, pgprot_t pgprot)
1696{
1697 return __pte(page_to_pfn(page) | pgprot_val(pgprot));
1698}
1699
1700static pte_t sun4c_mk_pte_phys(unsigned long phys_page, pgprot_t pgprot)
1701{
1702 return __pte((phys_page >> PAGE_SHIFT) | pgprot_val(pgprot));
1703}
1704
1705static pte_t sun4c_mk_pte_io(unsigned long page, pgprot_t pgprot, int space)
1706{
1707 return __pte(((page - PAGE_OFFSET) >> PAGE_SHIFT) | pgprot_val(pgprot));
1708}
1709
1710static unsigned long sun4c_pte_pfn(pte_t pte)
1711{
1712 return pte_val(pte) & SUN4C_PFN_MASK;
1713}
1714
1715static pte_t sun4c_pgoff_to_pte(unsigned long pgoff)
1716{
1717 return __pte(pgoff | _SUN4C_PAGE_FILE);
1718}
1719
1720static unsigned long sun4c_pte_to_pgoff(pte_t pte)
1721{
1722 return pte_val(pte) & ((1UL << PTE_FILE_MAX_BITS) - 1);
1723}
1724
1725
1726static inline unsigned long sun4c_pmd_page_v(pmd_t pmd)
1727{
1728 return (pmd_val(pmd) & PAGE_MASK);
1729}
1730
1731static struct page *sun4c_pmd_page(pmd_t pmd)
1732{
1733 return virt_to_page(sun4c_pmd_page_v(pmd));
1734}
1735
1736static unsigned long sun4c_pgd_page(pgd_t pgd) { return 0; }
1737
1738/* to find an entry in a page-table-directory */
1739static inline pgd_t *sun4c_pgd_offset(struct mm_struct * mm, unsigned long address)
1740{
1741 return mm->pgd + (address >> SUN4C_PGDIR_SHIFT);
1742}
1743
1744/* Find an entry in the second-level page table.. */
1745static pmd_t *sun4c_pmd_offset(pgd_t * dir, unsigned long address)
1746{
1747 return (pmd_t *) dir;
1748}
1749
1750/* Find an entry in the third-level page table.. */
1751pte_t *sun4c_pte_offset_kernel(pmd_t * dir, unsigned long address)
1752{
1753 return (pte_t *) sun4c_pmd_page_v(*dir) +
1754 ((address >> PAGE_SHIFT) & (SUN4C_PTRS_PER_PTE - 1));
1755}
1756
1757static unsigned long sun4c_swp_type(swp_entry_t entry)
1758{
1759 return (entry.val & SUN4C_SWP_TYPE_MASK);
1760}
1761
1762static unsigned long sun4c_swp_offset(swp_entry_t entry)
1763{
1764 return (entry.val >> SUN4C_SWP_OFF_SHIFT) & SUN4C_SWP_OFF_MASK;
1765}
1766
1767static swp_entry_t sun4c_swp_entry(unsigned long type, unsigned long offset)
1768{
1769 return (swp_entry_t) {
1770 (offset & SUN4C_SWP_OFF_MASK) << SUN4C_SWP_OFF_SHIFT
1771 | (type & SUN4C_SWP_TYPE_MASK) };
1772}
1773
1774static void sun4c_free_pte_slow(pte_t *pte)
1775{
1776 free_page((unsigned long)pte);
1777}
1778
1779static void sun4c_free_pgd_slow(pgd_t *pgd)
1780{
1781 free_page((unsigned long)pgd);
1782}
1783
1784static pgd_t *sun4c_get_pgd_fast(void)
1785{
1786 unsigned long *ret;
1787
1788 if ((ret = pgd_quicklist) != NULL) {
1789 pgd_quicklist = (unsigned long *)(*ret);
1790 ret[0] = ret[1];
1791 pgtable_cache_size--;
1792 } else {
1793 pgd_t *init;
1794
1795 ret = (unsigned long *)__get_free_page(GFP_KERNEL);
1796 memset (ret, 0, (KERNBASE / SUN4C_PGDIR_SIZE) * sizeof(pgd_t));
1797 init = sun4c_pgd_offset(&init_mm, 0);
1798 memcpy (((pgd_t *)ret) + USER_PTRS_PER_PGD, init + USER_PTRS_PER_PGD,
1799 (PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t));
1800 }
1801 return (pgd_t *)ret;
1802}
1803
1804static void sun4c_free_pgd_fast(pgd_t *pgd)
1805{
1806 *(unsigned long *)pgd = (unsigned long) pgd_quicklist;
1807 pgd_quicklist = (unsigned long *) pgd;
1808 pgtable_cache_size++;
1809}
1810
1811
1812static inline pte_t *
1813sun4c_pte_alloc_one_fast(struct mm_struct *mm, unsigned long address)
1814{
1815 unsigned long *ret;
1816
1817 if ((ret = (unsigned long *)pte_quicklist) != NULL) {
1818 pte_quicklist = (unsigned long *)(*ret);
1819 ret[0] = ret[1];
1820 pgtable_cache_size--;
1821 }
1822 return (pte_t *)ret;
1823}
1824
1825static pte_t *sun4c_pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address)
1826{
1827 pte_t *pte;
1828
1829 if ((pte = sun4c_pte_alloc_one_fast(mm, address)) != NULL)
1830 return pte;
1831
1832 pte = (pte_t *)get_zeroed_page(GFP_KERNEL|__GFP_REPEAT);
1833 return pte;
1834}
1835
1836static pgtable_t sun4c_pte_alloc_one(struct mm_struct *mm, unsigned long address)
1837{
1838 pte_t *pte;
1839 struct page *page;
1840
1841 pte = sun4c_pte_alloc_one_kernel(mm, address);
1842 if (pte == NULL)
1843 return NULL;
1844 page = virt_to_page(pte);
1845 pgtable_page_ctor(page);
1846 return page;
1847}
1848
1849static inline void sun4c_free_pte_fast(pte_t *pte)
1850{
1851 *(unsigned long *)pte = (unsigned long) pte_quicklist;
1852 pte_quicklist = (unsigned long *) pte;
1853 pgtable_cache_size++;
1854}
1855
1856static void sun4c_pte_free(pgtable_t pte)
1857{
1858 pgtable_page_dtor(pte);
1859 sun4c_free_pte_fast(page_address(pte));
1860}
1861
1862/*
1863 * allocating and freeing a pmd is trivial: the 1-entry pmd is
1864 * inside the pgd, so has no extra memory associated with it.
1865 */
1866static pmd_t *sun4c_pmd_alloc_one(struct mm_struct *mm, unsigned long address)
1867{
1868 BUG();
1869 return NULL;
1870}
1871
1872static void sun4c_free_pmd_fast(pmd_t * pmd) { }
1873
1874static void sun4c_check_pgt_cache(int low, int high)
1875{
1876 if (pgtable_cache_size > high) {
1877 do {
1878 if (pgd_quicklist)
1879 sun4c_free_pgd_slow(sun4c_get_pgd_fast());
1880 if (pte_quicklist)
1881 sun4c_free_pte_slow(sun4c_pte_alloc_one_fast(NULL, 0));
1882 } while (pgtable_cache_size > low);
1883 }
1884}
1885
1886/* An experiment, turn off by default for now... -DaveM */
1887#define SUN4C_PRELOAD_PSEG
1888
1889void sun4c_update_mmu_cache(struct vm_area_struct *vma, unsigned long address, pte_t *ptep)
1890{
1891 unsigned long flags;
1892 int pseg;
1893
1894 if (vma->vm_mm->context == NO_CONTEXT)
1895 return;
1896
1897 local_irq_save(flags);
1898 address &= PAGE_MASK;
1899 if ((pseg = sun4c_get_segmap(address)) == invalid_segment) {
1900 struct sun4c_mmu_entry *entry = sun4c_user_strategy();
1901 struct mm_struct *mm = vma->vm_mm;
1902 unsigned long start, end;
1903
1904 entry->vaddr = start = (address & SUN4C_REAL_PGDIR_MASK);
1905 entry->ctx = mm->context;
1906 add_ring_ordered(sun4c_context_ring + mm->context, entry);
1907 sun4c_put_segmap(entry->vaddr, entry->pseg);
1908 end = start + SUN4C_REAL_PGDIR_SIZE;
1909 while (start < end) {
1910#ifdef SUN4C_PRELOAD_PSEG
1911 pgd_t *pgdp = sun4c_pgd_offset(mm, start);
1912 pte_t *ptep;
1913
1914 if (!pgdp)
1915 goto no_mapping;
1916 ptep = sun4c_pte_offset_kernel((pmd_t *) pgdp, start);
1917 if (!ptep || !(pte_val(*ptep) & _SUN4C_PAGE_PRESENT))
1918 goto no_mapping;
1919 sun4c_put_pte(start, pte_val(*ptep));
1920 goto next;
1921
1922 no_mapping:
1923#endif
1924 sun4c_put_pte(start, 0);
1925#ifdef SUN4C_PRELOAD_PSEG
1926 next:
1927#endif
1928 start += PAGE_SIZE;
1929 }
1930#ifndef SUN4C_PRELOAD_PSEG
1931 sun4c_put_pte(address, pte_val(*ptep));
1932#endif
1933 local_irq_restore(flags);
1934 return;
1935 } else {
1936 struct sun4c_mmu_entry *entry = &mmu_entry_pool[pseg];
1937
1938 remove_lru(entry);
1939 add_lru(entry);
1940 }
1941
1942 sun4c_put_pte(address, pte_val(*ptep));
1943 local_irq_restore(flags);
1944}
1945
1946extern void sparc_context_init(int);
1947extern unsigned long bootmem_init(unsigned long *pages_avail);
1948extern unsigned long last_valid_pfn;
1949
1950void __init sun4c_paging_init(void)
1951{
1952 int i, cnt;
1953 unsigned long kernel_end, vaddr;
1954 extern struct resource sparc_iomap;
1955 unsigned long end_pfn, pages_avail;
1956
1957 kernel_end = (unsigned long) &_end;
1958 kernel_end = SUN4C_REAL_PGDIR_ALIGN(kernel_end);
1959
1960 pages_avail = 0;
1961 last_valid_pfn = bootmem_init(&pages_avail);
1962 end_pfn = last_valid_pfn;
1963
1964 sun4c_probe_mmu();
1965 invalid_segment = (num_segmaps - 1);
1966 sun4c_init_mmu_entry_pool();
1967 sun4c_init_rings();
1968 sun4c_init_map_kernelprom(kernel_end);
1969 sun4c_init_clean_mmu(kernel_end);
1970 sun4c_init_fill_kernel_ring(SUN4C_KERNEL_BUCKETS);
1971 sun4c_init_lock_area(sparc_iomap.start, IOBASE_END);
1972 sun4c_init_lock_area(DVMA_VADDR, DVMA_END);
1973 sun4c_init_lock_areas();
1974 sun4c_init_fill_user_ring();
1975
1976 sun4c_set_context(0);
1977 memset(swapper_pg_dir, 0, PAGE_SIZE);
1978 memset(pg0, 0, PAGE_SIZE);
1979 memset(pg1, 0, PAGE_SIZE);
1980 memset(pg2, 0, PAGE_SIZE);
1981 memset(pg3, 0, PAGE_SIZE);
1982
1983 /* Save work later. */
1984 vaddr = VMALLOC_START;
1985 swapper_pg_dir[vaddr>>SUN4C_PGDIR_SHIFT] = __pgd(PGD_TABLE | (unsigned long) pg0);
1986 vaddr += SUN4C_PGDIR_SIZE;
1987 swapper_pg_dir[vaddr>>SUN4C_PGDIR_SHIFT] = __pgd(PGD_TABLE | (unsigned long) pg1);
1988 vaddr += SUN4C_PGDIR_SIZE;
1989 swapper_pg_dir[vaddr>>SUN4C_PGDIR_SHIFT] = __pgd(PGD_TABLE | (unsigned long) pg2);
1990 vaddr += SUN4C_PGDIR_SIZE;
1991 swapper_pg_dir[vaddr>>SUN4C_PGDIR_SHIFT] = __pgd(PGD_TABLE | (unsigned long) pg3);
1992 sun4c_init_ss2_cache_bug();
1993 sparc_context_init(num_contexts);
1994
1995 {
1996 unsigned long zones_size[MAX_NR_ZONES];
1997 unsigned long zholes_size[MAX_NR_ZONES];
1998 unsigned long npages;
1999 int znum;
2000
2001 for (znum = 0; znum < MAX_NR_ZONES; znum++)
2002 zones_size[znum] = zholes_size[znum] = 0;
2003
2004 npages = max_low_pfn - pfn_base;
2005
2006 zones_size[ZONE_DMA] = npages;
2007 zholes_size[ZONE_DMA] = npages - pages_avail;
2008
2009 npages = highend_pfn - max_low_pfn;
2010 zones_size[ZONE_HIGHMEM] = npages;
2011 zholes_size[ZONE_HIGHMEM] = npages - calc_highpages();
2012
2013 free_area_init_node(0, zones_size, pfn_base, zholes_size);
2014 }
2015
2016 cnt = 0;
2017 for (i = 0; i < num_segmaps; i++)
2018 if (mmu_entry_pool[i].locked)
2019 cnt++;
2020
2021 max_user_taken_entries = num_segmaps - cnt - 40 - 1;
2022
2023 printk("SUN4C: %d mmu entries for the kernel\n", cnt);
2024}
2025
2026static pgprot_t sun4c_pgprot_noncached(pgprot_t prot)
2027{
2028 prot |= __pgprot(_SUN4C_PAGE_IO | _SUN4C_PAGE_NOCACHE);
2029
2030 return prot;
2031}
2032
2033/* Load up routines and constants for sun4c mmu */
2034void __init ld_mmu_sun4c(void)
2035{
2036 extern void ___xchg32_sun4c(void);
2037
2038 printk("Loading sun4c MMU routines\n");
2039
2040 /* First the constants */
2041 BTFIXUPSET_SIMM13(pgdir_shift, SUN4C_PGDIR_SHIFT);
2042 BTFIXUPSET_SETHI(pgdir_size, SUN4C_PGDIR_SIZE);
2043 BTFIXUPSET_SETHI(pgdir_mask, SUN4C_PGDIR_MASK);
2044
2045 BTFIXUPSET_SIMM13(ptrs_per_pmd, SUN4C_PTRS_PER_PMD);
2046 BTFIXUPSET_SIMM13(ptrs_per_pgd, SUN4C_PTRS_PER_PGD);
2047 BTFIXUPSET_SIMM13(user_ptrs_per_pgd, KERNBASE / SUN4C_PGDIR_SIZE);
2048
2049 BTFIXUPSET_INT(page_none, pgprot_val(SUN4C_PAGE_NONE));
2050 PAGE_SHARED = pgprot_val(SUN4C_PAGE_SHARED);
2051 BTFIXUPSET_INT(page_copy, pgprot_val(SUN4C_PAGE_COPY));
2052 BTFIXUPSET_INT(page_readonly, pgprot_val(SUN4C_PAGE_READONLY));
2053 BTFIXUPSET_INT(page_kernel, pgprot_val(SUN4C_PAGE_KERNEL));
2054 page_kernel = pgprot_val(SUN4C_PAGE_KERNEL);
2055
2056 /* Functions */
2057 BTFIXUPSET_CALL(pgprot_noncached, sun4c_pgprot_noncached, BTFIXUPCALL_NORM);
2058 BTFIXUPSET_CALL(___xchg32, ___xchg32_sun4c, BTFIXUPCALL_NORM);
2059 BTFIXUPSET_CALL(do_check_pgt_cache, sun4c_check_pgt_cache, BTFIXUPCALL_NORM);
2060
2061 BTFIXUPSET_CALL(flush_cache_all, sun4c_flush_cache_all, BTFIXUPCALL_NORM);
2062
2063 if (sun4c_vacinfo.do_hwflushes) {
2064 BTFIXUPSET_CALL(sun4c_flush_page, sun4c_flush_page_hw, BTFIXUPCALL_NORM);
2065 BTFIXUPSET_CALL(sun4c_flush_segment, sun4c_flush_segment_hw, BTFIXUPCALL_NORM);
2066 BTFIXUPSET_CALL(sun4c_flush_context, sun4c_flush_context_hw, BTFIXUPCALL_NORM);
2067 } else {
2068 BTFIXUPSET_CALL(sun4c_flush_page, sun4c_flush_page_sw, BTFIXUPCALL_NORM);
2069 BTFIXUPSET_CALL(sun4c_flush_segment, sun4c_flush_segment_sw, BTFIXUPCALL_NORM);
2070 BTFIXUPSET_CALL(sun4c_flush_context, sun4c_flush_context_sw, BTFIXUPCALL_NORM);
2071 }
2072
2073 BTFIXUPSET_CALL(flush_tlb_mm, sun4c_flush_tlb_mm, BTFIXUPCALL_NORM);
2074 BTFIXUPSET_CALL(flush_cache_mm, sun4c_flush_cache_mm, BTFIXUPCALL_NORM);
2075 BTFIXUPSET_CALL(destroy_context, sun4c_destroy_context, BTFIXUPCALL_NORM);
2076 BTFIXUPSET_CALL(switch_mm, sun4c_switch_mm, BTFIXUPCALL_NORM);
2077 BTFIXUPSET_CALL(flush_cache_page, sun4c_flush_cache_page, BTFIXUPCALL_NORM);
2078 BTFIXUPSET_CALL(flush_tlb_page, sun4c_flush_tlb_page, BTFIXUPCALL_NORM);
2079 BTFIXUPSET_CALL(flush_tlb_range, sun4c_flush_tlb_range, BTFIXUPCALL_NORM);
2080 BTFIXUPSET_CALL(flush_cache_range, sun4c_flush_cache_range, BTFIXUPCALL_NORM);
2081 BTFIXUPSET_CALL(__flush_page_to_ram, sun4c_flush_page_to_ram, BTFIXUPCALL_NORM);
2082 BTFIXUPSET_CALL(flush_tlb_all, sun4c_flush_tlb_all, BTFIXUPCALL_NORM);
2083
2084 BTFIXUPSET_CALL(flush_sig_insns, sun4c_flush_sig_insns, BTFIXUPCALL_NOP);
2085
2086 BTFIXUPSET_CALL(set_pte, sun4c_set_pte, BTFIXUPCALL_STO1O0);
2087
2088 BTFIXUPSET_CALL(pte_pfn, sun4c_pte_pfn, BTFIXUPCALL_NORM);
2089#if 0 /* PAGE_SHIFT <= 12 */ /* Eek. Investigate. XXX */
2090 BTFIXUPSET_CALL(pmd_page, sun4c_pmd_page, BTFIXUPCALL_ANDNINT(PAGE_SIZE - 1));
2091#else
2092 BTFIXUPSET_CALL(pmd_page, sun4c_pmd_page, BTFIXUPCALL_NORM);
2093#endif
2094 BTFIXUPSET_CALL(pmd_set, sun4c_pmd_set, BTFIXUPCALL_NORM);
2095 BTFIXUPSET_CALL(pmd_populate, sun4c_pmd_populate, BTFIXUPCALL_NORM);
2096
2097 BTFIXUPSET_CALL(pte_present, sun4c_pte_present, BTFIXUPCALL_NORM);
2098 BTFIXUPSET_CALL(pte_clear, sun4c_pte_clear, BTFIXUPCALL_STG0O0);
2099
2100 BTFIXUPSET_CALL(pmd_bad, sun4c_pmd_bad, BTFIXUPCALL_NORM);
2101 BTFIXUPSET_CALL(pmd_present, sun4c_pmd_present, BTFIXUPCALL_NORM);
2102 BTFIXUPSET_CALL(pmd_clear, sun4c_pmd_clear, BTFIXUPCALL_STG0O0);
2103
2104 BTFIXUPSET_CALL(pgd_none, sun4c_pgd_none, BTFIXUPCALL_RETINT(0));
2105 BTFIXUPSET_CALL(pgd_bad, sun4c_pgd_bad, BTFIXUPCALL_RETINT(0));
2106 BTFIXUPSET_CALL(pgd_present, sun4c_pgd_present, BTFIXUPCALL_RETINT(1));
2107 BTFIXUPSET_CALL(pgd_clear, sun4c_pgd_clear, BTFIXUPCALL_NOP);
2108
2109 BTFIXUPSET_CALL(mk_pte, sun4c_mk_pte, BTFIXUPCALL_NORM);
2110 BTFIXUPSET_CALL(mk_pte_phys, sun4c_mk_pte_phys, BTFIXUPCALL_NORM);
2111 BTFIXUPSET_CALL(mk_pte_io, sun4c_mk_pte_io, BTFIXUPCALL_NORM);
2112
2113 BTFIXUPSET_INT(pte_modify_mask, _SUN4C_PAGE_CHG_MASK);
2114 BTFIXUPSET_CALL(pmd_offset, sun4c_pmd_offset, BTFIXUPCALL_NORM);
2115 BTFIXUPSET_CALL(pte_offset_kernel, sun4c_pte_offset_kernel, BTFIXUPCALL_NORM);
2116 BTFIXUPSET_CALL(free_pte_fast, sun4c_free_pte_fast, BTFIXUPCALL_NORM);
2117 BTFIXUPSET_CALL(pte_free, sun4c_pte_free, BTFIXUPCALL_NORM);
2118 BTFIXUPSET_CALL(pte_alloc_one_kernel, sun4c_pte_alloc_one_kernel, BTFIXUPCALL_NORM);
2119 BTFIXUPSET_CALL(pte_alloc_one, sun4c_pte_alloc_one, BTFIXUPCALL_NORM);
2120 BTFIXUPSET_CALL(free_pmd_fast, sun4c_free_pmd_fast, BTFIXUPCALL_NOP);
2121 BTFIXUPSET_CALL(pmd_alloc_one, sun4c_pmd_alloc_one, BTFIXUPCALL_RETO0);
2122 BTFIXUPSET_CALL(free_pgd_fast, sun4c_free_pgd_fast, BTFIXUPCALL_NORM);
2123 BTFIXUPSET_CALL(get_pgd_fast, sun4c_get_pgd_fast, BTFIXUPCALL_NORM);
2124
2125 BTFIXUPSET_HALF(pte_writei, _SUN4C_PAGE_WRITE);
2126 BTFIXUPSET_HALF(pte_dirtyi, _SUN4C_PAGE_MODIFIED);
2127 BTFIXUPSET_HALF(pte_youngi, _SUN4C_PAGE_ACCESSED);
2128 BTFIXUPSET_HALF(pte_filei, _SUN4C_PAGE_FILE);
2129 BTFIXUPSET_HALF(pte_wrprotecti, _SUN4C_PAGE_WRITE|_SUN4C_PAGE_SILENT_WRITE);
2130 BTFIXUPSET_HALF(pte_mkcleani, _SUN4C_PAGE_MODIFIED|_SUN4C_PAGE_SILENT_WRITE);
2131 BTFIXUPSET_HALF(pte_mkoldi, _SUN4C_PAGE_ACCESSED|_SUN4C_PAGE_SILENT_READ);
2132 BTFIXUPSET_CALL(pte_mkwrite, sun4c_pte_mkwrite, BTFIXUPCALL_NORM);
2133 BTFIXUPSET_CALL(pte_mkdirty, sun4c_pte_mkdirty, BTFIXUPCALL_NORM);
2134 BTFIXUPSET_CALL(pte_mkyoung, sun4c_pte_mkyoung, BTFIXUPCALL_NORM);
2135 BTFIXUPSET_CALL(update_mmu_cache, sun4c_update_mmu_cache, BTFIXUPCALL_NORM);
2136
2137 BTFIXUPSET_CALL(pte_to_pgoff, sun4c_pte_to_pgoff, BTFIXUPCALL_NORM);
2138 BTFIXUPSET_CALL(pgoff_to_pte, sun4c_pgoff_to_pte, BTFIXUPCALL_NORM);
2139
2140 BTFIXUPSET_CALL(mmu_lockarea, sun4c_lockarea, BTFIXUPCALL_NORM);
2141 BTFIXUPSET_CALL(mmu_unlockarea, sun4c_unlockarea, BTFIXUPCALL_NORM);
2142
2143 BTFIXUPSET_CALL(mmu_get_scsi_one, sun4c_get_scsi_one, BTFIXUPCALL_NORM);
2144 BTFIXUPSET_CALL(mmu_get_scsi_sgl, sun4c_get_scsi_sgl, BTFIXUPCALL_NORM);
2145 BTFIXUPSET_CALL(mmu_release_scsi_one, sun4c_release_scsi_one, BTFIXUPCALL_NORM);
2146 BTFIXUPSET_CALL(mmu_release_scsi_sgl, sun4c_release_scsi_sgl, BTFIXUPCALL_NORM);
2147
2148 BTFIXUPSET_CALL(mmu_map_dma_area, sun4c_map_dma_area, BTFIXUPCALL_NORM);
2149 BTFIXUPSET_CALL(mmu_unmap_dma_area, sun4c_unmap_dma_area, BTFIXUPCALL_NORM);
2150
2151 BTFIXUPSET_CALL(sparc_mapiorange, sun4c_mapiorange, BTFIXUPCALL_NORM);
2152 BTFIXUPSET_CALL(sparc_unmapiorange, sun4c_unmapiorange, BTFIXUPCALL_NORM);
2153
2154 BTFIXUPSET_CALL(__swp_type, sun4c_swp_type, BTFIXUPCALL_NORM);
2155 BTFIXUPSET_CALL(__swp_offset, sun4c_swp_offset, BTFIXUPCALL_NORM);
2156 BTFIXUPSET_CALL(__swp_entry, sun4c_swp_entry, BTFIXUPCALL_NORM);
2157
2158 BTFIXUPSET_CALL(alloc_thread_info_node, sun4c_alloc_thread_info_node, BTFIXUPCALL_NORM);
2159 BTFIXUPSET_CALL(free_thread_info, sun4c_free_thread_info, BTFIXUPCALL_NORM);
2160
2161 BTFIXUPSET_CALL(mmu_info, sun4c_mmu_info, BTFIXUPCALL_NORM);
2162
2163 /* These should _never_ get called with two level tables. */
2164 BTFIXUPSET_CALL(pgd_set, sun4c_pgd_set, BTFIXUPCALL_NOP);
2165 BTFIXUPSET_CALL(pgd_page_vaddr, sun4c_pgd_page, BTFIXUPCALL_RETO0);
2166}
diff --git a/arch/sparc/mm/viking.S b/arch/sparc/mm/viking.S
index 6dfcc13d3100..bf8ee0613ae7 100644
--- a/arch/sparc/mm/viking.S
+++ b/arch/sparc/mm/viking.S
@@ -14,7 +14,6 @@
14#include <asm/page.h> 14#include <asm/page.h>
15#include <asm/pgtsrmmu.h> 15#include <asm/pgtsrmmu.h>
16#include <asm/viking.h> 16#include <asm/viking.h>
17#include <asm/btfixup.h>
18 17
19#ifdef CONFIG_SMP 18#ifdef CONFIG_SMP
20 .data 19 .data
diff --git a/arch/sparc/prom/Makefile b/arch/sparc/prom/Makefile
index 8287bbe88768..020300b18c0b 100644
--- a/arch/sparc/prom/Makefile
+++ b/arch/sparc/prom/Makefile
@@ -10,7 +10,6 @@ lib-$(CONFIG_SPARC32) += memory.o
10lib-y += misc_$(BITS).o 10lib-y += misc_$(BITS).o
11lib-$(CONFIG_SPARC32) += mp.o 11lib-$(CONFIG_SPARC32) += mp.o
12lib-$(CONFIG_SPARC32) += ranges.o 12lib-$(CONFIG_SPARC32) += ranges.o
13lib-$(CONFIG_SPARC32) += segment.o
14lib-y += console_$(BITS).o 13lib-y += console_$(BITS).o
15lib-y += printf.o 14lib-y += printf.o
16lib-y += tree_$(BITS).o 15lib-y += tree_$(BITS).o
diff --git a/arch/sparc/prom/segment.c b/arch/sparc/prom/segment.c
deleted file mode 100644
index 86a663f1d3c5..000000000000
--- a/arch/sparc/prom/segment.c
+++ /dev/null
@@ -1,28 +0,0 @@
1/*
2 * segment.c: Prom routine to map segments in other contexts before
3 * a standalone is completely mapped. This is for sun4 and
4 * sun4c architectures only.
5 *
6 * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
7 */
8
9#include <linux/types.h>
10#include <linux/kernel.h>
11#include <linux/sched.h>
12#include <asm/openprom.h>
13#include <asm/oplib.h>
14
15extern void restore_current(void);
16
17/* Set physical segment 'segment' at virtual address 'vaddr' in
18 * context 'ctx'.
19 */
20void
21prom_putsegment(int ctx, unsigned long vaddr, int segment)
22{
23 unsigned long flags;
24 spin_lock_irqsave(&prom_lock, flags);
25 (*(romvec->pv_setctxt))(ctx, (char *) vaddr, segment);
26 restore_current();
27 spin_unlock_irqrestore(&prom_lock, flags);
28}