aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sparc
diff options
context:
space:
mode:
Diffstat (limited to 'arch/sparc')
-rw-r--r--arch/sparc/Kbuild8
-rw-r--r--arch/sparc/Kconfig16
-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.h66
-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.h10
-rw-r--r--arch/sparc/include/asm/thread_info_64.h25
-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/Makefile4
-rw-r--r--arch/sparc/kernel/auxio_32.c13
-rw-r--r--arch/sparc/kernel/central.c2
-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/init_task.c22
-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.c122
-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/ptrace_64.c2
-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.c187
-rw-r--r--arch/sparc/kernel/smp_64.c12
-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.c127
-rw-r--r--arch/sparc/kernel/sun4m_irq.c58
-rw-r--r--arch/sparc/kernel/sun4m_smp.c124
-rw-r--r--arch/sparc/kernel/sys_sparc_32.c11
-rw-r--r--arch/sparc/kernel/systbls_64.S2
-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/ultra.S6
-rw-r--r--arch/sparc/mm/viking.S1
-rw-r--r--arch/sparc/net/Makefile4
-rw-r--r--arch/sparc/net/bpf_jit.h68
-rw-r--r--arch/sparc/net/bpf_jit_asm.S205
-rw-r--r--arch/sparc/net/bpf_jit_comp.c802
-rw-r--r--arch/sparc/prom/Makefile1
-rw-r--r--arch/sparc/prom/segment.c28
147 files changed, 3353 insertions, 10813 deletions
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 6c0683d3fcba..1ea3fd954756 100644
--- a/arch/sparc/Kconfig
+++ b/arch/sparc/Kconfig
@@ -30,11 +30,14 @@ 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
34 select GENERIC_SMP_IDLE_THREAD
33 35
34config SPARC32 36config SPARC32
35 def_bool !64BIT 37 def_bool !64BIT
36 select GENERIC_ATOMIC64 38 select GENERIC_ATOMIC64
37 select CLZ_TAB 39 select CLZ_TAB
40 select ARCH_THREAD_INFO_ALLOCATOR
38 41
39config SPARC64 42config SPARC64
40 def_bool 64BIT 43 def_bool 64BIT
@@ -61,6 +64,7 @@ config SPARC64
61 select IRQ_PREFLOW_FASTEOI 64 select IRQ_PREFLOW_FASTEOI
62 select ARCH_HAVE_NMI_SAFE_CMPXCHG 65 select ARCH_HAVE_NMI_SAFE_CMPXCHG
63 select HAVE_C_RECORDMCOUNT 66 select HAVE_C_RECORDMCOUNT
67 select NO_BOOTMEM
64 68
65config ARCH_DEFCONFIG 69config ARCH_DEFCONFIG
66 string 70 string
@@ -73,17 +77,12 @@ config BITS
73 default 32 if SPARC32 77 default 32 if SPARC32
74 default 64 if SPARC64 78 default 64 if SPARC64
75 79
76config ARCH_USES_GETTIMEOFFSET
77 bool
78 default y if SPARC32
79
80config GENERIC_CMOS_UPDATE 80config GENERIC_CMOS_UPDATE
81 bool 81 bool
82 default y 82 default y
83 83
84config GENERIC_CLOCKEVENTS 84config GENERIC_CLOCKEVENTS
85 bool 85 def_bool y
86 default y if SPARC64
87 86
88config IOMMU_HELPER 87config IOMMU_HELPER
89 bool 88 bool
@@ -154,7 +153,7 @@ source "kernel/Kconfig.freezer"
154menu "Processor type and features" 153menu "Processor type and features"
155 154
156config SMP 155config SMP
157 bool "Symmetric multi-processing support (does not work on sun4/sun4c)" 156 bool "Symmetric multi-processing support"
158 ---help--- 157 ---help---
159 This enables support for systems with more than one CPU. If you have 158 This enables support for systems with more than one CPU. If you have
160 a system with only one CPU, say N. If you have a system with more 159 a system with only one CPU, say N. If you have a system with more
@@ -584,6 +583,9 @@ config SYSVIPC_COMPAT
584 depends on COMPAT && SYSVIPC 583 depends on COMPAT && SYSVIPC
585 default y 584 default y
586 585
586config KEYS_COMPAT
587 def_bool y if COMPAT && KEYS
588
587endmenu 589endmenu
588 590
589source "net/Kconfig" 591source "net/Kconfig"
diff --git a/arch/sparc/Makefile b/arch/sparc/Makefile
index eddcfb36aafb..541b8b075c7d 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
@@ -62,27 +50,15 @@ endif
62endif 50endif
63 51
64head-y := arch/sparc/kernel/head_$(BITS).o 52head-y := arch/sparc/kernel/head_$(BITS).o
65head-y += arch/sparc/kernel/init_task.o
66 53
67core-y += arch/sparc/kernel/ 54# See arch/sparc/Kbuild for the core part of the kernel
68core-y += arch/sparc/mm/ arch/sparc/math-emu/ 55core-y += arch/sparc/
69 56
70libs-y += arch/sparc/prom/ 57libs-y += arch/sparc/prom/
71libs-y += arch/sparc/lib/ 58libs-y += arch/sparc/lib/
72 59
73drivers-$(CONFIG_OPROFILE) += arch/sparc/oprofile/ 60drivers-$(CONFIG_OPROFILE) += arch/sparc/oprofile/
74 61
75# Export what is needed by arch/sparc/boot/Makefile
76export VMLINUX_INIT VMLINUX_MAIN
77VMLINUX_INIT := $(head-y) $(init-y)
78VMLINUX_MAIN := $(core-y) kernel/ mm/ fs/ ipc/ security/ crypto/ block/
79VMLINUX_MAIN += $(patsubst %/, %/lib.a, $(libs-y)) $(libs-y)
80VMLINUX_MAIN += $(drivers-y) $(net-y)
81
82ifdef CONFIG_KALLSYMS
83export kallsyms.o := .tmp_kallsyms2.o
84endif
85
86boot := arch/sparc/boot 62boot := arch/sparc/boot
87 63
88# Default target 64# 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..07659124c140 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;
@@ -315,28 +270,19 @@ struct leon2_cacheregs {
315#include <linux/interrupt.h> 270#include <linux/interrupt.h>
316 271
317struct device_node; 272struct device_node;
273struct task_struct;
318extern unsigned int leon_build_device_irq(unsigned int real_irq, 274extern unsigned int leon_build_device_irq(unsigned int real_irq,
319 irq_flow_handler_t flow_handler, 275 irq_flow_handler_t flow_handler,
320 const char *name, int do_ack); 276 const char *name, int do_ack);
321extern void leon_update_virq_handling(unsigned int virq, 277extern void leon_update_virq_handling(unsigned int virq,
322 irq_flow_handler_t flow_handler, 278 irq_flow_handler_t flow_handler,
323 const char *name, int do_ack); 279 const char *name, int do_ack);
324extern void leon_clear_clock_irq(void); 280extern 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); 281extern void leon_trans_init(struct device_node *dp);
330extern void leon_node_init(struct device_node *dp, struct device_node ***nextp); 282extern 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); 283extern void init_leon(void);
335extern void poke_leonsparc(void); 284extern void poke_leonsparc(void);
336extern void leon3_getCacheRegs(struct leon3_cacheregs *regs); 285extern 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; 286extern int leon3_ticker_irq;
341 287
342#ifdef CONFIG_SMP 288#ifdef CONFIG_SMP
@@ -344,7 +290,7 @@ extern int leon_smp_nrcpus(void);
344extern void leon_clear_profile_irq(int cpu); 290extern void leon_clear_profile_irq(int cpu);
345extern void leon_smp_done(void); 291extern void leon_smp_done(void);
346extern void leon_boot_cpus(void); 292extern void leon_boot_cpus(void);
347extern int leon_boot_one_cpu(int i); 293extern int leon_boot_one_cpu(int i, struct task_struct *);
348void leon_init_smp(void); 294void leon_init_smp(void);
349extern void cpu_idle(void); 295extern void cpu_idle(void);
350extern void init_IRQ(void); 296extern void init_IRQ(void);
@@ -380,7 +326,7 @@ extern int leon_ipi_irq;
380#define init_leon() do {} while (0) 326#define init_leon() do {} while (0)
381#define leon_smp_done() do {} while (0) 327#define leon_smp_done() do {} while (0)
382#define leon_boot_cpus() do {} while (0) 328#define leon_boot_cpus() do {} while (0)
383#define leon_boot_one_cpu(i) 1 329#define leon_boot_one_cpu(i, t) 1
384#define leon_init_smp() do {} while (0) 330#define leon_init_smp() do {} while (0)
385 331
386#endif /* !defined(CONFIG_SPARC_LEON) */ 332#endif /* !defined(CONFIG_SPARC_LEON) */
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..21a38946541d 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
@@ -80,13 +79,8 @@ register struct thread_info *current_thread_info_reg asm("g6");
80 */ 79 */
81#define THREAD_INFO_ORDER 1 80#define THREAD_INFO_ORDER 1
82 81
83#define __HAVE_ARCH_THREAD_INFO_ALLOCATOR 82struct thread_info * alloc_thread_info_node(struct task_struct *tsk, int node);
84 83void free_thread_info(struct thread_info *);
85BTFIXUPDEF_CALL(struct thread_info *, alloc_thread_info_node, int)
86#define alloc_thread_info_node(tsk, node) BTFIXUP_CALL(alloc_thread_info_node)(node)
87
88BTFIXUPDEF_CALL(void, free_thread_info, struct thread_info *)
89#define free_thread_info(ti) BTFIXUP_CALL(free_thread_info)(ti)
90 84
91#endif /* __ASSEMBLY__ */ 85#endif /* __ASSEMBLY__ */
92 86
diff --git a/arch/sparc/include/asm/thread_info_64.h b/arch/sparc/include/asm/thread_info_64.h
index 01d057fe6a3f..7f0981b09451 100644
--- a/arch/sparc/include/asm/thread_info_64.h
+++ b/arch/sparc/include/asm/thread_info_64.h
@@ -138,32 +138,11 @@ register struct thread_info *current_thread_info_reg asm("g6");
138 138
139/* thread information allocation */ 139/* thread information allocation */
140#if PAGE_SHIFT == 13 140#if PAGE_SHIFT == 13
141#define __THREAD_INFO_ORDER 1 141#define THREAD_SIZE_ORDER 1
142#else /* PAGE_SHIFT == 13 */ 142#else /* PAGE_SHIFT == 13 */
143#define __THREAD_INFO_ORDER 0 143#define THREAD_SIZE_ORDER 0
144#endif /* PAGE_SHIFT == 13 */ 144#endif /* PAGE_SHIFT == 13 */
145 145
146#define __HAVE_ARCH_THREAD_INFO_ALLOCATOR
147
148#ifdef CONFIG_DEBUG_STACK_USAGE
149#define THREAD_FLAGS (GFP_KERNEL | __GFP_ZERO)
150#else
151#define THREAD_FLAGS (GFP_KERNEL)
152#endif
153
154#define alloc_thread_info_node(tsk, node) \
155({ \
156 struct page *page = alloc_pages_node(node, THREAD_FLAGS, \
157 __THREAD_INFO_ORDER); \
158 struct thread_info *ret; \
159 \
160 ret = page ? page_address(page) : NULL; \
161 ret; \
162})
163
164#define free_thread_info(ti) \
165 free_pages((unsigned long)(ti),__THREAD_INFO_ORDER)
166
167#define __thread_flag_byte_ptr(ti) \ 146#define __thread_flag_byte_ptr(ti) \
168 ((unsigned char *)(&((ti)->flags))) 147 ((unsigned char *)(&((ti)->flags)))
169#define __cur_thread_flag_byte_ptr __thread_flag_byte_ptr(current_thread_info()) 148#define __cur_thread_flag_byte_ptr __thread_flag_byte_ptr(current_thread_info())
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..72308f9b0096 100644
--- a/arch/sparc/kernel/Makefile
+++ b/arch/sparc/kernel/Makefile
@@ -6,7 +6,6 @@ asflags-y := -ansi
6ccflags-y := -Werror 6ccflags-y := -Werror
7 7
8extra-y := head_$(BITS).o 8extra-y := head_$(BITS).o
9extra-y += init_task.o
10 9
11# Undefine sparc when processing vmlinux.lds - it is used 10# Undefine sparc when processing vmlinux.lds - it is used
12# And teach CPP we are doing $(BITS) builds (for this case) 11# And teach CPP we are doing $(BITS) builds (for this case)
@@ -28,7 +27,7 @@ obj-y += traps_$(BITS).o
28 27
29# IRQ 28# IRQ
30obj-y += irq_$(BITS).o 29obj-y += irq_$(BITS).o
31obj-$(CONFIG_SPARC32) += sun4m_irq.o sun4c_irq.o sun4d_irq.o 30obj-$(CONFIG_SPARC32) += sun4m_irq.o sun4d_irq.o
32 31
33obj-y += process_$(BITS).o 32obj-y += process_$(BITS).o
34obj-y += signal_$(BITS).o 33obj-y += signal_$(BITS).o
@@ -46,7 +45,6 @@ obj-$(CONFIG_SPARC32) += tadpole.o
46obj-y += ptrace_$(BITS).o 45obj-y += ptrace_$(BITS).o
47obj-y += unaligned_$(BITS).o 46obj-y += unaligned_$(BITS).o
48obj-y += una_asm_$(BITS).o 47obj-y += una_asm_$(BITS).o
49obj-$(CONFIG_SPARC32) += muldiv.o
50obj-y += prom_common.o 48obj-y += prom_common.o
51obj-y += prom_$(BITS).o 49obj-y += prom_$(BITS).o
52obj-y += of_device_common.o 50obj-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/central.c b/arch/sparc/kernel/central.c
index 38d48a59879c..9708851a8b9f 100644
--- a/arch/sparc/kernel/central.c
+++ b/arch/sparc/kernel/central.c
@@ -269,4 +269,4 @@ static int __init sunfire_init(void)
269 return 0; 269 return 0;
270} 270}
271 271
272subsys_initcall(sunfire_init); 272fs_initcall(sunfire_init);
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/init_task.c b/arch/sparc/kernel/init_task.c
deleted file mode 100644
index 35f141a9f506..000000000000
--- a/arch/sparc/kernel/init_task.c
+++ /dev/null
@@ -1,22 +0,0 @@
1#include <linux/mm.h>
2#include <linux/fs.h>
3#include <linux/module.h>
4#include <linux/sched.h>
5#include <linux/init_task.h>
6#include <linux/mqueue.h>
7
8#include <asm/pgtable.h>
9#include <asm/uaccess.h>
10
11static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
12static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
13struct task_struct init_task = INIT_TASK(init_task);
14EXPORT_SYMBOL(init_task);
15
16/* .text section in head.S is aligned at 8k boundary and this gets linked
17 * right after that so that the init_thread_union is aligned properly as well.
18 * If this is not aligned on a 8k boundary, then you should change code
19 * in etrap.S which assumes it.
20 */
21union thread_union init_thread_union __init_task_data =
22 { INIT_THREAD_INFO(init_task) };
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..a469090faf9f 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,21 +199,15 @@ 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
207int __cpuinit leon_boot_one_cpu(int i) 206int __cpuinit leon_boot_one_cpu(int i, struct task_struct *idle)
208{ 207{
209
210 struct task_struct *p;
211 int timeout; 208 int timeout;
212 209
213 /* Cook up an idler for this guy. */ 210 current_set[i] = task_thread_info(idle);
214 p = fork_idle(i);
215
216 current_set[i] = task_thread_info(p);
217 211
218 /* See trampoline.S:leon_smp_cpu_startup for details... 212 /* See trampoline.S:leon_smp_cpu_startup for details...
219 * Initialize the contexts table 213 * Initialize the contexts table
@@ -227,7 +221,7 @@ int __cpuinit leon_boot_one_cpu(int i)
227 /* whirrr, whirrr, whirrrrrrrrr... */ 221 /* whirrr, whirrr, whirrrrrrrrr... */
228 printk(KERN_INFO "Starting CPU %d : (irqmp: 0x%x)\n", (unsigned int)i, 222 printk(KERN_INFO "Starting CPU %d : (irqmp: 0x%x)\n", (unsigned int)i,
229 (unsigned int)&leon3_irqctrl_regs->mpstatus); 223 (unsigned int)&leon3_irqctrl_regs->mpstatus);
230 local_flush_cache_all(); 224 local_ops->cache_all();
231 225
232 /* Make sure all IRQs are of from the start for this new CPU */ 226 /* Make sure all IRQs are of from the start for this new CPU */
233 LEON_BYPASS_STORE_PA(&leon3_irqctrl_regs->mask[i], 0); 227 LEON_BYPASS_STORE_PA(&leon3_irqctrl_regs->mask[i], 0);
@@ -252,7 +246,7 @@ int __cpuinit leon_boot_one_cpu(int i)
252 leon_enable_irq_cpu(leon_ipi_irq, i); 246 leon_enable_irq_cpu(leon_ipi_irq, i);
253 } 247 }
254 248
255 local_flush_cache_all(); 249 local_ops->cache_all();
256 return 0; 250 return 0;
257} 251}
258 252
@@ -272,7 +266,7 @@ void __init leon_smp_done(void)
272 } 266 }
273 } 267 }
274 *prev = first; 268 *prev = first;
275 local_flush_cache_all(); 269 local_ops->cache_all();
276 270
277 /* Free unneeded trap tables */ 271 /* Free unneeded trap tables */
278 if (!cpu_present(1)) { 272 if (!cpu_present(1)) {
@@ -338,7 +332,7 @@ static void __init leon_ipi_init(void)
338 local_irq_save(flags); 332 local_irq_save(flags);
339 trap_table = &sparc_ttable[SP_TRAP_IRQ1 + (leon_ipi_irq - 1)]; 333 trap_table = &sparc_ttable[SP_TRAP_IRQ1 + (leon_ipi_irq - 1)];
340 trap_table->inst_three += smpleon_ipi - real_irq_entry; 334 trap_table->inst_three += smpleon_ipi - real_irq_entry;
341 local_flush_cache_all(); 335 local_ops->cache_all();
342 local_irq_restore(flags); 336 local_irq_restore(flags);
343 337
344 for_each_possible_cpu(cpu) { 338 for_each_possible_cpu(cpu) {
@@ -347,6 +341,13 @@ static void __init leon_ipi_init(void)
347 } 341 }
348} 342}
349 343
344static void leon_send_ipi(int cpu, int level)
345{
346 unsigned long mask;
347 mask = leon_get_irqmask(level);
348 LEON3_BYPASS_STORE_PA(&leon3_irqctrl_regs->force[cpu], mask);
349}
350
350static void leon_ipi_single(int cpu) 351static void leon_ipi_single(int cpu)
351{ 352{
352 struct leon_ipi_work *work = &per_cpu(leon_ipi_work, cpu); 353 struct leon_ipi_work *work = &per_cpu(leon_ipi_work, cpu);
@@ -355,7 +356,7 @@ static void leon_ipi_single(int cpu)
355 work->single = 1; 356 work->single = 1;
356 357
357 /* Generate IRQ on the CPU */ 358 /* Generate IRQ on the CPU */
358 set_cpu_int(cpu, leon_ipi_irq); 359 leon_send_ipi(cpu, leon_ipi_irq);
359} 360}
360 361
361static void leon_ipi_mask_one(int cpu) 362static void leon_ipi_mask_one(int cpu)
@@ -366,7 +367,7 @@ static void leon_ipi_mask_one(int cpu)
366 work->msk = 1; 367 work->msk = 1;
367 368
368 /* Generate IRQ on the CPU */ 369 /* Generate IRQ on the CPU */
369 set_cpu_int(cpu, leon_ipi_irq); 370 leon_send_ipi(cpu, leon_ipi_irq);
370} 371}
371 372
372static void leon_ipi_resched(int cpu) 373static void leon_ipi_resched(int cpu)
@@ -377,7 +378,7 @@ static void leon_ipi_resched(int cpu)
377 work->resched = 1; 378 work->resched = 1;
378 379
379 /* Generate IRQ on the CPU (any IRQ will cause resched) */ 380 /* Generate IRQ on the CPU (any IRQ will cause resched) */
380 set_cpu_int(cpu, leon_ipi_irq); 381 leon_send_ipi(cpu, leon_ipi_irq);
381} 382}
382 383
383void leonsmp_ipi_interrupt(void) 384void leonsmp_ipi_interrupt(void)
@@ -449,7 +450,7 @@ static void leon_cross_call(smpfunc_t func, cpumask_t mask, unsigned long arg1,
449 if (cpumask_test_cpu(i, &mask)) { 450 if (cpumask_test_cpu(i, &mask)) {
450 ccall_info.processors_in[i] = 0; 451 ccall_info.processors_in[i] = 0;
451 ccall_info.processors_out[i] = 0; 452 ccall_info.processors_out[i] = 0;
452 set_cpu_int(i, LEON3_IRQ_CROSS_CALL); 453 leon_send_ipi(i, LEON3_IRQ_CROSS_CALL);
453 454
454 } 455 }
455 } 456 }
@@ -492,68 +493,19 @@ void leon_cross_call_irq(void)
492 ccall_info.processors_out[i] = 1; 493 ccall_info.processors_out[i] = 1;
493} 494}
494 495
495irqreturn_t leon_percpu_timer_interrupt(int irq, void *unused) 496static const struct sparc32_ipi_ops leon_ipi_ops = {
496{ 497 .cross_call = leon_cross_call,
497 int cpu = smp_processor_id(); 498 .resched = leon_ipi_resched,
498 499 .single = leon_ipi_single,
499 leon_clear_profile_irq(cpu); 500 .mask_one = leon_ipi_mask_one,
500 501};
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 502
544void __init leon_init_smp(void) 503void __init leon_init_smp(void)
545{ 504{
546 /* Patch ipi15 trap table */ 505 /* Patch ipi15 trap table */
547 t_nmi[1] = t_nmi[1] + (linux_trap_ipi15_leon - linux_trap_ipi15_sun4m); 506 t_nmi[1] = t_nmi[1] + (linux_trap_ipi15_leon - linux_trap_ipi15_sun4m);
548 507
549 BTFIXUPSET_BLACKBOX(hard_smp_processor_id, leon_blackbox_id); 508 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} 509}
558 510
559#endif /* CONFIG_SPARC_LEON */ 511#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/ptrace_64.c b/arch/sparc/kernel/ptrace_64.c
index 6f97c0767995..484dabac7045 100644
--- a/arch/sparc/kernel/ptrace_64.c
+++ b/arch/sparc/kernel/ptrace_64.c
@@ -1062,7 +1062,7 @@ asmlinkage int syscall_trace_enter(struct pt_regs *regs)
1062 int ret = 0; 1062 int ret = 0;
1063 1063
1064 /* do the secure computing check first */ 1064 /* do the secure computing check first */
1065 secure_computing(regs->u_regs[UREG_G1]); 1065 secure_computing_strict(regs->u_regs[UREG_G1]);
1066 1066
1067 if (test_thread_flag(TIF_SYSCALL_TRACE)) 1067 if (test_thread_flag(TIF_SYSCALL_TRACE))
1068 ret = tracehook_report_syscall_entry(regs); 1068 ret = tracehook_report_syscall_entry(regs);
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..79db45e5134a 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;
@@ -411,29 +256,21 @@ void __init smp_prepare_boot_cpu(void)
411 set_cpu_possible(cpuid, true); 256 set_cpu_possible(cpuid, true);
412} 257}
413 258
414int __cpuinit __cpu_up(unsigned int cpu) 259int __cpuinit __cpu_up(unsigned int cpu, struct task_struct *tidle)
415{ 260{
416 extern int __cpuinit smp4m_boot_one_cpu(int); 261 extern int __cpuinit smp4m_boot_one_cpu(int, struct task_struct *);
417 extern int __cpuinit smp4d_boot_one_cpu(int); 262 extern int __cpuinit smp4d_boot_one_cpu(int, struct task_struct *);
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, tidle);
431 break; 268 break;
432 case sun4d: 269 case sun4d:
433 ret = smp4d_boot_one_cpu(cpu); 270 ret = smp4d_boot_one_cpu(cpu, tidle);
434 break; 271 break;
435 case sparc_leon: 272 case sparc_leon:
436 ret = leon_boot_one_cpu(cpu); 273 ret = leon_boot_one_cpu(cpu, tidle);
437 break; 274 break;
438 case sun4e: 275 case sun4e:
439 printk("SUN4E\n"); 276 printk("SUN4E\n");
diff --git a/arch/sparc/kernel/smp_64.c b/arch/sparc/kernel/smp_64.c
index 3b1bd7c50164..f591598d92f6 100644
--- a/arch/sparc/kernel/smp_64.c
+++ b/arch/sparc/kernel/smp_64.c
@@ -343,21 +343,17 @@ extern unsigned long sparc64_cpu_startup;
343 */ 343 */
344static struct thread_info *cpu_new_thread = NULL; 344static struct thread_info *cpu_new_thread = NULL;
345 345
346static int __cpuinit smp_boot_one_cpu(unsigned int cpu) 346static int __cpuinit smp_boot_one_cpu(unsigned int cpu, struct task_struct *idle)
347{ 347{
348 unsigned long entry = 348 unsigned long entry =
349 (unsigned long)(&sparc64_cpu_startup); 349 (unsigned long)(&sparc64_cpu_startup);
350 unsigned long cookie = 350 unsigned long cookie =
351 (unsigned long)(&cpu_new_thread); 351 (unsigned long)(&cpu_new_thread);
352 struct task_struct *p;
353 void *descr = NULL; 352 void *descr = NULL;
354 int timeout, ret; 353 int timeout, ret;
355 354
356 p = fork_idle(cpu);
357 if (IS_ERR(p))
358 return PTR_ERR(p);
359 callin_flag = 0; 355 callin_flag = 0;
360 cpu_new_thread = task_thread_info(p); 356 cpu_new_thread = task_thread_info(idle);
361 357
362 if (tlb_type == hypervisor) { 358 if (tlb_type == hypervisor) {
363#if defined(CONFIG_SUN_LDOMS) && defined(CONFIG_HOTPLUG_CPU) 359#if defined(CONFIG_SUN_LDOMS) && defined(CONFIG_HOTPLUG_CPU)
@@ -1227,9 +1223,9 @@ void __devinit smp_fill_in_sib_core_maps(void)
1227 } 1223 }
1228} 1224}
1229 1225
1230int __cpuinit __cpu_up(unsigned int cpu) 1226int __cpuinit __cpu_up(unsigned int cpu, struct task_struct *tidle)
1231{ 1227{
1232 int ret = smp_boot_one_cpu(cpu); 1228 int ret = smp_boot_one_cpu(cpu, tidle);
1233 1229
1234 if (!ret) { 1230 if (!ret) {
1235 cpumask_set_cpu(cpu, &smp_commenced_mask); 1231 cpumask_set_cpu(cpu, &smp_commenced_mask);
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..ddaea31de586 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,22 +126,17 @@ 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, struct task_struct *idle)
131{ 133{
132 unsigned long *entry = &sun4d_cpu_startup; 134 unsigned long *entry = &sun4d_cpu_startup;
133 struct task_struct *p;
134 int timeout; 135 int timeout;
135 int cpu_node; 136 int cpu_node;
136 137
137 cpu_find_by_instance(i, &cpu_node, NULL); 138 cpu_find_by_instance(i, &cpu_node, NULL);
138 /* Cook up an idler for this guy. */ 139 current_set[i] = task_thread_info(idle);
139 p = fork_idle(i);
140 current_set[i] = task_thread_info(p);
141
142 /* 140 /*
143 * Initialize the contexts table 141 * Initialize the contexts table
144 * Since the call to prom_startcpu() trashes the structure, 142 * Since the call to prom_startcpu() trashes the structure,
@@ -150,7 +148,7 @@ int __cpuinit smp4d_boot_one_cpu(int i)
150 148
151 /* whirrr, whirrr, whirrrrrrrrr... */ 149 /* whirrr, whirrr, whirrrrrrrrr... */
152 printk(KERN_INFO "Starting CPU %d at %p\n", i, entry); 150 printk(KERN_INFO "Starting CPU %d at %p\n", i, entry);
153 local_flush_cache_all(); 151 local_ops->cache_all();
154 prom_startcpu(cpu_node, 152 prom_startcpu(cpu_node,
155 &smp_penguin_ctable, 0, (char *)entry); 153 &smp_penguin_ctable, 0, (char *)entry);
156 154
@@ -168,7 +166,7 @@ int __cpuinit smp4d_boot_one_cpu(int i)
168 return -ENODEV; 166 return -ENODEV;
169 167
170 } 168 }
171 local_flush_cache_all(); 169 local_ops->cache_all();
172 return 0; 170 return 0;
173} 171}
174 172
@@ -185,7 +183,7 @@ void __init smp4d_smp_done(void)
185 prev = &cpu_data(i).next; 183 prev = &cpu_data(i).next;
186 } 184 }
187 *prev = first; 185 *prev = first;
188 local_flush_cache_all(); 186 local_ops->cache_all();
189 187
190 /* Ok, they are spinning and ready to go. */ 188 /* Ok, they are spinning and ready to go. */
191 smp_processors_ready = 1; 189 smp_processors_ready = 1;
@@ -233,7 +231,20 @@ void sun4d_ipi_interrupt(void)
233 } 231 }
234} 232}
235 233
236static void smp4d_ipi_single(int cpu) 234/* +-------+-------------+-----------+------------------------------------+
235 * | bcast | devid | sid | levels mask |
236 * +-------+-------------+-----------+------------------------------------+
237 * 31 30 23 22 15 14 0
238 */
239#define IGEN_MESSAGE(bcast, devid, sid, levels) \
240 (((bcast) << 31) | ((devid) << 23) | ((sid) << 15) | (levels))
241
242static void sun4d_send_ipi(int cpu, int level)
243{
244 cc_set_igen(IGEN_MESSAGE(0, cpu << 3, 6 + ((level >> 1) & 7), 1 << (level - 1)));
245}
246
247static void sun4d_ipi_single(int cpu)
237{ 248{
238 struct sun4d_ipi_work *work = &per_cpu(sun4d_ipi_work, cpu); 249 struct sun4d_ipi_work *work = &per_cpu(sun4d_ipi_work, cpu);
239 250
@@ -244,7 +255,7 @@ static void smp4d_ipi_single(int cpu)
244 sun4d_send_ipi(cpu, SUN4D_IPI_IRQ); 255 sun4d_send_ipi(cpu, SUN4D_IPI_IRQ);
245} 256}
246 257
247static void smp4d_ipi_mask_one(int cpu) 258static void sun4d_ipi_mask_one(int cpu)
248{ 259{
249 struct sun4d_ipi_work *work = &per_cpu(sun4d_ipi_work, cpu); 260 struct sun4d_ipi_work *work = &per_cpu(sun4d_ipi_work, cpu);
250 261
@@ -255,7 +266,7 @@ static void smp4d_ipi_mask_one(int cpu)
255 sun4d_send_ipi(cpu, SUN4D_IPI_IRQ); 266 sun4d_send_ipi(cpu, SUN4D_IPI_IRQ);
256} 267}
257 268
258static void smp4d_ipi_resched(int cpu) 269static void sun4d_ipi_resched(int cpu)
259{ 270{
260 struct sun4d_ipi_work *work = &per_cpu(sun4d_ipi_work, cpu); 271 struct sun4d_ipi_work *work = &per_cpu(sun4d_ipi_work, cpu);
261 272
@@ -280,7 +291,7 @@ static struct smp_funcall {
280static DEFINE_SPINLOCK(cross_call_lock); 291static DEFINE_SPINLOCK(cross_call_lock);
281 292
282/* Cross calls must be serialized, at least currently. */ 293/* Cross calls must be serialized, at least currently. */
283static void smp4d_cross_call(smpfunc_t func, cpumask_t mask, unsigned long arg1, 294static void sun4d_cross_call(smpfunc_t func, cpumask_t mask, unsigned long arg1,
284 unsigned long arg2, unsigned long arg3, 295 unsigned long arg2, unsigned long arg3,
285 unsigned long arg4) 296 unsigned long arg4)
286{ 297{
@@ -352,7 +363,7 @@ static void smp4d_cross_call(smpfunc_t func, cpumask_t mask, unsigned long arg1,
352/* Running cross calls. */ 363/* Running cross calls. */
353void smp4d_cross_call_irq(void) 364void smp4d_cross_call_irq(void)
354{ 365{
355 int i = hard_smp4d_processor_id(); 366 int i = hard_smp_processor_id();
356 367
357 ccall_info.processors_in[i] = 1; 368 ccall_info.processors_in[i] = 1;
358 ccall_info.func(ccall_info.arg1, ccall_info.arg2, ccall_info.arg3, 369 ccall_info.func(ccall_info.arg1, ccall_info.arg2, ccall_info.arg3,
@@ -363,7 +374,8 @@ void smp4d_cross_call_irq(void)
363void smp4d_percpu_timer_interrupt(struct pt_regs *regs) 374void smp4d_percpu_timer_interrupt(struct pt_regs *regs)
364{ 375{
365 struct pt_regs *old_regs; 376 struct pt_regs *old_regs;
366 int cpu = hard_smp4d_processor_id(); 377 int cpu = hard_smp_processor_id();
378 struct clock_event_device *ce;
367 static int cpu_tick[NR_CPUS]; 379 static int cpu_tick[NR_CPUS];
368 static char led_mask[] = { 0xe, 0xd, 0xb, 0x7, 0xb, 0xd }; 380 static char led_mask[] = { 0xe, 0xd, 0xb, 0x7, 0xb, 0xd };
369 381
@@ -379,45 +391,21 @@ void smp4d_percpu_timer_interrupt(struct pt_regs *regs)
379 show_leds(cpu); 391 show_leds(cpu);
380 } 392 }
381 393
382 profile_tick(CPU_PROFILING); 394 ce = &per_cpu(sparc32_clockevent, cpu);
383
384 if (!--prof_counter(cpu)) {
385 int user = user_mode(regs);
386 395
387 irq_enter(); 396 irq_enter();
388 update_process_times(user); 397 ce->event_handler(ce);
389 irq_exit(); 398 irq_exit();
390 399
391 prof_counter(cpu) = prof_multiplier(cpu);
392 }
393 set_irq_regs(old_regs); 400 set_irq_regs(old_regs);
394} 401}
395 402
396static void __cpuinit smp_setup_percpu_timer(void) 403static const struct sparc32_ipi_ops sun4d_ipi_ops = {
397{ 404 .cross_call = sun4d_cross_call,
398 int cpu = hard_smp4d_processor_id(); 405 .resched = sun4d_ipi_resched,
399 406 .single = sun4d_ipi_single,
400 prof_counter(cpu) = prof_multiplier(cpu) = 1; 407 .mask_one = sun4d_ipi_mask_one,
401 load_profile_irq(cpu, lvl14_resolution); 408};
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 409
422void __init sun4d_init_smp(void) 410void __init sun4d_init_smp(void)
423{ 411{
@@ -426,14 +414,7 @@ void __init sun4d_init_smp(void)
426 /* Patch ipi15 trap table */ 414 /* Patch ipi15 trap table */
427 t_nmi[1] = t_nmi[1] + (linux_trap_ipi15_sun4d - linux_trap_ipi15_sun4m); 415 t_nmi[1] = t_nmi[1] + (linux_trap_ipi15_sun4d - linux_trap_ipi15_sun4m);
428 416
429 /* And set btfixup... */ 417 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 418
438 for (i = 0; i < NR_CPUS; i++) { 419 for (i = 0; i < NR_CPUS; i++) {
439 ccall_info.processors_in[i] = 1; 420 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..128af7304288 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,23 +86,19 @@ 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, struct task_struct *idle)
95{ 94{
96 unsigned long *entry = &sun4m_cpu_startup; 95 unsigned long *entry = &sun4m_cpu_startup;
97 struct task_struct *p;
98 int timeout; 96 int timeout;
99 int cpu_node; 97 int cpu_node;
100 98
101 cpu_find_by_mid(i, &cpu_node); 99 cpu_find_by_mid(i, &cpu_node);
100 current_set[i] = task_thread_info(idle);
102 101
103 /* Cook up an idler for this guy. */
104 p = fork_idle(i);
105 current_set[i] = task_thread_info(p);
106 /* See trampoline.S for details... */ 102 /* See trampoline.S for details... */
107 entry += ((i - 1) * 3); 103 entry += ((i - 1) * 3);
108 104
@@ -117,7 +113,7 @@ int __cpuinit smp4m_boot_one_cpu(int i)
117 113
118 /* whirrr, whirrr, whirrrrrrrrr... */ 114 /* whirrr, whirrr, whirrrrrrrrr... */
119 printk(KERN_INFO "Starting CPU %d at %p\n", i, entry); 115 printk(KERN_INFO "Starting CPU %d at %p\n", i, entry);
120 local_flush_cache_all(); 116 local_ops->cache_all();
121 prom_startcpu(cpu_node, &smp_penguin_ctable, 0, (char *)entry); 117 prom_startcpu(cpu_node, &smp_penguin_ctable, 0, (char *)entry);
122 118
123 /* wheee... it's going... */ 119 /* wheee... it's going... */
@@ -132,7 +128,7 @@ int __cpuinit smp4m_boot_one_cpu(int i)
132 return -ENODEV; 128 return -ENODEV;
133 } 129 }
134 130
135 local_flush_cache_all(); 131 local_ops->cache_all();
136 return 0; 132 return 0;
137} 133}
138 134
@@ -149,30 +145,29 @@ void __init smp4m_smp_done(void)
149 prev = &cpu_data(i).next; 145 prev = &cpu_data(i).next;
150 } 146 }
151 *prev = first; 147 *prev = first;
152 local_flush_cache_all(); 148 local_ops->cache_all();
153 149
154 /* Ok, they are spinning and ready to go. */ 150 /* Ok, they are spinning and ready to go. */
155} 151}
156 152
157 153static void sun4m_send_ipi(int cpu, int level)
158/* Initialize IPIs on the SUN4M SMP machine */
159static void __init smp4m_ipi_init(void)
160{ 154{
155 sbus_writel(SUN4M_SOFT_INT(level), &sun4m_irq_percpu[cpu]->set);
161} 156}
162 157
163static void smp4m_ipi_resched(int cpu) 158static void sun4m_ipi_resched(int cpu)
164{ 159{
165 set_cpu_int(cpu, IRQ_IPI_RESCHED); 160 sun4m_send_ipi(cpu, IRQ_IPI_RESCHED);
166} 161}
167 162
168static void smp4m_ipi_single(int cpu) 163static void sun4m_ipi_single(int cpu)
169{ 164{
170 set_cpu_int(cpu, IRQ_IPI_SINGLE); 165 sun4m_send_ipi(cpu, IRQ_IPI_SINGLE);
171} 166}
172 167
173static void smp4m_ipi_mask_one(int cpu) 168static void sun4m_ipi_mask_one(int cpu)
174{ 169{
175 set_cpu_int(cpu, IRQ_IPI_MASK); 170 sun4m_send_ipi(cpu, IRQ_IPI_MASK);
176} 171}
177 172
178static struct smp_funcall { 173static struct smp_funcall {
@@ -189,7 +184,7 @@ static struct smp_funcall {
189static DEFINE_SPINLOCK(cross_call_lock); 184static DEFINE_SPINLOCK(cross_call_lock);
190 185
191/* Cross calls must be serialized, at least currently. */ 186/* Cross calls must be serialized, at least currently. */
192static void smp4m_cross_call(smpfunc_t func, cpumask_t mask, unsigned long arg1, 187static void sun4m_cross_call(smpfunc_t func, cpumask_t mask, unsigned long arg1,
193 unsigned long arg2, unsigned long arg3, 188 unsigned long arg2, unsigned long arg3,
194 unsigned long arg4) 189 unsigned long arg4)
195{ 190{
@@ -216,7 +211,7 @@ static void smp4m_cross_call(smpfunc_t func, cpumask_t mask, unsigned long arg1,
216 if (cpumask_test_cpu(i, &mask)) { 211 if (cpumask_test_cpu(i, &mask)) {
217 ccall_info.processors_in[i] = 0; 212 ccall_info.processors_in[i] = 0;
218 ccall_info.processors_out[i] = 0; 213 ccall_info.processors_out[i] = 0;
219 set_cpu_int(i, IRQ_CROSS_CALL); 214 sun4m_send_ipi(i, IRQ_CROSS_CALL);
220 } else { 215 } else {
221 ccall_info.processors_in[i] = 1; 216 ccall_info.processors_in[i] = 1;
222 ccall_info.processors_out[i] = 1; 217 ccall_info.processors_out[i] = 1;
@@ -260,64 +255,33 @@ void smp4m_cross_call_irq(void)
260void smp4m_percpu_timer_interrupt(struct pt_regs *regs) 255void smp4m_percpu_timer_interrupt(struct pt_regs *regs)
261{ 256{
262 struct pt_regs *old_regs; 257 struct pt_regs *old_regs;
258 struct clock_event_device *ce;
263 int cpu = smp_processor_id(); 259 int cpu = smp_processor_id();
264 260
265 old_regs = set_irq_regs(regs); 261 old_regs = set_irq_regs(regs);
266 262
267 sun4m_clear_profile_irq(cpu); 263 ce = &per_cpu(sparc32_clockevent, cpu);
268
269 profile_tick(CPU_PROFILING);
270 264
271 if (!--prof_counter(cpu)) { 265 if (ce->mode & CLOCK_EVT_MODE_PERIODIC)
272 int user = user_mode(regs); 266 sun4m_clear_profile_irq(cpu);
267 else
268 sparc_config.load_profile_irq(cpu, 0); /* Is this needless? */
273 269
274 irq_enter(); 270 irq_enter();
275 update_process_times(user); 271 ce->event_handler(ce);
276 irq_exit(); 272 irq_exit();
277 273
278 prof_counter(cpu) = prof_multiplier(cpu);
279 }
280 set_irq_regs(old_regs); 274 set_irq_regs(old_regs);
281} 275}
282 276
283static void __cpuinit smp_setup_percpu_timer(void) 277static const struct sparc32_ipi_ops sun4m_ipi_ops = {
284{ 278 .cross_call = sun4m_cross_call,
285 int cpu = smp_processor_id(); 279 .resched = sun4m_ipi_resched,
286 280 .single = sun4m_ipi_single,
287 prof_counter(cpu) = prof_multiplier(cpu) = 1; 281 .mask_one = sun4m_ipi_mask_one,
288 load_profile_irq(cpu, lvl14_resolution); 282};
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 283
314void __init sun4m_init_smp(void) 284void __init sun4m_init_smp(void)
315{ 285{
316 BTFIXUPSET_BLACKBOX(hard_smp_processor_id, smp4m_blackbox_id); 286 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} 287}
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/systbls_64.S b/arch/sparc/kernel/systbls_64.S
index db86b1a0e9a9..3a58e0d66f51 100644
--- a/arch/sparc/kernel/systbls_64.S
+++ b/arch/sparc/kernel/systbls_64.S
@@ -74,7 +74,7 @@ sys_call_table32:
74 .word sys_timer_delete, compat_sys_timer_create, sys_ni_syscall, compat_sys_io_setup, sys_io_destroy 74 .word sys_timer_delete, compat_sys_timer_create, sys_ni_syscall, compat_sys_io_setup, sys_io_destroy
75/*270*/ .word sys32_io_submit, sys_io_cancel, compat_sys_io_getevents, sys32_mq_open, sys_mq_unlink 75/*270*/ .word sys32_io_submit, sys_io_cancel, compat_sys_io_getevents, sys32_mq_open, sys_mq_unlink
76 .word compat_sys_mq_timedsend, compat_sys_mq_timedreceive, compat_sys_mq_notify, compat_sys_mq_getsetattr, compat_sys_waitid 76 .word compat_sys_mq_timedsend, compat_sys_mq_timedreceive, compat_sys_mq_notify, compat_sys_mq_getsetattr, compat_sys_waitid
77/*280*/ .word sys32_tee, sys_add_key, sys_request_key, sys_keyctl, compat_sys_openat 77/*280*/ .word sys32_tee, sys_add_key, sys_request_key, compat_sys_keyctl, compat_sys_openat
78 .word sys_mkdirat, sys_mknodat, sys_fchownat, compat_sys_futimesat, compat_sys_fstatat64 78 .word sys_mkdirat, sys_mknodat, sys_fchownat, compat_sys_futimesat, compat_sys_fstatat64
79/*290*/ .word sys_unlinkat, sys_renameat, sys_linkat, sys_symlinkat, sys_readlinkat 79/*290*/ .word sys_unlinkat, sys_renameat, sys_linkat, sys_symlinkat, sys_readlinkat
80 .word sys_fchmodat, sys_faccessat, compat_sys_pselect6, compat_sys_ppoll, sys_unshare 80 .word sys_fchmodat, sys_faccessat, compat_sys_pselect6, compat_sys_ppoll, sys_unshare
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/ultra.S b/arch/sparc/mm/ultra.S
index b57a5942ba64..874162a11ceb 100644
--- a/arch/sparc/mm/ultra.S
+++ b/arch/sparc/mm/ultra.S
@@ -495,11 +495,11 @@ xcall_fetch_glob_regs:
495 stx %o7, [%g1 + GR_SNAP_O7] 495 stx %o7, [%g1 + GR_SNAP_O7]
496 stx %i7, [%g1 + GR_SNAP_I7] 496 stx %i7, [%g1 + GR_SNAP_I7]
497 /* Don't try this at home kids... */ 497 /* Don't try this at home kids... */
498 rdpr %cwp, %g2 498 rdpr %cwp, %g3
499 sub %g2, 1, %g7 499 sub %g3, 1, %g7
500 wrpr %g7, %cwp 500 wrpr %g7, %cwp
501 mov %i7, %g7 501 mov %i7, %g7
502 wrpr %g2, %cwp 502 wrpr %g3, %cwp
503 stx %g7, [%g1 + GR_SNAP_RPC] 503 stx %g7, [%g1 + GR_SNAP_RPC]
504 sethi %hi(trap_block), %g7 504 sethi %hi(trap_block), %g7
505 or %g7, %lo(trap_block), %g7 505 or %g7, %lo(trap_block), %g7
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/net/Makefile b/arch/sparc/net/Makefile
new file mode 100644
index 000000000000..1306a58ac541
--- /dev/null
+++ b/arch/sparc/net/Makefile
@@ -0,0 +1,4 @@
1#
2# Arch-specific network modules
3#
4obj-$(CONFIG_BPF_JIT) += bpf_jit_asm.o bpf_jit_comp.o
diff --git a/arch/sparc/net/bpf_jit.h b/arch/sparc/net/bpf_jit.h
new file mode 100644
index 000000000000..33d6b375ff12
--- /dev/null
+++ b/arch/sparc/net/bpf_jit.h
@@ -0,0 +1,68 @@
1#ifndef _BPF_JIT_H
2#define _BPF_JIT_H
3
4/* Conventions:
5 * %g1 : temporary
6 * %g2 : Secondary temporary used by SKB data helper stubs.
7 * %g3 : packet offset passed into SKB data helper stubs.
8 * %o0 : pointer to skb (first argument given to JIT function)
9 * %o1 : BPF A accumulator
10 * %o2 : BPF X accumulator
11 * %o3 : Holds saved %o7 so we can call helper functions without needing
12 * to allocate a register window.
13 * %o4 : skb->len - skb->data_len
14 * %o5 : skb->data
15 */
16
17#ifndef __ASSEMBLER__
18#define G0 0x00
19#define G1 0x01
20#define G3 0x03
21#define G6 0x06
22#define O0 0x08
23#define O1 0x09
24#define O2 0x0a
25#define O3 0x0b
26#define O4 0x0c
27#define O5 0x0d
28#define SP 0x0e
29#define O7 0x0f
30#define FP 0x1e
31
32#define r_SKB O0
33#define r_A O1
34#define r_X O2
35#define r_saved_O7 O3
36#define r_HEADLEN O4
37#define r_SKB_DATA O5
38#define r_TMP G1
39#define r_TMP2 G2
40#define r_OFF G3
41
42/* assembly code in arch/sparc/net/bpf_jit_asm.S */
43extern u32 bpf_jit_load_word[];
44extern u32 bpf_jit_load_half[];
45extern u32 bpf_jit_load_byte[];
46extern u32 bpf_jit_load_byte_msh[];
47extern u32 bpf_jit_load_word_positive_offset[];
48extern u32 bpf_jit_load_half_positive_offset[];
49extern u32 bpf_jit_load_byte_positive_offset[];
50extern u32 bpf_jit_load_byte_msh_positive_offset[];
51extern u32 bpf_jit_load_word_negative_offset[];
52extern u32 bpf_jit_load_half_negative_offset[];
53extern u32 bpf_jit_load_byte_negative_offset[];
54extern u32 bpf_jit_load_byte_msh_negative_offset[];
55
56#else
57#define r_SKB %o0
58#define r_A %o1
59#define r_X %o2
60#define r_saved_O7 %o3
61#define r_HEADLEN %o4
62#define r_SKB_DATA %o5
63#define r_TMP %g1
64#define r_TMP2 %g2
65#define r_OFF %g3
66#endif
67
68#endif /* _BPF_JIT_H */
diff --git a/arch/sparc/net/bpf_jit_asm.S b/arch/sparc/net/bpf_jit_asm.S
new file mode 100644
index 000000000000..9d016c7017f7
--- /dev/null
+++ b/arch/sparc/net/bpf_jit_asm.S
@@ -0,0 +1,205 @@
1#include <asm/ptrace.h>
2
3#include "bpf_jit.h"
4
5#ifdef CONFIG_SPARC64
6#define SAVE_SZ 176
7#define SCRATCH_OFF STACK_BIAS + 128
8#define BE_PTR(label) be,pn %xcc, label
9#else
10#define SAVE_SZ 96
11#define SCRATCH_OFF 72
12#define BE_PTR(label) be label
13#endif
14
15#define SKF_MAX_NEG_OFF (-0x200000) /* SKF_LL_OFF from filter.h */
16
17 .text
18 .globl bpf_jit_load_word
19bpf_jit_load_word:
20 cmp r_OFF, 0
21 bl bpf_slow_path_word_neg
22 nop
23 .globl bpf_jit_load_word_positive_offset
24bpf_jit_load_word_positive_offset:
25 sub r_HEADLEN, r_OFF, r_TMP
26 cmp r_TMP, 3
27 ble bpf_slow_path_word
28 add r_SKB_DATA, r_OFF, r_TMP
29 andcc r_TMP, 3, %g0
30 bne load_word_unaligned
31 nop
32 retl
33 ld [r_TMP], r_A
34load_word_unaligned:
35 ldub [r_TMP + 0x0], r_OFF
36 ldub [r_TMP + 0x1], r_TMP2
37 sll r_OFF, 8, r_OFF
38 or r_OFF, r_TMP2, r_OFF
39 ldub [r_TMP + 0x2], r_TMP2
40 sll r_OFF, 8, r_OFF
41 or r_OFF, r_TMP2, r_OFF
42 ldub [r_TMP + 0x3], r_TMP2
43 sll r_OFF, 8, r_OFF
44 retl
45 or r_OFF, r_TMP2, r_A
46
47 .globl bpf_jit_load_half
48bpf_jit_load_half:
49 cmp r_OFF, 0
50 bl bpf_slow_path_half_neg
51 nop
52 .globl bpf_jit_load_half_positive_offset
53bpf_jit_load_half_positive_offset:
54 sub r_HEADLEN, r_OFF, r_TMP
55 cmp r_TMP, 1
56 ble bpf_slow_path_half
57 add r_SKB_DATA, r_OFF, r_TMP
58 andcc r_TMP, 1, %g0
59 bne load_half_unaligned
60 nop
61 retl
62 lduh [r_TMP], r_A
63load_half_unaligned:
64 ldub [r_TMP + 0x0], r_OFF
65 ldub [r_TMP + 0x1], r_TMP2
66 sll r_OFF, 8, r_OFF
67 retl
68 or r_OFF, r_TMP2, r_A
69
70 .globl bpf_jit_load_byte
71bpf_jit_load_byte:
72 cmp r_OFF, 0
73 bl bpf_slow_path_byte_neg
74 nop
75 .globl bpf_jit_load_byte_positive_offset
76bpf_jit_load_byte_positive_offset:
77 cmp r_OFF, r_HEADLEN
78 bge bpf_slow_path_byte
79 nop
80 retl
81 ldub [r_SKB_DATA + r_OFF], r_A
82
83 .globl bpf_jit_load_byte_msh
84bpf_jit_load_byte_msh:
85 cmp r_OFF, 0
86 bl bpf_slow_path_byte_msh_neg
87 nop
88 .globl bpf_jit_load_byte_msh_positive_offset
89bpf_jit_load_byte_msh_positive_offset:
90 cmp r_OFF, r_HEADLEN
91 bge bpf_slow_path_byte_msh
92 nop
93 ldub [r_SKB_DATA + r_OFF], r_OFF
94 and r_OFF, 0xf, r_OFF
95 retl
96 sll r_OFF, 2, r_X
97
98#define bpf_slow_path_common(LEN) \
99 save %sp, -SAVE_SZ, %sp; \
100 mov %i0, %o0; \
101 mov r_OFF, %o1; \
102 add %fp, SCRATCH_OFF, %o2; \
103 call skb_copy_bits; \
104 mov (LEN), %o3; \
105 cmp %o0, 0; \
106 restore;
107
108bpf_slow_path_word:
109 bpf_slow_path_common(4)
110 bl bpf_error
111 ld [%sp + SCRATCH_OFF], r_A
112 retl
113 nop
114bpf_slow_path_half:
115 bpf_slow_path_common(2)
116 bl bpf_error
117 lduh [%sp + SCRATCH_OFF], r_A
118 retl
119 nop
120bpf_slow_path_byte:
121 bpf_slow_path_common(1)
122 bl bpf_error
123 ldub [%sp + SCRATCH_OFF], r_A
124 retl
125 nop
126bpf_slow_path_byte_msh:
127 bpf_slow_path_common(1)
128 bl bpf_error
129 ldub [%sp + SCRATCH_OFF], r_A
130 and r_OFF, 0xf, r_OFF
131 retl
132 sll r_OFF, 2, r_X
133
134#define bpf_negative_common(LEN) \
135 save %sp, -SAVE_SZ, %sp; \
136 mov %i0, %o0; \
137 mov r_OFF, %o1; \
138 call bpf_internal_load_pointer_neg_helper; \
139 mov (LEN), %o2; \
140 mov %o0, r_TMP; \
141 cmp %o0, 0; \
142 BE_PTR(bpf_error); \
143 restore;
144
145bpf_slow_path_word_neg:
146 sethi %hi(SKF_MAX_NEG_OFF), r_TMP
147 cmp r_OFF, r_TMP
148 bl bpf_error
149 nop
150 .globl bpf_jit_load_word_negative_offset
151bpf_jit_load_word_negative_offset:
152 bpf_negative_common(4)
153 andcc r_TMP, 3, %g0
154 bne load_word_unaligned
155 nop
156 retl
157 ld [r_TMP], r_A
158
159bpf_slow_path_half_neg:
160 sethi %hi(SKF_MAX_NEG_OFF), r_TMP
161 cmp r_OFF, r_TMP
162 bl bpf_error
163 nop
164 .globl bpf_jit_load_half_negative_offset
165bpf_jit_load_half_negative_offset:
166 bpf_negative_common(2)
167 andcc r_TMP, 1, %g0
168 bne load_half_unaligned
169 nop
170 retl
171 lduh [r_TMP], r_A
172
173bpf_slow_path_byte_neg:
174 sethi %hi(SKF_MAX_NEG_OFF), r_TMP
175 cmp r_OFF, r_TMP
176 bl bpf_error
177 nop
178 .globl bpf_jit_load_byte_negative_offset
179bpf_jit_load_byte_negative_offset:
180 bpf_negative_common(1)
181 retl
182 ldub [r_TMP], r_A
183
184bpf_slow_path_byte_msh_neg:
185 sethi %hi(SKF_MAX_NEG_OFF), r_TMP
186 cmp r_OFF, r_TMP
187 bl bpf_error
188 nop
189 .globl bpf_jit_load_byte_msh_negative_offset
190bpf_jit_load_byte_msh_negative_offset:
191 bpf_negative_common(1)
192 ldub [r_TMP], r_OFF
193 and r_OFF, 0xf, r_OFF
194 retl
195 sll r_OFF, 2, r_X
196
197bpf_error:
198 /* Make the JIT program return zero. The JIT epilogue
199 * stores away the original %o7 into r_saved_O7. The
200 * normal leaf function return is to use "retl" which
201 * would evalute to "jmpl %o7 + 8, %g0" but we want to
202 * use the saved value thus the sequence you see here.
203 */
204 jmpl r_saved_O7 + 8, %g0
205 clr %o0
diff --git a/arch/sparc/net/bpf_jit_comp.c b/arch/sparc/net/bpf_jit_comp.c
new file mode 100644
index 000000000000..1a69244e785b
--- /dev/null
+++ b/arch/sparc/net/bpf_jit_comp.c
@@ -0,0 +1,802 @@
1#include <linux/moduleloader.h>
2#include <linux/workqueue.h>
3#include <linux/netdevice.h>
4#include <linux/filter.h>
5#include <linux/cache.h>
6
7#include <asm/cacheflush.h>
8#include <asm/ptrace.h>
9
10#include "bpf_jit.h"
11
12int bpf_jit_enable __read_mostly;
13
14static inline bool is_simm13(unsigned int value)
15{
16 return value + 0x1000 < 0x2000;
17}
18
19static void bpf_flush_icache(void *start_, void *end_)
20{
21#ifdef CONFIG_SPARC64
22 /* Cheetah's I-cache is fully coherent. */
23 if (tlb_type == spitfire) {
24 unsigned long start = (unsigned long) start_;
25 unsigned long end = (unsigned long) end_;
26
27 start &= ~7UL;
28 end = (end + 7UL) & ~7UL;
29 while (start < end) {
30 flushi(start);
31 start += 32;
32 }
33 }
34#endif
35}
36
37#define SEEN_DATAREF 1 /* might call external helpers */
38#define SEEN_XREG 2 /* ebx is used */
39#define SEEN_MEM 4 /* use mem[] for temporary storage */
40
41#define S13(X) ((X) & 0x1fff)
42#define IMMED 0x00002000
43#define RD(X) ((X) << 25)
44#define RS1(X) ((X) << 14)
45#define RS2(X) ((X))
46#define OP(X) ((X) << 30)
47#define OP2(X) ((X) << 22)
48#define OP3(X) ((X) << 19)
49#define COND(X) ((X) << 25)
50#define F1(X) OP(X)
51#define F2(X, Y) (OP(X) | OP2(Y))
52#define F3(X, Y) (OP(X) | OP3(Y))
53
54#define CONDN COND(0x0)
55#define CONDE COND(0x1)
56#define CONDLE COND(0x2)
57#define CONDL COND(0x3)
58#define CONDLEU COND(0x4)
59#define CONDCS COND(0x5)
60#define CONDNEG COND(0x6)
61#define CONDVC COND(0x7)
62#define CONDA COND(0x8)
63#define CONDNE COND(0x9)
64#define CONDG COND(0xa)
65#define CONDGE COND(0xb)
66#define CONDGU COND(0xc)
67#define CONDCC COND(0xd)
68#define CONDPOS COND(0xe)
69#define CONDVS COND(0xf)
70
71#define CONDGEU CONDCC
72#define CONDLU CONDCS
73
74#define WDISP22(X) (((X) >> 2) & 0x3fffff)
75
76#define BA (F2(0, 2) | CONDA)
77#define BGU (F2(0, 2) | CONDGU)
78#define BLEU (F2(0, 2) | CONDLEU)
79#define BGEU (F2(0, 2) | CONDGEU)
80#define BLU (F2(0, 2) | CONDLU)
81#define BE (F2(0, 2) | CONDE)
82#define BNE (F2(0, 2) | CONDNE)
83
84#ifdef CONFIG_SPARC64
85#define BNE_PTR (F2(0, 1) | CONDNE | (2 << 20))
86#else
87#define BNE_PTR BNE
88#endif
89
90#define SETHI(K, REG) \
91 (F2(0, 0x4) | RD(REG) | (((K) >> 10) & 0x3fffff))
92#define OR_LO(K, REG) \
93 (F3(2, 0x02) | IMMED | RS1(REG) | ((K) & 0x3ff) | RD(REG))
94
95#define ADD F3(2, 0x00)
96#define AND F3(2, 0x01)
97#define ANDCC F3(2, 0x11)
98#define OR F3(2, 0x02)
99#define SUB F3(2, 0x04)
100#define SUBCC F3(2, 0x14)
101#define MUL F3(2, 0x0a) /* umul */
102#define DIV F3(2, 0x0e) /* udiv */
103#define SLL F3(2, 0x25)
104#define SRL F3(2, 0x26)
105#define JMPL F3(2, 0x38)
106#define CALL F1(1)
107#define BR F2(0, 0x01)
108#define RD_Y F3(2, 0x28)
109#define WR_Y F3(2, 0x30)
110
111#define LD32 F3(3, 0x00)
112#define LD8 F3(3, 0x01)
113#define LD16 F3(3, 0x02)
114#define LD64 F3(3, 0x0b)
115#define ST32 F3(3, 0x04)
116
117#ifdef CONFIG_SPARC64
118#define LDPTR LD64
119#define BASE_STACKFRAME 176
120#else
121#define LDPTR LD32
122#define BASE_STACKFRAME 96
123#endif
124
125#define LD32I (LD32 | IMMED)
126#define LD8I (LD8 | IMMED)
127#define LD16I (LD16 | IMMED)
128#define LD64I (LD64 | IMMED)
129#define LDPTRI (LDPTR | IMMED)
130#define ST32I (ST32 | IMMED)
131
132#define emit_nop() \
133do { \
134 *prog++ = SETHI(0, G0); \
135} while (0)
136
137#define emit_neg() \
138do { /* sub %g0, r_A, r_A */ \
139 *prog++ = SUB | RS1(G0) | RS2(r_A) | RD(r_A); \
140} while (0)
141
142#define emit_reg_move(FROM, TO) \
143do { /* or %g0, FROM, TO */ \
144 *prog++ = OR | RS1(G0) | RS2(FROM) | RD(TO); \
145} while (0)
146
147#define emit_clear(REG) \
148do { /* or %g0, %g0, REG */ \
149 *prog++ = OR | RS1(G0) | RS2(G0) | RD(REG); \
150} while (0)
151
152#define emit_set_const(K, REG) \
153do { /* sethi %hi(K), REG */ \
154 *prog++ = SETHI(K, REG); \
155 /* or REG, %lo(K), REG */ \
156 *prog++ = OR_LO(K, REG); \
157} while (0)
158
159 /* Emit
160 *
161 * OP r_A, r_X, r_A
162 */
163#define emit_alu_X(OPCODE) \
164do { \
165 seen |= SEEN_XREG; \
166 *prog++ = OPCODE | RS1(r_A) | RS2(r_X) | RD(r_A); \
167} while (0)
168
169 /* Emit either:
170 *
171 * OP r_A, K, r_A
172 *
173 * or
174 *
175 * sethi %hi(K), r_TMP
176 * or r_TMP, %lo(K), r_TMP
177 * OP r_A, r_TMP, r_A
178 *
179 * depending upon whether K fits in a signed 13-bit
180 * immediate instruction field. Emit nothing if K
181 * is zero.
182 */
183#define emit_alu_K(OPCODE, K) \
184do { \
185 if (K) { \
186 unsigned int _insn = OPCODE; \
187 _insn |= RS1(r_A) | RD(r_A); \
188 if (is_simm13(K)) { \
189 *prog++ = _insn | IMMED | S13(K); \
190 } else { \
191 emit_set_const(K, r_TMP); \
192 *prog++ = _insn | RS2(r_TMP); \
193 } \
194 } \
195} while (0)
196
197#define emit_loadimm(K, DEST) \
198do { \
199 if (is_simm13(K)) { \
200 /* or %g0, K, DEST */ \
201 *prog++ = OR | IMMED | RS1(G0) | S13(K) | RD(DEST); \
202 } else { \
203 emit_set_const(K, DEST); \
204 } \
205} while (0)
206
207#define emit_loadptr(BASE, STRUCT, FIELD, DEST) \
208do { unsigned int _off = offsetof(STRUCT, FIELD); \
209 BUILD_BUG_ON(FIELD_SIZEOF(STRUCT, FIELD) != sizeof(void *)); \
210 *prog++ = LDPTRI | RS1(BASE) | S13(_off) | RD(DEST); \
211} while (0)
212
213#define emit_load32(BASE, STRUCT, FIELD, DEST) \
214do { unsigned int _off = offsetof(STRUCT, FIELD); \
215 BUILD_BUG_ON(FIELD_SIZEOF(STRUCT, FIELD) != sizeof(u32)); \
216 *prog++ = LD32I | RS1(BASE) | S13(_off) | RD(DEST); \
217} while (0)
218
219#define emit_load16(BASE, STRUCT, FIELD, DEST) \
220do { unsigned int _off = offsetof(STRUCT, FIELD); \
221 BUILD_BUG_ON(FIELD_SIZEOF(STRUCT, FIELD) != sizeof(u16)); \
222 *prog++ = LD16I | RS1(BASE) | S13(_off) | RD(DEST); \
223} while (0)
224
225#define __emit_load8(BASE, STRUCT, FIELD, DEST) \
226do { unsigned int _off = offsetof(STRUCT, FIELD); \
227 *prog++ = LD8I | RS1(BASE) | S13(_off) | RD(DEST); \
228} while (0)
229
230#define emit_load8(BASE, STRUCT, FIELD, DEST) \
231do { BUILD_BUG_ON(FIELD_SIZEOF(STRUCT, FIELD) != sizeof(u8)); \
232 __emit_load8(BASE, STRUCT, FIELD, DEST); \
233} while (0)
234
235#define emit_ldmem(OFF, DEST) \
236do { *prog++ = LD32I | RS1(FP) | S13(-(OFF)) | RD(DEST); \
237} while (0)
238
239#define emit_stmem(OFF, SRC) \
240do { *prog++ = LD32I | RS1(FP) | S13(-(OFF)) | RD(SRC); \
241} while (0)
242
243#ifdef CONFIG_SMP
244#ifdef CONFIG_SPARC64
245#define emit_load_cpu(REG) \
246 emit_load16(G6, struct thread_info, cpu, REG)
247#else
248#define emit_load_cpu(REG) \
249 emit_load32(G6, struct thread_info, cpu, REG)
250#endif
251#else
252#define emit_load_cpu(REG) emit_clear(REG)
253#endif
254
255#define emit_skb_loadptr(FIELD, DEST) \
256 emit_loadptr(r_SKB, struct sk_buff, FIELD, DEST)
257#define emit_skb_load32(FIELD, DEST) \
258 emit_load32(r_SKB, struct sk_buff, FIELD, DEST)
259#define emit_skb_load16(FIELD, DEST) \
260 emit_load16(r_SKB, struct sk_buff, FIELD, DEST)
261#define __emit_skb_load8(FIELD, DEST) \
262 __emit_load8(r_SKB, struct sk_buff, FIELD, DEST)
263#define emit_skb_load8(FIELD, DEST) \
264 emit_load8(r_SKB, struct sk_buff, FIELD, DEST)
265
266#define emit_jmpl(BASE, IMM_OFF, LREG) \
267 *prog++ = (JMPL | IMMED | RS1(BASE) | S13(IMM_OFF) | RD(LREG))
268
269#define emit_call(FUNC) \
270do { void *_here = image + addrs[i] - 8; \
271 unsigned int _off = (void *)(FUNC) - _here; \
272 *prog++ = CALL | (((_off) >> 2) & 0x3fffffff); \
273 emit_nop(); \
274} while (0)
275
276#define emit_branch(BR_OPC, DEST) \
277do { unsigned int _here = addrs[i] - 8; \
278 *prog++ = BR_OPC | WDISP22((DEST) - _here); \
279} while (0)
280
281#define emit_branch_off(BR_OPC, OFF) \
282do { *prog++ = BR_OPC | WDISP22(OFF); \
283} while (0)
284
285#define emit_jump(DEST) emit_branch(BA, DEST)
286
287#define emit_read_y(REG) *prog++ = RD_Y | RD(REG)
288#define emit_write_y(REG) *prog++ = WR_Y | IMMED | RS1(REG) | S13(0)
289
290#define emit_cmp(R1, R2) \
291 *prog++ = (SUBCC | RS1(R1) | RS2(R2) | RD(G0))
292
293#define emit_cmpi(R1, IMM) \
294 *prog++ = (SUBCC | IMMED | RS1(R1) | S13(IMM) | RD(G0));
295
296#define emit_btst(R1, R2) \
297 *prog++ = (ANDCC | RS1(R1) | RS2(R2) | RD(G0))
298
299#define emit_btsti(R1, IMM) \
300 *prog++ = (ANDCC | IMMED | RS1(R1) | S13(IMM) | RD(G0));
301
302#define emit_sub(R1, R2, R3) \
303 *prog++ = (SUB | RS1(R1) | RS2(R2) | RD(R3))
304
305#define emit_subi(R1, IMM, R3) \
306 *prog++ = (SUB | IMMED | RS1(R1) | S13(IMM) | RD(R3))
307
308#define emit_add(R1, R2, R3) \
309 *prog++ = (ADD | RS1(R1) | RS2(R2) | RD(R3))
310
311#define emit_addi(R1, IMM, R3) \
312 *prog++ = (ADD | IMMED | RS1(R1) | S13(IMM) | RD(R3))
313
314#define emit_alloc_stack(SZ) \
315 *prog++ = (SUB | IMMED | RS1(SP) | S13(SZ) | RD(SP))
316
317#define emit_release_stack(SZ) \
318 *prog++ = (ADD | IMMED | RS1(SP) | S13(SZ) | RD(SP))
319
320/* A note about branch offset calculations. The addrs[] array,
321 * indexed by BPF instruction, records the address after all the
322 * sparc instructions emitted for that BPF instruction.
323 *
324 * The most common case is to emit a branch at the end of such
325 * a code sequence. So this would be two instructions, the
326 * branch and it's delay slot.
327 *
328 * Therefore by default the branch emitters calculate the branch
329 * offset field as:
330 *
331 * destination - (addrs[i] - 8)
332 *
333 * This "addrs[i] - 8" is the address of the branch itself or
334 * what "." would be in assembler notation. The "8" part is
335 * how we take into consideration the branch and it's delay
336 * slot mentioned above.
337 *
338 * Sometimes we need to emit a branch earlier in the code
339 * sequence. And in these situations we adjust "destination"
340 * to accomodate this difference. For example, if we needed
341 * to emit a branch (and it's delay slot) right before the
342 * final instruction emitted for a BPF opcode, we'd use
343 * "destination + 4" instead of just plain "destination" above.
344 *
345 * This is why you see all of these funny emit_branch() and
346 * emit_jump() calls with adjusted offsets.
347 */
348
349void bpf_jit_compile(struct sk_filter *fp)
350{
351 unsigned int cleanup_addr, proglen, oldproglen = 0;
352 u32 temp[8], *prog, *func, seen = 0, pass;
353 const struct sock_filter *filter = fp->insns;
354 int i, flen = fp->len, pc_ret0 = -1;
355 unsigned int *addrs;
356 void *image;
357
358 if (!bpf_jit_enable)
359 return;
360
361 addrs = kmalloc(flen * sizeof(*addrs), GFP_KERNEL);
362 if (addrs == NULL)
363 return;
364
365 /* Before first pass, make a rough estimation of addrs[]
366 * each bpf instruction is translated to less than 64 bytes
367 */
368 for (proglen = 0, i = 0; i < flen; i++) {
369 proglen += 64;
370 addrs[i] = proglen;
371 }
372 cleanup_addr = proglen; /* epilogue address */
373 image = NULL;
374 for (pass = 0; pass < 10; pass++) {
375 u8 seen_or_pass0 = (pass == 0) ? (SEEN_XREG | SEEN_DATAREF | SEEN_MEM) : seen;
376
377 /* no prologue/epilogue for trivial filters (RET something) */
378 proglen = 0;
379 prog = temp;
380
381 /* Prologue */
382 if (seen_or_pass0) {
383 if (seen_or_pass0 & SEEN_MEM) {
384 unsigned int sz = BASE_STACKFRAME;
385 sz += BPF_MEMWORDS * sizeof(u32);
386 emit_alloc_stack(sz);
387 }
388
389 /* Make sure we dont leek kernel memory. */
390 if (seen_or_pass0 & SEEN_XREG)
391 emit_clear(r_X);
392
393 /* If this filter needs to access skb data,
394 * load %o4 and %o5 with:
395 * %o4 = skb->len - skb->data_len
396 * %o5 = skb->data
397 * And also back up %o7 into r_saved_O7 so we can
398 * invoke the stubs using 'call'.
399 */
400 if (seen_or_pass0 & SEEN_DATAREF) {
401 emit_load32(r_SKB, struct sk_buff, len, r_HEADLEN);
402 emit_load32(r_SKB, struct sk_buff, data_len, r_TMP);
403 emit_sub(r_HEADLEN, r_TMP, r_HEADLEN);
404 emit_loadptr(r_SKB, struct sk_buff, data, r_SKB_DATA);
405 }
406 }
407 emit_reg_move(O7, r_saved_O7);
408
409 switch (filter[0].code) {
410 case BPF_S_RET_K:
411 case BPF_S_LD_W_LEN:
412 case BPF_S_ANC_PROTOCOL:
413 case BPF_S_ANC_PKTTYPE:
414 case BPF_S_ANC_IFINDEX:
415 case BPF_S_ANC_MARK:
416 case BPF_S_ANC_RXHASH:
417 case BPF_S_ANC_CPU:
418 case BPF_S_ANC_QUEUE:
419 case BPF_S_LD_W_ABS:
420 case BPF_S_LD_H_ABS:
421 case BPF_S_LD_B_ABS:
422 /* The first instruction sets the A register (or is
423 * a "RET 'constant'")
424 */
425 break;
426 default:
427 /* Make sure we dont leak kernel information to the
428 * user.
429 */
430 emit_clear(r_A); /* A = 0 */
431 }
432
433 for (i = 0; i < flen; i++) {
434 unsigned int K = filter[i].k;
435 unsigned int t_offset;
436 unsigned int f_offset;
437 u32 t_op, f_op;
438 int ilen;
439
440 switch (filter[i].code) {
441 case BPF_S_ALU_ADD_X: /* A += X; */
442 emit_alu_X(ADD);
443 break;
444 case BPF_S_ALU_ADD_K: /* A += K; */
445 emit_alu_K(ADD, K);
446 break;
447 case BPF_S_ALU_SUB_X: /* A -= X; */
448 emit_alu_X(SUB);
449 break;
450 case BPF_S_ALU_SUB_K: /* A -= K */
451 emit_alu_K(SUB, K);
452 break;
453 case BPF_S_ALU_AND_X: /* A &= X */
454 emit_alu_X(AND);
455 break;
456 case BPF_S_ALU_AND_K: /* A &= K */
457 emit_alu_K(AND, K);
458 break;
459 case BPF_S_ALU_OR_X: /* A |= X */
460 emit_alu_X(OR);
461 break;
462 case BPF_S_ALU_OR_K: /* A |= K */
463 emit_alu_K(OR, K);
464 break;
465 case BPF_S_ALU_LSH_X: /* A <<= X */
466 emit_alu_X(SLL);
467 break;
468 case BPF_S_ALU_LSH_K: /* A <<= K */
469 emit_alu_K(SLL, K);
470 break;
471 case BPF_S_ALU_RSH_X: /* A >>= X */
472 emit_alu_X(SRL);
473 break;
474 case BPF_S_ALU_RSH_K: /* A >>= K */
475 emit_alu_K(SRL, K);
476 break;
477 case BPF_S_ALU_MUL_X: /* A *= X; */
478 emit_alu_X(MUL);
479 break;
480 case BPF_S_ALU_MUL_K: /* A *= K */
481 emit_alu_K(MUL, K);
482 break;
483 case BPF_S_ALU_DIV_K: /* A /= K */
484 emit_alu_K(MUL, K);
485 emit_read_y(r_A);
486 break;
487 case BPF_S_ALU_DIV_X: /* A /= X; */
488 emit_cmpi(r_X, 0);
489 if (pc_ret0 > 0) {
490 t_offset = addrs[pc_ret0 - 1];
491#ifdef CONFIG_SPARC32
492 emit_branch(BE, t_offset + 20);
493#else
494 emit_branch(BE, t_offset + 8);
495#endif
496 emit_nop(); /* delay slot */
497 } else {
498 emit_branch_off(BNE, 16);
499 emit_nop();
500#ifdef CONFIG_SPARC32
501 emit_jump(cleanup_addr + 20);
502#else
503 emit_jump(cleanup_addr + 8);
504#endif
505 emit_clear(r_A);
506 }
507 emit_write_y(G0);
508#ifdef CONFIG_SPARC32
509 /* The Sparc v8 architecture requires
510 * three instructions between a %y
511 * register write and the first use.
512 */
513 emit_nop();
514 emit_nop();
515 emit_nop();
516#endif
517 emit_alu_X(DIV);
518 break;
519 case BPF_S_ALU_NEG:
520 emit_neg();
521 break;
522 case BPF_S_RET_K:
523 if (!K) {
524 if (pc_ret0 == -1)
525 pc_ret0 = i;
526 emit_clear(r_A);
527 } else {
528 emit_loadimm(K, r_A);
529 }
530 /* Fallthrough */
531 case BPF_S_RET_A:
532 if (seen_or_pass0) {
533 if (i != flen - 1) {
534 emit_jump(cleanup_addr);
535 emit_nop();
536 break;
537 }
538 if (seen_or_pass0 & SEEN_MEM) {
539 unsigned int sz = BASE_STACKFRAME;
540 sz += BPF_MEMWORDS * sizeof(u32);
541 emit_release_stack(sz);
542 }
543 }
544 /* jmpl %r_saved_O7 + 8, %g0 */
545 emit_jmpl(r_saved_O7, 8, G0);
546 emit_reg_move(r_A, O0); /* delay slot */
547 break;
548 case BPF_S_MISC_TAX:
549 seen |= SEEN_XREG;
550 emit_reg_move(r_A, r_X);
551 break;
552 case BPF_S_MISC_TXA:
553 seen |= SEEN_XREG;
554 emit_reg_move(r_X, r_A);
555 break;
556 case BPF_S_ANC_CPU:
557 emit_load_cpu(r_A);
558 break;
559 case BPF_S_ANC_PROTOCOL:
560 emit_skb_load16(protocol, r_A);
561 break;
562#if 0
563 /* GCC won't let us take the address of
564 * a bit field even though we very much
565 * know what we are doing here.
566 */
567 case BPF_S_ANC_PKTTYPE:
568 __emit_skb_load8(pkt_type, r_A);
569 emit_alu_K(SRL, 5);
570 break;
571#endif
572 case BPF_S_ANC_IFINDEX:
573 emit_skb_loadptr(dev, r_A);
574 emit_cmpi(r_A, 0);
575 emit_branch(BNE_PTR, cleanup_addr + 4);
576 emit_nop();
577 emit_load32(r_A, struct net_device, ifindex, r_A);
578 break;
579 case BPF_S_ANC_MARK:
580 emit_skb_load32(mark, r_A);
581 break;
582 case BPF_S_ANC_QUEUE:
583 emit_skb_load16(queue_mapping, r_A);
584 break;
585 case BPF_S_ANC_HATYPE:
586 emit_skb_loadptr(dev, r_A);
587 emit_cmpi(r_A, 0);
588 emit_branch(BNE_PTR, cleanup_addr + 4);
589 emit_nop();
590 emit_load16(r_A, struct net_device, type, r_A);
591 break;
592 case BPF_S_ANC_RXHASH:
593 emit_skb_load32(rxhash, r_A);
594 break;
595
596 case BPF_S_LD_IMM:
597 emit_loadimm(K, r_A);
598 break;
599 case BPF_S_LDX_IMM:
600 emit_loadimm(K, r_X);
601 break;
602 case BPF_S_LD_MEM:
603 emit_ldmem(K * 4, r_A);
604 break;
605 case BPF_S_LDX_MEM:
606 emit_ldmem(K * 4, r_X);
607 break;
608 case BPF_S_ST:
609 emit_stmem(K * 4, r_A);
610 break;
611 case BPF_S_STX:
612 emit_stmem(K * 4, r_X);
613 break;
614
615#define CHOOSE_LOAD_FUNC(K, func) \
616 ((int)K < 0 ? ((int)K >= SKF_LL_OFF ? func##_negative_offset : func) : func##_positive_offset)
617
618 case BPF_S_LD_W_ABS:
619 func = CHOOSE_LOAD_FUNC(K, bpf_jit_load_word);
620common_load: seen |= SEEN_DATAREF;
621 emit_loadimm(K, r_OFF);
622 emit_call(func);
623 break;
624 case BPF_S_LD_H_ABS:
625 func = CHOOSE_LOAD_FUNC(K, bpf_jit_load_half);
626 goto common_load;
627 case BPF_S_LD_B_ABS:
628 func = CHOOSE_LOAD_FUNC(K, bpf_jit_load_byte);
629 goto common_load;
630 case BPF_S_LDX_B_MSH:
631 func = CHOOSE_LOAD_FUNC(K, bpf_jit_load_byte_msh);
632 goto common_load;
633 case BPF_S_LD_W_IND:
634 func = bpf_jit_load_word;
635common_load_ind: seen |= SEEN_DATAREF | SEEN_XREG;
636 if (K) {
637 if (is_simm13(K)) {
638 emit_addi(r_X, K, r_OFF);
639 } else {
640 emit_loadimm(K, r_TMP);
641 emit_add(r_X, r_TMP, r_OFF);
642 }
643 } else {
644 emit_reg_move(r_X, r_OFF);
645 }
646 emit_call(func);
647 break;
648 case BPF_S_LD_H_IND:
649 func = bpf_jit_load_half;
650 goto common_load_ind;
651 case BPF_S_LD_B_IND:
652 func = bpf_jit_load_byte;
653 goto common_load_ind;
654 case BPF_S_JMP_JA:
655 emit_jump(addrs[i + K]);
656 emit_nop();
657 break;
658
659#define COND_SEL(CODE, TOP, FOP) \
660 case CODE: \
661 t_op = TOP; \
662 f_op = FOP; \
663 goto cond_branch
664
665 COND_SEL(BPF_S_JMP_JGT_K, BGU, BLEU);
666 COND_SEL(BPF_S_JMP_JGE_K, BGEU, BLU);
667 COND_SEL(BPF_S_JMP_JEQ_K, BE, BNE);
668 COND_SEL(BPF_S_JMP_JSET_K, BNE, BE);
669 COND_SEL(BPF_S_JMP_JGT_X, BGU, BLEU);
670 COND_SEL(BPF_S_JMP_JGE_X, BGEU, BLU);
671 COND_SEL(BPF_S_JMP_JEQ_X, BE, BNE);
672 COND_SEL(BPF_S_JMP_JSET_X, BNE, BE);
673
674cond_branch: f_offset = addrs[i + filter[i].jf];
675 t_offset = addrs[i + filter[i].jt];
676
677 /* same targets, can avoid doing the test :) */
678 if (filter[i].jt == filter[i].jf) {
679 emit_jump(t_offset);
680 emit_nop();
681 break;
682 }
683
684 switch (filter[i].code) {
685 case BPF_S_JMP_JGT_X:
686 case BPF_S_JMP_JGE_X:
687 case BPF_S_JMP_JEQ_X:
688 seen |= SEEN_XREG;
689 emit_cmp(r_A, r_X);
690 break;
691 case BPF_S_JMP_JSET_X:
692 seen |= SEEN_XREG;
693 emit_btst(r_A, r_X);
694 break;
695 case BPF_S_JMP_JEQ_K:
696 case BPF_S_JMP_JGT_K:
697 case BPF_S_JMP_JGE_K:
698 if (is_simm13(K)) {
699 emit_cmpi(r_A, K);
700 } else {
701 emit_loadimm(K, r_TMP);
702 emit_cmp(r_A, r_TMP);
703 }
704 break;
705 case BPF_S_JMP_JSET_K:
706 if (is_simm13(K)) {
707 emit_btsti(r_A, K);
708 } else {
709 emit_loadimm(K, r_TMP);
710 emit_btst(r_A, r_TMP);
711 }
712 break;
713 }
714 if (filter[i].jt != 0) {
715 if (filter[i].jf)
716 t_offset += 8;
717 emit_branch(t_op, t_offset);
718 emit_nop(); /* delay slot */
719 if (filter[i].jf) {
720 emit_jump(f_offset);
721 emit_nop();
722 }
723 break;
724 }
725 emit_branch(f_op, f_offset);
726 emit_nop(); /* delay slot */
727 break;
728
729 default:
730 /* hmm, too complex filter, give up with jit compiler */
731 goto out;
732 }
733 ilen = (void *) prog - (void *) temp;
734 if (image) {
735 if (unlikely(proglen + ilen > oldproglen)) {
736 pr_err("bpb_jit_compile fatal error\n");
737 kfree(addrs);
738 module_free(NULL, image);
739 return;
740 }
741 memcpy(image + proglen, temp, ilen);
742 }
743 proglen += ilen;
744 addrs[i] = proglen;
745 prog = temp;
746 }
747 /* last bpf instruction is always a RET :
748 * use it to give the cleanup instruction(s) addr
749 */
750 cleanup_addr = proglen - 8; /* jmpl; mov r_A,%o0; */
751 if (seen_or_pass0 & SEEN_MEM)
752 cleanup_addr -= 4; /* add %sp, X, %sp; */
753
754 if (image) {
755 if (proglen != oldproglen)
756 pr_err("bpb_jit_compile proglen=%u != oldproglen=%u\n",
757 proglen, oldproglen);
758 break;
759 }
760 if (proglen == oldproglen) {
761 image = module_alloc(max_t(unsigned int,
762 proglen,
763 sizeof(struct work_struct)));
764 if (!image)
765 goto out;
766 }
767 oldproglen = proglen;
768 }
769
770 if (bpf_jit_enable > 1)
771 pr_err("flen=%d proglen=%u pass=%d image=%p\n",
772 flen, proglen, pass, image);
773
774 if (image) {
775 if (bpf_jit_enable > 1)
776 print_hex_dump(KERN_ERR, "JIT code: ", DUMP_PREFIX_ADDRESS,
777 16, 1, image, proglen, false);
778 bpf_flush_icache(image, image + proglen);
779 fp->bpf_func = (void *)image;
780 }
781out:
782 kfree(addrs);
783 return;
784}
785
786static void jit_free_defer(struct work_struct *arg)
787{
788 module_free(NULL, arg);
789}
790
791/* run from softirq, we must use a work_struct to call
792 * module_free() from process context
793 */
794void bpf_jit_free(struct sk_filter *fp)
795{
796 if (fp->bpf_func != sk_run_filter) {
797 struct work_struct *work = (struct work_struct *)fp->bpf_func;
798
799 INIT_WORK(work, jit_free_defer);
800 schedule_work(work);
801 }
802}
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}