aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGreg Ungerer <gerg@uclinux.org>2011-03-21 23:39:27 -0400
committerGreg Ungerer <gerg@uclinux.org>2011-03-25 00:05:13 -0400
commit66d857b08b8c3ed5c72c361f863cce77d2a978d7 (patch)
tree47222d86f4d78dc0da31baf64188bd2e4b38ac1e
parentd39dd11c3e6a7af5c20bfac40594db36cf270f42 (diff)
m68k: merge m68k and m68knommu arch directories
There is a lot of common code that could be shared between the m68k and m68knommu arch branches. It makes sense to merge the two branches into a single directory structure so that we can more easily share that common code. This is a brute force merge, based on a script from Stephen King <sfking@fdwdc.com>, which was originally written by Arnd Bergmann <arnd@arndb.de>. > The script was inspired by the script Sam Ravnborg used to merge the > includes from m68knommu. For those files common to both arches but > differing in content, the m68k version of the file is renamed to > <file>_mm.<ext> and the m68knommu version of the file is moved into the > corresponding m68k directory and renamed <file>_no.<ext> and a small > wrapper file <file>.<ext> is used to select between the two version. Files > that are common to both but don't differ are removed from the m68knommu > tree and files and directories that are unique to the m68knommu tree are > moved to the m68k tree. Finally, the arch/m68knommu tree is removed. > > To select between the the versions of the files, the wrapper uses > > #ifdef CONFIG_MMU > #include <file>_mm.<ext> > #else > #include <file>_no.<ext> > #endif On top of this file merge I have done a simplistic merge of m68k and m68knommu Kconfig, which primarily attempts to keep existing options and menus in place. Other than a handful of options being moved it produces identical .config outputs on m68k and m68knommu targets I tested it on. With this in place there is now quite a bit of scope for merge cleanups in future patches. Signed-off-by: Greg Ungerer <gerg@uclinux.org>
-rw-r--r--arch/m68k/Kconfig456
-rw-r--r--arch/m68k/Kconfig.debug34
-rw-r--r--arch/m68k/Kconfig.mmu417
-rw-r--r--arch/m68k/Kconfig.nommu (renamed from arch/m68knommu/Kconfig)94
-rw-r--r--arch/m68k/Makefile122
-rw-r--r--arch/m68k/Makefile_mm121
-rw-r--r--arch/m68k/Makefile_no (renamed from arch/m68knommu/Makefile)16
-rw-r--r--arch/m68k/configs/m5208evb_defconfig (renamed from arch/m68knommu/configs/m5208evb_defconfig)2
-rw-r--r--arch/m68k/configs/m5249evb_defconfig (renamed from arch/m68knommu/configs/m5249evb_defconfig)2
-rw-r--r--arch/m68k/configs/m5272c3_defconfig (renamed from arch/m68knommu/configs/m5272c3_defconfig)2
-rw-r--r--arch/m68k/configs/m5275evb_defconfig (renamed from arch/m68knommu/configs/m5275evb_defconfig)2
-rw-r--r--arch/m68k/configs/m5307c3_defconfig (renamed from arch/m68knommu/configs/m5307c3_defconfig)2
-rw-r--r--arch/m68k/configs/m5407c3_defconfig (renamed from arch/m68knommu/configs/m5407c3_defconfig)2
-rw-r--r--arch/m68k/kernel/Makefile18
-rw-r--r--arch/m68k/kernel/Makefile_mm17
-rw-r--r--arch/m68k/kernel/Makefile_no (renamed from arch/m68knommu/kernel/Makefile)0
-rw-r--r--arch/m68k/kernel/asm-offsets.c101
-rw-r--r--arch/m68k/kernel/asm-offsets_mm.c100
-rw-r--r--arch/m68k/kernel/asm-offsets_no.c (renamed from arch/m68knommu/kernel/asm-offsets.c)0
-rw-r--r--arch/m68k/kernel/dma.c135
-rw-r--r--arch/m68k/kernel/dma_mm.c130
-rw-r--r--arch/m68k/kernel/dma_no.c (renamed from arch/m68knommu/kernel/dma.c)0
-rw-r--r--arch/m68k/kernel/entry.S756
-rw-r--r--arch/m68k/kernel/entry_mm.S753
-rw-r--r--arch/m68k/kernel/entry_no.S (renamed from arch/m68knommu/kernel/entry.S)0
-rw-r--r--arch/m68k/kernel/init_task.c (renamed from arch/m68knommu/kernel/init_task.c)0
-rw-r--r--arch/m68k/kernel/irq.c (renamed from arch/m68knommu/kernel/irq.c)0
-rw-r--r--arch/m68k/kernel/m68k_ksyms.c21
-rw-r--r--arch/m68k/kernel/m68k_ksyms_mm.c16
-rw-r--r--arch/m68k/kernel/m68k_ksyms_no.c (renamed from arch/m68knommu/kernel/m68k_ksyms.c)0
-rw-r--r--arch/m68k/kernel/module.c156
-rw-r--r--arch/m68k/kernel/module_mm.c155
-rw-r--r--arch/m68k/kernel/module_no.c (renamed from arch/m68knommu/kernel/module.c)0
-rw-r--r--arch/m68k/kernel/process.c355
-rw-r--r--arch/m68k/kernel/process_mm.c354
-rw-r--r--arch/m68k/kernel/process_no.c (renamed from arch/m68knommu/kernel/process.c)0
-rw-r--r--arch/m68k/kernel/ptrace.c282
-rw-r--r--arch/m68k/kernel/ptrace_mm.c277
-rw-r--r--arch/m68k/kernel/ptrace_no.c (renamed from arch/m68knommu/kernel/ptrace.c)0
-rw-r--r--arch/m68k/kernel/setup.c534
-rw-r--r--arch/m68k/kernel/setup_mm.c533
-rw-r--r--arch/m68k/kernel/setup_no.c (renamed from arch/m68knommu/kernel/setup.c)0
-rw-r--r--arch/m68k/kernel/signal.c1018
-rw-r--r--arch/m68k/kernel/signal_mm.c1017
-rw-r--r--arch/m68k/kernel/signal_no.c (renamed from arch/m68knommu/kernel/signal.c)0
-rw-r--r--arch/m68k/kernel/sys_m68k.c551
-rw-r--r--arch/m68k/kernel/sys_m68k_mm.c546
-rw-r--r--arch/m68k/kernel/sys_m68k_no.c (renamed from arch/m68knommu/kernel/sys_m68k.c)0
-rw-r--r--arch/m68k/kernel/syscalltable.S (renamed from arch/m68knommu/kernel/syscalltable.S)0
-rw-r--r--arch/m68k/kernel/time.c119
-rw-r--r--arch/m68k/kernel/time_mm.c114
-rw-r--r--arch/m68k/kernel/time_no.c (renamed from arch/m68knommu/kernel/time.c)0
-rw-r--r--arch/m68k/kernel/traps.c1208
-rw-r--r--arch/m68k/kernel/traps_mm.c1207
-rw-r--r--arch/m68k/kernel/traps_no.c (renamed from arch/m68knommu/kernel/traps.c)0
-rw-r--r--arch/m68k/kernel/vmlinux.lds.S11
-rw-r--r--arch/m68k/kernel/vmlinux.lds_mm.S10
-rw-r--r--arch/m68k/kernel/vmlinux.lds_no.S (renamed from arch/m68knommu/kernel/vmlinux.lds.S)0
-rw-r--r--arch/m68k/lib/Makefile11
-rw-r--r--arch/m68k/lib/Makefile_mm6
-rw-r--r--arch/m68k/lib/Makefile_no (renamed from arch/m68knommu/lib/Makefile)0
-rw-r--r--arch/m68k/lib/checksum.c430
-rw-r--r--arch/m68k/lib/checksum_mm.c425
-rw-r--r--arch/m68k/lib/checksum_no.c (renamed from arch/m68knommu/lib/checksum.c)0
-rw-r--r--arch/m68k/lib/delay.c (renamed from arch/m68knommu/lib/delay.c)0
-rw-r--r--arch/m68k/lib/divsi3.S (renamed from arch/m68knommu/lib/divsi3.S)0
-rw-r--r--arch/m68k/lib/memcpy.c (renamed from arch/m68knommu/lib/memcpy.c)0
-rw-r--r--arch/m68k/lib/memmove.c (renamed from arch/m68knommu/lib/memmove.c)0
-rw-r--r--arch/m68k/lib/memset.c (renamed from arch/m68knommu/lib/memset.c)0
-rw-r--r--arch/m68k/lib/modsi3.S (renamed from arch/m68knommu/lib/modsi3.S)0
-rw-r--r--arch/m68k/lib/muldi3.c68
-rw-r--r--arch/m68k/lib/muldi3_mm.c (renamed from arch/m68knommu/lib/ashrdi3.c)48
-rw-r--r--arch/m68k/lib/muldi3_no.c (renamed from arch/m68knommu/lib/muldi3.c)0
-rw-r--r--arch/m68k/lib/mulsi3.S (renamed from arch/m68knommu/lib/mulsi3.S)0
-rw-r--r--arch/m68k/lib/udivsi3.S (renamed from arch/m68knommu/lib/udivsi3.S)0
-rw-r--r--arch/m68k/lib/umodsi3.S (renamed from arch/m68knommu/lib/umodsi3.S)0
-rw-r--r--arch/m68k/mm/Makefile13
-rw-r--r--arch/m68k/mm/Makefile_mm8
-rw-r--r--arch/m68k/mm/Makefile_no (renamed from arch/m68knommu/mm/Makefile)0
-rw-r--r--arch/m68k/mm/init.c153
-rw-r--r--arch/m68k/mm/init_mm.c150
-rw-r--r--arch/m68k/mm/init_no.c (renamed from arch/m68knommu/mm/init.c)0
-rw-r--r--arch/m68k/mm/kmap.c368
-rw-r--r--arch/m68k/mm/kmap_mm.c367
-rw-r--r--arch/m68k/mm/kmap_no.c (renamed from arch/m68knommu/mm/kmap.c)0
-rw-r--r--arch/m68k/platform/5206/Makefile (renamed from arch/m68knommu/platform/5206/Makefile)0
-rw-r--r--arch/m68k/platform/5206/config.c (renamed from arch/m68knommu/platform/5206/config.c)0
-rw-r--r--arch/m68k/platform/5206/gpio.c (renamed from arch/m68knommu/platform/5206/gpio.c)0
-rw-r--r--arch/m68k/platform/5206e/Makefile (renamed from arch/m68knommu/platform/5206e/Makefile)0
-rw-r--r--arch/m68k/platform/5206e/config.c (renamed from arch/m68knommu/platform/5206e/config.c)0
-rw-r--r--arch/m68k/platform/5206e/gpio.c (renamed from arch/m68knommu/platform/5206e/gpio.c)0
-rw-r--r--arch/m68k/platform/520x/Makefile (renamed from arch/m68knommu/platform/520x/Makefile)0
-rw-r--r--arch/m68k/platform/520x/config.c (renamed from arch/m68knommu/platform/520x/config.c)0
-rw-r--r--arch/m68k/platform/520x/gpio.c (renamed from arch/m68knommu/platform/520x/gpio.c)0
-rw-r--r--arch/m68k/platform/523x/Makefile (renamed from arch/m68knommu/platform/523x/Makefile)0
-rw-r--r--arch/m68k/platform/523x/config.c (renamed from arch/m68knommu/platform/523x/config.c)0
-rw-r--r--arch/m68k/platform/523x/gpio.c (renamed from arch/m68knommu/platform/523x/gpio.c)0
-rw-r--r--arch/m68k/platform/5249/Makefile (renamed from arch/m68knommu/platform/5249/Makefile)0
-rw-r--r--arch/m68k/platform/5249/config.c (renamed from arch/m68knommu/platform/5249/config.c)0
-rw-r--r--arch/m68k/platform/5249/gpio.c (renamed from arch/m68knommu/platform/5249/gpio.c)0
-rw-r--r--arch/m68k/platform/5249/intc2.c (renamed from arch/m68knommu/platform/5249/intc2.c)0
-rw-r--r--arch/m68k/platform/5272/Makefile (renamed from arch/m68knommu/platform/5272/Makefile)0
-rw-r--r--arch/m68k/platform/5272/config.c (renamed from arch/m68knommu/platform/5272/config.c)0
-rw-r--r--arch/m68k/platform/5272/gpio.c (renamed from arch/m68knommu/platform/5272/gpio.c)0
-rw-r--r--arch/m68k/platform/5272/intc.c (renamed from arch/m68knommu/platform/5272/intc.c)0
-rw-r--r--arch/m68k/platform/527x/Makefile (renamed from arch/m68knommu/platform/527x/Makefile)0
-rw-r--r--arch/m68k/platform/527x/config.c (renamed from arch/m68knommu/platform/527x/config.c)0
-rw-r--r--arch/m68k/platform/527x/gpio.c (renamed from arch/m68knommu/platform/527x/gpio.c)0
-rw-r--r--arch/m68k/platform/528x/Makefile (renamed from arch/m68knommu/platform/528x/Makefile)0
-rw-r--r--arch/m68k/platform/528x/config.c (renamed from arch/m68knommu/platform/528x/config.c)0
-rw-r--r--arch/m68k/platform/528x/gpio.c (renamed from arch/m68knommu/platform/528x/gpio.c)0
-rw-r--r--arch/m68k/platform/5307/Makefile (renamed from arch/m68knommu/platform/5307/Makefile)0
-rw-r--r--arch/m68k/platform/5307/config.c (renamed from arch/m68knommu/platform/5307/config.c)0
-rw-r--r--arch/m68k/platform/5307/gpio.c (renamed from arch/m68knommu/platform/5307/gpio.c)0
-rw-r--r--arch/m68k/platform/5307/nettel.c (renamed from arch/m68knommu/platform/5307/nettel.c)0
-rw-r--r--arch/m68k/platform/532x/Makefile (renamed from arch/m68knommu/platform/532x/Makefile)0
-rw-r--r--arch/m68k/platform/532x/config.c (renamed from arch/m68knommu/platform/532x/config.c)0
-rw-r--r--arch/m68k/platform/532x/gpio.c (renamed from arch/m68knommu/platform/532x/gpio.c)0
-rw-r--r--arch/m68k/platform/5407/Makefile (renamed from arch/m68knommu/platform/5407/Makefile)0
-rw-r--r--arch/m68k/platform/5407/config.c (renamed from arch/m68knommu/platform/5407/config.c)0
-rw-r--r--arch/m68k/platform/5407/gpio.c (renamed from arch/m68knommu/platform/5407/gpio.c)0
-rw-r--r--arch/m68k/platform/54xx/Makefile (renamed from arch/m68knommu/platform/54xx/Makefile)0
-rw-r--r--arch/m68k/platform/54xx/config.c (renamed from arch/m68knommu/platform/54xx/config.c)0
-rw-r--r--arch/m68k/platform/54xx/firebee.c (renamed from arch/m68knommu/platform/54xx/firebee.c)0
-rw-r--r--arch/m68k/platform/68328/Makefile (renamed from arch/m68knommu/platform/68328/Makefile)0
-rw-r--r--arch/m68k/platform/68328/bootlogo.h (renamed from arch/m68knommu/platform/68328/bootlogo.h)0
-rw-r--r--arch/m68k/platform/68328/bootlogo.pl (renamed from arch/m68knommu/platform/68328/bootlogo.pl)0
-rw-r--r--arch/m68k/platform/68328/config.c (renamed from arch/m68knommu/platform/68328/config.c)0
-rw-r--r--arch/m68k/platform/68328/entry.S (renamed from arch/m68knommu/platform/68328/entry.S)0
-rw-r--r--arch/m68k/platform/68328/head-de2.S (renamed from arch/m68knommu/platform/68328/head-de2.S)0
-rw-r--r--arch/m68k/platform/68328/head-pilot.S (renamed from arch/m68knommu/platform/68328/head-pilot.S)0
-rw-r--r--arch/m68k/platform/68328/head-ram.S (renamed from arch/m68knommu/platform/68328/head-ram.S)0
-rw-r--r--arch/m68k/platform/68328/head-rom.S (renamed from arch/m68knommu/platform/68328/head-rom.S)0
-rw-r--r--arch/m68k/platform/68328/ints.c (renamed from arch/m68knommu/platform/68328/ints.c)0
-rw-r--r--arch/m68k/platform/68328/romvec.S (renamed from arch/m68knommu/platform/68328/romvec.S)0
-rw-r--r--arch/m68k/platform/68328/timers.c (renamed from arch/m68knommu/platform/68328/timers.c)0
-rw-r--r--arch/m68k/platform/68360/Makefile (renamed from arch/m68knommu/platform/68360/Makefile)0
-rw-r--r--arch/m68k/platform/68360/commproc.c (renamed from arch/m68knommu/platform/68360/commproc.c)0
-rw-r--r--arch/m68k/platform/68360/config.c (renamed from arch/m68knommu/platform/68360/config.c)0
-rw-r--r--arch/m68k/platform/68360/entry.S (renamed from arch/m68knommu/platform/68360/entry.S)0
-rw-r--r--arch/m68k/platform/68360/head-ram.S (renamed from arch/m68knommu/platform/68360/head-ram.S)0
-rw-r--r--arch/m68k/platform/68360/head-rom.S (renamed from arch/m68knommu/platform/68360/head-rom.S)0
-rw-r--r--arch/m68k/platform/68360/ints.c (renamed from arch/m68knommu/platform/68360/ints.c)0
-rw-r--r--arch/m68k/platform/68EZ328/Makefile (renamed from arch/m68knommu/platform/68EZ328/Makefile)0
-rw-r--r--arch/m68k/platform/68EZ328/bootlogo.h (renamed from arch/m68knommu/platform/68EZ328/bootlogo.h)0
-rw-r--r--arch/m68k/platform/68EZ328/config.c (renamed from arch/m68knommu/platform/68EZ328/config.c)0
-rw-r--r--arch/m68k/platform/68VZ328/Makefile (renamed from arch/m68knommu/platform/68VZ328/Makefile)0
-rw-r--r--arch/m68k/platform/68VZ328/config.c (renamed from arch/m68knommu/platform/68VZ328/config.c)0
-rw-r--r--arch/m68k/platform/Makefile (renamed from arch/m68knommu/platform/Makefile)0
-rw-r--r--arch/m68k/platform/coldfire/Makefile (renamed from arch/m68knommu/platform/coldfire/Makefile)0
-rw-r--r--arch/m68k/platform/coldfire/cache.c (renamed from arch/m68knommu/platform/coldfire/cache.c)0
-rw-r--r--arch/m68k/platform/coldfire/clk.c (renamed from arch/m68knommu/platform/coldfire/clk.c)0
-rw-r--r--arch/m68k/platform/coldfire/dma.c (renamed from arch/m68knommu/platform/coldfire/dma.c)0
-rw-r--r--arch/m68k/platform/coldfire/dma_timer.c (renamed from arch/m68knommu/platform/coldfire/dma_timer.c)0
-rw-r--r--arch/m68k/platform/coldfire/entry.S (renamed from arch/m68knommu/platform/coldfire/entry.S)0
-rw-r--r--arch/m68k/platform/coldfire/gpio.c (renamed from arch/m68knommu/platform/coldfire/gpio.c)0
-rw-r--r--arch/m68k/platform/coldfire/head.S (renamed from arch/m68knommu/platform/coldfire/head.S)0
-rw-r--r--arch/m68k/platform/coldfire/intc-2.c (renamed from arch/m68knommu/platform/coldfire/intc-2.c)0
-rw-r--r--arch/m68k/platform/coldfire/intc-simr.c (renamed from arch/m68knommu/platform/coldfire/intc-simr.c)0
-rw-r--r--arch/m68k/platform/coldfire/intc.c (renamed from arch/m68knommu/platform/coldfire/intc.c)0
-rw-r--r--arch/m68k/platform/coldfire/pinmux.c (renamed from arch/m68knommu/platform/coldfire/pinmux.c)0
-rw-r--r--arch/m68k/platform/coldfire/pit.c (renamed from arch/m68knommu/platform/coldfire/pit.c)0
-rw-r--r--arch/m68k/platform/coldfire/sltimers.c (renamed from arch/m68knommu/platform/coldfire/sltimers.c)0
-rw-r--r--arch/m68k/platform/coldfire/timers.c (renamed from arch/m68knommu/platform/coldfire/timers.c)0
-rw-r--r--arch/m68k/platform/coldfire/vectors.c (renamed from arch/m68knommu/platform/coldfire/vectors.c)0
-rw-r--r--arch/m68knommu/Kconfig.debug35
-rw-r--r--arch/m68knommu/defconfig74
-rw-r--r--arch/m68knommu/kernel/.gitignore1
-rw-r--r--arch/m68knommu/lib/ashldi3.c62
-rw-r--r--arch/m68knommu/lib/lshrdi3.c62
170 files changed, 6916 insertions, 7131 deletions
diff --git a/arch/m68k/Kconfig b/arch/m68k/Kconfig
index 525174d4167..6e056d3c5d0 100644
--- a/arch/m68k/Kconfig
+++ b/arch/m68k/Kconfig
@@ -1,13 +1,11 @@
1config M68K 1config M68K
2 bool 2 bool
3 default y 3 default y
4 select HAVE_AOUT
5 select HAVE_IDE 4 select HAVE_IDE
6 select GENERIC_ATOMIC64 5 select HAVE_AOUT if MMU
7 6 select GENERIC_ATOMIC64 if MMU
8config MMU 7 select HAVE_GENERIC_HARDIRQS if !MMU
9 bool 8 select GENERIC_HARDIRQS_NO_DEPRECATED if !MMU
10 default y
11 9
12config RWSEM_GENERIC_SPINLOCK 10config RWSEM_GENERIC_SPINLOCK
13 bool 11 bool
@@ -34,457 +32,67 @@ config TIME_LOW_RES
34 bool 32 bool
35 default y 33 default y
36 34
37config GENERIC_IOMAP
38 bool
39 default y
40
41config ARCH_MAY_HAVE_PC_FDC
42 bool
43 depends on BROKEN && (Q40 || SUN3X)
44 default y
45
46config NO_IOPORT 35config NO_IOPORT
47 def_bool y 36 def_bool y
48 37
49config NO_DMA 38config NO_DMA
50 def_bool SUN3 39 def_bool (MMU && SUN3) || (!MMU && !COLDFIRE)
51 40
41config ZONE_DMA
42 bool
43 default y
52config HZ 44config HZ
53 int 45 int
46 default 1000 if CLEOPATRA
54 default 100 47 default 100
55 48
56config ARCH_USES_GETTIMEOFFSET
57 def_bool y
58
59source "init/Kconfig" 49source "init/Kconfig"
60 50
61source "kernel/Kconfig.freezer" 51source "kernel/Kconfig.freezer"
62 52
63menu "Platform dependent setup" 53config MMU
64 54 bool "MMU-based Paged Memory Management Support"
65config EISA
66 bool
67 ---help---
68 The Extended Industry Standard Architecture (EISA) bus was
69 developed as an open alternative to the IBM MicroChannel bus.
70
71 The EISA bus provided some of the features of the IBM MicroChannel
72 bus while maintaining backward compatibility with cards made for
73 the older ISA bus. The EISA bus saw limited use between 1988 and
74 1995 when it was made obsolete by the PCI bus.
75
76 Say Y here if you are building a kernel for an EISA-based machine.
77
78 Otherwise, say N.
79
80config MCA
81 bool
82 help
83 MicroChannel Architecture is found in some IBM PS/2 machines and
84 laptops. It is a bus system similar to PCI or ISA. See
85 <file:Documentation/mca.txt> (and especially the web page given
86 there) before attempting to build an MCA bus kernel.
87
88config PCMCIA
89 tristate
90 ---help---
91 Say Y here if you want to attach PCMCIA- or PC-cards to your Linux
92 computer. These are credit-card size devices such as network cards,
93 modems or hard drives often used with laptops computers. There are
94 actually two varieties of these cards: the older 16 bit PCMCIA cards
95 and the newer 32 bit CardBus cards. If you want to use CardBus
96 cards, you need to say Y here and also to "CardBus support" below.
97
98 To use your PC-cards, you will need supporting software from David
99 Hinds' pcmcia-cs package (see the file <file:Documentation/Changes>
100 for location). Please also read the PCMCIA-HOWTO, available from
101 <http://www.tldp.org/docs.html#howto>.
102
103 To compile this driver as modules, choose M here: the
104 modules will be called pcmcia_core and ds.
105
106config AMIGA
107 bool "Amiga support"
108 select MMU_MOTOROLA if MMU
109 help
110 This option enables support for the Amiga series of computers. If
111 you plan to use this kernel on an Amiga, say Y here and browse the
112 material available in <file:Documentation/m68k>; otherwise say N.
113
114config ATARI
115 bool "Atari support"
116 select MMU_MOTOROLA if MMU
117 help
118 This option enables support for the 68000-based Atari series of
119 computers (including the TT, Falcon and Medusa). If you plan to use
120 this kernel on an Atari, say Y here and browse the material
121 available in <file:Documentation/m68k>; otherwise say N.
122
123config MAC
124 bool "Macintosh support"
125 select MMU_MOTOROLA if MMU
126 help
127 This option enables support for the Apple Macintosh series of
128 computers (yes, there is experimental support now, at least for part
129 of the series).
130
131 Say N unless you're willing to code the remaining necessary support.
132 ;)
133
134config NUBUS
135 bool
136 depends on MAC
137 default y
138
139config M68K_L2_CACHE
140 bool
141 depends on MAC
142 default y
143
144config APOLLO
145 bool "Apollo support"
146 select MMU_MOTOROLA if MMU
147 help
148 Say Y here if you want to run Linux on an MC680x0-based Apollo
149 Domain workstation such as the DN3500.
150
151config VME
152 bool "VME (Motorola and BVM) support"
153 select MMU_MOTOROLA if MMU
154 help
155 Say Y here if you want to build a kernel for a 680x0 based VME
156 board. Boards currently supported include Motorola boards MVME147,
157 MVME162, MVME166, MVME167, MVME172, and MVME177. BVME4000 and
158 BVME6000 boards from BVM Ltd are also supported.
159
160config MVME147
161 bool "MVME147 support"
162 depends on VME
163 help
164 Say Y to include support for early Motorola VME boards. This will
165 build a kernel which can run on MVME147 single-board computers. If
166 you select this option you will have to select the appropriate
167 drivers for SCSI, Ethernet and serial ports later on.
168
169config MVME16x
170 bool "MVME162, 166 and 167 support"
171 depends on VME
172 help
173 Say Y to include support for Motorola VME boards. This will build a
174 kernel which can run on MVME162, MVME166, MVME167, MVME172, and
175 MVME177 boards. If you select this option you will have to select
176 the appropriate drivers for SCSI, Ethernet and serial ports later
177 on.
178
179config BVME6000
180 bool "BVME4000 and BVME6000 support"
181 depends on VME
182 help
183 Say Y to include support for VME boards from BVM Ltd. This will
184 build a kernel which can run on BVME4000 and BVME6000 boards. If
185 you select this option you will have to select the appropriate
186 drivers for SCSI, Ethernet and serial ports later on.
187
188config HP300
189 bool "HP9000/300 and HP9000/400 support"
190 select MMU_MOTOROLA if MMU
191 help
192 This option enables support for the HP9000/300 and HP9000/400 series
193 of workstations. Support for these machines is still somewhat
194 experimental. If you plan to try to use the kernel on such a machine
195 say Y here.
196 Everybody else says N.
197
198config DIO
199 bool "DIO bus support"
200 depends on HP300
201 default y 55 default y
202 help 56 help
203 Say Y here to enable support for the "DIO" expansion bus used in 57 Select if you want MMU-based virtualised addressing space
204 HP300 machines. If you are using such a system you almost certainly 58 support by paged memory management. If unsure, say 'Y'.
205 want this.
206
207config SUN3X
208 bool "Sun3x support"
209 select MMU_MOTOROLA if MMU
210 select M68030
211 help
212 This option enables support for the Sun 3x series of workstations.
213 Be warned that this support is very experimental.
214 Note that Sun 3x kernels are not compatible with Sun 3 hardware.
215 General Linux information on the Sun 3x series (now discontinued)
216 is at <http://www.angelfire.com/ca2/tech68k/sun3.html>.
217
218 If you don't want to compile a kernel for a Sun 3x, say N.
219
220config Q40
221 bool "Q40/Q60 support"
222 select MMU_MOTOROLA if MMU
223 help
224 The Q40 is a Motorola 68040-based successor to the Sinclair QL
225 manufactured in Germany. There is an official Q40 home page at
226 <http://www.q40.de/>. This option enables support for the Q40 and
227 Q60. Select your CPU below. For 68LC060 don't forget to enable FPU
228 emulation.
229
230config SUN3
231 bool "Sun3 support"
232 depends on !MMU_MOTOROLA
233 select MMU_SUN3 if MMU
234 select M68020
235 help
236 This option enables support for the Sun 3 series of workstations
237 (3/50, 3/60, 3/1xx, 3/2xx systems). Enabling this option requires
238 that all other hardware types must be disabled, as Sun 3 kernels
239 are incompatible with all other m68k targets (including Sun 3x!).
240
241 If you don't want to compile a kernel exclusively for a Sun 3, say N.
242
243config NATFEAT
244 bool "ARAnyM emulator support"
245 depends on ATARI
246 help
247 This option enables support for ARAnyM native features, such as
248 access to a disk image as /dev/hda.
249
250config NFBLOCK
251 tristate "NatFeat block device support"
252 depends on BLOCK && NATFEAT
253 help
254 Say Y to include support for the ARAnyM NatFeat block device
255 which allows direct access to the hard drives without using
256 the hardware emulation.
257
258config NFCON
259 tristate "NatFeat console driver"
260 depends on NATFEAT
261 help
262 Say Y to include support for the ARAnyM NatFeat console driver
263 which allows the console output to be redirected to the stderr
264 output of ARAnyM.
265
266config NFETH
267 tristate "NatFeat Ethernet support"
268 depends on NET_ETHERNET && NATFEAT
269 help
270 Say Y to include support for the ARAnyM NatFeat network device
271 which will emulate a regular ethernet device while presenting an
272 ethertap device to the host system.
273
274comment "Processor type"
275
276config M68020
277 bool "68020 support"
278 help
279 If you anticipate running this kernel on a computer with a MC68020
280 processor, say Y. Otherwise, say N. Note that the 68020 requires a
281 68851 MMU (Memory Management Unit) to run Linux/m68k, except on the
282 Sun 3, which provides its own version.
283
284config M68030
285 bool "68030 support"
286 depends on !MMU_SUN3
287 help
288 If you anticipate running this kernel on a computer with a MC68030
289 processor, say Y. Otherwise, say N. Note that a MC68EC030 will not
290 work, as it does not include an MMU (Memory Management Unit).
291
292config M68040
293 bool "68040 support"
294 depends on !MMU_SUN3
295 help
296 If you anticipate running this kernel on a computer with a MC68LC040
297 or MC68040 processor, say Y. Otherwise, say N. Note that an
298 MC68EC040 will not work, as it does not include an MMU (Memory
299 Management Unit).
300
301config M68060
302 bool "68060 support"
303 depends on !MMU_SUN3
304 help
305 If you anticipate running this kernel on a computer with a MC68060
306 processor, say Y. Otherwise, say N.
307
308config MMU_MOTOROLA
309 bool
310
311config MMU_SUN3
312 bool
313 depends on MMU && !MMU_MOTOROLA
314
315config M68KFPU_EMU
316 bool "Math emulation support (EXPERIMENTAL)"
317 depends on EXPERIMENTAL
318 help
319 At some point in the future, this will cause floating-point math
320 instructions to be emulated by the kernel on machines that lack a
321 floating-point math coprocessor. Thrill-seekers and chronically
322 sleep-deprived psychotic hacker types can say Y now, everyone else
323 should probably wait a while.
324
325config M68KFPU_EMU_EXTRAPREC
326 bool "Math emulation extra precision"
327 depends on M68KFPU_EMU
328 help
329 The fpu uses normally a few bit more during calculations for
330 correct rounding, the emulator can (often) do the same but this
331 extra calculation can cost quite some time, so you can disable
332 it here. The emulator will then "only" calculate with a 64 bit
333 mantissa and round slightly incorrect, what is more than enough
334 for normal usage.
335
336config M68KFPU_EMU_ONLY
337 bool "Math emulation only kernel"
338 depends on M68KFPU_EMU
339 help
340 This option prevents any floating-point instructions from being
341 compiled into the kernel, thereby the kernel doesn't save any
342 floating point context anymore during task switches, so this
343 kernel will only be usable on machines without a floating-point
344 math coprocessor. This makes the kernel a bit faster as no tests
345 needs to be executed whether a floating-point instruction in the
346 kernel should be executed or not.
347
348config ADVANCED
349 bool "Advanced configuration options"
350 ---help---
351 This gives you access to some advanced options for the CPU. The
352 defaults should be fine for most users, but these options may make
353 it possible for you to improve performance somewhat if you know what
354 you are doing.
355
356 Note that the answer to this question won't directly affect the
357 kernel: saying N will just cause the configurator to skip all
358 the questions about these options.
359 59
360 Most users should say N to this question. 60menu "Platform dependent setup"
361
362config RMW_INSNS
363 bool "Use read-modify-write instructions"
364 depends on ADVANCED
365 ---help---
366 This allows to use certain instructions that work with indivisible
367 read-modify-write bus cycles. While this is faster than the
368 workaround of disabling interrupts, it can conflict with DMA
369 ( = direct memory access) on many Amiga systems, and it is also said
370 to destabilize other machines. It is very likely that this will
371 cause serious problems on any Amiga or Atari Medusa if set. The only
372 configuration where it should work are 68030-based Ataris, where it
373 apparently improves performance. But you've been warned! Unless you
374 really know what you are doing, say N. Try Y only if you're quite
375 adventurous.
376
377config SINGLE_MEMORY_CHUNK
378 bool "Use one physical chunk of memory only" if ADVANCED && !SUN3
379 default y if SUN3
380 select NEED_MULTIPLE_NODES
381 help
382 Ignore all but the first contiguous chunk of physical memory for VM
383 purposes. This will save a few bytes kernel size and may speed up
384 some operations. Say N if not sure.
385 61
386config 060_WRITETHROUGH 62if MMU
387 bool "Use write-through caching for 68060 supervisor accesses" 63source arch/m68k/Kconfig.mmu
388 depends on ADVANCED && M68060 64endif
389 ---help--- 65if !MMU
390 The 68060 generally uses copyback caching of recently accessed data. 66source arch/m68k/Kconfig.nommu
391 Copyback caching means that memory writes will be held in an on-chip 67endif
392 cache and only written back to memory some time later. Saying Y
393 here will force supervisor (kernel) accesses to use writethrough
394 caching. Writethrough caching means that data is written to memory
395 straight away, so that cache and memory data always agree.
396 Writethrough caching is less efficient, but is needed for some
397 drivers on 68060 based systems where the 68060 bus snooping signal
398 is hardwired on. The 53c710 SCSI driver is known to suffer from
399 this problem.
400
401config ARCH_DISCONTIGMEM_ENABLE
402 def_bool !SINGLE_MEMORY_CHUNK
403
404config NODES_SHIFT
405 int
406 default "3"
407 depends on !SINGLE_MEMORY_CHUNK
408 68
409source "mm/Kconfig" 69source "mm/Kconfig"
410 70
411endmenu 71endmenu
412 72
413menu "General setup" 73menu "Executable file formats"
414 74
415source "fs/Kconfig.binfmt" 75source "fs/Kconfig.binfmt"
416 76
417config ZORRO 77endmenu
418 bool "Amiga Zorro (AutoConfig) bus support"
419 depends on AMIGA
420 help
421 This enables support for the Zorro bus in the Amiga. If you have
422 expansion cards in your Amiga that conform to the Amiga
423 AutoConfig(tm) specification, say Y, otherwise N. Note that even
424 expansion cards that do not fit in the Zorro slots but fit in e.g.
425 the CPU slot may fall in this category, so you have to say Y to let
426 Linux use these.
427
428config AMIGA_PCMCIA
429 bool "Amiga 1200/600 PCMCIA support (EXPERIMENTAL)"
430 depends on AMIGA && EXPERIMENTAL
431 help
432 Include support in the kernel for pcmcia on Amiga 1200 and Amiga
433 600. If you intend to use pcmcia cards say Y; otherwise say N.
434
435config STRAM_PROC
436 bool "ST-RAM statistics in /proc"
437 depends on ATARI
438 help
439 Say Y here to report ST-RAM usage statistics in /proc/stram.
440
441config HEARTBEAT
442 bool "Use power LED as a heartbeat" if AMIGA || APOLLO || ATARI || MAC ||Q40
443 default y if !AMIGA && !APOLLO && !ATARI && !MAC && !Q40 && HP300
444 help
445 Use the power-on LED on your machine as a load meter. The exact
446 behavior is platform-dependent, but normally the flash frequency is
447 a hyperbolic function of the 5-minute load average.
448
449# We have a dedicated heartbeat LED. :-)
450config PROC_HARDWARE
451 bool "/proc/hardware support"
452 help
453 Say Y here to support the /proc/hardware file, which gives you
454 access to information about the machine you're running on,
455 including the model, CPU, MMU, clock speed, BogoMIPS rating,
456 and memory size.
457
458config ISA
459 bool
460 depends on Q40 || AMIGA_PCMCIA
461 default y
462 help
463 Find out whether you have ISA slots on your motherboard. ISA is the
464 name of a bus system, i.e. the way the CPU talks to the other stuff
465 inside your box. Other bus systems are PCI, EISA, MicroChannel
466 (MCA) or VESA. ISA is an older system, now being displaced by PCI;
467 newer boards don't support it. If you have ISA, say Y, otherwise N.
468
469config GENERIC_ISA_DMA
470 bool
471 depends on Q40 || AMIGA_PCMCIA
472 default y
473
474config ZONE_DMA
475 bool
476 default y
477 78
478source "drivers/pci/Kconfig" 79if !MMU
80menu "Power management options"
479 81
480source "drivers/zorro/Kconfig" 82config PM
83 bool "Power Management support"
84 help
85 Support processor power management modes
481 86
482endmenu 87endmenu
88endif
483 89
484source "net/Kconfig" 90source "net/Kconfig"
485 91
486source "drivers/Kconfig" 92source "drivers/Kconfig"
487 93
94if MMU
95
488menu "Character devices" 96menu "Character devices"
489 97
490config ATARI_MFPSER 98config ATARI_MFPSER
@@ -627,6 +235,8 @@ config SERIAL_CONSOLE
627 235
628endmenu 236endmenu
629 237
238endif
239
630source "fs/Kconfig" 240source "fs/Kconfig"
631 241
632source "arch/m68k/Kconfig.debug" 242source "arch/m68k/Kconfig.debug"
diff --git a/arch/m68k/Kconfig.debug b/arch/m68k/Kconfig.debug
index f53b6d5300e..2bdb1b01115 100644
--- a/arch/m68k/Kconfig.debug
+++ b/arch/m68k/Kconfig.debug
@@ -2,4 +2,38 @@ menu "Kernel hacking"
2 2
3source "lib/Kconfig.debug" 3source "lib/Kconfig.debug"
4 4
5if !MMU
6
7config FULLDEBUG
8 bool "Full Symbolic/Source Debugging support"
9 help
10 Enable debugging symbols on kernel build.
11
12config HIGHPROFILE
13 bool "Use fast second timer for profiling"
14 depends on COLDFIRE
15 help
16 Use a fast secondary clock to produce profiling information.
17
18config BOOTPARAM
19 bool 'Compiled-in Kernel Boot Parameter'
20
21config BOOTPARAM_STRING
22 string 'Kernel Boot Parameter'
23 default 'console=ttyS0,19200'
24 depends on BOOTPARAM
25
26config NO_KERNEL_MSG
27 bool "Suppress Kernel BUG Messages"
28 help
29 Do not output any debug BUG messages within the kernel.
30
31config BDM_DISABLE
32 bool "Disable BDM signals"
33 depends on (EXPERIMENTAL && COLDFIRE)
34 help
35 Disable the ColdFire CPU's BDM signals.
36
37endif
38
5endmenu 39endmenu
diff --git a/arch/m68k/Kconfig.mmu b/arch/m68k/Kconfig.mmu
new file mode 100644
index 00000000000..16539b1d5d3
--- /dev/null
+++ b/arch/m68k/Kconfig.mmu
@@ -0,0 +1,417 @@
1config GENERIC_IOMAP
2 bool
3 default y
4
5config ARCH_MAY_HAVE_PC_FDC
6 bool
7 depends on BROKEN && (Q40 || SUN3X)
8 default y
9
10config ARCH_USES_GETTIMEOFFSET
11 def_bool y
12
13config EISA
14 bool
15 ---help---
16 The Extended Industry Standard Architecture (EISA) bus was
17 developed as an open alternative to the IBM MicroChannel bus.
18
19 The EISA bus provided some of the features of the IBM MicroChannel
20 bus while maintaining backward compatibility with cards made for
21 the older ISA bus. The EISA bus saw limited use between 1988 and
22 1995 when it was made obsolete by the PCI bus.
23
24 Say Y here if you are building a kernel for an EISA-based machine.
25
26 Otherwise, say N.
27
28config MCA
29 bool
30 help
31 MicroChannel Architecture is found in some IBM PS/2 machines and
32 laptops. It is a bus system similar to PCI or ISA. See
33 <file:Documentation/mca.txt> (and especially the web page given
34 there) before attempting to build an MCA bus kernel.
35
36config PCMCIA
37 tristate
38 ---help---
39 Say Y here if you want to attach PCMCIA- or PC-cards to your Linux
40 computer. These are credit-card size devices such as network cards,
41 modems or hard drives often used with laptops computers. There are
42 actually two varieties of these cards: the older 16 bit PCMCIA cards
43 and the newer 32 bit CardBus cards. If you want to use CardBus
44 cards, you need to say Y here and also to "CardBus support" below.
45
46 To use your PC-cards, you will need supporting software from David
47 Hinds' pcmcia-cs package (see the file <file:Documentation/Changes>
48 for location). Please also read the PCMCIA-HOWTO, available from
49 <http://www.tldp.org/docs.html#howto>.
50
51 To compile this driver as modules, choose M here: the
52 modules will be called pcmcia_core and ds.
53
54config AMIGA
55 bool "Amiga support"
56 select MMU_MOTOROLA if MMU
57 help
58 This option enables support for the Amiga series of computers. If
59 you plan to use this kernel on an Amiga, say Y here and browse the
60 material available in <file:Documentation/m68k>; otherwise say N.
61
62config ATARI
63 bool "Atari support"
64 select MMU_MOTOROLA if MMU
65 help
66 This option enables support for the 68000-based Atari series of
67 computers (including the TT, Falcon and Medusa). If you plan to use
68 this kernel on an Atari, say Y here and browse the material
69 available in <file:Documentation/m68k>; otherwise say N.
70
71config MAC
72 bool "Macintosh support"
73 select MMU_MOTOROLA if MMU
74 help
75 This option enables support for the Apple Macintosh series of
76 computers (yes, there is experimental support now, at least for part
77 of the series).
78
79 Say N unless you're willing to code the remaining necessary support.
80 ;)
81
82config NUBUS
83 bool
84 depends on MAC
85 default y
86
87config M68K_L2_CACHE
88 bool
89 depends on MAC
90 default y
91
92config APOLLO
93 bool "Apollo support"
94 select MMU_MOTOROLA if MMU
95 help
96 Say Y here if you want to run Linux on an MC680x0-based Apollo
97 Domain workstation such as the DN3500.
98
99config VME
100 bool "VME (Motorola and BVM) support"
101 select MMU_MOTOROLA if MMU
102 help
103 Say Y here if you want to build a kernel for a 680x0 based VME
104 board. Boards currently supported include Motorola boards MVME147,
105 MVME162, MVME166, MVME167, MVME172, and MVME177. BVME4000 and
106 BVME6000 boards from BVM Ltd are also supported.
107
108config MVME147
109 bool "MVME147 support"
110 depends on VME
111 help
112 Say Y to include support for early Motorola VME boards. This will
113 build a kernel which can run on MVME147 single-board computers. If
114 you select this option you will have to select the appropriate
115 drivers for SCSI, Ethernet and serial ports later on.
116
117config MVME16x
118 bool "MVME162, 166 and 167 support"
119 depends on VME
120 help
121 Say Y to include support for Motorola VME boards. This will build a
122 kernel which can run on MVME162, MVME166, MVME167, MVME172, and
123 MVME177 boards. If you select this option you will have to select
124 the appropriate drivers for SCSI, Ethernet and serial ports later
125 on.
126
127config BVME6000
128 bool "BVME4000 and BVME6000 support"
129 depends on VME
130 help
131 Say Y to include support for VME boards from BVM Ltd. This will
132 build a kernel which can run on BVME4000 and BVME6000 boards. If
133 you select this option you will have to select the appropriate
134 drivers for SCSI, Ethernet and serial ports later on.
135
136config HP300
137 bool "HP9000/300 and HP9000/400 support"
138 select MMU_MOTOROLA if MMU
139 help
140 This option enables support for the HP9000/300 and HP9000/400 series
141 of workstations. Support for these machines is still somewhat
142 experimental. If you plan to try to use the kernel on such a machine
143 say Y here.
144 Everybody else says N.
145
146config DIO
147 bool "DIO bus support"
148 depends on HP300
149 default y
150 help
151 Say Y here to enable support for the "DIO" expansion bus used in
152 HP300 machines. If you are using such a system you almost certainly
153 want this.
154
155config SUN3X
156 bool "Sun3x support"
157 select MMU_MOTOROLA if MMU
158 select M68030
159 help
160 This option enables support for the Sun 3x series of workstations.
161 Be warned that this support is very experimental.
162 Note that Sun 3x kernels are not compatible with Sun 3 hardware.
163 General Linux information on the Sun 3x series (now discontinued)
164 is at <http://www.angelfire.com/ca2/tech68k/sun3.html>.
165
166 If you don't want to compile a kernel for a Sun 3x, say N.
167
168config Q40
169 bool "Q40/Q60 support"
170 select MMU_MOTOROLA if MMU
171 help
172 The Q40 is a Motorola 68040-based successor to the Sinclair QL
173 manufactured in Germany. There is an official Q40 home page at
174 <http://www.q40.de/>. This option enables support for the Q40 and
175 Q60. Select your CPU below. For 68LC060 don't forget to enable FPU
176 emulation.
177
178config SUN3
179 bool "Sun3 support"
180 depends on !MMU_MOTOROLA
181 select MMU_SUN3 if MMU
182 select M68020
183 help
184 This option enables support for the Sun 3 series of workstations
185 (3/50, 3/60, 3/1xx, 3/2xx systems). Enabling this option requires
186 that all other hardware types must be disabled, as Sun 3 kernels
187 are incompatible with all other m68k targets (including Sun 3x!).
188
189 If you don't want to compile a kernel exclusively for a Sun 3, say N.
190
191config NATFEAT
192 bool "ARAnyM emulator support"
193 depends on ATARI
194 help
195 This option enables support for ARAnyM native features, such as
196 access to a disk image as /dev/hda.
197
198config NFBLOCK
199 tristate "NatFeat block device support"
200 depends on BLOCK && NATFEAT
201 help
202 Say Y to include support for the ARAnyM NatFeat block device
203 which allows direct access to the hard drives without using
204 the hardware emulation.
205
206config NFCON
207 tristate "NatFeat console driver"
208 depends on NATFEAT
209 help
210 Say Y to include support for the ARAnyM NatFeat console driver
211 which allows the console output to be redirected to the stderr
212 output of ARAnyM.
213
214config NFETH
215 tristate "NatFeat Ethernet support"
216 depends on NET_ETHERNET && NATFEAT
217 help
218 Say Y to include support for the ARAnyM NatFeat network device
219 which will emulate a regular ethernet device while presenting an
220 ethertap device to the host system.
221
222comment "Processor type"
223
224config M68020
225 bool "68020 support"
226 help
227 If you anticipate running this kernel on a computer with a MC68020
228 processor, say Y. Otherwise, say N. Note that the 68020 requires a
229 68851 MMU (Memory Management Unit) to run Linux/m68k, except on the
230 Sun 3, which provides its own version.
231
232config M68030
233 bool "68030 support"
234 depends on !MMU_SUN3
235 help
236 If you anticipate running this kernel on a computer with a MC68030
237 processor, say Y. Otherwise, say N. Note that a MC68EC030 will not
238 work, as it does not include an MMU (Memory Management Unit).
239
240config M68040
241 bool "68040 support"
242 depends on !MMU_SUN3
243 help
244 If you anticipate running this kernel on a computer with a MC68LC040
245 or MC68040 processor, say Y. Otherwise, say N. Note that an
246 MC68EC040 will not work, as it does not include an MMU (Memory
247 Management Unit).
248
249config M68060
250 bool "68060 support"
251 depends on !MMU_SUN3
252 help
253 If you anticipate running this kernel on a computer with a MC68060
254 processor, say Y. Otherwise, say N.
255
256config MMU_MOTOROLA
257 bool
258
259config MMU_SUN3
260 bool
261 depends on MMU && !MMU_MOTOROLA
262
263config M68KFPU_EMU
264 bool "Math emulation support (EXPERIMENTAL)"
265 depends on EXPERIMENTAL
266 help
267 At some point in the future, this will cause floating-point math
268 instructions to be emulated by the kernel on machines that lack a
269 floating-point math coprocessor. Thrill-seekers and chronically
270 sleep-deprived psychotic hacker types can say Y now, everyone else
271 should probably wait a while.
272
273config M68KFPU_EMU_EXTRAPREC
274 bool "Math emulation extra precision"
275 depends on M68KFPU_EMU
276 help
277 The fpu uses normally a few bit more during calculations for
278 correct rounding, the emulator can (often) do the same but this
279 extra calculation can cost quite some time, so you can disable
280 it here. The emulator will then "only" calculate with a 64 bit
281 mantissa and round slightly incorrect, what is more than enough
282 for normal usage.
283
284config M68KFPU_EMU_ONLY
285 bool "Math emulation only kernel"
286 depends on M68KFPU_EMU
287 help
288 This option prevents any floating-point instructions from being
289 compiled into the kernel, thereby the kernel doesn't save any
290 floating point context anymore during task switches, so this
291 kernel will only be usable on machines without a floating-point
292 math coprocessor. This makes the kernel a bit faster as no tests
293 needs to be executed whether a floating-point instruction in the
294 kernel should be executed or not.
295
296config ADVANCED
297 bool "Advanced configuration options"
298 ---help---
299 This gives you access to some advanced options for the CPU. The
300 defaults should be fine for most users, but these options may make
301 it possible for you to improve performance somewhat if you know what
302 you are doing.
303
304 Note that the answer to this question won't directly affect the
305 kernel: saying N will just cause the configurator to skip all
306 the questions about these options.
307
308 Most users should say N to this question.
309
310config RMW_INSNS
311 bool "Use read-modify-write instructions"
312 depends on ADVANCED
313 ---help---
314 This allows to use certain instructions that work with indivisible
315 read-modify-write bus cycles. While this is faster than the
316 workaround of disabling interrupts, it can conflict with DMA
317 ( = direct memory access) on many Amiga systems, and it is also said
318 to destabilize other machines. It is very likely that this will
319 cause serious problems on any Amiga or Atari Medusa if set. The only
320 configuration where it should work are 68030-based Ataris, where it
321 apparently improves performance. But you've been warned! Unless you
322 really know what you are doing, say N. Try Y only if you're quite
323 adventurous.
324
325config SINGLE_MEMORY_CHUNK
326 bool "Use one physical chunk of memory only" if ADVANCED && !SUN3
327 default y if SUN3
328 select NEED_MULTIPLE_NODES
329 help
330 Ignore all but the first contiguous chunk of physical memory for VM
331 purposes. This will save a few bytes kernel size and may speed up
332 some operations. Say N if not sure.
333
334config 060_WRITETHROUGH
335 bool "Use write-through caching for 68060 supervisor accesses"
336 depends on ADVANCED && M68060
337 ---help---
338 The 68060 generally uses copyback caching of recently accessed data.
339 Copyback caching means that memory writes will be held in an on-chip
340 cache and only written back to memory some time later. Saying Y
341 here will force supervisor (kernel) accesses to use writethrough
342 caching. Writethrough caching means that data is written to memory
343 straight away, so that cache and memory data always agree.
344 Writethrough caching is less efficient, but is needed for some
345 drivers on 68060 based systems where the 68060 bus snooping signal
346 is hardwired on. The 53c710 SCSI driver is known to suffer from
347 this problem.
348
349config ARCH_DISCONTIGMEM_ENABLE
350 def_bool !SINGLE_MEMORY_CHUNK
351
352config NODES_SHIFT
353 int
354 default "3"
355 depends on !SINGLE_MEMORY_CHUNK
356
357config ZORRO
358 bool "Amiga Zorro (AutoConfig) bus support"
359 depends on AMIGA
360 help
361 This enables support for the Zorro bus in the Amiga. If you have
362 expansion cards in your Amiga that conform to the Amiga
363 AutoConfig(tm) specification, say Y, otherwise N. Note that even
364 expansion cards that do not fit in the Zorro slots but fit in e.g.
365 the CPU slot may fall in this category, so you have to say Y to let
366 Linux use these.
367
368config AMIGA_PCMCIA
369 bool "Amiga 1200/600 PCMCIA support (EXPERIMENTAL)"
370 depends on AMIGA && EXPERIMENTAL
371 help
372 Include support in the kernel for pcmcia on Amiga 1200 and Amiga
373 600. If you intend to use pcmcia cards say Y; otherwise say N.
374
375config STRAM_PROC
376 bool "ST-RAM statistics in /proc"
377 depends on ATARI
378 help
379 Say Y here to report ST-RAM usage statistics in /proc/stram.
380
381config HEARTBEAT
382 bool "Use power LED as a heartbeat" if AMIGA || APOLLO || ATARI || MAC ||Q40
383 default y if !AMIGA && !APOLLO && !ATARI && !MAC && !Q40 && HP300
384 help
385 Use the power-on LED on your machine as a load meter. The exact
386 behavior is platform-dependent, but normally the flash frequency is
387 a hyperbolic function of the 5-minute load average.
388
389# We have a dedicated heartbeat LED. :-)
390config PROC_HARDWARE
391 bool "/proc/hardware support"
392 help
393 Say Y here to support the /proc/hardware file, which gives you
394 access to information about the machine you're running on,
395 including the model, CPU, MMU, clock speed, BogoMIPS rating,
396 and memory size.
397
398config ISA
399 bool
400 depends on Q40 || AMIGA_PCMCIA
401 default y
402 help
403 Find out whether you have ISA slots on your motherboard. ISA is the
404 name of a bus system, i.e. the way the CPU talks to the other stuff
405 inside your box. Other bus systems are PCI, EISA, MicroChannel
406 (MCA) or VESA. ISA is an older system, now being displaced by PCI;
407 newer boards don't support it. If you have ISA, say Y, otherwise N.
408
409config GENERIC_ISA_DMA
410 bool
411 depends on Q40 || AMIGA_PCMCIA
412 default y
413
414source "drivers/pci/Kconfig"
415
416source "drivers/zorro/Kconfig"
417
diff --git a/arch/m68knommu/Kconfig b/arch/m68k/Kconfig.nommu
index b5424cf948e..273bccab951 100644
--- a/arch/m68knommu/Kconfig
+++ b/arch/m68k/Kconfig.nommu
@@ -1,43 +1,7 @@
1config M68K
2 bool
3 default y
4 select HAVE_IDE
5 select HAVE_GENERIC_HARDIRQS
6 select GENERIC_HARDIRQS_NO_DEPRECATED
7
8config MMU
9 bool
10 default n
11
12config NO_DMA
13 bool
14 depends on !COLDFIRE
15 default y
16
17config FPU 1config FPU
18 bool 2 bool
19 default n 3 default n
20 4
21config ZONE_DMA
22 bool
23 default y
24
25config RWSEM_GENERIC_SPINLOCK
26 bool
27 default y
28
29config RWSEM_XCHGADD_ALGORITHM
30 bool
31 default n
32
33config ARCH_HAS_ILOG2_U32
34 bool
35 default n
36
37config ARCH_HAS_ILOG2_U64
38 bool
39 default n
40
41config GENERIC_FIND_NEXT_BIT 5config GENERIC_FIND_NEXT_BIT
42 bool 6 bool
43 default y 7 default y
@@ -46,29 +10,14 @@ config GENERIC_GPIO
46 bool 10 bool
47 default n 11 default n
48 12
49config GENERIC_HWEIGHT
50 bool
51 default y
52
53config GENERIC_CALIBRATE_DELAY
54 bool
55 default y
56
57config GENERIC_CMOS_UPDATE 13config GENERIC_CMOS_UPDATE
58 bool 14 bool
59 default y 15 default y
60 16
61config TIME_LOW_RES
62 bool
63 default y
64
65config GENERIC_CLOCKEVENTS 17config GENERIC_CLOCKEVENTS
66 bool 18 bool
67 default n 19 default n
68 20
69config NO_IOPORT
70 def_bool y
71
72config COLDFIRE_SW_A7 21config COLDFIRE_SW_A7
73 bool 22 bool
74 default n 23 default n
@@ -85,12 +34,6 @@ config HAVE_MBAR
85config HAVE_IPSBAR 34config HAVE_IPSBAR
86 bool 35 bool
87 36
88source "init/Kconfig"
89
90source "kernel/Kconfig.freezer"
91
92menu "Processor type and features"
93
94choice 37choice
95 prompt "CPU" 38 prompt "CPU"
96 default M68EZ328 39 default M68EZ328
@@ -630,11 +573,6 @@ config 4KSTACKS
630 running more threads on a system and also reduces the pressure 573 running more threads on a system and also reduces the pressure
631 on the VM subsystem for higher order allocations. 574 on the VM subsystem for higher order allocations.
632 575
633config HZ
634 int
635 default 1000 if CLEOPATRA
636 default 100
637
638comment "RAM configuration" 576comment "RAM configuration"
639 577
640config RAMBASE 578config RAMBASE
@@ -803,10 +741,6 @@ endif
803 741
804source "kernel/time/Kconfig" 742source "kernel/time/Kconfig"
805 743
806source "mm/Kconfig"
807
808endmenu
809
810config ISA_DMA_API 744config ISA_DMA_API
811 bool 745 bool
812 depends on !M5272 746 depends on !M5272
@@ -814,31 +748,3 @@ config ISA_DMA_API
814 748
815source "drivers/pcmcia/Kconfig" 749source "drivers/pcmcia/Kconfig"
816 750
817menu "Executable file formats"
818
819source "fs/Kconfig.binfmt"
820
821endmenu
822
823menu "Power management options"
824
825config PM
826 bool "Power Management support"
827 help
828 Support processor power management modes
829
830endmenu
831
832source "net/Kconfig"
833
834source "drivers/Kconfig"
835
836source "fs/Kconfig"
837
838source "arch/m68knommu/Kconfig.debug"
839
840source "security/Kconfig"
841
842source "crypto/Kconfig"
843
844source "lib/Kconfig"
diff --git a/arch/m68k/Makefile b/arch/m68k/Makefile
index b793163abc6..be46cadd401 100644
--- a/arch/m68k/Makefile
+++ b/arch/m68k/Makefile
@@ -1,123 +1,7 @@
1#
2# m68k/Makefile
3#
4# This file is included by the global makefile so that you can add your own
5# architecture-specific flags and dependencies. Remember to do have actions
6# for "archclean" and "archdep" for cleaning up and making dependencies for
7# this architecture
8#
9# This file is subject to the terms and conditions of the GNU General Public
10# License. See the file "COPYING" in the main directory of this archive
11# for more details.
12#
13# Copyright (C) 1994 by Hamish Macdonald
14#
15
16KBUILD_DEFCONFIG := multi_defconfig 1KBUILD_DEFCONFIG := multi_defconfig
17 2
18# override top level makefile 3ifdef CONFIG_MMU
19AS += -m68020 4include $(srctree)/arch/m68k/Makefile_mm
20LDFLAGS := -m m68kelf
21KBUILD_LDFLAGS_MODULE += -T $(srctree)/arch/m68k/kernel/module.lds
22ifneq ($(SUBARCH),$(ARCH))
23 ifeq ($(CROSS_COMPILE),)
24 CROSS_COMPILE := $(call cc-cross-prefix, \
25 m68k-linux-gnu- m68k-linux- m68k-unknown-linux-gnu-)
26 endif
27endif
28
29ifdef CONFIG_SUN3
30LDFLAGS_vmlinux = -N
31endif
32
33CHECKFLAGS += -D__mc68000__
34
35# without -fno-strength-reduce the 53c7xx.c driver fails ;-(
36KBUILD_CFLAGS += -pipe -fno-strength-reduce -ffixed-a2
37
38# enable processor switch if compiled only for a single cpu
39ifndef CONFIG_M68020
40ifndef CONFIG_M68030
41
42ifndef CONFIG_M68060
43KBUILD_CFLAGS += -m68040
44endif
45
46ifndef CONFIG_M68040
47KBUILD_CFLAGS += -m68060
48endif
49
50endif
51endif
52
53ifdef CONFIG_KGDB
54# If configured for kgdb support, include debugging infos and keep the
55# frame pointer
56KBUILD_CFLAGS := $(subst -fomit-frame-pointer,,$(KBUILD_CFLAGS)) -g
57endif
58
59ifndef CONFIG_SUN3
60head-y := arch/m68k/kernel/head.o
61else 5else
62head-y := arch/m68k/kernel/sun3-head.o 6include $(srctree)/arch/m68k/Makefile_no
63endif 7endif
64
65core-y += arch/m68k/kernel/ arch/m68k/mm/
66libs-y += arch/m68k/lib/
67
68core-$(CONFIG_Q40) += arch/m68k/q40/
69core-$(CONFIG_AMIGA) += arch/m68k/amiga/
70core-$(CONFIG_ATARI) += arch/m68k/atari/
71core-$(CONFIG_MAC) += arch/m68k/mac/
72core-$(CONFIG_HP300) += arch/m68k/hp300/
73core-$(CONFIG_APOLLO) += arch/m68k/apollo/
74core-$(CONFIG_MVME147) += arch/m68k/mvme147/
75core-$(CONFIG_MVME16x) += arch/m68k/mvme16x/
76core-$(CONFIG_BVME6000) += arch/m68k/bvme6000/
77core-$(CONFIG_SUN3X) += arch/m68k/sun3x/ arch/m68k/sun3/
78core-$(CONFIG_SUN3) += arch/m68k/sun3/ arch/m68k/sun3/prom/
79core-$(CONFIG_NATFEAT) += arch/m68k/emu/
80core-$(CONFIG_M68040) += arch/m68k/fpsp040/
81core-$(CONFIG_M68060) += arch/m68k/ifpsp060/
82core-$(CONFIG_M68KFPU_EMU) += arch/m68k/math-emu/
83
84all: zImage
85
86lilo: vmlinux
87 if [ -f $(INSTALL_PATH)/vmlinux ]; then mv -f $(INSTALL_PATH)/vmlinux $(INSTALL_PATH)/vmlinux.old; fi
88 if [ -f $(INSTALL_PATH)/System.map ]; then mv -f $(INSTALL_PATH)/System.map $(INSTALL_PATH)/System.old; fi
89 cat vmlinux > $(INSTALL_PATH)/vmlinux
90 cp System.map $(INSTALL_PATH)/System.map
91 if [ -x /sbin/lilo ]; then /sbin/lilo; else /etc/lilo/install; fi
92
93zImage compressed: vmlinux.gz
94
95vmlinux.gz: vmlinux
96
97ifndef CONFIG_KGDB
98 cp vmlinux vmlinux.tmp
99 $(STRIP) vmlinux.tmp
100 gzip -9c vmlinux.tmp >vmlinux.gz
101 rm vmlinux.tmp
102else
103 gzip -9c vmlinux >vmlinux.gz
104endif
105
106bzImage: vmlinux.bz2
107
108vmlinux.bz2: vmlinux
109
110ifndef CONFIG_KGDB
111 cp vmlinux vmlinux.tmp
112 $(STRIP) vmlinux.tmp
113 bzip2 -1c vmlinux.tmp >vmlinux.bz2
114 rm vmlinux.tmp
115else
116 bzip2 -1c vmlinux >vmlinux.bz2
117endif
118
119archclean:
120 rm -f vmlinux.gz vmlinux.bz2
121
122install:
123 sh $(srctree)/arch/m68k/install.sh $(KERNELRELEASE) vmlinux.gz System.map "$(INSTALL_PATH)"
diff --git a/arch/m68k/Makefile_mm b/arch/m68k/Makefile_mm
new file mode 100644
index 00000000000..d449b6d5aec
--- /dev/null
+++ b/arch/m68k/Makefile_mm
@@ -0,0 +1,121 @@
1#
2# m68k/Makefile
3#
4# This file is included by the global makefile so that you can add your own
5# architecture-specific flags and dependencies. Remember to do have actions
6# for "archclean" and "archdep" for cleaning up and making dependencies for
7# this architecture
8#
9# This file is subject to the terms and conditions of the GNU General Public
10# License. See the file "COPYING" in the main directory of this archive
11# for more details.
12#
13# Copyright (C) 1994 by Hamish Macdonald
14#
15
16# override top level makefile
17AS += -m68020
18LDFLAGS := -m m68kelf
19KBUILD_LDFLAGS_MODULE += -T $(srctree)/arch/m68k/kernel/module.lds
20ifneq ($(SUBARCH),$(ARCH))
21 ifeq ($(CROSS_COMPILE),)
22 CROSS_COMPILE := $(call cc-cross-prefix, \
23 m68k-linux-gnu- m68k-linux- m68k-unknown-linux-gnu-)
24 endif
25endif
26
27ifdef CONFIG_SUN3
28LDFLAGS_vmlinux = -N
29endif
30
31CHECKFLAGS += -D__mc68000__
32
33# without -fno-strength-reduce the 53c7xx.c driver fails ;-(
34KBUILD_CFLAGS += -pipe -fno-strength-reduce -ffixed-a2
35
36# enable processor switch if compiled only for a single cpu
37ifndef CONFIG_M68020
38ifndef CONFIG_M68030
39
40ifndef CONFIG_M68060
41KBUILD_CFLAGS += -m68040
42endif
43
44ifndef CONFIG_M68040
45KBUILD_CFLAGS += -m68060
46endif
47
48endif
49endif
50
51ifdef CONFIG_KGDB
52# If configured for kgdb support, include debugging infos and keep the
53# frame pointer
54KBUILD_CFLAGS := $(subst -fomit-frame-pointer,,$(KBUILD_CFLAGS)) -g
55endif
56
57ifndef CONFIG_SUN3
58head-y := arch/m68k/kernel/head.o
59else
60head-y := arch/m68k/kernel/sun3-head.o
61endif
62
63core-y += arch/m68k/kernel/ arch/m68k/mm/
64libs-y += arch/m68k/lib/
65
66core-$(CONFIG_Q40) += arch/m68k/q40/
67core-$(CONFIG_AMIGA) += arch/m68k/amiga/
68core-$(CONFIG_ATARI) += arch/m68k/atari/
69core-$(CONFIG_MAC) += arch/m68k/mac/
70core-$(CONFIG_HP300) += arch/m68k/hp300/
71core-$(CONFIG_APOLLO) += arch/m68k/apollo/
72core-$(CONFIG_MVME147) += arch/m68k/mvme147/
73core-$(CONFIG_MVME16x) += arch/m68k/mvme16x/
74core-$(CONFIG_BVME6000) += arch/m68k/bvme6000/
75core-$(CONFIG_SUN3X) += arch/m68k/sun3x/ arch/m68k/sun3/
76core-$(CONFIG_SUN3) += arch/m68k/sun3/ arch/m68k/sun3/prom/
77core-$(CONFIG_NATFEAT) += arch/m68k/emu/
78core-$(CONFIG_M68040) += arch/m68k/fpsp040/
79core-$(CONFIG_M68060) += arch/m68k/ifpsp060/
80core-$(CONFIG_M68KFPU_EMU) += arch/m68k/math-emu/
81
82all: zImage
83
84lilo: vmlinux
85 if [ -f $(INSTALL_PATH)/vmlinux ]; then mv -f $(INSTALL_PATH)/vmlinux $(INSTALL_PATH)/vmlinux.old; fi
86 if [ -f $(INSTALL_PATH)/System.map ]; then mv -f $(INSTALL_PATH)/System.map $(INSTALL_PATH)/System.old; fi
87 cat vmlinux > $(INSTALL_PATH)/vmlinux
88 cp System.map $(INSTALL_PATH)/System.map
89 if [ -x /sbin/lilo ]; then /sbin/lilo; else /etc/lilo/install; fi
90
91zImage compressed: vmlinux.gz
92
93vmlinux.gz: vmlinux
94
95ifndef CONFIG_KGDB
96 cp vmlinux vmlinux.tmp
97 $(STRIP) vmlinux.tmp
98 gzip -9c vmlinux.tmp >vmlinux.gz
99 rm vmlinux.tmp
100else
101 gzip -9c vmlinux >vmlinux.gz
102endif
103
104bzImage: vmlinux.bz2
105
106vmlinux.bz2: vmlinux
107
108ifndef CONFIG_KGDB
109 cp vmlinux vmlinux.tmp
110 $(STRIP) vmlinux.tmp
111 bzip2 -1c vmlinux.tmp >vmlinux.bz2
112 rm vmlinux.tmp
113else
114 bzip2 -1c vmlinux >vmlinux.bz2
115endif
116
117archclean:
118 rm -f vmlinux.gz vmlinux.bz2
119
120install:
121 sh $(srctree)/arch/m68k/install.sh $(KERNELRELEASE) vmlinux.gz System.map "$(INSTALL_PATH)"
diff --git a/arch/m68knommu/Makefile b/arch/m68k/Makefile_no
index 589613fed31..81652ab893e 100644
--- a/arch/m68knommu/Makefile
+++ b/arch/m68k/Makefile_no
@@ -1,5 +1,5 @@
1# 1#
2# arch/m68knommu/Makefile 2# arch/m68k/Makefile
3# 3#
4# This file is subject to the terms and conditions of the GNU General Public 4# This file is subject to the terms and conditions of the GNU General Public
5# License. See the file "COPYING" in the main directory of this archive 5# License. See the file "COPYING" in the main directory of this archive
@@ -8,8 +8,6 @@
8# (C) Copyright 2002, Greg Ungerer <gerg@snapgear.com> 8# (C) Copyright 2002, Greg Ungerer <gerg@snapgear.com>
9# 9#
10 10
11KBUILD_DEFCONFIG := m5208evb_defconfig
12
13platform-$(CONFIG_M68328) := 68328 11platform-$(CONFIG_M68328) := 68328
14platform-$(CONFIG_M68EZ328) := 68EZ328 12platform-$(CONFIG_M68EZ328) := 68EZ328
15platform-$(CONFIG_M68VZ328) := 68VZ328 13platform-$(CONFIG_M68VZ328) := 68VZ328
@@ -82,7 +80,7 @@ cpuclass-$(CONFIG_M68360) := 68360
82CPUCLASS := $(cpuclass-y) 80CPUCLASS := $(cpuclass-y)
83 81
84ifneq ($(CPUCLASS),$(PLATFORM)) 82ifneq ($(CPUCLASS),$(PLATFORM))
85CLASSDIR := arch/m68knommu/platform/$(cpuclass-y)/ 83CLASSDIR := arch/m68k/platform/$(cpuclass-y)/
86endif 84endif
87 85
88export PLATFORM BOARD MODEL CPUCLASS 86export PLATFORM BOARD MODEL CPUCLASS
@@ -114,13 +112,13 @@ KBUILD_CFLAGS += $(cflags-y)
114KBUILD_CFLAGS += -D__linux__ 112KBUILD_CFLAGS += -D__linux__
115KBUILD_CFLAGS += -DUTS_SYSNAME=\"uClinux\" 113KBUILD_CFLAGS += -DUTS_SYSNAME=\"uClinux\"
116 114
117head-y := arch/m68knommu/platform/$(cpuclass-y)/head.o 115head-y := arch/m68k/platform/$(cpuclass-y)/head.o
118 116
119core-y += arch/m68knommu/kernel/ \ 117core-y += arch/m68k/kernel/ \
120 arch/m68knommu/mm/ \ 118 arch/m68k/mm/ \
121 $(CLASSDIR) \ 119 $(CLASSDIR) \
122 arch/m68knommu/platform/$(PLATFORM)/ 120 arch/m68k/platform/$(PLATFORM)/
123libs-y += arch/m68knommu/lib/ 121libs-y += arch/m68k/lib/
124 122
125archclean: 123archclean:
126 124
diff --git a/arch/m68knommu/configs/m5208evb_defconfig b/arch/m68k/configs/m5208evb_defconfig
index 2f5655c577a..c1616824e20 100644
--- a/arch/m68knommu/configs/m5208evb_defconfig
+++ b/arch/m68k/configs/m5208evb_defconfig
@@ -1,3 +1,4 @@
1# CONFIG_MMU is not set
1CONFIG_EXPERIMENTAL=y 2CONFIG_EXPERIMENTAL=y
2CONFIG_LOG_BUF_SHIFT=14 3CONFIG_LOG_BUF_SHIFT=14
3# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set 4# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
@@ -37,6 +38,7 @@ CONFIG_INET=y
37# CONFIG_INET_LRO is not set 38# CONFIG_INET_LRO is not set
38# CONFIG_INET_DIAG is not set 39# CONFIG_INET_DIAG is not set
39# CONFIG_IPV6 is not set 40# CONFIG_IPV6 is not set
41# CONFIG_FW_LOADER is not set
40CONFIG_MTD=y 42CONFIG_MTD=y
41CONFIG_MTD_PARTITIONS=y 43CONFIG_MTD_PARTITIONS=y
42CONFIG_MTD_CHAR=y 44CONFIG_MTD_CHAR=y
diff --git a/arch/m68knommu/configs/m5249evb_defconfig b/arch/m68k/configs/m5249evb_defconfig
index 16df72bfbd4..a6599e42fac 100644
--- a/arch/m68knommu/configs/m5249evb_defconfig
+++ b/arch/m68k/configs/m5249evb_defconfig
@@ -1,3 +1,4 @@
1# CONFIG_MMU is not set
1CONFIG_EXPERIMENTAL=y 2CONFIG_EXPERIMENTAL=y
2CONFIG_LOG_BUF_SHIFT=14 3CONFIG_LOG_BUF_SHIFT=14
3# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set 4# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
@@ -35,6 +36,7 @@ CONFIG_INET=y
35# CONFIG_INET_LRO is not set 36# CONFIG_INET_LRO is not set
36# CONFIG_INET_DIAG is not set 37# CONFIG_INET_DIAG is not set
37# CONFIG_IPV6 is not set 38# CONFIG_IPV6 is not set
39# CONFIG_FW_LOADER is not set
38CONFIG_MTD=y 40CONFIG_MTD=y
39CONFIG_MTD_PARTITIONS=y 41CONFIG_MTD_PARTITIONS=y
40CONFIG_MTD_CHAR=y 42CONFIG_MTD_CHAR=y
diff --git a/arch/m68knommu/configs/m5272c3_defconfig b/arch/m68k/configs/m5272c3_defconfig
index 4e6ea50c7f3..3fa60a57a0f 100644
--- a/arch/m68knommu/configs/m5272c3_defconfig
+++ b/arch/m68k/configs/m5272c3_defconfig
@@ -1,3 +1,4 @@
1# CONFIG_MMU is not set
1CONFIG_EXPERIMENTAL=y 2CONFIG_EXPERIMENTAL=y
2CONFIG_LOG_BUF_SHIFT=14 3CONFIG_LOG_BUF_SHIFT=14
3# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set 4# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
@@ -33,6 +34,7 @@ CONFIG_INET=y
33# CONFIG_INET_LRO is not set 34# CONFIG_INET_LRO is not set
34# CONFIG_INET_DIAG is not set 35# CONFIG_INET_DIAG is not set
35# CONFIG_IPV6 is not set 36# CONFIG_IPV6 is not set
37# CONFIG_FW_LOADER is not set
36CONFIG_MTD=y 38CONFIG_MTD=y
37CONFIG_MTD_PARTITIONS=y 39CONFIG_MTD_PARTITIONS=y
38CONFIG_MTD_CHAR=y 40CONFIG_MTD_CHAR=y
diff --git a/arch/m68knommu/configs/m5275evb_defconfig b/arch/m68k/configs/m5275evb_defconfig
index f3dd74115a3..33c32aeca12 100644
--- a/arch/m68knommu/configs/m5275evb_defconfig
+++ b/arch/m68k/configs/m5275evb_defconfig
@@ -1,3 +1,4 @@
1# CONFIG_MMU is not set
1CONFIG_EXPERIMENTAL=y 2CONFIG_EXPERIMENTAL=y
2CONFIG_LOG_BUF_SHIFT=14 3CONFIG_LOG_BUF_SHIFT=14
3# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set 4# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
@@ -36,6 +37,7 @@ CONFIG_INET=y
36# CONFIG_INET_LRO is not set 37# CONFIG_INET_LRO is not set
37# CONFIG_INET_DIAG is not set 38# CONFIG_INET_DIAG is not set
38# CONFIG_IPV6 is not set 39# CONFIG_IPV6 is not set
40# CONFIG_FW_LOADER is not set
39CONFIG_MTD=y 41CONFIG_MTD=y
40CONFIG_MTD_PARTITIONS=y 42CONFIG_MTD_PARTITIONS=y
41CONFIG_MTD_CHAR=y 43CONFIG_MTD_CHAR=y
diff --git a/arch/m68knommu/configs/m5307c3_defconfig b/arch/m68k/configs/m5307c3_defconfig
index bce0a20c373..43795f41f7c 100644
--- a/arch/m68knommu/configs/m5307c3_defconfig
+++ b/arch/m68k/configs/m5307c3_defconfig
@@ -1,3 +1,4 @@
1# CONFIG_MMU is not set
1CONFIG_EXPERIMENTAL=y 2CONFIG_EXPERIMENTAL=y
2CONFIG_LOG_BUF_SHIFT=14 3CONFIG_LOG_BUF_SHIFT=14
3# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set 4# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
@@ -35,6 +36,7 @@ CONFIG_INET=y
35# CONFIG_INET_LRO is not set 36# CONFIG_INET_LRO is not set
36# CONFIG_INET_DIAG is not set 37# CONFIG_INET_DIAG is not set
37# CONFIG_IPV6 is not set 38# CONFIG_IPV6 is not set
39# CONFIG_FW_LOADER is not set
38CONFIG_MTD=y 40CONFIG_MTD=y
39CONFIG_MTD_PARTITIONS=y 41CONFIG_MTD_PARTITIONS=y
40CONFIG_MTD_CHAR=y 42CONFIG_MTD_CHAR=y
diff --git a/arch/m68knommu/configs/m5407c3_defconfig b/arch/m68k/configs/m5407c3_defconfig
index 618cc32691f..72746c57a57 100644
--- a/arch/m68knommu/configs/m5407c3_defconfig
+++ b/arch/m68k/configs/m5407c3_defconfig
@@ -1,3 +1,4 @@
1# CONFIG_MMU is not set
1CONFIG_EXPERIMENTAL=y 2CONFIG_EXPERIMENTAL=y
2CONFIG_LOG_BUF_SHIFT=14 3CONFIG_LOG_BUF_SHIFT=14
3# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set 4# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
@@ -35,6 +36,7 @@ CONFIG_INET=y
35# CONFIG_INET_LRO is not set 36# CONFIG_INET_LRO is not set
36# CONFIG_INET_DIAG is not set 37# CONFIG_INET_DIAG is not set
37# CONFIG_IPV6 is not set 38# CONFIG_IPV6 is not set
39# CONFIG_FW_LOADER is not set
38CONFIG_MTD=y 40CONFIG_MTD=y
39CONFIG_MTD_PARTITIONS=y 41CONFIG_MTD_PARTITIONS=y
40CONFIG_MTD_CHAR=y 42CONFIG_MTD_CHAR=y
diff --git a/arch/m68k/kernel/Makefile b/arch/m68k/kernel/Makefile
index 55d5d6b680a..c482ebc9dd5 100644
--- a/arch/m68k/kernel/Makefile
+++ b/arch/m68k/kernel/Makefile
@@ -1,17 +1,5 @@
1# 1ifdef CONFIG_MMU
2# Makefile for the linux kernel. 2include arch/m68k/kernel/Makefile_mm
3#
4
5ifndef CONFIG_SUN3
6 extra-y := head.o
7else 3else
8 extra-y := sun3-head.o 4include arch/m68k/kernel/Makefile_no
9endif 5endif
10extra-y += vmlinux.lds
11
12obj-y := entry.o process.o traps.o ints.o signal.o ptrace.o module.o \
13 sys_m68k.o time.o setup.o m68k_ksyms.o devres.o
14
15devres-y = ../../../kernel/irq/devres.o
16
17obj-y$(CONFIG_MMU_SUN3) += dma.o # no, it's not a typo
diff --git a/arch/m68k/kernel/Makefile_mm b/arch/m68k/kernel/Makefile_mm
new file mode 100644
index 00000000000..55d5d6b680a
--- /dev/null
+++ b/arch/m68k/kernel/Makefile_mm
@@ -0,0 +1,17 @@
1#
2# Makefile for the linux kernel.
3#
4
5ifndef CONFIG_SUN3
6 extra-y := head.o
7else
8 extra-y := sun3-head.o
9endif
10extra-y += vmlinux.lds
11
12obj-y := entry.o process.o traps.o ints.o signal.o ptrace.o module.o \
13 sys_m68k.o time.o setup.o m68k_ksyms.o devres.o
14
15devres-y = ../../../kernel/irq/devres.o
16
17obj-y$(CONFIG_MMU_SUN3) += dma.o # no, it's not a typo
diff --git a/arch/m68knommu/kernel/Makefile b/arch/m68k/kernel/Makefile_no
index 37c3fc074c0..37c3fc074c0 100644
--- a/arch/m68knommu/kernel/Makefile
+++ b/arch/m68k/kernel/Makefile_no
diff --git a/arch/m68k/kernel/asm-offsets.c b/arch/m68k/kernel/asm-offsets.c
index 78e59b82ebc..59a69a5c62f 100644
--- a/arch/m68k/kernel/asm-offsets.c
+++ b/arch/m68k/kernel/asm-offsets.c
@@ -1,100 +1,5 @@
1/*
2 * This program is used to generate definitions needed by
3 * assembly language modules.
4 *
5 * We use the technique used in the OSF Mach kernel code:
6 * generate asm statements containing #defines,
7 * compile this file to assembler, and then extract the
8 * #defines from the assembly-language output.
9 */
10
11#define ASM_OFFSETS_C
12
13#include <linux/stddef.h>
14#include <linux/sched.h>
15#include <linux/kernel_stat.h>
16#include <linux/kbuild.h>
17#include <asm/bootinfo.h>
18#include <asm/irq.h>
19#include <asm/amigahw.h>
20#include <linux/font.h>
21
22int main(void)
23{
24 /* offsets into the task struct */
25 DEFINE(TASK_THREAD, offsetof(struct task_struct, thread));
26 DEFINE(TASK_INFO, offsetof(struct task_struct, thread.info));
27 DEFINE(TASK_MM, offsetof(struct task_struct, mm));
28#ifdef CONFIG_MMU 1#ifdef CONFIG_MMU
29 DEFINE(TASK_TINFO, offsetof(struct task_struct, thread.info)); 2#include "asm-offsets_mm.c"
3#else
4#include "asm-offsets_no.c"
30#endif 5#endif
31
32 /* offsets into the thread struct */
33 DEFINE(THREAD_KSP, offsetof(struct thread_struct, ksp));
34 DEFINE(THREAD_USP, offsetof(struct thread_struct, usp));
35 DEFINE(THREAD_SR, offsetof(struct thread_struct, sr));
36 DEFINE(THREAD_FS, offsetof(struct thread_struct, fs));
37 DEFINE(THREAD_CRP, offsetof(struct thread_struct, crp));
38 DEFINE(THREAD_ESP0, offsetof(struct thread_struct, esp0));
39 DEFINE(THREAD_FPREG, offsetof(struct thread_struct, fp));
40 DEFINE(THREAD_FPCNTL, offsetof(struct thread_struct, fpcntl));
41 DEFINE(THREAD_FPSTATE, offsetof(struct thread_struct, fpstate));
42
43 /* offsets into the thread_info struct */
44 DEFINE(TINFO_PREEMPT, offsetof(struct thread_info, preempt_count));
45 DEFINE(TINFO_FLAGS, offsetof(struct thread_info, flags));
46
47 /* offsets into the pt_regs */
48 DEFINE(PT_OFF_D0, offsetof(struct pt_regs, d0));
49 DEFINE(PT_OFF_ORIG_D0, offsetof(struct pt_regs, orig_d0));
50 DEFINE(PT_OFF_D1, offsetof(struct pt_regs, d1));
51 DEFINE(PT_OFF_D2, offsetof(struct pt_regs, d2));
52 DEFINE(PT_OFF_D3, offsetof(struct pt_regs, d3));
53 DEFINE(PT_OFF_D4, offsetof(struct pt_regs, d4));
54 DEFINE(PT_OFF_D5, offsetof(struct pt_regs, d5));
55 DEFINE(PT_OFF_A0, offsetof(struct pt_regs, a0));
56 DEFINE(PT_OFF_A1, offsetof(struct pt_regs, a1));
57 DEFINE(PT_OFF_A2, offsetof(struct pt_regs, a2));
58 DEFINE(PT_OFF_PC, offsetof(struct pt_regs, pc));
59 DEFINE(PT_OFF_SR, offsetof(struct pt_regs, sr));
60 /* bitfields are a bit difficult */
61 DEFINE(PT_OFF_FORMATVEC, offsetof(struct pt_regs, pc) + 4);
62
63 /* offsets into the irq_cpustat_t struct */
64 DEFINE(CPUSTAT_SOFTIRQ_PENDING, offsetof(irq_cpustat_t, __softirq_pending));
65
66 /* offsets into the bi_record struct */
67 DEFINE(BIR_TAG, offsetof(struct bi_record, tag));
68 DEFINE(BIR_SIZE, offsetof(struct bi_record, size));
69 DEFINE(BIR_DATA, offsetof(struct bi_record, data));
70
71 /* offsets into font_desc (drivers/video/console/font.h) */
72 DEFINE(FONT_DESC_IDX, offsetof(struct font_desc, idx));
73 DEFINE(FONT_DESC_NAME, offsetof(struct font_desc, name));
74 DEFINE(FONT_DESC_WIDTH, offsetof(struct font_desc, width));
75 DEFINE(FONT_DESC_HEIGHT, offsetof(struct font_desc, height));
76 DEFINE(FONT_DESC_DATA, offsetof(struct font_desc, data));
77 DEFINE(FONT_DESC_PREF, offsetof(struct font_desc, pref));
78
79 /* signal defines */
80 DEFINE(LSIGSEGV, SIGSEGV);
81 DEFINE(LSEGV_MAPERR, SEGV_MAPERR);
82 DEFINE(LSIGTRAP, SIGTRAP);
83 DEFINE(LTRAP_TRACE, TRAP_TRACE);
84
85 /* offsets into the custom struct */
86 DEFINE(CUSTOMBASE, &amiga_custom);
87 DEFINE(C_INTENAR, offsetof(struct CUSTOM, intenar));
88 DEFINE(C_INTREQR, offsetof(struct CUSTOM, intreqr));
89 DEFINE(C_INTENA, offsetof(struct CUSTOM, intena));
90 DEFINE(C_INTREQ, offsetof(struct CUSTOM, intreq));
91 DEFINE(C_SERDATR, offsetof(struct CUSTOM, serdatr));
92 DEFINE(C_SERDAT, offsetof(struct CUSTOM, serdat));
93 DEFINE(C_SERPER, offsetof(struct CUSTOM, serper));
94 DEFINE(CIAABASE, &ciaa);
95 DEFINE(CIABBASE, &ciab);
96 DEFINE(C_PRA, offsetof(struct CIA, pra));
97 DEFINE(ZTWOBASE, zTwoBase);
98
99 return 0;
100}
diff --git a/arch/m68k/kernel/asm-offsets_mm.c b/arch/m68k/kernel/asm-offsets_mm.c
new file mode 100644
index 00000000000..78e59b82ebc
--- /dev/null
+++ b/arch/m68k/kernel/asm-offsets_mm.c
@@ -0,0 +1,100 @@
1/*
2 * This program is used to generate definitions needed by
3 * assembly language modules.
4 *
5 * We use the technique used in the OSF Mach kernel code:
6 * generate asm statements containing #defines,
7 * compile this file to assembler, and then extract the
8 * #defines from the assembly-language output.
9 */
10
11#define ASM_OFFSETS_C
12
13#include <linux/stddef.h>
14#include <linux/sched.h>
15#include <linux/kernel_stat.h>
16#include <linux/kbuild.h>
17#include <asm/bootinfo.h>
18#include <asm/irq.h>
19#include <asm/amigahw.h>
20#include <linux/font.h>
21
22int main(void)
23{
24 /* offsets into the task struct */
25 DEFINE(TASK_THREAD, offsetof(struct task_struct, thread));
26 DEFINE(TASK_INFO, offsetof(struct task_struct, thread.info));
27 DEFINE(TASK_MM, offsetof(struct task_struct, mm));
28#ifdef CONFIG_MMU
29 DEFINE(TASK_TINFO, offsetof(struct task_struct, thread.info));
30#endif
31
32 /* offsets into the thread struct */
33 DEFINE(THREAD_KSP, offsetof(struct thread_struct, ksp));
34 DEFINE(THREAD_USP, offsetof(struct thread_struct, usp));
35 DEFINE(THREAD_SR, offsetof(struct thread_struct, sr));
36 DEFINE(THREAD_FS, offsetof(struct thread_struct, fs));
37 DEFINE(THREAD_CRP, offsetof(struct thread_struct, crp));
38 DEFINE(THREAD_ESP0, offsetof(struct thread_struct, esp0));
39 DEFINE(THREAD_FPREG, offsetof(struct thread_struct, fp));
40 DEFINE(THREAD_FPCNTL, offsetof(struct thread_struct, fpcntl));
41 DEFINE(THREAD_FPSTATE, offsetof(struct thread_struct, fpstate));
42
43 /* offsets into the thread_info struct */
44 DEFINE(TINFO_PREEMPT, offsetof(struct thread_info, preempt_count));
45 DEFINE(TINFO_FLAGS, offsetof(struct thread_info, flags));
46
47 /* offsets into the pt_regs */
48 DEFINE(PT_OFF_D0, offsetof(struct pt_regs, d0));
49 DEFINE(PT_OFF_ORIG_D0, offsetof(struct pt_regs, orig_d0));
50 DEFINE(PT_OFF_D1, offsetof(struct pt_regs, d1));
51 DEFINE(PT_OFF_D2, offsetof(struct pt_regs, d2));
52 DEFINE(PT_OFF_D3, offsetof(struct pt_regs, d3));
53 DEFINE(PT_OFF_D4, offsetof(struct pt_regs, d4));
54 DEFINE(PT_OFF_D5, offsetof(struct pt_regs, d5));
55 DEFINE(PT_OFF_A0, offsetof(struct pt_regs, a0));
56 DEFINE(PT_OFF_A1, offsetof(struct pt_regs, a1));
57 DEFINE(PT_OFF_A2, offsetof(struct pt_regs, a2));
58 DEFINE(PT_OFF_PC, offsetof(struct pt_regs, pc));
59 DEFINE(PT_OFF_SR, offsetof(struct pt_regs, sr));
60 /* bitfields are a bit difficult */
61 DEFINE(PT_OFF_FORMATVEC, offsetof(struct pt_regs, pc) + 4);
62
63 /* offsets into the irq_cpustat_t struct */
64 DEFINE(CPUSTAT_SOFTIRQ_PENDING, offsetof(irq_cpustat_t, __softirq_pending));
65
66 /* offsets into the bi_record struct */
67 DEFINE(BIR_TAG, offsetof(struct bi_record, tag));
68 DEFINE(BIR_SIZE, offsetof(struct bi_record, size));
69 DEFINE(BIR_DATA, offsetof(struct bi_record, data));
70
71 /* offsets into font_desc (drivers/video/console/font.h) */
72 DEFINE(FONT_DESC_IDX, offsetof(struct font_desc, idx));
73 DEFINE(FONT_DESC_NAME, offsetof(struct font_desc, name));
74 DEFINE(FONT_DESC_WIDTH, offsetof(struct font_desc, width));
75 DEFINE(FONT_DESC_HEIGHT, offsetof(struct font_desc, height));
76 DEFINE(FONT_DESC_DATA, offsetof(struct font_desc, data));
77 DEFINE(FONT_DESC_PREF, offsetof(struct font_desc, pref));
78
79 /* signal defines */
80 DEFINE(LSIGSEGV, SIGSEGV);
81 DEFINE(LSEGV_MAPERR, SEGV_MAPERR);
82 DEFINE(LSIGTRAP, SIGTRAP);
83 DEFINE(LTRAP_TRACE, TRAP_TRACE);
84
85 /* offsets into the custom struct */
86 DEFINE(CUSTOMBASE, &amiga_custom);
87 DEFINE(C_INTENAR, offsetof(struct CUSTOM, intenar));
88 DEFINE(C_INTREQR, offsetof(struct CUSTOM, intreqr));
89 DEFINE(C_INTENA, offsetof(struct CUSTOM, intena));
90 DEFINE(C_INTREQ, offsetof(struct CUSTOM, intreq));
91 DEFINE(C_SERDATR, offsetof(struct CUSTOM, serdatr));
92 DEFINE(C_SERDAT, offsetof(struct CUSTOM, serdat));
93 DEFINE(C_SERPER, offsetof(struct CUSTOM, serper));
94 DEFINE(CIAABASE, &ciaa);
95 DEFINE(CIABBASE, &ciab);
96 DEFINE(C_PRA, offsetof(struct CIA, pra));
97 DEFINE(ZTWOBASE, zTwoBase);
98
99 return 0;
100}
diff --git a/arch/m68knommu/kernel/asm-offsets.c b/arch/m68k/kernel/asm-offsets_no.c
index ffe02f41ad4..ffe02f41ad4 100644
--- a/arch/m68knommu/kernel/asm-offsets.c
+++ b/arch/m68k/kernel/asm-offsets_no.c
diff --git a/arch/m68k/kernel/dma.c b/arch/m68k/kernel/dma.c
index 4bbb3c2a888..90e8cb726c8 100644
--- a/arch/m68k/kernel/dma.c
+++ b/arch/m68k/kernel/dma.c
@@ -1,130 +1,5 @@
1/* 1#ifdef CONFIG_MMU
2 * This file is subject to the terms and conditions of the GNU General Public 2#include "dma_mm.c"
3 * License. See the file COPYING in the main directory of this archive 3#else
4 * for more details. 4#include "dma_no.c"
5 */ 5#endif
6
7#undef DEBUG
8
9#include <linux/dma-mapping.h>
10#include <linux/device.h>
11#include <linux/kernel.h>
12#include <linux/scatterlist.h>
13#include <linux/slab.h>
14#include <linux/vmalloc.h>
15
16#include <asm/pgalloc.h>
17
18void *dma_alloc_coherent(struct device *dev, size_t size,
19 dma_addr_t *handle, gfp_t flag)
20{
21 struct page *page, **map;
22 pgprot_t pgprot;
23 void *addr;
24 int i, order;
25
26 pr_debug("dma_alloc_coherent: %d,%x\n", size, flag);
27
28 size = PAGE_ALIGN(size);
29 order = get_order(size);
30
31 page = alloc_pages(flag, order);
32 if (!page)
33 return NULL;
34
35 *handle = page_to_phys(page);
36 map = kmalloc(sizeof(struct page *) << order, flag & ~__GFP_DMA);
37 if (!map) {
38 __free_pages(page, order);
39 return NULL;
40 }
41 split_page(page, order);
42
43 order = 1 << order;
44 size >>= PAGE_SHIFT;
45 map[0] = page;
46 for (i = 1; i < size; i++)
47 map[i] = page + i;
48 for (; i < order; i++)
49 __free_page(page + i);
50 pgprot = __pgprot(_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_DIRTY);
51 if (CPU_IS_040_OR_060)
52 pgprot_val(pgprot) |= _PAGE_GLOBAL040 | _PAGE_NOCACHE_S;
53 else
54 pgprot_val(pgprot) |= _PAGE_NOCACHE030;
55 addr = vmap(map, size, VM_MAP, pgprot);
56 kfree(map);
57
58 return addr;
59}
60EXPORT_SYMBOL(dma_alloc_coherent);
61
62void dma_free_coherent(struct device *dev, size_t size,
63 void *addr, dma_addr_t handle)
64{
65 pr_debug("dma_free_coherent: %p, %x\n", addr, handle);
66 vfree(addr);
67}
68EXPORT_SYMBOL(dma_free_coherent);
69
70void dma_sync_single_for_device(struct device *dev, dma_addr_t handle,
71 size_t size, enum dma_data_direction dir)
72{
73 switch (dir) {
74 case DMA_TO_DEVICE:
75 cache_push(handle, size);
76 break;
77 case DMA_FROM_DEVICE:
78 cache_clear(handle, size);
79 break;
80 default:
81 if (printk_ratelimit())
82 printk("dma_sync_single_for_device: unsupported dir %u\n", dir);
83 break;
84 }
85}
86EXPORT_SYMBOL(dma_sync_single_for_device);
87
88void dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, int nents,
89 enum dma_data_direction dir)
90{
91 int i;
92
93 for (i = 0; i < nents; sg++, i++)
94 dma_sync_single_for_device(dev, sg->dma_address, sg->length, dir);
95}
96EXPORT_SYMBOL(dma_sync_sg_for_device);
97
98dma_addr_t dma_map_single(struct device *dev, void *addr, size_t size,
99 enum dma_data_direction dir)
100{
101 dma_addr_t handle = virt_to_bus(addr);
102
103 dma_sync_single_for_device(dev, handle, size, dir);
104 return handle;
105}
106EXPORT_SYMBOL(dma_map_single);
107
108dma_addr_t dma_map_page(struct device *dev, struct page *page,
109 unsigned long offset, size_t size,
110 enum dma_data_direction dir)
111{
112 dma_addr_t handle = page_to_phys(page) + offset;
113
114 dma_sync_single_for_device(dev, handle, size, dir);
115 return handle;
116}
117EXPORT_SYMBOL(dma_map_page);
118
119int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
120 enum dma_data_direction dir)
121{
122 int i;
123
124 for (i = 0; i < nents; sg++, i++) {
125 sg->dma_address = sg_phys(sg);
126 dma_sync_single_for_device(dev, sg->dma_address, sg->length, dir);
127 }
128 return nents;
129}
130EXPORT_SYMBOL(dma_map_sg);
diff --git a/arch/m68k/kernel/dma_mm.c b/arch/m68k/kernel/dma_mm.c
new file mode 100644
index 00000000000..4bbb3c2a888
--- /dev/null
+++ b/arch/m68k/kernel/dma_mm.c
@@ -0,0 +1,130 @@
1/*
2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file COPYING in the main directory of this archive
4 * for more details.
5 */
6
7#undef DEBUG
8
9#include <linux/dma-mapping.h>
10#include <linux/device.h>
11#include <linux/kernel.h>
12#include <linux/scatterlist.h>
13#include <linux/slab.h>
14#include <linux/vmalloc.h>
15
16#include <asm/pgalloc.h>
17
18void *dma_alloc_coherent(struct device *dev, size_t size,
19 dma_addr_t *handle, gfp_t flag)
20{
21 struct page *page, **map;
22 pgprot_t pgprot;
23 void *addr;
24 int i, order;
25
26 pr_debug("dma_alloc_coherent: %d,%x\n", size, flag);
27
28 size = PAGE_ALIGN(size);
29 order = get_order(size);
30
31 page = alloc_pages(flag, order);
32 if (!page)
33 return NULL;
34
35 *handle = page_to_phys(page);
36 map = kmalloc(sizeof(struct page *) << order, flag & ~__GFP_DMA);
37 if (!map) {
38 __free_pages(page, order);
39 return NULL;
40 }
41 split_page(page, order);
42
43 order = 1 << order;
44 size >>= PAGE_SHIFT;
45 map[0] = page;
46 for (i = 1; i < size; i++)
47 map[i] = page + i;
48 for (; i < order; i++)
49 __free_page(page + i);
50 pgprot = __pgprot(_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_DIRTY);
51 if (CPU_IS_040_OR_060)
52 pgprot_val(pgprot) |= _PAGE_GLOBAL040 | _PAGE_NOCACHE_S;
53 else
54 pgprot_val(pgprot) |= _PAGE_NOCACHE030;
55 addr = vmap(map, size, VM_MAP, pgprot);
56 kfree(map);
57
58 return addr;
59}
60EXPORT_SYMBOL(dma_alloc_coherent);
61
62void dma_free_coherent(struct device *dev, size_t size,
63 void *addr, dma_addr_t handle)
64{
65 pr_debug("dma_free_coherent: %p, %x\n", addr, handle);
66 vfree(addr);
67}
68EXPORT_SYMBOL(dma_free_coherent);
69
70void dma_sync_single_for_device(struct device *dev, dma_addr_t handle,
71 size_t size, enum dma_data_direction dir)
72{
73 switch (dir) {
74 case DMA_TO_DEVICE:
75 cache_push(handle, size);
76 break;
77 case DMA_FROM_DEVICE:
78 cache_clear(handle, size);
79 break;
80 default:
81 if (printk_ratelimit())
82 printk("dma_sync_single_for_device: unsupported dir %u\n", dir);
83 break;
84 }
85}
86EXPORT_SYMBOL(dma_sync_single_for_device);
87
88void dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, int nents,
89 enum dma_data_direction dir)
90{
91 int i;
92
93 for (i = 0; i < nents; sg++, i++)
94 dma_sync_single_for_device(dev, sg->dma_address, sg->length, dir);
95}
96EXPORT_SYMBOL(dma_sync_sg_for_device);
97
98dma_addr_t dma_map_single(struct device *dev, void *addr, size_t size,
99 enum dma_data_direction dir)
100{
101 dma_addr_t handle = virt_to_bus(addr);
102
103 dma_sync_single_for_device(dev, handle, size, dir);
104 return handle;
105}
106EXPORT_SYMBOL(dma_map_single);
107
108dma_addr_t dma_map_page(struct device *dev, struct page *page,
109 unsigned long offset, size_t size,
110 enum dma_data_direction dir)
111{
112 dma_addr_t handle = page_to_phys(page) + offset;
113
114 dma_sync_single_for_device(dev, handle, size, dir);
115 return handle;
116}
117EXPORT_SYMBOL(dma_map_page);
118
119int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
120 enum dma_data_direction dir)
121{
122 int i;
123
124 for (i = 0; i < nents; sg++, i++) {
125 sg->dma_address = sg_phys(sg);
126 dma_sync_single_for_device(dev, sg->dma_address, sg->length, dir);
127 }
128 return nents;
129}
130EXPORT_SYMBOL(dma_map_sg);
diff --git a/arch/m68knommu/kernel/dma.c b/arch/m68k/kernel/dma_no.c
index fc61541aeb7..fc61541aeb7 100644
--- a/arch/m68knommu/kernel/dma.c
+++ b/arch/m68k/kernel/dma_no.c
diff --git a/arch/m68k/kernel/entry.S b/arch/m68k/kernel/entry.S
index 1559dea36e5..081cf96f243 100644
--- a/arch/m68k/kernel/entry.S
+++ b/arch/m68k/kernel/entry.S
@@ -1,753 +1,5 @@
1/* -*- mode: asm -*- 1#ifdef CONFIG_MMU
2 * 2#include "entry_mm.S"
3 * linux/arch/m68k/kernel/entry.S 3#else
4 * 4#include "entry_no.S"
5 * Copyright (C) 1991, 1992 Linus Torvalds
6 *
7 * This file is subject to the terms and conditions of the GNU General Public
8 * License. See the file README.legal in the main directory of this archive
9 * for more details.
10 *
11 * Linux/m68k support by Hamish Macdonald
12 *
13 * 68060 fixes by Jesper Skov
14 *
15 */
16
17/*
18 * entry.S contains the system-call and fault low-level handling routines.
19 * This also contains the timer-interrupt handler, as well as all interrupts
20 * and faults that can result in a task-switch.
21 *
22 * NOTE: This code handles signal-recognition, which happens every time
23 * after a timer-interrupt and after each system call.
24 *
25 */
26
27/*
28 * 12/03/96 Jes: Currently we only support m68k single-cpu systems, so
29 * all pointers that used to be 'current' are now entry
30 * number 0 in the 'current_set' list.
31 *
32 * 6/05/00 RZ: addedd writeback completion after return from sighandler
33 * for 68040
34 */
35
36#include <linux/linkage.h>
37#include <asm/entry.h>
38#include <asm/errno.h>
39#include <asm/setup.h>
40#include <asm/segment.h>
41#include <asm/traps.h>
42#include <asm/unistd.h>
43
44#include <asm/asm-offsets.h>
45
46.globl system_call, buserr, trap, resume
47.globl sys_call_table
48.globl sys_fork, sys_clone, sys_vfork
49.globl ret_from_interrupt, bad_interrupt
50.globl auto_irqhandler_fixup
51.globl user_irqvec_fixup, user_irqhandler_fixup
52
53.text
54ENTRY(buserr)
55 SAVE_ALL_INT
56 GET_CURRENT(%d0)
57 movel %sp,%sp@- | stack frame pointer argument
58 bsrl buserr_c
59 addql #4,%sp
60 jra .Lret_from_exception
61
62ENTRY(trap)
63 SAVE_ALL_INT
64 GET_CURRENT(%d0)
65 movel %sp,%sp@- | stack frame pointer argument
66 bsrl trap_c
67 addql #4,%sp
68 jra .Lret_from_exception
69
70 | After a fork we jump here directly from resume,
71 | so that %d1 contains the previous task
72 | schedule_tail now used regardless of CONFIG_SMP
73ENTRY(ret_from_fork)
74 movel %d1,%sp@-
75 jsr schedule_tail
76 addql #4,%sp
77 jra .Lret_from_exception
78
79do_trace_entry:
80 movel #-ENOSYS,%sp@(PT_OFF_D0)| needed for strace
81 subql #4,%sp
82 SAVE_SWITCH_STACK
83 jbsr syscall_trace
84 RESTORE_SWITCH_STACK
85 addql #4,%sp
86 movel %sp@(PT_OFF_ORIG_D0),%d0
87 cmpl #NR_syscalls,%d0
88 jcs syscall
89badsys:
90 movel #-ENOSYS,%sp@(PT_OFF_D0)
91 jra ret_from_syscall
92
93do_trace_exit:
94 subql #4,%sp
95 SAVE_SWITCH_STACK
96 jbsr syscall_trace
97 RESTORE_SWITCH_STACK
98 addql #4,%sp
99 jra .Lret_from_exception
100
101ENTRY(ret_from_signal)
102 tstb %curptr@(TASK_INFO+TINFO_FLAGS+2)
103 jge 1f
104 jbsr syscall_trace
1051: RESTORE_SWITCH_STACK
106 addql #4,%sp
107/* on 68040 complete pending writebacks if any */
108#ifdef CONFIG_M68040
109 bfextu %sp@(PT_OFF_FORMATVEC){#0,#4},%d0
110 subql #7,%d0 | bus error frame ?
111 jbne 1f
112 movel %sp,%sp@-
113 jbsr berr_040cleanup
114 addql #4,%sp
1151:
116#endif 5#endif
117 jra .Lret_from_exception
118
119ENTRY(system_call)
120 SAVE_ALL_SYS
121
122 GET_CURRENT(%d1)
123 | save top of frame
124 movel %sp,%curptr@(TASK_THREAD+THREAD_ESP0)
125
126 | syscall trace?
127 tstb %curptr@(TASK_INFO+TINFO_FLAGS+2)
128 jmi do_trace_entry
129 cmpl #NR_syscalls,%d0
130 jcc badsys
131syscall:
132 jbsr @(sys_call_table,%d0:l:4)@(0)
133 movel %d0,%sp@(PT_OFF_D0) | save the return value
134ret_from_syscall:
135 |oriw #0x0700,%sr
136 movew %curptr@(TASK_INFO+TINFO_FLAGS+2),%d0
137 jne syscall_exit_work
1381: RESTORE_ALL
139
140syscall_exit_work:
141 btst #5,%sp@(PT_OFF_SR) | check if returning to kernel
142 bnes 1b | if so, skip resched, signals
143 lslw #1,%d0
144 jcs do_trace_exit
145 jmi do_delayed_trace
146 lslw #8,%d0
147 jmi do_signal_return
148 pea resume_userspace
149 jra schedule
150
151
152ENTRY(ret_from_exception)
153.Lret_from_exception:
154 btst #5,%sp@(PT_OFF_SR) | check if returning to kernel
155 bnes 1f | if so, skip resched, signals
156 | only allow interrupts when we are really the last one on the
157 | kernel stack, otherwise stack overflow can occur during
158 | heavy interrupt load
159 andw #ALLOWINT,%sr
160
161resume_userspace:
162 moveb %curptr@(TASK_INFO+TINFO_FLAGS+3),%d0
163 jne exit_work
1641: RESTORE_ALL
165
166exit_work:
167 | save top of frame
168 movel %sp,%curptr@(TASK_THREAD+THREAD_ESP0)
169 lslb #1,%d0
170 jmi do_signal_return
171 pea resume_userspace
172 jra schedule
173
174
175do_signal_return:
176 |andw #ALLOWINT,%sr
177 subql #4,%sp | dummy return address
178 SAVE_SWITCH_STACK
179 pea %sp@(SWITCH_STACK_SIZE)
180 bsrl do_signal
181 addql #4,%sp
182 RESTORE_SWITCH_STACK
183 addql #4,%sp
184 jbra resume_userspace
185
186do_delayed_trace:
187 bclr #7,%sp@(PT_OFF_SR) | clear trace bit in SR
188 pea 1 | send SIGTRAP
189 movel %curptr,%sp@-
190 pea LSIGTRAP
191 jbsr send_sig
192 addql #8,%sp
193 addql #4,%sp
194 jbra resume_userspace
195
196
197/* This is the main interrupt handler for autovector interrupts */
198
199ENTRY(auto_inthandler)
200 SAVE_ALL_INT
201 GET_CURRENT(%d0)
202 addqb #1,%curptr@(TASK_INFO+TINFO_PREEMPT+1)
203 | put exception # in d0
204 bfextu %sp@(PT_OFF_FORMATVEC){#4,#10},%d0
205 subw #VEC_SPUR,%d0
206
207 movel %sp,%sp@-
208 movel %d0,%sp@- | put vector # on stack
209auto_irqhandler_fixup = . + 2
210 jsr __m68k_handle_int | process the IRQ
211 addql #8,%sp | pop parameters off stack
212
213ret_from_interrupt:
214 subqb #1,%curptr@(TASK_INFO+TINFO_PREEMPT+1)
215 jeq ret_from_last_interrupt
2162: RESTORE_ALL
217
218 ALIGN
219ret_from_last_interrupt:
220 moveq #(~ALLOWINT>>8)&0xff,%d0
221 andb %sp@(PT_OFF_SR),%d0
222 jne 2b
223
224 /* check if we need to do software interrupts */
225 tstl irq_stat+CPUSTAT_SOFTIRQ_PENDING
226 jeq .Lret_from_exception
227 pea ret_from_exception
228 jra do_softirq
229
230/* Handler for user defined interrupt vectors */
231
232ENTRY(user_inthandler)
233 SAVE_ALL_INT
234 GET_CURRENT(%d0)
235 addqb #1,%curptr@(TASK_INFO+TINFO_PREEMPT+1)
236 | put exception # in d0
237 bfextu %sp@(PT_OFF_FORMATVEC){#4,#10},%d0
238user_irqvec_fixup = . + 2
239 subw #VEC_USER,%d0
240
241 movel %sp,%sp@-
242 movel %d0,%sp@- | put vector # on stack
243user_irqhandler_fixup = . + 2
244 jsr __m68k_handle_int | process the IRQ
245 addql #8,%sp | pop parameters off stack
246
247 subqb #1,%curptr@(TASK_INFO+TINFO_PREEMPT+1)
248 jeq ret_from_last_interrupt
249 RESTORE_ALL
250
251/* Handler for uninitialized and spurious interrupts */
252
253ENTRY(bad_inthandler)
254 SAVE_ALL_INT
255 GET_CURRENT(%d0)
256 addqb #1,%curptr@(TASK_INFO+TINFO_PREEMPT+1)
257
258 movel %sp,%sp@-
259 jsr handle_badint
260 addql #4,%sp
261
262 subqb #1,%curptr@(TASK_INFO+TINFO_PREEMPT+1)
263 jeq ret_from_last_interrupt
264 RESTORE_ALL
265
266
267ENTRY(sys_fork)
268 SAVE_SWITCH_STACK
269 pea %sp@(SWITCH_STACK_SIZE)
270 jbsr m68k_fork
271 addql #4,%sp
272 RESTORE_SWITCH_STACK
273 rts
274
275ENTRY(sys_clone)
276 SAVE_SWITCH_STACK
277 pea %sp@(SWITCH_STACK_SIZE)
278 jbsr m68k_clone
279 addql #4,%sp
280 RESTORE_SWITCH_STACK
281 rts
282
283ENTRY(sys_vfork)
284 SAVE_SWITCH_STACK
285 pea %sp@(SWITCH_STACK_SIZE)
286 jbsr m68k_vfork
287 addql #4,%sp
288 RESTORE_SWITCH_STACK
289 rts
290
291ENTRY(sys_sigreturn)
292 SAVE_SWITCH_STACK
293 jbsr do_sigreturn
294 RESTORE_SWITCH_STACK
295 rts
296
297ENTRY(sys_rt_sigreturn)
298 SAVE_SWITCH_STACK
299 jbsr do_rt_sigreturn
300 RESTORE_SWITCH_STACK
301 rts
302
303resume:
304 /*
305 * Beware - when entering resume, prev (the current task) is
306 * in a0, next (the new task) is in a1,so don't change these
307 * registers until their contents are no longer needed.
308 */
309
310 /* save sr */
311 movew %sr,%a0@(TASK_THREAD+THREAD_SR)
312
313 /* save fs (sfc,%dfc) (may be pointing to kernel memory) */
314 movec %sfc,%d0
315 movew %d0,%a0@(TASK_THREAD+THREAD_FS)
316
317 /* save usp */
318 /* it is better to use a movel here instead of a movew 8*) */
319 movec %usp,%d0
320 movel %d0,%a0@(TASK_THREAD+THREAD_USP)
321
322 /* save non-scratch registers on stack */
323 SAVE_SWITCH_STACK
324
325 /* save current kernel stack pointer */
326 movel %sp,%a0@(TASK_THREAD+THREAD_KSP)
327
328 /* save floating point context */
329#ifndef CONFIG_M68KFPU_EMU_ONLY
330#ifdef CONFIG_M68KFPU_EMU
331 tstl m68k_fputype
332 jeq 3f
333#endif
334 fsave %a0@(TASK_THREAD+THREAD_FPSTATE)
335
336#if defined(CONFIG_M68060)
337#if !defined(CPU_M68060_ONLY)
338 btst #3,m68k_cputype+3
339 beqs 1f
340#endif
341 /* The 060 FPU keeps status in bits 15-8 of the first longword */
342 tstb %a0@(TASK_THREAD+THREAD_FPSTATE+2)
343 jeq 3f
344#if !defined(CPU_M68060_ONLY)
345 jra 2f
346#endif
347#endif /* CONFIG_M68060 */
348#if !defined(CPU_M68060_ONLY)
3491: tstb %a0@(TASK_THREAD+THREAD_FPSTATE)
350 jeq 3f
351#endif
3522: fmovemx %fp0-%fp7,%a0@(TASK_THREAD+THREAD_FPREG)
353 fmoveml %fpcr/%fpsr/%fpiar,%a0@(TASK_THREAD+THREAD_FPCNTL)
3543:
355#endif /* CONFIG_M68KFPU_EMU_ONLY */
356 /* Return previous task in %d1 */
357 movel %curptr,%d1
358
359 /* switch to new task (a1 contains new task) */
360 movel %a1,%curptr
361
362 /* restore floating point context */
363#ifndef CONFIG_M68KFPU_EMU_ONLY
364#ifdef CONFIG_M68KFPU_EMU
365 tstl m68k_fputype
366 jeq 4f
367#endif
368#if defined(CONFIG_M68060)
369#if !defined(CPU_M68060_ONLY)
370 btst #3,m68k_cputype+3
371 beqs 1f
372#endif
373 /* The 060 FPU keeps status in bits 15-8 of the first longword */
374 tstb %a1@(TASK_THREAD+THREAD_FPSTATE+2)
375 jeq 3f
376#if !defined(CPU_M68060_ONLY)
377 jra 2f
378#endif
379#endif /* CONFIG_M68060 */
380#if !defined(CPU_M68060_ONLY)
3811: tstb %a1@(TASK_THREAD+THREAD_FPSTATE)
382 jeq 3f
383#endif
3842: fmovemx %a1@(TASK_THREAD+THREAD_FPREG),%fp0-%fp7
385 fmoveml %a1@(TASK_THREAD+THREAD_FPCNTL),%fpcr/%fpsr/%fpiar
3863: frestore %a1@(TASK_THREAD+THREAD_FPSTATE)
3874:
388#endif /* CONFIG_M68KFPU_EMU_ONLY */
389
390 /* restore the kernel stack pointer */
391 movel %a1@(TASK_THREAD+THREAD_KSP),%sp
392
393 /* restore non-scratch registers */
394 RESTORE_SWITCH_STACK
395
396 /* restore user stack pointer */
397 movel %a1@(TASK_THREAD+THREAD_USP),%a0
398 movel %a0,%usp
399
400 /* restore fs (sfc,%dfc) */
401 movew %a1@(TASK_THREAD+THREAD_FS),%a0
402 movec %a0,%sfc
403 movec %a0,%dfc
404
405 /* restore status register */
406 movew %a1@(TASK_THREAD+THREAD_SR),%sr
407
408 rts
409
410.data
411ALIGN
412sys_call_table:
413 .long sys_restart_syscall /* 0 - old "setup()" system call, used for restarting */
414 .long sys_exit
415 .long sys_fork
416 .long sys_read
417 .long sys_write
418 .long sys_open /* 5 */
419 .long sys_close
420 .long sys_waitpid
421 .long sys_creat
422 .long sys_link
423 .long sys_unlink /* 10 */
424 .long sys_execve
425 .long sys_chdir
426 .long sys_time
427 .long sys_mknod
428 .long sys_chmod /* 15 */
429 .long sys_chown16
430 .long sys_ni_syscall /* old break syscall holder */
431 .long sys_stat
432 .long sys_lseek
433 .long sys_getpid /* 20 */
434 .long sys_mount
435 .long sys_oldumount
436 .long sys_setuid16
437 .long sys_getuid16
438 .long sys_stime /* 25 */
439 .long sys_ptrace
440 .long sys_alarm
441 .long sys_fstat
442 .long sys_pause
443 .long sys_utime /* 30 */
444 .long sys_ni_syscall /* old stty syscall holder */
445 .long sys_ni_syscall /* old gtty syscall holder */
446 .long sys_access
447 .long sys_nice
448 .long sys_ni_syscall /* 35 */ /* old ftime syscall holder */
449 .long sys_sync
450 .long sys_kill
451 .long sys_rename
452 .long sys_mkdir
453 .long sys_rmdir /* 40 */
454 .long sys_dup
455 .long sys_pipe
456 .long sys_times
457 .long sys_ni_syscall /* old prof syscall holder */
458 .long sys_brk /* 45 */
459 .long sys_setgid16
460 .long sys_getgid16
461 .long sys_signal
462 .long sys_geteuid16
463 .long sys_getegid16 /* 50 */
464 .long sys_acct
465 .long sys_umount /* recycled never used phys() */
466 .long sys_ni_syscall /* old lock syscall holder */
467 .long sys_ioctl
468 .long sys_fcntl /* 55 */
469 .long sys_ni_syscall /* old mpx syscall holder */
470 .long sys_setpgid
471 .long sys_ni_syscall /* old ulimit syscall holder */
472 .long sys_ni_syscall
473 .long sys_umask /* 60 */
474 .long sys_chroot
475 .long sys_ustat
476 .long sys_dup2
477 .long sys_getppid
478 .long sys_getpgrp /* 65 */
479 .long sys_setsid
480 .long sys_sigaction
481 .long sys_sgetmask
482 .long sys_ssetmask
483 .long sys_setreuid16 /* 70 */
484 .long sys_setregid16
485 .long sys_sigsuspend
486 .long sys_sigpending
487 .long sys_sethostname
488 .long sys_setrlimit /* 75 */
489 .long sys_old_getrlimit
490 .long sys_getrusage
491 .long sys_gettimeofday
492 .long sys_settimeofday
493 .long sys_getgroups16 /* 80 */
494 .long sys_setgroups16
495 .long sys_old_select
496 .long sys_symlink
497 .long sys_lstat
498 .long sys_readlink /* 85 */
499 .long sys_uselib
500 .long sys_swapon
501 .long sys_reboot
502 .long sys_old_readdir
503 .long sys_old_mmap /* 90 */
504 .long sys_munmap
505 .long sys_truncate
506 .long sys_ftruncate
507 .long sys_fchmod
508 .long sys_fchown16 /* 95 */
509 .long sys_getpriority
510 .long sys_setpriority
511 .long sys_ni_syscall /* old profil syscall holder */
512 .long sys_statfs
513 .long sys_fstatfs /* 100 */
514 .long sys_ni_syscall /* ioperm for i386 */
515 .long sys_socketcall
516 .long sys_syslog
517 .long sys_setitimer
518 .long sys_getitimer /* 105 */
519 .long sys_newstat
520 .long sys_newlstat
521 .long sys_newfstat
522 .long sys_ni_syscall
523 .long sys_ni_syscall /* 110 */ /* iopl for i386 */
524 .long sys_vhangup
525 .long sys_ni_syscall /* obsolete idle() syscall */
526 .long sys_ni_syscall /* vm86old for i386 */
527 .long sys_wait4
528 .long sys_swapoff /* 115 */
529 .long sys_sysinfo
530 .long sys_ipc
531 .long sys_fsync
532 .long sys_sigreturn
533 .long sys_clone /* 120 */
534 .long sys_setdomainname
535 .long sys_newuname
536 .long sys_cacheflush /* modify_ldt for i386 */
537 .long sys_adjtimex
538 .long sys_mprotect /* 125 */
539 .long sys_sigprocmask
540 .long sys_ni_syscall /* old "create_module" */
541 .long sys_init_module
542 .long sys_delete_module
543 .long sys_ni_syscall /* 130 - old "get_kernel_syms" */
544 .long sys_quotactl
545 .long sys_getpgid
546 .long sys_fchdir
547 .long sys_bdflush
548 .long sys_sysfs /* 135 */
549 .long sys_personality
550 .long sys_ni_syscall /* for afs_syscall */
551 .long sys_setfsuid16
552 .long sys_setfsgid16
553 .long sys_llseek /* 140 */
554 .long sys_getdents
555 .long sys_select
556 .long sys_flock
557 .long sys_msync
558 .long sys_readv /* 145 */
559 .long sys_writev
560 .long sys_getsid
561 .long sys_fdatasync
562 .long sys_sysctl
563 .long sys_mlock /* 150 */
564 .long sys_munlock
565 .long sys_mlockall
566 .long sys_munlockall
567 .long sys_sched_setparam
568 .long sys_sched_getparam /* 155 */
569 .long sys_sched_setscheduler
570 .long sys_sched_getscheduler
571 .long sys_sched_yield
572 .long sys_sched_get_priority_max
573 .long sys_sched_get_priority_min /* 160 */
574 .long sys_sched_rr_get_interval
575 .long sys_nanosleep
576 .long sys_mremap
577 .long sys_setresuid16
578 .long sys_getresuid16 /* 165 */
579 .long sys_getpagesize
580 .long sys_ni_syscall /* old sys_query_module */
581 .long sys_poll
582 .long sys_nfsservctl
583 .long sys_setresgid16 /* 170 */
584 .long sys_getresgid16
585 .long sys_prctl
586 .long sys_rt_sigreturn
587 .long sys_rt_sigaction
588 .long sys_rt_sigprocmask /* 175 */
589 .long sys_rt_sigpending
590 .long sys_rt_sigtimedwait
591 .long sys_rt_sigqueueinfo
592 .long sys_rt_sigsuspend
593 .long sys_pread64 /* 180 */
594 .long sys_pwrite64
595 .long sys_lchown16;
596 .long sys_getcwd
597 .long sys_capget
598 .long sys_capset /* 185 */
599 .long sys_sigaltstack
600 .long sys_sendfile
601 .long sys_ni_syscall /* streams1 */
602 .long sys_ni_syscall /* streams2 */
603 .long sys_vfork /* 190 */
604 .long sys_getrlimit
605 .long sys_mmap2
606 .long sys_truncate64
607 .long sys_ftruncate64
608 .long sys_stat64 /* 195 */
609 .long sys_lstat64
610 .long sys_fstat64
611 .long sys_chown
612 .long sys_getuid
613 .long sys_getgid /* 200 */
614 .long sys_geteuid
615 .long sys_getegid
616 .long sys_setreuid
617 .long sys_setregid
618 .long sys_getgroups /* 205 */
619 .long sys_setgroups
620 .long sys_fchown
621 .long sys_setresuid
622 .long sys_getresuid
623 .long sys_setresgid /* 210 */
624 .long sys_getresgid
625 .long sys_lchown
626 .long sys_setuid
627 .long sys_setgid
628 .long sys_setfsuid /* 215 */
629 .long sys_setfsgid
630 .long sys_pivot_root
631 .long sys_ni_syscall
632 .long sys_ni_syscall
633 .long sys_getdents64 /* 220 */
634 .long sys_gettid
635 .long sys_tkill
636 .long sys_setxattr
637 .long sys_lsetxattr
638 .long sys_fsetxattr /* 225 */
639 .long sys_getxattr
640 .long sys_lgetxattr
641 .long sys_fgetxattr
642 .long sys_listxattr
643 .long sys_llistxattr /* 230 */
644 .long sys_flistxattr
645 .long sys_removexattr
646 .long sys_lremovexattr
647 .long sys_fremovexattr
648 .long sys_futex /* 235 */
649 .long sys_sendfile64
650 .long sys_mincore
651 .long sys_madvise
652 .long sys_fcntl64
653 .long sys_readahead /* 240 */
654 .long sys_io_setup
655 .long sys_io_destroy
656 .long sys_io_getevents
657 .long sys_io_submit
658 .long sys_io_cancel /* 245 */
659 .long sys_fadvise64
660 .long sys_exit_group
661 .long sys_lookup_dcookie
662 .long sys_epoll_create
663 .long sys_epoll_ctl /* 250 */
664 .long sys_epoll_wait
665 .long sys_remap_file_pages
666 .long sys_set_tid_address
667 .long sys_timer_create
668 .long sys_timer_settime /* 255 */
669 .long sys_timer_gettime
670 .long sys_timer_getoverrun
671 .long sys_timer_delete
672 .long sys_clock_settime
673 .long sys_clock_gettime /* 260 */
674 .long sys_clock_getres
675 .long sys_clock_nanosleep
676 .long sys_statfs64
677 .long sys_fstatfs64
678 .long sys_tgkill /* 265 */
679 .long sys_utimes
680 .long sys_fadvise64_64
681 .long sys_mbind
682 .long sys_get_mempolicy
683 .long sys_set_mempolicy /* 270 */
684 .long sys_mq_open
685 .long sys_mq_unlink
686 .long sys_mq_timedsend
687 .long sys_mq_timedreceive
688 .long sys_mq_notify /* 275 */
689 .long sys_mq_getsetattr
690 .long sys_waitid
691 .long sys_ni_syscall /* for sys_vserver */
692 .long sys_add_key
693 .long sys_request_key /* 280 */
694 .long sys_keyctl
695 .long sys_ioprio_set
696 .long sys_ioprio_get
697 .long sys_inotify_init
698 .long sys_inotify_add_watch /* 285 */
699 .long sys_inotify_rm_watch
700 .long sys_migrate_pages
701 .long sys_openat
702 .long sys_mkdirat
703 .long sys_mknodat /* 290 */
704 .long sys_fchownat
705 .long sys_futimesat
706 .long sys_fstatat64
707 .long sys_unlinkat
708 .long sys_renameat /* 295 */
709 .long sys_linkat
710 .long sys_symlinkat
711 .long sys_readlinkat
712 .long sys_fchmodat
713 .long sys_faccessat /* 300 */
714 .long sys_ni_syscall /* Reserved for pselect6 */
715 .long sys_ni_syscall /* Reserved for ppoll */
716 .long sys_unshare
717 .long sys_set_robust_list
718 .long sys_get_robust_list /* 305 */
719 .long sys_splice
720 .long sys_sync_file_range
721 .long sys_tee
722 .long sys_vmsplice
723 .long sys_move_pages /* 310 */
724 .long sys_sched_setaffinity
725 .long sys_sched_getaffinity
726 .long sys_kexec_load
727 .long sys_getcpu
728 .long sys_epoll_pwait /* 315 */
729 .long sys_utimensat
730 .long sys_signalfd
731 .long sys_timerfd_create
732 .long sys_eventfd
733 .long sys_fallocate /* 320 */
734 .long sys_timerfd_settime
735 .long sys_timerfd_gettime
736 .long sys_signalfd4
737 .long sys_eventfd2
738 .long sys_epoll_create1 /* 325 */
739 .long sys_dup3
740 .long sys_pipe2
741 .long sys_inotify_init1
742 .long sys_preadv
743 .long sys_pwritev /* 330 */
744 .long sys_rt_tgsigqueueinfo
745 .long sys_perf_event_open
746 .long sys_get_thread_area
747 .long sys_set_thread_area
748 .long sys_atomic_cmpxchg_32 /* 335 */
749 .long sys_atomic_barrier
750 .long sys_fanotify_init
751 .long sys_fanotify_mark
752 .long sys_prlimit64
753
diff --git a/arch/m68k/kernel/entry_mm.S b/arch/m68k/kernel/entry_mm.S
new file mode 100644
index 00000000000..1559dea36e5
--- /dev/null
+++ b/arch/m68k/kernel/entry_mm.S
@@ -0,0 +1,753 @@
1/* -*- mode: asm -*-
2 *
3 * linux/arch/m68k/kernel/entry.S
4 *
5 * Copyright (C) 1991, 1992 Linus Torvalds
6 *
7 * This file is subject to the terms and conditions of the GNU General Public
8 * License. See the file README.legal in the main directory of this archive
9 * for more details.
10 *
11 * Linux/m68k support by Hamish Macdonald
12 *
13 * 68060 fixes by Jesper Skov
14 *
15 */
16
17/*
18 * entry.S contains the system-call and fault low-level handling routines.
19 * This also contains the timer-interrupt handler, as well as all interrupts
20 * and faults that can result in a task-switch.
21 *
22 * NOTE: This code handles signal-recognition, which happens every time
23 * after a timer-interrupt and after each system call.
24 *
25 */
26
27/*
28 * 12/03/96 Jes: Currently we only support m68k single-cpu systems, so
29 * all pointers that used to be 'current' are now entry
30 * number 0 in the 'current_set' list.
31 *
32 * 6/05/00 RZ: addedd writeback completion after return from sighandler
33 * for 68040
34 */
35
36#include <linux/linkage.h>
37#include <asm/entry.h>
38#include <asm/errno.h>
39#include <asm/setup.h>
40#include <asm/segment.h>
41#include <asm/traps.h>
42#include <asm/unistd.h>
43
44#include <asm/asm-offsets.h>
45
46.globl system_call, buserr, trap, resume
47.globl sys_call_table
48.globl sys_fork, sys_clone, sys_vfork
49.globl ret_from_interrupt, bad_interrupt
50.globl auto_irqhandler_fixup
51.globl user_irqvec_fixup, user_irqhandler_fixup
52
53.text
54ENTRY(buserr)
55 SAVE_ALL_INT
56 GET_CURRENT(%d0)
57 movel %sp,%sp@- | stack frame pointer argument
58 bsrl buserr_c
59 addql #4,%sp
60 jra .Lret_from_exception
61
62ENTRY(trap)
63 SAVE_ALL_INT
64 GET_CURRENT(%d0)
65 movel %sp,%sp@- | stack frame pointer argument
66 bsrl trap_c
67 addql #4,%sp
68 jra .Lret_from_exception
69
70 | After a fork we jump here directly from resume,
71 | so that %d1 contains the previous task
72 | schedule_tail now used regardless of CONFIG_SMP
73ENTRY(ret_from_fork)
74 movel %d1,%sp@-
75 jsr schedule_tail
76 addql #4,%sp
77 jra .Lret_from_exception
78
79do_trace_entry:
80 movel #-ENOSYS,%sp@(PT_OFF_D0)| needed for strace
81 subql #4,%sp
82 SAVE_SWITCH_STACK
83 jbsr syscall_trace
84 RESTORE_SWITCH_STACK
85 addql #4,%sp
86 movel %sp@(PT_OFF_ORIG_D0),%d0
87 cmpl #NR_syscalls,%d0
88 jcs syscall
89badsys:
90 movel #-ENOSYS,%sp@(PT_OFF_D0)
91 jra ret_from_syscall
92
93do_trace_exit:
94 subql #4,%sp
95 SAVE_SWITCH_STACK
96 jbsr syscall_trace
97 RESTORE_SWITCH_STACK
98 addql #4,%sp
99 jra .Lret_from_exception
100
101ENTRY(ret_from_signal)
102 tstb %curptr@(TASK_INFO+TINFO_FLAGS+2)
103 jge 1f
104 jbsr syscall_trace
1051: RESTORE_SWITCH_STACK
106 addql #4,%sp
107/* on 68040 complete pending writebacks if any */
108#ifdef CONFIG_M68040
109 bfextu %sp@(PT_OFF_FORMATVEC){#0,#4},%d0
110 subql #7,%d0 | bus error frame ?
111 jbne 1f
112 movel %sp,%sp@-
113 jbsr berr_040cleanup
114 addql #4,%sp
1151:
116#endif
117 jra .Lret_from_exception
118
119ENTRY(system_call)
120 SAVE_ALL_SYS
121
122 GET_CURRENT(%d1)
123 | save top of frame
124 movel %sp,%curptr@(TASK_THREAD+THREAD_ESP0)
125
126 | syscall trace?
127 tstb %curptr@(TASK_INFO+TINFO_FLAGS+2)
128 jmi do_trace_entry
129 cmpl #NR_syscalls,%d0
130 jcc badsys
131syscall:
132 jbsr @(sys_call_table,%d0:l:4)@(0)
133 movel %d0,%sp@(PT_OFF_D0) | save the return value
134ret_from_syscall:
135 |oriw #0x0700,%sr
136 movew %curptr@(TASK_INFO+TINFO_FLAGS+2),%d0
137 jne syscall_exit_work
1381: RESTORE_ALL
139
140syscall_exit_work:
141 btst #5,%sp@(PT_OFF_SR) | check if returning to kernel
142 bnes 1b | if so, skip resched, signals
143 lslw #1,%d0
144 jcs do_trace_exit
145 jmi do_delayed_trace
146 lslw #8,%d0
147 jmi do_signal_return
148 pea resume_userspace
149 jra schedule
150
151
152ENTRY(ret_from_exception)
153.Lret_from_exception:
154 btst #5,%sp@(PT_OFF_SR) | check if returning to kernel
155 bnes 1f | if so, skip resched, signals
156 | only allow interrupts when we are really the last one on the
157 | kernel stack, otherwise stack overflow can occur during
158 | heavy interrupt load
159 andw #ALLOWINT,%sr
160
161resume_userspace:
162 moveb %curptr@(TASK_INFO+TINFO_FLAGS+3),%d0
163 jne exit_work
1641: RESTORE_ALL
165
166exit_work:
167 | save top of frame
168 movel %sp,%curptr@(TASK_THREAD+THREAD_ESP0)
169 lslb #1,%d0
170 jmi do_signal_return
171 pea resume_userspace
172 jra schedule
173
174
175do_signal_return:
176 |andw #ALLOWINT,%sr
177 subql #4,%sp | dummy return address
178 SAVE_SWITCH_STACK
179 pea %sp@(SWITCH_STACK_SIZE)
180 bsrl do_signal
181 addql #4,%sp
182 RESTORE_SWITCH_STACK
183 addql #4,%sp
184 jbra resume_userspace
185
186do_delayed_trace:
187 bclr #7,%sp@(PT_OFF_SR) | clear trace bit in SR
188 pea 1 | send SIGTRAP
189 movel %curptr,%sp@-
190 pea LSIGTRAP
191 jbsr send_sig
192 addql #8,%sp
193 addql #4,%sp
194 jbra resume_userspace
195
196
197/* This is the main interrupt handler for autovector interrupts */
198
199ENTRY(auto_inthandler)
200 SAVE_ALL_INT
201 GET_CURRENT(%d0)
202 addqb #1,%curptr@(TASK_INFO+TINFO_PREEMPT+1)
203 | put exception # in d0
204 bfextu %sp@(PT_OFF_FORMATVEC){#4,#10},%d0
205 subw #VEC_SPUR,%d0
206
207 movel %sp,%sp@-
208 movel %d0,%sp@- | put vector # on stack
209auto_irqhandler_fixup = . + 2
210 jsr __m68k_handle_int | process the IRQ
211 addql #8,%sp | pop parameters off stack
212
213ret_from_interrupt:
214 subqb #1,%curptr@(TASK_INFO+TINFO_PREEMPT+1)
215 jeq ret_from_last_interrupt
2162: RESTORE_ALL
217
218 ALIGN
219ret_from_last_interrupt:
220 moveq #(~ALLOWINT>>8)&0xff,%d0
221 andb %sp@(PT_OFF_SR),%d0
222 jne 2b
223
224 /* check if we need to do software interrupts */
225 tstl irq_stat+CPUSTAT_SOFTIRQ_PENDING
226 jeq .Lret_from_exception
227 pea ret_from_exception
228 jra do_softirq
229
230/* Handler for user defined interrupt vectors */
231
232ENTRY(user_inthandler)
233 SAVE_ALL_INT
234 GET_CURRENT(%d0)
235 addqb #1,%curptr@(TASK_INFO+TINFO_PREEMPT+1)
236 | put exception # in d0
237 bfextu %sp@(PT_OFF_FORMATVEC){#4,#10},%d0
238user_irqvec_fixup = . + 2
239 subw #VEC_USER,%d0
240
241 movel %sp,%sp@-
242 movel %d0,%sp@- | put vector # on stack
243user_irqhandler_fixup = . + 2
244 jsr __m68k_handle_int | process the IRQ
245 addql #8,%sp | pop parameters off stack
246
247 subqb #1,%curptr@(TASK_INFO+TINFO_PREEMPT+1)
248 jeq ret_from_last_interrupt
249 RESTORE_ALL
250
251/* Handler for uninitialized and spurious interrupts */
252
253ENTRY(bad_inthandler)
254 SAVE_ALL_INT
255 GET_CURRENT(%d0)
256 addqb #1,%curptr@(TASK_INFO+TINFO_PREEMPT+1)
257
258 movel %sp,%sp@-
259 jsr handle_badint
260 addql #4,%sp
261
262 subqb #1,%curptr@(TASK_INFO+TINFO_PREEMPT+1)
263 jeq ret_from_last_interrupt
264 RESTORE_ALL
265
266
267ENTRY(sys_fork)
268 SAVE_SWITCH_STACK
269 pea %sp@(SWITCH_STACK_SIZE)
270 jbsr m68k_fork
271 addql #4,%sp
272 RESTORE_SWITCH_STACK
273 rts
274
275ENTRY(sys_clone)
276 SAVE_SWITCH_STACK
277 pea %sp@(SWITCH_STACK_SIZE)
278 jbsr m68k_clone
279 addql #4,%sp
280 RESTORE_SWITCH_STACK
281 rts
282
283ENTRY(sys_vfork)
284 SAVE_SWITCH_STACK
285 pea %sp@(SWITCH_STACK_SIZE)
286 jbsr m68k_vfork
287 addql #4,%sp
288 RESTORE_SWITCH_STACK
289 rts
290
291ENTRY(sys_sigreturn)
292 SAVE_SWITCH_STACK
293 jbsr do_sigreturn
294 RESTORE_SWITCH_STACK
295 rts
296
297ENTRY(sys_rt_sigreturn)
298 SAVE_SWITCH_STACK
299 jbsr do_rt_sigreturn
300 RESTORE_SWITCH_STACK
301 rts
302
303resume:
304 /*
305 * Beware - when entering resume, prev (the current task) is
306 * in a0, next (the new task) is in a1,so don't change these
307 * registers until their contents are no longer needed.
308 */
309
310 /* save sr */
311 movew %sr,%a0@(TASK_THREAD+THREAD_SR)
312
313 /* save fs (sfc,%dfc) (may be pointing to kernel memory) */
314 movec %sfc,%d0
315 movew %d0,%a0@(TASK_THREAD+THREAD_FS)
316
317 /* save usp */
318 /* it is better to use a movel here instead of a movew 8*) */
319 movec %usp,%d0
320 movel %d0,%a0@(TASK_THREAD+THREAD_USP)
321
322 /* save non-scratch registers on stack */
323 SAVE_SWITCH_STACK
324
325 /* save current kernel stack pointer */
326 movel %sp,%a0@(TASK_THREAD+THREAD_KSP)
327
328 /* save floating point context */
329#ifndef CONFIG_M68KFPU_EMU_ONLY
330#ifdef CONFIG_M68KFPU_EMU
331 tstl m68k_fputype
332 jeq 3f
333#endif
334 fsave %a0@(TASK_THREAD+THREAD_FPSTATE)
335
336#if defined(CONFIG_M68060)
337#if !defined(CPU_M68060_ONLY)
338 btst #3,m68k_cputype+3
339 beqs 1f
340#endif
341 /* The 060 FPU keeps status in bits 15-8 of the first longword */
342 tstb %a0@(TASK_THREAD+THREAD_FPSTATE+2)
343 jeq 3f
344#if !defined(CPU_M68060_ONLY)
345 jra 2f
346#endif
347#endif /* CONFIG_M68060 */
348#if !defined(CPU_M68060_ONLY)
3491: tstb %a0@(TASK_THREAD+THREAD_FPSTATE)
350 jeq 3f
351#endif
3522: fmovemx %fp0-%fp7,%a0@(TASK_THREAD+THREAD_FPREG)
353 fmoveml %fpcr/%fpsr/%fpiar,%a0@(TASK_THREAD+THREAD_FPCNTL)
3543:
355#endif /* CONFIG_M68KFPU_EMU_ONLY */
356 /* Return previous task in %d1 */
357 movel %curptr,%d1
358
359 /* switch to new task (a1 contains new task) */
360 movel %a1,%curptr
361
362 /* restore floating point context */
363#ifndef CONFIG_M68KFPU_EMU_ONLY
364#ifdef CONFIG_M68KFPU_EMU
365 tstl m68k_fputype
366 jeq 4f
367#endif
368#if defined(CONFIG_M68060)
369#if !defined(CPU_M68060_ONLY)
370 btst #3,m68k_cputype+3
371 beqs 1f
372#endif
373 /* The 060 FPU keeps status in bits 15-8 of the first longword */
374 tstb %a1@(TASK_THREAD+THREAD_FPSTATE+2)
375 jeq 3f
376#if !defined(CPU_M68060_ONLY)
377 jra 2f
378#endif
379#endif /* CONFIG_M68060 */
380#if !defined(CPU_M68060_ONLY)
3811: tstb %a1@(TASK_THREAD+THREAD_FPSTATE)
382 jeq 3f
383#endif
3842: fmovemx %a1@(TASK_THREAD+THREAD_FPREG),%fp0-%fp7
385 fmoveml %a1@(TASK_THREAD+THREAD_FPCNTL),%fpcr/%fpsr/%fpiar
3863: frestore %a1@(TASK_THREAD+THREAD_FPSTATE)
3874:
388#endif /* CONFIG_M68KFPU_EMU_ONLY */
389
390 /* restore the kernel stack pointer */
391 movel %a1@(TASK_THREAD+THREAD_KSP),%sp
392
393 /* restore non-scratch registers */
394 RESTORE_SWITCH_STACK
395
396 /* restore user stack pointer */
397 movel %a1@(TASK_THREAD+THREAD_USP),%a0
398 movel %a0,%usp
399
400 /* restore fs (sfc,%dfc) */
401 movew %a1@(TASK_THREAD+THREAD_FS),%a0
402 movec %a0,%sfc
403 movec %a0,%dfc
404
405 /* restore status register */
406 movew %a1@(TASK_THREAD+THREAD_SR),%sr
407
408 rts
409
410.data
411ALIGN
412sys_call_table:
413 .long sys_restart_syscall /* 0 - old "setup()" system call, used for restarting */
414 .long sys_exit
415 .long sys_fork
416 .long sys_read
417 .long sys_write
418 .long sys_open /* 5 */
419 .long sys_close
420 .long sys_waitpid
421 .long sys_creat
422 .long sys_link
423 .long sys_unlink /* 10 */
424 .long sys_execve
425 .long sys_chdir
426 .long sys_time
427 .long sys_mknod
428 .long sys_chmod /* 15 */
429 .long sys_chown16
430 .long sys_ni_syscall /* old break syscall holder */
431 .long sys_stat
432 .long sys_lseek
433 .long sys_getpid /* 20 */
434 .long sys_mount
435 .long sys_oldumount
436 .long sys_setuid16
437 .long sys_getuid16
438 .long sys_stime /* 25 */
439 .long sys_ptrace
440 .long sys_alarm
441 .long sys_fstat
442 .long sys_pause
443 .long sys_utime /* 30 */
444 .long sys_ni_syscall /* old stty syscall holder */
445 .long sys_ni_syscall /* old gtty syscall holder */
446 .long sys_access
447 .long sys_nice
448 .long sys_ni_syscall /* 35 */ /* old ftime syscall holder */
449 .long sys_sync
450 .long sys_kill
451 .long sys_rename
452 .long sys_mkdir
453 .long sys_rmdir /* 40 */
454 .long sys_dup
455 .long sys_pipe
456 .long sys_times
457 .long sys_ni_syscall /* old prof syscall holder */
458 .long sys_brk /* 45 */
459 .long sys_setgid16
460 .long sys_getgid16
461 .long sys_signal
462 .long sys_geteuid16
463 .long sys_getegid16 /* 50 */
464 .long sys_acct
465 .long sys_umount /* recycled never used phys() */
466 .long sys_ni_syscall /* old lock syscall holder */
467 .long sys_ioctl
468 .long sys_fcntl /* 55 */
469 .long sys_ni_syscall /* old mpx syscall holder */
470 .long sys_setpgid
471 .long sys_ni_syscall /* old ulimit syscall holder */
472 .long sys_ni_syscall
473 .long sys_umask /* 60 */
474 .long sys_chroot
475 .long sys_ustat
476 .long sys_dup2
477 .long sys_getppid
478 .long sys_getpgrp /* 65 */
479 .long sys_setsid
480 .long sys_sigaction
481 .long sys_sgetmask
482 .long sys_ssetmask
483 .long sys_setreuid16 /* 70 */
484 .long sys_setregid16
485 .long sys_sigsuspend
486 .long sys_sigpending
487 .long sys_sethostname
488 .long sys_setrlimit /* 75 */
489 .long sys_old_getrlimit
490 .long sys_getrusage
491 .long sys_gettimeofday
492 .long sys_settimeofday
493 .long sys_getgroups16 /* 80 */
494 .long sys_setgroups16
495 .long sys_old_select
496 .long sys_symlink
497 .long sys_lstat
498 .long sys_readlink /* 85 */
499 .long sys_uselib
500 .long sys_swapon
501 .long sys_reboot
502 .long sys_old_readdir
503 .long sys_old_mmap /* 90 */
504 .long sys_munmap
505 .long sys_truncate
506 .long sys_ftruncate
507 .long sys_fchmod
508 .long sys_fchown16 /* 95 */
509 .long sys_getpriority
510 .long sys_setpriority
511 .long sys_ni_syscall /* old profil syscall holder */
512 .long sys_statfs
513 .long sys_fstatfs /* 100 */
514 .long sys_ni_syscall /* ioperm for i386 */
515 .long sys_socketcall
516 .long sys_syslog
517 .long sys_setitimer
518 .long sys_getitimer /* 105 */
519 .long sys_newstat
520 .long sys_newlstat
521 .long sys_newfstat
522 .long sys_ni_syscall
523 .long sys_ni_syscall /* 110 */ /* iopl for i386 */
524 .long sys_vhangup
525 .long sys_ni_syscall /* obsolete idle() syscall */
526 .long sys_ni_syscall /* vm86old for i386 */
527 .long sys_wait4
528 .long sys_swapoff /* 115 */
529 .long sys_sysinfo
530 .long sys_ipc
531 .long sys_fsync
532 .long sys_sigreturn
533 .long sys_clone /* 120 */
534 .long sys_setdomainname
535 .long sys_newuname
536 .long sys_cacheflush /* modify_ldt for i386 */
537 .long sys_adjtimex
538 .long sys_mprotect /* 125 */
539 .long sys_sigprocmask
540 .long sys_ni_syscall /* old "create_module" */
541 .long sys_init_module
542 .long sys_delete_module
543 .long sys_ni_syscall /* 130 - old "get_kernel_syms" */
544 .long sys_quotactl
545 .long sys_getpgid
546 .long sys_fchdir
547 .long sys_bdflush
548 .long sys_sysfs /* 135 */
549 .long sys_personality
550 .long sys_ni_syscall /* for afs_syscall */
551 .long sys_setfsuid16
552 .long sys_setfsgid16
553 .long sys_llseek /* 140 */
554 .long sys_getdents
555 .long sys_select
556 .long sys_flock
557 .long sys_msync
558 .long sys_readv /* 145 */
559 .long sys_writev
560 .long sys_getsid
561 .long sys_fdatasync
562 .long sys_sysctl
563 .long sys_mlock /* 150 */
564 .long sys_munlock
565 .long sys_mlockall
566 .long sys_munlockall
567 .long sys_sched_setparam
568 .long sys_sched_getparam /* 155 */
569 .long sys_sched_setscheduler
570 .long sys_sched_getscheduler
571 .long sys_sched_yield
572 .long sys_sched_get_priority_max
573 .long sys_sched_get_priority_min /* 160 */
574 .long sys_sched_rr_get_interval
575 .long sys_nanosleep
576 .long sys_mremap
577 .long sys_setresuid16
578 .long sys_getresuid16 /* 165 */
579 .long sys_getpagesize
580 .long sys_ni_syscall /* old sys_query_module */
581 .long sys_poll
582 .long sys_nfsservctl
583 .long sys_setresgid16 /* 170 */
584 .long sys_getresgid16
585 .long sys_prctl
586 .long sys_rt_sigreturn
587 .long sys_rt_sigaction
588 .long sys_rt_sigprocmask /* 175 */
589 .long sys_rt_sigpending
590 .long sys_rt_sigtimedwait
591 .long sys_rt_sigqueueinfo
592 .long sys_rt_sigsuspend
593 .long sys_pread64 /* 180 */
594 .long sys_pwrite64
595 .long sys_lchown16;
596 .long sys_getcwd
597 .long sys_capget
598 .long sys_capset /* 185 */
599 .long sys_sigaltstack
600 .long sys_sendfile
601 .long sys_ni_syscall /* streams1 */
602 .long sys_ni_syscall /* streams2 */
603 .long sys_vfork /* 190 */
604 .long sys_getrlimit
605 .long sys_mmap2
606 .long sys_truncate64
607 .long sys_ftruncate64
608 .long sys_stat64 /* 195 */
609 .long sys_lstat64
610 .long sys_fstat64
611 .long sys_chown
612 .long sys_getuid
613 .long sys_getgid /* 200 */
614 .long sys_geteuid
615 .long sys_getegid
616 .long sys_setreuid
617 .long sys_setregid
618 .long sys_getgroups /* 205 */
619 .long sys_setgroups
620 .long sys_fchown
621 .long sys_setresuid
622 .long sys_getresuid
623 .long sys_setresgid /* 210 */
624 .long sys_getresgid
625 .long sys_lchown
626 .long sys_setuid
627 .long sys_setgid
628 .long sys_setfsuid /* 215 */
629 .long sys_setfsgid
630 .long sys_pivot_root
631 .long sys_ni_syscall
632 .long sys_ni_syscall
633 .long sys_getdents64 /* 220 */
634 .long sys_gettid
635 .long sys_tkill
636 .long sys_setxattr
637 .long sys_lsetxattr
638 .long sys_fsetxattr /* 225 */
639 .long sys_getxattr
640 .long sys_lgetxattr
641 .long sys_fgetxattr
642 .long sys_listxattr
643 .long sys_llistxattr /* 230 */
644 .long sys_flistxattr
645 .long sys_removexattr
646 .long sys_lremovexattr
647 .long sys_fremovexattr
648 .long sys_futex /* 235 */
649 .long sys_sendfile64
650 .long sys_mincore
651 .long sys_madvise
652 .long sys_fcntl64
653 .long sys_readahead /* 240 */
654 .long sys_io_setup
655 .long sys_io_destroy
656 .long sys_io_getevents
657 .long sys_io_submit
658 .long sys_io_cancel /* 245 */
659 .long sys_fadvise64
660 .long sys_exit_group
661 .long sys_lookup_dcookie
662 .long sys_epoll_create
663 .long sys_epoll_ctl /* 250 */
664 .long sys_epoll_wait
665 .long sys_remap_file_pages
666 .long sys_set_tid_address
667 .long sys_timer_create
668 .long sys_timer_settime /* 255 */
669 .long sys_timer_gettime
670 .long sys_timer_getoverrun
671 .long sys_timer_delete
672 .long sys_clock_settime
673 .long sys_clock_gettime /* 260 */
674 .long sys_clock_getres
675 .long sys_clock_nanosleep
676 .long sys_statfs64
677 .long sys_fstatfs64
678 .long sys_tgkill /* 265 */
679 .long sys_utimes
680 .long sys_fadvise64_64
681 .long sys_mbind
682 .long sys_get_mempolicy
683 .long sys_set_mempolicy /* 270 */
684 .long sys_mq_open
685 .long sys_mq_unlink
686 .long sys_mq_timedsend
687 .long sys_mq_timedreceive
688 .long sys_mq_notify /* 275 */
689 .long sys_mq_getsetattr
690 .long sys_waitid
691 .long sys_ni_syscall /* for sys_vserver */
692 .long sys_add_key
693 .long sys_request_key /* 280 */
694 .long sys_keyctl
695 .long sys_ioprio_set
696 .long sys_ioprio_get
697 .long sys_inotify_init
698 .long sys_inotify_add_watch /* 285 */
699 .long sys_inotify_rm_watch
700 .long sys_migrate_pages
701 .long sys_openat
702 .long sys_mkdirat
703 .long sys_mknodat /* 290 */
704 .long sys_fchownat
705 .long sys_futimesat
706 .long sys_fstatat64
707 .long sys_unlinkat
708 .long sys_renameat /* 295 */
709 .long sys_linkat
710 .long sys_symlinkat
711 .long sys_readlinkat
712 .long sys_fchmodat
713 .long sys_faccessat /* 300 */
714 .long sys_ni_syscall /* Reserved for pselect6 */
715 .long sys_ni_syscall /* Reserved for ppoll */
716 .long sys_unshare
717 .long sys_set_robust_list
718 .long sys_get_robust_list /* 305 */
719 .long sys_splice
720 .long sys_sync_file_range
721 .long sys_tee
722 .long sys_vmsplice
723 .long sys_move_pages /* 310 */
724 .long sys_sched_setaffinity
725 .long sys_sched_getaffinity
726 .long sys_kexec_load
727 .long sys_getcpu
728 .long sys_epoll_pwait /* 315 */
729 .long sys_utimensat
730 .long sys_signalfd
731 .long sys_timerfd_create
732 .long sys_eventfd
733 .long sys_fallocate /* 320 */
734 .long sys_timerfd_settime
735 .long sys_timerfd_gettime
736 .long sys_signalfd4
737 .long sys_eventfd2
738 .long sys_epoll_create1 /* 325 */
739 .long sys_dup3
740 .long sys_pipe2
741 .long sys_inotify_init1
742 .long sys_preadv
743 .long sys_pwritev /* 330 */
744 .long sys_rt_tgsigqueueinfo
745 .long sys_perf_event_open
746 .long sys_get_thread_area
747 .long sys_set_thread_area
748 .long sys_atomic_cmpxchg_32 /* 335 */
749 .long sys_atomic_barrier
750 .long sys_fanotify_init
751 .long sys_fanotify_mark
752 .long sys_prlimit64
753
diff --git a/arch/m68knommu/kernel/entry.S b/arch/m68k/kernel/entry_no.S
index 2783f25e38b..2783f25e38b 100644
--- a/arch/m68knommu/kernel/entry.S
+++ b/arch/m68k/kernel/entry_no.S
diff --git a/arch/m68knommu/kernel/init_task.c b/arch/m68k/kernel/init_task.c
index cbf9dc3cc51..cbf9dc3cc51 100644
--- a/arch/m68knommu/kernel/init_task.c
+++ b/arch/m68k/kernel/init_task.c
diff --git a/arch/m68knommu/kernel/irq.c b/arch/m68k/kernel/irq.c
index c7dd48f37be..c7dd48f37be 100644
--- a/arch/m68knommu/kernel/irq.c
+++ b/arch/m68k/kernel/irq.c
diff --git a/arch/m68k/kernel/m68k_ksyms.c b/arch/m68k/kernel/m68k_ksyms.c
index d900e77e536..4752c28ce0a 100644
--- a/arch/m68k/kernel/m68k_ksyms.c
+++ b/arch/m68k/kernel/m68k_ksyms.c
@@ -1,16 +1,5 @@
1#include <linux/module.h> 1#ifdef CONFIG_MMU
2 2#include "m68k_ksyms_mm.c"
3asmlinkage long long __ashldi3 (long long, int); 3#else
4asmlinkage long long __ashrdi3 (long long, int); 4#include "m68k_ksyms_no.c"
5asmlinkage long long __lshrdi3 (long long, int); 5#endif
6asmlinkage long long __muldi3 (long long, long long);
7
8/* The following are special because they're not called
9 explicitly (the C compiler generates them). Fortunately,
10 their interface isn't gonna change any time soon now, so
11 it's OK to leave it out of version control. */
12EXPORT_SYMBOL(__ashldi3);
13EXPORT_SYMBOL(__ashrdi3);
14EXPORT_SYMBOL(__lshrdi3);
15EXPORT_SYMBOL(__muldi3);
16
diff --git a/arch/m68k/kernel/m68k_ksyms_mm.c b/arch/m68k/kernel/m68k_ksyms_mm.c
new file mode 100644
index 00000000000..d900e77e536
--- /dev/null
+++ b/arch/m68k/kernel/m68k_ksyms_mm.c
@@ -0,0 +1,16 @@
1#include <linux/module.h>
2
3asmlinkage long long __ashldi3 (long long, int);
4asmlinkage long long __ashrdi3 (long long, int);
5asmlinkage long long __lshrdi3 (long long, int);
6asmlinkage long long __muldi3 (long long, long long);
7
8/* The following are special because they're not called
9 explicitly (the C compiler generates them). Fortunately,
10 their interface isn't gonna change any time soon now, so
11 it's OK to leave it out of version control. */
12EXPORT_SYMBOL(__ashldi3);
13EXPORT_SYMBOL(__ashrdi3);
14EXPORT_SYMBOL(__lshrdi3);
15EXPORT_SYMBOL(__muldi3);
16
diff --git a/arch/m68knommu/kernel/m68k_ksyms.c b/arch/m68k/kernel/m68k_ksyms_no.c
index 39fe0a7aec3..39fe0a7aec3 100644
--- a/arch/m68knommu/kernel/m68k_ksyms.c
+++ b/arch/m68k/kernel/m68k_ksyms_no.c
diff --git a/arch/m68k/kernel/module.c b/arch/m68k/kernel/module.c
index cd6bcb1c957..7ea203ce6b1 100644
--- a/arch/m68k/kernel/module.c
+++ b/arch/m68k/kernel/module.c
@@ -1,155 +1,5 @@
1/* 1#ifdef CONFIG_MMU
2 * This file is subject to the terms and conditions of the GNU General Public 2#include "module_mm.c"
3 * License. See the file COPYING in the main directory of this archive
4 * for more details.
5 */
6
7#include <linux/moduleloader.h>
8#include <linux/elf.h>
9#include <linux/vmalloc.h>
10#include <linux/fs.h>
11#include <linux/string.h>
12#include <linux/kernel.h>
13
14#if 0
15#define DEBUGP printk
16#else 3#else
17#define DEBUGP(fmt...) 4#include "module_no.c"
18#endif 5#endif
19
20#ifdef CONFIG_MODULES
21
22void *module_alloc(unsigned long size)
23{
24 if (size == 0)
25 return NULL;
26 return vmalloc(size);
27}
28
29
30/* Free memory returned from module_alloc */
31void module_free(struct module *mod, void *module_region)
32{
33 vfree(module_region);
34}
35
36/* We don't need anything special. */
37int module_frob_arch_sections(Elf_Ehdr *hdr,
38 Elf_Shdr *sechdrs,
39 char *secstrings,
40 struct module *mod)
41{
42 return 0;
43}
44
45int apply_relocate(Elf32_Shdr *sechdrs,
46 const char *strtab,
47 unsigned int symindex,
48 unsigned int relsec,
49 struct module *me)
50{
51 unsigned int i;
52 Elf32_Rel *rel = (void *)sechdrs[relsec].sh_addr;
53 Elf32_Sym *sym;
54 uint32_t *location;
55
56 DEBUGP("Applying relocate section %u to %u\n", relsec,
57 sechdrs[relsec].sh_info);
58 for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) {
59 /* This is where to make the change */
60 location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr
61 + rel[i].r_offset;
62 /* This is the symbol it is referring to. Note that all
63 undefined symbols have been resolved. */
64 sym = (Elf32_Sym *)sechdrs[symindex].sh_addr
65 + ELF32_R_SYM(rel[i].r_info);
66
67 switch (ELF32_R_TYPE(rel[i].r_info)) {
68 case R_68K_32:
69 /* We add the value into the location given */
70 *location += sym->st_value;
71 break;
72 case R_68K_PC32:
73 /* Add the value, subtract its postition */
74 *location += sym->st_value - (uint32_t)location;
75 break;
76 default:
77 printk(KERN_ERR "module %s: Unknown relocation: %u\n",
78 me->name, ELF32_R_TYPE(rel[i].r_info));
79 return -ENOEXEC;
80 }
81 }
82 return 0;
83}
84
85int apply_relocate_add(Elf32_Shdr *sechdrs,
86 const char *strtab,
87 unsigned int symindex,
88 unsigned int relsec,
89 struct module *me)
90{
91 unsigned int i;
92 Elf32_Rela *rel = (void *)sechdrs[relsec].sh_addr;
93 Elf32_Sym *sym;
94 uint32_t *location;
95
96 DEBUGP("Applying relocate_add section %u to %u\n", relsec,
97 sechdrs[relsec].sh_info);
98 for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) {
99 /* This is where to make the change */
100 location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr
101 + rel[i].r_offset;
102 /* This is the symbol it is referring to. Note that all
103 undefined symbols have been resolved. */
104 sym = (Elf32_Sym *)sechdrs[symindex].sh_addr
105 + ELF32_R_SYM(rel[i].r_info);
106
107 switch (ELF32_R_TYPE(rel[i].r_info)) {
108 case R_68K_32:
109 /* We add the value into the location given */
110 *location = rel[i].r_addend + sym->st_value;
111 break;
112 case R_68K_PC32:
113 /* Add the value, subtract its postition */
114 *location = rel[i].r_addend + sym->st_value - (uint32_t)location;
115 break;
116 default:
117 printk(KERN_ERR "module %s: Unknown relocation: %u\n",
118 me->name, ELF32_R_TYPE(rel[i].r_info));
119 return -ENOEXEC;
120 }
121 }
122 return 0;
123}
124
125int module_finalize(const Elf_Ehdr *hdr,
126 const Elf_Shdr *sechdrs,
127 struct module *mod)
128{
129 module_fixup(mod, mod->arch.fixup_start, mod->arch.fixup_end);
130
131 return 0;
132}
133
134void module_arch_cleanup(struct module *mod)
135{
136}
137
138#endif /* CONFIG_MODULES */
139
140void module_fixup(struct module *mod, struct m68k_fixup_info *start,
141 struct m68k_fixup_info *end)
142{
143 struct m68k_fixup_info *fixup;
144
145 for (fixup = start; fixup < end; fixup++) {
146 switch (fixup->type) {
147 case m68k_fixup_memoffset:
148 *(u32 *)fixup->addr = m68k_memoffset;
149 break;
150 case m68k_fixup_vnode_shift:
151 *(u16 *)fixup->addr += m68k_virt_to_node_shift;
152 break;
153 }
154 }
155}
diff --git a/arch/m68k/kernel/module_mm.c b/arch/m68k/kernel/module_mm.c
new file mode 100644
index 00000000000..cd6bcb1c957
--- /dev/null
+++ b/arch/m68k/kernel/module_mm.c
@@ -0,0 +1,155 @@
1/*
2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file COPYING in the main directory of this archive
4 * for more details.
5 */
6
7#include <linux/moduleloader.h>
8#include <linux/elf.h>
9#include <linux/vmalloc.h>
10#include <linux/fs.h>
11#include <linux/string.h>
12#include <linux/kernel.h>
13
14#if 0
15#define DEBUGP printk
16#else
17#define DEBUGP(fmt...)
18#endif
19
20#ifdef CONFIG_MODULES
21
22void *module_alloc(unsigned long size)
23{
24 if (size == 0)
25 return NULL;
26 return vmalloc(size);
27}
28
29
30/* Free memory returned from module_alloc */
31void module_free(struct module *mod, void *module_region)
32{
33 vfree(module_region);
34}
35
36/* We don't need anything special. */
37int module_frob_arch_sections(Elf_Ehdr *hdr,
38 Elf_Shdr *sechdrs,
39 char *secstrings,
40 struct module *mod)
41{
42 return 0;
43}
44
45int apply_relocate(Elf32_Shdr *sechdrs,
46 const char *strtab,
47 unsigned int symindex,
48 unsigned int relsec,
49 struct module *me)
50{
51 unsigned int i;
52 Elf32_Rel *rel = (void *)sechdrs[relsec].sh_addr;
53 Elf32_Sym *sym;
54 uint32_t *location;
55
56 DEBUGP("Applying relocate section %u to %u\n", relsec,
57 sechdrs[relsec].sh_info);
58 for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) {
59 /* This is where to make the change */
60 location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr
61 + rel[i].r_offset;
62 /* This is the symbol it is referring to. Note that all
63 undefined symbols have been resolved. */
64 sym = (Elf32_Sym *)sechdrs[symindex].sh_addr
65 + ELF32_R_SYM(rel[i].r_info);
66
67 switch (ELF32_R_TYPE(rel[i].r_info)) {
68 case R_68K_32:
69 /* We add the value into the location given */
70 *location += sym->st_value;
71 break;
72 case R_68K_PC32:
73 /* Add the value, subtract its postition */
74 *location += sym->st_value - (uint32_t)location;
75 break;
76 default:
77 printk(KERN_ERR "module %s: Unknown relocation: %u\n",
78 me->name, ELF32_R_TYPE(rel[i].r_info));
79 return -ENOEXEC;
80 }
81 }
82 return 0;
83}
84
85int apply_relocate_add(Elf32_Shdr *sechdrs,
86 const char *strtab,
87 unsigned int symindex,
88 unsigned int relsec,
89 struct module *me)
90{
91 unsigned int i;
92 Elf32_Rela *rel = (void *)sechdrs[relsec].sh_addr;
93 Elf32_Sym *sym;
94 uint32_t *location;
95
96 DEBUGP("Applying relocate_add section %u to %u\n", relsec,
97 sechdrs[relsec].sh_info);
98 for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) {
99 /* This is where to make the change */
100 location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr
101 + rel[i].r_offset;
102 /* This is the symbol it is referring to. Note that all
103 undefined symbols have been resolved. */
104 sym = (Elf32_Sym *)sechdrs[symindex].sh_addr
105 + ELF32_R_SYM(rel[i].r_info);
106
107 switch (ELF32_R_TYPE(rel[i].r_info)) {
108 case R_68K_32:
109 /* We add the value into the location given */
110 *location = rel[i].r_addend + sym->st_value;
111 break;
112 case R_68K_PC32:
113 /* Add the value, subtract its postition */
114 *location = rel[i].r_addend + sym->st_value - (uint32_t)location;
115 break;
116 default:
117 printk(KERN_ERR "module %s: Unknown relocation: %u\n",
118 me->name, ELF32_R_TYPE(rel[i].r_info));
119 return -ENOEXEC;
120 }
121 }
122 return 0;
123}
124
125int module_finalize(const Elf_Ehdr *hdr,
126 const Elf_Shdr *sechdrs,
127 struct module *mod)
128{
129 module_fixup(mod, mod->arch.fixup_start, mod->arch.fixup_end);
130
131 return 0;
132}
133
134void module_arch_cleanup(struct module *mod)
135{
136}
137
138#endif /* CONFIG_MODULES */
139
140void module_fixup(struct module *mod, struct m68k_fixup_info *start,
141 struct m68k_fixup_info *end)
142{
143 struct m68k_fixup_info *fixup;
144
145 for (fixup = start; fixup < end; fixup++) {
146 switch (fixup->type) {
147 case m68k_fixup_memoffset:
148 *(u32 *)fixup->addr = m68k_memoffset;
149 break;
150 case m68k_fixup_vnode_shift:
151 *(u16 *)fixup->addr += m68k_virt_to_node_shift;
152 break;
153 }
154 }
155}
diff --git a/arch/m68knommu/kernel/module.c b/arch/m68k/kernel/module_no.c
index d11ffae7956..d11ffae7956 100644
--- a/arch/m68knommu/kernel/module.c
+++ b/arch/m68k/kernel/module_no.c
diff --git a/arch/m68k/kernel/process.c b/arch/m68k/kernel/process.c
index c2a1fc23dd7..6cf4bd6e34f 100644
--- a/arch/m68k/kernel/process.c
+++ b/arch/m68k/kernel/process.c
@@ -1,354 +1,5 @@
1/* 1#ifdef CONFIG_MMU
2 * linux/arch/m68k/kernel/process.c 2#include "process_mm.c"
3 *
4 * Copyright (C) 1995 Hamish Macdonald
5 *
6 * 68060 fixes by Jesper Skov
7 */
8
9/*
10 * This file handles the architecture-dependent parts of process handling..
11 */
12
13#include <linux/errno.h>
14#include <linux/module.h>
15#include <linux/sched.h>
16#include <linux/kernel.h>
17#include <linux/mm.h>
18#include <linux/slab.h>
19#include <linux/fs.h>
20#include <linux/smp.h>
21#include <linux/stddef.h>
22#include <linux/unistd.h>
23#include <linux/ptrace.h>
24#include <linux/user.h>
25#include <linux/reboot.h>
26#include <linux/init_task.h>
27#include <linux/mqueue.h>
28
29#include <asm/uaccess.h>
30#include <asm/system.h>
31#include <asm/traps.h>
32#include <asm/machdep.h>
33#include <asm/setup.h>
34#include <asm/pgtable.h>
35
36/*
37 * Initial task/thread structure. Make this a per-architecture thing,
38 * because different architectures tend to have different
39 * alignment requirements and potentially different initial
40 * setup.
41 */
42static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
43static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
44union thread_union init_thread_union __init_task_data
45 __attribute__((aligned(THREAD_SIZE))) =
46 { INIT_THREAD_INFO(init_task) };
47
48/* initial task structure */
49struct task_struct init_task = INIT_TASK(init_task);
50
51EXPORT_SYMBOL(init_task);
52
53asmlinkage void ret_from_fork(void);
54
55
56/*
57 * Return saved PC from a blocked thread
58 */
59unsigned long thread_saved_pc(struct task_struct *tsk)
60{
61 struct switch_stack *sw = (struct switch_stack *)tsk->thread.ksp;
62 /* Check whether the thread is blocked in resume() */
63 if (in_sched_functions(sw->retpc))
64 return ((unsigned long *)sw->a6)[1];
65 else
66 return sw->retpc;
67}
68
69/*
70 * The idle loop on an m68k..
71 */
72static void default_idle(void)
73{
74 if (!need_resched())
75#if defined(MACH_ATARI_ONLY)
76 /* block out HSYNC on the atari (falcon) */
77 __asm__("stop #0x2200" : : : "cc");
78#else 3#else
79 __asm__("stop #0x2000" : : : "cc"); 4#include "process_no.c"
80#endif 5#endif
81}
82
83void (*idle)(void) = default_idle;
84
85/*
86 * The idle thread. There's no useful work to be
87 * done, so just try to conserve power and have a
88 * low exit latency (ie sit in a loop waiting for
89 * somebody to say that they'd like to reschedule)
90 */
91void cpu_idle(void)
92{
93 /* endless idle loop with no priority at all */
94 while (1) {
95 while (!need_resched())
96 idle();
97 preempt_enable_no_resched();
98 schedule();
99 preempt_disable();
100 }
101}
102
103void machine_restart(char * __unused)
104{
105 if (mach_reset)
106 mach_reset();
107 for (;;);
108}
109
110void machine_halt(void)
111{
112 if (mach_halt)
113 mach_halt();
114 for (;;);
115}
116
117void machine_power_off(void)
118{
119 if (mach_power_off)
120 mach_power_off();
121 for (;;);
122}
123
124void (*pm_power_off)(void) = machine_power_off;
125EXPORT_SYMBOL(pm_power_off);
126
127void show_regs(struct pt_regs * regs)
128{
129 printk("\n");
130 printk("Format %02x Vector: %04x PC: %08lx Status: %04x %s\n",
131 regs->format, regs->vector, regs->pc, regs->sr, print_tainted());
132 printk("ORIG_D0: %08lx D0: %08lx A2: %08lx A1: %08lx\n",
133 regs->orig_d0, regs->d0, regs->a2, regs->a1);
134 printk("A0: %08lx D5: %08lx D4: %08lx\n",
135 regs->a0, regs->d5, regs->d4);
136 printk("D3: %08lx D2: %08lx D1: %08lx\n",
137 regs->d3, regs->d2, regs->d1);
138 if (!(regs->sr & PS_S))
139 printk("USP: %08lx\n", rdusp());
140}
141
142/*
143 * Create a kernel thread
144 */
145int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
146{
147 int pid;
148 mm_segment_t fs;
149
150 fs = get_fs();
151 set_fs (KERNEL_DS);
152
153 {
154 register long retval __asm__ ("d0");
155 register long clone_arg __asm__ ("d1") = flags | CLONE_VM | CLONE_UNTRACED;
156
157 retval = __NR_clone;
158 __asm__ __volatile__
159 ("clrl %%d2\n\t"
160 "trap #0\n\t" /* Linux/m68k system call */
161 "tstl %0\n\t" /* child or parent */
162 "jne 1f\n\t" /* parent - jump */
163 "lea %%sp@(%c7),%6\n\t" /* reload current */
164 "movel %6@,%6\n\t"
165 "movel %3,%%sp@-\n\t" /* push argument */
166 "jsr %4@\n\t" /* call fn */
167 "movel %0,%%d1\n\t" /* pass exit value */
168 "movel %2,%%d0\n\t" /* exit */
169 "trap #0\n"
170 "1:"
171 : "+d" (retval)
172 : "i" (__NR_clone), "i" (__NR_exit),
173 "r" (arg), "a" (fn), "d" (clone_arg), "r" (current),
174 "i" (-THREAD_SIZE)
175 : "d2");
176
177 pid = retval;
178 }
179
180 set_fs (fs);
181 return pid;
182}
183EXPORT_SYMBOL(kernel_thread);
184
185void flush_thread(void)
186{
187 unsigned long zero = 0;
188 set_fs(USER_DS);
189 current->thread.fs = __USER_DS;
190 if (!FPU_IS_EMU)
191 asm volatile (".chip 68k/68881\n\t"
192 "frestore %0@\n\t"
193 ".chip 68k" : : "a" (&zero));
194}
195
196/*
197 * "m68k_fork()".. By the time we get here, the
198 * non-volatile registers have also been saved on the
199 * stack. We do some ugly pointer stuff here.. (see
200 * also copy_thread)
201 */
202
203asmlinkage int m68k_fork(struct pt_regs *regs)
204{
205 return do_fork(SIGCHLD, rdusp(), regs, 0, NULL, NULL);
206}
207
208asmlinkage int m68k_vfork(struct pt_regs *regs)
209{
210 return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, rdusp(), regs, 0,
211 NULL, NULL);
212}
213
214asmlinkage int m68k_clone(struct pt_regs *regs)
215{
216 unsigned long clone_flags;
217 unsigned long newsp;
218 int __user *parent_tidptr, *child_tidptr;
219
220 /* syscall2 puts clone_flags in d1 and usp in d2 */
221 clone_flags = regs->d1;
222 newsp = regs->d2;
223 parent_tidptr = (int __user *)regs->d3;
224 child_tidptr = (int __user *)regs->d4;
225 if (!newsp)
226 newsp = rdusp();
227 return do_fork(clone_flags, newsp, regs, 0,
228 parent_tidptr, child_tidptr);
229}
230
231int copy_thread(unsigned long clone_flags, unsigned long usp,
232 unsigned long unused,
233 struct task_struct * p, struct pt_regs * regs)
234{
235 struct pt_regs * childregs;
236 struct switch_stack * childstack, *stack;
237 unsigned long *retp;
238
239 childregs = (struct pt_regs *) (task_stack_page(p) + THREAD_SIZE) - 1;
240
241 *childregs = *regs;
242 childregs->d0 = 0;
243
244 retp = ((unsigned long *) regs);
245 stack = ((struct switch_stack *) retp) - 1;
246
247 childstack = ((struct switch_stack *) childregs) - 1;
248 *childstack = *stack;
249 childstack->retpc = (unsigned long)ret_from_fork;
250
251 p->thread.usp = usp;
252 p->thread.ksp = (unsigned long)childstack;
253
254 if (clone_flags & CLONE_SETTLS)
255 task_thread_info(p)->tp_value = regs->d5;
256
257 /*
258 * Must save the current SFC/DFC value, NOT the value when
259 * the parent was last descheduled - RGH 10-08-96
260 */
261 p->thread.fs = get_fs().seg;
262
263 if (!FPU_IS_EMU) {
264 /* Copy the current fpu state */
265 asm volatile ("fsave %0" : : "m" (p->thread.fpstate[0]) : "memory");
266
267 if (!CPU_IS_060 ? p->thread.fpstate[0] : p->thread.fpstate[2])
268 asm volatile ("fmovemx %/fp0-%/fp7,%0\n\t"
269 "fmoveml %/fpiar/%/fpcr/%/fpsr,%1"
270 : : "m" (p->thread.fp[0]), "m" (p->thread.fpcntl[0])
271 : "memory");
272 /* Restore the state in case the fpu was busy */
273 asm volatile ("frestore %0" : : "m" (p->thread.fpstate[0]));
274 }
275
276 return 0;
277}
278
279/* Fill in the fpu structure for a core dump. */
280
281int dump_fpu (struct pt_regs *regs, struct user_m68kfp_struct *fpu)
282{
283 char fpustate[216];
284
285 if (FPU_IS_EMU) {
286 int i;
287
288 memcpy(fpu->fpcntl, current->thread.fpcntl, 12);
289 memcpy(fpu->fpregs, current->thread.fp, 96);
290 /* Convert internal fpu reg representation
291 * into long double format
292 */
293 for (i = 0; i < 24; i += 3)
294 fpu->fpregs[i] = ((fpu->fpregs[i] & 0xffff0000) << 15) |
295 ((fpu->fpregs[i] & 0x0000ffff) << 16);
296 return 1;
297 }
298
299 /* First dump the fpu context to avoid protocol violation. */
300 asm volatile ("fsave %0" :: "m" (fpustate[0]) : "memory");
301 if (!CPU_IS_060 ? !fpustate[0] : !fpustate[2])
302 return 0;
303
304 asm volatile ("fmovem %/fpiar/%/fpcr/%/fpsr,%0"
305 :: "m" (fpu->fpcntl[0])
306 : "memory");
307 asm volatile ("fmovemx %/fp0-%/fp7,%0"
308 :: "m" (fpu->fpregs[0])
309 : "memory");
310 return 1;
311}
312EXPORT_SYMBOL(dump_fpu);
313
314/*
315 * sys_execve() executes a new program.
316 */
317asmlinkage int sys_execve(const char __user *name,
318 const char __user *const __user *argv,
319 const char __user *const __user *envp)
320{
321 int error;
322 char * filename;
323 struct pt_regs *regs = (struct pt_regs *) &name;
324
325 filename = getname(name);
326 error = PTR_ERR(filename);
327 if (IS_ERR(filename))
328 return error;
329 error = do_execve(filename, argv, envp, regs);
330 putname(filename);
331 return error;
332}
333
334unsigned long get_wchan(struct task_struct *p)
335{
336 unsigned long fp, pc;
337 unsigned long stack_page;
338 int count = 0;
339 if (!p || p == current || p->state == TASK_RUNNING)
340 return 0;
341
342 stack_page = (unsigned long)task_stack_page(p);
343 fp = ((struct switch_stack *)p->thread.ksp)->a6;
344 do {
345 if (fp < stack_page+sizeof(struct thread_info) ||
346 fp >= 8184+stack_page)
347 return 0;
348 pc = ((unsigned long *)fp)[1];
349 if (!in_sched_functions(pc))
350 return pc;
351 fp = *(unsigned long *) fp;
352 } while (count++ < 16);
353 return 0;
354}
diff --git a/arch/m68k/kernel/process_mm.c b/arch/m68k/kernel/process_mm.c
new file mode 100644
index 00000000000..c2a1fc23dd7
--- /dev/null
+++ b/arch/m68k/kernel/process_mm.c
@@ -0,0 +1,354 @@
1/*
2 * linux/arch/m68k/kernel/process.c
3 *
4 * Copyright (C) 1995 Hamish Macdonald
5 *
6 * 68060 fixes by Jesper Skov
7 */
8
9/*
10 * This file handles the architecture-dependent parts of process handling..
11 */
12
13#include <linux/errno.h>
14#include <linux/module.h>
15#include <linux/sched.h>
16#include <linux/kernel.h>
17#include <linux/mm.h>
18#include <linux/slab.h>
19#include <linux/fs.h>
20#include <linux/smp.h>
21#include <linux/stddef.h>
22#include <linux/unistd.h>
23#include <linux/ptrace.h>
24#include <linux/user.h>
25#include <linux/reboot.h>
26#include <linux/init_task.h>
27#include <linux/mqueue.h>
28
29#include <asm/uaccess.h>
30#include <asm/system.h>
31#include <asm/traps.h>
32#include <asm/machdep.h>
33#include <asm/setup.h>
34#include <asm/pgtable.h>
35
36/*
37 * Initial task/thread structure. Make this a per-architecture thing,
38 * because different architectures tend to have different
39 * alignment requirements and potentially different initial
40 * setup.
41 */
42static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
43static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
44union thread_union init_thread_union __init_task_data
45 __attribute__((aligned(THREAD_SIZE))) =
46 { INIT_THREAD_INFO(init_task) };
47
48/* initial task structure */
49struct task_struct init_task = INIT_TASK(init_task);
50
51EXPORT_SYMBOL(init_task);
52
53asmlinkage void ret_from_fork(void);
54
55
56/*
57 * Return saved PC from a blocked thread
58 */
59unsigned long thread_saved_pc(struct task_struct *tsk)
60{
61 struct switch_stack *sw = (struct switch_stack *)tsk->thread.ksp;
62 /* Check whether the thread is blocked in resume() */
63 if (in_sched_functions(sw->retpc))
64 return ((unsigned long *)sw->a6)[1];
65 else
66 return sw->retpc;
67}
68
69/*
70 * The idle loop on an m68k..
71 */
72static void default_idle(void)
73{
74 if (!need_resched())
75#if defined(MACH_ATARI_ONLY)
76 /* block out HSYNC on the atari (falcon) */
77 __asm__("stop #0x2200" : : : "cc");
78#else
79 __asm__("stop #0x2000" : : : "cc");
80#endif
81}
82
83void (*idle)(void) = default_idle;
84
85/*
86 * The idle thread. There's no useful work to be
87 * done, so just try to conserve power and have a
88 * low exit latency (ie sit in a loop waiting for
89 * somebody to say that they'd like to reschedule)
90 */
91void cpu_idle(void)
92{
93 /* endless idle loop with no priority at all */
94 while (1) {
95 while (!need_resched())
96 idle();
97 preempt_enable_no_resched();
98 schedule();
99 preempt_disable();
100 }
101}
102
103void machine_restart(char * __unused)
104{
105 if (mach_reset)
106 mach_reset();
107 for (;;);
108}
109
110void machine_halt(void)
111{
112 if (mach_halt)
113 mach_halt();
114 for (;;);
115}
116
117void machine_power_off(void)
118{
119 if (mach_power_off)
120 mach_power_off();
121 for (;;);
122}
123
124void (*pm_power_off)(void) = machine_power_off;
125EXPORT_SYMBOL(pm_power_off);
126
127void show_regs(struct pt_regs * regs)
128{
129 printk("\n");
130 printk("Format %02x Vector: %04x PC: %08lx Status: %04x %s\n",
131 regs->format, regs->vector, regs->pc, regs->sr, print_tainted());
132 printk("ORIG_D0: %08lx D0: %08lx A2: %08lx A1: %08lx\n",
133 regs->orig_d0, regs->d0, regs->a2, regs->a1);
134 printk("A0: %08lx D5: %08lx D4: %08lx\n",
135 regs->a0, regs->d5, regs->d4);
136 printk("D3: %08lx D2: %08lx D1: %08lx\n",
137 regs->d3, regs->d2, regs->d1);
138 if (!(regs->sr & PS_S))
139 printk("USP: %08lx\n", rdusp());
140}
141
142/*
143 * Create a kernel thread
144 */
145int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
146{
147 int pid;
148 mm_segment_t fs;
149
150 fs = get_fs();
151 set_fs (KERNEL_DS);
152
153 {
154 register long retval __asm__ ("d0");
155 register long clone_arg __asm__ ("d1") = flags | CLONE_VM | CLONE_UNTRACED;
156
157 retval = __NR_clone;
158 __asm__ __volatile__
159 ("clrl %%d2\n\t"
160 "trap #0\n\t" /* Linux/m68k system call */
161 "tstl %0\n\t" /* child or parent */
162 "jne 1f\n\t" /* parent - jump */
163 "lea %%sp@(%c7),%6\n\t" /* reload current */
164 "movel %6@,%6\n\t"
165 "movel %3,%%sp@-\n\t" /* push argument */
166 "jsr %4@\n\t" /* call fn */
167 "movel %0,%%d1\n\t" /* pass exit value */
168 "movel %2,%%d0\n\t" /* exit */
169 "trap #0\n"
170 "1:"
171 : "+d" (retval)
172 : "i" (__NR_clone), "i" (__NR_exit),
173 "r" (arg), "a" (fn), "d" (clone_arg), "r" (current),
174 "i" (-THREAD_SIZE)
175 : "d2");
176
177 pid = retval;
178 }
179
180 set_fs (fs);
181 return pid;
182}
183EXPORT_SYMBOL(kernel_thread);
184
185void flush_thread(void)
186{
187 unsigned long zero = 0;
188 set_fs(USER_DS);
189 current->thread.fs = __USER_DS;
190 if (!FPU_IS_EMU)
191 asm volatile (".chip 68k/68881\n\t"
192 "frestore %0@\n\t"
193 ".chip 68k" : : "a" (&zero));
194}
195
196/*
197 * "m68k_fork()".. By the time we get here, the
198 * non-volatile registers have also been saved on the
199 * stack. We do some ugly pointer stuff here.. (see
200 * also copy_thread)
201 */
202
203asmlinkage int m68k_fork(struct pt_regs *regs)
204{
205 return do_fork(SIGCHLD, rdusp(), regs, 0, NULL, NULL);
206}
207
208asmlinkage int m68k_vfork(struct pt_regs *regs)
209{
210 return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, rdusp(), regs, 0,
211 NULL, NULL);
212}
213
214asmlinkage int m68k_clone(struct pt_regs *regs)
215{
216 unsigned long clone_flags;
217 unsigned long newsp;
218 int __user *parent_tidptr, *child_tidptr;
219
220 /* syscall2 puts clone_flags in d1 and usp in d2 */
221 clone_flags = regs->d1;
222 newsp = regs->d2;
223 parent_tidptr = (int __user *)regs->d3;
224 child_tidptr = (int __user *)regs->d4;
225 if (!newsp)
226 newsp = rdusp();
227 return do_fork(clone_flags, newsp, regs, 0,
228 parent_tidptr, child_tidptr);
229}
230
231int copy_thread(unsigned long clone_flags, unsigned long usp,
232 unsigned long unused,
233 struct task_struct * p, struct pt_regs * regs)
234{
235 struct pt_regs * childregs;
236 struct switch_stack * childstack, *stack;
237 unsigned long *retp;
238
239 childregs = (struct pt_regs *) (task_stack_page(p) + THREAD_SIZE) - 1;
240
241 *childregs = *regs;
242 childregs->d0 = 0;
243
244 retp = ((unsigned long *) regs);
245 stack = ((struct switch_stack *) retp) - 1;
246
247 childstack = ((struct switch_stack *) childregs) - 1;
248 *childstack = *stack;
249 childstack->retpc = (unsigned long)ret_from_fork;
250
251 p->thread.usp = usp;
252 p->thread.ksp = (unsigned long)childstack;
253
254 if (clone_flags & CLONE_SETTLS)
255 task_thread_info(p)->tp_value = regs->d5;
256
257 /*
258 * Must save the current SFC/DFC value, NOT the value when
259 * the parent was last descheduled - RGH 10-08-96
260 */
261 p->thread.fs = get_fs().seg;
262
263 if (!FPU_IS_EMU) {
264 /* Copy the current fpu state */
265 asm volatile ("fsave %0" : : "m" (p->thread.fpstate[0]) : "memory");
266
267 if (!CPU_IS_060 ? p->thread.fpstate[0] : p->thread.fpstate[2])
268 asm volatile ("fmovemx %/fp0-%/fp7,%0\n\t"
269 "fmoveml %/fpiar/%/fpcr/%/fpsr,%1"
270 : : "m" (p->thread.fp[0]), "m" (p->thread.fpcntl[0])
271 : "memory");
272 /* Restore the state in case the fpu was busy */
273 asm volatile ("frestore %0" : : "m" (p->thread.fpstate[0]));
274 }
275
276 return 0;
277}
278
279/* Fill in the fpu structure for a core dump. */
280
281int dump_fpu (struct pt_regs *regs, struct user_m68kfp_struct *fpu)
282{
283 char fpustate[216];
284
285 if (FPU_IS_EMU) {
286 int i;
287
288 memcpy(fpu->fpcntl, current->thread.fpcntl, 12);
289 memcpy(fpu->fpregs, current->thread.fp, 96);
290 /* Convert internal fpu reg representation
291 * into long double format
292 */
293 for (i = 0; i < 24; i += 3)
294 fpu->fpregs[i] = ((fpu->fpregs[i] & 0xffff0000) << 15) |
295 ((fpu->fpregs[i] & 0x0000ffff) << 16);
296 return 1;
297 }
298
299 /* First dump the fpu context to avoid protocol violation. */
300 asm volatile ("fsave %0" :: "m" (fpustate[0]) : "memory");
301 if (!CPU_IS_060 ? !fpustate[0] : !fpustate[2])
302 return 0;
303
304 asm volatile ("fmovem %/fpiar/%/fpcr/%/fpsr,%0"
305 :: "m" (fpu->fpcntl[0])
306 : "memory");
307 asm volatile ("fmovemx %/fp0-%/fp7,%0"
308 :: "m" (fpu->fpregs[0])
309 : "memory");
310 return 1;
311}
312EXPORT_SYMBOL(dump_fpu);
313
314/*
315 * sys_execve() executes a new program.
316 */
317asmlinkage int sys_execve(const char __user *name,
318 const char __user *const __user *argv,
319 const char __user *const __user *envp)
320{
321 int error;
322 char * filename;
323 struct pt_regs *regs = (struct pt_regs *) &name;
324
325 filename = getname(name);
326 error = PTR_ERR(filename);
327 if (IS_ERR(filename))
328 return error;
329 error = do_execve(filename, argv, envp, regs);
330 putname(filename);
331 return error;
332}
333
334unsigned long get_wchan(struct task_struct *p)
335{
336 unsigned long fp, pc;
337 unsigned long stack_page;
338 int count = 0;
339 if (!p || p == current || p->state == TASK_RUNNING)
340 return 0;
341
342 stack_page = (unsigned long)task_stack_page(p);
343 fp = ((struct switch_stack *)p->thread.ksp)->a6;
344 do {
345 if (fp < stack_page+sizeof(struct thread_info) ||
346 fp >= 8184+stack_page)
347 return 0;
348 pc = ((unsigned long *)fp)[1];
349 if (!in_sched_functions(pc))
350 return pc;
351 fp = *(unsigned long *) fp;
352 } while (count++ < 16);
353 return 0;
354}
diff --git a/arch/m68knommu/kernel/process.c b/arch/m68k/kernel/process_no.c
index e2a63af5d51..e2a63af5d51 100644
--- a/arch/m68knommu/kernel/process.c
+++ b/arch/m68k/kernel/process_no.c
diff --git a/arch/m68k/kernel/ptrace.c b/arch/m68k/kernel/ptrace.c
index 0b252683cef..07a417550e9 100644
--- a/arch/m68k/kernel/ptrace.c
+++ b/arch/m68k/kernel/ptrace.c
@@ -1,277 +1,5 @@
1/* 1#ifdef CONFIG_MMU
2 * linux/arch/m68k/kernel/ptrace.c 2#include "ptrace_mm.c"
3 * 3#else
4 * Copyright (C) 1994 by Hamish Macdonald 4#include "ptrace_no.c"
5 * Taken from linux/kernel/ptrace.c and modified for M680x0. 5#endif
6 * linux/kernel/ptrace.c is by Ross Biro 1/23/92, edited by Linus Torvalds
7 *
8 * This file is subject to the terms and conditions of the GNU General
9 * Public License. See the file COPYING in the main directory of
10 * this archive for more details.
11 */
12
13#include <linux/kernel.h>
14#include <linux/sched.h>
15#include <linux/mm.h>
16#include <linux/smp.h>
17#include <linux/errno.h>
18#include <linux/ptrace.h>
19#include <linux/user.h>
20#include <linux/signal.h>
21
22#include <asm/uaccess.h>
23#include <asm/page.h>
24#include <asm/pgtable.h>
25#include <asm/system.h>
26#include <asm/processor.h>
27
28/*
29 * does not yet catch signals sent when the child dies.
30 * in exit.c or in signal.c.
31 */
32
33/* determines which bits in the SR the user has access to. */
34/* 1 = access 0 = no access */
35#define SR_MASK 0x001f
36
37/* sets the trace bits. */
38#define TRACE_BITS 0xC000
39#define T1_BIT 0x8000
40#define T0_BIT 0x4000
41
42/* Find the stack offset for a register, relative to thread.esp0. */
43#define PT_REG(reg) ((long)&((struct pt_regs *)0)->reg)
44#define SW_REG(reg) ((long)&((struct switch_stack *)0)->reg \
45 - sizeof(struct switch_stack))
46/* Mapping from PT_xxx to the stack offset at which the register is
47 saved. Notice that usp has no stack-slot and needs to be treated
48 specially (see get_reg/put_reg below). */
49static const int regoff[] = {
50 [0] = PT_REG(d1),
51 [1] = PT_REG(d2),
52 [2] = PT_REG(d3),
53 [3] = PT_REG(d4),
54 [4] = PT_REG(d5),
55 [5] = SW_REG(d6),
56 [6] = SW_REG(d7),
57 [7] = PT_REG(a0),
58 [8] = PT_REG(a1),
59 [9] = PT_REG(a2),
60 [10] = SW_REG(a3),
61 [11] = SW_REG(a4),
62 [12] = SW_REG(a5),
63 [13] = SW_REG(a6),
64 [14] = PT_REG(d0),
65 [15] = -1,
66 [16] = PT_REG(orig_d0),
67 [17] = PT_REG(sr),
68 [18] = PT_REG(pc),
69};
70
71/*
72 * Get contents of register REGNO in task TASK.
73 */
74static inline long get_reg(struct task_struct *task, int regno)
75{
76 unsigned long *addr;
77
78 if (regno == PT_USP)
79 addr = &task->thread.usp;
80 else if (regno < ARRAY_SIZE(regoff))
81 addr = (unsigned long *)(task->thread.esp0 + regoff[regno]);
82 else
83 return 0;
84 /* Need to take stkadj into account. */
85 if (regno == PT_SR || regno == PT_PC) {
86 long stkadj = *(long *)(task->thread.esp0 + PT_REG(stkadj));
87 addr = (unsigned long *) ((unsigned long)addr + stkadj);
88 /* The sr is actually a 16 bit register. */
89 if (regno == PT_SR)
90 return *(unsigned short *)addr;
91 }
92 return *addr;
93}
94
95/*
96 * Write contents of register REGNO in task TASK.
97 */
98static inline int put_reg(struct task_struct *task, int regno,
99 unsigned long data)
100{
101 unsigned long *addr;
102
103 if (regno == PT_USP)
104 addr = &task->thread.usp;
105 else if (regno < ARRAY_SIZE(regoff))
106 addr = (unsigned long *)(task->thread.esp0 + regoff[regno]);
107 else
108 return -1;
109 /* Need to take stkadj into account. */
110 if (regno == PT_SR || regno == PT_PC) {
111 long stkadj = *(long *)(task->thread.esp0 + PT_REG(stkadj));
112 addr = (unsigned long *) ((unsigned long)addr + stkadj);
113 /* The sr is actually a 16 bit register. */
114 if (regno == PT_SR) {
115 *(unsigned short *)addr = data;
116 return 0;
117 }
118 }
119 *addr = data;
120 return 0;
121}
122
123/*
124 * Make sure the single step bit is not set.
125 */
126static inline void singlestep_disable(struct task_struct *child)
127{
128 unsigned long tmp = get_reg(child, PT_SR) & ~TRACE_BITS;
129 put_reg(child, PT_SR, tmp);
130 clear_tsk_thread_flag(child, TIF_DELAYED_TRACE);
131}
132
133/*
134 * Called by kernel/ptrace.c when detaching..
135 */
136void ptrace_disable(struct task_struct *child)
137{
138 singlestep_disable(child);
139}
140
141void user_enable_single_step(struct task_struct *child)
142{
143 unsigned long tmp = get_reg(child, PT_SR) & ~TRACE_BITS;
144 put_reg(child, PT_SR, tmp | T1_BIT);
145 set_tsk_thread_flag(child, TIF_DELAYED_TRACE);
146}
147
148void user_enable_block_step(struct task_struct *child)
149{
150 unsigned long tmp = get_reg(child, PT_SR) & ~TRACE_BITS;
151 put_reg(child, PT_SR, tmp | T0_BIT);
152}
153
154void user_disable_single_step(struct task_struct *child)
155{
156 singlestep_disable(child);
157}
158
159long arch_ptrace(struct task_struct *child, long request,
160 unsigned long addr, unsigned long data)
161{
162 unsigned long tmp;
163 int i, ret = 0;
164 int regno = addr >> 2; /* temporary hack. */
165 unsigned long __user *datap = (unsigned long __user *) data;
166
167 switch (request) {
168 /* read the word at location addr in the USER area. */
169 case PTRACE_PEEKUSR:
170 if (addr & 3)
171 goto out_eio;
172
173 if (regno >= 0 && regno < 19) {
174 tmp = get_reg(child, regno);
175 } else if (regno >= 21 && regno < 49) {
176 tmp = child->thread.fp[regno - 21];
177 /* Convert internal fpu reg representation
178 * into long double format
179 */
180 if (FPU_IS_EMU && (regno < 45) && !(regno % 3))
181 tmp = ((tmp & 0xffff0000) << 15) |
182 ((tmp & 0x0000ffff) << 16);
183 } else
184 goto out_eio;
185 ret = put_user(tmp, datap);
186 break;
187
188 case PTRACE_POKEUSR:
189 /* write the word at location addr in the USER area */
190 if (addr & 3)
191 goto out_eio;
192
193 if (regno == PT_SR) {
194 data &= SR_MASK;
195 data |= get_reg(child, PT_SR) & ~SR_MASK;
196 }
197 if (regno >= 0 && regno < 19) {
198 if (put_reg(child, regno, data))
199 goto out_eio;
200 } else if (regno >= 21 && regno < 48) {
201 /* Convert long double format
202 * into internal fpu reg representation
203 */
204 if (FPU_IS_EMU && (regno < 45) && !(regno % 3)) {
205 data <<= 15;
206 data = (data & 0xffff0000) |
207 ((data & 0x0000ffff) >> 1);
208 }
209 child->thread.fp[regno - 21] = data;
210 } else
211 goto out_eio;
212 break;
213
214 case PTRACE_GETREGS: /* Get all gp regs from the child. */
215 for (i = 0; i < 19; i++) {
216 tmp = get_reg(child, i);
217 ret = put_user(tmp, datap);
218 if (ret)
219 break;
220 datap++;
221 }
222 break;
223
224 case PTRACE_SETREGS: /* Set all gp regs in the child. */
225 for (i = 0; i < 19; i++) {
226 ret = get_user(tmp, datap);
227 if (ret)
228 break;
229 if (i == PT_SR) {
230 tmp &= SR_MASK;
231 tmp |= get_reg(child, PT_SR) & ~SR_MASK;
232 }
233 put_reg(child, i, tmp);
234 datap++;
235 }
236 break;
237
238 case PTRACE_GETFPREGS: /* Get the child FPU state. */
239 if (copy_to_user(datap, &child->thread.fp,
240 sizeof(struct user_m68kfp_struct)))
241 ret = -EFAULT;
242 break;
243
244 case PTRACE_SETFPREGS: /* Set the child FPU state. */
245 if (copy_from_user(&child->thread.fp, datap,
246 sizeof(struct user_m68kfp_struct)))
247 ret = -EFAULT;
248 break;
249
250 case PTRACE_GET_THREAD_AREA:
251 ret = put_user(task_thread_info(child)->tp_value, datap);
252 break;
253
254 default:
255 ret = ptrace_request(child, request, addr, data);
256 break;
257 }
258
259 return ret;
260out_eio:
261 return -EIO;
262}
263
264asmlinkage void syscall_trace(void)
265{
266 ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
267 ? 0x80 : 0));
268 /*
269 * this isn't the same as continuing with a signal, but it will do
270 * for normal use. strace only continues with a signal if the
271 * stopping signal is not SIGTRAP. -brl
272 */
273 if (current->exit_code) {
274 send_sig(current->exit_code, current, 1);
275 current->exit_code = 0;
276 }
277}
diff --git a/arch/m68k/kernel/ptrace_mm.c b/arch/m68k/kernel/ptrace_mm.c
new file mode 100644
index 00000000000..0b252683cef
--- /dev/null
+++ b/arch/m68k/kernel/ptrace_mm.c
@@ -0,0 +1,277 @@
1/*
2 * linux/arch/m68k/kernel/ptrace.c
3 *
4 * Copyright (C) 1994 by Hamish Macdonald
5 * Taken from linux/kernel/ptrace.c and modified for M680x0.
6 * linux/kernel/ptrace.c is by Ross Biro 1/23/92, edited by Linus Torvalds
7 *
8 * This file is subject to the terms and conditions of the GNU General
9 * Public License. See the file COPYING in the main directory of
10 * this archive for more details.
11 */
12
13#include <linux/kernel.h>
14#include <linux/sched.h>
15#include <linux/mm.h>
16#include <linux/smp.h>
17#include <linux/errno.h>
18#include <linux/ptrace.h>
19#include <linux/user.h>
20#include <linux/signal.h>
21
22#include <asm/uaccess.h>
23#include <asm/page.h>
24#include <asm/pgtable.h>
25#include <asm/system.h>
26#include <asm/processor.h>
27
28/*
29 * does not yet catch signals sent when the child dies.
30 * in exit.c or in signal.c.
31 */
32
33/* determines which bits in the SR the user has access to. */
34/* 1 = access 0 = no access */
35#define SR_MASK 0x001f
36
37/* sets the trace bits. */
38#define TRACE_BITS 0xC000
39#define T1_BIT 0x8000
40#define T0_BIT 0x4000
41
42/* Find the stack offset for a register, relative to thread.esp0. */
43#define PT_REG(reg) ((long)&((struct pt_regs *)0)->reg)
44#define SW_REG(reg) ((long)&((struct switch_stack *)0)->reg \
45 - sizeof(struct switch_stack))
46/* Mapping from PT_xxx to the stack offset at which the register is
47 saved. Notice that usp has no stack-slot and needs to be treated
48 specially (see get_reg/put_reg below). */
49static const int regoff[] = {
50 [0] = PT_REG(d1),
51 [1] = PT_REG(d2),
52 [2] = PT_REG(d3),
53 [3] = PT_REG(d4),
54 [4] = PT_REG(d5),
55 [5] = SW_REG(d6),
56 [6] = SW_REG(d7),
57 [7] = PT_REG(a0),
58 [8] = PT_REG(a1),
59 [9] = PT_REG(a2),
60 [10] = SW_REG(a3),
61 [11] = SW_REG(a4),
62 [12] = SW_REG(a5),
63 [13] = SW_REG(a6),
64 [14] = PT_REG(d0),
65 [15] = -1,
66 [16] = PT_REG(orig_d0),
67 [17] = PT_REG(sr),
68 [18] = PT_REG(pc),
69};
70
71/*
72 * Get contents of register REGNO in task TASK.
73 */
74static inline long get_reg(struct task_struct *task, int regno)
75{
76 unsigned long *addr;
77
78 if (regno == PT_USP)
79 addr = &task->thread.usp;
80 else if (regno < ARRAY_SIZE(regoff))
81 addr = (unsigned long *)(task->thread.esp0 + regoff[regno]);
82 else
83 return 0;
84 /* Need to take stkadj into account. */
85 if (regno == PT_SR || regno == PT_PC) {
86 long stkadj = *(long *)(task->thread.esp0 + PT_REG(stkadj));
87 addr = (unsigned long *) ((unsigned long)addr + stkadj);
88 /* The sr is actually a 16 bit register. */
89 if (regno == PT_SR)
90 return *(unsigned short *)addr;
91 }
92 return *addr;
93}
94
95/*
96 * Write contents of register REGNO in task TASK.
97 */
98static inline int put_reg(struct task_struct *task, int regno,
99 unsigned long data)
100{
101 unsigned long *addr;
102
103 if (regno == PT_USP)
104 addr = &task->thread.usp;
105 else if (regno < ARRAY_SIZE(regoff))
106 addr = (unsigned long *)(task->thread.esp0 + regoff[regno]);
107 else
108 return -1;
109 /* Need to take stkadj into account. */
110 if (regno == PT_SR || regno == PT_PC) {
111 long stkadj = *(long *)(task->thread.esp0 + PT_REG(stkadj));
112 addr = (unsigned long *) ((unsigned long)addr + stkadj);
113 /* The sr is actually a 16 bit register. */
114 if (regno == PT_SR) {
115 *(unsigned short *)addr = data;
116 return 0;
117 }
118 }
119 *addr = data;
120 return 0;
121}
122
123/*
124 * Make sure the single step bit is not set.
125 */
126static inline void singlestep_disable(struct task_struct *child)
127{
128 unsigned long tmp = get_reg(child, PT_SR) & ~TRACE_BITS;
129 put_reg(child, PT_SR, tmp);
130 clear_tsk_thread_flag(child, TIF_DELAYED_TRACE);
131}
132
133/*
134 * Called by kernel/ptrace.c when detaching..
135 */
136void ptrace_disable(struct task_struct *child)
137{
138 singlestep_disable(child);
139}
140
141void user_enable_single_step(struct task_struct *child)
142{
143 unsigned long tmp = get_reg(child, PT_SR) & ~TRACE_BITS;
144 put_reg(child, PT_SR, tmp | T1_BIT);
145 set_tsk_thread_flag(child, TIF_DELAYED_TRACE);
146}
147
148void user_enable_block_step(struct task_struct *child)
149{
150 unsigned long tmp = get_reg(child, PT_SR) & ~TRACE_BITS;
151 put_reg(child, PT_SR, tmp | T0_BIT);
152}
153
154void user_disable_single_step(struct task_struct *child)
155{
156 singlestep_disable(child);
157}
158
159long arch_ptrace(struct task_struct *child, long request,
160 unsigned long addr, unsigned long data)
161{
162 unsigned long tmp;
163 int i, ret = 0;
164 int regno = addr >> 2; /* temporary hack. */
165 unsigned long __user *datap = (unsigned long __user *) data;
166
167 switch (request) {
168 /* read the word at location addr in the USER area. */
169 case PTRACE_PEEKUSR:
170 if (addr & 3)
171 goto out_eio;
172
173 if (regno >= 0 && regno < 19) {
174 tmp = get_reg(child, regno);
175 } else if (regno >= 21 && regno < 49) {
176 tmp = child->thread.fp[regno - 21];
177 /* Convert internal fpu reg representation
178 * into long double format
179 */
180 if (FPU_IS_EMU && (regno < 45) && !(regno % 3))
181 tmp = ((tmp & 0xffff0000) << 15) |
182 ((tmp & 0x0000ffff) << 16);
183 } else
184 goto out_eio;
185 ret = put_user(tmp, datap);
186 break;
187
188 case PTRACE_POKEUSR:
189 /* write the word at location addr in the USER area */
190 if (addr & 3)
191 goto out_eio;
192
193 if (regno == PT_SR) {
194 data &= SR_MASK;
195 data |= get_reg(child, PT_SR) & ~SR_MASK;
196 }
197 if (regno >= 0 && regno < 19) {
198 if (put_reg(child, regno, data))
199 goto out_eio;
200 } else if (regno >= 21 && regno < 48) {
201 /* Convert long double format
202 * into internal fpu reg representation
203 */
204 if (FPU_IS_EMU && (regno < 45) && !(regno % 3)) {
205 data <<= 15;
206 data = (data & 0xffff0000) |
207 ((data & 0x0000ffff) >> 1);
208 }
209 child->thread.fp[regno - 21] = data;
210 } else
211 goto out_eio;
212 break;
213
214 case PTRACE_GETREGS: /* Get all gp regs from the child. */
215 for (i = 0; i < 19; i++) {
216 tmp = get_reg(child, i);
217 ret = put_user(tmp, datap);
218 if (ret)
219 break;
220 datap++;
221 }
222 break;
223
224 case PTRACE_SETREGS: /* Set all gp regs in the child. */
225 for (i = 0; i < 19; i++) {
226 ret = get_user(tmp, datap);
227 if (ret)
228 break;
229 if (i == PT_SR) {
230 tmp &= SR_MASK;
231 tmp |= get_reg(child, PT_SR) & ~SR_MASK;
232 }
233 put_reg(child, i, tmp);
234 datap++;
235 }
236 break;
237
238 case PTRACE_GETFPREGS: /* Get the child FPU state. */
239 if (copy_to_user(datap, &child->thread.fp,
240 sizeof(struct user_m68kfp_struct)))
241 ret = -EFAULT;
242 break;
243
244 case PTRACE_SETFPREGS: /* Set the child FPU state. */
245 if (copy_from_user(&child->thread.fp, datap,
246 sizeof(struct user_m68kfp_struct)))
247 ret = -EFAULT;
248 break;
249
250 case PTRACE_GET_THREAD_AREA:
251 ret = put_user(task_thread_info(child)->tp_value, datap);
252 break;
253
254 default:
255 ret = ptrace_request(child, request, addr, data);
256 break;
257 }
258
259 return ret;
260out_eio:
261 return -EIO;
262}
263
264asmlinkage void syscall_trace(void)
265{
266 ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
267 ? 0x80 : 0));
268 /*
269 * this isn't the same as continuing with a signal, but it will do
270 * for normal use. strace only continues with a signal if the
271 * stopping signal is not SIGTRAP. -brl
272 */
273 if (current->exit_code) {
274 send_sig(current->exit_code, current, 1);
275 current->exit_code = 0;
276 }
277}
diff --git a/arch/m68knommu/kernel/ptrace.c b/arch/m68k/kernel/ptrace_no.c
index 6709fb70733..6709fb70733 100644
--- a/arch/m68knommu/kernel/ptrace.c
+++ b/arch/m68k/kernel/ptrace_no.c
diff --git a/arch/m68k/kernel/setup.c b/arch/m68k/kernel/setup.c
index 334d8364037..4bf129f1d2e 100644
--- a/arch/m68k/kernel/setup.c
+++ b/arch/m68k/kernel/setup.c
@@ -1,533 +1,5 @@
1/* 1#ifdef CONFIG_MMU
2 * linux/arch/m68k/kernel/setup.c 2#include "setup_mm.c"
3 *
4 * Copyright (C) 1995 Hamish Macdonald
5 */
6
7/*
8 * This file handles the architecture-dependent parts of system setup
9 */
10
11#include <linux/kernel.h>
12#include <linux/mm.h>
13#include <linux/sched.h>
14#include <linux/delay.h>
15#include <linux/interrupt.h>
16#include <linux/fs.h>
17#include <linux/console.h>
18#include <linux/genhd.h>
19#include <linux/errno.h>
20#include <linux/string.h>
21#include <linux/init.h>
22#include <linux/bootmem.h>
23#include <linux/proc_fs.h>
24#include <linux/seq_file.h>
25#include <linux/module.h>
26#include <linux/initrd.h>
27
28#include <asm/bootinfo.h>
29#include <asm/sections.h>
30#include <asm/setup.h>
31#include <asm/fpu.h>
32#include <asm/irq.h>
33#include <asm/io.h>
34#include <asm/machdep.h>
35#ifdef CONFIG_AMIGA
36#include <asm/amigahw.h>
37#endif
38#ifdef CONFIG_ATARI
39#include <asm/atarihw.h>
40#include <asm/atari_stram.h>
41#endif
42#ifdef CONFIG_SUN3X
43#include <asm/dvma.h>
44#endif
45#include <asm/natfeat.h>
46
47#if !FPSTATESIZE || !NR_IRQS
48#warning No CPU/platform type selected, your kernel will not work!
49#warning Are you building an allnoconfig kernel?
50#endif
51
52unsigned long m68k_machtype;
53EXPORT_SYMBOL(m68k_machtype);
54unsigned long m68k_cputype;
55EXPORT_SYMBOL(m68k_cputype);
56unsigned long m68k_fputype;
57unsigned long m68k_mmutype;
58EXPORT_SYMBOL(m68k_mmutype);
59#ifdef CONFIG_VME
60unsigned long vme_brdtype;
61EXPORT_SYMBOL(vme_brdtype);
62#endif
63
64int m68k_is040or060;
65EXPORT_SYMBOL(m68k_is040or060);
66
67extern unsigned long availmem;
68
69int m68k_num_memory;
70EXPORT_SYMBOL(m68k_num_memory);
71int m68k_realnum_memory;
72EXPORT_SYMBOL(m68k_realnum_memory);
73unsigned long m68k_memoffset;
74struct mem_info m68k_memory[NUM_MEMINFO];
75EXPORT_SYMBOL(m68k_memory);
76
77struct mem_info m68k_ramdisk;
78
79static char m68k_command_line[CL_SIZE];
80
81void (*mach_sched_init) (irq_handler_t handler) __initdata = NULL;
82/* machine dependent irq functions */
83void (*mach_init_IRQ) (void) __initdata = NULL;
84void (*mach_get_model) (char *model);
85void (*mach_get_hardware_list) (struct seq_file *m);
86/* machine dependent timer functions */
87unsigned long (*mach_gettimeoffset) (void);
88int (*mach_hwclk) (int, struct rtc_time*);
89EXPORT_SYMBOL(mach_hwclk);
90int (*mach_set_clock_mmss) (unsigned long);
91unsigned int (*mach_get_ss)(void);
92int (*mach_get_rtc_pll)(struct rtc_pll_info *);
93int (*mach_set_rtc_pll)(struct rtc_pll_info *);
94EXPORT_SYMBOL(mach_get_ss);
95EXPORT_SYMBOL(mach_get_rtc_pll);
96EXPORT_SYMBOL(mach_set_rtc_pll);
97void (*mach_reset)( void );
98void (*mach_halt)( void );
99void (*mach_power_off)( void );
100long mach_max_dma_address = 0x00ffffff; /* default set to the lower 16MB */
101#ifdef CONFIG_HEARTBEAT
102void (*mach_heartbeat) (int);
103EXPORT_SYMBOL(mach_heartbeat);
104#endif
105#ifdef CONFIG_M68K_L2_CACHE
106void (*mach_l2_flush) (int);
107#endif
108#if defined(CONFIG_INPUT_M68K_BEEP) || defined(CONFIG_INPUT_M68K_BEEP_MODULE)
109void (*mach_beep)(unsigned int, unsigned int);
110EXPORT_SYMBOL(mach_beep);
111#endif
112#if defined(CONFIG_ISA) && defined(MULTI_ISA)
113int isa_type;
114int isa_sex;
115EXPORT_SYMBOL(isa_type);
116EXPORT_SYMBOL(isa_sex);
117#endif
118
119extern int amiga_parse_bootinfo(const struct bi_record *);
120extern int atari_parse_bootinfo(const struct bi_record *);
121extern int mac_parse_bootinfo(const struct bi_record *);
122extern int q40_parse_bootinfo(const struct bi_record *);
123extern int bvme6000_parse_bootinfo(const struct bi_record *);
124extern int mvme16x_parse_bootinfo(const struct bi_record *);
125extern int mvme147_parse_bootinfo(const struct bi_record *);
126extern int hp300_parse_bootinfo(const struct bi_record *);
127extern int apollo_parse_bootinfo(const struct bi_record *);
128
129extern void config_amiga(void);
130extern void config_atari(void);
131extern void config_mac(void);
132extern void config_sun3(void);
133extern void config_apollo(void);
134extern void config_mvme147(void);
135extern void config_mvme16x(void);
136extern void config_bvme6000(void);
137extern void config_hp300(void);
138extern void config_q40(void);
139extern void config_sun3x(void);
140
141#define MASK_256K 0xfffc0000
142
143extern void paging_init(void);
144
145static void __init m68k_parse_bootinfo(const struct bi_record *record)
146{
147 while (record->tag != BI_LAST) {
148 int unknown = 0;
149 const unsigned long *data = record->data;
150
151 switch (record->tag) {
152 case BI_MACHTYPE:
153 case BI_CPUTYPE:
154 case BI_FPUTYPE:
155 case BI_MMUTYPE:
156 /* Already set up by head.S */
157 break;
158
159 case BI_MEMCHUNK:
160 if (m68k_num_memory < NUM_MEMINFO) {
161 m68k_memory[m68k_num_memory].addr = data[0];
162 m68k_memory[m68k_num_memory].size = data[1];
163 m68k_num_memory++;
164 } else
165 printk("m68k_parse_bootinfo: too many memory chunks\n");
166 break;
167
168 case BI_RAMDISK:
169 m68k_ramdisk.addr = data[0];
170 m68k_ramdisk.size = data[1];
171 break;
172
173 case BI_COMMAND_LINE:
174 strlcpy(m68k_command_line, (const char *)data,
175 sizeof(m68k_command_line));
176 break;
177
178 default:
179 if (MACH_IS_AMIGA)
180 unknown = amiga_parse_bootinfo(record);
181 else if (MACH_IS_ATARI)
182 unknown = atari_parse_bootinfo(record);
183 else if (MACH_IS_MAC)
184 unknown = mac_parse_bootinfo(record);
185 else if (MACH_IS_Q40)
186 unknown = q40_parse_bootinfo(record);
187 else if (MACH_IS_BVME6000)
188 unknown = bvme6000_parse_bootinfo(record);
189 else if (MACH_IS_MVME16x)
190 unknown = mvme16x_parse_bootinfo(record);
191 else if (MACH_IS_MVME147)
192 unknown = mvme147_parse_bootinfo(record);
193 else if (MACH_IS_HP300)
194 unknown = hp300_parse_bootinfo(record);
195 else if (MACH_IS_APOLLO)
196 unknown = apollo_parse_bootinfo(record);
197 else
198 unknown = 1;
199 }
200 if (unknown)
201 printk("m68k_parse_bootinfo: unknown tag 0x%04x ignored\n",
202 record->tag);
203 record = (struct bi_record *)((unsigned long)record +
204 record->size);
205 }
206
207 m68k_realnum_memory = m68k_num_memory;
208#ifdef CONFIG_SINGLE_MEMORY_CHUNK
209 if (m68k_num_memory > 1) {
210 printk("Ignoring last %i chunks of physical memory\n",
211 (m68k_num_memory - 1));
212 m68k_num_memory = 1;
213 }
214#endif
215}
216
217void __init setup_arch(char **cmdline_p)
218{
219 int i;
220
221 /* The bootinfo is located right after the kernel bss */
222 m68k_parse_bootinfo((const struct bi_record *)_end);
223
224 if (CPU_IS_040)
225 m68k_is040or060 = 4;
226 else if (CPU_IS_060)
227 m68k_is040or060 = 6;
228
229 /* FIXME: m68k_fputype is passed in by Penguin booter, which can
230 * be confused by software FPU emulation. BEWARE.
231 * We should really do our own FPU check at startup.
232 * [what do we do with buggy 68LC040s? if we have problems
233 * with them, we should add a test to check_bugs() below] */
234#ifndef CONFIG_M68KFPU_EMU_ONLY
235 /* clear the fpu if we have one */
236 if (m68k_fputype & (FPU_68881|FPU_68882|FPU_68040|FPU_68060)) {
237 volatile int zero = 0;
238 asm volatile ("frestore %0" : : "m" (zero));
239 }
240#endif
241
242 if (CPU_IS_060) {
243 u32 pcr;
244
245 asm (".chip 68060; movec %%pcr,%0; .chip 68k"
246 : "=d" (pcr));
247 if (((pcr >> 8) & 0xff) <= 5) {
248 printk("Enabling workaround for errata I14\n");
249 asm (".chip 68060; movec %0,%%pcr; .chip 68k"
250 : : "d" (pcr | 0x20));
251 }
252 }
253
254 init_mm.start_code = PAGE_OFFSET;
255 init_mm.end_code = (unsigned long)_etext;
256 init_mm.end_data = (unsigned long)_edata;
257 init_mm.brk = (unsigned long)_end;
258
259 *cmdline_p = m68k_command_line;
260 memcpy(boot_command_line, *cmdline_p, CL_SIZE);
261
262 parse_early_param();
263
264#ifdef CONFIG_DUMMY_CONSOLE
265 conswitchp = &dummy_con;
266#endif
267
268 switch (m68k_machtype) {
269#ifdef CONFIG_AMIGA
270 case MACH_AMIGA:
271 config_amiga();
272 break;
273#endif
274#ifdef CONFIG_ATARI
275 case MACH_ATARI:
276 config_atari();
277 break;
278#endif
279#ifdef CONFIG_MAC
280 case MACH_MAC:
281 config_mac();
282 break;
283#endif
284#ifdef CONFIG_SUN3
285 case MACH_SUN3:
286 config_sun3();
287 break;
288#endif
289#ifdef CONFIG_APOLLO
290 case MACH_APOLLO:
291 config_apollo();
292 break;
293#endif
294#ifdef CONFIG_MVME147
295 case MACH_MVME147:
296 config_mvme147();
297 break;
298#endif
299#ifdef CONFIG_MVME16x
300 case MACH_MVME16x:
301 config_mvme16x();
302 break;
303#endif
304#ifdef CONFIG_BVME6000
305 case MACH_BVME6000:
306 config_bvme6000();
307 break;
308#endif
309#ifdef CONFIG_HP300
310 case MACH_HP300:
311 config_hp300();
312 break;
313#endif
314#ifdef CONFIG_Q40
315 case MACH_Q40:
316 config_q40();
317 break;
318#endif
319#ifdef CONFIG_SUN3X
320 case MACH_SUN3X:
321 config_sun3x();
322 break;
323#endif
324 default:
325 panic("No configuration setup");
326 }
327
328#ifdef CONFIG_NATFEAT
329 nf_init();
330#endif
331
332 paging_init();
333
334#ifndef CONFIG_SUN3
335 for (i = 1; i < m68k_num_memory; i++)
336 free_bootmem_node(NODE_DATA(i), m68k_memory[i].addr,
337 m68k_memory[i].size);
338#ifdef CONFIG_BLK_DEV_INITRD
339 if (m68k_ramdisk.size) {
340 reserve_bootmem_node(__virt_to_node(phys_to_virt(m68k_ramdisk.addr)),
341 m68k_ramdisk.addr, m68k_ramdisk.size,
342 BOOTMEM_DEFAULT);
343 initrd_start = (unsigned long)phys_to_virt(m68k_ramdisk.addr);
344 initrd_end = initrd_start + m68k_ramdisk.size;
345 printk("initrd: %08lx - %08lx\n", initrd_start, initrd_end);
346 }
347#endif
348
349#ifdef CONFIG_ATARI
350 if (MACH_IS_ATARI)
351 atari_stram_reserve_pages((void *)availmem);
352#endif
353#ifdef CONFIG_SUN3X
354 if (MACH_IS_SUN3X) {
355 dvma_init();
356 }
357#endif
358
359#endif /* !CONFIG_SUN3 */
360
361/* set ISA defs early as possible */
362#if defined(CONFIG_ISA) && defined(MULTI_ISA)
363 if (MACH_IS_Q40) {
364 isa_type = ISA_TYPE_Q40;
365 isa_sex = 0;
366 }
367#ifdef CONFIG_AMIGA_PCMCIA
368 if (MACH_IS_AMIGA && AMIGAHW_PRESENT(PCMCIA)) {
369 isa_type = ISA_TYPE_AG;
370 isa_sex = 1;
371 }
372#endif
373#endif
374}
375
376static int show_cpuinfo(struct seq_file *m, void *v)
377{
378 const char *cpu, *mmu, *fpu;
379 unsigned long clockfreq, clockfactor;
380
381#define LOOP_CYCLES_68020 (8)
382#define LOOP_CYCLES_68030 (8)
383#define LOOP_CYCLES_68040 (3)
384#define LOOP_CYCLES_68060 (1)
385
386 if (CPU_IS_020) {
387 cpu = "68020";
388 clockfactor = LOOP_CYCLES_68020;
389 } else if (CPU_IS_030) {
390 cpu = "68030";
391 clockfactor = LOOP_CYCLES_68030;
392 } else if (CPU_IS_040) {
393 cpu = "68040";
394 clockfactor = LOOP_CYCLES_68040;
395 } else if (CPU_IS_060) {
396 cpu = "68060";
397 clockfactor = LOOP_CYCLES_68060;
398 } else {
399 cpu = "680x0";
400 clockfactor = 0;
401 }
402
403#ifdef CONFIG_M68KFPU_EMU_ONLY
404 fpu = "none(soft float)";
405#else 3#else
406 if (m68k_fputype & FPU_68881) 4#include "setup_no.c"
407 fpu = "68881";
408 else if (m68k_fputype & FPU_68882)
409 fpu = "68882";
410 else if (m68k_fputype & FPU_68040)
411 fpu = "68040";
412 else if (m68k_fputype & FPU_68060)
413 fpu = "68060";
414 else if (m68k_fputype & FPU_SUNFPA)
415 fpu = "Sun FPA";
416 else
417 fpu = "none";
418#endif
419
420 if (m68k_mmutype & MMU_68851)
421 mmu = "68851";
422 else if (m68k_mmutype & MMU_68030)
423 mmu = "68030";
424 else if (m68k_mmutype & MMU_68040)
425 mmu = "68040";
426 else if (m68k_mmutype & MMU_68060)
427 mmu = "68060";
428 else if (m68k_mmutype & MMU_SUN3)
429 mmu = "Sun-3";
430 else if (m68k_mmutype & MMU_APOLLO)
431 mmu = "Apollo";
432 else
433 mmu = "unknown";
434
435 clockfreq = loops_per_jiffy * HZ * clockfactor;
436
437 seq_printf(m, "CPU:\t\t%s\n"
438 "MMU:\t\t%s\n"
439 "FPU:\t\t%s\n"
440 "Clocking:\t%lu.%1luMHz\n"
441 "BogoMips:\t%lu.%02lu\n"
442 "Calibration:\t%lu loops\n",
443 cpu, mmu, fpu,
444 clockfreq/1000000,(clockfreq/100000)%10,
445 loops_per_jiffy/(500000/HZ),(loops_per_jiffy/(5000/HZ))%100,
446 loops_per_jiffy);
447 return 0;
448}
449
450static void *c_start(struct seq_file *m, loff_t *pos)
451{
452 return *pos < 1 ? (void *)1 : NULL;
453}
454static void *c_next(struct seq_file *m, void *v, loff_t *pos)
455{
456 ++*pos;
457 return NULL;
458}
459static void c_stop(struct seq_file *m, void *v)
460{
461}
462const struct seq_operations cpuinfo_op = {
463 .start = c_start,
464 .next = c_next,
465 .stop = c_stop,
466 .show = show_cpuinfo,
467};
468
469#ifdef CONFIG_PROC_HARDWARE
470static int hardware_proc_show(struct seq_file *m, void *v)
471{
472 char model[80];
473 unsigned long mem;
474 int i;
475
476 if (mach_get_model)
477 mach_get_model(model);
478 else
479 strcpy(model, "Unknown m68k");
480
481 seq_printf(m, "Model:\t\t%s\n", model);
482 for (mem = 0, i = 0; i < m68k_num_memory; i++)
483 mem += m68k_memory[i].size;
484 seq_printf(m, "System Memory:\t%ldK\n", mem >> 10);
485
486 if (mach_get_hardware_list)
487 mach_get_hardware_list(m);
488
489 return 0;
490}
491
492static int hardware_proc_open(struct inode *inode, struct file *file)
493{
494 return single_open(file, hardware_proc_show, NULL);
495}
496
497static const struct file_operations hardware_proc_fops = {
498 .open = hardware_proc_open,
499 .read = seq_read,
500 .llseek = seq_lseek,
501 .release = single_release,
502};
503
504static int __init proc_hardware_init(void)
505{
506 proc_create("hardware", 0, NULL, &hardware_proc_fops);
507 return 0;
508}
509module_init(proc_hardware_init);
510#endif 5#endif
511
512void check_bugs(void)
513{
514#ifndef CONFIG_M68KFPU_EMU
515 if (m68k_fputype == 0) {
516 printk(KERN_EMERG "*** YOU DO NOT HAVE A FLOATING POINT UNIT, "
517 "WHICH IS REQUIRED BY LINUX/M68K ***\n");
518 printk(KERN_EMERG "Upgrade your hardware or join the FPU "
519 "emulation project\n");
520 panic("no FPU");
521 }
522#endif /* !CONFIG_M68KFPU_EMU */
523}
524
525#ifdef CONFIG_ADB
526static int __init adb_probe_sync_enable (char *str) {
527 extern int __adb_probe_sync;
528 __adb_probe_sync = 1;
529 return 1;
530}
531
532__setup("adb_sync", adb_probe_sync_enable);
533#endif /* CONFIG_ADB */
diff --git a/arch/m68k/kernel/setup_mm.c b/arch/m68k/kernel/setup_mm.c
new file mode 100644
index 00000000000..334d8364037
--- /dev/null
+++ b/arch/m68k/kernel/setup_mm.c
@@ -0,0 +1,533 @@
1/*
2 * linux/arch/m68k/kernel/setup.c
3 *
4 * Copyright (C) 1995 Hamish Macdonald
5 */
6
7/*
8 * This file handles the architecture-dependent parts of system setup
9 */
10
11#include <linux/kernel.h>
12#include <linux/mm.h>
13#include <linux/sched.h>
14#include <linux/delay.h>
15#include <linux/interrupt.h>
16#include <linux/fs.h>
17#include <linux/console.h>
18#include <linux/genhd.h>
19#include <linux/errno.h>
20#include <linux/string.h>
21#include <linux/init.h>
22#include <linux/bootmem.h>
23#include <linux/proc_fs.h>
24#include <linux/seq_file.h>
25#include <linux/module.h>
26#include <linux/initrd.h>
27
28#include <asm/bootinfo.h>
29#include <asm/sections.h>
30#include <asm/setup.h>
31#include <asm/fpu.h>
32#include <asm/irq.h>
33#include <asm/io.h>
34#include <asm/machdep.h>
35#ifdef CONFIG_AMIGA
36#include <asm/amigahw.h>
37#endif
38#ifdef CONFIG_ATARI
39#include <asm/atarihw.h>
40#include <asm/atari_stram.h>
41#endif
42#ifdef CONFIG_SUN3X
43#include <asm/dvma.h>
44#endif
45#include <asm/natfeat.h>
46
47#if !FPSTATESIZE || !NR_IRQS
48#warning No CPU/platform type selected, your kernel will not work!
49#warning Are you building an allnoconfig kernel?
50#endif
51
52unsigned long m68k_machtype;
53EXPORT_SYMBOL(m68k_machtype);
54unsigned long m68k_cputype;
55EXPORT_SYMBOL(m68k_cputype);
56unsigned long m68k_fputype;
57unsigned long m68k_mmutype;
58EXPORT_SYMBOL(m68k_mmutype);
59#ifdef CONFIG_VME
60unsigned long vme_brdtype;
61EXPORT_SYMBOL(vme_brdtype);
62#endif
63
64int m68k_is040or060;
65EXPORT_SYMBOL(m68k_is040or060);
66
67extern unsigned long availmem;
68
69int m68k_num_memory;
70EXPORT_SYMBOL(m68k_num_memory);
71int m68k_realnum_memory;
72EXPORT_SYMBOL(m68k_realnum_memory);
73unsigned long m68k_memoffset;
74struct mem_info m68k_memory[NUM_MEMINFO];
75EXPORT_SYMBOL(m68k_memory);
76
77struct mem_info m68k_ramdisk;
78
79static char m68k_command_line[CL_SIZE];
80
81void (*mach_sched_init) (irq_handler_t handler) __initdata = NULL;
82/* machine dependent irq functions */
83void (*mach_init_IRQ) (void) __initdata = NULL;
84void (*mach_get_model) (char *model);
85void (*mach_get_hardware_list) (struct seq_file *m);
86/* machine dependent timer functions */
87unsigned long (*mach_gettimeoffset) (void);
88int (*mach_hwclk) (int, struct rtc_time*);
89EXPORT_SYMBOL(mach_hwclk);
90int (*mach_set_clock_mmss) (unsigned long);
91unsigned int (*mach_get_ss)(void);
92int (*mach_get_rtc_pll)(struct rtc_pll_info *);
93int (*mach_set_rtc_pll)(struct rtc_pll_info *);
94EXPORT_SYMBOL(mach_get_ss);
95EXPORT_SYMBOL(mach_get_rtc_pll);
96EXPORT_SYMBOL(mach_set_rtc_pll);
97void (*mach_reset)( void );
98void (*mach_halt)( void );
99void (*mach_power_off)( void );
100long mach_max_dma_address = 0x00ffffff; /* default set to the lower 16MB */
101#ifdef CONFIG_HEARTBEAT
102void (*mach_heartbeat) (int);
103EXPORT_SYMBOL(mach_heartbeat);
104#endif
105#ifdef CONFIG_M68K_L2_CACHE
106void (*mach_l2_flush) (int);
107#endif
108#if defined(CONFIG_INPUT_M68K_BEEP) || defined(CONFIG_INPUT_M68K_BEEP_MODULE)
109void (*mach_beep)(unsigned int, unsigned int);
110EXPORT_SYMBOL(mach_beep);
111#endif
112#if defined(CONFIG_ISA) && defined(MULTI_ISA)
113int isa_type;
114int isa_sex;
115EXPORT_SYMBOL(isa_type);
116EXPORT_SYMBOL(isa_sex);
117#endif
118
119extern int amiga_parse_bootinfo(const struct bi_record *);
120extern int atari_parse_bootinfo(const struct bi_record *);
121extern int mac_parse_bootinfo(const struct bi_record *);
122extern int q40_parse_bootinfo(const struct bi_record *);
123extern int bvme6000_parse_bootinfo(const struct bi_record *);
124extern int mvme16x_parse_bootinfo(const struct bi_record *);
125extern int mvme147_parse_bootinfo(const struct bi_record *);
126extern int hp300_parse_bootinfo(const struct bi_record *);
127extern int apollo_parse_bootinfo(const struct bi_record *);
128
129extern void config_amiga(void);
130extern void config_atari(void);
131extern void config_mac(void);
132extern void config_sun3(void);
133extern void config_apollo(void);
134extern void config_mvme147(void);
135extern void config_mvme16x(void);
136extern void config_bvme6000(void);
137extern void config_hp300(void);
138extern void config_q40(void);
139extern void config_sun3x(void);
140
141#define MASK_256K 0xfffc0000
142
143extern void paging_init(void);
144
145static void __init m68k_parse_bootinfo(const struct bi_record *record)
146{
147 while (record->tag != BI_LAST) {
148 int unknown = 0;
149 const unsigned long *data = record->data;
150
151 switch (record->tag) {
152 case BI_MACHTYPE:
153 case BI_CPUTYPE:
154 case BI_FPUTYPE:
155 case BI_MMUTYPE:
156 /* Already set up by head.S */
157 break;
158
159 case BI_MEMCHUNK:
160 if (m68k_num_memory < NUM_MEMINFO) {
161 m68k_memory[m68k_num_memory].addr = data[0];
162 m68k_memory[m68k_num_memory].size = data[1];
163 m68k_num_memory++;
164 } else
165 printk("m68k_parse_bootinfo: too many memory chunks\n");
166 break;
167
168 case BI_RAMDISK:
169 m68k_ramdisk.addr = data[0];
170 m68k_ramdisk.size = data[1];
171 break;
172
173 case BI_COMMAND_LINE:
174 strlcpy(m68k_command_line, (const char *)data,
175 sizeof(m68k_command_line));
176 break;
177
178 default:
179 if (MACH_IS_AMIGA)
180 unknown = amiga_parse_bootinfo(record);
181 else if (MACH_IS_ATARI)
182 unknown = atari_parse_bootinfo(record);
183 else if (MACH_IS_MAC)
184 unknown = mac_parse_bootinfo(record);
185 else if (MACH_IS_Q40)
186 unknown = q40_parse_bootinfo(record);
187 else if (MACH_IS_BVME6000)
188 unknown = bvme6000_parse_bootinfo(record);
189 else if (MACH_IS_MVME16x)
190 unknown = mvme16x_parse_bootinfo(record);
191 else if (MACH_IS_MVME147)
192 unknown = mvme147_parse_bootinfo(record);
193 else if (MACH_IS_HP300)
194 unknown = hp300_parse_bootinfo(record);
195 else if (MACH_IS_APOLLO)
196 unknown = apollo_parse_bootinfo(record);
197 else
198 unknown = 1;
199 }
200 if (unknown)
201 printk("m68k_parse_bootinfo: unknown tag 0x%04x ignored\n",
202 record->tag);
203 record = (struct bi_record *)((unsigned long)record +
204 record->size);
205 }
206
207 m68k_realnum_memory = m68k_num_memory;
208#ifdef CONFIG_SINGLE_MEMORY_CHUNK
209 if (m68k_num_memory > 1) {
210 printk("Ignoring last %i chunks of physical memory\n",
211 (m68k_num_memory - 1));
212 m68k_num_memory = 1;
213 }
214#endif
215}
216
217void __init setup_arch(char **cmdline_p)
218{
219 int i;
220
221 /* The bootinfo is located right after the kernel bss */
222 m68k_parse_bootinfo((const struct bi_record *)_end);
223
224 if (CPU_IS_040)
225 m68k_is040or060 = 4;
226 else if (CPU_IS_060)
227 m68k_is040or060 = 6;
228
229 /* FIXME: m68k_fputype is passed in by Penguin booter, which can
230 * be confused by software FPU emulation. BEWARE.
231 * We should really do our own FPU check at startup.
232 * [what do we do with buggy 68LC040s? if we have problems
233 * with them, we should add a test to check_bugs() below] */
234#ifndef CONFIG_M68KFPU_EMU_ONLY
235 /* clear the fpu if we have one */
236 if (m68k_fputype & (FPU_68881|FPU_68882|FPU_68040|FPU_68060)) {
237 volatile int zero = 0;
238 asm volatile ("frestore %0" : : "m" (zero));
239 }
240#endif
241
242 if (CPU_IS_060) {
243 u32 pcr;
244
245 asm (".chip 68060; movec %%pcr,%0; .chip 68k"
246 : "=d" (pcr));
247 if (((pcr >> 8) & 0xff) <= 5) {
248 printk("Enabling workaround for errata I14\n");
249 asm (".chip 68060; movec %0,%%pcr; .chip 68k"
250 : : "d" (pcr | 0x20));
251 }
252 }
253
254 init_mm.start_code = PAGE_OFFSET;
255 init_mm.end_code = (unsigned long)_etext;
256 init_mm.end_data = (unsigned long)_edata;
257 init_mm.brk = (unsigned long)_end;
258
259 *cmdline_p = m68k_command_line;
260 memcpy(boot_command_line, *cmdline_p, CL_SIZE);
261
262 parse_early_param();
263
264#ifdef CONFIG_DUMMY_CONSOLE
265 conswitchp = &dummy_con;
266#endif
267
268 switch (m68k_machtype) {
269#ifdef CONFIG_AMIGA
270 case MACH_AMIGA:
271 config_amiga();
272 break;
273#endif
274#ifdef CONFIG_ATARI
275 case MACH_ATARI:
276 config_atari();
277 break;
278#endif
279#ifdef CONFIG_MAC
280 case MACH_MAC:
281 config_mac();
282 break;
283#endif
284#ifdef CONFIG_SUN3
285 case MACH_SUN3:
286 config_sun3();
287 break;
288#endif
289#ifdef CONFIG_APOLLO
290 case MACH_APOLLO:
291 config_apollo();
292 break;
293#endif
294#ifdef CONFIG_MVME147
295 case MACH_MVME147:
296 config_mvme147();
297 break;
298#endif
299#ifdef CONFIG_MVME16x
300 case MACH_MVME16x:
301 config_mvme16x();
302 break;
303#endif
304#ifdef CONFIG_BVME6000
305 case MACH_BVME6000:
306 config_bvme6000();
307 break;
308#endif
309#ifdef CONFIG_HP300
310 case MACH_HP300:
311 config_hp300();
312 break;
313#endif
314#ifdef CONFIG_Q40
315 case MACH_Q40:
316 config_q40();
317 break;
318#endif
319#ifdef CONFIG_SUN3X
320 case MACH_SUN3X:
321 config_sun3x();
322 break;
323#endif
324 default:
325 panic("No configuration setup");
326 }
327
328#ifdef CONFIG_NATFEAT
329 nf_init();
330#endif
331
332 paging_init();
333
334#ifndef CONFIG_SUN3
335 for (i = 1; i < m68k_num_memory; i++)
336 free_bootmem_node(NODE_DATA(i), m68k_memory[i].addr,
337 m68k_memory[i].size);
338#ifdef CONFIG_BLK_DEV_INITRD
339 if (m68k_ramdisk.size) {
340 reserve_bootmem_node(__virt_to_node(phys_to_virt(m68k_ramdisk.addr)),
341 m68k_ramdisk.addr, m68k_ramdisk.size,
342 BOOTMEM_DEFAULT);
343 initrd_start = (unsigned long)phys_to_virt(m68k_ramdisk.addr);
344 initrd_end = initrd_start + m68k_ramdisk.size;
345 printk("initrd: %08lx - %08lx\n", initrd_start, initrd_end);
346 }
347#endif
348
349#ifdef CONFIG_ATARI
350 if (MACH_IS_ATARI)
351 atari_stram_reserve_pages((void *)availmem);
352#endif
353#ifdef CONFIG_SUN3X
354 if (MACH_IS_SUN3X) {
355 dvma_init();
356 }
357#endif
358
359#endif /* !CONFIG_SUN3 */
360
361/* set ISA defs early as possible */
362#if defined(CONFIG_ISA) && defined(MULTI_ISA)
363 if (MACH_IS_Q40) {
364 isa_type = ISA_TYPE_Q40;
365 isa_sex = 0;
366 }
367#ifdef CONFIG_AMIGA_PCMCIA
368 if (MACH_IS_AMIGA && AMIGAHW_PRESENT(PCMCIA)) {
369 isa_type = ISA_TYPE_AG;
370 isa_sex = 1;
371 }
372#endif
373#endif
374}
375
376static int show_cpuinfo(struct seq_file *m, void *v)
377{
378 const char *cpu, *mmu, *fpu;
379 unsigned long clockfreq, clockfactor;
380
381#define LOOP_CYCLES_68020 (8)
382#define LOOP_CYCLES_68030 (8)
383#define LOOP_CYCLES_68040 (3)
384#define LOOP_CYCLES_68060 (1)
385
386 if (CPU_IS_020) {
387 cpu = "68020";
388 clockfactor = LOOP_CYCLES_68020;
389 } else if (CPU_IS_030) {
390 cpu = "68030";
391 clockfactor = LOOP_CYCLES_68030;
392 } else if (CPU_IS_040) {
393 cpu = "68040";
394 clockfactor = LOOP_CYCLES_68040;
395 } else if (CPU_IS_060) {
396 cpu = "68060";
397 clockfactor = LOOP_CYCLES_68060;
398 } else {
399 cpu = "680x0";
400 clockfactor = 0;
401 }
402
403#ifdef CONFIG_M68KFPU_EMU_ONLY
404 fpu = "none(soft float)";
405#else
406 if (m68k_fputype & FPU_68881)
407 fpu = "68881";
408 else if (m68k_fputype & FPU_68882)
409 fpu = "68882";
410 else if (m68k_fputype & FPU_68040)
411 fpu = "68040";
412 else if (m68k_fputype & FPU_68060)
413 fpu = "68060";
414 else if (m68k_fputype & FPU_SUNFPA)
415 fpu = "Sun FPA";
416 else
417 fpu = "none";
418#endif
419
420 if (m68k_mmutype & MMU_68851)
421 mmu = "68851";
422 else if (m68k_mmutype & MMU_68030)
423 mmu = "68030";
424 else if (m68k_mmutype & MMU_68040)
425 mmu = "68040";
426 else if (m68k_mmutype & MMU_68060)
427 mmu = "68060";
428 else if (m68k_mmutype & MMU_SUN3)
429 mmu = "Sun-3";
430 else if (m68k_mmutype & MMU_APOLLO)
431 mmu = "Apollo";
432 else
433 mmu = "unknown";
434
435 clockfreq = loops_per_jiffy * HZ * clockfactor;
436
437 seq_printf(m, "CPU:\t\t%s\n"
438 "MMU:\t\t%s\n"
439 "FPU:\t\t%s\n"
440 "Clocking:\t%lu.%1luMHz\n"
441 "BogoMips:\t%lu.%02lu\n"
442 "Calibration:\t%lu loops\n",
443 cpu, mmu, fpu,
444 clockfreq/1000000,(clockfreq/100000)%10,
445 loops_per_jiffy/(500000/HZ),(loops_per_jiffy/(5000/HZ))%100,
446 loops_per_jiffy);
447 return 0;
448}
449
450static void *c_start(struct seq_file *m, loff_t *pos)
451{
452 return *pos < 1 ? (void *)1 : NULL;
453}
454static void *c_next(struct seq_file *m, void *v, loff_t *pos)
455{
456 ++*pos;
457 return NULL;
458}
459static void c_stop(struct seq_file *m, void *v)
460{
461}
462const struct seq_operations cpuinfo_op = {
463 .start = c_start,
464 .next = c_next,
465 .stop = c_stop,
466 .show = show_cpuinfo,
467};
468
469#ifdef CONFIG_PROC_HARDWARE
470static int hardware_proc_show(struct seq_file *m, void *v)
471{
472 char model[80];
473 unsigned long mem;
474 int i;
475
476 if (mach_get_model)
477 mach_get_model(model);
478 else
479 strcpy(model, "Unknown m68k");
480
481 seq_printf(m, "Model:\t\t%s\n", model);
482 for (mem = 0, i = 0; i < m68k_num_memory; i++)
483 mem += m68k_memory[i].size;
484 seq_printf(m, "System Memory:\t%ldK\n", mem >> 10);
485
486 if (mach_get_hardware_list)
487 mach_get_hardware_list(m);
488
489 return 0;
490}
491
492static int hardware_proc_open(struct inode *inode, struct file *file)
493{
494 return single_open(file, hardware_proc_show, NULL);
495}
496
497static const struct file_operations hardware_proc_fops = {
498 .open = hardware_proc_open,
499 .read = seq_read,
500 .llseek = seq_lseek,
501 .release = single_release,
502};
503
504static int __init proc_hardware_init(void)
505{
506 proc_create("hardware", 0, NULL, &hardware_proc_fops);
507 return 0;
508}
509module_init(proc_hardware_init);
510#endif
511
512void check_bugs(void)
513{
514#ifndef CONFIG_M68KFPU_EMU
515 if (m68k_fputype == 0) {
516 printk(KERN_EMERG "*** YOU DO NOT HAVE A FLOATING POINT UNIT, "
517 "WHICH IS REQUIRED BY LINUX/M68K ***\n");
518 printk(KERN_EMERG "Upgrade your hardware or join the FPU "
519 "emulation project\n");
520 panic("no FPU");
521 }
522#endif /* !CONFIG_M68KFPU_EMU */
523}
524
525#ifdef CONFIG_ADB
526static int __init adb_probe_sync_enable (char *str) {
527 extern int __adb_probe_sync;
528 __adb_probe_sync = 1;
529 return 1;
530}
531
532__setup("adb_sync", adb_probe_sync_enable);
533#endif /* CONFIG_ADB */
diff --git a/arch/m68knommu/kernel/setup.c b/arch/m68k/kernel/setup_no.c
index 16b2de7f510..16b2de7f510 100644
--- a/arch/m68knommu/kernel/setup.c
+++ b/arch/m68k/kernel/setup_no.c
diff --git a/arch/m68k/kernel/signal.c b/arch/m68k/kernel/signal.c
index a0afc239304..2e25713e2ea 100644
--- a/arch/m68k/kernel/signal.c
+++ b/arch/m68k/kernel/signal.c
@@ -1,1017 +1,5 @@
1/* 1#ifdef CONFIG_MMU
2 * linux/arch/m68k/kernel/signal.c 2#include "signal_mm.c"
3 *
4 * Copyright (C) 1991, 1992 Linus Torvalds
5 *
6 * This file is subject to the terms and conditions of the GNU General Public
7 * License. See the file COPYING in the main directory of this archive
8 * for more details.
9 */
10
11/*
12 * Linux/m68k support by Hamish Macdonald
13 *
14 * 68060 fixes by Jesper Skov
15 *
16 * 1997-12-01 Modified for POSIX.1b signals by Andreas Schwab
17 *
18 * mathemu support by Roman Zippel
19 * (Note: fpstate in the signal context is completely ignored for the emulator
20 * and the internal floating point format is put on stack)
21 */
22
23/*
24 * ++roman (07/09/96): implemented signal stacks (specially for tosemu on
25 * Atari :-) Current limitation: Only one sigstack can be active at one time.
26 * If a second signal with SA_ONSTACK set arrives while working on a sigstack,
27 * SA_ONSTACK is ignored. This behaviour avoids lots of trouble with nested
28 * signal handlers!
29 */
30
31#include <linux/sched.h>
32#include <linux/mm.h>
33#include <linux/kernel.h>
34#include <linux/signal.h>
35#include <linux/syscalls.h>
36#include <linux/errno.h>
37#include <linux/wait.h>
38#include <linux/ptrace.h>
39#include <linux/unistd.h>
40#include <linux/stddef.h>
41#include <linux/highuid.h>
42#include <linux/personality.h>
43#include <linux/tty.h>
44#include <linux/binfmts.h>
45#include <linux/module.h>
46
47#include <asm/setup.h>
48#include <asm/uaccess.h>
49#include <asm/pgtable.h>
50#include <asm/traps.h>
51#include <asm/ucontext.h>
52
53#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
54
55static const int frame_extra_sizes[16] = {
56 [1] = -1, /* sizeof(((struct frame *)0)->un.fmt1), */
57 [2] = sizeof(((struct frame *)0)->un.fmt2),
58 [3] = sizeof(((struct frame *)0)->un.fmt3),
59 [4] = sizeof(((struct frame *)0)->un.fmt4),
60 [5] = -1, /* sizeof(((struct frame *)0)->un.fmt5), */
61 [6] = -1, /* sizeof(((struct frame *)0)->un.fmt6), */
62 [7] = sizeof(((struct frame *)0)->un.fmt7),
63 [8] = -1, /* sizeof(((struct frame *)0)->un.fmt8), */
64 [9] = sizeof(((struct frame *)0)->un.fmt9),
65 [10] = sizeof(((struct frame *)0)->un.fmta),
66 [11] = sizeof(((struct frame *)0)->un.fmtb),
67 [12] = -1, /* sizeof(((struct frame *)0)->un.fmtc), */
68 [13] = -1, /* sizeof(((struct frame *)0)->un.fmtd), */
69 [14] = -1, /* sizeof(((struct frame *)0)->un.fmte), */
70 [15] = -1, /* sizeof(((struct frame *)0)->un.fmtf), */
71};
72
73int handle_kernel_fault(struct pt_regs *regs)
74{
75 const struct exception_table_entry *fixup;
76 struct pt_regs *tregs;
77
78 /* Are we prepared to handle this kernel fault? */
79 fixup = search_exception_tables(regs->pc);
80 if (!fixup)
81 return 0;
82
83 /* Create a new four word stack frame, discarding the old one. */
84 regs->stkadj = frame_extra_sizes[regs->format];
85 tregs = (struct pt_regs *)((long)regs + regs->stkadj);
86 tregs->vector = regs->vector;
87 tregs->format = 0;
88 tregs->pc = fixup->fixup;
89 tregs->sr = regs->sr;
90
91 return 1;
92}
93
94/*
95 * Atomically swap in the new signal mask, and wait for a signal.
96 */
97asmlinkage int
98sys_sigsuspend(int unused0, int unused1, old_sigset_t mask)
99{
100 mask &= _BLOCKABLE;
101 spin_lock_irq(&current->sighand->siglock);
102 current->saved_sigmask = current->blocked;
103 siginitset(&current->blocked, mask);
104 recalc_sigpending();
105 spin_unlock_irq(&current->sighand->siglock);
106
107 current->state = TASK_INTERRUPTIBLE;
108 schedule();
109 set_restore_sigmask();
110
111 return -ERESTARTNOHAND;
112}
113
114asmlinkage int
115sys_sigaction(int sig, const struct old_sigaction __user *act,
116 struct old_sigaction __user *oact)
117{
118 struct k_sigaction new_ka, old_ka;
119 int ret;
120
121 if (act) {
122 old_sigset_t mask;
123 if (!access_ok(VERIFY_READ, act, sizeof(*act)) ||
124 __get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
125 __get_user(new_ka.sa.sa_restorer, &act->sa_restorer) ||
126 __get_user(new_ka.sa.sa_flags, &act->sa_flags) ||
127 __get_user(mask, &act->sa_mask))
128 return -EFAULT;
129 siginitset(&new_ka.sa.sa_mask, mask);
130 }
131
132 ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
133
134 if (!ret && oact) {
135 if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) ||
136 __put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
137 __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer) ||
138 __put_user(old_ka.sa.sa_flags, &oact->sa_flags) ||
139 __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask))
140 return -EFAULT;
141 }
142
143 return ret;
144}
145
146asmlinkage int
147sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss)
148{
149 return do_sigaltstack(uss, uoss, rdusp());
150}
151
152
153/*
154 * Do a signal return; undo the signal stack.
155 *
156 * Keep the return code on the stack quadword aligned!
157 * That makes the cache flush below easier.
158 */
159
160struct sigframe
161{
162 char __user *pretcode;
163 int sig;
164 int code;
165 struct sigcontext __user *psc;
166 char retcode[8];
167 unsigned long extramask[_NSIG_WORDS-1];
168 struct sigcontext sc;
169};
170
171struct rt_sigframe
172{
173 char __user *pretcode;
174 int sig;
175 struct siginfo __user *pinfo;
176 void __user *puc;
177 char retcode[8];
178 struct siginfo info;
179 struct ucontext uc;
180};
181
182
183static unsigned char fpu_version; /* version number of fpu, set by setup_frame */
184
185static inline int restore_fpu_state(struct sigcontext *sc)
186{
187 int err = 1;
188
189 if (FPU_IS_EMU) {
190 /* restore registers */
191 memcpy(current->thread.fpcntl, sc->sc_fpcntl, 12);
192 memcpy(current->thread.fp, sc->sc_fpregs, 24);
193 return 0;
194 }
195
196 if (CPU_IS_060 ? sc->sc_fpstate[2] : sc->sc_fpstate[0]) {
197 /* Verify the frame format. */
198 if (!CPU_IS_060 && (sc->sc_fpstate[0] != fpu_version))
199 goto out;
200 if (CPU_IS_020_OR_030) {
201 if (m68k_fputype & FPU_68881 &&
202 !(sc->sc_fpstate[1] == 0x18 || sc->sc_fpstate[1] == 0xb4))
203 goto out;
204 if (m68k_fputype & FPU_68882 &&
205 !(sc->sc_fpstate[1] == 0x38 || sc->sc_fpstate[1] == 0xd4))
206 goto out;
207 } else if (CPU_IS_040) {
208 if (!(sc->sc_fpstate[1] == 0x00 ||
209 sc->sc_fpstate[1] == 0x28 ||
210 sc->sc_fpstate[1] == 0x60))
211 goto out;
212 } else if (CPU_IS_060) {
213 if (!(sc->sc_fpstate[3] == 0x00 ||
214 sc->sc_fpstate[3] == 0x60 ||
215 sc->sc_fpstate[3] == 0xe0))
216 goto out;
217 } else
218 goto out;
219
220 __asm__ volatile (".chip 68k/68881\n\t"
221 "fmovemx %0,%%fp0-%%fp1\n\t"
222 "fmoveml %1,%%fpcr/%%fpsr/%%fpiar\n\t"
223 ".chip 68k"
224 : /* no outputs */
225 : "m" (*sc->sc_fpregs), "m" (*sc->sc_fpcntl));
226 }
227 __asm__ volatile (".chip 68k/68881\n\t"
228 "frestore %0\n\t"
229 ".chip 68k" : : "m" (*sc->sc_fpstate));
230 err = 0;
231
232out:
233 return err;
234}
235
236#define FPCONTEXT_SIZE 216
237#define uc_fpstate uc_filler[0]
238#define uc_formatvec uc_filler[FPCONTEXT_SIZE/4]
239#define uc_extra uc_filler[FPCONTEXT_SIZE/4+1]
240
241static inline int rt_restore_fpu_state(struct ucontext __user *uc)
242{
243 unsigned char fpstate[FPCONTEXT_SIZE];
244 int context_size = CPU_IS_060 ? 8 : 0;
245 fpregset_t fpregs;
246 int err = 1;
247
248 if (FPU_IS_EMU) {
249 /* restore fpu control register */
250 if (__copy_from_user(current->thread.fpcntl,
251 uc->uc_mcontext.fpregs.f_fpcntl, 12))
252 goto out;
253 /* restore all other fpu register */
254 if (__copy_from_user(current->thread.fp,
255 uc->uc_mcontext.fpregs.f_fpregs, 96))
256 goto out;
257 return 0;
258 }
259
260 if (__get_user(*(long *)fpstate, (long __user *)&uc->uc_fpstate))
261 goto out;
262 if (CPU_IS_060 ? fpstate[2] : fpstate[0]) {
263 if (!CPU_IS_060)
264 context_size = fpstate[1];
265 /* Verify the frame format. */
266 if (!CPU_IS_060 && (fpstate[0] != fpu_version))
267 goto out;
268 if (CPU_IS_020_OR_030) {
269 if (m68k_fputype & FPU_68881 &&
270 !(context_size == 0x18 || context_size == 0xb4))
271 goto out;
272 if (m68k_fputype & FPU_68882 &&
273 !(context_size == 0x38 || context_size == 0xd4))
274 goto out;
275 } else if (CPU_IS_040) {
276 if (!(context_size == 0x00 ||
277 context_size == 0x28 ||
278 context_size == 0x60))
279 goto out;
280 } else if (CPU_IS_060) {
281 if (!(fpstate[3] == 0x00 ||
282 fpstate[3] == 0x60 ||
283 fpstate[3] == 0xe0))
284 goto out;
285 } else
286 goto out;
287 if (__copy_from_user(&fpregs, &uc->uc_mcontext.fpregs,
288 sizeof(fpregs)))
289 goto out;
290 __asm__ volatile (".chip 68k/68881\n\t"
291 "fmovemx %0,%%fp0-%%fp7\n\t"
292 "fmoveml %1,%%fpcr/%%fpsr/%%fpiar\n\t"
293 ".chip 68k"
294 : /* no outputs */
295 : "m" (*fpregs.f_fpregs),
296 "m" (*fpregs.f_fpcntl));
297 }
298 if (context_size &&
299 __copy_from_user(fpstate + 4, (long __user *)&uc->uc_fpstate + 1,
300 context_size))
301 goto out;
302 __asm__ volatile (".chip 68k/68881\n\t"
303 "frestore %0\n\t"
304 ".chip 68k" : : "m" (*fpstate));
305 err = 0;
306
307out:
308 return err;
309}
310
311static int mangle_kernel_stack(struct pt_regs *regs, int formatvec,
312 void __user *fp)
313{
314 int fsize = frame_extra_sizes[formatvec >> 12];
315 if (fsize < 0) {
316 /*
317 * user process trying to return with weird frame format
318 */
319#ifdef DEBUG
320 printk("user process returning with weird frame format\n");
321#endif
322 return 1;
323 }
324 if (!fsize) {
325 regs->format = formatvec >> 12;
326 regs->vector = formatvec & 0xfff;
327 } else {
328 struct switch_stack *sw = (struct switch_stack *)regs - 1;
329 unsigned long buf[fsize / 2]; /* yes, twice as much */
330
331 /* that'll make sure that expansion won't crap over data */
332 if (copy_from_user(buf + fsize / 4, fp, fsize))
333 return 1;
334
335 /* point of no return */
336 regs->format = formatvec >> 12;
337 regs->vector = formatvec & 0xfff;
338#define frame_offset (sizeof(struct pt_regs)+sizeof(struct switch_stack))
339 __asm__ __volatile__
340 (" movel %0,%/a0\n\t"
341 " subl %1,%/a0\n\t" /* make room on stack */
342 " movel %/a0,%/sp\n\t" /* set stack pointer */
343 /* move switch_stack and pt_regs */
344 "1: movel %0@+,%/a0@+\n\t"
345 " dbra %2,1b\n\t"
346 " lea %/sp@(%c3),%/a0\n\t" /* add offset of fmt */
347 " lsrl #2,%1\n\t"
348 " subql #1,%1\n\t"
349 /* copy to the gap we'd made */
350 "2: movel %4@+,%/a0@+\n\t"
351 " dbra %1,2b\n\t"
352 " bral ret_from_signal\n"
353 : /* no outputs, it doesn't ever return */
354 : "a" (sw), "d" (fsize), "d" (frame_offset/4-1),
355 "n" (frame_offset), "a" (buf + fsize/4)
356 : "a0");
357#undef frame_offset
358 }
359 return 0;
360}
361
362static inline int
363restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *usc, void __user *fp)
364{
365 int formatvec;
366 struct sigcontext context;
367 int err;
368
369 /* Always make any pending restarted system calls return -EINTR */
370 current_thread_info()->restart_block.fn = do_no_restart_syscall;
371
372 /* get previous context */
373 if (copy_from_user(&context, usc, sizeof(context)))
374 goto badframe;
375
376 /* restore passed registers */
377 regs->d0 = context.sc_d0;
378 regs->d1 = context.sc_d1;
379 regs->a0 = context.sc_a0;
380 regs->a1 = context.sc_a1;
381 regs->sr = (regs->sr & 0xff00) | (context.sc_sr & 0xff);
382 regs->pc = context.sc_pc;
383 regs->orig_d0 = -1; /* disable syscall checks */
384 wrusp(context.sc_usp);
385 formatvec = context.sc_formatvec;
386
387 err = restore_fpu_state(&context);
388
389 if (err || mangle_kernel_stack(regs, formatvec, fp))
390 goto badframe;
391
392 return 0;
393
394badframe:
395 return 1;
396}
397
398static inline int
399rt_restore_ucontext(struct pt_regs *regs, struct switch_stack *sw,
400 struct ucontext __user *uc)
401{
402 int temp;
403 greg_t __user *gregs = uc->uc_mcontext.gregs;
404 unsigned long usp;
405 int err;
406
407 /* Always make any pending restarted system calls return -EINTR */
408 current_thread_info()->restart_block.fn = do_no_restart_syscall;
409
410 err = __get_user(temp, &uc->uc_mcontext.version);
411 if (temp != MCONTEXT_VERSION)
412 goto badframe;
413 /* restore passed registers */
414 err |= __get_user(regs->d0, &gregs[0]);
415 err |= __get_user(regs->d1, &gregs[1]);
416 err |= __get_user(regs->d2, &gregs[2]);
417 err |= __get_user(regs->d3, &gregs[3]);
418 err |= __get_user(regs->d4, &gregs[4]);
419 err |= __get_user(regs->d5, &gregs[5]);
420 err |= __get_user(sw->d6, &gregs[6]);
421 err |= __get_user(sw->d7, &gregs[7]);
422 err |= __get_user(regs->a0, &gregs[8]);
423 err |= __get_user(regs->a1, &gregs[9]);
424 err |= __get_user(regs->a2, &gregs[10]);
425 err |= __get_user(sw->a3, &gregs[11]);
426 err |= __get_user(sw->a4, &gregs[12]);
427 err |= __get_user(sw->a5, &gregs[13]);
428 err |= __get_user(sw->a6, &gregs[14]);
429 err |= __get_user(usp, &gregs[15]);
430 wrusp(usp);
431 err |= __get_user(regs->pc, &gregs[16]);
432 err |= __get_user(temp, &gregs[17]);
433 regs->sr = (regs->sr & 0xff00) | (temp & 0xff);
434 regs->orig_d0 = -1; /* disable syscall checks */
435 err |= __get_user(temp, &uc->uc_formatvec);
436
437 err |= rt_restore_fpu_state(uc);
438
439 if (err || do_sigaltstack(&uc->uc_stack, NULL, usp) == -EFAULT)
440 goto badframe;
441
442 if (mangle_kernel_stack(regs, temp, &uc->uc_extra))
443 goto badframe;
444
445 return 0;
446
447badframe:
448 return 1;
449}
450
451asmlinkage int do_sigreturn(unsigned long __unused)
452{
453 struct switch_stack *sw = (struct switch_stack *) &__unused;
454 struct pt_regs *regs = (struct pt_regs *) (sw + 1);
455 unsigned long usp = rdusp();
456 struct sigframe __user *frame = (struct sigframe __user *)(usp - 4);
457 sigset_t set;
458
459 if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
460 goto badframe;
461 if (__get_user(set.sig[0], &frame->sc.sc_mask) ||
462 (_NSIG_WORDS > 1 &&
463 __copy_from_user(&set.sig[1], &frame->extramask,
464 sizeof(frame->extramask))))
465 goto badframe;
466
467 sigdelsetmask(&set, ~_BLOCKABLE);
468 current->blocked = set;
469 recalc_sigpending();
470
471 if (restore_sigcontext(regs, &frame->sc, frame + 1))
472 goto badframe;
473 return regs->d0;
474
475badframe:
476 force_sig(SIGSEGV, current);
477 return 0;
478}
479
480asmlinkage int do_rt_sigreturn(unsigned long __unused)
481{
482 struct switch_stack *sw = (struct switch_stack *) &__unused;
483 struct pt_regs *regs = (struct pt_regs *) (sw + 1);
484 unsigned long usp = rdusp();
485 struct rt_sigframe __user *frame = (struct rt_sigframe __user *)(usp - 4);
486 sigset_t set;
487
488 if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
489 goto badframe;
490 if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
491 goto badframe;
492
493 sigdelsetmask(&set, ~_BLOCKABLE);
494 current->blocked = set;
495 recalc_sigpending();
496
497 if (rt_restore_ucontext(regs, sw, &frame->uc))
498 goto badframe;
499 return regs->d0;
500
501badframe:
502 force_sig(SIGSEGV, current);
503 return 0;
504}
505
506/*
507 * Set up a signal frame.
508 */
509
510static inline void save_fpu_state(struct sigcontext *sc, struct pt_regs *regs)
511{
512 if (FPU_IS_EMU) {
513 /* save registers */
514 memcpy(sc->sc_fpcntl, current->thread.fpcntl, 12);
515 memcpy(sc->sc_fpregs, current->thread.fp, 24);
516 return;
517 }
518
519 __asm__ volatile (".chip 68k/68881\n\t"
520 "fsave %0\n\t"
521 ".chip 68k"
522 : : "m" (*sc->sc_fpstate) : "memory");
523
524 if (CPU_IS_060 ? sc->sc_fpstate[2] : sc->sc_fpstate[0]) {
525 fpu_version = sc->sc_fpstate[0];
526 if (CPU_IS_020_OR_030 &&
527 regs->vector >= (VEC_FPBRUC * 4) &&
528 regs->vector <= (VEC_FPNAN * 4)) {
529 /* Clear pending exception in 68882 idle frame */
530 if (*(unsigned short *) sc->sc_fpstate == 0x1f38)
531 sc->sc_fpstate[0x38] |= 1 << 3;
532 }
533 __asm__ volatile (".chip 68k/68881\n\t"
534 "fmovemx %%fp0-%%fp1,%0\n\t"
535 "fmoveml %%fpcr/%%fpsr/%%fpiar,%1\n\t"
536 ".chip 68k"
537 : "=m" (*sc->sc_fpregs),
538 "=m" (*sc->sc_fpcntl)
539 : /* no inputs */
540 : "memory");
541 }
542}
543
544static inline int rt_save_fpu_state(struct ucontext __user *uc, struct pt_regs *regs)
545{
546 unsigned char fpstate[FPCONTEXT_SIZE];
547 int context_size = CPU_IS_060 ? 8 : 0;
548 int err = 0;
549
550 if (FPU_IS_EMU) {
551 /* save fpu control register */
552 err |= copy_to_user(uc->uc_mcontext.fpregs.f_fpcntl,
553 current->thread.fpcntl, 12);
554 /* save all other fpu register */
555 err |= copy_to_user(uc->uc_mcontext.fpregs.f_fpregs,
556 current->thread.fp, 96);
557 return err;
558 }
559
560 __asm__ volatile (".chip 68k/68881\n\t"
561 "fsave %0\n\t"
562 ".chip 68k"
563 : : "m" (*fpstate) : "memory");
564
565 err |= __put_user(*(long *)fpstate, (long __user *)&uc->uc_fpstate);
566 if (CPU_IS_060 ? fpstate[2] : fpstate[0]) {
567 fpregset_t fpregs;
568 if (!CPU_IS_060)
569 context_size = fpstate[1];
570 fpu_version = fpstate[0];
571 if (CPU_IS_020_OR_030 &&
572 regs->vector >= (VEC_FPBRUC * 4) &&
573 regs->vector <= (VEC_FPNAN * 4)) {
574 /* Clear pending exception in 68882 idle frame */
575 if (*(unsigned short *) fpstate == 0x1f38)
576 fpstate[0x38] |= 1 << 3;
577 }
578 __asm__ volatile (".chip 68k/68881\n\t"
579 "fmovemx %%fp0-%%fp7,%0\n\t"
580 "fmoveml %%fpcr/%%fpsr/%%fpiar,%1\n\t"
581 ".chip 68k"
582 : "=m" (*fpregs.f_fpregs),
583 "=m" (*fpregs.f_fpcntl)
584 : /* no inputs */
585 : "memory");
586 err |= copy_to_user(&uc->uc_mcontext.fpregs, &fpregs,
587 sizeof(fpregs));
588 }
589 if (context_size)
590 err |= copy_to_user((long __user *)&uc->uc_fpstate + 1, fpstate + 4,
591 context_size);
592 return err;
593}
594
595static void setup_sigcontext(struct sigcontext *sc, struct pt_regs *regs,
596 unsigned long mask)
597{
598 sc->sc_mask = mask;
599 sc->sc_usp = rdusp();
600 sc->sc_d0 = regs->d0;
601 sc->sc_d1 = regs->d1;
602 sc->sc_a0 = regs->a0;
603 sc->sc_a1 = regs->a1;
604 sc->sc_sr = regs->sr;
605 sc->sc_pc = regs->pc;
606 sc->sc_formatvec = regs->format << 12 | regs->vector;
607 save_fpu_state(sc, regs);
608}
609
610static inline int rt_setup_ucontext(struct ucontext __user *uc, struct pt_regs *regs)
611{
612 struct switch_stack *sw = (struct switch_stack *)regs - 1;
613 greg_t __user *gregs = uc->uc_mcontext.gregs;
614 int err = 0;
615
616 err |= __put_user(MCONTEXT_VERSION, &uc->uc_mcontext.version);
617 err |= __put_user(regs->d0, &gregs[0]);
618 err |= __put_user(regs->d1, &gregs[1]);
619 err |= __put_user(regs->d2, &gregs[2]);
620 err |= __put_user(regs->d3, &gregs[3]);
621 err |= __put_user(regs->d4, &gregs[4]);
622 err |= __put_user(regs->d5, &gregs[5]);
623 err |= __put_user(sw->d6, &gregs[6]);
624 err |= __put_user(sw->d7, &gregs[7]);
625 err |= __put_user(regs->a0, &gregs[8]);
626 err |= __put_user(regs->a1, &gregs[9]);
627 err |= __put_user(regs->a2, &gregs[10]);
628 err |= __put_user(sw->a3, &gregs[11]);
629 err |= __put_user(sw->a4, &gregs[12]);
630 err |= __put_user(sw->a5, &gregs[13]);
631 err |= __put_user(sw->a6, &gregs[14]);
632 err |= __put_user(rdusp(), &gregs[15]);
633 err |= __put_user(regs->pc, &gregs[16]);
634 err |= __put_user(regs->sr, &gregs[17]);
635 err |= __put_user((regs->format << 12) | regs->vector, &uc->uc_formatvec);
636 err |= rt_save_fpu_state(uc, regs);
637 return err;
638}
639
640static inline void push_cache (unsigned long vaddr)
641{
642 /*
643 * Using the old cache_push_v() was really a big waste.
644 *
645 * What we are trying to do is to flush 8 bytes to ram.
646 * Flushing 2 cache lines of 16 bytes is much cheaper than
647 * flushing 1 or 2 pages, as previously done in
648 * cache_push_v().
649 * Jes
650 */
651 if (CPU_IS_040) {
652 unsigned long temp;
653
654 __asm__ __volatile__ (".chip 68040\n\t"
655 "nop\n\t"
656 "ptestr (%1)\n\t"
657 "movec %%mmusr,%0\n\t"
658 ".chip 68k"
659 : "=r" (temp)
660 : "a" (vaddr));
661
662 temp &= PAGE_MASK;
663 temp |= vaddr & ~PAGE_MASK;
664
665 __asm__ __volatile__ (".chip 68040\n\t"
666 "nop\n\t"
667 "cpushl %%bc,(%0)\n\t"
668 ".chip 68k"
669 : : "a" (temp));
670 }
671 else if (CPU_IS_060) {
672 unsigned long temp;
673 __asm__ __volatile__ (".chip 68060\n\t"
674 "plpar (%0)\n\t"
675 ".chip 68k"
676 : "=a" (temp)
677 : "0" (vaddr));
678 __asm__ __volatile__ (".chip 68060\n\t"
679 "cpushl %%bc,(%0)\n\t"
680 ".chip 68k"
681 : : "a" (temp));
682 }
683 else {
684 /*
685 * 68030/68020 have no writeback cache;
686 * still need to clear icache.
687 * Note that vaddr is guaranteed to be long word aligned.
688 */
689 unsigned long temp;
690 asm volatile ("movec %%cacr,%0" : "=r" (temp));
691 temp += 4;
692 asm volatile ("movec %0,%%caar\n\t"
693 "movec %1,%%cacr"
694 : : "r" (vaddr), "r" (temp));
695 asm volatile ("movec %0,%%caar\n\t"
696 "movec %1,%%cacr"
697 : : "r" (vaddr + 4), "r" (temp));
698 }
699}
700
701static inline void __user *
702get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size)
703{
704 unsigned long usp;
705
706 /* Default to using normal stack. */
707 usp = rdusp();
708
709 /* This is the X/Open sanctioned signal stack switching. */
710 if (ka->sa.sa_flags & SA_ONSTACK) {
711 if (!sas_ss_flags(usp))
712 usp = current->sas_ss_sp + current->sas_ss_size;
713 }
714 return (void __user *)((usp - frame_size) & -8UL);
715}
716
717static int setup_frame (int sig, struct k_sigaction *ka,
718 sigset_t *set, struct pt_regs *regs)
719{
720 struct sigframe __user *frame;
721 int fsize = frame_extra_sizes[regs->format];
722 struct sigcontext context;
723 int err = 0;
724
725 if (fsize < 0) {
726#ifdef DEBUG
727 printk ("setup_frame: Unknown frame format %#x\n",
728 regs->format);
729#endif
730 goto give_sigsegv;
731 }
732
733 frame = get_sigframe(ka, regs, sizeof(*frame) + fsize);
734
735 if (fsize)
736 err |= copy_to_user (frame + 1, regs + 1, fsize);
737
738 err |= __put_user((current_thread_info()->exec_domain
739 && current_thread_info()->exec_domain->signal_invmap
740 && sig < 32
741 ? current_thread_info()->exec_domain->signal_invmap[sig]
742 : sig),
743 &frame->sig);
744
745 err |= __put_user(regs->vector, &frame->code);
746 err |= __put_user(&frame->sc, &frame->psc);
747
748 if (_NSIG_WORDS > 1)
749 err |= copy_to_user(frame->extramask, &set->sig[1],
750 sizeof(frame->extramask));
751
752 setup_sigcontext(&context, regs, set->sig[0]);
753 err |= copy_to_user (&frame->sc, &context, sizeof(context));
754
755 /* Set up to return from userspace. */
756 err |= __put_user(frame->retcode, &frame->pretcode);
757 /* moveq #,d0; trap #0 */
758 err |= __put_user(0x70004e40 + (__NR_sigreturn << 16),
759 (long __user *)(frame->retcode));
760
761 if (err)
762 goto give_sigsegv;
763
764 push_cache ((unsigned long) &frame->retcode);
765
766 /*
767 * Set up registers for signal handler. All the state we are about
768 * to destroy is successfully copied to sigframe.
769 */
770 wrusp ((unsigned long) frame);
771 regs->pc = (unsigned long) ka->sa.sa_handler;
772
773 /*
774 * This is subtle; if we build more than one sigframe, all but the
775 * first one will see frame format 0 and have fsize == 0, so we won't
776 * screw stkadj.
777 */
778 if (fsize)
779 regs->stkadj = fsize;
780
781 /* Prepare to skip over the extra stuff in the exception frame. */
782 if (regs->stkadj) {
783 struct pt_regs *tregs =
784 (struct pt_regs *)((ulong)regs + regs->stkadj);
785#ifdef DEBUG
786 printk("Performing stackadjust=%04x\n", regs->stkadj);
787#endif
788 /* This must be copied with decreasing addresses to
789 handle overlaps. */
790 tregs->vector = 0;
791 tregs->format = 0;
792 tregs->pc = regs->pc;
793 tregs->sr = regs->sr;
794 }
795 return 0;
796
797give_sigsegv:
798 force_sigsegv(sig, current);
799 return err;
800}
801
802static int setup_rt_frame (int sig, struct k_sigaction *ka, siginfo_t *info,
803 sigset_t *set, struct pt_regs *regs)
804{
805 struct rt_sigframe __user *frame;
806 int fsize = frame_extra_sizes[regs->format];
807 int err = 0;
808
809 if (fsize < 0) {
810#ifdef DEBUG
811 printk ("setup_frame: Unknown frame format %#x\n",
812 regs->format);
813#endif
814 goto give_sigsegv;
815 }
816
817 frame = get_sigframe(ka, regs, sizeof(*frame));
818
819 if (fsize)
820 err |= copy_to_user (&frame->uc.uc_extra, regs + 1, fsize);
821
822 err |= __put_user((current_thread_info()->exec_domain
823 && current_thread_info()->exec_domain->signal_invmap
824 && sig < 32
825 ? current_thread_info()->exec_domain->signal_invmap[sig]
826 : sig),
827 &frame->sig);
828 err |= __put_user(&frame->info, &frame->pinfo);
829 err |= __put_user(&frame->uc, &frame->puc);
830 err |= copy_siginfo_to_user(&frame->info, info);
831
832 /* Create the ucontext. */
833 err |= __put_user(0, &frame->uc.uc_flags);
834 err |= __put_user(NULL, &frame->uc.uc_link);
835 err |= __put_user((void __user *)current->sas_ss_sp,
836 &frame->uc.uc_stack.ss_sp);
837 err |= __put_user(sas_ss_flags(rdusp()),
838 &frame->uc.uc_stack.ss_flags);
839 err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
840 err |= rt_setup_ucontext(&frame->uc, regs);
841 err |= copy_to_user (&frame->uc.uc_sigmask, set, sizeof(*set));
842
843 /* Set up to return from userspace. */
844 err |= __put_user(frame->retcode, &frame->pretcode);
845#ifdef __mcoldfire__
846 /* movel #__NR_rt_sigreturn,d0; trap #0 */
847 err |= __put_user(0x203c0000, (long __user *)(frame->retcode + 0));
848 err |= __put_user(0x00004e40 + (__NR_rt_sigreturn << 16),
849 (long __user *)(frame->retcode + 4));
850#else 3#else
851 /* moveq #,d0; notb d0; trap #0 */ 4#include "signal_no.c"
852 err |= __put_user(0x70004600 + ((__NR_rt_sigreturn ^ 0xff) << 16),
853 (long __user *)(frame->retcode + 0));
854 err |= __put_user(0x4e40, (short __user *)(frame->retcode + 4));
855#endif
856
857 if (err)
858 goto give_sigsegv;
859
860 push_cache ((unsigned long) &frame->retcode);
861
862 /*
863 * Set up registers for signal handler. All the state we are about
864 * to destroy is successfully copied to sigframe.
865 */
866 wrusp ((unsigned long) frame);
867 regs->pc = (unsigned long) ka->sa.sa_handler;
868
869 /*
870 * This is subtle; if we build more than one sigframe, all but the
871 * first one will see frame format 0 and have fsize == 0, so we won't
872 * screw stkadj.
873 */
874 if (fsize)
875 regs->stkadj = fsize;
876
877 /* Prepare to skip over the extra stuff in the exception frame. */
878 if (regs->stkadj) {
879 struct pt_regs *tregs =
880 (struct pt_regs *)((ulong)regs + regs->stkadj);
881#ifdef DEBUG
882 printk("Performing stackadjust=%04x\n", regs->stkadj);
883#endif 5#endif
884 /* This must be copied with decreasing addresses to
885 handle overlaps. */
886 tregs->vector = 0;
887 tregs->format = 0;
888 tregs->pc = regs->pc;
889 tregs->sr = regs->sr;
890 }
891 return 0;
892
893give_sigsegv:
894 force_sigsegv(sig, current);
895 return err;
896}
897
898static inline void
899handle_restart(struct pt_regs *regs, struct k_sigaction *ka, int has_handler)
900{
901 switch (regs->d0) {
902 case -ERESTARTNOHAND:
903 if (!has_handler)
904 goto do_restart;
905 regs->d0 = -EINTR;
906 break;
907
908 case -ERESTART_RESTARTBLOCK:
909 if (!has_handler) {
910 regs->d0 = __NR_restart_syscall;
911 regs->pc -= 2;
912 break;
913 }
914 regs->d0 = -EINTR;
915 break;
916
917 case -ERESTARTSYS:
918 if (has_handler && !(ka->sa.sa_flags & SA_RESTART)) {
919 regs->d0 = -EINTR;
920 break;
921 }
922 /* fallthrough */
923 case -ERESTARTNOINTR:
924 do_restart:
925 regs->d0 = regs->orig_d0;
926 regs->pc -= 2;
927 break;
928 }
929}
930
931void ptrace_signal_deliver(struct pt_regs *regs, void *cookie)
932{
933 if (regs->orig_d0 < 0)
934 return;
935 switch (regs->d0) {
936 case -ERESTARTNOHAND:
937 case -ERESTARTSYS:
938 case -ERESTARTNOINTR:
939 regs->d0 = regs->orig_d0;
940 regs->orig_d0 = -1;
941 regs->pc -= 2;
942 break;
943 }
944}
945
946/*
947 * OK, we're invoking a handler
948 */
949static void
950handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info,
951 sigset_t *oldset, struct pt_regs *regs)
952{
953 int err;
954 /* are we from a system call? */
955 if (regs->orig_d0 >= 0)
956 /* If so, check system call restarting.. */
957 handle_restart(regs, ka, 1);
958
959 /* set up the stack frame */
960 if (ka->sa.sa_flags & SA_SIGINFO)
961 err = setup_rt_frame(sig, ka, info, oldset, regs);
962 else
963 err = setup_frame(sig, ka, oldset, regs);
964
965 if (err)
966 return;
967
968 sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
969 if (!(ka->sa.sa_flags & SA_NODEFER))
970 sigaddset(&current->blocked,sig);
971 recalc_sigpending();
972
973 if (test_thread_flag(TIF_DELAYED_TRACE)) {
974 regs->sr &= ~0x8000;
975 send_sig(SIGTRAP, current, 1);
976 }
977
978 clear_thread_flag(TIF_RESTORE_SIGMASK);
979}
980
981/*
982 * Note that 'init' is a special process: it doesn't get signals it doesn't
983 * want to handle. Thus you cannot kill init even with a SIGKILL even by
984 * mistake.
985 */
986asmlinkage void do_signal(struct pt_regs *regs)
987{
988 siginfo_t info;
989 struct k_sigaction ka;
990 int signr;
991 sigset_t *oldset;
992
993 current->thread.esp0 = (unsigned long) regs;
994
995 if (test_thread_flag(TIF_RESTORE_SIGMASK))
996 oldset = &current->saved_sigmask;
997 else
998 oldset = &current->blocked;
999
1000 signr = get_signal_to_deliver(&info, &ka, regs, NULL);
1001 if (signr > 0) {
1002 /* Whee! Actually deliver the signal. */
1003 handle_signal(signr, &ka, &info, oldset, regs);
1004 return;
1005 }
1006
1007 /* Did we come from a system call? */
1008 if (regs->orig_d0 >= 0)
1009 /* Restart the system call - no handlers present */
1010 handle_restart(regs, NULL, 0);
1011
1012 /* If there's no signal to deliver, we just restore the saved mask. */
1013 if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
1014 clear_thread_flag(TIF_RESTORE_SIGMASK);
1015 sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
1016 }
1017}
diff --git a/arch/m68k/kernel/signal_mm.c b/arch/m68k/kernel/signal_mm.c
new file mode 100644
index 00000000000..a0afc239304
--- /dev/null
+++ b/arch/m68k/kernel/signal_mm.c
@@ -0,0 +1,1017 @@
1/*
2 * linux/arch/m68k/kernel/signal.c
3 *
4 * Copyright (C) 1991, 1992 Linus Torvalds
5 *
6 * This file is subject to the terms and conditions of the GNU General Public
7 * License. See the file COPYING in the main directory of this archive
8 * for more details.
9 */
10
11/*
12 * Linux/m68k support by Hamish Macdonald
13 *
14 * 68060 fixes by Jesper Skov
15 *
16 * 1997-12-01 Modified for POSIX.1b signals by Andreas Schwab
17 *
18 * mathemu support by Roman Zippel
19 * (Note: fpstate in the signal context is completely ignored for the emulator
20 * and the internal floating point format is put on stack)
21 */
22
23/*
24 * ++roman (07/09/96): implemented signal stacks (specially for tosemu on
25 * Atari :-) Current limitation: Only one sigstack can be active at one time.
26 * If a second signal with SA_ONSTACK set arrives while working on a sigstack,
27 * SA_ONSTACK is ignored. This behaviour avoids lots of trouble with nested
28 * signal handlers!
29 */
30
31#include <linux/sched.h>
32#include <linux/mm.h>
33#include <linux/kernel.h>
34#include <linux/signal.h>
35#include <linux/syscalls.h>
36#include <linux/errno.h>
37#include <linux/wait.h>
38#include <linux/ptrace.h>
39#include <linux/unistd.h>
40#include <linux/stddef.h>
41#include <linux/highuid.h>
42#include <linux/personality.h>
43#include <linux/tty.h>
44#include <linux/binfmts.h>
45#include <linux/module.h>
46
47#include <asm/setup.h>
48#include <asm/uaccess.h>
49#include <asm/pgtable.h>
50#include <asm/traps.h>
51#include <asm/ucontext.h>
52
53#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
54
55static const int frame_extra_sizes[16] = {
56 [1] = -1, /* sizeof(((struct frame *)0)->un.fmt1), */
57 [2] = sizeof(((struct frame *)0)->un.fmt2),
58 [3] = sizeof(((struct frame *)0)->un.fmt3),
59 [4] = sizeof(((struct frame *)0)->un.fmt4),
60 [5] = -1, /* sizeof(((struct frame *)0)->un.fmt5), */
61 [6] = -1, /* sizeof(((struct frame *)0)->un.fmt6), */
62 [7] = sizeof(((struct frame *)0)->un.fmt7),
63 [8] = -1, /* sizeof(((struct frame *)0)->un.fmt8), */
64 [9] = sizeof(((struct frame *)0)->un.fmt9),
65 [10] = sizeof(((struct frame *)0)->un.fmta),
66 [11] = sizeof(((struct frame *)0)->un.fmtb),
67 [12] = -1, /* sizeof(((struct frame *)0)->un.fmtc), */
68 [13] = -1, /* sizeof(((struct frame *)0)->un.fmtd), */
69 [14] = -1, /* sizeof(((struct frame *)0)->un.fmte), */
70 [15] = -1, /* sizeof(((struct frame *)0)->un.fmtf), */
71};
72
73int handle_kernel_fault(struct pt_regs *regs)
74{
75 const struct exception_table_entry *fixup;
76 struct pt_regs *tregs;
77
78 /* Are we prepared to handle this kernel fault? */
79 fixup = search_exception_tables(regs->pc);
80 if (!fixup)
81 return 0;
82
83 /* Create a new four word stack frame, discarding the old one. */
84 regs->stkadj = frame_extra_sizes[regs->format];
85 tregs = (struct pt_regs *)((long)regs + regs->stkadj);
86 tregs->vector = regs->vector;
87 tregs->format = 0;
88 tregs->pc = fixup->fixup;
89 tregs->sr = regs->sr;
90
91 return 1;
92}
93
94/*
95 * Atomically swap in the new signal mask, and wait for a signal.
96 */
97asmlinkage int
98sys_sigsuspend(int unused0, int unused1, old_sigset_t mask)
99{
100 mask &= _BLOCKABLE;
101 spin_lock_irq(&current->sighand->siglock);
102 current->saved_sigmask = current->blocked;
103 siginitset(&current->blocked, mask);
104 recalc_sigpending();
105 spin_unlock_irq(&current->sighand->siglock);
106
107 current->state = TASK_INTERRUPTIBLE;
108 schedule();
109 set_restore_sigmask();
110
111 return -ERESTARTNOHAND;
112}
113
114asmlinkage int
115sys_sigaction(int sig, const struct old_sigaction __user *act,
116 struct old_sigaction __user *oact)
117{
118 struct k_sigaction new_ka, old_ka;
119 int ret;
120
121 if (act) {
122 old_sigset_t mask;
123 if (!access_ok(VERIFY_READ, act, sizeof(*act)) ||
124 __get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
125 __get_user(new_ka.sa.sa_restorer, &act->sa_restorer) ||
126 __get_user(new_ka.sa.sa_flags, &act->sa_flags) ||
127 __get_user(mask, &act->sa_mask))
128 return -EFAULT;
129 siginitset(&new_ka.sa.sa_mask, mask);
130 }
131
132 ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
133
134 if (!ret && oact) {
135 if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) ||
136 __put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
137 __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer) ||
138 __put_user(old_ka.sa.sa_flags, &oact->sa_flags) ||
139 __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask))
140 return -EFAULT;
141 }
142
143 return ret;
144}
145
146asmlinkage int
147sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss)
148{
149 return do_sigaltstack(uss, uoss, rdusp());
150}
151
152
153/*
154 * Do a signal return; undo the signal stack.
155 *
156 * Keep the return code on the stack quadword aligned!
157 * That makes the cache flush below easier.
158 */
159
160struct sigframe
161{
162 char __user *pretcode;
163 int sig;
164 int code;
165 struct sigcontext __user *psc;
166 char retcode[8];
167 unsigned long extramask[_NSIG_WORDS-1];
168 struct sigcontext sc;
169};
170
171struct rt_sigframe
172{
173 char __user *pretcode;
174 int sig;
175 struct siginfo __user *pinfo;
176 void __user *puc;
177 char retcode[8];
178 struct siginfo info;
179 struct ucontext uc;
180};
181
182
183static unsigned char fpu_version; /* version number of fpu, set by setup_frame */
184
185static inline int restore_fpu_state(struct sigcontext *sc)
186{
187 int err = 1;
188
189 if (FPU_IS_EMU) {
190 /* restore registers */
191 memcpy(current->thread.fpcntl, sc->sc_fpcntl, 12);
192 memcpy(current->thread.fp, sc->sc_fpregs, 24);
193 return 0;
194 }
195
196 if (CPU_IS_060 ? sc->sc_fpstate[2] : sc->sc_fpstate[0]) {
197 /* Verify the frame format. */
198 if (!CPU_IS_060 && (sc->sc_fpstate[0] != fpu_version))
199 goto out;
200 if (CPU_IS_020_OR_030) {
201 if (m68k_fputype & FPU_68881 &&
202 !(sc->sc_fpstate[1] == 0x18 || sc->sc_fpstate[1] == 0xb4))
203 goto out;
204 if (m68k_fputype & FPU_68882 &&
205 !(sc->sc_fpstate[1] == 0x38 || sc->sc_fpstate[1] == 0xd4))
206 goto out;
207 } else if (CPU_IS_040) {
208 if (!(sc->sc_fpstate[1] == 0x00 ||
209 sc->sc_fpstate[1] == 0x28 ||
210 sc->sc_fpstate[1] == 0x60))
211 goto out;
212 } else if (CPU_IS_060) {
213 if (!(sc->sc_fpstate[3] == 0x00 ||
214 sc->sc_fpstate[3] == 0x60 ||
215 sc->sc_fpstate[3] == 0xe0))
216 goto out;
217 } else
218 goto out;
219
220 __asm__ volatile (".chip 68k/68881\n\t"
221 "fmovemx %0,%%fp0-%%fp1\n\t"
222 "fmoveml %1,%%fpcr/%%fpsr/%%fpiar\n\t"
223 ".chip 68k"
224 : /* no outputs */
225 : "m" (*sc->sc_fpregs), "m" (*sc->sc_fpcntl));
226 }
227 __asm__ volatile (".chip 68k/68881\n\t"
228 "frestore %0\n\t"
229 ".chip 68k" : : "m" (*sc->sc_fpstate));
230 err = 0;
231
232out:
233 return err;
234}
235
236#define FPCONTEXT_SIZE 216
237#define uc_fpstate uc_filler[0]
238#define uc_formatvec uc_filler[FPCONTEXT_SIZE/4]
239#define uc_extra uc_filler[FPCONTEXT_SIZE/4+1]
240
241static inline int rt_restore_fpu_state(struct ucontext __user *uc)
242{
243 unsigned char fpstate[FPCONTEXT_SIZE];
244 int context_size = CPU_IS_060 ? 8 : 0;
245 fpregset_t fpregs;
246 int err = 1;
247
248 if (FPU_IS_EMU) {
249 /* restore fpu control register */
250 if (__copy_from_user(current->thread.fpcntl,
251 uc->uc_mcontext.fpregs.f_fpcntl, 12))
252 goto out;
253 /* restore all other fpu register */
254 if (__copy_from_user(current->thread.fp,
255 uc->uc_mcontext.fpregs.f_fpregs, 96))
256 goto out;
257 return 0;
258 }
259
260 if (__get_user(*(long *)fpstate, (long __user *)&uc->uc_fpstate))
261 goto out;
262 if (CPU_IS_060 ? fpstate[2] : fpstate[0]) {
263 if (!CPU_IS_060)
264 context_size = fpstate[1];
265 /* Verify the frame format. */
266 if (!CPU_IS_060 && (fpstate[0] != fpu_version))
267 goto out;
268 if (CPU_IS_020_OR_030) {
269 if (m68k_fputype & FPU_68881 &&
270 !(context_size == 0x18 || context_size == 0xb4))
271 goto out;
272 if (m68k_fputype & FPU_68882 &&
273 !(context_size == 0x38 || context_size == 0xd4))
274 goto out;
275 } else if (CPU_IS_040) {
276 if (!(context_size == 0x00 ||
277 context_size == 0x28 ||
278 context_size == 0x60))
279 goto out;
280 } else if (CPU_IS_060) {
281 if (!(fpstate[3] == 0x00 ||
282 fpstate[3] == 0x60 ||
283 fpstate[3] == 0xe0))
284 goto out;
285 } else
286 goto out;
287 if (__copy_from_user(&fpregs, &uc->uc_mcontext.fpregs,
288 sizeof(fpregs)))
289 goto out;
290 __asm__ volatile (".chip 68k/68881\n\t"
291 "fmovemx %0,%%fp0-%%fp7\n\t"
292 "fmoveml %1,%%fpcr/%%fpsr/%%fpiar\n\t"
293 ".chip 68k"
294 : /* no outputs */
295 : "m" (*fpregs.f_fpregs),
296 "m" (*fpregs.f_fpcntl));
297 }
298 if (context_size &&
299 __copy_from_user(fpstate + 4, (long __user *)&uc->uc_fpstate + 1,
300 context_size))
301 goto out;
302 __asm__ volatile (".chip 68k/68881\n\t"
303 "frestore %0\n\t"
304 ".chip 68k" : : "m" (*fpstate));
305 err = 0;
306
307out:
308 return err;
309}
310
311static int mangle_kernel_stack(struct pt_regs *regs, int formatvec,
312 void __user *fp)
313{
314 int fsize = frame_extra_sizes[formatvec >> 12];
315 if (fsize < 0) {
316 /*
317 * user process trying to return with weird frame format
318 */
319#ifdef DEBUG
320 printk("user process returning with weird frame format\n");
321#endif
322 return 1;
323 }
324 if (!fsize) {
325 regs->format = formatvec >> 12;
326 regs->vector = formatvec & 0xfff;
327 } else {
328 struct switch_stack *sw = (struct switch_stack *)regs - 1;
329 unsigned long buf[fsize / 2]; /* yes, twice as much */
330
331 /* that'll make sure that expansion won't crap over data */
332 if (copy_from_user(buf + fsize / 4, fp, fsize))
333 return 1;
334
335 /* point of no return */
336 regs->format = formatvec >> 12;
337 regs->vector = formatvec & 0xfff;
338#define frame_offset (sizeof(struct pt_regs)+sizeof(struct switch_stack))
339 __asm__ __volatile__
340 (" movel %0,%/a0\n\t"
341 " subl %1,%/a0\n\t" /* make room on stack */
342 " movel %/a0,%/sp\n\t" /* set stack pointer */
343 /* move switch_stack and pt_regs */
344 "1: movel %0@+,%/a0@+\n\t"
345 " dbra %2,1b\n\t"
346 " lea %/sp@(%c3),%/a0\n\t" /* add offset of fmt */
347 " lsrl #2,%1\n\t"
348 " subql #1,%1\n\t"
349 /* copy to the gap we'd made */
350 "2: movel %4@+,%/a0@+\n\t"
351 " dbra %1,2b\n\t"
352 " bral ret_from_signal\n"
353 : /* no outputs, it doesn't ever return */
354 : "a" (sw), "d" (fsize), "d" (frame_offset/4-1),
355 "n" (frame_offset), "a" (buf + fsize/4)
356 : "a0");
357#undef frame_offset
358 }
359 return 0;
360}
361
362static inline int
363restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *usc, void __user *fp)
364{
365 int formatvec;
366 struct sigcontext context;
367 int err;
368
369 /* Always make any pending restarted system calls return -EINTR */
370 current_thread_info()->restart_block.fn = do_no_restart_syscall;
371
372 /* get previous context */
373 if (copy_from_user(&context, usc, sizeof(context)))
374 goto badframe;
375
376 /* restore passed registers */
377 regs->d0 = context.sc_d0;
378 regs->d1 = context.sc_d1;
379 regs->a0 = context.sc_a0;
380 regs->a1 = context.sc_a1;
381 regs->sr = (regs->sr & 0xff00) | (context.sc_sr & 0xff);
382 regs->pc = context.sc_pc;
383 regs->orig_d0 = -1; /* disable syscall checks */
384 wrusp(context.sc_usp);
385 formatvec = context.sc_formatvec;
386
387 err = restore_fpu_state(&context);
388
389 if (err || mangle_kernel_stack(regs, formatvec, fp))
390 goto badframe;
391
392 return 0;
393
394badframe:
395 return 1;
396}
397
398static inline int
399rt_restore_ucontext(struct pt_regs *regs, struct switch_stack *sw,
400 struct ucontext __user *uc)
401{
402 int temp;
403 greg_t __user *gregs = uc->uc_mcontext.gregs;
404 unsigned long usp;
405 int err;
406
407 /* Always make any pending restarted system calls return -EINTR */
408 current_thread_info()->restart_block.fn = do_no_restart_syscall;
409
410 err = __get_user(temp, &uc->uc_mcontext.version);
411 if (temp != MCONTEXT_VERSION)
412 goto badframe;
413 /* restore passed registers */
414 err |= __get_user(regs->d0, &gregs[0]);
415 err |= __get_user(regs->d1, &gregs[1]);
416 err |= __get_user(regs->d2, &gregs[2]);
417 err |= __get_user(regs->d3, &gregs[3]);
418 err |= __get_user(regs->d4, &gregs[4]);
419 err |= __get_user(regs->d5, &gregs[5]);
420 err |= __get_user(sw->d6, &gregs[6]);
421 err |= __get_user(sw->d7, &gregs[7]);
422 err |= __get_user(regs->a0, &gregs[8]);
423 err |= __get_user(regs->a1, &gregs[9]);
424 err |= __get_user(regs->a2, &gregs[10]);
425 err |= __get_user(sw->a3, &gregs[11]);
426 err |= __get_user(sw->a4, &gregs[12]);
427 err |= __get_user(sw->a5, &gregs[13]);
428 err |= __get_user(sw->a6, &gregs[14]);
429 err |= __get_user(usp, &gregs[15]);
430 wrusp(usp);
431 err |= __get_user(regs->pc, &gregs[16]);
432 err |= __get_user(temp, &gregs[17]);
433 regs->sr = (regs->sr & 0xff00) | (temp & 0xff);
434 regs->orig_d0 = -1; /* disable syscall checks */
435 err |= __get_user(temp, &uc->uc_formatvec);
436
437 err |= rt_restore_fpu_state(uc);
438
439 if (err || do_sigaltstack(&uc->uc_stack, NULL, usp) == -EFAULT)
440 goto badframe;
441
442 if (mangle_kernel_stack(regs, temp, &uc->uc_extra))
443 goto badframe;
444
445 return 0;
446
447badframe:
448 return 1;
449}
450
451asmlinkage int do_sigreturn(unsigned long __unused)
452{
453 struct switch_stack *sw = (struct switch_stack *) &__unused;
454 struct pt_regs *regs = (struct pt_regs *) (sw + 1);
455 unsigned long usp = rdusp();
456 struct sigframe __user *frame = (struct sigframe __user *)(usp - 4);
457 sigset_t set;
458
459 if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
460 goto badframe;
461 if (__get_user(set.sig[0], &frame->sc.sc_mask) ||
462 (_NSIG_WORDS > 1 &&
463 __copy_from_user(&set.sig[1], &frame->extramask,
464 sizeof(frame->extramask))))
465 goto badframe;
466
467 sigdelsetmask(&set, ~_BLOCKABLE);
468 current->blocked = set;
469 recalc_sigpending();
470
471 if (restore_sigcontext(regs, &frame->sc, frame + 1))
472 goto badframe;
473 return regs->d0;
474
475badframe:
476 force_sig(SIGSEGV, current);
477 return 0;
478}
479
480asmlinkage int do_rt_sigreturn(unsigned long __unused)
481{
482 struct switch_stack *sw = (struct switch_stack *) &__unused;
483 struct pt_regs *regs = (struct pt_regs *) (sw + 1);
484 unsigned long usp = rdusp();
485 struct rt_sigframe __user *frame = (struct rt_sigframe __user *)(usp - 4);
486 sigset_t set;
487
488 if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
489 goto badframe;
490 if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
491 goto badframe;
492
493 sigdelsetmask(&set, ~_BLOCKABLE);
494 current->blocked = set;
495 recalc_sigpending();
496
497 if (rt_restore_ucontext(regs, sw, &frame->uc))
498 goto badframe;
499 return regs->d0;
500
501badframe:
502 force_sig(SIGSEGV, current);
503 return 0;
504}
505
506/*
507 * Set up a signal frame.
508 */
509
510static inline void save_fpu_state(struct sigcontext *sc, struct pt_regs *regs)
511{
512 if (FPU_IS_EMU) {
513 /* save registers */
514 memcpy(sc->sc_fpcntl, current->thread.fpcntl, 12);
515 memcpy(sc->sc_fpregs, current->thread.fp, 24);
516 return;
517 }
518
519 __asm__ volatile (".chip 68k/68881\n\t"
520 "fsave %0\n\t"
521 ".chip 68k"
522 : : "m" (*sc->sc_fpstate) : "memory");
523
524 if (CPU_IS_060 ? sc->sc_fpstate[2] : sc->sc_fpstate[0]) {
525 fpu_version = sc->sc_fpstate[0];
526 if (CPU_IS_020_OR_030 &&
527 regs->vector >= (VEC_FPBRUC * 4) &&
528 regs->vector <= (VEC_FPNAN * 4)) {
529 /* Clear pending exception in 68882 idle frame */
530 if (*(unsigned short *) sc->sc_fpstate == 0x1f38)
531 sc->sc_fpstate[0x38] |= 1 << 3;
532 }
533 __asm__ volatile (".chip 68k/68881\n\t"
534 "fmovemx %%fp0-%%fp1,%0\n\t"
535 "fmoveml %%fpcr/%%fpsr/%%fpiar,%1\n\t"
536 ".chip 68k"
537 : "=m" (*sc->sc_fpregs),
538 "=m" (*sc->sc_fpcntl)
539 : /* no inputs */
540 : "memory");
541 }
542}
543
544static inline int rt_save_fpu_state(struct ucontext __user *uc, struct pt_regs *regs)
545{
546 unsigned char fpstate[FPCONTEXT_SIZE];
547 int context_size = CPU_IS_060 ? 8 : 0;
548 int err = 0;
549
550 if (FPU_IS_EMU) {
551 /* save fpu control register */
552 err |= copy_to_user(uc->uc_mcontext.fpregs.f_fpcntl,
553 current->thread.fpcntl, 12);
554 /* save all other fpu register */
555 err |= copy_to_user(uc->uc_mcontext.fpregs.f_fpregs,
556 current->thread.fp, 96);
557 return err;
558 }
559
560 __asm__ volatile (".chip 68k/68881\n\t"
561 "fsave %0\n\t"
562 ".chip 68k"
563 : : "m" (*fpstate) : "memory");
564
565 err |= __put_user(*(long *)fpstate, (long __user *)&uc->uc_fpstate);
566 if (CPU_IS_060 ? fpstate[2] : fpstate[0]) {
567 fpregset_t fpregs;
568 if (!CPU_IS_060)
569 context_size = fpstate[1];
570 fpu_version = fpstate[0];
571 if (CPU_IS_020_OR_030 &&
572 regs->vector >= (VEC_FPBRUC * 4) &&
573 regs->vector <= (VEC_FPNAN * 4)) {
574 /* Clear pending exception in 68882 idle frame */
575 if (*(unsigned short *) fpstate == 0x1f38)
576 fpstate[0x38] |= 1 << 3;
577 }
578 __asm__ volatile (".chip 68k/68881\n\t"
579 "fmovemx %%fp0-%%fp7,%0\n\t"
580 "fmoveml %%fpcr/%%fpsr/%%fpiar,%1\n\t"
581 ".chip 68k"
582 : "=m" (*fpregs.f_fpregs),
583 "=m" (*fpregs.f_fpcntl)
584 : /* no inputs */
585 : "memory");
586 err |= copy_to_user(&uc->uc_mcontext.fpregs, &fpregs,
587 sizeof(fpregs));
588 }
589 if (context_size)
590 err |= copy_to_user((long __user *)&uc->uc_fpstate + 1, fpstate + 4,
591 context_size);
592 return err;
593}
594
595static void setup_sigcontext(struct sigcontext *sc, struct pt_regs *regs,
596 unsigned long mask)
597{
598 sc->sc_mask = mask;
599 sc->sc_usp = rdusp();
600 sc->sc_d0 = regs->d0;
601 sc->sc_d1 = regs->d1;
602 sc->sc_a0 = regs->a0;
603 sc->sc_a1 = regs->a1;
604 sc->sc_sr = regs->sr;
605 sc->sc_pc = regs->pc;
606 sc->sc_formatvec = regs->format << 12 | regs->vector;
607 save_fpu_state(sc, regs);
608}
609
610static inline int rt_setup_ucontext(struct ucontext __user *uc, struct pt_regs *regs)
611{
612 struct switch_stack *sw = (struct switch_stack *)regs - 1;
613 greg_t __user *gregs = uc->uc_mcontext.gregs;
614 int err = 0;
615
616 err |= __put_user(MCONTEXT_VERSION, &uc->uc_mcontext.version);
617 err |= __put_user(regs->d0, &gregs[0]);
618 err |= __put_user(regs->d1, &gregs[1]);
619 err |= __put_user(regs->d2, &gregs[2]);
620 err |= __put_user(regs->d3, &gregs[3]);
621 err |= __put_user(regs->d4, &gregs[4]);
622 err |= __put_user(regs->d5, &gregs[5]);
623 err |= __put_user(sw->d6, &gregs[6]);
624 err |= __put_user(sw->d7, &gregs[7]);
625 err |= __put_user(regs->a0, &gregs[8]);
626 err |= __put_user(regs->a1, &gregs[9]);
627 err |= __put_user(regs->a2, &gregs[10]);
628 err |= __put_user(sw->a3, &gregs[11]);
629 err |= __put_user(sw->a4, &gregs[12]);
630 err |= __put_user(sw->a5, &gregs[13]);
631 err |= __put_user(sw->a6, &gregs[14]);
632 err |= __put_user(rdusp(), &gregs[15]);
633 err |= __put_user(regs->pc, &gregs[16]);
634 err |= __put_user(regs->sr, &gregs[17]);
635 err |= __put_user((regs->format << 12) | regs->vector, &uc->uc_formatvec);
636 err |= rt_save_fpu_state(uc, regs);
637 return err;
638}
639
640static inline void push_cache (unsigned long vaddr)
641{
642 /*
643 * Using the old cache_push_v() was really a big waste.
644 *
645 * What we are trying to do is to flush 8 bytes to ram.
646 * Flushing 2 cache lines of 16 bytes is much cheaper than
647 * flushing 1 or 2 pages, as previously done in
648 * cache_push_v().
649 * Jes
650 */
651 if (CPU_IS_040) {
652 unsigned long temp;
653
654 __asm__ __volatile__ (".chip 68040\n\t"
655 "nop\n\t"
656 "ptestr (%1)\n\t"
657 "movec %%mmusr,%0\n\t"
658 ".chip 68k"
659 : "=r" (temp)
660 : "a" (vaddr));
661
662 temp &= PAGE_MASK;
663 temp |= vaddr & ~PAGE_MASK;
664
665 __asm__ __volatile__ (".chip 68040\n\t"
666 "nop\n\t"
667 "cpushl %%bc,(%0)\n\t"
668 ".chip 68k"
669 : : "a" (temp));
670 }
671 else if (CPU_IS_060) {
672 unsigned long temp;
673 __asm__ __volatile__ (".chip 68060\n\t"
674 "plpar (%0)\n\t"
675 ".chip 68k"
676 : "=a" (temp)
677 : "0" (vaddr));
678 __asm__ __volatile__ (".chip 68060\n\t"
679 "cpushl %%bc,(%0)\n\t"
680 ".chip 68k"
681 : : "a" (temp));
682 }
683 else {
684 /*
685 * 68030/68020 have no writeback cache;
686 * still need to clear icache.
687 * Note that vaddr is guaranteed to be long word aligned.
688 */
689 unsigned long temp;
690 asm volatile ("movec %%cacr,%0" : "=r" (temp));
691 temp += 4;
692 asm volatile ("movec %0,%%caar\n\t"
693 "movec %1,%%cacr"
694 : : "r" (vaddr), "r" (temp));
695 asm volatile ("movec %0,%%caar\n\t"
696 "movec %1,%%cacr"
697 : : "r" (vaddr + 4), "r" (temp));
698 }
699}
700
701static inline void __user *
702get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size)
703{
704 unsigned long usp;
705
706 /* Default to using normal stack. */
707 usp = rdusp();
708
709 /* This is the X/Open sanctioned signal stack switching. */
710 if (ka->sa.sa_flags & SA_ONSTACK) {
711 if (!sas_ss_flags(usp))
712 usp = current->sas_ss_sp + current->sas_ss_size;
713 }
714 return (void __user *)((usp - frame_size) & -8UL);
715}
716
717static int setup_frame (int sig, struct k_sigaction *ka,
718 sigset_t *set, struct pt_regs *regs)
719{
720 struct sigframe __user *frame;
721 int fsize = frame_extra_sizes[regs->format];
722 struct sigcontext context;
723 int err = 0;
724
725 if (fsize < 0) {
726#ifdef DEBUG
727 printk ("setup_frame: Unknown frame format %#x\n",
728 regs->format);
729#endif
730 goto give_sigsegv;
731 }
732
733 frame = get_sigframe(ka, regs, sizeof(*frame) + fsize);
734
735 if (fsize)
736 err |= copy_to_user (frame + 1, regs + 1, fsize);
737
738 err |= __put_user((current_thread_info()->exec_domain
739 && current_thread_info()->exec_domain->signal_invmap
740 && sig < 32
741 ? current_thread_info()->exec_domain->signal_invmap[sig]
742 : sig),
743 &frame->sig);
744
745 err |= __put_user(regs->vector, &frame->code);
746 err |= __put_user(&frame->sc, &frame->psc);
747
748 if (_NSIG_WORDS > 1)
749 err |= copy_to_user(frame->extramask, &set->sig[1],
750 sizeof(frame->extramask));
751
752 setup_sigcontext(&context, regs, set->sig[0]);
753 err |= copy_to_user (&frame->sc, &context, sizeof(context));
754
755 /* Set up to return from userspace. */
756 err |= __put_user(frame->retcode, &frame->pretcode);
757 /* moveq #,d0; trap #0 */
758 err |= __put_user(0x70004e40 + (__NR_sigreturn << 16),
759 (long __user *)(frame->retcode));
760
761 if (err)
762 goto give_sigsegv;
763
764 push_cache ((unsigned long) &frame->retcode);
765
766 /*
767 * Set up registers for signal handler. All the state we are about
768 * to destroy is successfully copied to sigframe.
769 */
770 wrusp ((unsigned long) frame);
771 regs->pc = (unsigned long) ka->sa.sa_handler;
772
773 /*
774 * This is subtle; if we build more than one sigframe, all but the
775 * first one will see frame format 0 and have fsize == 0, so we won't
776 * screw stkadj.
777 */
778 if (fsize)
779 regs->stkadj = fsize;
780
781 /* Prepare to skip over the extra stuff in the exception frame. */
782 if (regs->stkadj) {
783 struct pt_regs *tregs =
784 (struct pt_regs *)((ulong)regs + regs->stkadj);
785#ifdef DEBUG
786 printk("Performing stackadjust=%04x\n", regs->stkadj);
787#endif
788 /* This must be copied with decreasing addresses to
789 handle overlaps. */
790 tregs->vector = 0;
791 tregs->format = 0;
792 tregs->pc = regs->pc;
793 tregs->sr = regs->sr;
794 }
795 return 0;
796
797give_sigsegv:
798 force_sigsegv(sig, current);
799 return err;
800}
801
802static int setup_rt_frame (int sig, struct k_sigaction *ka, siginfo_t *info,
803 sigset_t *set, struct pt_regs *regs)
804{
805 struct rt_sigframe __user *frame;
806 int fsize = frame_extra_sizes[regs->format];
807 int err = 0;
808
809 if (fsize < 0) {
810#ifdef DEBUG
811 printk ("setup_frame: Unknown frame format %#x\n",
812 regs->format);
813#endif
814 goto give_sigsegv;
815 }
816
817 frame = get_sigframe(ka, regs, sizeof(*frame));
818
819 if (fsize)
820 err |= copy_to_user (&frame->uc.uc_extra, regs + 1, fsize);
821
822 err |= __put_user((current_thread_info()->exec_domain
823 && current_thread_info()->exec_domain->signal_invmap
824 && sig < 32
825 ? current_thread_info()->exec_domain->signal_invmap[sig]
826 : sig),
827 &frame->sig);
828 err |= __put_user(&frame->info, &frame->pinfo);
829 err |= __put_user(&frame->uc, &frame->puc);
830 err |= copy_siginfo_to_user(&frame->info, info);
831
832 /* Create the ucontext. */
833 err |= __put_user(0, &frame->uc.uc_flags);
834 err |= __put_user(NULL, &frame->uc.uc_link);
835 err |= __put_user((void __user *)current->sas_ss_sp,
836 &frame->uc.uc_stack.ss_sp);
837 err |= __put_user(sas_ss_flags(rdusp()),
838 &frame->uc.uc_stack.ss_flags);
839 err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
840 err |= rt_setup_ucontext(&frame->uc, regs);
841 err |= copy_to_user (&frame->uc.uc_sigmask, set, sizeof(*set));
842
843 /* Set up to return from userspace. */
844 err |= __put_user(frame->retcode, &frame->pretcode);
845#ifdef __mcoldfire__
846 /* movel #__NR_rt_sigreturn,d0; trap #0 */
847 err |= __put_user(0x203c0000, (long __user *)(frame->retcode + 0));
848 err |= __put_user(0x00004e40 + (__NR_rt_sigreturn << 16),
849 (long __user *)(frame->retcode + 4));
850#else
851 /* moveq #,d0; notb d0; trap #0 */
852 err |= __put_user(0x70004600 + ((__NR_rt_sigreturn ^ 0xff) << 16),
853 (long __user *)(frame->retcode + 0));
854 err |= __put_user(0x4e40, (short __user *)(frame->retcode + 4));
855#endif
856
857 if (err)
858 goto give_sigsegv;
859
860 push_cache ((unsigned long) &frame->retcode);
861
862 /*
863 * Set up registers for signal handler. All the state we are about
864 * to destroy is successfully copied to sigframe.
865 */
866 wrusp ((unsigned long) frame);
867 regs->pc = (unsigned long) ka->sa.sa_handler;
868
869 /*
870 * This is subtle; if we build more than one sigframe, all but the
871 * first one will see frame format 0 and have fsize == 0, so we won't
872 * screw stkadj.
873 */
874 if (fsize)
875 regs->stkadj = fsize;
876
877 /* Prepare to skip over the extra stuff in the exception frame. */
878 if (regs->stkadj) {
879 struct pt_regs *tregs =
880 (struct pt_regs *)((ulong)regs + regs->stkadj);
881#ifdef DEBUG
882 printk("Performing stackadjust=%04x\n", regs->stkadj);
883#endif
884 /* This must be copied with decreasing addresses to
885 handle overlaps. */
886 tregs->vector = 0;
887 tregs->format = 0;
888 tregs->pc = regs->pc;
889 tregs->sr = regs->sr;
890 }
891 return 0;
892
893give_sigsegv:
894 force_sigsegv(sig, current);
895 return err;
896}
897
898static inline void
899handle_restart(struct pt_regs *regs, struct k_sigaction *ka, int has_handler)
900{
901 switch (regs->d0) {
902 case -ERESTARTNOHAND:
903 if (!has_handler)
904 goto do_restart;
905 regs->d0 = -EINTR;
906 break;
907
908 case -ERESTART_RESTARTBLOCK:
909 if (!has_handler) {
910 regs->d0 = __NR_restart_syscall;
911 regs->pc -= 2;
912 break;
913 }
914 regs->d0 = -EINTR;
915 break;
916
917 case -ERESTARTSYS:
918 if (has_handler && !(ka->sa.sa_flags & SA_RESTART)) {
919 regs->d0 = -EINTR;
920 break;
921 }
922 /* fallthrough */
923 case -ERESTARTNOINTR:
924 do_restart:
925 regs->d0 = regs->orig_d0;
926 regs->pc -= 2;
927 break;
928 }
929}
930
931void ptrace_signal_deliver(struct pt_regs *regs, void *cookie)
932{
933 if (regs->orig_d0 < 0)
934 return;
935 switch (regs->d0) {
936 case -ERESTARTNOHAND:
937 case -ERESTARTSYS:
938 case -ERESTARTNOINTR:
939 regs->d0 = regs->orig_d0;
940 regs->orig_d0 = -1;
941 regs->pc -= 2;
942 break;
943 }
944}
945
946/*
947 * OK, we're invoking a handler
948 */
949static void
950handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info,
951 sigset_t *oldset, struct pt_regs *regs)
952{
953 int err;
954 /* are we from a system call? */
955 if (regs->orig_d0 >= 0)
956 /* If so, check system call restarting.. */
957 handle_restart(regs, ka, 1);
958
959 /* set up the stack frame */
960 if (ka->sa.sa_flags & SA_SIGINFO)
961 err = setup_rt_frame(sig, ka, info, oldset, regs);
962 else
963 err = setup_frame(sig, ka, oldset, regs);
964
965 if (err)
966 return;
967
968 sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
969 if (!(ka->sa.sa_flags & SA_NODEFER))
970 sigaddset(&current->blocked,sig);
971 recalc_sigpending();
972
973 if (test_thread_flag(TIF_DELAYED_TRACE)) {
974 regs->sr &= ~0x8000;
975 send_sig(SIGTRAP, current, 1);
976 }
977
978 clear_thread_flag(TIF_RESTORE_SIGMASK);
979}
980
981/*
982 * Note that 'init' is a special process: it doesn't get signals it doesn't
983 * want to handle. Thus you cannot kill init even with a SIGKILL even by
984 * mistake.
985 */
986asmlinkage void do_signal(struct pt_regs *regs)
987{
988 siginfo_t info;
989 struct k_sigaction ka;
990 int signr;
991 sigset_t *oldset;
992
993 current->thread.esp0 = (unsigned long) regs;
994
995 if (test_thread_flag(TIF_RESTORE_SIGMASK))
996 oldset = &current->saved_sigmask;
997 else
998 oldset = &current->blocked;
999
1000 signr = get_signal_to_deliver(&info, &ka, regs, NULL);
1001 if (signr > 0) {
1002 /* Whee! Actually deliver the signal. */
1003 handle_signal(signr, &ka, &info, oldset, regs);
1004 return;
1005 }
1006
1007 /* Did we come from a system call? */
1008 if (regs->orig_d0 >= 0)
1009 /* Restart the system call - no handlers present */
1010 handle_restart(regs, NULL, 0);
1011
1012 /* If there's no signal to deliver, we just restore the saved mask. */
1013 if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
1014 clear_thread_flag(TIF_RESTORE_SIGMASK);
1015 sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
1016 }
1017}
diff --git a/arch/m68knommu/kernel/signal.c b/arch/m68k/kernel/signal_no.c
index 36a81bb6835..36a81bb6835 100644
--- a/arch/m68knommu/kernel/signal.c
+++ b/arch/m68k/kernel/signal_no.c
diff --git a/arch/m68k/kernel/sys_m68k.c b/arch/m68k/kernel/sys_m68k.c
index 3db2e7f902a..63013df3358 100644
--- a/arch/m68k/kernel/sys_m68k.c
+++ b/arch/m68k/kernel/sys_m68k.c
@@ -1,546 +1,5 @@
1/* 1#ifdef CONFIG_MMU
2 * linux/arch/m68k/kernel/sys_m68k.c 2#include "sys_m68k_mm.c"
3 * 3#else
4 * This file contains various random system calls that 4#include "sys_m68k_no.c"
5 * have a non-standard calling sequence on the Linux/m68k 5#endif
6 * platform.
7 */
8
9#include <linux/capability.h>
10#include <linux/errno.h>
11#include <linux/sched.h>
12#include <linux/mm.h>
13#include <linux/fs.h>
14#include <linux/smp.h>
15#include <linux/sem.h>
16#include <linux/msg.h>
17#include <linux/shm.h>
18#include <linux/stat.h>
19#include <linux/syscalls.h>
20#include <linux/mman.h>
21#include <linux/file.h>
22#include <linux/ipc.h>
23
24#include <asm/setup.h>
25#include <asm/uaccess.h>
26#include <asm/cachectl.h>
27#include <asm/traps.h>
28#include <asm/page.h>
29#include <asm/unistd.h>
30#include <linux/elf.h>
31#include <asm/tlb.h>
32
33asmlinkage int do_page_fault(struct pt_regs *regs, unsigned long address,
34 unsigned long error_code);
35
36asmlinkage long sys_mmap2(unsigned long addr, unsigned long len,
37 unsigned long prot, unsigned long flags,
38 unsigned long fd, unsigned long pgoff)
39{
40 /*
41 * This is wrong for sun3 - there PAGE_SIZE is 8Kb,
42 * so we need to shift the argument down by 1; m68k mmap64(3)
43 * (in libc) expects the last argument of mmap2 in 4Kb units.
44 */
45 return sys_mmap_pgoff(addr, len, prot, flags, fd, pgoff);
46}
47
48/* Convert virtual (user) address VADDR to physical address PADDR */
49#define virt_to_phys_040(vaddr) \
50({ \
51 unsigned long _mmusr, _paddr; \
52 \
53 __asm__ __volatile__ (".chip 68040\n\t" \
54 "ptestr (%1)\n\t" \
55 "movec %%mmusr,%0\n\t" \
56 ".chip 68k" \
57 : "=r" (_mmusr) \
58 : "a" (vaddr)); \
59 _paddr = (_mmusr & MMU_R_040) ? (_mmusr & PAGE_MASK) : 0; \
60 _paddr; \
61})
62
63static inline int
64cache_flush_040 (unsigned long addr, int scope, int cache, unsigned long len)
65{
66 unsigned long paddr, i;
67
68 switch (scope)
69 {
70 case FLUSH_SCOPE_ALL:
71 switch (cache)
72 {
73 case FLUSH_CACHE_DATA:
74 /* This nop is needed for some broken versions of the 68040. */
75 __asm__ __volatile__ ("nop\n\t"
76 ".chip 68040\n\t"
77 "cpusha %dc\n\t"
78 ".chip 68k");
79 break;
80 case FLUSH_CACHE_INSN:
81 __asm__ __volatile__ ("nop\n\t"
82 ".chip 68040\n\t"
83 "cpusha %ic\n\t"
84 ".chip 68k");
85 break;
86 default:
87 case FLUSH_CACHE_BOTH:
88 __asm__ __volatile__ ("nop\n\t"
89 ".chip 68040\n\t"
90 "cpusha %bc\n\t"
91 ".chip 68k");
92 break;
93 }
94 break;
95
96 case FLUSH_SCOPE_LINE:
97 /* Find the physical address of the first mapped page in the
98 address range. */
99 if ((paddr = virt_to_phys_040(addr))) {
100 paddr += addr & ~(PAGE_MASK | 15);
101 len = (len + (addr & 15) + 15) >> 4;
102 } else {
103 unsigned long tmp = PAGE_SIZE - (addr & ~PAGE_MASK);
104
105 if (len <= tmp)
106 return 0;
107 addr += tmp;
108 len -= tmp;
109 tmp = PAGE_SIZE;
110 for (;;)
111 {
112 if ((paddr = virt_to_phys_040(addr)))
113 break;
114 if (len <= tmp)
115 return 0;
116 addr += tmp;
117 len -= tmp;
118 }
119 len = (len + 15) >> 4;
120 }
121 i = (PAGE_SIZE - (paddr & ~PAGE_MASK)) >> 4;
122 while (len--)
123 {
124 switch (cache)
125 {
126 case FLUSH_CACHE_DATA:
127 __asm__ __volatile__ ("nop\n\t"
128 ".chip 68040\n\t"
129 "cpushl %%dc,(%0)\n\t"
130 ".chip 68k"
131 : : "a" (paddr));
132 break;
133 case FLUSH_CACHE_INSN:
134 __asm__ __volatile__ ("nop\n\t"
135 ".chip 68040\n\t"
136 "cpushl %%ic,(%0)\n\t"
137 ".chip 68k"
138 : : "a" (paddr));
139 break;
140 default:
141 case FLUSH_CACHE_BOTH:
142 __asm__ __volatile__ ("nop\n\t"
143 ".chip 68040\n\t"
144 "cpushl %%bc,(%0)\n\t"
145 ".chip 68k"
146 : : "a" (paddr));
147 break;
148 }
149 if (!--i && len)
150 {
151 /*
152 * No need to page align here since it is done by
153 * virt_to_phys_040().
154 */
155 addr += PAGE_SIZE;
156 i = PAGE_SIZE / 16;
157 /* Recompute physical address when crossing a page
158 boundary. */
159 for (;;)
160 {
161 if ((paddr = virt_to_phys_040(addr)))
162 break;
163 if (len <= i)
164 return 0;
165 len -= i;
166 addr += PAGE_SIZE;
167 }
168 }
169 else
170 paddr += 16;
171 }
172 break;
173
174 default:
175 case FLUSH_SCOPE_PAGE:
176 len += (addr & ~PAGE_MASK) + (PAGE_SIZE - 1);
177 for (len >>= PAGE_SHIFT; len--; addr += PAGE_SIZE)
178 {
179 if (!(paddr = virt_to_phys_040(addr)))
180 continue;
181 switch (cache)
182 {
183 case FLUSH_CACHE_DATA:
184 __asm__ __volatile__ ("nop\n\t"
185 ".chip 68040\n\t"
186 "cpushp %%dc,(%0)\n\t"
187 ".chip 68k"
188 : : "a" (paddr));
189 break;
190 case FLUSH_CACHE_INSN:
191 __asm__ __volatile__ ("nop\n\t"
192 ".chip 68040\n\t"
193 "cpushp %%ic,(%0)\n\t"
194 ".chip 68k"
195 : : "a" (paddr));
196 break;
197 default:
198 case FLUSH_CACHE_BOTH:
199 __asm__ __volatile__ ("nop\n\t"
200 ".chip 68040\n\t"
201 "cpushp %%bc,(%0)\n\t"
202 ".chip 68k"
203 : : "a" (paddr));
204 break;
205 }
206 }
207 break;
208 }
209 return 0;
210}
211
212#define virt_to_phys_060(vaddr) \
213({ \
214 unsigned long paddr; \
215 __asm__ __volatile__ (".chip 68060\n\t" \
216 "plpar (%0)\n\t" \
217 ".chip 68k" \
218 : "=a" (paddr) \
219 : "0" (vaddr)); \
220 (paddr); /* XXX */ \
221})
222
223static inline int
224cache_flush_060 (unsigned long addr, int scope, int cache, unsigned long len)
225{
226 unsigned long paddr, i;
227
228 /*
229 * 68060 manual says:
230 * cpush %dc : flush DC, remains valid (with our %cacr setup)
231 * cpush %ic : invalidate IC
232 * cpush %bc : flush DC + invalidate IC
233 */
234 switch (scope)
235 {
236 case FLUSH_SCOPE_ALL:
237 switch (cache)
238 {
239 case FLUSH_CACHE_DATA:
240 __asm__ __volatile__ (".chip 68060\n\t"
241 "cpusha %dc\n\t"
242 ".chip 68k");
243 break;
244 case FLUSH_CACHE_INSN:
245 __asm__ __volatile__ (".chip 68060\n\t"
246 "cpusha %ic\n\t"
247 ".chip 68k");
248 break;
249 default:
250 case FLUSH_CACHE_BOTH:
251 __asm__ __volatile__ (".chip 68060\n\t"
252 "cpusha %bc\n\t"
253 ".chip 68k");
254 break;
255 }
256 break;
257
258 case FLUSH_SCOPE_LINE:
259 /* Find the physical address of the first mapped page in the
260 address range. */
261 len += addr & 15;
262 addr &= -16;
263 if (!(paddr = virt_to_phys_060(addr))) {
264 unsigned long tmp = PAGE_SIZE - (addr & ~PAGE_MASK);
265
266 if (len <= tmp)
267 return 0;
268 addr += tmp;
269 len -= tmp;
270 tmp = PAGE_SIZE;
271 for (;;)
272 {
273 if ((paddr = virt_to_phys_060(addr)))
274 break;
275 if (len <= tmp)
276 return 0;
277 addr += tmp;
278 len -= tmp;
279 }
280 }
281 len = (len + 15) >> 4;
282 i = (PAGE_SIZE - (paddr & ~PAGE_MASK)) >> 4;
283 while (len--)
284 {
285 switch (cache)
286 {
287 case FLUSH_CACHE_DATA:
288 __asm__ __volatile__ (".chip 68060\n\t"
289 "cpushl %%dc,(%0)\n\t"
290 ".chip 68k"
291 : : "a" (paddr));
292 break;
293 case FLUSH_CACHE_INSN:
294 __asm__ __volatile__ (".chip 68060\n\t"
295 "cpushl %%ic,(%0)\n\t"
296 ".chip 68k"
297 : : "a" (paddr));
298 break;
299 default:
300 case FLUSH_CACHE_BOTH:
301 __asm__ __volatile__ (".chip 68060\n\t"
302 "cpushl %%bc,(%0)\n\t"
303 ".chip 68k"
304 : : "a" (paddr));
305 break;
306 }
307 if (!--i && len)
308 {
309
310 /*
311 * We just want to jump to the first cache line
312 * in the next page.
313 */
314 addr += PAGE_SIZE;
315 addr &= PAGE_MASK;
316
317 i = PAGE_SIZE / 16;
318 /* Recompute physical address when crossing a page
319 boundary. */
320 for (;;)
321 {
322 if ((paddr = virt_to_phys_060(addr)))
323 break;
324 if (len <= i)
325 return 0;
326 len -= i;
327 addr += PAGE_SIZE;
328 }
329 }
330 else
331 paddr += 16;
332 }
333 break;
334
335 default:
336 case FLUSH_SCOPE_PAGE:
337 len += (addr & ~PAGE_MASK) + (PAGE_SIZE - 1);
338 addr &= PAGE_MASK; /* Workaround for bug in some
339 revisions of the 68060 */
340 for (len >>= PAGE_SHIFT; len--; addr += PAGE_SIZE)
341 {
342 if (!(paddr = virt_to_phys_060(addr)))
343 continue;
344 switch (cache)
345 {
346 case FLUSH_CACHE_DATA:
347 __asm__ __volatile__ (".chip 68060\n\t"
348 "cpushp %%dc,(%0)\n\t"
349 ".chip 68k"
350 : : "a" (paddr));
351 break;
352 case FLUSH_CACHE_INSN:
353 __asm__ __volatile__ (".chip 68060\n\t"
354 "cpushp %%ic,(%0)\n\t"
355 ".chip 68k"
356 : : "a" (paddr));
357 break;
358 default:
359 case FLUSH_CACHE_BOTH:
360 __asm__ __volatile__ (".chip 68060\n\t"
361 "cpushp %%bc,(%0)\n\t"
362 ".chip 68k"
363 : : "a" (paddr));
364 break;
365 }
366 }
367 break;
368 }
369 return 0;
370}
371
372/* sys_cacheflush -- flush (part of) the processor cache. */
373asmlinkage int
374sys_cacheflush (unsigned long addr, int scope, int cache, unsigned long len)
375{
376 struct vm_area_struct *vma;
377 int ret = -EINVAL;
378
379 if (scope < FLUSH_SCOPE_LINE || scope > FLUSH_SCOPE_ALL ||
380 cache & ~FLUSH_CACHE_BOTH)
381 goto out;
382
383 if (scope == FLUSH_SCOPE_ALL) {
384 /* Only the superuser may explicitly flush the whole cache. */
385 ret = -EPERM;
386 if (!capable(CAP_SYS_ADMIN))
387 goto out;
388 } else {
389 /*
390 * Verify that the specified address region actually belongs
391 * to this process.
392 */
393 vma = find_vma (current->mm, addr);
394 ret = -EINVAL;
395 /* Check for overflow. */
396 if (addr + len < addr)
397 goto out;
398 if (vma == NULL || addr < vma->vm_start || addr + len > vma->vm_end)
399 goto out;
400 }
401
402 if (CPU_IS_020_OR_030) {
403 if (scope == FLUSH_SCOPE_LINE && len < 256) {
404 unsigned long cacr;
405 __asm__ ("movec %%cacr, %0" : "=r" (cacr));
406 if (cache & FLUSH_CACHE_INSN)
407 cacr |= 4;
408 if (cache & FLUSH_CACHE_DATA)
409 cacr |= 0x400;
410 len >>= 2;
411 while (len--) {
412 __asm__ __volatile__ ("movec %1, %%caar\n\t"
413 "movec %0, %%cacr"
414 : /* no outputs */
415 : "r" (cacr), "r" (addr));
416 addr += 4;
417 }
418 } else {
419 /* Flush the whole cache, even if page granularity requested. */
420 unsigned long cacr;
421 __asm__ ("movec %%cacr, %0" : "=r" (cacr));
422 if (cache & FLUSH_CACHE_INSN)
423 cacr |= 8;
424 if (cache & FLUSH_CACHE_DATA)
425 cacr |= 0x800;
426 __asm__ __volatile__ ("movec %0, %%cacr" : : "r" (cacr));
427 }
428 ret = 0;
429 goto out;
430 } else {
431 /*
432 * 040 or 060: don't blindly trust 'scope', someone could
433 * try to flush a few megs of memory.
434 */
435
436 if (len>=3*PAGE_SIZE && scope<FLUSH_SCOPE_PAGE)
437 scope=FLUSH_SCOPE_PAGE;
438 if (len>=10*PAGE_SIZE && scope<FLUSH_SCOPE_ALL)
439 scope=FLUSH_SCOPE_ALL;
440 if (CPU_IS_040) {
441 ret = cache_flush_040 (addr, scope, cache, len);
442 } else if (CPU_IS_060) {
443 ret = cache_flush_060 (addr, scope, cache, len);
444 }
445 }
446out:
447 return ret;
448}
449
450asmlinkage int sys_getpagesize(void)
451{
452 return PAGE_SIZE;
453}
454
455/*
456 * Do a system call from kernel instead of calling sys_execve so we
457 * end up with proper pt_regs.
458 */
459int kernel_execve(const char *filename,
460 const char *const argv[],
461 const char *const envp[])
462{
463 register long __res asm ("%d0") = __NR_execve;
464 register long __a asm ("%d1") = (long)(filename);
465 register long __b asm ("%d2") = (long)(argv);
466 register long __c asm ("%d3") = (long)(envp);
467 asm volatile ("trap #0" : "+d" (__res)
468 : "d" (__a), "d" (__b), "d" (__c));
469 return __res;
470}
471
472asmlinkage unsigned long sys_get_thread_area(void)
473{
474 return current_thread_info()->tp_value;
475}
476
477asmlinkage int sys_set_thread_area(unsigned long tp)
478{
479 current_thread_info()->tp_value = tp;
480 return 0;
481}
482
483/* This syscall gets its arguments in A0 (mem), D2 (oldval) and
484 D1 (newval). */
485asmlinkage int
486sys_atomic_cmpxchg_32(unsigned long newval, int oldval, int d3, int d4, int d5,
487 unsigned long __user * mem)
488{
489 /* This was borrowed from ARM's implementation. */
490 for (;;) {
491 struct mm_struct *mm = current->mm;
492 pgd_t *pgd;
493 pmd_t *pmd;
494 pte_t *pte;
495 spinlock_t *ptl;
496 unsigned long mem_value;
497
498 down_read(&mm->mmap_sem);
499 pgd = pgd_offset(mm, (unsigned long)mem);
500 if (!pgd_present(*pgd))
501 goto bad_access;
502 pmd = pmd_offset(pgd, (unsigned long)mem);
503 if (!pmd_present(*pmd))
504 goto bad_access;
505 pte = pte_offset_map_lock(mm, pmd, (unsigned long)mem, &ptl);
506 if (!pte_present(*pte) || !pte_dirty(*pte)
507 || !pte_write(*pte)) {
508 pte_unmap_unlock(pte, ptl);
509 goto bad_access;
510 }
511
512 mem_value = *mem;
513 if (mem_value == oldval)
514 *mem = newval;
515
516 pte_unmap_unlock(pte, ptl);
517 up_read(&mm->mmap_sem);
518 return mem_value;
519
520 bad_access:
521 up_read(&mm->mmap_sem);
522 /* This is not necessarily a bad access, we can get here if
523 a memory we're trying to write to should be copied-on-write.
524 Make the kernel do the necessary page stuff, then re-iterate.
525 Simulate a write access fault to do that. */
526 {
527 /* The first argument of the function corresponds to
528 D1, which is the first field of struct pt_regs. */
529 struct pt_regs *fp = (struct pt_regs *)&newval;
530
531 /* '3' is an RMW flag. */
532 if (do_page_fault(fp, (unsigned long)mem, 3))
533 /* If the do_page_fault() failed, we don't
534 have anything meaningful to return.
535 There should be a SIGSEGV pending for
536 the process. */
537 return 0xdeadbeef;
538 }
539 }
540}
541
542asmlinkage int sys_atomic_barrier(void)
543{
544 /* no code needed for uniprocs */
545 return 0;
546}
diff --git a/arch/m68k/kernel/sys_m68k_mm.c b/arch/m68k/kernel/sys_m68k_mm.c
new file mode 100644
index 00000000000..3db2e7f902a
--- /dev/null
+++ b/arch/m68k/kernel/sys_m68k_mm.c
@@ -0,0 +1,546 @@
1/*
2 * linux/arch/m68k/kernel/sys_m68k.c
3 *
4 * This file contains various random system calls that
5 * have a non-standard calling sequence on the Linux/m68k
6 * platform.
7 */
8
9#include <linux/capability.h>
10#include <linux/errno.h>
11#include <linux/sched.h>
12#include <linux/mm.h>
13#include <linux/fs.h>
14#include <linux/smp.h>
15#include <linux/sem.h>
16#include <linux/msg.h>
17#include <linux/shm.h>
18#include <linux/stat.h>
19#include <linux/syscalls.h>
20#include <linux/mman.h>
21#include <linux/file.h>
22#include <linux/ipc.h>
23
24#include <asm/setup.h>
25#include <asm/uaccess.h>
26#include <asm/cachectl.h>
27#include <asm/traps.h>
28#include <asm/page.h>
29#include <asm/unistd.h>
30#include <linux/elf.h>
31#include <asm/tlb.h>
32
33asmlinkage int do_page_fault(struct pt_regs *regs, unsigned long address,
34 unsigned long error_code);
35
36asmlinkage long sys_mmap2(unsigned long addr, unsigned long len,
37 unsigned long prot, unsigned long flags,
38 unsigned long fd, unsigned long pgoff)
39{
40 /*
41 * This is wrong for sun3 - there PAGE_SIZE is 8Kb,
42 * so we need to shift the argument down by 1; m68k mmap64(3)
43 * (in libc) expects the last argument of mmap2 in 4Kb units.
44 */
45 return sys_mmap_pgoff(addr, len, prot, flags, fd, pgoff);
46}
47
48/* Convert virtual (user) address VADDR to physical address PADDR */
49#define virt_to_phys_040(vaddr) \
50({ \
51 unsigned long _mmusr, _paddr; \
52 \
53 __asm__ __volatile__ (".chip 68040\n\t" \
54 "ptestr (%1)\n\t" \
55 "movec %%mmusr,%0\n\t" \
56 ".chip 68k" \
57 : "=r" (_mmusr) \
58 : "a" (vaddr)); \
59 _paddr = (_mmusr & MMU_R_040) ? (_mmusr & PAGE_MASK) : 0; \
60 _paddr; \
61})
62
63static inline int
64cache_flush_040 (unsigned long addr, int scope, int cache, unsigned long len)
65{
66 unsigned long paddr, i;
67
68 switch (scope)
69 {
70 case FLUSH_SCOPE_ALL:
71 switch (cache)
72 {
73 case FLUSH_CACHE_DATA:
74 /* This nop is needed for some broken versions of the 68040. */
75 __asm__ __volatile__ ("nop\n\t"
76 ".chip 68040\n\t"
77 "cpusha %dc\n\t"
78 ".chip 68k");
79 break;
80 case FLUSH_CACHE_INSN:
81 __asm__ __volatile__ ("nop\n\t"
82 ".chip 68040\n\t"
83 "cpusha %ic\n\t"
84 ".chip 68k");
85 break;
86 default:
87 case FLUSH_CACHE_BOTH:
88 __asm__ __volatile__ ("nop\n\t"
89 ".chip 68040\n\t"
90 "cpusha %bc\n\t"
91 ".chip 68k");
92 break;
93 }
94 break;
95
96 case FLUSH_SCOPE_LINE:
97 /* Find the physical address of the first mapped page in the
98 address range. */
99 if ((paddr = virt_to_phys_040(addr))) {
100 paddr += addr & ~(PAGE_MASK | 15);
101 len = (len + (addr & 15) + 15) >> 4;
102 } else {
103 unsigned long tmp = PAGE_SIZE - (addr & ~PAGE_MASK);
104
105 if (len <= tmp)
106 return 0;
107 addr += tmp;
108 len -= tmp;
109 tmp = PAGE_SIZE;
110 for (;;)
111 {
112 if ((paddr = virt_to_phys_040(addr)))
113 break;
114 if (len <= tmp)
115 return 0;
116 addr += tmp;
117 len -= tmp;
118 }
119 len = (len + 15) >> 4;
120 }
121 i = (PAGE_SIZE - (paddr & ~PAGE_MASK)) >> 4;
122 while (len--)
123 {
124 switch (cache)
125 {
126 case FLUSH_CACHE_DATA:
127 __asm__ __volatile__ ("nop\n\t"
128 ".chip 68040\n\t"
129 "cpushl %%dc,(%0)\n\t"
130 ".chip 68k"
131 : : "a" (paddr));
132 break;
133 case FLUSH_CACHE_INSN:
134 __asm__ __volatile__ ("nop\n\t"
135 ".chip 68040\n\t"
136 "cpushl %%ic,(%0)\n\t"
137 ".chip 68k"
138 : : "a" (paddr));
139 break;
140 default:
141 case FLUSH_CACHE_BOTH:
142 __asm__ __volatile__ ("nop\n\t"
143 ".chip 68040\n\t"
144 "cpushl %%bc,(%0)\n\t"
145 ".chip 68k"
146 : : "a" (paddr));
147 break;
148 }
149 if (!--i && len)
150 {
151 /*
152 * No need to page align here since it is done by
153 * virt_to_phys_040().
154 */
155 addr += PAGE_SIZE;
156 i = PAGE_SIZE / 16;
157 /* Recompute physical address when crossing a page
158 boundary. */
159 for (;;)
160 {
161 if ((paddr = virt_to_phys_040(addr)))
162 break;
163 if (len <= i)
164 return 0;
165 len -= i;
166 addr += PAGE_SIZE;
167 }
168 }
169 else
170 paddr += 16;
171 }
172 break;
173
174 default:
175 case FLUSH_SCOPE_PAGE:
176 len += (addr & ~PAGE_MASK) + (PAGE_SIZE - 1);
177 for (len >>= PAGE_SHIFT; len--; addr += PAGE_SIZE)
178 {
179 if (!(paddr = virt_to_phys_040(addr)))
180 continue;
181 switch (cache)
182 {
183 case FLUSH_CACHE_DATA:
184 __asm__ __volatile__ ("nop\n\t"
185 ".chip 68040\n\t"
186 "cpushp %%dc,(%0)\n\t"
187 ".chip 68k"
188 : : "a" (paddr));
189 break;
190 case FLUSH_CACHE_INSN:
191 __asm__ __volatile__ ("nop\n\t"
192 ".chip 68040\n\t"
193 "cpushp %%ic,(%0)\n\t"
194 ".chip 68k"
195 : : "a" (paddr));
196 break;
197 default:
198 case FLUSH_CACHE_BOTH:
199 __asm__ __volatile__ ("nop\n\t"
200 ".chip 68040\n\t"
201 "cpushp %%bc,(%0)\n\t"
202 ".chip 68k"
203 : : "a" (paddr));
204 break;
205 }
206 }
207 break;
208 }
209 return 0;
210}
211
212#define virt_to_phys_060(vaddr) \
213({ \
214 unsigned long paddr; \
215 __asm__ __volatile__ (".chip 68060\n\t" \
216 "plpar (%0)\n\t" \
217 ".chip 68k" \
218 : "=a" (paddr) \
219 : "0" (vaddr)); \
220 (paddr); /* XXX */ \
221})
222
223static inline int
224cache_flush_060 (unsigned long addr, int scope, int cache, unsigned long len)
225{
226 unsigned long paddr, i;
227
228 /*
229 * 68060 manual says:
230 * cpush %dc : flush DC, remains valid (with our %cacr setup)
231 * cpush %ic : invalidate IC
232 * cpush %bc : flush DC + invalidate IC
233 */
234 switch (scope)
235 {
236 case FLUSH_SCOPE_ALL:
237 switch (cache)
238 {
239 case FLUSH_CACHE_DATA:
240 __asm__ __volatile__ (".chip 68060\n\t"
241 "cpusha %dc\n\t"
242 ".chip 68k");
243 break;
244 case FLUSH_CACHE_INSN:
245 __asm__ __volatile__ (".chip 68060\n\t"
246 "cpusha %ic\n\t"
247 ".chip 68k");
248 break;
249 default:
250 case FLUSH_CACHE_BOTH:
251 __asm__ __volatile__ (".chip 68060\n\t"
252 "cpusha %bc\n\t"
253 ".chip 68k");
254 break;
255 }
256 break;
257
258 case FLUSH_SCOPE_LINE:
259 /* Find the physical address of the first mapped page in the
260 address range. */
261 len += addr & 15;
262 addr &= -16;
263 if (!(paddr = virt_to_phys_060(addr))) {
264 unsigned long tmp = PAGE_SIZE - (addr & ~PAGE_MASK);
265
266 if (len <= tmp)
267 return 0;
268 addr += tmp;
269 len -= tmp;
270 tmp = PAGE_SIZE;
271 for (;;)
272 {
273 if ((paddr = virt_to_phys_060(addr)))
274 break;
275 if (len <= tmp)
276 return 0;
277 addr += tmp;
278 len -= tmp;
279 }
280 }
281 len = (len + 15) >> 4;
282 i = (PAGE_SIZE - (paddr & ~PAGE_MASK)) >> 4;
283 while (len--)
284 {
285 switch (cache)
286 {
287 case FLUSH_CACHE_DATA:
288 __asm__ __volatile__ (".chip 68060\n\t"
289 "cpushl %%dc,(%0)\n\t"
290 ".chip 68k"
291 : : "a" (paddr));
292 break;
293 case FLUSH_CACHE_INSN:
294 __asm__ __volatile__ (".chip 68060\n\t"
295 "cpushl %%ic,(%0)\n\t"
296 ".chip 68k"
297 : : "a" (paddr));
298 break;
299 default:
300 case FLUSH_CACHE_BOTH:
301 __asm__ __volatile__ (".chip 68060\n\t"
302 "cpushl %%bc,(%0)\n\t"
303 ".chip 68k"
304 : : "a" (paddr));
305 break;
306 }
307 if (!--i && len)
308 {
309
310 /*
311 * We just want to jump to the first cache line
312 * in the next page.
313 */
314 addr += PAGE_SIZE;
315 addr &= PAGE_MASK;
316
317 i = PAGE_SIZE / 16;
318 /* Recompute physical address when crossing a page
319 boundary. */
320 for (;;)
321 {
322 if ((paddr = virt_to_phys_060(addr)))
323 break;
324 if (len <= i)
325 return 0;
326 len -= i;
327 addr += PAGE_SIZE;
328 }
329 }
330 else
331 paddr += 16;
332 }
333 break;
334
335 default:
336 case FLUSH_SCOPE_PAGE:
337 len += (addr & ~PAGE_MASK) + (PAGE_SIZE - 1);
338 addr &= PAGE_MASK; /* Workaround for bug in some
339 revisions of the 68060 */
340 for (len >>= PAGE_SHIFT; len--; addr += PAGE_SIZE)
341 {
342 if (!(paddr = virt_to_phys_060(addr)))
343 continue;
344 switch (cache)
345 {
346 case FLUSH_CACHE_DATA:
347 __asm__ __volatile__ (".chip 68060\n\t"
348 "cpushp %%dc,(%0)\n\t"
349 ".chip 68k"
350 : : "a" (paddr));
351 break;
352 case FLUSH_CACHE_INSN:
353 __asm__ __volatile__ (".chip 68060\n\t"
354 "cpushp %%ic,(%0)\n\t"
355 ".chip 68k"
356 : : "a" (paddr));
357 break;
358 default:
359 case FLUSH_CACHE_BOTH:
360 __asm__ __volatile__ (".chip 68060\n\t"
361 "cpushp %%bc,(%0)\n\t"
362 ".chip 68k"
363 : : "a" (paddr));
364 break;
365 }
366 }
367 break;
368 }
369 return 0;
370}
371
372/* sys_cacheflush -- flush (part of) the processor cache. */
373asmlinkage int
374sys_cacheflush (unsigned long addr, int scope, int cache, unsigned long len)
375{
376 struct vm_area_struct *vma;
377 int ret = -EINVAL;
378
379 if (scope < FLUSH_SCOPE_LINE || scope > FLUSH_SCOPE_ALL ||
380 cache & ~FLUSH_CACHE_BOTH)
381 goto out;
382
383 if (scope == FLUSH_SCOPE_ALL) {
384 /* Only the superuser may explicitly flush the whole cache. */
385 ret = -EPERM;
386 if (!capable(CAP_SYS_ADMIN))
387 goto out;
388 } else {
389 /*
390 * Verify that the specified address region actually belongs
391 * to this process.
392 */
393 vma = find_vma (current->mm, addr);
394 ret = -EINVAL;
395 /* Check for overflow. */
396 if (addr + len < addr)
397 goto out;
398 if (vma == NULL || addr < vma->vm_start || addr + len > vma->vm_end)
399 goto out;
400 }
401
402 if (CPU_IS_020_OR_030) {
403 if (scope == FLUSH_SCOPE_LINE && len < 256) {
404 unsigned long cacr;
405 __asm__ ("movec %%cacr, %0" : "=r" (cacr));
406 if (cache & FLUSH_CACHE_INSN)
407 cacr |= 4;
408 if (cache & FLUSH_CACHE_DATA)
409 cacr |= 0x400;
410 len >>= 2;
411 while (len--) {
412 __asm__ __volatile__ ("movec %1, %%caar\n\t"
413 "movec %0, %%cacr"
414 : /* no outputs */
415 : "r" (cacr), "r" (addr));
416 addr += 4;
417 }
418 } else {
419 /* Flush the whole cache, even if page granularity requested. */
420 unsigned long cacr;
421 __asm__ ("movec %%cacr, %0" : "=r" (cacr));
422 if (cache & FLUSH_CACHE_INSN)
423 cacr |= 8;
424 if (cache & FLUSH_CACHE_DATA)
425 cacr |= 0x800;
426 __asm__ __volatile__ ("movec %0, %%cacr" : : "r" (cacr));
427 }
428 ret = 0;
429 goto out;
430 } else {
431 /*
432 * 040 or 060: don't blindly trust 'scope', someone could
433 * try to flush a few megs of memory.
434 */
435
436 if (len>=3*PAGE_SIZE && scope<FLUSH_SCOPE_PAGE)
437 scope=FLUSH_SCOPE_PAGE;
438 if (len>=10*PAGE_SIZE && scope<FLUSH_SCOPE_ALL)
439 scope=FLUSH_SCOPE_ALL;
440 if (CPU_IS_040) {
441 ret = cache_flush_040 (addr, scope, cache, len);
442 } else if (CPU_IS_060) {
443 ret = cache_flush_060 (addr, scope, cache, len);
444 }
445 }
446out:
447 return ret;
448}
449
450asmlinkage int sys_getpagesize(void)
451{
452 return PAGE_SIZE;
453}
454
455/*
456 * Do a system call from kernel instead of calling sys_execve so we
457 * end up with proper pt_regs.
458 */
459int kernel_execve(const char *filename,
460 const char *const argv[],
461 const char *const envp[])
462{
463 register long __res asm ("%d0") = __NR_execve;
464 register long __a asm ("%d1") = (long)(filename);
465 register long __b asm ("%d2") = (long)(argv);
466 register long __c asm ("%d3") = (long)(envp);
467 asm volatile ("trap #0" : "+d" (__res)
468 : "d" (__a), "d" (__b), "d" (__c));
469 return __res;
470}
471
472asmlinkage unsigned long sys_get_thread_area(void)
473{
474 return current_thread_info()->tp_value;
475}
476
477asmlinkage int sys_set_thread_area(unsigned long tp)
478{
479 current_thread_info()->tp_value = tp;
480 return 0;
481}
482
483/* This syscall gets its arguments in A0 (mem), D2 (oldval) and
484 D1 (newval). */
485asmlinkage int
486sys_atomic_cmpxchg_32(unsigned long newval, int oldval, int d3, int d4, int d5,
487 unsigned long __user * mem)
488{
489 /* This was borrowed from ARM's implementation. */
490 for (;;) {
491 struct mm_struct *mm = current->mm;
492 pgd_t *pgd;
493 pmd_t *pmd;
494 pte_t *pte;
495 spinlock_t *ptl;
496 unsigned long mem_value;
497
498 down_read(&mm->mmap_sem);
499 pgd = pgd_offset(mm, (unsigned long)mem);
500 if (!pgd_present(*pgd))
501 goto bad_access;
502 pmd = pmd_offset(pgd, (unsigned long)mem);
503 if (!pmd_present(*pmd))
504 goto bad_access;
505 pte = pte_offset_map_lock(mm, pmd, (unsigned long)mem, &ptl);
506 if (!pte_present(*pte) || !pte_dirty(*pte)
507 || !pte_write(*pte)) {
508 pte_unmap_unlock(pte, ptl);
509 goto bad_access;
510 }
511
512 mem_value = *mem;
513 if (mem_value == oldval)
514 *mem = newval;
515
516 pte_unmap_unlock(pte, ptl);
517 up_read(&mm->mmap_sem);
518 return mem_value;
519
520 bad_access:
521 up_read(&mm->mmap_sem);
522 /* This is not necessarily a bad access, we can get here if
523 a memory we're trying to write to should be copied-on-write.
524 Make the kernel do the necessary page stuff, then re-iterate.
525 Simulate a write access fault to do that. */
526 {
527 /* The first argument of the function corresponds to
528 D1, which is the first field of struct pt_regs. */
529 struct pt_regs *fp = (struct pt_regs *)&newval;
530
531 /* '3' is an RMW flag. */
532 if (do_page_fault(fp, (unsigned long)mem, 3))
533 /* If the do_page_fault() failed, we don't
534 have anything meaningful to return.
535 There should be a SIGSEGV pending for
536 the process. */
537 return 0xdeadbeef;
538 }
539 }
540}
541
542asmlinkage int sys_atomic_barrier(void)
543{
544 /* no code needed for uniprocs */
545 return 0;
546}
diff --git a/arch/m68knommu/kernel/sys_m68k.c b/arch/m68k/kernel/sys_m68k_no.c
index 68488ae47f0..68488ae47f0 100644
--- a/arch/m68knommu/kernel/sys_m68k.c
+++ b/arch/m68k/kernel/sys_m68k_no.c
diff --git a/arch/m68knommu/kernel/syscalltable.S b/arch/m68k/kernel/syscalltable.S
index 79b1ed198c0..79b1ed198c0 100644
--- a/arch/m68knommu/kernel/syscalltable.S
+++ b/arch/m68k/kernel/syscalltable.S
diff --git a/arch/m68k/kernel/time.c b/arch/m68k/kernel/time.c
index 18b34ee5db3..a5cf40c26de 100644
--- a/arch/m68k/kernel/time.c
+++ b/arch/m68k/kernel/time.c
@@ -1,114 +1,5 @@
1/* 1#ifdef CONFIG_MMU
2 * linux/arch/m68k/kernel/time.c 2#include "time_mm.c"
3 * 3#else
4 * Copyright (C) 1991, 1992, 1995 Linus Torvalds 4#include "time_no.c"
5 * 5#endif
6 * This file contains the m68k-specific time handling details.
7 * Most of the stuff is located in the machine specific files.
8 *
9 * 1997-09-10 Updated NTP code according to technical memorandum Jan '96
10 * "A Kernel Model for Precision Timekeeping" by Dave Mills
11 */
12
13#include <linux/errno.h>
14#include <linux/module.h>
15#include <linux/sched.h>
16#include <linux/kernel.h>
17#include <linux/param.h>
18#include <linux/string.h>
19#include <linux/mm.h>
20#include <linux/rtc.h>
21#include <linux/platform_device.h>
22
23#include <asm/machdep.h>
24#include <asm/io.h>
25#include <asm/irq_regs.h>
26
27#include <linux/time.h>
28#include <linux/timex.h>
29#include <linux/profile.h>
30
31static inline int set_rtc_mmss(unsigned long nowtime)
32{
33 if (mach_set_clock_mmss)
34 return mach_set_clock_mmss (nowtime);
35 return -1;
36}
37
38/*
39 * timer_interrupt() needs to keep up the real-time clock,
40 * as well as call the "xtime_update()" routine every clocktick
41 */
42static irqreturn_t timer_interrupt(int irq, void *dummy)
43{
44 xtime_update(1);
45 update_process_times(user_mode(get_irq_regs()));
46 profile_tick(CPU_PROFILING);
47
48#ifdef CONFIG_HEARTBEAT
49 /* use power LED as a heartbeat instead -- much more useful
50 for debugging -- based on the version for PReP by Cort */
51 /* acts like an actual heart beat -- ie thump-thump-pause... */
52 if (mach_heartbeat) {
53 static unsigned cnt = 0, period = 0, dist = 0;
54
55 if (cnt == 0 || cnt == dist)
56 mach_heartbeat( 1 );
57 else if (cnt == 7 || cnt == dist+7)
58 mach_heartbeat( 0 );
59
60 if (++cnt > period) {
61 cnt = 0;
62 /* The hyperbolic function below modifies the heartbeat period
63 * length in dependency of the current (5min) load. It goes
64 * through the points f(0)=126, f(1)=86, f(5)=51,
65 * f(inf)->30. */
66 period = ((672<<FSHIFT)/(5*avenrun[0]+(7<<FSHIFT))) + 30;
67 dist = period / 4;
68 }
69 }
70#endif /* CONFIG_HEARTBEAT */
71 return IRQ_HANDLED;
72}
73
74void read_persistent_clock(struct timespec *ts)
75{
76 struct rtc_time time;
77 ts->tv_sec = 0;
78 ts->tv_nsec = 0;
79
80 if (mach_hwclk) {
81 mach_hwclk(0, &time);
82
83 if ((time.tm_year += 1900) < 1970)
84 time.tm_year += 100;
85 ts->tv_sec = mktime(time.tm_year, time.tm_mon, time.tm_mday,
86 time.tm_hour, time.tm_min, time.tm_sec);
87 }
88}
89
90void __init time_init(void)
91{
92 mach_sched_init(timer_interrupt);
93}
94
95u32 arch_gettimeoffset(void)
96{
97 return mach_gettimeoffset() * 1000;
98}
99
100static int __init rtc_init(void)
101{
102 struct platform_device *pdev;
103
104 if (!mach_hwclk)
105 return -ENODEV;
106
107 pdev = platform_device_register_simple("rtc-generic", -1, NULL, 0);
108 if (IS_ERR(pdev))
109 return PTR_ERR(pdev);
110
111 return 0;
112}
113
114module_init(rtc_init);
diff --git a/arch/m68k/kernel/time_mm.c b/arch/m68k/kernel/time_mm.c
new file mode 100644
index 00000000000..18b34ee5db3
--- /dev/null
+++ b/arch/m68k/kernel/time_mm.c
@@ -0,0 +1,114 @@
1/*
2 * linux/arch/m68k/kernel/time.c
3 *
4 * Copyright (C) 1991, 1992, 1995 Linus Torvalds
5 *
6 * This file contains the m68k-specific time handling details.
7 * Most of the stuff is located in the machine specific files.
8 *
9 * 1997-09-10 Updated NTP code according to technical memorandum Jan '96
10 * "A Kernel Model for Precision Timekeeping" by Dave Mills
11 */
12
13#include <linux/errno.h>
14#include <linux/module.h>
15#include <linux/sched.h>
16#include <linux/kernel.h>
17#include <linux/param.h>
18#include <linux/string.h>
19#include <linux/mm.h>
20#include <linux/rtc.h>
21#include <linux/platform_device.h>
22
23#include <asm/machdep.h>
24#include <asm/io.h>
25#include <asm/irq_regs.h>
26
27#include <linux/time.h>
28#include <linux/timex.h>
29#include <linux/profile.h>
30
31static inline int set_rtc_mmss(unsigned long nowtime)
32{
33 if (mach_set_clock_mmss)
34 return mach_set_clock_mmss (nowtime);
35 return -1;
36}
37
38/*
39 * timer_interrupt() needs to keep up the real-time clock,
40 * as well as call the "xtime_update()" routine every clocktick
41 */
42static irqreturn_t timer_interrupt(int irq, void *dummy)
43{
44 xtime_update(1);
45 update_process_times(user_mode(get_irq_regs()));
46 profile_tick(CPU_PROFILING);
47
48#ifdef CONFIG_HEARTBEAT
49 /* use power LED as a heartbeat instead -- much more useful
50 for debugging -- based on the version for PReP by Cort */
51 /* acts like an actual heart beat -- ie thump-thump-pause... */
52 if (mach_heartbeat) {
53 static unsigned cnt = 0, period = 0, dist = 0;
54
55 if (cnt == 0 || cnt == dist)
56 mach_heartbeat( 1 );
57 else if (cnt == 7 || cnt == dist+7)
58 mach_heartbeat( 0 );
59
60 if (++cnt > period) {
61 cnt = 0;
62 /* The hyperbolic function below modifies the heartbeat period
63 * length in dependency of the current (5min) load. It goes
64 * through the points f(0)=126, f(1)=86, f(5)=51,
65 * f(inf)->30. */
66 period = ((672<<FSHIFT)/(5*avenrun[0]+(7<<FSHIFT))) + 30;
67 dist = period / 4;
68 }
69 }
70#endif /* CONFIG_HEARTBEAT */
71 return IRQ_HANDLED;
72}
73
74void read_persistent_clock(struct timespec *ts)
75{
76 struct rtc_time time;
77 ts->tv_sec = 0;
78 ts->tv_nsec = 0;
79
80 if (mach_hwclk) {
81 mach_hwclk(0, &time);
82
83 if ((time.tm_year += 1900) < 1970)
84 time.tm_year += 100;
85 ts->tv_sec = mktime(time.tm_year, time.tm_mon, time.tm_mday,
86 time.tm_hour, time.tm_min, time.tm_sec);
87 }
88}
89
90void __init time_init(void)
91{
92 mach_sched_init(timer_interrupt);
93}
94
95u32 arch_gettimeoffset(void)
96{
97 return mach_gettimeoffset() * 1000;
98}
99
100static int __init rtc_init(void)
101{
102 struct platform_device *pdev;
103
104 if (!mach_hwclk)
105 return -ENODEV;
106
107 pdev = platform_device_register_simple("rtc-generic", -1, NULL, 0);
108 if (IS_ERR(pdev))
109 return PTR_ERR(pdev);
110
111 return 0;
112}
113
114module_init(rtc_init);
diff --git a/arch/m68knommu/kernel/time.c b/arch/m68k/kernel/time_no.c
index 6623909f70e..6623909f70e 100644
--- a/arch/m68knommu/kernel/time.c
+++ b/arch/m68k/kernel/time_no.c
diff --git a/arch/m68k/kernel/traps.c b/arch/m68k/kernel/traps.c
index 4022bbc2887..c98add3f5f0 100644
--- a/arch/m68k/kernel/traps.c
+++ b/arch/m68k/kernel/traps.c
@@ -1,1207 +1,5 @@
1/* 1#ifdef CONFIG_MMU
2 * linux/arch/m68k/kernel/traps.c 2#include "traps_mm.c"
3 *
4 * Copyright (C) 1993, 1994 by Hamish Macdonald
5 *
6 * 68040 fixes by Michael Rausch
7 * 68040 fixes by Martin Apel
8 * 68040 fixes and writeback by Richard Zidlicky
9 * 68060 fixes by Roman Hodek
10 * 68060 fixes by Jesper Skov
11 *
12 * This file is subject to the terms and conditions of the GNU General Public
13 * License. See the file COPYING in the main directory of this archive
14 * for more details.
15 */
16
17/*
18 * Sets up all exception vectors
19 */
20
21#include <linux/sched.h>
22#include <linux/signal.h>
23#include <linux/kernel.h>
24#include <linux/mm.h>
25#include <linux/module.h>
26#include <linux/user.h>
27#include <linux/string.h>
28#include <linux/linkage.h>
29#include <linux/init.h>
30#include <linux/ptrace.h>
31#include <linux/kallsyms.h>
32
33#include <asm/setup.h>
34#include <asm/fpu.h>
35#include <asm/system.h>
36#include <asm/uaccess.h>
37#include <asm/traps.h>
38#include <asm/pgalloc.h>
39#include <asm/machdep.h>
40#include <asm/siginfo.h>
41
42/* assembler routines */
43asmlinkage void system_call(void);
44asmlinkage void buserr(void);
45asmlinkage void trap(void);
46asmlinkage void nmihandler(void);
47#ifdef CONFIG_M68KFPU_EMU
48asmlinkage void fpu_emu(void);
49#endif
50
51e_vector vectors[256];
52
53/* nmi handler for the Amiga */
54asm(".text\n"
55 __ALIGN_STR "\n"
56 "nmihandler: rte");
57
58/*
59 * this must be called very early as the kernel might
60 * use some instruction that are emulated on the 060
61 * and so we're prepared for early probe attempts (e.g. nf_init).
62 */
63void __init base_trap_init(void)
64{
65 if (MACH_IS_SUN3X) {
66 extern e_vector *sun3x_prom_vbr;
67
68 __asm__ volatile ("movec %%vbr, %0" : "=r" (sun3x_prom_vbr));
69 }
70
71 /* setup the exception vector table */
72 __asm__ volatile ("movec %0,%%vbr" : : "r" ((void*)vectors));
73
74 if (CPU_IS_060) {
75 /* set up ISP entry points */
76 asmlinkage void unimp_vec(void) asm ("_060_isp_unimp");
77
78 vectors[VEC_UNIMPII] = unimp_vec;
79 }
80
81 vectors[VEC_BUSERR] = buserr;
82 vectors[VEC_ILLEGAL] = trap;
83 vectors[VEC_SYS] = system_call;
84}
85
86void __init trap_init (void)
87{
88 int i;
89
90 for (i = VEC_SPUR; i <= VEC_INT7; i++)
91 vectors[i] = bad_inthandler;
92
93 for (i = 0; i < VEC_USER; i++)
94 if (!vectors[i])
95 vectors[i] = trap;
96
97 for (i = VEC_USER; i < 256; i++)
98 vectors[i] = bad_inthandler;
99
100#ifdef CONFIG_M68KFPU_EMU
101 if (FPU_IS_EMU)
102 vectors[VEC_LINE11] = fpu_emu;
103#endif
104
105 if (CPU_IS_040 && !FPU_IS_EMU) {
106 /* set up FPSP entry points */
107 asmlinkage void dz_vec(void) asm ("dz");
108 asmlinkage void inex_vec(void) asm ("inex");
109 asmlinkage void ovfl_vec(void) asm ("ovfl");
110 asmlinkage void unfl_vec(void) asm ("unfl");
111 asmlinkage void snan_vec(void) asm ("snan");
112 asmlinkage void operr_vec(void) asm ("operr");
113 asmlinkage void bsun_vec(void) asm ("bsun");
114 asmlinkage void fline_vec(void) asm ("fline");
115 asmlinkage void unsupp_vec(void) asm ("unsupp");
116
117 vectors[VEC_FPDIVZ] = dz_vec;
118 vectors[VEC_FPIR] = inex_vec;
119 vectors[VEC_FPOVER] = ovfl_vec;
120 vectors[VEC_FPUNDER] = unfl_vec;
121 vectors[VEC_FPNAN] = snan_vec;
122 vectors[VEC_FPOE] = operr_vec;
123 vectors[VEC_FPBRUC] = bsun_vec;
124 vectors[VEC_LINE11] = fline_vec;
125 vectors[VEC_FPUNSUP] = unsupp_vec;
126 }
127
128 if (CPU_IS_060 && !FPU_IS_EMU) {
129 /* set up IFPSP entry points */
130 asmlinkage void snan_vec6(void) asm ("_060_fpsp_snan");
131 asmlinkage void operr_vec6(void) asm ("_060_fpsp_operr");
132 asmlinkage void ovfl_vec6(void) asm ("_060_fpsp_ovfl");
133 asmlinkage void unfl_vec6(void) asm ("_060_fpsp_unfl");
134 asmlinkage void dz_vec6(void) asm ("_060_fpsp_dz");
135 asmlinkage void inex_vec6(void) asm ("_060_fpsp_inex");
136 asmlinkage void fline_vec6(void) asm ("_060_fpsp_fline");
137 asmlinkage void unsupp_vec6(void) asm ("_060_fpsp_unsupp");
138 asmlinkage void effadd_vec6(void) asm ("_060_fpsp_effadd");
139
140 vectors[VEC_FPNAN] = snan_vec6;
141 vectors[VEC_FPOE] = operr_vec6;
142 vectors[VEC_FPOVER] = ovfl_vec6;
143 vectors[VEC_FPUNDER] = unfl_vec6;
144 vectors[VEC_FPDIVZ] = dz_vec6;
145 vectors[VEC_FPIR] = inex_vec6;
146 vectors[VEC_LINE11] = fline_vec6;
147 vectors[VEC_FPUNSUP] = unsupp_vec6;
148 vectors[VEC_UNIMPEA] = effadd_vec6;
149 }
150
151 /* if running on an amiga, make the NMI interrupt do nothing */
152 if (MACH_IS_AMIGA) {
153 vectors[VEC_INT7] = nmihandler;
154 }
155}
156
157
158static const char *vec_names[] = {
159 [VEC_RESETSP] = "RESET SP",
160 [VEC_RESETPC] = "RESET PC",
161 [VEC_BUSERR] = "BUS ERROR",
162 [VEC_ADDRERR] = "ADDRESS ERROR",
163 [VEC_ILLEGAL] = "ILLEGAL INSTRUCTION",
164 [VEC_ZERODIV] = "ZERO DIVIDE",
165 [VEC_CHK] = "CHK",
166 [VEC_TRAP] = "TRAPcc",
167 [VEC_PRIV] = "PRIVILEGE VIOLATION",
168 [VEC_TRACE] = "TRACE",
169 [VEC_LINE10] = "LINE 1010",
170 [VEC_LINE11] = "LINE 1111",
171 [VEC_RESV12] = "UNASSIGNED RESERVED 12",
172 [VEC_COPROC] = "COPROCESSOR PROTOCOL VIOLATION",
173 [VEC_FORMAT] = "FORMAT ERROR",
174 [VEC_UNINT] = "UNINITIALIZED INTERRUPT",
175 [VEC_RESV16] = "UNASSIGNED RESERVED 16",
176 [VEC_RESV17] = "UNASSIGNED RESERVED 17",
177 [VEC_RESV18] = "UNASSIGNED RESERVED 18",
178 [VEC_RESV19] = "UNASSIGNED RESERVED 19",
179 [VEC_RESV20] = "UNASSIGNED RESERVED 20",
180 [VEC_RESV21] = "UNASSIGNED RESERVED 21",
181 [VEC_RESV22] = "UNASSIGNED RESERVED 22",
182 [VEC_RESV23] = "UNASSIGNED RESERVED 23",
183 [VEC_SPUR] = "SPURIOUS INTERRUPT",
184 [VEC_INT1] = "LEVEL 1 INT",
185 [VEC_INT2] = "LEVEL 2 INT",
186 [VEC_INT3] = "LEVEL 3 INT",
187 [VEC_INT4] = "LEVEL 4 INT",
188 [VEC_INT5] = "LEVEL 5 INT",
189 [VEC_INT6] = "LEVEL 6 INT",
190 [VEC_INT7] = "LEVEL 7 INT",
191 [VEC_SYS] = "SYSCALL",
192 [VEC_TRAP1] = "TRAP #1",
193 [VEC_TRAP2] = "TRAP #2",
194 [VEC_TRAP3] = "TRAP #3",
195 [VEC_TRAP4] = "TRAP #4",
196 [VEC_TRAP5] = "TRAP #5",
197 [VEC_TRAP6] = "TRAP #6",
198 [VEC_TRAP7] = "TRAP #7",
199 [VEC_TRAP8] = "TRAP #8",
200 [VEC_TRAP9] = "TRAP #9",
201 [VEC_TRAP10] = "TRAP #10",
202 [VEC_TRAP11] = "TRAP #11",
203 [VEC_TRAP12] = "TRAP #12",
204 [VEC_TRAP13] = "TRAP #13",
205 [VEC_TRAP14] = "TRAP #14",
206 [VEC_TRAP15] = "TRAP #15",
207 [VEC_FPBRUC] = "FPCP BSUN",
208 [VEC_FPIR] = "FPCP INEXACT",
209 [VEC_FPDIVZ] = "FPCP DIV BY 0",
210 [VEC_FPUNDER] = "FPCP UNDERFLOW",
211 [VEC_FPOE] = "FPCP OPERAND ERROR",
212 [VEC_FPOVER] = "FPCP OVERFLOW",
213 [VEC_FPNAN] = "FPCP SNAN",
214 [VEC_FPUNSUP] = "FPCP UNSUPPORTED OPERATION",
215 [VEC_MMUCFG] = "MMU CONFIGURATION ERROR",
216 [VEC_MMUILL] = "MMU ILLEGAL OPERATION ERROR",
217 [VEC_MMUACC] = "MMU ACCESS LEVEL VIOLATION ERROR",
218 [VEC_RESV59] = "UNASSIGNED RESERVED 59",
219 [VEC_UNIMPEA] = "UNASSIGNED RESERVED 60",
220 [VEC_UNIMPII] = "UNASSIGNED RESERVED 61",
221 [VEC_RESV62] = "UNASSIGNED RESERVED 62",
222 [VEC_RESV63] = "UNASSIGNED RESERVED 63",
223};
224
225static const char *space_names[] = {
226 [0] = "Space 0",
227 [USER_DATA] = "User Data",
228 [USER_PROGRAM] = "User Program",
229#ifndef CONFIG_SUN3
230 [3] = "Space 3",
231#else 3#else
232 [FC_CONTROL] = "Control", 4#include "traps_no.c"
233#endif
234 [4] = "Space 4",
235 [SUPER_DATA] = "Super Data",
236 [SUPER_PROGRAM] = "Super Program",
237 [CPU_SPACE] = "CPU"
238};
239
240void die_if_kernel(char *,struct pt_regs *,int);
241asmlinkage int do_page_fault(struct pt_regs *regs, unsigned long address,
242 unsigned long error_code);
243int send_fault_sig(struct pt_regs *regs);
244
245asmlinkage void trap_c(struct frame *fp);
246
247#if defined (CONFIG_M68060)
248static inline void access_error060 (struct frame *fp)
249{
250 unsigned long fslw = fp->un.fmt4.pc; /* is really FSLW for access error */
251
252#ifdef DEBUG
253 printk("fslw=%#lx, fa=%#lx\n", fslw, fp->un.fmt4.effaddr);
254#endif
255
256 if (fslw & MMU060_BPE) {
257 /* branch prediction error -> clear branch cache */
258 __asm__ __volatile__ ("movec %/cacr,%/d0\n\t"
259 "orl #0x00400000,%/d0\n\t"
260 "movec %/d0,%/cacr"
261 : : : "d0" );
262 /* return if there's no other error */
263 if (!(fslw & MMU060_ERR_BITS) && !(fslw & MMU060_SEE))
264 return;
265 }
266
267 if (fslw & (MMU060_DESC_ERR | MMU060_WP | MMU060_SP)) {
268 unsigned long errorcode;
269 unsigned long addr = fp->un.fmt4.effaddr;
270
271 if (fslw & MMU060_MA)
272 addr = (addr + PAGE_SIZE - 1) & PAGE_MASK;
273
274 errorcode = 1;
275 if (fslw & MMU060_DESC_ERR) {
276 __flush_tlb040_one(addr);
277 errorcode = 0;
278 }
279 if (fslw & MMU060_W)
280 errorcode |= 2;
281#ifdef DEBUG
282 printk("errorcode = %d\n", errorcode );
283#endif
284 do_page_fault(&fp->ptregs, addr, errorcode);
285 } else if (fslw & (MMU060_SEE)){
286 /* Software Emulation Error.
287 * fault during mem_read/mem_write in ifpsp060/os.S
288 */
289 send_fault_sig(&fp->ptregs);
290 } else if (!(fslw & (MMU060_RE|MMU060_WE)) ||
291 send_fault_sig(&fp->ptregs) > 0) {
292 printk("pc=%#lx, fa=%#lx\n", fp->ptregs.pc, fp->un.fmt4.effaddr);
293 printk( "68060 access error, fslw=%lx\n", fslw );
294 trap_c( fp );
295 }
296}
297#endif /* CONFIG_M68060 */
298
299#if defined (CONFIG_M68040)
300static inline unsigned long probe040(int iswrite, unsigned long addr, int wbs)
301{
302 unsigned long mmusr;
303 mm_segment_t old_fs = get_fs();
304
305 set_fs(MAKE_MM_SEG(wbs));
306
307 if (iswrite)
308 asm volatile (".chip 68040; ptestw (%0); .chip 68k" : : "a" (addr));
309 else
310 asm volatile (".chip 68040; ptestr (%0); .chip 68k" : : "a" (addr));
311
312 asm volatile (".chip 68040; movec %%mmusr,%0; .chip 68k" : "=r" (mmusr));
313
314 set_fs(old_fs);
315
316 return mmusr;
317}
318
319static inline int do_040writeback1(unsigned short wbs, unsigned long wba,
320 unsigned long wbd)
321{
322 int res = 0;
323 mm_segment_t old_fs = get_fs();
324
325 /* set_fs can not be moved, otherwise put_user() may oops */
326 set_fs(MAKE_MM_SEG(wbs));
327
328 switch (wbs & WBSIZ_040) {
329 case BA_SIZE_BYTE:
330 res = put_user(wbd & 0xff, (char __user *)wba);
331 break;
332 case BA_SIZE_WORD:
333 res = put_user(wbd & 0xffff, (short __user *)wba);
334 break;
335 case BA_SIZE_LONG:
336 res = put_user(wbd, (int __user *)wba);
337 break;
338 }
339
340 /* set_fs can not be moved, otherwise put_user() may oops */
341 set_fs(old_fs);
342
343
344#ifdef DEBUG
345 printk("do_040writeback1, res=%d\n",res);
346#endif
347
348 return res;
349}
350
351/* after an exception in a writeback the stack frame corresponding
352 * to that exception is discarded, set a few bits in the old frame
353 * to simulate what it should look like
354 */
355static inline void fix_xframe040(struct frame *fp, unsigned long wba, unsigned short wbs)
356{
357 fp->un.fmt7.faddr = wba;
358 fp->un.fmt7.ssw = wbs & 0xff;
359 if (wba != current->thread.faddr)
360 fp->un.fmt7.ssw |= MA_040;
361}
362
363static inline void do_040writebacks(struct frame *fp)
364{
365 int res = 0;
366#if 0
367 if (fp->un.fmt7.wb1s & WBV_040)
368 printk("access_error040: cannot handle 1st writeback. oops.\n");
369#endif
370
371 if ((fp->un.fmt7.wb2s & WBV_040) &&
372 !(fp->un.fmt7.wb2s & WBTT_040)) {
373 res = do_040writeback1(fp->un.fmt7.wb2s, fp->un.fmt7.wb2a,
374 fp->un.fmt7.wb2d);
375 if (res)
376 fix_xframe040(fp, fp->un.fmt7.wb2a, fp->un.fmt7.wb2s);
377 else
378 fp->un.fmt7.wb2s = 0;
379 }
380
381 /* do the 2nd wb only if the first one was successful (except for a kernel wb) */
382 if (fp->un.fmt7.wb3s & WBV_040 && (!res || fp->un.fmt7.wb3s & 4)) {
383 res = do_040writeback1(fp->un.fmt7.wb3s, fp->un.fmt7.wb3a,
384 fp->un.fmt7.wb3d);
385 if (res)
386 {
387 fix_xframe040(fp, fp->un.fmt7.wb3a, fp->un.fmt7.wb3s);
388
389 fp->un.fmt7.wb2s = fp->un.fmt7.wb3s;
390 fp->un.fmt7.wb3s &= (~WBV_040);
391 fp->un.fmt7.wb2a = fp->un.fmt7.wb3a;
392 fp->un.fmt7.wb2d = fp->un.fmt7.wb3d;
393 }
394 else
395 fp->un.fmt7.wb3s = 0;
396 }
397
398 if (res)
399 send_fault_sig(&fp->ptregs);
400}
401
402/*
403 * called from sigreturn(), must ensure userspace code didn't
404 * manipulate exception frame to circumvent protection, then complete
405 * pending writebacks
406 * we just clear TM2 to turn it into a userspace access
407 */
408asmlinkage void berr_040cleanup(struct frame *fp)
409{
410 fp->un.fmt7.wb2s &= ~4;
411 fp->un.fmt7.wb3s &= ~4;
412
413 do_040writebacks(fp);
414}
415
416static inline void access_error040(struct frame *fp)
417{
418 unsigned short ssw = fp->un.fmt7.ssw;
419 unsigned long mmusr;
420
421#ifdef DEBUG
422 printk("ssw=%#x, fa=%#lx\n", ssw, fp->un.fmt7.faddr);
423 printk("wb1s=%#x, wb2s=%#x, wb3s=%#x\n", fp->un.fmt7.wb1s,
424 fp->un.fmt7.wb2s, fp->un.fmt7.wb3s);
425 printk ("wb2a=%lx, wb3a=%lx, wb2d=%lx, wb3d=%lx\n",
426 fp->un.fmt7.wb2a, fp->un.fmt7.wb3a,
427 fp->un.fmt7.wb2d, fp->un.fmt7.wb3d);
428#endif
429
430 if (ssw & ATC_040) {
431 unsigned long addr = fp->un.fmt7.faddr;
432 unsigned long errorcode;
433
434 /*
435 * The MMU status has to be determined AFTER the address
436 * has been corrected if there was a misaligned access (MA).
437 */
438 if (ssw & MA_040)
439 addr = (addr + 7) & -8;
440
441 /* MMU error, get the MMUSR info for this access */
442 mmusr = probe040(!(ssw & RW_040), addr, ssw);
443#ifdef DEBUG
444 printk("mmusr = %lx\n", mmusr);
445#endif
446 errorcode = 1;
447 if (!(mmusr & MMU_R_040)) {
448 /* clear the invalid atc entry */
449 __flush_tlb040_one(addr);
450 errorcode = 0;
451 }
452
453 /* despite what documentation seems to say, RMW
454 * accesses have always both the LK and RW bits set */
455 if (!(ssw & RW_040) || (ssw & LK_040))
456 errorcode |= 2;
457
458 if (do_page_fault(&fp->ptregs, addr, errorcode)) {
459#ifdef DEBUG
460 printk("do_page_fault() !=0\n");
461#endif
462 if (user_mode(&fp->ptregs)){
463 /* delay writebacks after signal delivery */
464#ifdef DEBUG
465 printk(".. was usermode - return\n");
466#endif
467 return;
468 }
469 /* disable writeback into user space from kernel
470 * (if do_page_fault didn't fix the mapping,
471 * the writeback won't do good)
472 */
473disable_wb:
474#ifdef DEBUG
475 printk(".. disabling wb2\n");
476#endif
477 if (fp->un.fmt7.wb2a == fp->un.fmt7.faddr)
478 fp->un.fmt7.wb2s &= ~WBV_040;
479 if (fp->un.fmt7.wb3a == fp->un.fmt7.faddr)
480 fp->un.fmt7.wb3s &= ~WBV_040;
481 }
482 } else {
483 /* In case of a bus error we either kill the process or expect
484 * the kernel to catch the fault, which then is also responsible
485 * for cleaning up the mess.
486 */
487 current->thread.signo = SIGBUS;
488 current->thread.faddr = fp->un.fmt7.faddr;
489 if (send_fault_sig(&fp->ptregs) >= 0)
490 printk("68040 bus error (ssw=%x, faddr=%lx)\n", ssw,
491 fp->un.fmt7.faddr);
492 goto disable_wb;
493 }
494
495 do_040writebacks(fp);
496}
497#endif /* CONFIG_M68040 */
498
499#if defined(CONFIG_SUN3)
500#include <asm/sun3mmu.h>
501
502extern int mmu_emu_handle_fault (unsigned long, int, int);
503
504/* sun3 version of bus_error030 */
505
506static inline void bus_error030 (struct frame *fp)
507{
508 unsigned char buserr_type = sun3_get_buserr ();
509 unsigned long addr, errorcode;
510 unsigned short ssw = fp->un.fmtb.ssw;
511 extern unsigned long _sun3_map_test_start, _sun3_map_test_end;
512
513#ifdef DEBUG
514 if (ssw & (FC | FB))
515 printk ("Instruction fault at %#010lx\n",
516 ssw & FC ?
517 fp->ptregs.format == 0xa ? fp->ptregs.pc + 2 : fp->un.fmtb.baddr - 2
518 :
519 fp->ptregs.format == 0xa ? fp->ptregs.pc + 4 : fp->un.fmtb.baddr);
520 if (ssw & DF)
521 printk ("Data %s fault at %#010lx in %s (pc=%#lx)\n",
522 ssw & RW ? "read" : "write",
523 fp->un.fmtb.daddr,
524 space_names[ssw & DFC], fp->ptregs.pc);
525#endif
526
527 /*
528 * Check if this page should be demand-mapped. This needs to go before
529 * the testing for a bad kernel-space access (demand-mapping applies
530 * to kernel accesses too).
531 */
532
533 if ((ssw & DF)
534 && (buserr_type & (SUN3_BUSERR_PROTERR | SUN3_BUSERR_INVALID))) {
535 if (mmu_emu_handle_fault (fp->un.fmtb.daddr, ssw & RW, 0))
536 return;
537 }
538
539 /* Check for kernel-space pagefault (BAD). */
540 if (fp->ptregs.sr & PS_S) {
541 /* kernel fault must be a data fault to user space */
542 if (! ((ssw & DF) && ((ssw & DFC) == USER_DATA))) {
543 // try checking the kernel mappings before surrender
544 if (mmu_emu_handle_fault (fp->un.fmtb.daddr, ssw & RW, 1))
545 return;
546 /* instruction fault or kernel data fault! */
547 if (ssw & (FC | FB))
548 printk ("Instruction fault at %#010lx\n",
549 fp->ptregs.pc);
550 if (ssw & DF) {
551 /* was this fault incurred testing bus mappings? */
552 if((fp->ptregs.pc >= (unsigned long)&_sun3_map_test_start) &&
553 (fp->ptregs.pc <= (unsigned long)&_sun3_map_test_end)) {
554 send_fault_sig(&fp->ptregs);
555 return;
556 }
557
558 printk ("Data %s fault at %#010lx in %s (pc=%#lx)\n",
559 ssw & RW ? "read" : "write",
560 fp->un.fmtb.daddr,
561 space_names[ssw & DFC], fp->ptregs.pc);
562 }
563 printk ("BAD KERNEL BUSERR\n");
564
565 die_if_kernel("Oops", &fp->ptregs,0);
566 force_sig(SIGKILL, current);
567 return;
568 }
569 } else {
570 /* user fault */
571 if (!(ssw & (FC | FB)) && !(ssw & DF))
572 /* not an instruction fault or data fault! BAD */
573 panic ("USER BUSERR w/o instruction or data fault");
574 }
575
576
577 /* First handle the data fault, if any. */
578 if (ssw & DF) {
579 addr = fp->un.fmtb.daddr;
580
581// errorcode bit 0: 0 -> no page 1 -> protection fault
582// errorcode bit 1: 0 -> read fault 1 -> write fault
583
584// (buserr_type & SUN3_BUSERR_PROTERR) -> protection fault
585// (buserr_type & SUN3_BUSERR_INVALID) -> invalid page fault
586
587 if (buserr_type & SUN3_BUSERR_PROTERR)
588 errorcode = 0x01;
589 else if (buserr_type & SUN3_BUSERR_INVALID)
590 errorcode = 0x00;
591 else {
592#ifdef DEBUG
593 printk ("*** unexpected busfault type=%#04x\n", buserr_type);
594 printk ("invalid %s access at %#lx from pc %#lx\n",
595 !(ssw & RW) ? "write" : "read", addr,
596 fp->ptregs.pc);
597#endif
598 die_if_kernel ("Oops", &fp->ptregs, buserr_type);
599 force_sig (SIGBUS, current);
600 return;
601 }
602
603//todo: wtf is RM bit? --m
604 if (!(ssw & RW) || ssw & RM)
605 errorcode |= 0x02;
606
607 /* Handle page fault. */
608 do_page_fault (&fp->ptregs, addr, errorcode);
609
610 /* Retry the data fault now. */
611 return;
612 }
613
614 /* Now handle the instruction fault. */
615
616 /* Get the fault address. */
617 if (fp->ptregs.format == 0xA)
618 addr = fp->ptregs.pc + 4;
619 else
620 addr = fp->un.fmtb.baddr;
621 if (ssw & FC)
622 addr -= 2;
623
624 if (buserr_type & SUN3_BUSERR_INVALID) {
625 if (!mmu_emu_handle_fault (fp->un.fmtb.daddr, 1, 0))
626 do_page_fault (&fp->ptregs, addr, 0);
627 } else {
628#ifdef DEBUG
629 printk ("protection fault on insn access (segv).\n");
630#endif
631 force_sig (SIGSEGV, current);
632 }
633}
634#else
635#if defined(CPU_M68020_OR_M68030)
636static inline void bus_error030 (struct frame *fp)
637{
638 volatile unsigned short temp;
639 unsigned short mmusr;
640 unsigned long addr, errorcode;
641 unsigned short ssw = fp->un.fmtb.ssw;
642#ifdef DEBUG
643 unsigned long desc;
644
645 printk ("pid = %x ", current->pid);
646 printk ("SSW=%#06x ", ssw);
647
648 if (ssw & (FC | FB))
649 printk ("Instruction fault at %#010lx\n",
650 ssw & FC ?
651 fp->ptregs.format == 0xa ? fp->ptregs.pc + 2 : fp->un.fmtb.baddr - 2
652 :
653 fp->ptregs.format == 0xa ? fp->ptregs.pc + 4 : fp->un.fmtb.baddr);
654 if (ssw & DF)
655 printk ("Data %s fault at %#010lx in %s (pc=%#lx)\n",
656 ssw & RW ? "read" : "write",
657 fp->un.fmtb.daddr,
658 space_names[ssw & DFC], fp->ptregs.pc);
659#endif
660
661 /* ++andreas: If a data fault and an instruction fault happen
662 at the same time map in both pages. */
663
664 /* First handle the data fault, if any. */
665 if (ssw & DF) {
666 addr = fp->un.fmtb.daddr;
667
668#ifdef DEBUG
669 asm volatile ("ptestr %3,%2@,#7,%0\n\t"
670 "pmove %%psr,%1@"
671 : "=a&" (desc)
672 : "a" (&temp), "a" (addr), "d" (ssw));
673#else
674 asm volatile ("ptestr %2,%1@,#7\n\t"
675 "pmove %%psr,%0@"
676 : : "a" (&temp), "a" (addr), "d" (ssw));
677#endif
678 mmusr = temp;
679
680#ifdef DEBUG
681 printk("mmusr is %#x for addr %#lx in task %p\n",
682 mmusr, addr, current);
683 printk("descriptor address is %#lx, contents %#lx\n",
684 __va(desc), *(unsigned long *)__va(desc));
685#endif
686
687 errorcode = (mmusr & MMU_I) ? 0 : 1;
688 if (!(ssw & RW) || (ssw & RM))
689 errorcode |= 2;
690
691 if (mmusr & (MMU_I | MMU_WP)) {
692 if (ssw & 4) {
693 printk("Data %s fault at %#010lx in %s (pc=%#lx)\n",
694 ssw & RW ? "read" : "write",
695 fp->un.fmtb.daddr,
696 space_names[ssw & DFC], fp->ptregs.pc);
697 goto buserr;
698 }
699 /* Don't try to do anything further if an exception was
700 handled. */
701 if (do_page_fault (&fp->ptregs, addr, errorcode) < 0)
702 return;
703 } else if (!(mmusr & MMU_I)) {
704 /* probably a 020 cas fault */
705 if (!(ssw & RM) && send_fault_sig(&fp->ptregs) > 0)
706 printk("unexpected bus error (%#x,%#x)\n", ssw, mmusr);
707 } else if (mmusr & (MMU_B|MMU_L|MMU_S)) {
708 printk("invalid %s access at %#lx from pc %#lx\n",
709 !(ssw & RW) ? "write" : "read", addr,
710 fp->ptregs.pc);
711 die_if_kernel("Oops",&fp->ptregs,mmusr);
712 force_sig(SIGSEGV, current);
713 return;
714 } else {
715#if 0
716 static volatile long tlong;
717#endif
718
719 printk("weird %s access at %#lx from pc %#lx (ssw is %#x)\n",
720 !(ssw & RW) ? "write" : "read", addr,
721 fp->ptregs.pc, ssw);
722 asm volatile ("ptestr #1,%1@,#0\n\t"
723 "pmove %%psr,%0@"
724 : /* no outputs */
725 : "a" (&temp), "a" (addr));
726 mmusr = temp;
727
728 printk ("level 0 mmusr is %#x\n", mmusr);
729#if 0
730 asm volatile ("pmove %%tt0,%0@"
731 : /* no outputs */
732 : "a" (&tlong));
733 printk("tt0 is %#lx, ", tlong);
734 asm volatile ("pmove %%tt1,%0@"
735 : /* no outputs */
736 : "a" (&tlong));
737 printk("tt1 is %#lx\n", tlong);
738#endif
739#ifdef DEBUG
740 printk("Unknown SIGSEGV - 1\n");
741#endif
742 die_if_kernel("Oops",&fp->ptregs,mmusr);
743 force_sig(SIGSEGV, current);
744 return;
745 }
746
747 /* setup an ATC entry for the access about to be retried */
748 if (!(ssw & RW) || (ssw & RM))
749 asm volatile ("ploadw %1,%0@" : /* no outputs */
750 : "a" (addr), "d" (ssw));
751 else
752 asm volatile ("ploadr %1,%0@" : /* no outputs */
753 : "a" (addr), "d" (ssw));
754 }
755
756 /* Now handle the instruction fault. */
757
758 if (!(ssw & (FC|FB)))
759 return;
760
761 if (fp->ptregs.sr & PS_S) {
762 printk("Instruction fault at %#010lx\n",
763 fp->ptregs.pc);
764 buserr:
765 printk ("BAD KERNEL BUSERR\n");
766 die_if_kernel("Oops",&fp->ptregs,0);
767 force_sig(SIGKILL, current);
768 return;
769 }
770
771 /* get the fault address */
772 if (fp->ptregs.format == 10)
773 addr = fp->ptregs.pc + 4;
774 else
775 addr = fp->un.fmtb.baddr;
776 if (ssw & FC)
777 addr -= 2;
778
779 if ((ssw & DF) && ((addr ^ fp->un.fmtb.daddr) & PAGE_MASK) == 0)
780 /* Insn fault on same page as data fault. But we
781 should still create the ATC entry. */
782 goto create_atc_entry;
783
784#ifdef DEBUG
785 asm volatile ("ptestr #1,%2@,#7,%0\n\t"
786 "pmove %%psr,%1@"
787 : "=a&" (desc)
788 : "a" (&temp), "a" (addr));
789#else
790 asm volatile ("ptestr #1,%1@,#7\n\t"
791 "pmove %%psr,%0@"
792 : : "a" (&temp), "a" (addr));
793#endif
794 mmusr = temp;
795
796#ifdef DEBUG
797 printk ("mmusr is %#x for addr %#lx in task %p\n",
798 mmusr, addr, current);
799 printk ("descriptor address is %#lx, contents %#lx\n",
800 __va(desc), *(unsigned long *)__va(desc));
801#endif
802
803 if (mmusr & MMU_I)
804 do_page_fault (&fp->ptregs, addr, 0);
805 else if (mmusr & (MMU_B|MMU_L|MMU_S)) {
806 printk ("invalid insn access at %#lx from pc %#lx\n",
807 addr, fp->ptregs.pc);
808#ifdef DEBUG
809 printk("Unknown SIGSEGV - 2\n");
810#endif
811 die_if_kernel("Oops",&fp->ptregs,mmusr);
812 force_sig(SIGSEGV, current);
813 return;
814 }
815
816create_atc_entry:
817 /* setup an ATC entry for the access about to be retried */
818 asm volatile ("ploadr #2,%0@" : /* no outputs */
819 : "a" (addr));
820}
821#endif /* CPU_M68020_OR_M68030 */
822#endif /* !CONFIG_SUN3 */
823
824asmlinkage void buserr_c(struct frame *fp)
825{
826 /* Only set esp0 if coming from user mode */
827 if (user_mode(&fp->ptregs))
828 current->thread.esp0 = (unsigned long) fp;
829
830#ifdef DEBUG
831 printk ("*** Bus Error *** Format is %x\n", fp->ptregs.format);
832#endif
833
834 switch (fp->ptregs.format) {
835#if defined (CONFIG_M68060)
836 case 4: /* 68060 access error */
837 access_error060 (fp);
838 break;
839#endif
840#if defined (CONFIG_M68040)
841 case 0x7: /* 68040 access error */
842 access_error040 (fp);
843 break;
844#endif
845#if defined (CPU_M68020_OR_M68030)
846 case 0xa:
847 case 0xb:
848 bus_error030 (fp);
849 break;
850#endif
851 default:
852 die_if_kernel("bad frame format",&fp->ptregs,0);
853#ifdef DEBUG
854 printk("Unknown SIGSEGV - 4\n");
855#endif
856 force_sig(SIGSEGV, current);
857 }
858}
859
860
861static int kstack_depth_to_print = 48;
862
863void show_trace(unsigned long *stack)
864{
865 unsigned long *endstack;
866 unsigned long addr;
867 int i;
868
869 printk("Call Trace:");
870 addr = (unsigned long)stack + THREAD_SIZE - 1;
871 endstack = (unsigned long *)(addr & -THREAD_SIZE);
872 i = 0;
873 while (stack + 1 <= endstack) {
874 addr = *stack++;
875 /*
876 * If the address is either in the text segment of the
877 * kernel, or in the region which contains vmalloc'ed
878 * memory, it *may* be the address of a calling
879 * routine; if so, print it so that someone tracing
880 * down the cause of the crash will be able to figure
881 * out the call path that was taken.
882 */
883 if (__kernel_text_address(addr)) {
884#ifndef CONFIG_KALLSYMS
885 if (i % 5 == 0)
886 printk("\n ");
887#endif
888 printk(" [<%08lx>] %pS\n", addr, (void *)addr);
889 i++;
890 }
891 }
892 printk("\n");
893}
894
895void show_registers(struct pt_regs *regs)
896{
897 struct frame *fp = (struct frame *)regs;
898 mm_segment_t old_fs = get_fs();
899 u16 c, *cp;
900 unsigned long addr;
901 int i;
902
903 print_modules();
904 printk("PC: [<%08lx>] %pS\n", regs->pc, (void *)regs->pc);
905 printk("SR: %04x SP: %p a2: %08lx\n", regs->sr, regs, regs->a2);
906 printk("d0: %08lx d1: %08lx d2: %08lx d3: %08lx\n",
907 regs->d0, regs->d1, regs->d2, regs->d3);
908 printk("d4: %08lx d5: %08lx a0: %08lx a1: %08lx\n",
909 regs->d4, regs->d5, regs->a0, regs->a1);
910
911 printk("Process %s (pid: %d, task=%p)\n",
912 current->comm, task_pid_nr(current), current);
913 addr = (unsigned long)&fp->un;
914 printk("Frame format=%X ", regs->format);
915 switch (regs->format) {
916 case 0x2:
917 printk("instr addr=%08lx\n", fp->un.fmt2.iaddr);
918 addr += sizeof(fp->un.fmt2);
919 break;
920 case 0x3:
921 printk("eff addr=%08lx\n", fp->un.fmt3.effaddr);
922 addr += sizeof(fp->un.fmt3);
923 break;
924 case 0x4:
925 printk((CPU_IS_060 ? "fault addr=%08lx fslw=%08lx\n"
926 : "eff addr=%08lx pc=%08lx\n"),
927 fp->un.fmt4.effaddr, fp->un.fmt4.pc);
928 addr += sizeof(fp->un.fmt4);
929 break;
930 case 0x7:
931 printk("eff addr=%08lx ssw=%04x faddr=%08lx\n",
932 fp->un.fmt7.effaddr, fp->un.fmt7.ssw, fp->un.fmt7.faddr);
933 printk("wb 1 stat/addr/data: %04x %08lx %08lx\n",
934 fp->un.fmt7.wb1s, fp->un.fmt7.wb1a, fp->un.fmt7.wb1dpd0);
935 printk("wb 2 stat/addr/data: %04x %08lx %08lx\n",
936 fp->un.fmt7.wb2s, fp->un.fmt7.wb2a, fp->un.fmt7.wb2d);
937 printk("wb 3 stat/addr/data: %04x %08lx %08lx\n",
938 fp->un.fmt7.wb3s, fp->un.fmt7.wb3a, fp->un.fmt7.wb3d);
939 printk("push data: %08lx %08lx %08lx %08lx\n",
940 fp->un.fmt7.wb1dpd0, fp->un.fmt7.pd1, fp->un.fmt7.pd2,
941 fp->un.fmt7.pd3);
942 addr += sizeof(fp->un.fmt7);
943 break;
944 case 0x9:
945 printk("instr addr=%08lx\n", fp->un.fmt9.iaddr);
946 addr += sizeof(fp->un.fmt9);
947 break;
948 case 0xa:
949 printk("ssw=%04x isc=%04x isb=%04x daddr=%08lx dobuf=%08lx\n",
950 fp->un.fmta.ssw, fp->un.fmta.isc, fp->un.fmta.isb,
951 fp->un.fmta.daddr, fp->un.fmta.dobuf);
952 addr += sizeof(fp->un.fmta);
953 break;
954 case 0xb:
955 printk("ssw=%04x isc=%04x isb=%04x daddr=%08lx dobuf=%08lx\n",
956 fp->un.fmtb.ssw, fp->un.fmtb.isc, fp->un.fmtb.isb,
957 fp->un.fmtb.daddr, fp->un.fmtb.dobuf);
958 printk("baddr=%08lx dibuf=%08lx ver=%x\n",
959 fp->un.fmtb.baddr, fp->un.fmtb.dibuf, fp->un.fmtb.ver);
960 addr += sizeof(fp->un.fmtb);
961 break;
962 default:
963 printk("\n");
964 }
965 show_stack(NULL, (unsigned long *)addr);
966
967 printk("Code:");
968 set_fs(KERNEL_DS);
969 cp = (u16 *)regs->pc;
970 for (i = -8; i < 16; i++) {
971 if (get_user(c, cp + i) && i >= 0) {
972 printk(" Bad PC value.");
973 break;
974 }
975 printk(i ? " %04x" : " <%04x>", c);
976 }
977 set_fs(old_fs);
978 printk ("\n");
979}
980
981void show_stack(struct task_struct *task, unsigned long *stack)
982{
983 unsigned long *p;
984 unsigned long *endstack;
985 int i;
986
987 if (!stack) {
988 if (task)
989 stack = (unsigned long *)task->thread.esp0;
990 else
991 stack = (unsigned long *)&stack;
992 }
993 endstack = (unsigned long *)(((unsigned long)stack + THREAD_SIZE - 1) & -THREAD_SIZE);
994
995 printk("Stack from %08lx:", (unsigned long)stack);
996 p = stack;
997 for (i = 0; i < kstack_depth_to_print; i++) {
998 if (p + 1 > endstack)
999 break;
1000 if (i % 8 == 0)
1001 printk("\n ");
1002 printk(" %08lx", *p++);
1003 }
1004 printk("\n");
1005 show_trace(stack);
1006}
1007
1008/*
1009 * The architecture-independent backtrace generator
1010 */
1011void dump_stack(void)
1012{
1013 unsigned long stack;
1014
1015 show_trace(&stack);
1016}
1017
1018EXPORT_SYMBOL(dump_stack);
1019
1020void bad_super_trap (struct frame *fp)
1021{
1022 console_verbose();
1023 if (fp->ptregs.vector < 4 * ARRAY_SIZE(vec_names))
1024 printk ("*** %s *** FORMAT=%X\n",
1025 vec_names[(fp->ptregs.vector) >> 2],
1026 fp->ptregs.format);
1027 else
1028 printk ("*** Exception %d *** FORMAT=%X\n",
1029 (fp->ptregs.vector) >> 2,
1030 fp->ptregs.format);
1031 if (fp->ptregs.vector >> 2 == VEC_ADDRERR && CPU_IS_020_OR_030) {
1032 unsigned short ssw = fp->un.fmtb.ssw;
1033
1034 printk ("SSW=%#06x ", ssw);
1035
1036 if (ssw & RC)
1037 printk ("Pipe stage C instruction fault at %#010lx\n",
1038 (fp->ptregs.format) == 0xA ?
1039 fp->ptregs.pc + 2 : fp->un.fmtb.baddr - 2);
1040 if (ssw & RB)
1041 printk ("Pipe stage B instruction fault at %#010lx\n",
1042 (fp->ptregs.format) == 0xA ?
1043 fp->ptregs.pc + 4 : fp->un.fmtb.baddr);
1044 if (ssw & DF)
1045 printk ("Data %s fault at %#010lx in %s (pc=%#lx)\n",
1046 ssw & RW ? "read" : "write",
1047 fp->un.fmtb.daddr, space_names[ssw & DFC],
1048 fp->ptregs.pc);
1049 }
1050 printk ("Current process id is %d\n", task_pid_nr(current));
1051 die_if_kernel("BAD KERNEL TRAP", &fp->ptregs, 0);
1052}
1053
1054asmlinkage void trap_c(struct frame *fp)
1055{
1056 int sig;
1057 siginfo_t info;
1058
1059 if (fp->ptregs.sr & PS_S) {
1060 if (fp->ptregs.vector == VEC_TRACE << 2) {
1061 /* traced a trapping instruction on a 68020/30,
1062 * real exception will be executed afterwards.
1063 */
1064 } else if (!handle_kernel_fault(&fp->ptregs))
1065 bad_super_trap(fp);
1066 return;
1067 }
1068
1069 /* send the appropriate signal to the user program */
1070 switch ((fp->ptregs.vector) >> 2) {
1071 case VEC_ADDRERR:
1072 info.si_code = BUS_ADRALN;
1073 sig = SIGBUS;
1074 break;
1075 case VEC_ILLEGAL:
1076 case VEC_LINE10:
1077 case VEC_LINE11:
1078 info.si_code = ILL_ILLOPC;
1079 sig = SIGILL;
1080 break;
1081 case VEC_PRIV:
1082 info.si_code = ILL_PRVOPC;
1083 sig = SIGILL;
1084 break;
1085 case VEC_COPROC:
1086 info.si_code = ILL_COPROC;
1087 sig = SIGILL;
1088 break;
1089 case VEC_TRAP1:
1090 case VEC_TRAP2:
1091 case VEC_TRAP3:
1092 case VEC_TRAP4:
1093 case VEC_TRAP5:
1094 case VEC_TRAP6:
1095 case VEC_TRAP7:
1096 case VEC_TRAP8:
1097 case VEC_TRAP9:
1098 case VEC_TRAP10:
1099 case VEC_TRAP11:
1100 case VEC_TRAP12:
1101 case VEC_TRAP13:
1102 case VEC_TRAP14:
1103 info.si_code = ILL_ILLTRP;
1104 sig = SIGILL;
1105 break;
1106 case VEC_FPBRUC:
1107 case VEC_FPOE:
1108 case VEC_FPNAN:
1109 info.si_code = FPE_FLTINV;
1110 sig = SIGFPE;
1111 break;
1112 case VEC_FPIR:
1113 info.si_code = FPE_FLTRES;
1114 sig = SIGFPE;
1115 break;
1116 case VEC_FPDIVZ:
1117 info.si_code = FPE_FLTDIV;
1118 sig = SIGFPE;
1119 break;
1120 case VEC_FPUNDER:
1121 info.si_code = FPE_FLTUND;
1122 sig = SIGFPE;
1123 break;
1124 case VEC_FPOVER:
1125 info.si_code = FPE_FLTOVF;
1126 sig = SIGFPE;
1127 break;
1128 case VEC_ZERODIV:
1129 info.si_code = FPE_INTDIV;
1130 sig = SIGFPE;
1131 break;
1132 case VEC_CHK:
1133 case VEC_TRAP:
1134 info.si_code = FPE_INTOVF;
1135 sig = SIGFPE;
1136 break;
1137 case VEC_TRACE: /* ptrace single step */
1138 info.si_code = TRAP_TRACE;
1139 sig = SIGTRAP;
1140 break;
1141 case VEC_TRAP15: /* breakpoint */
1142 info.si_code = TRAP_BRKPT;
1143 sig = SIGTRAP;
1144 break;
1145 default:
1146 info.si_code = ILL_ILLOPC;
1147 sig = SIGILL;
1148 break;
1149 }
1150 info.si_signo = sig;
1151 info.si_errno = 0;
1152 switch (fp->ptregs.format) {
1153 default:
1154 info.si_addr = (void *) fp->ptregs.pc;
1155 break;
1156 case 2:
1157 info.si_addr = (void *) fp->un.fmt2.iaddr;
1158 break;
1159 case 7:
1160 info.si_addr = (void *) fp->un.fmt7.effaddr;
1161 break;
1162 case 9:
1163 info.si_addr = (void *) fp->un.fmt9.iaddr;
1164 break;
1165 case 10:
1166 info.si_addr = (void *) fp->un.fmta.daddr;
1167 break;
1168 case 11:
1169 info.si_addr = (void *) fp->un.fmtb.daddr;
1170 break;
1171 }
1172 force_sig_info (sig, &info, current);
1173}
1174
1175void die_if_kernel (char *str, struct pt_regs *fp, int nr)
1176{
1177 if (!(fp->sr & PS_S))
1178 return;
1179
1180 console_verbose();
1181 printk("%s: %08x\n",str,nr);
1182 show_registers(fp);
1183 add_taint(TAINT_DIE);
1184 do_exit(SIGSEGV);
1185}
1186
1187/*
1188 * This function is called if an error occur while accessing
1189 * user-space from the fpsp040 code.
1190 */
1191asmlinkage void fpsp040_die(void)
1192{
1193 do_exit(SIGSEGV);
1194}
1195
1196#ifdef CONFIG_M68KFPU_EMU
1197asmlinkage void fpemu_signal(int signal, int code, void *addr)
1198{
1199 siginfo_t info;
1200
1201 info.si_signo = signal;
1202 info.si_errno = 0;
1203 info.si_code = code;
1204 info.si_addr = addr;
1205 force_sig_info(signal, &info, current);
1206}
1207#endif 5#endif
diff --git a/arch/m68k/kernel/traps_mm.c b/arch/m68k/kernel/traps_mm.c
new file mode 100644
index 00000000000..4022bbc2887
--- /dev/null
+++ b/arch/m68k/kernel/traps_mm.c
@@ -0,0 +1,1207 @@
1/*
2 * linux/arch/m68k/kernel/traps.c
3 *
4 * Copyright (C) 1993, 1994 by Hamish Macdonald
5 *
6 * 68040 fixes by Michael Rausch
7 * 68040 fixes by Martin Apel
8 * 68040 fixes and writeback by Richard Zidlicky
9 * 68060 fixes by Roman Hodek
10 * 68060 fixes by Jesper Skov
11 *
12 * This file is subject to the terms and conditions of the GNU General Public
13 * License. See the file COPYING in the main directory of this archive
14 * for more details.
15 */
16
17/*
18 * Sets up all exception vectors
19 */
20
21#include <linux/sched.h>
22#include <linux/signal.h>
23#include <linux/kernel.h>
24#include <linux/mm.h>
25#include <linux/module.h>
26#include <linux/user.h>
27#include <linux/string.h>
28#include <linux/linkage.h>
29#include <linux/init.h>
30#include <linux/ptrace.h>
31#include <linux/kallsyms.h>
32
33#include <asm/setup.h>
34#include <asm/fpu.h>
35#include <asm/system.h>
36#include <asm/uaccess.h>
37#include <asm/traps.h>
38#include <asm/pgalloc.h>
39#include <asm/machdep.h>
40#include <asm/siginfo.h>
41
42/* assembler routines */
43asmlinkage void system_call(void);
44asmlinkage void buserr(void);
45asmlinkage void trap(void);
46asmlinkage void nmihandler(void);
47#ifdef CONFIG_M68KFPU_EMU
48asmlinkage void fpu_emu(void);
49#endif
50
51e_vector vectors[256];
52
53/* nmi handler for the Amiga */
54asm(".text\n"
55 __ALIGN_STR "\n"
56 "nmihandler: rte");
57
58/*
59 * this must be called very early as the kernel might
60 * use some instruction that are emulated on the 060
61 * and so we're prepared for early probe attempts (e.g. nf_init).
62 */
63void __init base_trap_init(void)
64{
65 if (MACH_IS_SUN3X) {
66 extern e_vector *sun3x_prom_vbr;
67
68 __asm__ volatile ("movec %%vbr, %0" : "=r" (sun3x_prom_vbr));
69 }
70
71 /* setup the exception vector table */
72 __asm__ volatile ("movec %0,%%vbr" : : "r" ((void*)vectors));
73
74 if (CPU_IS_060) {
75 /* set up ISP entry points */
76 asmlinkage void unimp_vec(void) asm ("_060_isp_unimp");
77
78 vectors[VEC_UNIMPII] = unimp_vec;
79 }
80
81 vectors[VEC_BUSERR] = buserr;
82 vectors[VEC_ILLEGAL] = trap;
83 vectors[VEC_SYS] = system_call;
84}
85
86void __init trap_init (void)
87{
88 int i;
89
90 for (i = VEC_SPUR; i <= VEC_INT7; i++)
91 vectors[i] = bad_inthandler;
92
93 for (i = 0; i < VEC_USER; i++)
94 if (!vectors[i])
95 vectors[i] = trap;
96
97 for (i = VEC_USER; i < 256; i++)
98 vectors[i] = bad_inthandler;
99
100#ifdef CONFIG_M68KFPU_EMU
101 if (FPU_IS_EMU)
102 vectors[VEC_LINE11] = fpu_emu;
103#endif
104
105 if (CPU_IS_040 && !FPU_IS_EMU) {
106 /* set up FPSP entry points */
107 asmlinkage void dz_vec(void) asm ("dz");
108 asmlinkage void inex_vec(void) asm ("inex");
109 asmlinkage void ovfl_vec(void) asm ("ovfl");
110 asmlinkage void unfl_vec(void) asm ("unfl");
111 asmlinkage void snan_vec(void) asm ("snan");
112 asmlinkage void operr_vec(void) asm ("operr");
113 asmlinkage void bsun_vec(void) asm ("bsun");
114 asmlinkage void fline_vec(void) asm ("fline");
115 asmlinkage void unsupp_vec(void) asm ("unsupp");
116
117 vectors[VEC_FPDIVZ] = dz_vec;
118 vectors[VEC_FPIR] = inex_vec;
119 vectors[VEC_FPOVER] = ovfl_vec;
120 vectors[VEC_FPUNDER] = unfl_vec;
121 vectors[VEC_FPNAN] = snan_vec;
122 vectors[VEC_FPOE] = operr_vec;
123 vectors[VEC_FPBRUC] = bsun_vec;
124 vectors[VEC_LINE11] = fline_vec;
125 vectors[VEC_FPUNSUP] = unsupp_vec;
126 }
127
128 if (CPU_IS_060 && !FPU_IS_EMU) {
129 /* set up IFPSP entry points */
130 asmlinkage void snan_vec6(void) asm ("_060_fpsp_snan");
131 asmlinkage void operr_vec6(void) asm ("_060_fpsp_operr");
132 asmlinkage void ovfl_vec6(void) asm ("_060_fpsp_ovfl");
133 asmlinkage void unfl_vec6(void) asm ("_060_fpsp_unfl");
134 asmlinkage void dz_vec6(void) asm ("_060_fpsp_dz");
135 asmlinkage void inex_vec6(void) asm ("_060_fpsp_inex");
136 asmlinkage void fline_vec6(void) asm ("_060_fpsp_fline");
137 asmlinkage void unsupp_vec6(void) asm ("_060_fpsp_unsupp");
138 asmlinkage void effadd_vec6(void) asm ("_060_fpsp_effadd");
139
140 vectors[VEC_FPNAN] = snan_vec6;
141 vectors[VEC_FPOE] = operr_vec6;
142 vectors[VEC_FPOVER] = ovfl_vec6;
143 vectors[VEC_FPUNDER] = unfl_vec6;
144 vectors[VEC_FPDIVZ] = dz_vec6;
145 vectors[VEC_FPIR] = inex_vec6;
146 vectors[VEC_LINE11] = fline_vec6;
147 vectors[VEC_FPUNSUP] = unsupp_vec6;
148 vectors[VEC_UNIMPEA] = effadd_vec6;
149 }
150
151 /* if running on an amiga, make the NMI interrupt do nothing */
152 if (MACH_IS_AMIGA) {
153 vectors[VEC_INT7] = nmihandler;
154 }
155}
156
157
158static const char *vec_names[] = {
159 [VEC_RESETSP] = "RESET SP",
160 [VEC_RESETPC] = "RESET PC",
161 [VEC_BUSERR] = "BUS ERROR",
162 [VEC_ADDRERR] = "ADDRESS ERROR",
163 [VEC_ILLEGAL] = "ILLEGAL INSTRUCTION",
164 [VEC_ZERODIV] = "ZERO DIVIDE",
165 [VEC_CHK] = "CHK",
166 [VEC_TRAP] = "TRAPcc",
167 [VEC_PRIV] = "PRIVILEGE VIOLATION",
168 [VEC_TRACE] = "TRACE",
169 [VEC_LINE10] = "LINE 1010",
170 [VEC_LINE11] = "LINE 1111",
171 [VEC_RESV12] = "UNASSIGNED RESERVED 12",
172 [VEC_COPROC] = "COPROCESSOR PROTOCOL VIOLATION",
173 [VEC_FORMAT] = "FORMAT ERROR",
174 [VEC_UNINT] = "UNINITIALIZED INTERRUPT",
175 [VEC_RESV16] = "UNASSIGNED RESERVED 16",
176 [VEC_RESV17] = "UNASSIGNED RESERVED 17",
177 [VEC_RESV18] = "UNASSIGNED RESERVED 18",
178 [VEC_RESV19] = "UNASSIGNED RESERVED 19",
179 [VEC_RESV20] = "UNASSIGNED RESERVED 20",
180 [VEC_RESV21] = "UNASSIGNED RESERVED 21",
181 [VEC_RESV22] = "UNASSIGNED RESERVED 22",
182 [VEC_RESV23] = "UNASSIGNED RESERVED 23",
183 [VEC_SPUR] = "SPURIOUS INTERRUPT",
184 [VEC_INT1] = "LEVEL 1 INT",
185 [VEC_INT2] = "LEVEL 2 INT",
186 [VEC_INT3] = "LEVEL 3 INT",
187 [VEC_INT4] = "LEVEL 4 INT",
188 [VEC_INT5] = "LEVEL 5 INT",
189 [VEC_INT6] = "LEVEL 6 INT",
190 [VEC_INT7] = "LEVEL 7 INT",
191 [VEC_SYS] = "SYSCALL",
192 [VEC_TRAP1] = "TRAP #1",
193 [VEC_TRAP2] = "TRAP #2",
194 [VEC_TRAP3] = "TRAP #3",
195 [VEC_TRAP4] = "TRAP #4",
196 [VEC_TRAP5] = "TRAP #5",
197 [VEC_TRAP6] = "TRAP #6",
198 [VEC_TRAP7] = "TRAP #7",
199 [VEC_TRAP8] = "TRAP #8",
200 [VEC_TRAP9] = "TRAP #9",
201 [VEC_TRAP10] = "TRAP #10",
202 [VEC_TRAP11] = "TRAP #11",
203 [VEC_TRAP12] = "TRAP #12",
204 [VEC_TRAP13] = "TRAP #13",
205 [VEC_TRAP14] = "TRAP #14",
206 [VEC_TRAP15] = "TRAP #15",
207 [VEC_FPBRUC] = "FPCP BSUN",
208 [VEC_FPIR] = "FPCP INEXACT",
209 [VEC_FPDIVZ] = "FPCP DIV BY 0",
210 [VEC_FPUNDER] = "FPCP UNDERFLOW",
211 [VEC_FPOE] = "FPCP OPERAND ERROR",
212 [VEC_FPOVER] = "FPCP OVERFLOW",
213 [VEC_FPNAN] = "FPCP SNAN",
214 [VEC_FPUNSUP] = "FPCP UNSUPPORTED OPERATION",
215 [VEC_MMUCFG] = "MMU CONFIGURATION ERROR",
216 [VEC_MMUILL] = "MMU ILLEGAL OPERATION ERROR",
217 [VEC_MMUACC] = "MMU ACCESS LEVEL VIOLATION ERROR",
218 [VEC_RESV59] = "UNASSIGNED RESERVED 59",
219 [VEC_UNIMPEA] = "UNASSIGNED RESERVED 60",
220 [VEC_UNIMPII] = "UNASSIGNED RESERVED 61",
221 [VEC_RESV62] = "UNASSIGNED RESERVED 62",
222 [VEC_RESV63] = "UNASSIGNED RESERVED 63",
223};
224
225static const char *space_names[] = {
226 [0] = "Space 0",
227 [USER_DATA] = "User Data",
228 [USER_PROGRAM] = "User Program",
229#ifndef CONFIG_SUN3
230 [3] = "Space 3",
231#else
232 [FC_CONTROL] = "Control",
233#endif
234 [4] = "Space 4",
235 [SUPER_DATA] = "Super Data",
236 [SUPER_PROGRAM] = "Super Program",
237 [CPU_SPACE] = "CPU"
238};
239
240void die_if_kernel(char *,struct pt_regs *,int);
241asmlinkage int do_page_fault(struct pt_regs *regs, unsigned long address,
242 unsigned long error_code);
243int send_fault_sig(struct pt_regs *regs);
244
245asmlinkage void trap_c(struct frame *fp);
246
247#if defined (CONFIG_M68060)
248static inline void access_error060 (struct frame *fp)
249{
250 unsigned long fslw = fp->un.fmt4.pc; /* is really FSLW for access error */
251
252#ifdef DEBUG
253 printk("fslw=%#lx, fa=%#lx\n", fslw, fp->un.fmt4.effaddr);
254#endif
255
256 if (fslw & MMU060_BPE) {
257 /* branch prediction error -> clear branch cache */
258 __asm__ __volatile__ ("movec %/cacr,%/d0\n\t"
259 "orl #0x00400000,%/d0\n\t"
260 "movec %/d0,%/cacr"
261 : : : "d0" );
262 /* return if there's no other error */
263 if (!(fslw & MMU060_ERR_BITS) && !(fslw & MMU060_SEE))
264 return;
265 }
266
267 if (fslw & (MMU060_DESC_ERR | MMU060_WP | MMU060_SP)) {
268 unsigned long errorcode;
269 unsigned long addr = fp->un.fmt4.effaddr;
270
271 if (fslw & MMU060_MA)
272 addr = (addr + PAGE_SIZE - 1) & PAGE_MASK;
273
274 errorcode = 1;
275 if (fslw & MMU060_DESC_ERR) {
276 __flush_tlb040_one(addr);
277 errorcode = 0;
278 }
279 if (fslw & MMU060_W)
280 errorcode |= 2;
281#ifdef DEBUG
282 printk("errorcode = %d\n", errorcode );
283#endif
284 do_page_fault(&fp->ptregs, addr, errorcode);
285 } else if (fslw & (MMU060_SEE)){
286 /* Software Emulation Error.
287 * fault during mem_read/mem_write in ifpsp060/os.S
288 */
289 send_fault_sig(&fp->ptregs);
290 } else if (!(fslw & (MMU060_RE|MMU060_WE)) ||
291 send_fault_sig(&fp->ptregs) > 0) {
292 printk("pc=%#lx, fa=%#lx\n", fp->ptregs.pc, fp->un.fmt4.effaddr);
293 printk( "68060 access error, fslw=%lx\n", fslw );
294 trap_c( fp );
295 }
296}
297#endif /* CONFIG_M68060 */
298
299#if defined (CONFIG_M68040)
300static inline unsigned long probe040(int iswrite, unsigned long addr, int wbs)
301{
302 unsigned long mmusr;
303 mm_segment_t old_fs = get_fs();
304
305 set_fs(MAKE_MM_SEG(wbs));
306
307 if (iswrite)
308 asm volatile (".chip 68040; ptestw (%0); .chip 68k" : : "a" (addr));
309 else
310 asm volatile (".chip 68040; ptestr (%0); .chip 68k" : : "a" (addr));
311
312 asm volatile (".chip 68040; movec %%mmusr,%0; .chip 68k" : "=r" (mmusr));
313
314 set_fs(old_fs);
315
316 return mmusr;
317}
318
319static inline int do_040writeback1(unsigned short wbs, unsigned long wba,
320 unsigned long wbd)
321{
322 int res = 0;
323 mm_segment_t old_fs = get_fs();
324
325 /* set_fs can not be moved, otherwise put_user() may oops */
326 set_fs(MAKE_MM_SEG(wbs));
327
328 switch (wbs & WBSIZ_040) {
329 case BA_SIZE_BYTE:
330 res = put_user(wbd & 0xff, (char __user *)wba);
331 break;
332 case BA_SIZE_WORD:
333 res = put_user(wbd & 0xffff, (short __user *)wba);
334 break;
335 case BA_SIZE_LONG:
336 res = put_user(wbd, (int __user *)wba);
337 break;
338 }
339
340 /* set_fs can not be moved, otherwise put_user() may oops */
341 set_fs(old_fs);
342
343
344#ifdef DEBUG
345 printk("do_040writeback1, res=%d\n",res);
346#endif
347
348 return res;
349}
350
351/* after an exception in a writeback the stack frame corresponding
352 * to that exception is discarded, set a few bits in the old frame
353 * to simulate what it should look like
354 */
355static inline void fix_xframe040(struct frame *fp, unsigned long wba, unsigned short wbs)
356{
357 fp->un.fmt7.faddr = wba;
358 fp->un.fmt7.ssw = wbs & 0xff;
359 if (wba != current->thread.faddr)
360 fp->un.fmt7.ssw |= MA_040;
361}
362
363static inline void do_040writebacks(struct frame *fp)
364{
365 int res = 0;
366#if 0
367 if (fp->un.fmt7.wb1s & WBV_040)
368 printk("access_error040: cannot handle 1st writeback. oops.\n");
369#endif
370
371 if ((fp->un.fmt7.wb2s & WBV_040) &&
372 !(fp->un.fmt7.wb2s & WBTT_040)) {
373 res = do_040writeback1(fp->un.fmt7.wb2s, fp->un.fmt7.wb2a,
374 fp->un.fmt7.wb2d);
375 if (res)
376 fix_xframe040(fp, fp->un.fmt7.wb2a, fp->un.fmt7.wb2s);
377 else
378 fp->un.fmt7.wb2s = 0;
379 }
380
381 /* do the 2nd wb only if the first one was successful (except for a kernel wb) */
382 if (fp->un.fmt7.wb3s & WBV_040 && (!res || fp->un.fmt7.wb3s & 4)) {
383 res = do_040writeback1(fp->un.fmt7.wb3s, fp->un.fmt7.wb3a,
384 fp->un.fmt7.wb3d);
385 if (res)
386 {
387 fix_xframe040(fp, fp->un.fmt7.wb3a, fp->un.fmt7.wb3s);
388
389 fp->un.fmt7.wb2s = fp->un.fmt7.wb3s;
390 fp->un.fmt7.wb3s &= (~WBV_040);
391 fp->un.fmt7.wb2a = fp->un.fmt7.wb3a;
392 fp->un.fmt7.wb2d = fp->un.fmt7.wb3d;
393 }
394 else
395 fp->un.fmt7.wb3s = 0;
396 }
397
398 if (res)
399 send_fault_sig(&fp->ptregs);
400}
401
402/*
403 * called from sigreturn(), must ensure userspace code didn't
404 * manipulate exception frame to circumvent protection, then complete
405 * pending writebacks
406 * we just clear TM2 to turn it into a userspace access
407 */
408asmlinkage void berr_040cleanup(struct frame *fp)
409{
410 fp->un.fmt7.wb2s &= ~4;
411 fp->un.fmt7.wb3s &= ~4;
412
413 do_040writebacks(fp);
414}
415
416static inline void access_error040(struct frame *fp)
417{
418 unsigned short ssw = fp->un.fmt7.ssw;
419 unsigned long mmusr;
420
421#ifdef DEBUG
422 printk("ssw=%#x, fa=%#lx\n", ssw, fp->un.fmt7.faddr);
423 printk("wb1s=%#x, wb2s=%#x, wb3s=%#x\n", fp->un.fmt7.wb1s,
424 fp->un.fmt7.wb2s, fp->un.fmt7.wb3s);
425 printk ("wb2a=%lx, wb3a=%lx, wb2d=%lx, wb3d=%lx\n",
426 fp->un.fmt7.wb2a, fp->un.fmt7.wb3a,
427 fp->un.fmt7.wb2d, fp->un.fmt7.wb3d);
428#endif
429
430 if (ssw & ATC_040) {
431 unsigned long addr = fp->un.fmt7.faddr;
432 unsigned long errorcode;
433
434 /*
435 * The MMU status has to be determined AFTER the address
436 * has been corrected if there was a misaligned access (MA).
437 */
438 if (ssw & MA_040)
439 addr = (addr + 7) & -8;
440
441 /* MMU error, get the MMUSR info for this access */
442 mmusr = probe040(!(ssw & RW_040), addr, ssw);
443#ifdef DEBUG
444 printk("mmusr = %lx\n", mmusr);
445#endif
446 errorcode = 1;
447 if (!(mmusr & MMU_R_040)) {
448 /* clear the invalid atc entry */
449 __flush_tlb040_one(addr);
450 errorcode = 0;
451 }
452
453 /* despite what documentation seems to say, RMW
454 * accesses have always both the LK and RW bits set */
455 if (!(ssw & RW_040) || (ssw & LK_040))
456 errorcode |= 2;
457
458 if (do_page_fault(&fp->ptregs, addr, errorcode)) {
459#ifdef DEBUG
460 printk("do_page_fault() !=0\n");
461#endif
462 if (user_mode(&fp->ptregs)){
463 /* delay writebacks after signal delivery */
464#ifdef DEBUG
465 printk(".. was usermode - return\n");
466#endif
467 return;
468 }
469 /* disable writeback into user space from kernel
470 * (if do_page_fault didn't fix the mapping,
471 * the writeback won't do good)
472 */
473disable_wb:
474#ifdef DEBUG
475 printk(".. disabling wb2\n");
476#endif
477 if (fp->un.fmt7.wb2a == fp->un.fmt7.faddr)
478 fp->un.fmt7.wb2s &= ~WBV_040;
479 if (fp->un.fmt7.wb3a == fp->un.fmt7.faddr)
480 fp->un.fmt7.wb3s &= ~WBV_040;
481 }
482 } else {
483 /* In case of a bus error we either kill the process or expect
484 * the kernel to catch the fault, which then is also responsible
485 * for cleaning up the mess.
486 */
487 current->thread.signo = SIGBUS;
488 current->thread.faddr = fp->un.fmt7.faddr;
489 if (send_fault_sig(&fp->ptregs) >= 0)
490 printk("68040 bus error (ssw=%x, faddr=%lx)\n", ssw,
491 fp->un.fmt7.faddr);
492 goto disable_wb;
493 }
494
495 do_040writebacks(fp);
496}
497#endif /* CONFIG_M68040 */
498
499#if defined(CONFIG_SUN3)
500#include <asm/sun3mmu.h>
501
502extern int mmu_emu_handle_fault (unsigned long, int, int);
503
504/* sun3 version of bus_error030 */
505
506static inline void bus_error030 (struct frame *fp)
507{
508 unsigned char buserr_type = sun3_get_buserr ();
509 unsigned long addr, errorcode;
510 unsigned short ssw = fp->un.fmtb.ssw;
511 extern unsigned long _sun3_map_test_start, _sun3_map_test_end;
512
513#ifdef DEBUG
514 if (ssw & (FC | FB))
515 printk ("Instruction fault at %#010lx\n",
516 ssw & FC ?
517 fp->ptregs.format == 0xa ? fp->ptregs.pc + 2 : fp->un.fmtb.baddr - 2
518 :
519 fp->ptregs.format == 0xa ? fp->ptregs.pc + 4 : fp->un.fmtb.baddr);
520 if (ssw & DF)
521 printk ("Data %s fault at %#010lx in %s (pc=%#lx)\n",
522 ssw & RW ? "read" : "write",
523 fp->un.fmtb.daddr,
524 space_names[ssw & DFC], fp->ptregs.pc);
525#endif
526
527 /*
528 * Check if this page should be demand-mapped. This needs to go before
529 * the testing for a bad kernel-space access (demand-mapping applies
530 * to kernel accesses too).
531 */
532
533 if ((ssw & DF)
534 && (buserr_type & (SUN3_BUSERR_PROTERR | SUN3_BUSERR_INVALID))) {
535 if (mmu_emu_handle_fault (fp->un.fmtb.daddr, ssw & RW, 0))
536 return;
537 }
538
539 /* Check for kernel-space pagefault (BAD). */
540 if (fp->ptregs.sr & PS_S) {
541 /* kernel fault must be a data fault to user space */
542 if (! ((ssw & DF) && ((ssw & DFC) == USER_DATA))) {
543 // try checking the kernel mappings before surrender
544 if (mmu_emu_handle_fault (fp->un.fmtb.daddr, ssw & RW, 1))
545 return;
546 /* instruction fault or kernel data fault! */
547 if (ssw & (FC | FB))
548 printk ("Instruction fault at %#010lx\n",
549 fp->ptregs.pc);
550 if (ssw & DF) {
551 /* was this fault incurred testing bus mappings? */
552 if((fp->ptregs.pc >= (unsigned long)&_sun3_map_test_start) &&
553 (fp->ptregs.pc <= (unsigned long)&_sun3_map_test_end)) {
554 send_fault_sig(&fp->ptregs);
555 return;
556 }
557
558 printk ("Data %s fault at %#010lx in %s (pc=%#lx)\n",
559 ssw & RW ? "read" : "write",
560 fp->un.fmtb.daddr,
561 space_names[ssw & DFC], fp->ptregs.pc);
562 }
563 printk ("BAD KERNEL BUSERR\n");
564
565 die_if_kernel("Oops", &fp->ptregs,0);
566 force_sig(SIGKILL, current);
567 return;
568 }
569 } else {
570 /* user fault */
571 if (!(ssw & (FC | FB)) && !(ssw & DF))
572 /* not an instruction fault or data fault! BAD */
573 panic ("USER BUSERR w/o instruction or data fault");
574 }
575
576
577 /* First handle the data fault, if any. */
578 if (ssw & DF) {
579 addr = fp->un.fmtb.daddr;
580
581// errorcode bit 0: 0 -> no page 1 -> protection fault
582// errorcode bit 1: 0 -> read fault 1 -> write fault
583
584// (buserr_type & SUN3_BUSERR_PROTERR) -> protection fault
585// (buserr_type & SUN3_BUSERR_INVALID) -> invalid page fault
586
587 if (buserr_type & SUN3_BUSERR_PROTERR)
588 errorcode = 0x01;
589 else if (buserr_type & SUN3_BUSERR_INVALID)
590 errorcode = 0x00;
591 else {
592#ifdef DEBUG
593 printk ("*** unexpected busfault type=%#04x\n", buserr_type);
594 printk ("invalid %s access at %#lx from pc %#lx\n",
595 !(ssw & RW) ? "write" : "read", addr,
596 fp->ptregs.pc);
597#endif
598 die_if_kernel ("Oops", &fp->ptregs, buserr_type);
599 force_sig (SIGBUS, current);
600 return;
601 }
602
603//todo: wtf is RM bit? --m
604 if (!(ssw & RW) || ssw & RM)
605 errorcode |= 0x02;
606
607 /* Handle page fault. */
608 do_page_fault (&fp->ptregs, addr, errorcode);
609
610 /* Retry the data fault now. */
611 return;
612 }
613
614 /* Now handle the instruction fault. */
615
616 /* Get the fault address. */
617 if (fp->ptregs.format == 0xA)
618 addr = fp->ptregs.pc + 4;
619 else
620 addr = fp->un.fmtb.baddr;
621 if (ssw & FC)
622 addr -= 2;
623
624 if (buserr_type & SUN3_BUSERR_INVALID) {
625 if (!mmu_emu_handle_fault (fp->un.fmtb.daddr, 1, 0))
626 do_page_fault (&fp->ptregs, addr, 0);
627 } else {
628#ifdef DEBUG
629 printk ("protection fault on insn access (segv).\n");
630#endif
631 force_sig (SIGSEGV, current);
632 }
633}
634#else
635#if defined(CPU_M68020_OR_M68030)
636static inline void bus_error030 (struct frame *fp)
637{
638 volatile unsigned short temp;
639 unsigned short mmusr;
640 unsigned long addr, errorcode;
641 unsigned short ssw = fp->un.fmtb.ssw;
642#ifdef DEBUG
643 unsigned long desc;
644
645 printk ("pid = %x ", current->pid);
646 printk ("SSW=%#06x ", ssw);
647
648 if (ssw & (FC | FB))
649 printk ("Instruction fault at %#010lx\n",
650 ssw & FC ?
651 fp->ptregs.format == 0xa ? fp->ptregs.pc + 2 : fp->un.fmtb.baddr - 2
652 :
653 fp->ptregs.format == 0xa ? fp->ptregs.pc + 4 : fp->un.fmtb.baddr);
654 if (ssw & DF)
655 printk ("Data %s fault at %#010lx in %s (pc=%#lx)\n",
656 ssw & RW ? "read" : "write",
657 fp->un.fmtb.daddr,
658 space_names[ssw & DFC], fp->ptregs.pc);
659#endif
660
661 /* ++andreas: If a data fault and an instruction fault happen
662 at the same time map in both pages. */
663
664 /* First handle the data fault, if any. */
665 if (ssw & DF) {
666 addr = fp->un.fmtb.daddr;
667
668#ifdef DEBUG
669 asm volatile ("ptestr %3,%2@,#7,%0\n\t"
670 "pmove %%psr,%1@"
671 : "=a&" (desc)
672 : "a" (&temp), "a" (addr), "d" (ssw));
673#else
674 asm volatile ("ptestr %2,%1@,#7\n\t"
675 "pmove %%psr,%0@"
676 : : "a" (&temp), "a" (addr), "d" (ssw));
677#endif
678 mmusr = temp;
679
680#ifdef DEBUG
681 printk("mmusr is %#x for addr %#lx in task %p\n",
682 mmusr, addr, current);
683 printk("descriptor address is %#lx, contents %#lx\n",
684 __va(desc), *(unsigned long *)__va(desc));
685#endif
686
687 errorcode = (mmusr & MMU_I) ? 0 : 1;
688 if (!(ssw & RW) || (ssw & RM))
689 errorcode |= 2;
690
691 if (mmusr & (MMU_I | MMU_WP)) {
692 if (ssw & 4) {
693 printk("Data %s fault at %#010lx in %s (pc=%#lx)\n",
694 ssw & RW ? "read" : "write",
695 fp->un.fmtb.daddr,
696 space_names[ssw & DFC], fp->ptregs.pc);
697 goto buserr;
698 }
699 /* Don't try to do anything further if an exception was
700 handled. */
701 if (do_page_fault (&fp->ptregs, addr, errorcode) < 0)
702 return;
703 } else if (!(mmusr & MMU_I)) {
704 /* probably a 020 cas fault */
705 if (!(ssw & RM) && send_fault_sig(&fp->ptregs) > 0)
706 printk("unexpected bus error (%#x,%#x)\n", ssw, mmusr);
707 } else if (mmusr & (MMU_B|MMU_L|MMU_S)) {
708 printk("invalid %s access at %#lx from pc %#lx\n",
709 !(ssw & RW) ? "write" : "read", addr,
710 fp->ptregs.pc);
711 die_if_kernel("Oops",&fp->ptregs,mmusr);
712 force_sig(SIGSEGV, current);
713 return;
714 } else {
715#if 0
716 static volatile long tlong;
717#endif
718
719 printk("weird %s access at %#lx from pc %#lx (ssw is %#x)\n",
720 !(ssw & RW) ? "write" : "read", addr,
721 fp->ptregs.pc, ssw);
722 asm volatile ("ptestr #1,%1@,#0\n\t"
723 "pmove %%psr,%0@"
724 : /* no outputs */
725 : "a" (&temp), "a" (addr));
726 mmusr = temp;
727
728 printk ("level 0 mmusr is %#x\n", mmusr);
729#if 0
730 asm volatile ("pmove %%tt0,%0@"
731 : /* no outputs */
732 : "a" (&tlong));
733 printk("tt0 is %#lx, ", tlong);
734 asm volatile ("pmove %%tt1,%0@"
735 : /* no outputs */
736 : "a" (&tlong));
737 printk("tt1 is %#lx\n", tlong);
738#endif
739#ifdef DEBUG
740 printk("Unknown SIGSEGV - 1\n");
741#endif
742 die_if_kernel("Oops",&fp->ptregs,mmusr);
743 force_sig(SIGSEGV, current);
744 return;
745 }
746
747 /* setup an ATC entry for the access about to be retried */
748 if (!(ssw & RW) || (ssw & RM))
749 asm volatile ("ploadw %1,%0@" : /* no outputs */
750 : "a" (addr), "d" (ssw));
751 else
752 asm volatile ("ploadr %1,%0@" : /* no outputs */
753 : "a" (addr), "d" (ssw));
754 }
755
756 /* Now handle the instruction fault. */
757
758 if (!(ssw & (FC|FB)))
759 return;
760
761 if (fp->ptregs.sr & PS_S) {
762 printk("Instruction fault at %#010lx\n",
763 fp->ptregs.pc);
764 buserr:
765 printk ("BAD KERNEL BUSERR\n");
766 die_if_kernel("Oops",&fp->ptregs,0);
767 force_sig(SIGKILL, current);
768 return;
769 }
770
771 /* get the fault address */
772 if (fp->ptregs.format == 10)
773 addr = fp->ptregs.pc + 4;
774 else
775 addr = fp->un.fmtb.baddr;
776 if (ssw & FC)
777 addr -= 2;
778
779 if ((ssw & DF) && ((addr ^ fp->un.fmtb.daddr) & PAGE_MASK) == 0)
780 /* Insn fault on same page as data fault. But we
781 should still create the ATC entry. */
782 goto create_atc_entry;
783
784#ifdef DEBUG
785 asm volatile ("ptestr #1,%2@,#7,%0\n\t"
786 "pmove %%psr,%1@"
787 : "=a&" (desc)
788 : "a" (&temp), "a" (addr));
789#else
790 asm volatile ("ptestr #1,%1@,#7\n\t"
791 "pmove %%psr,%0@"
792 : : "a" (&temp), "a" (addr));
793#endif
794 mmusr = temp;
795
796#ifdef DEBUG
797 printk ("mmusr is %#x for addr %#lx in task %p\n",
798 mmusr, addr, current);
799 printk ("descriptor address is %#lx, contents %#lx\n",
800 __va(desc), *(unsigned long *)__va(desc));
801#endif
802
803 if (mmusr & MMU_I)
804 do_page_fault (&fp->ptregs, addr, 0);
805 else if (mmusr & (MMU_B|MMU_L|MMU_S)) {
806 printk ("invalid insn access at %#lx from pc %#lx\n",
807 addr, fp->ptregs.pc);
808#ifdef DEBUG
809 printk("Unknown SIGSEGV - 2\n");
810#endif
811 die_if_kernel("Oops",&fp->ptregs,mmusr);
812 force_sig(SIGSEGV, current);
813 return;
814 }
815
816create_atc_entry:
817 /* setup an ATC entry for the access about to be retried */
818 asm volatile ("ploadr #2,%0@" : /* no outputs */
819 : "a" (addr));
820}
821#endif /* CPU_M68020_OR_M68030 */
822#endif /* !CONFIG_SUN3 */
823
824asmlinkage void buserr_c(struct frame *fp)
825{
826 /* Only set esp0 if coming from user mode */
827 if (user_mode(&fp->ptregs))
828 current->thread.esp0 = (unsigned long) fp;
829
830#ifdef DEBUG
831 printk ("*** Bus Error *** Format is %x\n", fp->ptregs.format);
832#endif
833
834 switch (fp->ptregs.format) {
835#if defined (CONFIG_M68060)
836 case 4: /* 68060 access error */
837 access_error060 (fp);
838 break;
839#endif
840#if defined (CONFIG_M68040)
841 case 0x7: /* 68040 access error */
842 access_error040 (fp);
843 break;
844#endif
845#if defined (CPU_M68020_OR_M68030)
846 case 0xa:
847 case 0xb:
848 bus_error030 (fp);
849 break;
850#endif
851 default:
852 die_if_kernel("bad frame format",&fp->ptregs,0);
853#ifdef DEBUG
854 printk("Unknown SIGSEGV - 4\n");
855#endif
856 force_sig(SIGSEGV, current);
857 }
858}
859
860
861static int kstack_depth_to_print = 48;
862
863void show_trace(unsigned long *stack)
864{
865 unsigned long *endstack;
866 unsigned long addr;
867 int i;
868
869 printk("Call Trace:");
870 addr = (unsigned long)stack + THREAD_SIZE - 1;
871 endstack = (unsigned long *)(addr & -THREAD_SIZE);
872 i = 0;
873 while (stack + 1 <= endstack) {
874 addr = *stack++;
875 /*
876 * If the address is either in the text segment of the
877 * kernel, or in the region which contains vmalloc'ed
878 * memory, it *may* be the address of a calling
879 * routine; if so, print it so that someone tracing
880 * down the cause of the crash will be able to figure
881 * out the call path that was taken.
882 */
883 if (__kernel_text_address(addr)) {
884#ifndef CONFIG_KALLSYMS
885 if (i % 5 == 0)
886 printk("\n ");
887#endif
888 printk(" [<%08lx>] %pS\n", addr, (void *)addr);
889 i++;
890 }
891 }
892 printk("\n");
893}
894
895void show_registers(struct pt_regs *regs)
896{
897 struct frame *fp = (struct frame *)regs;
898 mm_segment_t old_fs = get_fs();
899 u16 c, *cp;
900 unsigned long addr;
901 int i;
902
903 print_modules();
904 printk("PC: [<%08lx>] %pS\n", regs->pc, (void *)regs->pc);
905 printk("SR: %04x SP: %p a2: %08lx\n", regs->sr, regs, regs->a2);
906 printk("d0: %08lx d1: %08lx d2: %08lx d3: %08lx\n",
907 regs->d0, regs->d1, regs->d2, regs->d3);
908 printk("d4: %08lx d5: %08lx a0: %08lx a1: %08lx\n",
909 regs->d4, regs->d5, regs->a0, regs->a1);
910
911 printk("Process %s (pid: %d, task=%p)\n",
912 current->comm, task_pid_nr(current), current);
913 addr = (unsigned long)&fp->un;
914 printk("Frame format=%X ", regs->format);
915 switch (regs->format) {
916 case 0x2:
917 printk("instr addr=%08lx\n", fp->un.fmt2.iaddr);
918 addr += sizeof(fp->un.fmt2);
919 break;
920 case 0x3:
921 printk("eff addr=%08lx\n", fp->un.fmt3.effaddr);
922 addr += sizeof(fp->un.fmt3);
923 break;
924 case 0x4:
925 printk((CPU_IS_060 ? "fault addr=%08lx fslw=%08lx\n"
926 : "eff addr=%08lx pc=%08lx\n"),
927 fp->un.fmt4.effaddr, fp->un.fmt4.pc);
928 addr += sizeof(fp->un.fmt4);
929 break;
930 case 0x7:
931 printk("eff addr=%08lx ssw=%04x faddr=%08lx\n",
932 fp->un.fmt7.effaddr, fp->un.fmt7.ssw, fp->un.fmt7.faddr);
933 printk("wb 1 stat/addr/data: %04x %08lx %08lx\n",
934 fp->un.fmt7.wb1s, fp->un.fmt7.wb1a, fp->un.fmt7.wb1dpd0);
935 printk("wb 2 stat/addr/data: %04x %08lx %08lx\n",
936 fp->un.fmt7.wb2s, fp->un.fmt7.wb2a, fp->un.fmt7.wb2d);
937 printk("wb 3 stat/addr/data: %04x %08lx %08lx\n",
938 fp->un.fmt7.wb3s, fp->un.fmt7.wb3a, fp->un.fmt7.wb3d);
939 printk("push data: %08lx %08lx %08lx %08lx\n",
940 fp->un.fmt7.wb1dpd0, fp->un.fmt7.pd1, fp->un.fmt7.pd2,
941 fp->un.fmt7.pd3);
942 addr += sizeof(fp->un.fmt7);
943 break;
944 case 0x9:
945 printk("instr addr=%08lx\n", fp->un.fmt9.iaddr);
946 addr += sizeof(fp->un.fmt9);
947 break;
948 case 0xa:
949 printk("ssw=%04x isc=%04x isb=%04x daddr=%08lx dobuf=%08lx\n",
950 fp->un.fmta.ssw, fp->un.fmta.isc, fp->un.fmta.isb,
951 fp->un.fmta.daddr, fp->un.fmta.dobuf);
952 addr += sizeof(fp->un.fmta);
953 break;
954 case 0xb:
955 printk("ssw=%04x isc=%04x isb=%04x daddr=%08lx dobuf=%08lx\n",
956 fp->un.fmtb.ssw, fp->un.fmtb.isc, fp->un.fmtb.isb,
957 fp->un.fmtb.daddr, fp->un.fmtb.dobuf);
958 printk("baddr=%08lx dibuf=%08lx ver=%x\n",
959 fp->un.fmtb.baddr, fp->un.fmtb.dibuf, fp->un.fmtb.ver);
960 addr += sizeof(fp->un.fmtb);
961 break;
962 default:
963 printk("\n");
964 }
965 show_stack(NULL, (unsigned long *)addr);
966
967 printk("Code:");
968 set_fs(KERNEL_DS);
969 cp = (u16 *)regs->pc;
970 for (i = -8; i < 16; i++) {
971 if (get_user(c, cp + i) && i >= 0) {
972 printk(" Bad PC value.");
973 break;
974 }
975 printk(i ? " %04x" : " <%04x>", c);
976 }
977 set_fs(old_fs);
978 printk ("\n");
979}
980
981void show_stack(struct task_struct *task, unsigned long *stack)
982{
983 unsigned long *p;
984 unsigned long *endstack;
985 int i;
986
987 if (!stack) {
988 if (task)
989 stack = (unsigned long *)task->thread.esp0;
990 else
991 stack = (unsigned long *)&stack;
992 }
993 endstack = (unsigned long *)(((unsigned long)stack + THREAD_SIZE - 1) & -THREAD_SIZE);
994
995 printk("Stack from %08lx:", (unsigned long)stack);
996 p = stack;
997 for (i = 0; i < kstack_depth_to_print; i++) {
998 if (p + 1 > endstack)
999 break;
1000 if (i % 8 == 0)
1001 printk("\n ");
1002 printk(" %08lx", *p++);
1003 }
1004 printk("\n");
1005 show_trace(stack);
1006}
1007
1008/*
1009 * The architecture-independent backtrace generator
1010 */
1011void dump_stack(void)
1012{
1013 unsigned long stack;
1014
1015 show_trace(&stack);
1016}
1017
1018EXPORT_SYMBOL(dump_stack);
1019
1020void bad_super_trap (struct frame *fp)
1021{
1022 console_verbose();
1023 if (fp->ptregs.vector < 4 * ARRAY_SIZE(vec_names))
1024 printk ("*** %s *** FORMAT=%X\n",
1025 vec_names[(fp->ptregs.vector) >> 2],
1026 fp->ptregs.format);
1027 else
1028 printk ("*** Exception %d *** FORMAT=%X\n",
1029 (fp->ptregs.vector) >> 2,
1030 fp->ptregs.format);
1031 if (fp->ptregs.vector >> 2 == VEC_ADDRERR && CPU_IS_020_OR_030) {
1032 unsigned short ssw = fp->un.fmtb.ssw;
1033
1034 printk ("SSW=%#06x ", ssw);
1035
1036 if (ssw & RC)
1037 printk ("Pipe stage C instruction fault at %#010lx\n",
1038 (fp->ptregs.format) == 0xA ?
1039 fp->ptregs.pc + 2 : fp->un.fmtb.baddr - 2);
1040 if (ssw & RB)
1041 printk ("Pipe stage B instruction fault at %#010lx\n",
1042 (fp->ptregs.format) == 0xA ?
1043 fp->ptregs.pc + 4 : fp->un.fmtb.baddr);
1044 if (ssw & DF)
1045 printk ("Data %s fault at %#010lx in %s (pc=%#lx)\n",
1046 ssw & RW ? "read" : "write",
1047 fp->un.fmtb.daddr, space_names[ssw & DFC],
1048 fp->ptregs.pc);
1049 }
1050 printk ("Current process id is %d\n", task_pid_nr(current));
1051 die_if_kernel("BAD KERNEL TRAP", &fp->ptregs, 0);
1052}
1053
1054asmlinkage void trap_c(struct frame *fp)
1055{
1056 int sig;
1057 siginfo_t info;
1058
1059 if (fp->ptregs.sr & PS_S) {
1060 if (fp->ptregs.vector == VEC_TRACE << 2) {
1061 /* traced a trapping instruction on a 68020/30,
1062 * real exception will be executed afterwards.
1063 */
1064 } else if (!handle_kernel_fault(&fp->ptregs))
1065 bad_super_trap(fp);
1066 return;
1067 }
1068
1069 /* send the appropriate signal to the user program */
1070 switch ((fp->ptregs.vector) >> 2) {
1071 case VEC_ADDRERR:
1072 info.si_code = BUS_ADRALN;
1073 sig = SIGBUS;
1074 break;
1075 case VEC_ILLEGAL:
1076 case VEC_LINE10:
1077 case VEC_LINE11:
1078 info.si_code = ILL_ILLOPC;
1079 sig = SIGILL;
1080 break;
1081 case VEC_PRIV:
1082 info.si_code = ILL_PRVOPC;
1083 sig = SIGILL;
1084 break;
1085 case VEC_COPROC:
1086 info.si_code = ILL_COPROC;
1087 sig = SIGILL;
1088 break;
1089 case VEC_TRAP1:
1090 case VEC_TRAP2:
1091 case VEC_TRAP3:
1092 case VEC_TRAP4:
1093 case VEC_TRAP5:
1094 case VEC_TRAP6:
1095 case VEC_TRAP7:
1096 case VEC_TRAP8:
1097 case VEC_TRAP9:
1098 case VEC_TRAP10:
1099 case VEC_TRAP11:
1100 case VEC_TRAP12:
1101 case VEC_TRAP13:
1102 case VEC_TRAP14:
1103 info.si_code = ILL_ILLTRP;
1104 sig = SIGILL;
1105 break;
1106 case VEC_FPBRUC:
1107 case VEC_FPOE:
1108 case VEC_FPNAN:
1109 info.si_code = FPE_FLTINV;
1110 sig = SIGFPE;
1111 break;
1112 case VEC_FPIR:
1113 info.si_code = FPE_FLTRES;
1114 sig = SIGFPE;
1115 break;
1116 case VEC_FPDIVZ:
1117 info.si_code = FPE_FLTDIV;
1118 sig = SIGFPE;
1119 break;
1120 case VEC_FPUNDER:
1121 info.si_code = FPE_FLTUND;
1122 sig = SIGFPE;
1123 break;
1124 case VEC_FPOVER:
1125 info.si_code = FPE_FLTOVF;
1126 sig = SIGFPE;
1127 break;
1128 case VEC_ZERODIV:
1129 info.si_code = FPE_INTDIV;
1130 sig = SIGFPE;
1131 break;
1132 case VEC_CHK:
1133 case VEC_TRAP:
1134 info.si_code = FPE_INTOVF;
1135 sig = SIGFPE;
1136 break;
1137 case VEC_TRACE: /* ptrace single step */
1138 info.si_code = TRAP_TRACE;
1139 sig = SIGTRAP;
1140 break;
1141 case VEC_TRAP15: /* breakpoint */
1142 info.si_code = TRAP_BRKPT;
1143 sig = SIGTRAP;
1144 break;
1145 default:
1146 info.si_code = ILL_ILLOPC;
1147 sig = SIGILL;
1148 break;
1149 }
1150 info.si_signo = sig;
1151 info.si_errno = 0;
1152 switch (fp->ptregs.format) {
1153 default:
1154 info.si_addr = (void *) fp->ptregs.pc;
1155 break;
1156 case 2:
1157 info.si_addr = (void *) fp->un.fmt2.iaddr;
1158 break;
1159 case 7:
1160 info.si_addr = (void *) fp->un.fmt7.effaddr;
1161 break;
1162 case 9:
1163 info.si_addr = (void *) fp->un.fmt9.iaddr;
1164 break;
1165 case 10:
1166 info.si_addr = (void *) fp->un.fmta.daddr;
1167 break;
1168 case 11:
1169 info.si_addr = (void *) fp->un.fmtb.daddr;
1170 break;
1171 }
1172 force_sig_info (sig, &info, current);
1173}
1174
1175void die_if_kernel (char *str, struct pt_regs *fp, int nr)
1176{
1177 if (!(fp->sr & PS_S))
1178 return;
1179
1180 console_verbose();
1181 printk("%s: %08x\n",str,nr);
1182 show_registers(fp);
1183 add_taint(TAINT_DIE);
1184 do_exit(SIGSEGV);
1185}
1186
1187/*
1188 * This function is called if an error occur while accessing
1189 * user-space from the fpsp040 code.
1190 */
1191asmlinkage void fpsp040_die(void)
1192{
1193 do_exit(SIGSEGV);
1194}
1195
1196#ifdef CONFIG_M68KFPU_EMU
1197asmlinkage void fpemu_signal(int signal, int code, void *addr)
1198{
1199 siginfo_t info;
1200
1201 info.si_signo = signal;
1202 info.si_errno = 0;
1203 info.si_code = code;
1204 info.si_addr = addr;
1205 force_sig_info(signal, &info, current);
1206}
1207#endif
diff --git a/arch/m68knommu/kernel/traps.c b/arch/m68k/kernel/traps_no.c
index a768008dfd0..a768008dfd0 100644
--- a/arch/m68knommu/kernel/traps.c
+++ b/arch/m68k/kernel/traps_no.c
diff --git a/arch/m68k/kernel/vmlinux.lds.S b/arch/m68k/kernel/vmlinux.lds.S
index 99ba315bd0a..030dabf0bc5 100644
--- a/arch/m68k/kernel/vmlinux.lds.S
+++ b/arch/m68k/kernel/vmlinux.lds.S
@@ -1,10 +1,5 @@
1PHDRS 1#ifdef CONFIG_MMU
2{ 2#include "vmlinux.lds_mm.S"
3 text PT_LOAD FILEHDR PHDRS FLAGS (7);
4 data PT_LOAD FLAGS (7);
5}
6#ifdef CONFIG_SUN3
7#include "vmlinux-sun3.lds"
8#else 3#else
9#include "vmlinux-std.lds" 4#include "vmlinux.lds_no.S"
10#endif 5#endif
diff --git a/arch/m68k/kernel/vmlinux.lds_mm.S b/arch/m68k/kernel/vmlinux.lds_mm.S
new file mode 100644
index 00000000000..99ba315bd0a
--- /dev/null
+++ b/arch/m68k/kernel/vmlinux.lds_mm.S
@@ -0,0 +1,10 @@
1PHDRS
2{
3 text PT_LOAD FILEHDR PHDRS FLAGS (7);
4 data PT_LOAD FLAGS (7);
5}
6#ifdef CONFIG_SUN3
7#include "vmlinux-sun3.lds"
8#else
9#include "vmlinux-std.lds"
10#endif
diff --git a/arch/m68knommu/kernel/vmlinux.lds.S b/arch/m68k/kernel/vmlinux.lds_no.S
index 47e15ebfd89..47e15ebfd89 100644
--- a/arch/m68knommu/kernel/vmlinux.lds.S
+++ b/arch/m68k/kernel/vmlinux.lds_no.S
diff --git a/arch/m68k/lib/Makefile b/arch/m68k/lib/Makefile
index af9abf8d9d9..1f95881d843 100644
--- a/arch/m68k/lib/Makefile
+++ b/arch/m68k/lib/Makefile
@@ -1,6 +1,5 @@
1# 1ifdef CONFIG_MMU
2# Makefile for m68k-specific library files.. 2include arch/m68k/lib/Makefile_mm
3# 3else
4 4include arch/m68k/lib/Makefile_no
5lib-y := ashldi3.o ashrdi3.o lshrdi3.o muldi3.o \ 5endif
6 checksum.o string.o uaccess.o
diff --git a/arch/m68k/lib/Makefile_mm b/arch/m68k/lib/Makefile_mm
new file mode 100644
index 00000000000..af9abf8d9d9
--- /dev/null
+++ b/arch/m68k/lib/Makefile_mm
@@ -0,0 +1,6 @@
1#
2# Makefile for m68k-specific library files..
3#
4
5lib-y := ashldi3.o ashrdi3.o lshrdi3.o muldi3.o \
6 checksum.o string.o uaccess.o
diff --git a/arch/m68knommu/lib/Makefile b/arch/m68k/lib/Makefile_no
index 32d852e586d..32d852e586d 100644
--- a/arch/m68knommu/lib/Makefile
+++ b/arch/m68k/lib/Makefile_no
diff --git a/arch/m68k/lib/checksum.c b/arch/m68k/lib/checksum.c
index 6216f12a756..1297536060d 100644
--- a/arch/m68k/lib/checksum.c
+++ b/arch/m68k/lib/checksum.c
@@ -1,425 +1,5 @@
1/* 1#ifdef CONFIG_MMU
2 * INET An implementation of the TCP/IP protocol suite for the LINUX 2#include "checksum_mm.c"
3 * operating system. INET is implemented using the BSD Socket 3#else
4 * interface as the means of communication with the user level. 4#include "checksum_no.c"
5 * 5#endif
6 * IP/TCP/UDP checksumming routines
7 *
8 * Authors: Jorge Cwik, <jorge@laser.satlink.net>
9 * Arnt Gulbrandsen, <agulbra@nvg.unit.no>
10 * Tom May, <ftom@netcom.com>
11 * Andreas Schwab, <schwab@issan.informatik.uni-dortmund.de>
12 * Lots of code moved from tcp.c and ip.c; see those files
13 * for more names.
14 *
15 * 03/02/96 Jes Sorensen, Andreas Schwab, Roman Hodek:
16 * Fixed some nasty bugs, causing some horrible crashes.
17 * A: At some points, the sum (%0) was used as
18 * length-counter instead of the length counter
19 * (%1). Thanks to Roman Hodek for pointing this out.
20 * B: GCC seems to mess up if one uses too many
21 * data-registers to hold input values and one tries to
22 * specify d0 and d1 as scratch registers. Letting gcc
23 * choose these registers itself solves the problem.
24 *
25 * This program is free software; you can redistribute it and/or
26 * modify it under the terms of the GNU General Public License
27 * as published by the Free Software Foundation; either version
28 * 2 of the License, or (at your option) any later version.
29 *
30 * 1998/8/31 Andreas Schwab:
31 * Zero out rest of buffer on exception in
32 * csum_partial_copy_from_user.
33 */
34
35#include <linux/module.h>
36#include <net/checksum.h>
37
38/*
39 * computes a partial checksum, e.g. for TCP/UDP fragments
40 */
41
42__wsum csum_partial(const void *buff, int len, __wsum sum)
43{
44 unsigned long tmp1, tmp2;
45 /*
46 * Experiments with ethernet and slip connections show that buff
47 * is aligned on either a 2-byte or 4-byte boundary.
48 */
49 __asm__("movel %2,%3\n\t"
50 "btst #1,%3\n\t" /* Check alignment */
51 "jeq 2f\n\t"
52 "subql #2,%1\n\t" /* buff%4==2: treat first word */
53 "jgt 1f\n\t"
54 "addql #2,%1\n\t" /* len was == 2, treat only rest */
55 "jra 4f\n"
56 "1:\t"
57 "addw %2@+,%0\n\t" /* add first word to sum */
58 "clrl %3\n\t"
59 "addxl %3,%0\n" /* add X bit */
60 "2:\t"
61 /* unrolled loop for the main part: do 8 longs at once */
62 "movel %1,%3\n\t" /* save len in tmp1 */
63 "lsrl #5,%1\n\t" /* len/32 */
64 "jeq 2f\n\t" /* not enough... */
65 "subql #1,%1\n"
66 "1:\t"
67 "movel %2@+,%4\n\t"
68 "addxl %4,%0\n\t"
69 "movel %2@+,%4\n\t"
70 "addxl %4,%0\n\t"
71 "movel %2@+,%4\n\t"
72 "addxl %4,%0\n\t"
73 "movel %2@+,%4\n\t"
74 "addxl %4,%0\n\t"
75 "movel %2@+,%4\n\t"
76 "addxl %4,%0\n\t"
77 "movel %2@+,%4\n\t"
78 "addxl %4,%0\n\t"
79 "movel %2@+,%4\n\t"
80 "addxl %4,%0\n\t"
81 "movel %2@+,%4\n\t"
82 "addxl %4,%0\n\t"
83 "dbra %1,1b\n\t"
84 "clrl %4\n\t"
85 "addxl %4,%0\n\t" /* add X bit */
86 "clrw %1\n\t"
87 "subql #1,%1\n\t"
88 "jcc 1b\n"
89 "2:\t"
90 "movel %3,%1\n\t" /* restore len from tmp1 */
91 "andw #0x1c,%3\n\t" /* number of rest longs */
92 "jeq 4f\n\t"
93 "lsrw #2,%3\n\t"
94 "subqw #1,%3\n"
95 "3:\t"
96 /* loop for rest longs */
97 "movel %2@+,%4\n\t"
98 "addxl %4,%0\n\t"
99 "dbra %3,3b\n\t"
100 "clrl %4\n\t"
101 "addxl %4,%0\n" /* add X bit */
102 "4:\t"
103 /* now check for rest bytes that do not fit into longs */
104 "andw #3,%1\n\t"
105 "jeq 7f\n\t"
106 "clrl %4\n\t" /* clear tmp2 for rest bytes */
107 "subqw #2,%1\n\t"
108 "jlt 5f\n\t"
109 "movew %2@+,%4\n\t" /* have rest >= 2: get word */
110 "swap %4\n\t" /* into bits 16..31 */
111 "tstw %1\n\t" /* another byte? */
112 "jeq 6f\n"
113 "5:\t"
114 "moveb %2@,%4\n\t" /* have odd rest: get byte */
115 "lslw #8,%4\n\t" /* into bits 8..15; 16..31 untouched */
116 "6:\t"
117 "addl %4,%0\n\t" /* now add rest long to sum */
118 "clrl %4\n\t"
119 "addxl %4,%0\n" /* add X bit */
120 "7:\t"
121 : "=d" (sum), "=d" (len), "=a" (buff),
122 "=&d" (tmp1), "=&d" (tmp2)
123 : "0" (sum), "1" (len), "2" (buff)
124 );
125 return(sum);
126}
127
128EXPORT_SYMBOL(csum_partial);
129
130
131/*
132 * copy from user space while checksumming, with exception handling.
133 */
134
135__wsum
136csum_partial_copy_from_user(const void __user *src, void *dst,
137 int len, __wsum sum, int *csum_err)
138{
139 /*
140 * GCC doesn't like more than 10 operands for the asm
141 * statements so we have to use tmp2 for the error
142 * code.
143 */
144 unsigned long tmp1, tmp2;
145
146 __asm__("movel %2,%4\n\t"
147 "btst #1,%4\n\t" /* Check alignment */
148 "jeq 2f\n\t"
149 "subql #2,%1\n\t" /* buff%4==2: treat first word */
150 "jgt 1f\n\t"
151 "addql #2,%1\n\t" /* len was == 2, treat only rest */
152 "jra 4f\n"
153 "1:\n"
154 "10:\t"
155 "movesw %2@+,%4\n\t" /* add first word to sum */
156 "addw %4,%0\n\t"
157 "movew %4,%3@+\n\t"
158 "clrl %4\n\t"
159 "addxl %4,%0\n" /* add X bit */
160 "2:\t"
161 /* unrolled loop for the main part: do 8 longs at once */
162 "movel %1,%4\n\t" /* save len in tmp1 */
163 "lsrl #5,%1\n\t" /* len/32 */
164 "jeq 2f\n\t" /* not enough... */
165 "subql #1,%1\n"
166 "1:\n"
167 "11:\t"
168 "movesl %2@+,%5\n\t"
169 "addxl %5,%0\n\t"
170 "movel %5,%3@+\n\t"
171 "12:\t"
172 "movesl %2@+,%5\n\t"
173 "addxl %5,%0\n\t"
174 "movel %5,%3@+\n\t"
175 "13:\t"
176 "movesl %2@+,%5\n\t"
177 "addxl %5,%0\n\t"
178 "movel %5,%3@+\n\t"
179 "14:\t"
180 "movesl %2@+,%5\n\t"
181 "addxl %5,%0\n\t"
182 "movel %5,%3@+\n\t"
183 "15:\t"
184 "movesl %2@+,%5\n\t"
185 "addxl %5,%0\n\t"
186 "movel %5,%3@+\n\t"
187 "16:\t"
188 "movesl %2@+,%5\n\t"
189 "addxl %5,%0\n\t"
190 "movel %5,%3@+\n\t"
191 "17:\t"
192 "movesl %2@+,%5\n\t"
193 "addxl %5,%0\n\t"
194 "movel %5,%3@+\n\t"
195 "18:\t"
196 "movesl %2@+,%5\n\t"
197 "addxl %5,%0\n\t"
198 "movel %5,%3@+\n\t"
199 "dbra %1,1b\n\t"
200 "clrl %5\n\t"
201 "addxl %5,%0\n\t" /* add X bit */
202 "clrw %1\n\t"
203 "subql #1,%1\n\t"
204 "jcc 1b\n"
205 "2:\t"
206 "movel %4,%1\n\t" /* restore len from tmp1 */
207 "andw #0x1c,%4\n\t" /* number of rest longs */
208 "jeq 4f\n\t"
209 "lsrw #2,%4\n\t"
210 "subqw #1,%4\n"
211 "3:\n"
212 /* loop for rest longs */
213 "19:\t"
214 "movesl %2@+,%5\n\t"
215 "addxl %5,%0\n\t"
216 "movel %5,%3@+\n\t"
217 "dbra %4,3b\n\t"
218 "clrl %5\n\t"
219 "addxl %5,%0\n" /* add X bit */
220 "4:\t"
221 /* now check for rest bytes that do not fit into longs */
222 "andw #3,%1\n\t"
223 "jeq 7f\n\t"
224 "clrl %5\n\t" /* clear tmp2 for rest bytes */
225 "subqw #2,%1\n\t"
226 "jlt 5f\n\t"
227 "20:\t"
228 "movesw %2@+,%5\n\t" /* have rest >= 2: get word */
229 "movew %5,%3@+\n\t"
230 "swap %5\n\t" /* into bits 16..31 */
231 "tstw %1\n\t" /* another byte? */
232 "jeq 6f\n"
233 "5:\n"
234 "21:\t"
235 "movesb %2@,%5\n\t" /* have odd rest: get byte */
236 "moveb %5,%3@+\n\t"
237 "lslw #8,%5\n\t" /* into bits 8..15; 16..31 untouched */
238 "6:\t"
239 "addl %5,%0\n\t" /* now add rest long to sum */
240 "clrl %5\n\t"
241 "addxl %5,%0\n\t" /* add X bit */
242 "7:\t"
243 "clrl %5\n" /* no error - clear return value */
244 "8:\n"
245 ".section .fixup,\"ax\"\n"
246 ".even\n"
247 /* If any exception occurs zero out the rest.
248 Similarities with the code above are intentional :-) */
249 "90:\t"
250 "clrw %3@+\n\t"
251 "movel %1,%4\n\t"
252 "lsrl #5,%1\n\t"
253 "jeq 1f\n\t"
254 "subql #1,%1\n"
255 "91:\t"
256 "clrl %3@+\n"
257 "92:\t"
258 "clrl %3@+\n"
259 "93:\t"
260 "clrl %3@+\n"
261 "94:\t"
262 "clrl %3@+\n"
263 "95:\t"
264 "clrl %3@+\n"
265 "96:\t"
266 "clrl %3@+\n"
267 "97:\t"
268 "clrl %3@+\n"
269 "98:\t"
270 "clrl %3@+\n\t"
271 "dbra %1,91b\n\t"
272 "clrw %1\n\t"
273 "subql #1,%1\n\t"
274 "jcc 91b\n"
275 "1:\t"
276 "movel %4,%1\n\t"
277 "andw #0x1c,%4\n\t"
278 "jeq 1f\n\t"
279 "lsrw #2,%4\n\t"
280 "subqw #1,%4\n"
281 "99:\t"
282 "clrl %3@+\n\t"
283 "dbra %4,99b\n\t"
284 "1:\t"
285 "andw #3,%1\n\t"
286 "jeq 9f\n"
287 "100:\t"
288 "clrw %3@+\n\t"
289 "tstw %1\n\t"
290 "jeq 9f\n"
291 "101:\t"
292 "clrb %3@+\n"
293 "9:\t"
294#define STR(X) STR1(X)
295#define STR1(X) #X
296 "moveq #-" STR(EFAULT) ",%5\n\t"
297 "jra 8b\n"
298 ".previous\n"
299 ".section __ex_table,\"a\"\n"
300 ".long 10b,90b\n"
301 ".long 11b,91b\n"
302 ".long 12b,92b\n"
303 ".long 13b,93b\n"
304 ".long 14b,94b\n"
305 ".long 15b,95b\n"
306 ".long 16b,96b\n"
307 ".long 17b,97b\n"
308 ".long 18b,98b\n"
309 ".long 19b,99b\n"
310 ".long 20b,100b\n"
311 ".long 21b,101b\n"
312 ".previous"
313 : "=d" (sum), "=d" (len), "=a" (src), "=a" (dst),
314 "=&d" (tmp1), "=d" (tmp2)
315 : "0" (sum), "1" (len), "2" (src), "3" (dst)
316 );
317
318 *csum_err = tmp2;
319
320 return(sum);
321}
322
323EXPORT_SYMBOL(csum_partial_copy_from_user);
324
325
326/*
327 * copy from kernel space while checksumming, otherwise like csum_partial
328 */
329
330__wsum
331csum_partial_copy_nocheck(const void *src, void *dst, int len, __wsum sum)
332{
333 unsigned long tmp1, tmp2;
334 __asm__("movel %2,%4\n\t"
335 "btst #1,%4\n\t" /* Check alignment */
336 "jeq 2f\n\t"
337 "subql #2,%1\n\t" /* buff%4==2: treat first word */
338 "jgt 1f\n\t"
339 "addql #2,%1\n\t" /* len was == 2, treat only rest */
340 "jra 4f\n"
341 "1:\t"
342 "movew %2@+,%4\n\t" /* add first word to sum */
343 "addw %4,%0\n\t"
344 "movew %4,%3@+\n\t"
345 "clrl %4\n\t"
346 "addxl %4,%0\n" /* add X bit */
347 "2:\t"
348 /* unrolled loop for the main part: do 8 longs at once */
349 "movel %1,%4\n\t" /* save len in tmp1 */
350 "lsrl #5,%1\n\t" /* len/32 */
351 "jeq 2f\n\t" /* not enough... */
352 "subql #1,%1\n"
353 "1:\t"
354 "movel %2@+,%5\n\t"
355 "addxl %5,%0\n\t"
356 "movel %5,%3@+\n\t"
357 "movel %2@+,%5\n\t"
358 "addxl %5,%0\n\t"
359 "movel %5,%3@+\n\t"
360 "movel %2@+,%5\n\t"
361 "addxl %5,%0\n\t"
362 "movel %5,%3@+\n\t"
363 "movel %2@+,%5\n\t"
364 "addxl %5,%0\n\t"
365 "movel %5,%3@+\n\t"
366 "movel %2@+,%5\n\t"
367 "addxl %5,%0\n\t"
368 "movel %5,%3@+\n\t"
369 "movel %2@+,%5\n\t"
370 "addxl %5,%0\n\t"
371 "movel %5,%3@+\n\t"
372 "movel %2@+,%5\n\t"
373 "addxl %5,%0\n\t"
374 "movel %5,%3@+\n\t"
375 "movel %2@+,%5\n\t"
376 "addxl %5,%0\n\t"
377 "movel %5,%3@+\n\t"
378 "dbra %1,1b\n\t"
379 "clrl %5\n\t"
380 "addxl %5,%0\n\t" /* add X bit */
381 "clrw %1\n\t"
382 "subql #1,%1\n\t"
383 "jcc 1b\n"
384 "2:\t"
385 "movel %4,%1\n\t" /* restore len from tmp1 */
386 "andw #0x1c,%4\n\t" /* number of rest longs */
387 "jeq 4f\n\t"
388 "lsrw #2,%4\n\t"
389 "subqw #1,%4\n"
390 "3:\t"
391 /* loop for rest longs */
392 "movel %2@+,%5\n\t"
393 "addxl %5,%0\n\t"
394 "movel %5,%3@+\n\t"
395 "dbra %4,3b\n\t"
396 "clrl %5\n\t"
397 "addxl %5,%0\n" /* add X bit */
398 "4:\t"
399 /* now check for rest bytes that do not fit into longs */
400 "andw #3,%1\n\t"
401 "jeq 7f\n\t"
402 "clrl %5\n\t" /* clear tmp2 for rest bytes */
403 "subqw #2,%1\n\t"
404 "jlt 5f\n\t"
405 "movew %2@+,%5\n\t" /* have rest >= 2: get word */
406 "movew %5,%3@+\n\t"
407 "swap %5\n\t" /* into bits 16..31 */
408 "tstw %1\n\t" /* another byte? */
409 "jeq 6f\n"
410 "5:\t"
411 "moveb %2@,%5\n\t" /* have odd rest: get byte */
412 "moveb %5,%3@+\n\t"
413 "lslw #8,%5\n" /* into bits 8..15; 16..31 untouched */
414 "6:\t"
415 "addl %5,%0\n\t" /* now add rest long to sum */
416 "clrl %5\n\t"
417 "addxl %5,%0\n" /* add X bit */
418 "7:\t"
419 : "=d" (sum), "=d" (len), "=a" (src), "=a" (dst),
420 "=&d" (tmp1), "=&d" (tmp2)
421 : "0" (sum), "1" (len), "2" (src), "3" (dst)
422 );
423 return(sum);
424}
425EXPORT_SYMBOL(csum_partial_copy_nocheck);
diff --git a/arch/m68k/lib/checksum_mm.c b/arch/m68k/lib/checksum_mm.c
new file mode 100644
index 00000000000..6216f12a756
--- /dev/null
+++ b/arch/m68k/lib/checksum_mm.c
@@ -0,0 +1,425 @@
1/*
2 * INET An implementation of the TCP/IP protocol suite for the LINUX
3 * operating system. INET is implemented using the BSD Socket
4 * interface as the means of communication with the user level.
5 *
6 * IP/TCP/UDP checksumming routines
7 *
8 * Authors: Jorge Cwik, <jorge@laser.satlink.net>
9 * Arnt Gulbrandsen, <agulbra@nvg.unit.no>
10 * Tom May, <ftom@netcom.com>
11 * Andreas Schwab, <schwab@issan.informatik.uni-dortmund.de>
12 * Lots of code moved from tcp.c and ip.c; see those files
13 * for more names.
14 *
15 * 03/02/96 Jes Sorensen, Andreas Schwab, Roman Hodek:
16 * Fixed some nasty bugs, causing some horrible crashes.
17 * A: At some points, the sum (%0) was used as
18 * length-counter instead of the length counter
19 * (%1). Thanks to Roman Hodek for pointing this out.
20 * B: GCC seems to mess up if one uses too many
21 * data-registers to hold input values and one tries to
22 * specify d0 and d1 as scratch registers. Letting gcc
23 * choose these registers itself solves the problem.
24 *
25 * This program is free software; you can redistribute it and/or
26 * modify it under the terms of the GNU General Public License
27 * as published by the Free Software Foundation; either version
28 * 2 of the License, or (at your option) any later version.
29 *
30 * 1998/8/31 Andreas Schwab:
31 * Zero out rest of buffer on exception in
32 * csum_partial_copy_from_user.
33 */
34
35#include <linux/module.h>
36#include <net/checksum.h>
37
38/*
39 * computes a partial checksum, e.g. for TCP/UDP fragments
40 */
41
42__wsum csum_partial(const void *buff, int len, __wsum sum)
43{
44 unsigned long tmp1, tmp2;
45 /*
46 * Experiments with ethernet and slip connections show that buff
47 * is aligned on either a 2-byte or 4-byte boundary.
48 */
49 __asm__("movel %2,%3\n\t"
50 "btst #1,%3\n\t" /* Check alignment */
51 "jeq 2f\n\t"
52 "subql #2,%1\n\t" /* buff%4==2: treat first word */
53 "jgt 1f\n\t"
54 "addql #2,%1\n\t" /* len was == 2, treat only rest */
55 "jra 4f\n"
56 "1:\t"
57 "addw %2@+,%0\n\t" /* add first word to sum */
58 "clrl %3\n\t"
59 "addxl %3,%0\n" /* add X bit */
60 "2:\t"
61 /* unrolled loop for the main part: do 8 longs at once */
62 "movel %1,%3\n\t" /* save len in tmp1 */
63 "lsrl #5,%1\n\t" /* len/32 */
64 "jeq 2f\n\t" /* not enough... */
65 "subql #1,%1\n"
66 "1:\t"
67 "movel %2@+,%4\n\t"
68 "addxl %4,%0\n\t"
69 "movel %2@+,%4\n\t"
70 "addxl %4,%0\n\t"
71 "movel %2@+,%4\n\t"
72 "addxl %4,%0\n\t"
73 "movel %2@+,%4\n\t"
74 "addxl %4,%0\n\t"
75 "movel %2@+,%4\n\t"
76 "addxl %4,%0\n\t"
77 "movel %2@+,%4\n\t"
78 "addxl %4,%0\n\t"
79 "movel %2@+,%4\n\t"
80 "addxl %4,%0\n\t"
81 "movel %2@+,%4\n\t"
82 "addxl %4,%0\n\t"
83 "dbra %1,1b\n\t"
84 "clrl %4\n\t"
85 "addxl %4,%0\n\t" /* add X bit */
86 "clrw %1\n\t"
87 "subql #1,%1\n\t"
88 "jcc 1b\n"
89 "2:\t"
90 "movel %3,%1\n\t" /* restore len from tmp1 */
91 "andw #0x1c,%3\n\t" /* number of rest longs */
92 "jeq 4f\n\t"
93 "lsrw #2,%3\n\t"
94 "subqw #1,%3\n"
95 "3:\t"
96 /* loop for rest longs */
97 "movel %2@+,%4\n\t"
98 "addxl %4,%0\n\t"
99 "dbra %3,3b\n\t"
100 "clrl %4\n\t"
101 "addxl %4,%0\n" /* add X bit */
102 "4:\t"
103 /* now check for rest bytes that do not fit into longs */
104 "andw #3,%1\n\t"
105 "jeq 7f\n\t"
106 "clrl %4\n\t" /* clear tmp2 for rest bytes */
107 "subqw #2,%1\n\t"
108 "jlt 5f\n\t"
109 "movew %2@+,%4\n\t" /* have rest >= 2: get word */
110 "swap %4\n\t" /* into bits 16..31 */
111 "tstw %1\n\t" /* another byte? */
112 "jeq 6f\n"
113 "5:\t"
114 "moveb %2@,%4\n\t" /* have odd rest: get byte */
115 "lslw #8,%4\n\t" /* into bits 8..15; 16..31 untouched */
116 "6:\t"
117 "addl %4,%0\n\t" /* now add rest long to sum */
118 "clrl %4\n\t"
119 "addxl %4,%0\n" /* add X bit */
120 "7:\t"
121 : "=d" (sum), "=d" (len), "=a" (buff),
122 "=&d" (tmp1), "=&d" (tmp2)
123 : "0" (sum), "1" (len), "2" (buff)
124 );
125 return(sum);
126}
127
128EXPORT_SYMBOL(csum_partial);
129
130
131/*
132 * copy from user space while checksumming, with exception handling.
133 */
134
135__wsum
136csum_partial_copy_from_user(const void __user *src, void *dst,
137 int len, __wsum sum, int *csum_err)
138{
139 /*
140 * GCC doesn't like more than 10 operands for the asm
141 * statements so we have to use tmp2 for the error
142 * code.
143 */
144 unsigned long tmp1, tmp2;
145
146 __asm__("movel %2,%4\n\t"
147 "btst #1,%4\n\t" /* Check alignment */
148 "jeq 2f\n\t"
149 "subql #2,%1\n\t" /* buff%4==2: treat first word */
150 "jgt 1f\n\t"
151 "addql #2,%1\n\t" /* len was == 2, treat only rest */
152 "jra 4f\n"
153 "1:\n"
154 "10:\t"
155 "movesw %2@+,%4\n\t" /* add first word to sum */
156 "addw %4,%0\n\t"
157 "movew %4,%3@+\n\t"
158 "clrl %4\n\t"
159 "addxl %4,%0\n" /* add X bit */
160 "2:\t"
161 /* unrolled loop for the main part: do 8 longs at once */
162 "movel %1,%4\n\t" /* save len in tmp1 */
163 "lsrl #5,%1\n\t" /* len/32 */
164 "jeq 2f\n\t" /* not enough... */
165 "subql #1,%1\n"
166 "1:\n"
167 "11:\t"
168 "movesl %2@+,%5\n\t"
169 "addxl %5,%0\n\t"
170 "movel %5,%3@+\n\t"
171 "12:\t"
172 "movesl %2@+,%5\n\t"
173 "addxl %5,%0\n\t"
174 "movel %5,%3@+\n\t"
175 "13:\t"
176 "movesl %2@+,%5\n\t"
177 "addxl %5,%0\n\t"
178 "movel %5,%3@+\n\t"
179 "14:\t"
180 "movesl %2@+,%5\n\t"
181 "addxl %5,%0\n\t"
182 "movel %5,%3@+\n\t"
183 "15:\t"
184 "movesl %2@+,%5\n\t"
185 "addxl %5,%0\n\t"
186 "movel %5,%3@+\n\t"
187 "16:\t"
188 "movesl %2@+,%5\n\t"
189 "addxl %5,%0\n\t"
190 "movel %5,%3@+\n\t"
191 "17:\t"
192 "movesl %2@+,%5\n\t"
193 "addxl %5,%0\n\t"
194 "movel %5,%3@+\n\t"
195 "18:\t"
196 "movesl %2@+,%5\n\t"
197 "addxl %5,%0\n\t"
198 "movel %5,%3@+\n\t"
199 "dbra %1,1b\n\t"
200 "clrl %5\n\t"
201 "addxl %5,%0\n\t" /* add X bit */
202 "clrw %1\n\t"
203 "subql #1,%1\n\t"
204 "jcc 1b\n"
205 "2:\t"
206 "movel %4,%1\n\t" /* restore len from tmp1 */
207 "andw #0x1c,%4\n\t" /* number of rest longs */
208 "jeq 4f\n\t"
209 "lsrw #2,%4\n\t"
210 "subqw #1,%4\n"
211 "3:\n"
212 /* loop for rest longs */
213 "19:\t"
214 "movesl %2@+,%5\n\t"
215 "addxl %5,%0\n\t"
216 "movel %5,%3@+\n\t"
217 "dbra %4,3b\n\t"
218 "clrl %5\n\t"
219 "addxl %5,%0\n" /* add X bit */
220 "4:\t"
221 /* now check for rest bytes that do not fit into longs */
222 "andw #3,%1\n\t"
223 "jeq 7f\n\t"
224 "clrl %5\n\t" /* clear tmp2 for rest bytes */
225 "subqw #2,%1\n\t"
226 "jlt 5f\n\t"
227 "20:\t"
228 "movesw %2@+,%5\n\t" /* have rest >= 2: get word */
229 "movew %5,%3@+\n\t"
230 "swap %5\n\t" /* into bits 16..31 */
231 "tstw %1\n\t" /* another byte? */
232 "jeq 6f\n"
233 "5:\n"
234 "21:\t"
235 "movesb %2@,%5\n\t" /* have odd rest: get byte */
236 "moveb %5,%3@+\n\t"
237 "lslw #8,%5\n\t" /* into bits 8..15; 16..31 untouched */
238 "6:\t"
239 "addl %5,%0\n\t" /* now add rest long to sum */
240 "clrl %5\n\t"
241 "addxl %5,%0\n\t" /* add X bit */
242 "7:\t"
243 "clrl %5\n" /* no error - clear return value */
244 "8:\n"
245 ".section .fixup,\"ax\"\n"
246 ".even\n"
247 /* If any exception occurs zero out the rest.
248 Similarities with the code above are intentional :-) */
249 "90:\t"
250 "clrw %3@+\n\t"
251 "movel %1,%4\n\t"
252 "lsrl #5,%1\n\t"
253 "jeq 1f\n\t"
254 "subql #1,%1\n"
255 "91:\t"
256 "clrl %3@+\n"
257 "92:\t"
258 "clrl %3@+\n"
259 "93:\t"
260 "clrl %3@+\n"
261 "94:\t"
262 "clrl %3@+\n"
263 "95:\t"
264 "clrl %3@+\n"
265 "96:\t"
266 "clrl %3@+\n"
267 "97:\t"
268 "clrl %3@+\n"
269 "98:\t"
270 "clrl %3@+\n\t"
271 "dbra %1,91b\n\t"
272 "clrw %1\n\t"
273 "subql #1,%1\n\t"
274 "jcc 91b\n"
275 "1:\t"
276 "movel %4,%1\n\t"
277 "andw #0x1c,%4\n\t"
278 "jeq 1f\n\t"
279 "lsrw #2,%4\n\t"
280 "subqw #1,%4\n"
281 "99:\t"
282 "clrl %3@+\n\t"
283 "dbra %4,99b\n\t"
284 "1:\t"
285 "andw #3,%1\n\t"
286 "jeq 9f\n"
287 "100:\t"
288 "clrw %3@+\n\t"
289 "tstw %1\n\t"
290 "jeq 9f\n"
291 "101:\t"
292 "clrb %3@+\n"
293 "9:\t"
294#define STR(X) STR1(X)
295#define STR1(X) #X
296 "moveq #-" STR(EFAULT) ",%5\n\t"
297 "jra 8b\n"
298 ".previous\n"
299 ".section __ex_table,\"a\"\n"
300 ".long 10b,90b\n"
301 ".long 11b,91b\n"
302 ".long 12b,92b\n"
303 ".long 13b,93b\n"
304 ".long 14b,94b\n"
305 ".long 15b,95b\n"
306 ".long 16b,96b\n"
307 ".long 17b,97b\n"
308 ".long 18b,98b\n"
309 ".long 19b,99b\n"
310 ".long 20b,100b\n"
311 ".long 21b,101b\n"
312 ".previous"
313 : "=d" (sum), "=d" (len), "=a" (src), "=a" (dst),
314 "=&d" (tmp1), "=d" (tmp2)
315 : "0" (sum), "1" (len), "2" (src), "3" (dst)
316 );
317
318 *csum_err = tmp2;
319
320 return(sum);
321}
322
323EXPORT_SYMBOL(csum_partial_copy_from_user);
324
325
326/*
327 * copy from kernel space while checksumming, otherwise like csum_partial
328 */
329
330__wsum
331csum_partial_copy_nocheck(const void *src, void *dst, int len, __wsum sum)
332{
333 unsigned long tmp1, tmp2;
334 __asm__("movel %2,%4\n\t"
335 "btst #1,%4\n\t" /* Check alignment */
336 "jeq 2f\n\t"
337 "subql #2,%1\n\t" /* buff%4==2: treat first word */
338 "jgt 1f\n\t"
339 "addql #2,%1\n\t" /* len was == 2, treat only rest */
340 "jra 4f\n"
341 "1:\t"
342 "movew %2@+,%4\n\t" /* add first word to sum */
343 "addw %4,%0\n\t"
344 "movew %4,%3@+\n\t"
345 "clrl %4\n\t"
346 "addxl %4,%0\n" /* add X bit */
347 "2:\t"
348 /* unrolled loop for the main part: do 8 longs at once */
349 "movel %1,%4\n\t" /* save len in tmp1 */
350 "lsrl #5,%1\n\t" /* len/32 */
351 "jeq 2f\n\t" /* not enough... */
352 "subql #1,%1\n"
353 "1:\t"
354 "movel %2@+,%5\n\t"
355 "addxl %5,%0\n\t"
356 "movel %5,%3@+\n\t"
357 "movel %2@+,%5\n\t"
358 "addxl %5,%0\n\t"
359 "movel %5,%3@+\n\t"
360 "movel %2@+,%5\n\t"
361 "addxl %5,%0\n\t"
362 "movel %5,%3@+\n\t"
363 "movel %2@+,%5\n\t"
364 "addxl %5,%0\n\t"
365 "movel %5,%3@+\n\t"
366 "movel %2@+,%5\n\t"
367 "addxl %5,%0\n\t"
368 "movel %5,%3@+\n\t"
369 "movel %2@+,%5\n\t"
370 "addxl %5,%0\n\t"
371 "movel %5,%3@+\n\t"
372 "movel %2@+,%5\n\t"
373 "addxl %5,%0\n\t"
374 "movel %5,%3@+\n\t"
375 "movel %2@+,%5\n\t"
376 "addxl %5,%0\n\t"
377 "movel %5,%3@+\n\t"
378 "dbra %1,1b\n\t"
379 "clrl %5\n\t"
380 "addxl %5,%0\n\t" /* add X bit */
381 "clrw %1\n\t"
382 "subql #1,%1\n\t"
383 "jcc 1b\n"
384 "2:\t"
385 "movel %4,%1\n\t" /* restore len from tmp1 */
386 "andw #0x1c,%4\n\t" /* number of rest longs */
387 "jeq 4f\n\t"
388 "lsrw #2,%4\n\t"
389 "subqw #1,%4\n"
390 "3:\t"
391 /* loop for rest longs */
392 "movel %2@+,%5\n\t"
393 "addxl %5,%0\n\t"
394 "movel %5,%3@+\n\t"
395 "dbra %4,3b\n\t"
396 "clrl %5\n\t"
397 "addxl %5,%0\n" /* add X bit */
398 "4:\t"
399 /* now check for rest bytes that do not fit into longs */
400 "andw #3,%1\n\t"
401 "jeq 7f\n\t"
402 "clrl %5\n\t" /* clear tmp2 for rest bytes */
403 "subqw #2,%1\n\t"
404 "jlt 5f\n\t"
405 "movew %2@+,%5\n\t" /* have rest >= 2: get word */
406 "movew %5,%3@+\n\t"
407 "swap %5\n\t" /* into bits 16..31 */
408 "tstw %1\n\t" /* another byte? */
409 "jeq 6f\n"
410 "5:\t"
411 "moveb %2@,%5\n\t" /* have odd rest: get byte */
412 "moveb %5,%3@+\n\t"
413 "lslw #8,%5\n" /* into bits 8..15; 16..31 untouched */
414 "6:\t"
415 "addl %5,%0\n\t" /* now add rest long to sum */
416 "clrl %5\n\t"
417 "addxl %5,%0\n" /* add X bit */
418 "7:\t"
419 : "=d" (sum), "=d" (len), "=a" (src), "=a" (dst),
420 "=&d" (tmp1), "=&d" (tmp2)
421 : "0" (sum), "1" (len), "2" (src), "3" (dst)
422 );
423 return(sum);
424}
425EXPORT_SYMBOL(csum_partial_copy_nocheck);
diff --git a/arch/m68knommu/lib/checksum.c b/arch/m68k/lib/checksum_no.c
index eccf25d3d73..eccf25d3d73 100644
--- a/arch/m68knommu/lib/checksum.c
+++ b/arch/m68k/lib/checksum_no.c
diff --git a/arch/m68knommu/lib/delay.c b/arch/m68k/lib/delay.c
index 5bd5472d38a..5bd5472d38a 100644
--- a/arch/m68knommu/lib/delay.c
+++ b/arch/m68k/lib/delay.c
diff --git a/arch/m68knommu/lib/divsi3.S b/arch/m68k/lib/divsi3.S
index ec307b61991..ec307b61991 100644
--- a/arch/m68knommu/lib/divsi3.S
+++ b/arch/m68k/lib/divsi3.S
diff --git a/arch/m68knommu/lib/memcpy.c b/arch/m68k/lib/memcpy.c
index b50dbcad474..b50dbcad474 100644
--- a/arch/m68knommu/lib/memcpy.c
+++ b/arch/m68k/lib/memcpy.c
diff --git a/arch/m68knommu/lib/memmove.c b/arch/m68k/lib/memmove.c
index b3dcfe9dab7..b3dcfe9dab7 100644
--- a/arch/m68knommu/lib/memmove.c
+++ b/arch/m68k/lib/memmove.c
diff --git a/arch/m68knommu/lib/memset.c b/arch/m68k/lib/memset.c
index 1389bf45563..1389bf45563 100644
--- a/arch/m68knommu/lib/memset.c
+++ b/arch/m68k/lib/memset.c
diff --git a/arch/m68knommu/lib/modsi3.S b/arch/m68k/lib/modsi3.S
index ef384943576..ef384943576 100644
--- a/arch/m68knommu/lib/modsi3.S
+++ b/arch/m68k/lib/modsi3.S
diff --git a/arch/m68k/lib/muldi3.c b/arch/m68k/lib/muldi3.c
index be4f275649e..16e0eb338ee 100644
--- a/arch/m68k/lib/muldi3.c
+++ b/arch/m68k/lib/muldi3.c
@@ -1,63 +1,5 @@
1/* muldi3.c extracted from gcc-2.7.2.3/libgcc2.c and 1#ifdef CONFIG_MMU
2 gcc-2.7.2.3/longlong.h which is: */ 2#include "muldi3_mm.c"
3/* Copyright (C) 1989, 1992, 1993, 1994, 1995 Free Software Foundation, Inc. 3#else
4 4#include "muldi3_no.c"
5This file is part of GNU CC. 5#endif
6
7GNU CC is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
9the Free Software Foundation; either version 2, or (at your option)
10any later version.
11
12GNU CC is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with GNU CC; see the file COPYING. If not, write to
19the Free Software Foundation, 59 Temple Place - Suite 330,
20Boston, MA 02111-1307, USA. */
21
22#define BITS_PER_UNIT 8
23
24#define umul_ppmm(w1, w0, u, v) \
25 __asm__ ("mulu%.l %3,%1:%0" \
26 : "=d" ((USItype)(w0)), \
27 "=d" ((USItype)(w1)) \
28 : "%0" ((USItype)(u)), \
29 "dmi" ((USItype)(v)))
30
31#define __umulsidi3(u, v) \
32 ({DIunion __w; \
33 umul_ppmm (__w.s.high, __w.s.low, u, v); \
34 __w.ll; })
35
36typedef int SItype __attribute__ ((mode (SI)));
37typedef unsigned int USItype __attribute__ ((mode (SI)));
38typedef int DItype __attribute__ ((mode (DI)));
39typedef int word_type __attribute__ ((mode (__word__)));
40
41struct DIstruct {SItype high, low;};
42
43typedef union
44{
45 struct DIstruct s;
46 DItype ll;
47} DIunion;
48
49DItype
50__muldi3 (DItype u, DItype v)
51{
52 DIunion w;
53 DIunion uu, vv;
54
55 uu.ll = u,
56 vv.ll = v;
57
58 w.ll = __umulsidi3 (uu.s.low, vv.s.low);
59 w.s.high += ((USItype) uu.s.low * (USItype) vv.s.high
60 + (USItype) uu.s.high * (USItype) vv.s.low);
61
62 return w.ll;
63}
diff --git a/arch/m68knommu/lib/ashrdi3.c b/arch/m68k/lib/muldi3_mm.c
index 78efb65e315..be4f275649e 100644
--- a/arch/m68knommu/lib/ashrdi3.c
+++ b/arch/m68k/lib/muldi3_mm.c
@@ -1,4 +1,5 @@
1/* ashrdi3.c extracted from gcc-2.7.2/libgcc2.c which is: */ 1/* muldi3.c extracted from gcc-2.7.2.3/libgcc2.c and
2 gcc-2.7.2.3/longlong.h which is: */
2/* Copyright (C) 1989, 1992, 1993, 1994, 1995 Free Software Foundation, Inc. 3/* Copyright (C) 1989, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
3 4
4This file is part of GNU CC. 5This file is part of GNU CC.
@@ -20,7 +21,19 @@ Boston, MA 02111-1307, USA. */
20 21
21#define BITS_PER_UNIT 8 22#define BITS_PER_UNIT 8
22 23
23typedef int SItype __attribute__ ((mode (SI))); 24#define umul_ppmm(w1, w0, u, v) \
25 __asm__ ("mulu%.l %3,%1:%0" \
26 : "=d" ((USItype)(w0)), \
27 "=d" ((USItype)(w1)) \
28 : "%0" ((USItype)(u)), \
29 "dmi" ((USItype)(v)))
30
31#define __umulsidi3(u, v) \
32 ({DIunion __w; \
33 umul_ppmm (__w.s.high, __w.s.low, u, v); \
34 __w.ll; })
35
36typedef int SItype __attribute__ ((mode (SI)));
24typedef unsigned int USItype __attribute__ ((mode (SI))); 37typedef unsigned int USItype __attribute__ ((mode (SI)));
25typedef int DItype __attribute__ ((mode (DI))); 38typedef int DItype __attribute__ ((mode (DI)));
26typedef int word_type __attribute__ ((mode (__word__))); 39typedef int word_type __attribute__ ((mode (__word__)));
@@ -34,30 +47,17 @@ typedef union
34} DIunion; 47} DIunion;
35 48
36DItype 49DItype
37__ashrdi3 (DItype u, word_type b) 50__muldi3 (DItype u, DItype v)
38{ 51{
39 DIunion w; 52 DIunion w;
40 word_type bm; 53 DIunion uu, vv;
41 DIunion uu; 54
42 55 uu.ll = u,
43 if (b == 0) 56 vv.ll = v;
44 return u; 57
45 58 w.ll = __umulsidi3 (uu.s.low, vv.s.low);
46 uu.ll = u; 59 w.s.high += ((USItype) uu.s.low * (USItype) vv.s.high
47 60 + (USItype) uu.s.high * (USItype) vv.s.low);
48 bm = (sizeof (SItype) * BITS_PER_UNIT) - b;
49 if (bm <= 0)
50 {
51 /* w.s.high = 1..1 or 0..0 */
52 w.s.high = uu.s.high >> (sizeof (SItype) * BITS_PER_UNIT - 1);
53 w.s.low = uu.s.high >> -bm;
54 }
55 else
56 {
57 USItype carries = (USItype)uu.s.high << bm;
58 w.s.high = uu.s.high >> b;
59 w.s.low = ((USItype)uu.s.low >> b) | carries;
60 }
61 61
62 return w.ll; 62 return w.ll;
63} 63}
diff --git a/arch/m68knommu/lib/muldi3.c b/arch/m68k/lib/muldi3_no.c
index 34af72c3030..34af72c3030 100644
--- a/arch/m68knommu/lib/muldi3.c
+++ b/arch/m68k/lib/muldi3_no.c
diff --git a/arch/m68knommu/lib/mulsi3.S b/arch/m68k/lib/mulsi3.S
index ce29ea37b45..ce29ea37b45 100644
--- a/arch/m68knommu/lib/mulsi3.S
+++ b/arch/m68k/lib/mulsi3.S
diff --git a/arch/m68knommu/lib/udivsi3.S b/arch/m68k/lib/udivsi3.S
index c424c4a1f0a..c424c4a1f0a 100644
--- a/arch/m68knommu/lib/udivsi3.S
+++ b/arch/m68k/lib/udivsi3.S
diff --git a/arch/m68knommu/lib/umodsi3.S b/arch/m68k/lib/umodsi3.S
index 5def5f62647..5def5f62647 100644
--- a/arch/m68knommu/lib/umodsi3.S
+++ b/arch/m68k/lib/umodsi3.S
diff --git a/arch/m68k/mm/Makefile b/arch/m68k/mm/Makefile
index 5eaa43c4cb3..b60270e4954 100644
--- a/arch/m68k/mm/Makefile
+++ b/arch/m68k/mm/Makefile
@@ -1,8 +1,5 @@
1# 1ifdef CONFIG_MMU
2# Makefile for the linux m68k-specific parts of the memory manager. 2include arch/m68k/mm/Makefile_mm
3# 3else
4 4include arch/m68k/mm/Makefile_no
5obj-y := cache.o init.o fault.o hwtest.o 5endif
6
7obj-$(CONFIG_MMU_MOTOROLA) += kmap.o memory.o motorola.o
8obj-$(CONFIG_MMU_SUN3) += sun3kmap.o sun3mmu.o
diff --git a/arch/m68k/mm/Makefile_mm b/arch/m68k/mm/Makefile_mm
new file mode 100644
index 00000000000..5eaa43c4cb3
--- /dev/null
+++ b/arch/m68k/mm/Makefile_mm
@@ -0,0 +1,8 @@
1#
2# Makefile for the linux m68k-specific parts of the memory manager.
3#
4
5obj-y := cache.o init.o fault.o hwtest.o
6
7obj-$(CONFIG_MMU_MOTOROLA) += kmap.o memory.o motorola.o
8obj-$(CONFIG_MMU_SUN3) += sun3kmap.o sun3mmu.o
diff --git a/arch/m68knommu/mm/Makefile b/arch/m68k/mm/Makefile_no
index b54ab6b4b52..b54ab6b4b52 100644
--- a/arch/m68knommu/mm/Makefile
+++ b/arch/m68k/mm/Makefile_no
diff --git a/arch/m68k/mm/init.c b/arch/m68k/mm/init.c
index 8bc842554e5..27b5ce089a3 100644
--- a/arch/m68k/mm/init.c
+++ b/arch/m68k/mm/init.c
@@ -1,150 +1,5 @@
1/* 1#ifdef CONFIG_MMU
2 * linux/arch/m68k/mm/init.c 2#include "init_mm.c"
3 * 3#else
4 * Copyright (C) 1995 Hamish Macdonald 4#include "init_no.c"
5 *
6 * Contains common initialization routines, specific init code moved
7 * to motorola.c and sun3mmu.c
8 */
9
10#include <linux/module.h>
11#include <linux/signal.h>
12#include <linux/sched.h>
13#include <linux/mm.h>
14#include <linux/swap.h>
15#include <linux/kernel.h>
16#include <linux/string.h>
17#include <linux/types.h>
18#include <linux/init.h>
19#include <linux/bootmem.h>
20#include <linux/gfp.h>
21
22#include <asm/setup.h>
23#include <asm/uaccess.h>
24#include <asm/page.h>
25#include <asm/pgalloc.h>
26#include <asm/system.h>
27#include <asm/machdep.h>
28#include <asm/io.h>
29#ifdef CONFIG_ATARI
30#include <asm/atari_stram.h>
31#endif
32#include <asm/sections.h>
33#include <asm/tlb.h>
34
35DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
36
37pg_data_t pg_data_map[MAX_NUMNODES];
38EXPORT_SYMBOL(pg_data_map);
39
40int m68k_virt_to_node_shift;
41
42#ifndef CONFIG_SINGLE_MEMORY_CHUNK
43pg_data_t *pg_data_table[65];
44EXPORT_SYMBOL(pg_data_table);
45#endif
46
47void __init m68k_setup_node(int node)
48{
49#ifndef CONFIG_SINGLE_MEMORY_CHUNK
50 struct mem_info *info = m68k_memory + node;
51 int i, end;
52
53 i = (unsigned long)phys_to_virt(info->addr) >> __virt_to_node_shift();
54 end = (unsigned long)phys_to_virt(info->addr + info->size - 1) >> __virt_to_node_shift();
55 for (; i <= end; i++) {
56 if (pg_data_table[i])
57 printk("overlap at %u for chunk %u\n", i, node);
58 pg_data_table[i] = pg_data_map + node;
59 }
60#endif
61 pg_data_map[node].bdata = bootmem_node_data + node;
62 node_set_online(node);
63}
64
65
66/*
67 * ZERO_PAGE is a special page that is used for zero-initialized
68 * data and COW.
69 */
70
71void *empty_zero_page;
72EXPORT_SYMBOL(empty_zero_page);
73
74extern void init_pointer_table(unsigned long ptable);
75
76/* References to section boundaries */
77
78extern pmd_t *zero_pgtable;
79
80void __init mem_init(void)
81{
82 pg_data_t *pgdat;
83 int codepages = 0;
84 int datapages = 0;
85 int initpages = 0;
86 int i;
87
88#ifdef CONFIG_ATARI
89 if (MACH_IS_ATARI)
90 atari_stram_mem_init_hook();
91#endif
92
93 /* this will put all memory onto the freelists */
94 totalram_pages = num_physpages = 0;
95 for_each_online_pgdat(pgdat) {
96 num_physpages += pgdat->node_present_pages;
97
98 totalram_pages += free_all_bootmem_node(pgdat);
99 for (i = 0; i < pgdat->node_spanned_pages; i++) {
100 struct page *page = pgdat->node_mem_map + i;
101 char *addr = page_to_virt(page);
102
103 if (!PageReserved(page))
104 continue;
105 if (addr >= _text &&
106 addr < _etext)
107 codepages++;
108 else if (addr >= __init_begin &&
109 addr < __init_end)
110 initpages++;
111 else
112 datapages++;
113 }
114 }
115
116#ifndef CONFIG_SUN3
117 /* insert pointer tables allocated so far into the tablelist */
118 init_pointer_table((unsigned long)kernel_pg_dir);
119 for (i = 0; i < PTRS_PER_PGD; i++) {
120 if (pgd_present(kernel_pg_dir[i]))
121 init_pointer_table(__pgd_page(kernel_pg_dir[i]));
122 }
123
124 /* insert also pointer table that we used to unmap the zero page */
125 if (zero_pgtable)
126 init_pointer_table((unsigned long)zero_pgtable);
127#endif
128
129 printk("Memory: %luk/%luk available (%dk kernel code, %dk data, %dk init)\n",
130 nr_free_pages() << (PAGE_SHIFT-10),
131 totalram_pages << (PAGE_SHIFT-10),
132 codepages << (PAGE_SHIFT-10),
133 datapages << (PAGE_SHIFT-10),
134 initpages << (PAGE_SHIFT-10));
135}
136
137#ifdef CONFIG_BLK_DEV_INITRD
138void free_initrd_mem(unsigned long start, unsigned long end)
139{
140 int pages = 0;
141 for (; start < end; start += PAGE_SIZE) {
142 ClearPageReserved(virt_to_page(start));
143 init_page_count(virt_to_page(start));
144 free_page(start);
145 totalram_pages++;
146 pages++;
147 }
148 printk ("Freeing initrd memory: %dk freed\n", pages);
149}
150#endif 5#endif
diff --git a/arch/m68k/mm/init_mm.c b/arch/m68k/mm/init_mm.c
new file mode 100644
index 00000000000..8bc842554e5
--- /dev/null
+++ b/arch/m68k/mm/init_mm.c
@@ -0,0 +1,150 @@
1/*
2 * linux/arch/m68k/mm/init.c
3 *
4 * Copyright (C) 1995 Hamish Macdonald
5 *
6 * Contains common initialization routines, specific init code moved
7 * to motorola.c and sun3mmu.c
8 */
9
10#include <linux/module.h>
11#include <linux/signal.h>
12#include <linux/sched.h>
13#include <linux/mm.h>
14#include <linux/swap.h>
15#include <linux/kernel.h>
16#include <linux/string.h>
17#include <linux/types.h>
18#include <linux/init.h>
19#include <linux/bootmem.h>
20#include <linux/gfp.h>
21
22#include <asm/setup.h>
23#include <asm/uaccess.h>
24#include <asm/page.h>
25#include <asm/pgalloc.h>
26#include <asm/system.h>
27#include <asm/machdep.h>
28#include <asm/io.h>
29#ifdef CONFIG_ATARI
30#include <asm/atari_stram.h>
31#endif
32#include <asm/sections.h>
33#include <asm/tlb.h>
34
35DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
36
37pg_data_t pg_data_map[MAX_NUMNODES];
38EXPORT_SYMBOL(pg_data_map);
39
40int m68k_virt_to_node_shift;
41
42#ifndef CONFIG_SINGLE_MEMORY_CHUNK
43pg_data_t *pg_data_table[65];
44EXPORT_SYMBOL(pg_data_table);
45#endif
46
47void __init m68k_setup_node(int node)
48{
49#ifndef CONFIG_SINGLE_MEMORY_CHUNK
50 struct mem_info *info = m68k_memory + node;
51 int i, end;
52
53 i = (unsigned long)phys_to_virt(info->addr) >> __virt_to_node_shift();
54 end = (unsigned long)phys_to_virt(info->addr + info->size - 1) >> __virt_to_node_shift();
55 for (; i <= end; i++) {
56 if (pg_data_table[i])
57 printk("overlap at %u for chunk %u\n", i, node);
58 pg_data_table[i] = pg_data_map + node;
59 }
60#endif
61 pg_data_map[node].bdata = bootmem_node_data + node;
62 node_set_online(node);
63}
64
65
66/*
67 * ZERO_PAGE is a special page that is used for zero-initialized
68 * data and COW.
69 */
70
71void *empty_zero_page;
72EXPORT_SYMBOL(empty_zero_page);
73
74extern void init_pointer_table(unsigned long ptable);
75
76/* References to section boundaries */
77
78extern pmd_t *zero_pgtable;
79
80void __init mem_init(void)
81{
82 pg_data_t *pgdat;
83 int codepages = 0;
84 int datapages = 0;
85 int initpages = 0;
86 int i;
87
88#ifdef CONFIG_ATARI
89 if (MACH_IS_ATARI)
90 atari_stram_mem_init_hook();
91#endif
92
93 /* this will put all memory onto the freelists */
94 totalram_pages = num_physpages = 0;
95 for_each_online_pgdat(pgdat) {
96 num_physpages += pgdat->node_present_pages;
97
98 totalram_pages += free_all_bootmem_node(pgdat);
99 for (i = 0; i < pgdat->node_spanned_pages; i++) {
100 struct page *page = pgdat->node_mem_map + i;
101 char *addr = page_to_virt(page);
102
103 if (!PageReserved(page))
104 continue;
105 if (addr >= _text &&
106 addr < _etext)
107 codepages++;
108 else if (addr >= __init_begin &&
109 addr < __init_end)
110 initpages++;
111 else
112 datapages++;
113 }
114 }
115
116#ifndef CONFIG_SUN3
117 /* insert pointer tables allocated so far into the tablelist */
118 init_pointer_table((unsigned long)kernel_pg_dir);
119 for (i = 0; i < PTRS_PER_PGD; i++) {
120 if (pgd_present(kernel_pg_dir[i]))
121 init_pointer_table(__pgd_page(kernel_pg_dir[i]));
122 }
123
124 /* insert also pointer table that we used to unmap the zero page */
125 if (zero_pgtable)
126 init_pointer_table((unsigned long)zero_pgtable);
127#endif
128
129 printk("Memory: %luk/%luk available (%dk kernel code, %dk data, %dk init)\n",
130 nr_free_pages() << (PAGE_SHIFT-10),
131 totalram_pages << (PAGE_SHIFT-10),
132 codepages << (PAGE_SHIFT-10),
133 datapages << (PAGE_SHIFT-10),
134 initpages << (PAGE_SHIFT-10));
135}
136
137#ifdef CONFIG_BLK_DEV_INITRD
138void free_initrd_mem(unsigned long start, unsigned long end)
139{
140 int pages = 0;
141 for (; start < end; start += PAGE_SIZE) {
142 ClearPageReserved(virt_to_page(start));
143 init_page_count(virt_to_page(start));
144 free_page(start);
145 totalram_pages++;
146 pages++;
147 }
148 printk ("Freeing initrd memory: %dk freed\n", pages);
149}
150#endif
diff --git a/arch/m68knommu/mm/init.c b/arch/m68k/mm/init_no.c
index 8a6653f56bd..8a6653f56bd 100644
--- a/arch/m68knommu/mm/init.c
+++ b/arch/m68k/mm/init_no.c
diff --git a/arch/m68k/mm/kmap.c b/arch/m68k/mm/kmap.c
index 69345849454..a373d136b2b 100644
--- a/arch/m68k/mm/kmap.c
+++ b/arch/m68k/mm/kmap.c
@@ -1,367 +1,5 @@
1/* 1#ifdef CONFIG_MMU
2 * linux/arch/m68k/mm/kmap.c 2#include "kmap_mm.c"
3 *
4 * Copyright (C) 1997 Roman Hodek
5 *
6 * 10/01/99 cleaned up the code and changing to the same interface
7 * used by other architectures /Roman Zippel
8 */
9
10#include <linux/module.h>
11#include <linux/mm.h>
12#include <linux/kernel.h>
13#include <linux/string.h>
14#include <linux/types.h>
15#include <linux/slab.h>
16#include <linux/vmalloc.h>
17
18#include <asm/setup.h>
19#include <asm/segment.h>
20#include <asm/page.h>
21#include <asm/pgalloc.h>
22#include <asm/io.h>
23#include <asm/system.h>
24
25#undef DEBUG
26
27#define PTRTREESIZE (256*1024)
28
29/*
30 * For 040/060 we can use the virtual memory area like other architectures,
31 * but for 020/030 we want to use early termination page descriptor and we
32 * can't mix this with normal page descriptors, so we have to copy that code
33 * (mm/vmalloc.c) and return appriorate aligned addresses.
34 */
35
36#ifdef CPU_M68040_OR_M68060_ONLY
37
38#define IO_SIZE PAGE_SIZE
39
40static inline struct vm_struct *get_io_area(unsigned long size)
41{
42 return get_vm_area(size, VM_IOREMAP);
43}
44
45
46static inline void free_io_area(void *addr)
47{
48 vfree((void *)(PAGE_MASK & (unsigned long)addr));
49}
50
51#else 3#else
52 4#include "kmap_no.c"
53#define IO_SIZE (256*1024)
54
55static struct vm_struct *iolist;
56
57static struct vm_struct *get_io_area(unsigned long size)
58{
59 unsigned long addr;
60 struct vm_struct **p, *tmp, *area;
61
62 area = kmalloc(sizeof(*area), GFP_KERNEL);
63 if (!area)
64 return NULL;
65 addr = KMAP_START;
66 for (p = &iolist; (tmp = *p) ; p = &tmp->next) {
67 if (size + addr < (unsigned long)tmp->addr)
68 break;
69 if (addr > KMAP_END-size) {
70 kfree(area);
71 return NULL;
72 }
73 addr = tmp->size + (unsigned long)tmp->addr;
74 }
75 area->addr = (void *)addr;
76 area->size = size + IO_SIZE;
77 area->next = *p;
78 *p = area;
79 return area;
80}
81
82static inline void free_io_area(void *addr)
83{
84 struct vm_struct **p, *tmp;
85
86 if (!addr)
87 return;
88 addr = (void *)((unsigned long)addr & -IO_SIZE);
89 for (p = &iolist ; (tmp = *p) ; p = &tmp->next) {
90 if (tmp->addr == addr) {
91 *p = tmp->next;
92 __iounmap(tmp->addr, tmp->size);
93 kfree(tmp);
94 return;
95 }
96 }
97}
98
99#endif 5#endif
100
101/*
102 * Map some physical address range into the kernel address space.
103 */
104/* Rewritten by Andreas Schwab to remove all races. */
105
106void __iomem *__ioremap(unsigned long physaddr, unsigned long size, int cacheflag)
107{
108 struct vm_struct *area;
109 unsigned long virtaddr, retaddr;
110 long offset;
111 pgd_t *pgd_dir;
112 pmd_t *pmd_dir;
113 pte_t *pte_dir;
114
115 /*
116 * Don't allow mappings that wrap..
117 */
118 if (!size || physaddr > (unsigned long)(-size))
119 return NULL;
120
121#ifdef CONFIG_AMIGA
122 if (MACH_IS_AMIGA) {
123 if ((physaddr >= 0x40000000) && (physaddr + size < 0x60000000)
124 && (cacheflag == IOMAP_NOCACHE_SER))
125 return (void __iomem *)physaddr;
126 }
127#endif
128
129#ifdef DEBUG
130 printk("ioremap: 0x%lx,0x%lx(%d) - ", physaddr, size, cacheflag);
131#endif
132 /*
133 * Mappings have to be aligned
134 */
135 offset = physaddr & (IO_SIZE - 1);
136 physaddr &= -IO_SIZE;
137 size = (size + offset + IO_SIZE - 1) & -IO_SIZE;
138
139 /*
140 * Ok, go for it..
141 */
142 area = get_io_area(size);
143 if (!area)
144 return NULL;
145
146 virtaddr = (unsigned long)area->addr;
147 retaddr = virtaddr + offset;
148#ifdef DEBUG
149 printk("0x%lx,0x%lx,0x%lx", physaddr, virtaddr, retaddr);
150#endif
151
152 /*
153 * add cache and table flags to physical address
154 */
155 if (CPU_IS_040_OR_060) {
156 physaddr |= (_PAGE_PRESENT | _PAGE_GLOBAL040 |
157 _PAGE_ACCESSED | _PAGE_DIRTY);
158 switch (cacheflag) {
159 case IOMAP_FULL_CACHING:
160 physaddr |= _PAGE_CACHE040;
161 break;
162 case IOMAP_NOCACHE_SER:
163 default:
164 physaddr |= _PAGE_NOCACHE_S;
165 break;
166 case IOMAP_NOCACHE_NONSER:
167 physaddr |= _PAGE_NOCACHE;
168 break;
169 case IOMAP_WRITETHROUGH:
170 physaddr |= _PAGE_CACHE040W;
171 break;
172 }
173 } else {
174 physaddr |= (_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_DIRTY);
175 switch (cacheflag) {
176 case IOMAP_NOCACHE_SER:
177 case IOMAP_NOCACHE_NONSER:
178 default:
179 physaddr |= _PAGE_NOCACHE030;
180 break;
181 case IOMAP_FULL_CACHING:
182 case IOMAP_WRITETHROUGH:
183 break;
184 }
185 }
186
187 while ((long)size > 0) {
188#ifdef DEBUG
189 if (!(virtaddr & (PTRTREESIZE-1)))
190 printk ("\npa=%#lx va=%#lx ", physaddr, virtaddr);
191#endif
192 pgd_dir = pgd_offset_k(virtaddr);
193 pmd_dir = pmd_alloc(&init_mm, pgd_dir, virtaddr);
194 if (!pmd_dir) {
195 printk("ioremap: no mem for pmd_dir\n");
196 return NULL;
197 }
198
199 if (CPU_IS_020_OR_030) {
200 pmd_dir->pmd[(virtaddr/PTRTREESIZE) & 15] = physaddr;
201 physaddr += PTRTREESIZE;
202 virtaddr += PTRTREESIZE;
203 size -= PTRTREESIZE;
204 } else {
205 pte_dir = pte_alloc_kernel(pmd_dir, virtaddr);
206 if (!pte_dir) {
207 printk("ioremap: no mem for pte_dir\n");
208 return NULL;
209 }
210
211 pte_val(*pte_dir) = physaddr;
212 virtaddr += PAGE_SIZE;
213 physaddr += PAGE_SIZE;
214 size -= PAGE_SIZE;
215 }
216 }
217#ifdef DEBUG
218 printk("\n");
219#endif
220 flush_tlb_all();
221
222 return (void __iomem *)retaddr;
223}
224EXPORT_SYMBOL(__ioremap);
225
226/*
227 * Unmap a ioremap()ed region again
228 */
229void iounmap(void __iomem *addr)
230{
231#ifdef CONFIG_AMIGA
232 if ((!MACH_IS_AMIGA) ||
233 (((unsigned long)addr < 0x40000000) ||
234 ((unsigned long)addr > 0x60000000)))
235 free_io_area((__force void *)addr);
236#else
237 free_io_area((__force void *)addr);
238#endif
239}
240EXPORT_SYMBOL(iounmap);
241
242/*
243 * __iounmap unmaps nearly everything, so be careful
244 * it doesn't free currently pointer/page tables anymore but it
245 * wans't used anyway and might be added later.
246 */
247void __iounmap(void *addr, unsigned long size)
248{
249 unsigned long virtaddr = (unsigned long)addr;
250 pgd_t *pgd_dir;
251 pmd_t *pmd_dir;
252 pte_t *pte_dir;
253
254 while ((long)size > 0) {
255 pgd_dir = pgd_offset_k(virtaddr);
256 if (pgd_bad(*pgd_dir)) {
257 printk("iounmap: bad pgd(%08lx)\n", pgd_val(*pgd_dir));
258 pgd_clear(pgd_dir);
259 return;
260 }
261 pmd_dir = pmd_offset(pgd_dir, virtaddr);
262
263 if (CPU_IS_020_OR_030) {
264 int pmd_off = (virtaddr/PTRTREESIZE) & 15;
265 int pmd_type = pmd_dir->pmd[pmd_off] & _DESCTYPE_MASK;
266
267 if (pmd_type == _PAGE_PRESENT) {
268 pmd_dir->pmd[pmd_off] = 0;
269 virtaddr += PTRTREESIZE;
270 size -= PTRTREESIZE;
271 continue;
272 } else if (pmd_type == 0)
273 continue;
274 }
275
276 if (pmd_bad(*pmd_dir)) {
277 printk("iounmap: bad pmd (%08lx)\n", pmd_val(*pmd_dir));
278 pmd_clear(pmd_dir);
279 return;
280 }
281 pte_dir = pte_offset_kernel(pmd_dir, virtaddr);
282
283 pte_val(*pte_dir) = 0;
284 virtaddr += PAGE_SIZE;
285 size -= PAGE_SIZE;
286 }
287
288 flush_tlb_all();
289}
290
291/*
292 * Set new cache mode for some kernel address space.
293 * The caller must push data for that range itself, if such data may already
294 * be in the cache.
295 */
296void kernel_set_cachemode(void *addr, unsigned long size, int cmode)
297{
298 unsigned long virtaddr = (unsigned long)addr;
299 pgd_t *pgd_dir;
300 pmd_t *pmd_dir;
301 pte_t *pte_dir;
302
303 if (CPU_IS_040_OR_060) {
304 switch (cmode) {
305 case IOMAP_FULL_CACHING:
306 cmode = _PAGE_CACHE040;
307 break;
308 case IOMAP_NOCACHE_SER:
309 default:
310 cmode = _PAGE_NOCACHE_S;
311 break;
312 case IOMAP_NOCACHE_NONSER:
313 cmode = _PAGE_NOCACHE;
314 break;
315 case IOMAP_WRITETHROUGH:
316 cmode = _PAGE_CACHE040W;
317 break;
318 }
319 } else {
320 switch (cmode) {
321 case IOMAP_NOCACHE_SER:
322 case IOMAP_NOCACHE_NONSER:
323 default:
324 cmode = _PAGE_NOCACHE030;
325 break;
326 case IOMAP_FULL_CACHING:
327 case IOMAP_WRITETHROUGH:
328 cmode = 0;
329 }
330 }
331
332 while ((long)size > 0) {
333 pgd_dir = pgd_offset_k(virtaddr);
334 if (pgd_bad(*pgd_dir)) {
335 printk("iocachemode: bad pgd(%08lx)\n", pgd_val(*pgd_dir));
336 pgd_clear(pgd_dir);
337 return;
338 }
339 pmd_dir = pmd_offset(pgd_dir, virtaddr);
340
341 if (CPU_IS_020_OR_030) {
342 int pmd_off = (virtaddr/PTRTREESIZE) & 15;
343
344 if ((pmd_dir->pmd[pmd_off] & _DESCTYPE_MASK) == _PAGE_PRESENT) {
345 pmd_dir->pmd[pmd_off] = (pmd_dir->pmd[pmd_off] &
346 _CACHEMASK040) | cmode;
347 virtaddr += PTRTREESIZE;
348 size -= PTRTREESIZE;
349 continue;
350 }
351 }
352
353 if (pmd_bad(*pmd_dir)) {
354 printk("iocachemode: bad pmd (%08lx)\n", pmd_val(*pmd_dir));
355 pmd_clear(pmd_dir);
356 return;
357 }
358 pte_dir = pte_offset_kernel(pmd_dir, virtaddr);
359
360 pte_val(*pte_dir) = (pte_val(*pte_dir) & _CACHEMASK040) | cmode;
361 virtaddr += PAGE_SIZE;
362 size -= PAGE_SIZE;
363 }
364
365 flush_tlb_all();
366}
367EXPORT_SYMBOL(kernel_set_cachemode);
diff --git a/arch/m68k/mm/kmap_mm.c b/arch/m68k/mm/kmap_mm.c
new file mode 100644
index 00000000000..69345849454
--- /dev/null
+++ b/arch/m68k/mm/kmap_mm.c
@@ -0,0 +1,367 @@
1/*
2 * linux/arch/m68k/mm/kmap.c
3 *
4 * Copyright (C) 1997 Roman Hodek
5 *
6 * 10/01/99 cleaned up the code and changing to the same interface
7 * used by other architectures /Roman Zippel
8 */
9
10#include <linux/module.h>
11#include <linux/mm.h>
12#include <linux/kernel.h>
13#include <linux/string.h>
14#include <linux/types.h>
15#include <linux/slab.h>
16#include <linux/vmalloc.h>
17
18#include <asm/setup.h>
19#include <asm/segment.h>
20#include <asm/page.h>
21#include <asm/pgalloc.h>
22#include <asm/io.h>
23#include <asm/system.h>
24
25#undef DEBUG
26
27#define PTRTREESIZE (256*1024)
28
29/*
30 * For 040/060 we can use the virtual memory area like other architectures,
31 * but for 020/030 we want to use early termination page descriptor and we
32 * can't mix this with normal page descriptors, so we have to copy that code
33 * (mm/vmalloc.c) and return appriorate aligned addresses.
34 */
35
36#ifdef CPU_M68040_OR_M68060_ONLY
37
38#define IO_SIZE PAGE_SIZE
39
40static inline struct vm_struct *get_io_area(unsigned long size)
41{
42 return get_vm_area(size, VM_IOREMAP);
43}
44
45
46static inline void free_io_area(void *addr)
47{
48 vfree((void *)(PAGE_MASK & (unsigned long)addr));
49}
50
51#else
52
53#define IO_SIZE (256*1024)
54
55static struct vm_struct *iolist;
56
57static struct vm_struct *get_io_area(unsigned long size)
58{
59 unsigned long addr;
60 struct vm_struct **p, *tmp, *area;
61
62 area = kmalloc(sizeof(*area), GFP_KERNEL);
63 if (!area)
64 return NULL;
65 addr = KMAP_START;
66 for (p = &iolist; (tmp = *p) ; p = &tmp->next) {
67 if (size + addr < (unsigned long)tmp->addr)
68 break;
69 if (addr > KMAP_END-size) {
70 kfree(area);
71 return NULL;
72 }
73 addr = tmp->size + (unsigned long)tmp->addr;
74 }
75 area->addr = (void *)addr;
76 area->size = size + IO_SIZE;
77 area->next = *p;
78 *p = area;
79 return area;
80}
81
82static inline void free_io_area(void *addr)
83{
84 struct vm_struct **p, *tmp;
85
86 if (!addr)
87 return;
88 addr = (void *)((unsigned long)addr & -IO_SIZE);
89 for (p = &iolist ; (tmp = *p) ; p = &tmp->next) {
90 if (tmp->addr == addr) {
91 *p = tmp->next;
92 __iounmap(tmp->addr, tmp->size);
93 kfree(tmp);
94 return;
95 }
96 }
97}
98
99#endif
100
101/*
102 * Map some physical address range into the kernel address space.
103 */
104/* Rewritten by Andreas Schwab to remove all races. */
105
106void __iomem *__ioremap(unsigned long physaddr, unsigned long size, int cacheflag)
107{
108 struct vm_struct *area;
109 unsigned long virtaddr, retaddr;
110 long offset;
111 pgd_t *pgd_dir;
112 pmd_t *pmd_dir;
113 pte_t *pte_dir;
114
115 /*
116 * Don't allow mappings that wrap..
117 */
118 if (!size || physaddr > (unsigned long)(-size))
119 return NULL;
120
121#ifdef CONFIG_AMIGA
122 if (MACH_IS_AMIGA) {
123 if ((physaddr >= 0x40000000) && (physaddr + size < 0x60000000)
124 && (cacheflag == IOMAP_NOCACHE_SER))
125 return (void __iomem *)physaddr;
126 }
127#endif
128
129#ifdef DEBUG
130 printk("ioremap: 0x%lx,0x%lx(%d) - ", physaddr, size, cacheflag);
131#endif
132 /*
133 * Mappings have to be aligned
134 */
135 offset = physaddr & (IO_SIZE - 1);
136 physaddr &= -IO_SIZE;
137 size = (size + offset + IO_SIZE - 1) & -IO_SIZE;
138
139 /*
140 * Ok, go for it..
141 */
142 area = get_io_area(size);
143 if (!area)
144 return NULL;
145
146 virtaddr = (unsigned long)area->addr;
147 retaddr = virtaddr + offset;
148#ifdef DEBUG
149 printk("0x%lx,0x%lx,0x%lx", physaddr, virtaddr, retaddr);
150#endif
151
152 /*
153 * add cache and table flags to physical address
154 */
155 if (CPU_IS_040_OR_060) {
156 physaddr |= (_PAGE_PRESENT | _PAGE_GLOBAL040 |
157 _PAGE_ACCESSED | _PAGE_DIRTY);
158 switch (cacheflag) {
159 case IOMAP_FULL_CACHING:
160 physaddr |= _PAGE_CACHE040;
161 break;
162 case IOMAP_NOCACHE_SER:
163 default:
164 physaddr |= _PAGE_NOCACHE_S;
165 break;
166 case IOMAP_NOCACHE_NONSER:
167 physaddr |= _PAGE_NOCACHE;
168 break;
169 case IOMAP_WRITETHROUGH:
170 physaddr |= _PAGE_CACHE040W;
171 break;
172 }
173 } else {
174 physaddr |= (_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_DIRTY);
175 switch (cacheflag) {
176 case IOMAP_NOCACHE_SER:
177 case IOMAP_NOCACHE_NONSER:
178 default:
179 physaddr |= _PAGE_NOCACHE030;
180 break;
181 case IOMAP_FULL_CACHING:
182 case IOMAP_WRITETHROUGH:
183 break;
184 }
185 }
186
187 while ((long)size > 0) {
188#ifdef DEBUG
189 if (!(virtaddr & (PTRTREESIZE-1)))
190 printk ("\npa=%#lx va=%#lx ", physaddr, virtaddr);
191#endif
192 pgd_dir = pgd_offset_k(virtaddr);
193 pmd_dir = pmd_alloc(&init_mm, pgd_dir, virtaddr);
194 if (!pmd_dir) {
195 printk("ioremap: no mem for pmd_dir\n");
196 return NULL;
197 }
198
199 if (CPU_IS_020_OR_030) {
200 pmd_dir->pmd[(virtaddr/PTRTREESIZE) & 15] = physaddr;
201 physaddr += PTRTREESIZE;
202 virtaddr += PTRTREESIZE;
203 size -= PTRTREESIZE;
204 } else {
205 pte_dir = pte_alloc_kernel(pmd_dir, virtaddr);
206 if (!pte_dir) {
207 printk("ioremap: no mem for pte_dir\n");
208 return NULL;
209 }
210
211 pte_val(*pte_dir) = physaddr;
212 virtaddr += PAGE_SIZE;
213 physaddr += PAGE_SIZE;
214 size -= PAGE_SIZE;
215 }
216 }
217#ifdef DEBUG
218 printk("\n");
219#endif
220 flush_tlb_all();
221
222 return (void __iomem *)retaddr;
223}
224EXPORT_SYMBOL(__ioremap);
225
226/*
227 * Unmap a ioremap()ed region again
228 */
229void iounmap(void __iomem *addr)
230{
231#ifdef CONFIG_AMIGA
232 if ((!MACH_IS_AMIGA) ||
233 (((unsigned long)addr < 0x40000000) ||
234 ((unsigned long)addr > 0x60000000)))
235 free_io_area((__force void *)addr);
236#else
237 free_io_area((__force void *)addr);
238#endif
239}
240EXPORT_SYMBOL(iounmap);
241
242/*
243 * __iounmap unmaps nearly everything, so be careful
244 * it doesn't free currently pointer/page tables anymore but it
245 * wans't used anyway and might be added later.
246 */
247void __iounmap(void *addr, unsigned long size)
248{
249 unsigned long virtaddr = (unsigned long)addr;
250 pgd_t *pgd_dir;
251 pmd_t *pmd_dir;
252 pte_t *pte_dir;
253
254 while ((long)size > 0) {
255 pgd_dir = pgd_offset_k(virtaddr);
256 if (pgd_bad(*pgd_dir)) {
257 printk("iounmap: bad pgd(%08lx)\n", pgd_val(*pgd_dir));
258 pgd_clear(pgd_dir);
259 return;
260 }
261 pmd_dir = pmd_offset(pgd_dir, virtaddr);
262
263 if (CPU_IS_020_OR_030) {
264 int pmd_off = (virtaddr/PTRTREESIZE) & 15;
265 int pmd_type = pmd_dir->pmd[pmd_off] & _DESCTYPE_MASK;
266
267 if (pmd_type == _PAGE_PRESENT) {
268 pmd_dir->pmd[pmd_off] = 0;
269 virtaddr += PTRTREESIZE;
270 size -= PTRTREESIZE;
271 continue;
272 } else if (pmd_type == 0)
273 continue;
274 }
275
276 if (pmd_bad(*pmd_dir)) {
277 printk("iounmap: bad pmd (%08lx)\n", pmd_val(*pmd_dir));
278 pmd_clear(pmd_dir);
279 return;
280 }
281 pte_dir = pte_offset_kernel(pmd_dir, virtaddr);
282
283 pte_val(*pte_dir) = 0;
284 virtaddr += PAGE_SIZE;
285 size -= PAGE_SIZE;
286 }
287
288 flush_tlb_all();
289}
290
291/*
292 * Set new cache mode for some kernel address space.
293 * The caller must push data for that range itself, if such data may already
294 * be in the cache.
295 */
296void kernel_set_cachemode(void *addr, unsigned long size, int cmode)
297{
298 unsigned long virtaddr = (unsigned long)addr;
299 pgd_t *pgd_dir;
300 pmd_t *pmd_dir;
301 pte_t *pte_dir;
302
303 if (CPU_IS_040_OR_060) {
304 switch (cmode) {
305 case IOMAP_FULL_CACHING:
306 cmode = _PAGE_CACHE040;
307 break;
308 case IOMAP_NOCACHE_SER:
309 default:
310 cmode = _PAGE_NOCACHE_S;
311 break;
312 case IOMAP_NOCACHE_NONSER:
313 cmode = _PAGE_NOCACHE;
314 break;
315 case IOMAP_WRITETHROUGH:
316 cmode = _PAGE_CACHE040W;
317 break;
318 }
319 } else {
320 switch (cmode) {
321 case IOMAP_NOCACHE_SER:
322 case IOMAP_NOCACHE_NONSER:
323 default:
324 cmode = _PAGE_NOCACHE030;
325 break;
326 case IOMAP_FULL_CACHING:
327 case IOMAP_WRITETHROUGH:
328 cmode = 0;
329 }
330 }
331
332 while ((long)size > 0) {
333 pgd_dir = pgd_offset_k(virtaddr);
334 if (pgd_bad(*pgd_dir)) {
335 printk("iocachemode: bad pgd(%08lx)\n", pgd_val(*pgd_dir));
336 pgd_clear(pgd_dir);
337 return;
338 }
339 pmd_dir = pmd_offset(pgd_dir, virtaddr);
340
341 if (CPU_IS_020_OR_030) {
342 int pmd_off = (virtaddr/PTRTREESIZE) & 15;
343
344 if ((pmd_dir->pmd[pmd_off] & _DESCTYPE_MASK) == _PAGE_PRESENT) {
345 pmd_dir->pmd[pmd_off] = (pmd_dir->pmd[pmd_off] &
346 _CACHEMASK040) | cmode;
347 virtaddr += PTRTREESIZE;
348 size -= PTRTREESIZE;
349 continue;
350 }
351 }
352
353 if (pmd_bad(*pmd_dir)) {
354 printk("iocachemode: bad pmd (%08lx)\n", pmd_val(*pmd_dir));
355 pmd_clear(pmd_dir);
356 return;
357 }
358 pte_dir = pte_offset_kernel(pmd_dir, virtaddr);
359
360 pte_val(*pte_dir) = (pte_val(*pte_dir) & _CACHEMASK040) | cmode;
361 virtaddr += PAGE_SIZE;
362 size -= PAGE_SIZE;
363 }
364
365 flush_tlb_all();
366}
367EXPORT_SYMBOL(kernel_set_cachemode);
diff --git a/arch/m68knommu/mm/kmap.c b/arch/m68k/mm/kmap_no.c
index ece8d5ad4e6..ece8d5ad4e6 100644
--- a/arch/m68knommu/mm/kmap.c
+++ b/arch/m68k/mm/kmap_no.c
diff --git a/arch/m68knommu/platform/5206/Makefile b/arch/m68k/platform/5206/Makefile
index b5db05625cf..b5db05625cf 100644
--- a/arch/m68knommu/platform/5206/Makefile
+++ b/arch/m68k/platform/5206/Makefile
diff --git a/arch/m68knommu/platform/5206/config.c b/arch/m68k/platform/5206/config.c
index 9c335465e66..9c335465e66 100644
--- a/arch/m68knommu/platform/5206/config.c
+++ b/arch/m68k/platform/5206/config.c
diff --git a/arch/m68knommu/platform/5206/gpio.c b/arch/m68k/platform/5206/gpio.c
index b9ab4a120f2..b9ab4a120f2 100644
--- a/arch/m68knommu/platform/5206/gpio.c
+++ b/arch/m68k/platform/5206/gpio.c
diff --git a/arch/m68knommu/platform/5206e/Makefile b/arch/m68k/platform/5206e/Makefile
index b5db05625cf..b5db05625cf 100644
--- a/arch/m68knommu/platform/5206e/Makefile
+++ b/arch/m68k/platform/5206e/Makefile
diff --git a/arch/m68knommu/platform/5206e/config.c b/arch/m68k/platform/5206e/config.c
index 942397984c6..942397984c6 100644
--- a/arch/m68knommu/platform/5206e/config.c
+++ b/arch/m68k/platform/5206e/config.c
diff --git a/arch/m68knommu/platform/5206e/gpio.c b/arch/m68k/platform/5206e/gpio.c
index b9ab4a120f2..b9ab4a120f2 100644
--- a/arch/m68knommu/platform/5206e/gpio.c
+++ b/arch/m68k/platform/5206e/gpio.c
diff --git a/arch/m68knommu/platform/520x/Makefile b/arch/m68k/platform/520x/Makefile
index ad3f4e5a57c..ad3f4e5a57c 100644
--- a/arch/m68knommu/platform/520x/Makefile
+++ b/arch/m68k/platform/520x/Makefile
diff --git a/arch/m68knommu/platform/520x/config.c b/arch/m68k/platform/520x/config.c
index 621238f1a21..621238f1a21 100644
--- a/arch/m68knommu/platform/520x/config.c
+++ b/arch/m68k/platform/520x/config.c
diff --git a/arch/m68knommu/platform/520x/gpio.c b/arch/m68k/platform/520x/gpio.c
index d757328563d..d757328563d 100644
--- a/arch/m68knommu/platform/520x/gpio.c
+++ b/arch/m68k/platform/520x/gpio.c
diff --git a/arch/m68knommu/platform/523x/Makefile b/arch/m68k/platform/523x/Makefile
index c04b8f71c88..c04b8f71c88 100644
--- a/arch/m68knommu/platform/523x/Makefile
+++ b/arch/m68k/platform/523x/Makefile
diff --git a/arch/m68knommu/platform/523x/config.c b/arch/m68k/platform/523x/config.c
index 418a76feb1e..418a76feb1e 100644
--- a/arch/m68knommu/platform/523x/config.c
+++ b/arch/m68k/platform/523x/config.c
diff --git a/arch/m68knommu/platform/523x/gpio.c b/arch/m68k/platform/523x/gpio.c
index 327ebf142c8..327ebf142c8 100644
--- a/arch/m68knommu/platform/523x/gpio.c
+++ b/arch/m68k/platform/523x/gpio.c
diff --git a/arch/m68knommu/platform/5249/Makefile b/arch/m68k/platform/5249/Makefile
index 4bed30fd007..4bed30fd007 100644
--- a/arch/m68knommu/platform/5249/Makefile
+++ b/arch/m68k/platform/5249/Makefile
diff --git a/arch/m68knommu/platform/5249/config.c b/arch/m68k/platform/5249/config.c
index ceb31e5744a..ceb31e5744a 100644
--- a/arch/m68knommu/platform/5249/config.c
+++ b/arch/m68k/platform/5249/config.c
diff --git a/arch/m68knommu/platform/5249/gpio.c b/arch/m68k/platform/5249/gpio.c
index 2b56c6ef65b..2b56c6ef65b 100644
--- a/arch/m68knommu/platform/5249/gpio.c
+++ b/arch/m68k/platform/5249/gpio.c
diff --git a/arch/m68knommu/platform/5249/intc2.c b/arch/m68k/platform/5249/intc2.c
index 8f4b63e1736..8f4b63e1736 100644
--- a/arch/m68knommu/platform/5249/intc2.c
+++ b/arch/m68k/platform/5249/intc2.c
diff --git a/arch/m68knommu/platform/5272/Makefile b/arch/m68k/platform/5272/Makefile
index 34110fc1430..34110fc1430 100644
--- a/arch/m68knommu/platform/5272/Makefile
+++ b/arch/m68k/platform/5272/Makefile
diff --git a/arch/m68knommu/platform/5272/config.c b/arch/m68k/platform/5272/config.c
index 65bb582734e..65bb582734e 100644
--- a/arch/m68knommu/platform/5272/config.c
+++ b/arch/m68k/platform/5272/config.c
diff --git a/arch/m68knommu/platform/5272/gpio.c b/arch/m68k/platform/5272/gpio.c
index 57ac10a5d7f..57ac10a5d7f 100644
--- a/arch/m68knommu/platform/5272/gpio.c
+++ b/arch/m68k/platform/5272/gpio.c
diff --git a/arch/m68knommu/platform/5272/intc.c b/arch/m68k/platform/5272/intc.c
index 969ff0a467c..969ff0a467c 100644
--- a/arch/m68knommu/platform/5272/intc.c
+++ b/arch/m68k/platform/5272/intc.c
diff --git a/arch/m68knommu/platform/527x/Makefile b/arch/m68k/platform/527x/Makefile
index 6ac4b57370e..6ac4b57370e 100644
--- a/arch/m68knommu/platform/527x/Makefile
+++ b/arch/m68k/platform/527x/Makefile
diff --git a/arch/m68knommu/platform/527x/config.c b/arch/m68k/platform/527x/config.c
index fa359593b61..fa359593b61 100644
--- a/arch/m68knommu/platform/527x/config.c
+++ b/arch/m68k/platform/527x/config.c
diff --git a/arch/m68knommu/platform/527x/gpio.c b/arch/m68k/platform/527x/gpio.c
index 205da0aa0f2..205da0aa0f2 100644
--- a/arch/m68knommu/platform/527x/gpio.c
+++ b/arch/m68k/platform/527x/gpio.c
diff --git a/arch/m68knommu/platform/528x/Makefile b/arch/m68k/platform/528x/Makefile
index 6ac4b57370e..6ac4b57370e 100644
--- a/arch/m68knommu/platform/528x/Makefile
+++ b/arch/m68k/platform/528x/Makefile
diff --git a/arch/m68knommu/platform/528x/config.c b/arch/m68k/platform/528x/config.c
index ac39fc66121..ac39fc66121 100644
--- a/arch/m68knommu/platform/528x/config.c
+++ b/arch/m68k/platform/528x/config.c
diff --git a/arch/m68knommu/platform/528x/gpio.c b/arch/m68k/platform/528x/gpio.c
index 526db665d87..526db665d87 100644
--- a/arch/m68knommu/platform/528x/gpio.c
+++ b/arch/m68k/platform/528x/gpio.c
diff --git a/arch/m68knommu/platform/5307/Makefile b/arch/m68k/platform/5307/Makefile
index d4293b791f2..d4293b791f2 100644
--- a/arch/m68knommu/platform/5307/Makefile
+++ b/arch/m68k/platform/5307/Makefile
diff --git a/arch/m68knommu/platform/5307/config.c b/arch/m68k/platform/5307/config.c
index 00900ac06a9..00900ac06a9 100644
--- a/arch/m68knommu/platform/5307/config.c
+++ b/arch/m68k/platform/5307/config.c
diff --git a/arch/m68knommu/platform/5307/gpio.c b/arch/m68k/platform/5307/gpio.c
index 5850612b4a3..5850612b4a3 100644
--- a/arch/m68knommu/platform/5307/gpio.c
+++ b/arch/m68k/platform/5307/gpio.c
diff --git a/arch/m68knommu/platform/5307/nettel.c b/arch/m68k/platform/5307/nettel.c
index e925ea4602f..e925ea4602f 100644
--- a/arch/m68knommu/platform/5307/nettel.c
+++ b/arch/m68k/platform/5307/nettel.c
diff --git a/arch/m68knommu/platform/532x/Makefile b/arch/m68k/platform/532x/Makefile
index ce01669399c..ce01669399c 100644
--- a/arch/m68knommu/platform/532x/Makefile
+++ b/arch/m68k/platform/532x/Makefile
diff --git a/arch/m68knommu/platform/532x/config.c b/arch/m68k/platform/532x/config.c
index ca51323f957..ca51323f957 100644
--- a/arch/m68knommu/platform/532x/config.c
+++ b/arch/m68k/platform/532x/config.c
diff --git a/arch/m68knommu/platform/532x/gpio.c b/arch/m68k/platform/532x/gpio.c
index 212a85deac9..212a85deac9 100644
--- a/arch/m68knommu/platform/532x/gpio.c
+++ b/arch/m68k/platform/532x/gpio.c
diff --git a/arch/m68knommu/platform/5407/Makefile b/arch/m68k/platform/5407/Makefile
index e83fe148edd..e83fe148edd 100644
--- a/arch/m68knommu/platform/5407/Makefile
+++ b/arch/m68k/platform/5407/Makefile
diff --git a/arch/m68knommu/platform/5407/config.c b/arch/m68k/platform/5407/config.c
index 70ea789a400..70ea789a400 100644
--- a/arch/m68knommu/platform/5407/config.c
+++ b/arch/m68k/platform/5407/config.c
diff --git a/arch/m68knommu/platform/5407/gpio.c b/arch/m68k/platform/5407/gpio.c
index 5850612b4a3..5850612b4a3 100644
--- a/arch/m68knommu/platform/5407/gpio.c
+++ b/arch/m68k/platform/5407/gpio.c
diff --git a/arch/m68knommu/platform/54xx/Makefile b/arch/m68k/platform/54xx/Makefile
index 6cfd090ec3c..6cfd090ec3c 100644
--- a/arch/m68knommu/platform/54xx/Makefile
+++ b/arch/m68k/platform/54xx/Makefile
diff --git a/arch/m68knommu/platform/54xx/config.c b/arch/m68k/platform/54xx/config.c
index 78130984db9..78130984db9 100644
--- a/arch/m68knommu/platform/54xx/config.c
+++ b/arch/m68k/platform/54xx/config.c
diff --git a/arch/m68knommu/platform/54xx/firebee.c b/arch/m68k/platform/54xx/firebee.c
index 46d50534f98..46d50534f98 100644
--- a/arch/m68knommu/platform/54xx/firebee.c
+++ b/arch/m68k/platform/54xx/firebee.c
diff --git a/arch/m68knommu/platform/68328/Makefile b/arch/m68k/platform/68328/Makefile
index 5e5435552d5..5e5435552d5 100644
--- a/arch/m68knommu/platform/68328/Makefile
+++ b/arch/m68k/platform/68328/Makefile
diff --git a/arch/m68knommu/platform/68328/bootlogo.h b/arch/m68k/platform/68328/bootlogo.h
index 67bc2c17386..67bc2c17386 100644
--- a/arch/m68knommu/platform/68328/bootlogo.h
+++ b/arch/m68k/platform/68328/bootlogo.h
diff --git a/arch/m68knommu/platform/68328/bootlogo.pl b/arch/m68k/platform/68328/bootlogo.pl
index b04ae3f50da..b04ae3f50da 100644
--- a/arch/m68knommu/platform/68328/bootlogo.pl
+++ b/arch/m68k/platform/68328/bootlogo.pl
diff --git a/arch/m68knommu/platform/68328/config.c b/arch/m68k/platform/68328/config.c
index a7bd21deb00..a7bd21deb00 100644
--- a/arch/m68knommu/platform/68328/config.c
+++ b/arch/m68k/platform/68328/config.c
diff --git a/arch/m68knommu/platform/68328/entry.S b/arch/m68k/platform/68328/entry.S
index 676960cf022..676960cf022 100644
--- a/arch/m68knommu/platform/68328/entry.S
+++ b/arch/m68k/platform/68328/entry.S
diff --git a/arch/m68knommu/platform/68328/head-de2.S b/arch/m68k/platform/68328/head-de2.S
index f632fdcb93e..f632fdcb93e 100644
--- a/arch/m68knommu/platform/68328/head-de2.S
+++ b/arch/m68k/platform/68328/head-de2.S
diff --git a/arch/m68knommu/platform/68328/head-pilot.S b/arch/m68k/platform/68328/head-pilot.S
index aecff532b34..aecff532b34 100644
--- a/arch/m68knommu/platform/68328/head-pilot.S
+++ b/arch/m68k/platform/68328/head-pilot.S
diff --git a/arch/m68knommu/platform/68328/head-ram.S b/arch/m68k/platform/68328/head-ram.S
index 7f1aeeacb21..7f1aeeacb21 100644
--- a/arch/m68knommu/platform/68328/head-ram.S
+++ b/arch/m68k/platform/68328/head-ram.S
diff --git a/arch/m68knommu/platform/68328/head-rom.S b/arch/m68k/platform/68328/head-rom.S
index 6ec77d3ea0b..6ec77d3ea0b 100644
--- a/arch/m68knommu/platform/68328/head-rom.S
+++ b/arch/m68k/platform/68328/head-rom.S
diff --git a/arch/m68knommu/platform/68328/ints.c b/arch/m68k/platform/68328/ints.c
index e5631831a20..e5631831a20 100644
--- a/arch/m68knommu/platform/68328/ints.c
+++ b/arch/m68k/platform/68328/ints.c
diff --git a/arch/m68knommu/platform/68328/romvec.S b/arch/m68k/platform/68328/romvec.S
index 31084466eae..31084466eae 100644
--- a/arch/m68knommu/platform/68328/romvec.S
+++ b/arch/m68k/platform/68328/romvec.S
diff --git a/arch/m68knommu/platform/68328/timers.c b/arch/m68k/platform/68328/timers.c
index 309f725995b..309f725995b 100644
--- a/arch/m68knommu/platform/68328/timers.c
+++ b/arch/m68k/platform/68328/timers.c
diff --git a/arch/m68knommu/platform/68360/Makefile b/arch/m68k/platform/68360/Makefile
index cf5af73a578..cf5af73a578 100644
--- a/arch/m68knommu/platform/68360/Makefile
+++ b/arch/m68k/platform/68360/Makefile
diff --git a/arch/m68knommu/platform/68360/commproc.c b/arch/m68k/platform/68360/commproc.c
index 8e4e10cc008..8e4e10cc008 100644
--- a/arch/m68knommu/platform/68360/commproc.c
+++ b/arch/m68k/platform/68360/commproc.c
diff --git a/arch/m68knommu/platform/68360/config.c b/arch/m68k/platform/68360/config.c
index 9dd5bca3874..9dd5bca3874 100644
--- a/arch/m68knommu/platform/68360/config.c
+++ b/arch/m68k/platform/68360/config.c
diff --git a/arch/m68knommu/platform/68360/entry.S b/arch/m68k/platform/68360/entry.S
index 46c1b18c9dc..46c1b18c9dc 100644
--- a/arch/m68knommu/platform/68360/entry.S
+++ b/arch/m68k/platform/68360/entry.S
diff --git a/arch/m68knommu/platform/68360/head-ram.S b/arch/m68k/platform/68360/head-ram.S
index 8eb94fb6b97..8eb94fb6b97 100644
--- a/arch/m68knommu/platform/68360/head-ram.S
+++ b/arch/m68k/platform/68360/head-ram.S
diff --git a/arch/m68knommu/platform/68360/head-rom.S b/arch/m68k/platform/68360/head-rom.S
index 97510e55b80..97510e55b80 100644
--- a/arch/m68knommu/platform/68360/head-rom.S
+++ b/arch/m68k/platform/68360/head-rom.S
diff --git a/arch/m68knommu/platform/68360/ints.c b/arch/m68k/platform/68360/ints.c
index 8de3feb568c..8de3feb568c 100644
--- a/arch/m68knommu/platform/68360/ints.c
+++ b/arch/m68k/platform/68360/ints.c
diff --git a/arch/m68knommu/platform/68EZ328/Makefile b/arch/m68k/platform/68EZ328/Makefile
index ee97735a242..ee97735a242 100644
--- a/arch/m68knommu/platform/68EZ328/Makefile
+++ b/arch/m68k/platform/68EZ328/Makefile
diff --git a/arch/m68knommu/platform/68EZ328/bootlogo.h b/arch/m68k/platform/68EZ328/bootlogo.h
index e842bdae583..e842bdae583 100644
--- a/arch/m68knommu/platform/68EZ328/bootlogo.h
+++ b/arch/m68k/platform/68EZ328/bootlogo.h
diff --git a/arch/m68knommu/platform/68EZ328/config.c b/arch/m68k/platform/68EZ328/config.c
index 1be1a16f689..1be1a16f689 100644
--- a/arch/m68knommu/platform/68EZ328/config.c
+++ b/arch/m68k/platform/68EZ328/config.c
diff --git a/arch/m68knommu/platform/68VZ328/Makefile b/arch/m68k/platform/68VZ328/Makefile
index 447ffa0fd7c..447ffa0fd7c 100644
--- a/arch/m68knommu/platform/68VZ328/Makefile
+++ b/arch/m68k/platform/68VZ328/Makefile
diff --git a/arch/m68knommu/platform/68VZ328/config.c b/arch/m68k/platform/68VZ328/config.c
index eabaabe8af3..eabaabe8af3 100644
--- a/arch/m68knommu/platform/68VZ328/config.c
+++ b/arch/m68k/platform/68VZ328/config.c
diff --git a/arch/m68knommu/platform/Makefile b/arch/m68k/platform/Makefile
index fc932bf65d3..fc932bf65d3 100644
--- a/arch/m68knommu/platform/Makefile
+++ b/arch/m68k/platform/Makefile
diff --git a/arch/m68knommu/platform/coldfire/Makefile b/arch/m68k/platform/coldfire/Makefile
index a8967baabd7..a8967baabd7 100644
--- a/arch/m68knommu/platform/coldfire/Makefile
+++ b/arch/m68k/platform/coldfire/Makefile
diff --git a/arch/m68knommu/platform/coldfire/cache.c b/arch/m68k/platform/coldfire/cache.c
index 235d3c4f4f0..235d3c4f4f0 100644
--- a/arch/m68knommu/platform/coldfire/cache.c
+++ b/arch/m68k/platform/coldfire/cache.c
diff --git a/arch/m68knommu/platform/coldfire/clk.c b/arch/m68k/platform/coldfire/clk.c
index 9f1260c5e2a..9f1260c5e2a 100644
--- a/arch/m68knommu/platform/coldfire/clk.c
+++ b/arch/m68k/platform/coldfire/clk.c
diff --git a/arch/m68knommu/platform/coldfire/dma.c b/arch/m68k/platform/coldfire/dma.c
index e88b95e2cc6..e88b95e2cc6 100644
--- a/arch/m68knommu/platform/coldfire/dma.c
+++ b/arch/m68k/platform/coldfire/dma.c
diff --git a/arch/m68knommu/platform/coldfire/dma_timer.c b/arch/m68k/platform/coldfire/dma_timer.c
index a5f562823d7..a5f562823d7 100644
--- a/arch/m68knommu/platform/coldfire/dma_timer.c
+++ b/arch/m68k/platform/coldfire/dma_timer.c
diff --git a/arch/m68knommu/platform/coldfire/entry.S b/arch/m68k/platform/coldfire/entry.S
index 5837cf080b6..5837cf080b6 100644
--- a/arch/m68knommu/platform/coldfire/entry.S
+++ b/arch/m68k/platform/coldfire/entry.S
diff --git a/arch/m68knommu/platform/coldfire/gpio.c b/arch/m68k/platform/coldfire/gpio.c
index ff004579345..ff004579345 100644
--- a/arch/m68knommu/platform/coldfire/gpio.c
+++ b/arch/m68k/platform/coldfire/gpio.c
diff --git a/arch/m68knommu/platform/coldfire/head.S b/arch/m68k/platform/coldfire/head.S
index 129bff4956b..129bff4956b 100644
--- a/arch/m68knommu/platform/coldfire/head.S
+++ b/arch/m68k/platform/coldfire/head.S
diff --git a/arch/m68knommu/platform/coldfire/intc-2.c b/arch/m68k/platform/coldfire/intc-2.c
index 2cbfbf035db..2cbfbf035db 100644
--- a/arch/m68knommu/platform/coldfire/intc-2.c
+++ b/arch/m68k/platform/coldfire/intc-2.c
diff --git a/arch/m68knommu/platform/coldfire/intc-simr.c b/arch/m68k/platform/coldfire/intc-simr.c
index e642b24ab72..e642b24ab72 100644
--- a/arch/m68knommu/platform/coldfire/intc-simr.c
+++ b/arch/m68k/platform/coldfire/intc-simr.c
diff --git a/arch/m68knommu/platform/coldfire/intc.c b/arch/m68k/platform/coldfire/intc.c
index d648081a63f..d648081a63f 100644
--- a/arch/m68knommu/platform/coldfire/intc.c
+++ b/arch/m68k/platform/coldfire/intc.c
diff --git a/arch/m68knommu/platform/coldfire/pinmux.c b/arch/m68k/platform/coldfire/pinmux.c
index 8c62b825939..8c62b825939 100644
--- a/arch/m68knommu/platform/coldfire/pinmux.c
+++ b/arch/m68k/platform/coldfire/pinmux.c
diff --git a/arch/m68knommu/platform/coldfire/pit.c b/arch/m68k/platform/coldfire/pit.c
index c2b980926be..c2b980926be 100644
--- a/arch/m68knommu/platform/coldfire/pit.c
+++ b/arch/m68k/platform/coldfire/pit.c
diff --git a/arch/m68knommu/platform/coldfire/sltimers.c b/arch/m68k/platform/coldfire/sltimers.c
index 0a1b937c3e1..0a1b937c3e1 100644
--- a/arch/m68knommu/platform/coldfire/sltimers.c
+++ b/arch/m68k/platform/coldfire/sltimers.c
diff --git a/arch/m68knommu/platform/coldfire/timers.c b/arch/m68k/platform/coldfire/timers.c
index 60242f65fea..60242f65fea 100644
--- a/arch/m68knommu/platform/coldfire/timers.c
+++ b/arch/m68k/platform/coldfire/timers.c
diff --git a/arch/m68knommu/platform/coldfire/vectors.c b/arch/m68k/platform/coldfire/vectors.c
index a21d3f870b7..a21d3f870b7 100644
--- a/arch/m68knommu/platform/coldfire/vectors.c
+++ b/arch/m68k/platform/coldfire/vectors.c
diff --git a/arch/m68knommu/Kconfig.debug b/arch/m68knommu/Kconfig.debug
deleted file mode 100644
index ed6d9a83bfd..00000000000
--- a/arch/m68knommu/Kconfig.debug
+++ /dev/null
@@ -1,35 +0,0 @@
1menu "Kernel hacking"
2
3source "lib/Kconfig.debug"
4
5config FULLDEBUG
6 bool "Full Symbolic/Source Debugging support"
7 help
8 Enable debugging symbols on kernel build.
9
10config HIGHPROFILE
11 bool "Use fast second timer for profiling"
12 depends on COLDFIRE
13 help
14 Use a fast secondary clock to produce profiling information.
15
16config BOOTPARAM
17 bool 'Compiled-in Kernel Boot Parameter'
18
19config BOOTPARAM_STRING
20 string 'Kernel Boot Parameter'
21 default 'console=ttyS0,19200'
22 depends on BOOTPARAM
23
24config NO_KERNEL_MSG
25 bool "Suppress Kernel BUG Messages"
26 help
27 Do not output any debug BUG messages within the kernel.
28
29config BDM_DISABLE
30 bool "Disable BDM signals"
31 depends on (EXPERIMENTAL && COLDFIRE)
32 help
33 Disable the ColdFire CPU's BDM signals.
34
35endmenu
diff --git a/arch/m68knommu/defconfig b/arch/m68knommu/defconfig
deleted file mode 100644
index 2f5655c577a..00000000000
--- a/arch/m68knommu/defconfig
+++ /dev/null
@@ -1,74 +0,0 @@
1CONFIG_EXPERIMENTAL=y
2CONFIG_LOG_BUF_SHIFT=14
3# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
4CONFIG_EXPERT=y
5# CONFIG_KALLSYMS is not set
6# CONFIG_HOTPLUG is not set
7# CONFIG_FUTEX is not set
8# CONFIG_EPOLL is not set
9# CONFIG_SIGNALFD is not set
10# CONFIG_TIMERFD is not set
11# CONFIG_EVENTFD is not set
12# CONFIG_AIO is not set
13# CONFIG_VM_EVENT_COUNTERS is not set
14# CONFIG_COMPAT_BRK is not set
15# CONFIG_BLK_DEV_BSG is not set
16# CONFIG_IOSCHED_DEADLINE is not set
17# CONFIG_IOSCHED_CFQ is not set
18CONFIG_M520x=y
19CONFIG_CLOCK_SET=y
20CONFIG_CLOCK_FREQ=166666666
21CONFIG_CLOCK_DIV=2
22CONFIG_M5208EVB=y
23# CONFIG_4KSTACKS is not set
24CONFIG_RAMBASE=0x40000000
25CONFIG_RAMSIZE=0x2000000
26CONFIG_VECTORBASE=0x40000000
27CONFIG_KERNELBASE=0x40020000
28CONFIG_RAM16BIT=y
29CONFIG_BINFMT_FLAT=y
30CONFIG_NET=y
31CONFIG_PACKET=y
32CONFIG_UNIX=y
33CONFIG_INET=y
34# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
35# CONFIG_INET_XFRM_MODE_TUNNEL is not set
36# CONFIG_INET_XFRM_MODE_BEET is not set
37# CONFIG_INET_LRO is not set
38# CONFIG_INET_DIAG is not set
39# CONFIG_IPV6 is not set
40CONFIG_MTD=y
41CONFIG_MTD_PARTITIONS=y
42CONFIG_MTD_CHAR=y
43CONFIG_MTD_BLOCK=y
44CONFIG_MTD_RAM=y
45CONFIG_MTD_UCLINUX=y
46CONFIG_BLK_DEV_RAM=y
47# CONFIG_MISC_DEVICES is not set
48CONFIG_NETDEVICES=y
49CONFIG_NET_ETHERNET=y
50CONFIG_FEC=y
51# CONFIG_NETDEV_1000 is not set
52# CONFIG_NETDEV_10000 is not set
53# CONFIG_INPUT is not set
54# CONFIG_SERIO is not set
55# CONFIG_VT is not set
56CONFIG_SERIAL_MCF=y
57CONFIG_SERIAL_MCF_BAUDRATE=115200
58CONFIG_SERIAL_MCF_CONSOLE=y
59# CONFIG_UNIX98_PTYS is not set
60# CONFIG_HW_RANDOM is not set
61# CONFIG_HWMON is not set
62# CONFIG_USB_SUPPORT is not set
63CONFIG_EXT2_FS=y
64# CONFIG_FILE_LOCKING is not set
65# CONFIG_DNOTIFY is not set
66# CONFIG_SYSFS is not set
67CONFIG_ROMFS_FS=y
68CONFIG_ROMFS_BACKED_BY_MTD=y
69# CONFIG_NETWORK_FILESYSTEMS is not set
70# CONFIG_RCU_CPU_STALL_DETECTOR is not set
71CONFIG_SYSCTL_SYSCALL_CHECK=y
72CONFIG_FULLDEBUG=y
73CONFIG_BOOTPARAM=y
74CONFIG_BOOTPARAM_STRING="root=/dev/mtdblock0"
diff --git a/arch/m68knommu/kernel/.gitignore b/arch/m68knommu/kernel/.gitignore
deleted file mode 100644
index c5f676c3c22..00000000000
--- a/arch/m68knommu/kernel/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
1vmlinux.lds
diff --git a/arch/m68knommu/lib/ashldi3.c b/arch/m68knommu/lib/ashldi3.c
deleted file mode 100644
index 008403eb8ce..00000000000
--- a/arch/m68knommu/lib/ashldi3.c
+++ /dev/null
@@ -1,62 +0,0 @@
1/* ashrdi3.c extracted from gcc-2.95.2/libgcc2.c which is: */
2/* Copyright (C) 1989, 92-98, 1999 Free Software Foundation, Inc.
3
4This file is part of GNU CC.
5
6GNU CC is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation; either version 2, or (at your option)
9any later version.
10
11GNU CC is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with GNU CC; see the file COPYING. If not, write to
18the Free Software Foundation, 59 Temple Place - Suite 330,
19Boston, MA 02111-1307, USA. */
20
21#define BITS_PER_UNIT 8
22
23typedef int SItype __attribute__ ((mode (SI)));
24typedef unsigned int USItype __attribute__ ((mode (SI)));
25typedef int DItype __attribute__ ((mode (DI)));
26typedef int word_type __attribute__ ((mode (__word__)));
27
28struct DIstruct {SItype high, low;};
29
30typedef union
31{
32 struct DIstruct s;
33 DItype ll;
34} DIunion;
35
36DItype
37__ashldi3 (DItype u, word_type b)
38{
39 DIunion w;
40 word_type bm;
41 DIunion uu;
42
43 if (b == 0)
44 return u;
45
46 uu.ll = u;
47
48 bm = (sizeof (SItype) * BITS_PER_UNIT) - b;
49 if (bm <= 0)
50 {
51 w.s.low = 0;
52 w.s.high = (USItype)uu.s.low << -bm;
53 }
54 else
55 {
56 USItype carries = (USItype)uu.s.low >> bm;
57 w.s.low = (USItype)uu.s.low << b;
58 w.s.high = ((USItype)uu.s.high << b) | carries;
59 }
60
61 return w.ll;
62}
diff --git a/arch/m68knommu/lib/lshrdi3.c b/arch/m68knommu/lib/lshrdi3.c
deleted file mode 100644
index 93b1cb6fdee..00000000000
--- a/arch/m68knommu/lib/lshrdi3.c
+++ /dev/null
@@ -1,62 +0,0 @@
1/* lshrdi3.c extracted from gcc-2.7.2/libgcc2.c which is: */
2/* Copyright (C) 1989, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
3
4This file is part of GNU CC.
5
6GNU CC is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation; either version 2, or (at your option)
9any later version.
10
11GNU CC is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with GNU CC; see the file COPYING. If not, write to
18the Free Software Foundation, 59 Temple Place - Suite 330,
19Boston, MA 02111-1307, USA. */
20
21#define BITS_PER_UNIT 8
22
23typedef int SItype __attribute__ ((mode (SI)));
24typedef unsigned int USItype __attribute__ ((mode (SI)));
25typedef int DItype __attribute__ ((mode (DI)));
26typedef int word_type __attribute__ ((mode (__word__)));
27
28struct DIstruct {SItype high, low;};
29
30typedef union
31{
32 struct DIstruct s;
33 DItype ll;
34} DIunion;
35
36DItype
37__lshrdi3 (DItype u, word_type b)
38{
39 DIunion w;
40 word_type bm;
41 DIunion uu;
42
43 if (b == 0)
44 return u;
45
46 uu.ll = u;
47
48 bm = (sizeof (SItype) * BITS_PER_UNIT) - b;
49 if (bm <= 0)
50 {
51 w.s.high = 0;
52 w.s.low = (USItype)uu.s.high >> -bm;
53 }
54 else
55 {
56 USItype carries = (USItype)uu.s.high << bm;
57 w.s.high = (USItype)uu.s.high >> b;
58 w.s.low = ((USItype)uu.s.low >> b) | carries;
59 }
60
61 return w.ll;
62}