mirror of
https://github.com/torvalds/linux.git
synced 2024-11-24 13:11:40 +00:00
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>
This commit is contained in:
parent
d39dd11c3e
commit
66d857b08b
@ -1,13 +1,11 @@
|
||||
config M68K
|
||||
bool
|
||||
default y
|
||||
select HAVE_AOUT
|
||||
select HAVE_IDE
|
||||
select GENERIC_ATOMIC64
|
||||
|
||||
config MMU
|
||||
bool
|
||||
default y
|
||||
select HAVE_AOUT if MMU
|
||||
select GENERIC_ATOMIC64 if MMU
|
||||
select HAVE_GENERIC_HARDIRQS if !MMU
|
||||
select GENERIC_HARDIRQS_NO_DEPRECATED if !MMU
|
||||
|
||||
config RWSEM_GENERIC_SPINLOCK
|
||||
bool
|
||||
@ -34,457 +32,67 @@ config TIME_LOW_RES
|
||||
bool
|
||||
default y
|
||||
|
||||
config GENERIC_IOMAP
|
||||
bool
|
||||
default y
|
||||
|
||||
config ARCH_MAY_HAVE_PC_FDC
|
||||
bool
|
||||
depends on BROKEN && (Q40 || SUN3X)
|
||||
default y
|
||||
|
||||
config NO_IOPORT
|
||||
def_bool y
|
||||
|
||||
config NO_DMA
|
||||
def_bool SUN3
|
||||
def_bool (MMU && SUN3) || (!MMU && !COLDFIRE)
|
||||
|
||||
config ZONE_DMA
|
||||
bool
|
||||
default y
|
||||
config HZ
|
||||
int
|
||||
default 1000 if CLEOPATRA
|
||||
default 100
|
||||
|
||||
config ARCH_USES_GETTIMEOFFSET
|
||||
def_bool y
|
||||
|
||||
source "init/Kconfig"
|
||||
|
||||
source "kernel/Kconfig.freezer"
|
||||
|
||||
config MMU
|
||||
bool "MMU-based Paged Memory Management Support"
|
||||
default y
|
||||
help
|
||||
Select if you want MMU-based virtualised addressing space
|
||||
support by paged memory management. If unsure, say 'Y'.
|
||||
|
||||
menu "Platform dependent setup"
|
||||
|
||||
config EISA
|
||||
bool
|
||||
---help---
|
||||
The Extended Industry Standard Architecture (EISA) bus was
|
||||
developed as an open alternative to the IBM MicroChannel bus.
|
||||
|
||||
The EISA bus provided some of the features of the IBM MicroChannel
|
||||
bus while maintaining backward compatibility with cards made for
|
||||
the older ISA bus. The EISA bus saw limited use between 1988 and
|
||||
1995 when it was made obsolete by the PCI bus.
|
||||
|
||||
Say Y here if you are building a kernel for an EISA-based machine.
|
||||
|
||||
Otherwise, say N.
|
||||
|
||||
config MCA
|
||||
bool
|
||||
help
|
||||
MicroChannel Architecture is found in some IBM PS/2 machines and
|
||||
laptops. It is a bus system similar to PCI or ISA. See
|
||||
<file:Documentation/mca.txt> (and especially the web page given
|
||||
there) before attempting to build an MCA bus kernel.
|
||||
|
||||
config PCMCIA
|
||||
tristate
|
||||
---help---
|
||||
Say Y here if you want to attach PCMCIA- or PC-cards to your Linux
|
||||
computer. These are credit-card size devices such as network cards,
|
||||
modems or hard drives often used with laptops computers. There are
|
||||
actually two varieties of these cards: the older 16 bit PCMCIA cards
|
||||
and the newer 32 bit CardBus cards. If you want to use CardBus
|
||||
cards, you need to say Y here and also to "CardBus support" below.
|
||||
|
||||
To use your PC-cards, you will need supporting software from David
|
||||
Hinds' pcmcia-cs package (see the file <file:Documentation/Changes>
|
||||
for location). Please also read the PCMCIA-HOWTO, available from
|
||||
<http://www.tldp.org/docs.html#howto>.
|
||||
|
||||
To compile this driver as modules, choose M here: the
|
||||
modules will be called pcmcia_core and ds.
|
||||
|
||||
config AMIGA
|
||||
bool "Amiga support"
|
||||
select MMU_MOTOROLA if MMU
|
||||
help
|
||||
This option enables support for the Amiga series of computers. If
|
||||
you plan to use this kernel on an Amiga, say Y here and browse the
|
||||
material available in <file:Documentation/m68k>; otherwise say N.
|
||||
|
||||
config ATARI
|
||||
bool "Atari support"
|
||||
select MMU_MOTOROLA if MMU
|
||||
help
|
||||
This option enables support for the 68000-based Atari series of
|
||||
computers (including the TT, Falcon and Medusa). If you plan to use
|
||||
this kernel on an Atari, say Y here and browse the material
|
||||
available in <file:Documentation/m68k>; otherwise say N.
|
||||
|
||||
config MAC
|
||||
bool "Macintosh support"
|
||||
select MMU_MOTOROLA if MMU
|
||||
help
|
||||
This option enables support for the Apple Macintosh series of
|
||||
computers (yes, there is experimental support now, at least for part
|
||||
of the series).
|
||||
|
||||
Say N unless you're willing to code the remaining necessary support.
|
||||
;)
|
||||
|
||||
config NUBUS
|
||||
bool
|
||||
depends on MAC
|
||||
default y
|
||||
|
||||
config M68K_L2_CACHE
|
||||
bool
|
||||
depends on MAC
|
||||
default y
|
||||
|
||||
config APOLLO
|
||||
bool "Apollo support"
|
||||
select MMU_MOTOROLA if MMU
|
||||
help
|
||||
Say Y here if you want to run Linux on an MC680x0-based Apollo
|
||||
Domain workstation such as the DN3500.
|
||||
|
||||
config VME
|
||||
bool "VME (Motorola and BVM) support"
|
||||
select MMU_MOTOROLA if MMU
|
||||
help
|
||||
Say Y here if you want to build a kernel for a 680x0 based VME
|
||||
board. Boards currently supported include Motorola boards MVME147,
|
||||
MVME162, MVME166, MVME167, MVME172, and MVME177. BVME4000 and
|
||||
BVME6000 boards from BVM Ltd are also supported.
|
||||
|
||||
config MVME147
|
||||
bool "MVME147 support"
|
||||
depends on VME
|
||||
help
|
||||
Say Y to include support for early Motorola VME boards. This will
|
||||
build a kernel which can run on MVME147 single-board computers. If
|
||||
you select this option you will have to select the appropriate
|
||||
drivers for SCSI, Ethernet and serial ports later on.
|
||||
|
||||
config MVME16x
|
||||
bool "MVME162, 166 and 167 support"
|
||||
depends on VME
|
||||
help
|
||||
Say Y to include support for Motorola VME boards. This will build a
|
||||
kernel which can run on MVME162, MVME166, MVME167, MVME172, and
|
||||
MVME177 boards. If you select this option you will have to select
|
||||
the appropriate drivers for SCSI, Ethernet and serial ports later
|
||||
on.
|
||||
|
||||
config BVME6000
|
||||
bool "BVME4000 and BVME6000 support"
|
||||
depends on VME
|
||||
help
|
||||
Say Y to include support for VME boards from BVM Ltd. This will
|
||||
build a kernel which can run on BVME4000 and BVME6000 boards. If
|
||||
you select this option you will have to select the appropriate
|
||||
drivers for SCSI, Ethernet and serial ports later on.
|
||||
|
||||
config HP300
|
||||
bool "HP9000/300 and HP9000/400 support"
|
||||
select MMU_MOTOROLA if MMU
|
||||
help
|
||||
This option enables support for the HP9000/300 and HP9000/400 series
|
||||
of workstations. Support for these machines is still somewhat
|
||||
experimental. If you plan to try to use the kernel on such a machine
|
||||
say Y here.
|
||||
Everybody else says N.
|
||||
|
||||
config DIO
|
||||
bool "DIO bus support"
|
||||
depends on HP300
|
||||
default y
|
||||
help
|
||||
Say Y here to enable support for the "DIO" expansion bus used in
|
||||
HP300 machines. If you are using such a system you almost certainly
|
||||
want this.
|
||||
|
||||
config SUN3X
|
||||
bool "Sun3x support"
|
||||
select MMU_MOTOROLA if MMU
|
||||
select M68030
|
||||
help
|
||||
This option enables support for the Sun 3x series of workstations.
|
||||
Be warned that this support is very experimental.
|
||||
Note that Sun 3x kernels are not compatible with Sun 3 hardware.
|
||||
General Linux information on the Sun 3x series (now discontinued)
|
||||
is at <http://www.angelfire.com/ca2/tech68k/sun3.html>.
|
||||
|
||||
If you don't want to compile a kernel for a Sun 3x, say N.
|
||||
|
||||
config Q40
|
||||
bool "Q40/Q60 support"
|
||||
select MMU_MOTOROLA if MMU
|
||||
help
|
||||
The Q40 is a Motorola 68040-based successor to the Sinclair QL
|
||||
manufactured in Germany. There is an official Q40 home page at
|
||||
<http://www.q40.de/>. This option enables support for the Q40 and
|
||||
Q60. Select your CPU below. For 68LC060 don't forget to enable FPU
|
||||
emulation.
|
||||
|
||||
config SUN3
|
||||
bool "Sun3 support"
|
||||
depends on !MMU_MOTOROLA
|
||||
select MMU_SUN3 if MMU
|
||||
select M68020
|
||||
help
|
||||
This option enables support for the Sun 3 series of workstations
|
||||
(3/50, 3/60, 3/1xx, 3/2xx systems). Enabling this option requires
|
||||
that all other hardware types must be disabled, as Sun 3 kernels
|
||||
are incompatible with all other m68k targets (including Sun 3x!).
|
||||
|
||||
If you don't want to compile a kernel exclusively for a Sun 3, say N.
|
||||
|
||||
config NATFEAT
|
||||
bool "ARAnyM emulator support"
|
||||
depends on ATARI
|
||||
help
|
||||
This option enables support for ARAnyM native features, such as
|
||||
access to a disk image as /dev/hda.
|
||||
|
||||
config NFBLOCK
|
||||
tristate "NatFeat block device support"
|
||||
depends on BLOCK && NATFEAT
|
||||
help
|
||||
Say Y to include support for the ARAnyM NatFeat block device
|
||||
which allows direct access to the hard drives without using
|
||||
the hardware emulation.
|
||||
|
||||
config NFCON
|
||||
tristate "NatFeat console driver"
|
||||
depends on NATFEAT
|
||||
help
|
||||
Say Y to include support for the ARAnyM NatFeat console driver
|
||||
which allows the console output to be redirected to the stderr
|
||||
output of ARAnyM.
|
||||
|
||||
config NFETH
|
||||
tristate "NatFeat Ethernet support"
|
||||
depends on NET_ETHERNET && NATFEAT
|
||||
help
|
||||
Say Y to include support for the ARAnyM NatFeat network device
|
||||
which will emulate a regular ethernet device while presenting an
|
||||
ethertap device to the host system.
|
||||
|
||||
comment "Processor type"
|
||||
|
||||
config M68020
|
||||
bool "68020 support"
|
||||
help
|
||||
If you anticipate running this kernel on a computer with a MC68020
|
||||
processor, say Y. Otherwise, say N. Note that the 68020 requires a
|
||||
68851 MMU (Memory Management Unit) to run Linux/m68k, except on the
|
||||
Sun 3, which provides its own version.
|
||||
|
||||
config M68030
|
||||
bool "68030 support"
|
||||
depends on !MMU_SUN3
|
||||
help
|
||||
If you anticipate running this kernel on a computer with a MC68030
|
||||
processor, say Y. Otherwise, say N. Note that a MC68EC030 will not
|
||||
work, as it does not include an MMU (Memory Management Unit).
|
||||
|
||||
config M68040
|
||||
bool "68040 support"
|
||||
depends on !MMU_SUN3
|
||||
help
|
||||
If you anticipate running this kernel on a computer with a MC68LC040
|
||||
or MC68040 processor, say Y. Otherwise, say N. Note that an
|
||||
MC68EC040 will not work, as it does not include an MMU (Memory
|
||||
Management Unit).
|
||||
|
||||
config M68060
|
||||
bool "68060 support"
|
||||
depends on !MMU_SUN3
|
||||
help
|
||||
If you anticipate running this kernel on a computer with a MC68060
|
||||
processor, say Y. Otherwise, say N.
|
||||
|
||||
config MMU_MOTOROLA
|
||||
bool
|
||||
|
||||
config MMU_SUN3
|
||||
bool
|
||||
depends on MMU && !MMU_MOTOROLA
|
||||
|
||||
config M68KFPU_EMU
|
||||
bool "Math emulation support (EXPERIMENTAL)"
|
||||
depends on EXPERIMENTAL
|
||||
help
|
||||
At some point in the future, this will cause floating-point math
|
||||
instructions to be emulated by the kernel on machines that lack a
|
||||
floating-point math coprocessor. Thrill-seekers and chronically
|
||||
sleep-deprived psychotic hacker types can say Y now, everyone else
|
||||
should probably wait a while.
|
||||
|
||||
config M68KFPU_EMU_EXTRAPREC
|
||||
bool "Math emulation extra precision"
|
||||
depends on M68KFPU_EMU
|
||||
help
|
||||
The fpu uses normally a few bit more during calculations for
|
||||
correct rounding, the emulator can (often) do the same but this
|
||||
extra calculation can cost quite some time, so you can disable
|
||||
it here. The emulator will then "only" calculate with a 64 bit
|
||||
mantissa and round slightly incorrect, what is more than enough
|
||||
for normal usage.
|
||||
|
||||
config M68KFPU_EMU_ONLY
|
||||
bool "Math emulation only kernel"
|
||||
depends on M68KFPU_EMU
|
||||
help
|
||||
This option prevents any floating-point instructions from being
|
||||
compiled into the kernel, thereby the kernel doesn't save any
|
||||
floating point context anymore during task switches, so this
|
||||
kernel will only be usable on machines without a floating-point
|
||||
math coprocessor. This makes the kernel a bit faster as no tests
|
||||
needs to be executed whether a floating-point instruction in the
|
||||
kernel should be executed or not.
|
||||
|
||||
config ADVANCED
|
||||
bool "Advanced configuration options"
|
||||
---help---
|
||||
This gives you access to some advanced options for the CPU. The
|
||||
defaults should be fine for most users, but these options may make
|
||||
it possible for you to improve performance somewhat if you know what
|
||||
you are doing.
|
||||
|
||||
Note that the answer to this question won't directly affect the
|
||||
kernel: saying N will just cause the configurator to skip all
|
||||
the questions about these options.
|
||||
|
||||
Most users should say N to this question.
|
||||
|
||||
config RMW_INSNS
|
||||
bool "Use read-modify-write instructions"
|
||||
depends on ADVANCED
|
||||
---help---
|
||||
This allows to use certain instructions that work with indivisible
|
||||
read-modify-write bus cycles. While this is faster than the
|
||||
workaround of disabling interrupts, it can conflict with DMA
|
||||
( = direct memory access) on many Amiga systems, and it is also said
|
||||
to destabilize other machines. It is very likely that this will
|
||||
cause serious problems on any Amiga or Atari Medusa if set. The only
|
||||
configuration where it should work are 68030-based Ataris, where it
|
||||
apparently improves performance. But you've been warned! Unless you
|
||||
really know what you are doing, say N. Try Y only if you're quite
|
||||
adventurous.
|
||||
|
||||
config SINGLE_MEMORY_CHUNK
|
||||
bool "Use one physical chunk of memory only" if ADVANCED && !SUN3
|
||||
default y if SUN3
|
||||
select NEED_MULTIPLE_NODES
|
||||
help
|
||||
Ignore all but the first contiguous chunk of physical memory for VM
|
||||
purposes. This will save a few bytes kernel size and may speed up
|
||||
some operations. Say N if not sure.
|
||||
|
||||
config 060_WRITETHROUGH
|
||||
bool "Use write-through caching for 68060 supervisor accesses"
|
||||
depends on ADVANCED && M68060
|
||||
---help---
|
||||
The 68060 generally uses copyback caching of recently accessed data.
|
||||
Copyback caching means that memory writes will be held in an on-chip
|
||||
cache and only written back to memory some time later. Saying Y
|
||||
here will force supervisor (kernel) accesses to use writethrough
|
||||
caching. Writethrough caching means that data is written to memory
|
||||
straight away, so that cache and memory data always agree.
|
||||
Writethrough caching is less efficient, but is needed for some
|
||||
drivers on 68060 based systems where the 68060 bus snooping signal
|
||||
is hardwired on. The 53c710 SCSI driver is known to suffer from
|
||||
this problem.
|
||||
|
||||
config ARCH_DISCONTIGMEM_ENABLE
|
||||
def_bool !SINGLE_MEMORY_CHUNK
|
||||
|
||||
config NODES_SHIFT
|
||||
int
|
||||
default "3"
|
||||
depends on !SINGLE_MEMORY_CHUNK
|
||||
if MMU
|
||||
source arch/m68k/Kconfig.mmu
|
||||
endif
|
||||
if !MMU
|
||||
source arch/m68k/Kconfig.nommu
|
||||
endif
|
||||
|
||||
source "mm/Kconfig"
|
||||
|
||||
endmenu
|
||||
|
||||
menu "General setup"
|
||||
menu "Executable file formats"
|
||||
|
||||
source "fs/Kconfig.binfmt"
|
||||
|
||||
config ZORRO
|
||||
bool "Amiga Zorro (AutoConfig) bus support"
|
||||
depends on AMIGA
|
||||
help
|
||||
This enables support for the Zorro bus in the Amiga. If you have
|
||||
expansion cards in your Amiga that conform to the Amiga
|
||||
AutoConfig(tm) specification, say Y, otherwise N. Note that even
|
||||
expansion cards that do not fit in the Zorro slots but fit in e.g.
|
||||
the CPU slot may fall in this category, so you have to say Y to let
|
||||
Linux use these.
|
||||
endmenu
|
||||
|
||||
config AMIGA_PCMCIA
|
||||
bool "Amiga 1200/600 PCMCIA support (EXPERIMENTAL)"
|
||||
depends on AMIGA && EXPERIMENTAL
|
||||
help
|
||||
Include support in the kernel for pcmcia on Amiga 1200 and Amiga
|
||||
600. If you intend to use pcmcia cards say Y; otherwise say N.
|
||||
if !MMU
|
||||
menu "Power management options"
|
||||
|
||||
config STRAM_PROC
|
||||
bool "ST-RAM statistics in /proc"
|
||||
depends on ATARI
|
||||
help
|
||||
Say Y here to report ST-RAM usage statistics in /proc/stram.
|
||||
|
||||
config HEARTBEAT
|
||||
bool "Use power LED as a heartbeat" if AMIGA || APOLLO || ATARI || MAC ||Q40
|
||||
default y if !AMIGA && !APOLLO && !ATARI && !MAC && !Q40 && HP300
|
||||
help
|
||||
Use the power-on LED on your machine as a load meter. The exact
|
||||
behavior is platform-dependent, but normally the flash frequency is
|
||||
a hyperbolic function of the 5-minute load average.
|
||||
|
||||
# We have a dedicated heartbeat LED. :-)
|
||||
config PROC_HARDWARE
|
||||
bool "/proc/hardware support"
|
||||
help
|
||||
Say Y here to support the /proc/hardware file, which gives you
|
||||
access to information about the machine you're running on,
|
||||
including the model, CPU, MMU, clock speed, BogoMIPS rating,
|
||||
and memory size.
|
||||
|
||||
config ISA
|
||||
bool
|
||||
depends on Q40 || AMIGA_PCMCIA
|
||||
default y
|
||||
help
|
||||
Find out whether you have ISA slots on your motherboard. ISA is the
|
||||
name of a bus system, i.e. the way the CPU talks to the other stuff
|
||||
inside your box. Other bus systems are PCI, EISA, MicroChannel
|
||||
(MCA) or VESA. ISA is an older system, now being displaced by PCI;
|
||||
newer boards don't support it. If you have ISA, say Y, otherwise N.
|
||||
|
||||
config GENERIC_ISA_DMA
|
||||
bool
|
||||
depends on Q40 || AMIGA_PCMCIA
|
||||
default y
|
||||
|
||||
config ZONE_DMA
|
||||
bool
|
||||
default y
|
||||
|
||||
source "drivers/pci/Kconfig"
|
||||
|
||||
source "drivers/zorro/Kconfig"
|
||||
config PM
|
||||
bool "Power Management support"
|
||||
help
|
||||
Support processor power management modes
|
||||
|
||||
endmenu
|
||||
endif
|
||||
|
||||
source "net/Kconfig"
|
||||
|
||||
source "drivers/Kconfig"
|
||||
|
||||
if MMU
|
||||
|
||||
menu "Character devices"
|
||||
|
||||
config ATARI_MFPSER
|
||||
@ -627,6 +235,8 @@ config SERIAL_CONSOLE
|
||||
|
||||
endmenu
|
||||
|
||||
endif
|
||||
|
||||
source "fs/Kconfig"
|
||||
|
||||
source "arch/m68k/Kconfig.debug"
|
||||
|
@ -2,4 +2,38 @@ menu "Kernel hacking"
|
||||
|
||||
source "lib/Kconfig.debug"
|
||||
|
||||
if !MMU
|
||||
|
||||
config FULLDEBUG
|
||||
bool "Full Symbolic/Source Debugging support"
|
||||
help
|
||||
Enable debugging symbols on kernel build.
|
||||
|
||||
config HIGHPROFILE
|
||||
bool "Use fast second timer for profiling"
|
||||
depends on COLDFIRE
|
||||
help
|
||||
Use a fast secondary clock to produce profiling information.
|
||||
|
||||
config BOOTPARAM
|
||||
bool 'Compiled-in Kernel Boot Parameter'
|
||||
|
||||
config BOOTPARAM_STRING
|
||||
string 'Kernel Boot Parameter'
|
||||
default 'console=ttyS0,19200'
|
||||
depends on BOOTPARAM
|
||||
|
||||
config NO_KERNEL_MSG
|
||||
bool "Suppress Kernel BUG Messages"
|
||||
help
|
||||
Do not output any debug BUG messages within the kernel.
|
||||
|
||||
config BDM_DISABLE
|
||||
bool "Disable BDM signals"
|
||||
depends on (EXPERIMENTAL && COLDFIRE)
|
||||
help
|
||||
Disable the ColdFire CPU's BDM signals.
|
||||
|
||||
endif
|
||||
|
||||
endmenu
|
||||
|
417
arch/m68k/Kconfig.mmu
Normal file
417
arch/m68k/Kconfig.mmu
Normal file
@ -0,0 +1,417 @@
|
||||
config GENERIC_IOMAP
|
||||
bool
|
||||
default y
|
||||
|
||||
config ARCH_MAY_HAVE_PC_FDC
|
||||
bool
|
||||
depends on BROKEN && (Q40 || SUN3X)
|
||||
default y
|
||||
|
||||
config ARCH_USES_GETTIMEOFFSET
|
||||
def_bool y
|
||||
|
||||
config EISA
|
||||
bool
|
||||
---help---
|
||||
The Extended Industry Standard Architecture (EISA) bus was
|
||||
developed as an open alternative to the IBM MicroChannel bus.
|
||||
|
||||
The EISA bus provided some of the features of the IBM MicroChannel
|
||||
bus while maintaining backward compatibility with cards made for
|
||||
the older ISA bus. The EISA bus saw limited use between 1988 and
|
||||
1995 when it was made obsolete by the PCI bus.
|
||||
|
||||
Say Y here if you are building a kernel for an EISA-based machine.
|
||||
|
||||
Otherwise, say N.
|
||||
|
||||
config MCA
|
||||
bool
|
||||
help
|
||||
MicroChannel Architecture is found in some IBM PS/2 machines and
|
||||
laptops. It is a bus system similar to PCI or ISA. See
|
||||
<file:Documentation/mca.txt> (and especially the web page given
|
||||
there) before attempting to build an MCA bus kernel.
|
||||
|
||||
config PCMCIA
|
||||
tristate
|
||||
---help---
|
||||
Say Y here if you want to attach PCMCIA- or PC-cards to your Linux
|
||||
computer. These are credit-card size devices such as network cards,
|
||||
modems or hard drives often used with laptops computers. There are
|
||||
actually two varieties of these cards: the older 16 bit PCMCIA cards
|
||||
and the newer 32 bit CardBus cards. If you want to use CardBus
|
||||
cards, you need to say Y here and also to "CardBus support" below.
|
||||
|
||||
To use your PC-cards, you will need supporting software from David
|
||||
Hinds' pcmcia-cs package (see the file <file:Documentation/Changes>
|
||||
for location). Please also read the PCMCIA-HOWTO, available from
|
||||
<http://www.tldp.org/docs.html#howto>.
|
||||
|
||||
To compile this driver as modules, choose M here: the
|
||||
modules will be called pcmcia_core and ds.
|
||||
|
||||
config AMIGA
|
||||
bool "Amiga support"
|
||||
select MMU_MOTOROLA if MMU
|
||||
help
|
||||
This option enables support for the Amiga series of computers. If
|
||||
you plan to use this kernel on an Amiga, say Y here and browse the
|
||||
material available in <file:Documentation/m68k>; otherwise say N.
|
||||
|
||||
config ATARI
|
||||
bool "Atari support"
|
||||
select MMU_MOTOROLA if MMU
|
||||
help
|
||||
This option enables support for the 68000-based Atari series of
|
||||
computers (including the TT, Falcon and Medusa). If you plan to use
|
||||
this kernel on an Atari, say Y here and browse the material
|
||||
available in <file:Documentation/m68k>; otherwise say N.
|
||||
|
||||
config MAC
|
||||
bool "Macintosh support"
|
||||
select MMU_MOTOROLA if MMU
|
||||
help
|
||||
This option enables support for the Apple Macintosh series of
|
||||
computers (yes, there is experimental support now, at least for part
|
||||
of the series).
|
||||
|
||||
Say N unless you're willing to code the remaining necessary support.
|
||||
;)
|
||||
|
||||
config NUBUS
|
||||
bool
|
||||
depends on MAC
|
||||
default y
|
||||
|
||||
config M68K_L2_CACHE
|
||||
bool
|
||||
depends on MAC
|
||||
default y
|
||||
|
||||
config APOLLO
|
||||
bool "Apollo support"
|
||||
select MMU_MOTOROLA if MMU
|
||||
help
|
||||
Say Y here if you want to run Linux on an MC680x0-based Apollo
|
||||
Domain workstation such as the DN3500.
|
||||
|
||||
config VME
|
||||
bool "VME (Motorola and BVM) support"
|
||||
select MMU_MOTOROLA if MMU
|
||||
help
|
||||
Say Y here if you want to build a kernel for a 680x0 based VME
|
||||
board. Boards currently supported include Motorola boards MVME147,
|
||||
MVME162, MVME166, MVME167, MVME172, and MVME177. BVME4000 and
|
||||
BVME6000 boards from BVM Ltd are also supported.
|
||||
|
||||
config MVME147
|
||||
bool "MVME147 support"
|
||||
depends on VME
|
||||
help
|
||||
Say Y to include support for early Motorola VME boards. This will
|
||||
build a kernel which can run on MVME147 single-board computers. If
|
||||
you select this option you will have to select the appropriate
|
||||
drivers for SCSI, Ethernet and serial ports later on.
|
||||
|
||||
config MVME16x
|
||||
bool "MVME162, 166 and 167 support"
|
||||
depends on VME
|
||||
help
|
||||
Say Y to include support for Motorola VME boards. This will build a
|
||||
kernel which can run on MVME162, MVME166, MVME167, MVME172, and
|
||||
MVME177 boards. If you select this option you will have to select
|
||||
the appropriate drivers for SCSI, Ethernet and serial ports later
|
||||
on.
|
||||
|
||||
config BVME6000
|
||||
bool "BVME4000 and BVME6000 support"
|
||||
depends on VME
|
||||
help
|
||||
Say Y to include support for VME boards from BVM Ltd. This will
|
||||
build a kernel which can run on BVME4000 and BVME6000 boards. If
|
||||
you select this option you will have to select the appropriate
|
||||
drivers for SCSI, Ethernet and serial ports later on.
|
||||
|
||||
config HP300
|
||||
bool "HP9000/300 and HP9000/400 support"
|
||||
select MMU_MOTOROLA if MMU
|
||||
help
|
||||
This option enables support for the HP9000/300 and HP9000/400 series
|
||||
of workstations. Support for these machines is still somewhat
|
||||
experimental. If you plan to try to use the kernel on such a machine
|
||||
say Y here.
|
||||
Everybody else says N.
|
||||
|
||||
config DIO
|
||||
bool "DIO bus support"
|
||||
depends on HP300
|
||||
default y
|
||||
help
|
||||
Say Y here to enable support for the "DIO" expansion bus used in
|
||||
HP300 machines. If you are using such a system you almost certainly
|
||||
want this.
|
||||
|
||||
config SUN3X
|
||||
bool "Sun3x support"
|
||||
select MMU_MOTOROLA if MMU
|
||||
select M68030
|
||||
help
|
||||
This option enables support for the Sun 3x series of workstations.
|
||||
Be warned that this support is very experimental.
|
||||
Note that Sun 3x kernels are not compatible with Sun 3 hardware.
|
||||
General Linux information on the Sun 3x series (now discontinued)
|
||||
is at <http://www.angelfire.com/ca2/tech68k/sun3.html>.
|
||||
|
||||
If you don't want to compile a kernel for a Sun 3x, say N.
|
||||
|
||||
config Q40
|
||||
bool "Q40/Q60 support"
|
||||
select MMU_MOTOROLA if MMU
|
||||
help
|
||||
The Q40 is a Motorola 68040-based successor to the Sinclair QL
|
||||
manufactured in Germany. There is an official Q40 home page at
|
||||
<http://www.q40.de/>. This option enables support for the Q40 and
|
||||
Q60. Select your CPU below. For 68LC060 don't forget to enable FPU
|
||||
emulation.
|
||||
|
||||
config SUN3
|
||||
bool "Sun3 support"
|
||||
depends on !MMU_MOTOROLA
|
||||
select MMU_SUN3 if MMU
|
||||
select M68020
|
||||
help
|
||||
This option enables support for the Sun 3 series of workstations
|
||||
(3/50, 3/60, 3/1xx, 3/2xx systems). Enabling this option requires
|
||||
that all other hardware types must be disabled, as Sun 3 kernels
|
||||
are incompatible with all other m68k targets (including Sun 3x!).
|
||||
|
||||
If you don't want to compile a kernel exclusively for a Sun 3, say N.
|
||||
|
||||
config NATFEAT
|
||||
bool "ARAnyM emulator support"
|
||||
depends on ATARI
|
||||
help
|
||||
This option enables support for ARAnyM native features, such as
|
||||
access to a disk image as /dev/hda.
|
||||
|
||||
config NFBLOCK
|
||||
tristate "NatFeat block device support"
|
||||
depends on BLOCK && NATFEAT
|
||||
help
|
||||
Say Y to include support for the ARAnyM NatFeat block device
|
||||
which allows direct access to the hard drives without using
|
||||
the hardware emulation.
|
||||
|
||||
config NFCON
|
||||
tristate "NatFeat console driver"
|
||||
depends on NATFEAT
|
||||
help
|
||||
Say Y to include support for the ARAnyM NatFeat console driver
|
||||
which allows the console output to be redirected to the stderr
|
||||
output of ARAnyM.
|
||||
|
||||
config NFETH
|
||||
tristate "NatFeat Ethernet support"
|
||||
depends on NET_ETHERNET && NATFEAT
|
||||
help
|
||||
Say Y to include support for the ARAnyM NatFeat network device
|
||||
which will emulate a regular ethernet device while presenting an
|
||||
ethertap device to the host system.
|
||||
|
||||
comment "Processor type"
|
||||
|
||||
config M68020
|
||||
bool "68020 support"
|
||||
help
|
||||
If you anticipate running this kernel on a computer with a MC68020
|
||||
processor, say Y. Otherwise, say N. Note that the 68020 requires a
|
||||
68851 MMU (Memory Management Unit) to run Linux/m68k, except on the
|
||||
Sun 3, which provides its own version.
|
||||
|
||||
config M68030
|
||||
bool "68030 support"
|
||||
depends on !MMU_SUN3
|
||||
help
|
||||
If you anticipate running this kernel on a computer with a MC68030
|
||||
processor, say Y. Otherwise, say N. Note that a MC68EC030 will not
|
||||
work, as it does not include an MMU (Memory Management Unit).
|
||||
|
||||
config M68040
|
||||
bool "68040 support"
|
||||
depends on !MMU_SUN3
|
||||
help
|
||||
If you anticipate running this kernel on a computer with a MC68LC040
|
||||
or MC68040 processor, say Y. Otherwise, say N. Note that an
|
||||
MC68EC040 will not work, as it does not include an MMU (Memory
|
||||
Management Unit).
|
||||
|
||||
config M68060
|
||||
bool "68060 support"
|
||||
depends on !MMU_SUN3
|
||||
help
|
||||
If you anticipate running this kernel on a computer with a MC68060
|
||||
processor, say Y. Otherwise, say N.
|
||||
|
||||
config MMU_MOTOROLA
|
||||
bool
|
||||
|
||||
config MMU_SUN3
|
||||
bool
|
||||
depends on MMU && !MMU_MOTOROLA
|
||||
|
||||
config M68KFPU_EMU
|
||||
bool "Math emulation support (EXPERIMENTAL)"
|
||||
depends on EXPERIMENTAL
|
||||
help
|
||||
At some point in the future, this will cause floating-point math
|
||||
instructions to be emulated by the kernel on machines that lack a
|
||||
floating-point math coprocessor. Thrill-seekers and chronically
|
||||
sleep-deprived psychotic hacker types can say Y now, everyone else
|
||||
should probably wait a while.
|
||||
|
||||
config M68KFPU_EMU_EXTRAPREC
|
||||
bool "Math emulation extra precision"
|
||||
depends on M68KFPU_EMU
|
||||
help
|
||||
The fpu uses normally a few bit more during calculations for
|
||||
correct rounding, the emulator can (often) do the same but this
|
||||
extra calculation can cost quite some time, so you can disable
|
||||
it here. The emulator will then "only" calculate with a 64 bit
|
||||
mantissa and round slightly incorrect, what is more than enough
|
||||
for normal usage.
|
||||
|
||||
config M68KFPU_EMU_ONLY
|
||||
bool "Math emulation only kernel"
|
||||
depends on M68KFPU_EMU
|
||||
help
|
||||
This option prevents any floating-point instructions from being
|
||||
compiled into the kernel, thereby the kernel doesn't save any
|
||||
floating point context anymore during task switches, so this
|
||||
kernel will only be usable on machines without a floating-point
|
||||
math coprocessor. This makes the kernel a bit faster as no tests
|
||||
needs to be executed whether a floating-point instruction in the
|
||||
kernel should be executed or not.
|
||||
|
||||
config ADVANCED
|
||||
bool "Advanced configuration options"
|
||||
---help---
|
||||
This gives you access to some advanced options for the CPU. The
|
||||
defaults should be fine for most users, but these options may make
|
||||
it possible for you to improve performance somewhat if you know what
|
||||
you are doing.
|
||||
|
||||
Note that the answer to this question won't directly affect the
|
||||
kernel: saying N will just cause the configurator to skip all
|
||||
the questions about these options.
|
||||
|
||||
Most users should say N to this question.
|
||||
|
||||
config RMW_INSNS
|
||||
bool "Use read-modify-write instructions"
|
||||
depends on ADVANCED
|
||||
---help---
|
||||
This allows to use certain instructions that work with indivisible
|
||||
read-modify-write bus cycles. While this is faster than the
|
||||
workaround of disabling interrupts, it can conflict with DMA
|
||||
( = direct memory access) on many Amiga systems, and it is also said
|
||||
to destabilize other machines. It is very likely that this will
|
||||
cause serious problems on any Amiga or Atari Medusa if set. The only
|
||||
configuration where it should work are 68030-based Ataris, where it
|
||||
apparently improves performance. But you've been warned! Unless you
|
||||
really know what you are doing, say N. Try Y only if you're quite
|
||||
adventurous.
|
||||
|
||||
config SINGLE_MEMORY_CHUNK
|
||||
bool "Use one physical chunk of memory only" if ADVANCED && !SUN3
|
||||
default y if SUN3
|
||||
select NEED_MULTIPLE_NODES
|
||||
help
|
||||
Ignore all but the first contiguous chunk of physical memory for VM
|
||||
purposes. This will save a few bytes kernel size and may speed up
|
||||
some operations. Say N if not sure.
|
||||
|
||||
config 060_WRITETHROUGH
|
||||
bool "Use write-through caching for 68060 supervisor accesses"
|
||||
depends on ADVANCED && M68060
|
||||
---help---
|
||||
The 68060 generally uses copyback caching of recently accessed data.
|
||||
Copyback caching means that memory writes will be held in an on-chip
|
||||
cache and only written back to memory some time later. Saying Y
|
||||
here will force supervisor (kernel) accesses to use writethrough
|
||||
caching. Writethrough caching means that data is written to memory
|
||||
straight away, so that cache and memory data always agree.
|
||||
Writethrough caching is less efficient, but is needed for some
|
||||
drivers on 68060 based systems where the 68060 bus snooping signal
|
||||
is hardwired on. The 53c710 SCSI driver is known to suffer from
|
||||
this problem.
|
||||
|
||||
config ARCH_DISCONTIGMEM_ENABLE
|
||||
def_bool !SINGLE_MEMORY_CHUNK
|
||||
|
||||
config NODES_SHIFT
|
||||
int
|
||||
default "3"
|
||||
depends on !SINGLE_MEMORY_CHUNK
|
||||
|
||||
config ZORRO
|
||||
bool "Amiga Zorro (AutoConfig) bus support"
|
||||
depends on AMIGA
|
||||
help
|
||||
This enables support for the Zorro bus in the Amiga. If you have
|
||||
expansion cards in your Amiga that conform to the Amiga
|
||||
AutoConfig(tm) specification, say Y, otherwise N. Note that even
|
||||
expansion cards that do not fit in the Zorro slots but fit in e.g.
|
||||
the CPU slot may fall in this category, so you have to say Y to let
|
||||
Linux use these.
|
||||
|
||||
config AMIGA_PCMCIA
|
||||
bool "Amiga 1200/600 PCMCIA support (EXPERIMENTAL)"
|
||||
depends on AMIGA && EXPERIMENTAL
|
||||
help
|
||||
Include support in the kernel for pcmcia on Amiga 1200 and Amiga
|
||||
600. If you intend to use pcmcia cards say Y; otherwise say N.
|
||||
|
||||
config STRAM_PROC
|
||||
bool "ST-RAM statistics in /proc"
|
||||
depends on ATARI
|
||||
help
|
||||
Say Y here to report ST-RAM usage statistics in /proc/stram.
|
||||
|
||||
config HEARTBEAT
|
||||
bool "Use power LED as a heartbeat" if AMIGA || APOLLO || ATARI || MAC ||Q40
|
||||
default y if !AMIGA && !APOLLO && !ATARI && !MAC && !Q40 && HP300
|
||||
help
|
||||
Use the power-on LED on your machine as a load meter. The exact
|
||||
behavior is platform-dependent, but normally the flash frequency is
|
||||
a hyperbolic function of the 5-minute load average.
|
||||
|
||||
# We have a dedicated heartbeat LED. :-)
|
||||
config PROC_HARDWARE
|
||||
bool "/proc/hardware support"
|
||||
help
|
||||
Say Y here to support the /proc/hardware file, which gives you
|
||||
access to information about the machine you're running on,
|
||||
including the model, CPU, MMU, clock speed, BogoMIPS rating,
|
||||
and memory size.
|
||||
|
||||
config ISA
|
||||
bool
|
||||
depends on Q40 || AMIGA_PCMCIA
|
||||
default y
|
||||
help
|
||||
Find out whether you have ISA slots on your motherboard. ISA is the
|
||||
name of a bus system, i.e. the way the CPU talks to the other stuff
|
||||
inside your box. Other bus systems are PCI, EISA, MicroChannel
|
||||
(MCA) or VESA. ISA is an older system, now being displaced by PCI;
|
||||
newer boards don't support it. If you have ISA, say Y, otherwise N.
|
||||
|
||||
config GENERIC_ISA_DMA
|
||||
bool
|
||||
depends on Q40 || AMIGA_PCMCIA
|
||||
default y
|
||||
|
||||
source "drivers/pci/Kconfig"
|
||||
|
||||
source "drivers/zorro/Kconfig"
|
||||
|
@ -1,43 +1,7 @@
|
||||
config M68K
|
||||
bool
|
||||
default y
|
||||
select HAVE_IDE
|
||||
select HAVE_GENERIC_HARDIRQS
|
||||
select GENERIC_HARDIRQS_NO_DEPRECATED
|
||||
|
||||
config MMU
|
||||
bool
|
||||
default n
|
||||
|
||||
config NO_DMA
|
||||
bool
|
||||
depends on !COLDFIRE
|
||||
default y
|
||||
|
||||
config FPU
|
||||
bool
|
||||
default n
|
||||
|
||||
config ZONE_DMA
|
||||
bool
|
||||
default y
|
||||
|
||||
config RWSEM_GENERIC_SPINLOCK
|
||||
bool
|
||||
default y
|
||||
|
||||
config RWSEM_XCHGADD_ALGORITHM
|
||||
bool
|
||||
default n
|
||||
|
||||
config ARCH_HAS_ILOG2_U32
|
||||
bool
|
||||
default n
|
||||
|
||||
config ARCH_HAS_ILOG2_U64
|
||||
bool
|
||||
default n
|
||||
|
||||
config GENERIC_FIND_NEXT_BIT
|
||||
bool
|
||||
default y
|
||||
@ -46,29 +10,14 @@ config GENERIC_GPIO
|
||||
bool
|
||||
default n
|
||||
|
||||
config GENERIC_HWEIGHT
|
||||
bool
|
||||
default y
|
||||
|
||||
config GENERIC_CALIBRATE_DELAY
|
||||
bool
|
||||
default y
|
||||
|
||||
config GENERIC_CMOS_UPDATE
|
||||
bool
|
||||
default y
|
||||
|
||||
config TIME_LOW_RES
|
||||
bool
|
||||
default y
|
||||
|
||||
config GENERIC_CLOCKEVENTS
|
||||
bool
|
||||
default n
|
||||
|
||||
config NO_IOPORT
|
||||
def_bool y
|
||||
|
||||
config COLDFIRE_SW_A7
|
||||
bool
|
||||
default n
|
||||
@ -85,12 +34,6 @@ config HAVE_MBAR
|
||||
config HAVE_IPSBAR
|
||||
bool
|
||||
|
||||
source "init/Kconfig"
|
||||
|
||||
source "kernel/Kconfig.freezer"
|
||||
|
||||
menu "Processor type and features"
|
||||
|
||||
choice
|
||||
prompt "CPU"
|
||||
default M68EZ328
|
||||
@ -630,11 +573,6 @@ config 4KSTACKS
|
||||
running more threads on a system and also reduces the pressure
|
||||
on the VM subsystem for higher order allocations.
|
||||
|
||||
config HZ
|
||||
int
|
||||
default 1000 if CLEOPATRA
|
||||
default 100
|
||||
|
||||
comment "RAM configuration"
|
||||
|
||||
config RAMBASE
|
||||
@ -803,10 +741,6 @@ endif
|
||||
|
||||
source "kernel/time/Kconfig"
|
||||
|
||||
source "mm/Kconfig"
|
||||
|
||||
endmenu
|
||||
|
||||
config ISA_DMA_API
|
||||
bool
|
||||
depends on !M5272
|
||||
@ -814,31 +748,3 @@ config ISA_DMA_API
|
||||
|
||||
source "drivers/pcmcia/Kconfig"
|
||||
|
||||
menu "Executable file formats"
|
||||
|
||||
source "fs/Kconfig.binfmt"
|
||||
|
||||
endmenu
|
||||
|
||||
menu "Power management options"
|
||||
|
||||
config PM
|
||||
bool "Power Management support"
|
||||
help
|
||||
Support processor power management modes
|
||||
|
||||
endmenu
|
||||
|
||||
source "net/Kconfig"
|
||||
|
||||
source "drivers/Kconfig"
|
||||
|
||||
source "fs/Kconfig"
|
||||
|
||||
source "arch/m68knommu/Kconfig.debug"
|
||||
|
||||
source "security/Kconfig"
|
||||
|
||||
source "crypto/Kconfig"
|
||||
|
||||
source "lib/Kconfig"
|
@ -1,123 +1,7 @@
|
||||
#
|
||||
# m68k/Makefile
|
||||
#
|
||||
# This file is included by the global makefile so that you can add your own
|
||||
# architecture-specific flags and dependencies. Remember to do have actions
|
||||
# for "archclean" and "archdep" for cleaning up and making dependencies for
|
||||
# this architecture
|
||||
#
|
||||
# This file is subject to the terms and conditions of the GNU General Public
|
||||
# License. See the file "COPYING" in the main directory of this archive
|
||||
# for more details.
|
||||
#
|
||||
# Copyright (C) 1994 by Hamish Macdonald
|
||||
#
|
||||
|
||||
KBUILD_DEFCONFIG := multi_defconfig
|
||||
|
||||
# override top level makefile
|
||||
AS += -m68020
|
||||
LDFLAGS := -m m68kelf
|
||||
KBUILD_LDFLAGS_MODULE += -T $(srctree)/arch/m68k/kernel/module.lds
|
||||
ifneq ($(SUBARCH),$(ARCH))
|
||||
ifeq ($(CROSS_COMPILE),)
|
||||
CROSS_COMPILE := $(call cc-cross-prefix, \
|
||||
m68k-linux-gnu- m68k-linux- m68k-unknown-linux-gnu-)
|
||||
endif
|
||||
endif
|
||||
|
||||
ifdef CONFIG_SUN3
|
||||
LDFLAGS_vmlinux = -N
|
||||
endif
|
||||
|
||||
CHECKFLAGS += -D__mc68000__
|
||||
|
||||
# without -fno-strength-reduce the 53c7xx.c driver fails ;-(
|
||||
KBUILD_CFLAGS += -pipe -fno-strength-reduce -ffixed-a2
|
||||
|
||||
# enable processor switch if compiled only for a single cpu
|
||||
ifndef CONFIG_M68020
|
||||
ifndef CONFIG_M68030
|
||||
|
||||
ifndef CONFIG_M68060
|
||||
KBUILD_CFLAGS += -m68040
|
||||
endif
|
||||
|
||||
ifndef CONFIG_M68040
|
||||
KBUILD_CFLAGS += -m68060
|
||||
endif
|
||||
|
||||
endif
|
||||
endif
|
||||
|
||||
ifdef CONFIG_KGDB
|
||||
# If configured for kgdb support, include debugging infos and keep the
|
||||
# frame pointer
|
||||
KBUILD_CFLAGS := $(subst -fomit-frame-pointer,,$(KBUILD_CFLAGS)) -g
|
||||
endif
|
||||
|
||||
ifndef CONFIG_SUN3
|
||||
head-y := arch/m68k/kernel/head.o
|
||||
ifdef CONFIG_MMU
|
||||
include $(srctree)/arch/m68k/Makefile_mm
|
||||
else
|
||||
head-y := arch/m68k/kernel/sun3-head.o
|
||||
include $(srctree)/arch/m68k/Makefile_no
|
||||
endif
|
||||
|
||||
core-y += arch/m68k/kernel/ arch/m68k/mm/
|
||||
libs-y += arch/m68k/lib/
|
||||
|
||||
core-$(CONFIG_Q40) += arch/m68k/q40/
|
||||
core-$(CONFIG_AMIGA) += arch/m68k/amiga/
|
||||
core-$(CONFIG_ATARI) += arch/m68k/atari/
|
||||
core-$(CONFIG_MAC) += arch/m68k/mac/
|
||||
core-$(CONFIG_HP300) += arch/m68k/hp300/
|
||||
core-$(CONFIG_APOLLO) += arch/m68k/apollo/
|
||||
core-$(CONFIG_MVME147) += arch/m68k/mvme147/
|
||||
core-$(CONFIG_MVME16x) += arch/m68k/mvme16x/
|
||||
core-$(CONFIG_BVME6000) += arch/m68k/bvme6000/
|
||||
core-$(CONFIG_SUN3X) += arch/m68k/sun3x/ arch/m68k/sun3/
|
||||
core-$(CONFIG_SUN3) += arch/m68k/sun3/ arch/m68k/sun3/prom/
|
||||
core-$(CONFIG_NATFEAT) += arch/m68k/emu/
|
||||
core-$(CONFIG_M68040) += arch/m68k/fpsp040/
|
||||
core-$(CONFIG_M68060) += arch/m68k/ifpsp060/
|
||||
core-$(CONFIG_M68KFPU_EMU) += arch/m68k/math-emu/
|
||||
|
||||
all: zImage
|
||||
|
||||
lilo: vmlinux
|
||||
if [ -f $(INSTALL_PATH)/vmlinux ]; then mv -f $(INSTALL_PATH)/vmlinux $(INSTALL_PATH)/vmlinux.old; fi
|
||||
if [ -f $(INSTALL_PATH)/System.map ]; then mv -f $(INSTALL_PATH)/System.map $(INSTALL_PATH)/System.old; fi
|
||||
cat vmlinux > $(INSTALL_PATH)/vmlinux
|
||||
cp System.map $(INSTALL_PATH)/System.map
|
||||
if [ -x /sbin/lilo ]; then /sbin/lilo; else /etc/lilo/install; fi
|
||||
|
||||
zImage compressed: vmlinux.gz
|
||||
|
||||
vmlinux.gz: vmlinux
|
||||
|
||||
ifndef CONFIG_KGDB
|
||||
cp vmlinux vmlinux.tmp
|
||||
$(STRIP) vmlinux.tmp
|
||||
gzip -9c vmlinux.tmp >vmlinux.gz
|
||||
rm vmlinux.tmp
|
||||
else
|
||||
gzip -9c vmlinux >vmlinux.gz
|
||||
endif
|
||||
|
||||
bzImage: vmlinux.bz2
|
||||
|
||||
vmlinux.bz2: vmlinux
|
||||
|
||||
ifndef CONFIG_KGDB
|
||||
cp vmlinux vmlinux.tmp
|
||||
$(STRIP) vmlinux.tmp
|
||||
bzip2 -1c vmlinux.tmp >vmlinux.bz2
|
||||
rm vmlinux.tmp
|
||||
else
|
||||
bzip2 -1c vmlinux >vmlinux.bz2
|
||||
endif
|
||||
|
||||
archclean:
|
||||
rm -f vmlinux.gz vmlinux.bz2
|
||||
|
||||
install:
|
||||
sh $(srctree)/arch/m68k/install.sh $(KERNELRELEASE) vmlinux.gz System.map "$(INSTALL_PATH)"
|
||||
|
121
arch/m68k/Makefile_mm
Normal file
121
arch/m68k/Makefile_mm
Normal file
@ -0,0 +1,121 @@
|
||||
#
|
||||
# m68k/Makefile
|
||||
#
|
||||
# This file is included by the global makefile so that you can add your own
|
||||
# architecture-specific flags and dependencies. Remember to do have actions
|
||||
# for "archclean" and "archdep" for cleaning up and making dependencies for
|
||||
# this architecture
|
||||
#
|
||||
# This file is subject to the terms and conditions of the GNU General Public
|
||||
# License. See the file "COPYING" in the main directory of this archive
|
||||
# for more details.
|
||||
#
|
||||
# Copyright (C) 1994 by Hamish Macdonald
|
||||
#
|
||||
|
||||
# override top level makefile
|
||||
AS += -m68020
|
||||
LDFLAGS := -m m68kelf
|
||||
KBUILD_LDFLAGS_MODULE += -T $(srctree)/arch/m68k/kernel/module.lds
|
||||
ifneq ($(SUBARCH),$(ARCH))
|
||||
ifeq ($(CROSS_COMPILE),)
|
||||
CROSS_COMPILE := $(call cc-cross-prefix, \
|
||||
m68k-linux-gnu- m68k-linux- m68k-unknown-linux-gnu-)
|
||||
endif
|
||||
endif
|
||||
|
||||
ifdef CONFIG_SUN3
|
||||
LDFLAGS_vmlinux = -N
|
||||
endif
|
||||
|
||||
CHECKFLAGS += -D__mc68000__
|
||||
|
||||
# without -fno-strength-reduce the 53c7xx.c driver fails ;-(
|
||||
KBUILD_CFLAGS += -pipe -fno-strength-reduce -ffixed-a2
|
||||
|
||||
# enable processor switch if compiled only for a single cpu
|
||||
ifndef CONFIG_M68020
|
||||
ifndef CONFIG_M68030
|
||||
|
||||
ifndef CONFIG_M68060
|
||||
KBUILD_CFLAGS += -m68040
|
||||
endif
|
||||
|
||||
ifndef CONFIG_M68040
|
||||
KBUILD_CFLAGS += -m68060
|
||||
endif
|
||||
|
||||
endif
|
||||
endif
|
||||
|
||||
ifdef CONFIG_KGDB
|
||||
# If configured for kgdb support, include debugging infos and keep the
|
||||
# frame pointer
|
||||
KBUILD_CFLAGS := $(subst -fomit-frame-pointer,,$(KBUILD_CFLAGS)) -g
|
||||
endif
|
||||
|
||||
ifndef CONFIG_SUN3
|
||||
head-y := arch/m68k/kernel/head.o
|
||||
else
|
||||
head-y := arch/m68k/kernel/sun3-head.o
|
||||
endif
|
||||
|
||||
core-y += arch/m68k/kernel/ arch/m68k/mm/
|
||||
libs-y += arch/m68k/lib/
|
||||
|
||||
core-$(CONFIG_Q40) += arch/m68k/q40/
|
||||
core-$(CONFIG_AMIGA) += arch/m68k/amiga/
|
||||
core-$(CONFIG_ATARI) += arch/m68k/atari/
|
||||
core-$(CONFIG_MAC) += arch/m68k/mac/
|
||||
core-$(CONFIG_HP300) += arch/m68k/hp300/
|
||||
core-$(CONFIG_APOLLO) += arch/m68k/apollo/
|
||||
core-$(CONFIG_MVME147) += arch/m68k/mvme147/
|
||||
core-$(CONFIG_MVME16x) += arch/m68k/mvme16x/
|
||||
core-$(CONFIG_BVME6000) += arch/m68k/bvme6000/
|
||||
core-$(CONFIG_SUN3X) += arch/m68k/sun3x/ arch/m68k/sun3/
|
||||
core-$(CONFIG_SUN3) += arch/m68k/sun3/ arch/m68k/sun3/prom/
|
||||
core-$(CONFIG_NATFEAT) += arch/m68k/emu/
|
||||
core-$(CONFIG_M68040) += arch/m68k/fpsp040/
|
||||
core-$(CONFIG_M68060) += arch/m68k/ifpsp060/
|
||||
core-$(CONFIG_M68KFPU_EMU) += arch/m68k/math-emu/
|
||||
|
||||
all: zImage
|
||||
|
||||
lilo: vmlinux
|
||||
if [ -f $(INSTALL_PATH)/vmlinux ]; then mv -f $(INSTALL_PATH)/vmlinux $(INSTALL_PATH)/vmlinux.old; fi
|
||||
if [ -f $(INSTALL_PATH)/System.map ]; then mv -f $(INSTALL_PATH)/System.map $(INSTALL_PATH)/System.old; fi
|
||||
cat vmlinux > $(INSTALL_PATH)/vmlinux
|
||||
cp System.map $(INSTALL_PATH)/System.map
|
||||
if [ -x /sbin/lilo ]; then /sbin/lilo; else /etc/lilo/install; fi
|
||||
|
||||
zImage compressed: vmlinux.gz
|
||||
|
||||
vmlinux.gz: vmlinux
|
||||
|
||||
ifndef CONFIG_KGDB
|
||||
cp vmlinux vmlinux.tmp
|
||||
$(STRIP) vmlinux.tmp
|
||||
gzip -9c vmlinux.tmp >vmlinux.gz
|
||||
rm vmlinux.tmp
|
||||
else
|
||||
gzip -9c vmlinux >vmlinux.gz
|
||||
endif
|
||||
|
||||
bzImage: vmlinux.bz2
|
||||
|
||||
vmlinux.bz2: vmlinux
|
||||
|
||||
ifndef CONFIG_KGDB
|
||||
cp vmlinux vmlinux.tmp
|
||||
$(STRIP) vmlinux.tmp
|
||||
bzip2 -1c vmlinux.tmp >vmlinux.bz2
|
||||
rm vmlinux.tmp
|
||||
else
|
||||
bzip2 -1c vmlinux >vmlinux.bz2
|
||||
endif
|
||||
|
||||
archclean:
|
||||
rm -f vmlinux.gz vmlinux.bz2
|
||||
|
||||
install:
|
||||
sh $(srctree)/arch/m68k/install.sh $(KERNELRELEASE) vmlinux.gz System.map "$(INSTALL_PATH)"
|
@ -1,5 +1,5 @@
|
||||
#
|
||||
# arch/m68knommu/Makefile
|
||||
# arch/m68k/Makefile
|
||||
#
|
||||
# This file is subject to the terms and conditions of the GNU General Public
|
||||
# License. See the file "COPYING" in the main directory of this archive
|
||||
@ -8,8 +8,6 @@
|
||||
# (C) Copyright 2002, Greg Ungerer <gerg@snapgear.com>
|
||||
#
|
||||
|
||||
KBUILD_DEFCONFIG := m5208evb_defconfig
|
||||
|
||||
platform-$(CONFIG_M68328) := 68328
|
||||
platform-$(CONFIG_M68EZ328) := 68EZ328
|
||||
platform-$(CONFIG_M68VZ328) := 68VZ328
|
||||
@ -82,7 +80,7 @@ cpuclass-$(CONFIG_M68360) := 68360
|
||||
CPUCLASS := $(cpuclass-y)
|
||||
|
||||
ifneq ($(CPUCLASS),$(PLATFORM))
|
||||
CLASSDIR := arch/m68knommu/platform/$(cpuclass-y)/
|
||||
CLASSDIR := arch/m68k/platform/$(cpuclass-y)/
|
||||
endif
|
||||
|
||||
export PLATFORM BOARD MODEL CPUCLASS
|
||||
@ -114,13 +112,13 @@ KBUILD_CFLAGS += $(cflags-y)
|
||||
KBUILD_CFLAGS += -D__linux__
|
||||
KBUILD_CFLAGS += -DUTS_SYSNAME=\"uClinux\"
|
||||
|
||||
head-y := arch/m68knommu/platform/$(cpuclass-y)/head.o
|
||||
head-y := arch/m68k/platform/$(cpuclass-y)/head.o
|
||||
|
||||
core-y += arch/m68knommu/kernel/ \
|
||||
arch/m68knommu/mm/ \
|
||||
core-y += arch/m68k/kernel/ \
|
||||
arch/m68k/mm/ \
|
||||
$(CLASSDIR) \
|
||||
arch/m68knommu/platform/$(PLATFORM)/
|
||||
libs-y += arch/m68knommu/lib/
|
||||
arch/m68k/platform/$(PLATFORM)/
|
||||
libs-y += arch/m68k/lib/
|
||||
|
||||
archclean:
|
||||
|
@ -1,3 +1,4 @@
|
||||
# CONFIG_MMU is not set
|
||||
CONFIG_EXPERIMENTAL=y
|
||||
CONFIG_LOG_BUF_SHIFT=14
|
||||
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
|
||||
@ -37,6 +38,7 @@ CONFIG_INET=y
|
||||
# CONFIG_INET_LRO is not set
|
||||
# CONFIG_INET_DIAG is not set
|
||||
# CONFIG_IPV6 is not set
|
||||
# CONFIG_FW_LOADER is not set
|
||||
CONFIG_MTD=y
|
||||
CONFIG_MTD_PARTITIONS=y
|
||||
CONFIG_MTD_CHAR=y
|
@ -1,3 +1,4 @@
|
||||
# CONFIG_MMU is not set
|
||||
CONFIG_EXPERIMENTAL=y
|
||||
CONFIG_LOG_BUF_SHIFT=14
|
||||
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
|
||||
@ -35,6 +36,7 @@ CONFIG_INET=y
|
||||
# CONFIG_INET_LRO is not set
|
||||
# CONFIG_INET_DIAG is not set
|
||||
# CONFIG_IPV6 is not set
|
||||
# CONFIG_FW_LOADER is not set
|
||||
CONFIG_MTD=y
|
||||
CONFIG_MTD_PARTITIONS=y
|
||||
CONFIG_MTD_CHAR=y
|
@ -1,3 +1,4 @@
|
||||
# CONFIG_MMU is not set
|
||||
CONFIG_EXPERIMENTAL=y
|
||||
CONFIG_LOG_BUF_SHIFT=14
|
||||
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
|
||||
@ -33,6 +34,7 @@ CONFIG_INET=y
|
||||
# CONFIG_INET_LRO is not set
|
||||
# CONFIG_INET_DIAG is not set
|
||||
# CONFIG_IPV6 is not set
|
||||
# CONFIG_FW_LOADER is not set
|
||||
CONFIG_MTD=y
|
||||
CONFIG_MTD_PARTITIONS=y
|
||||
CONFIG_MTD_CHAR=y
|
@ -1,3 +1,4 @@
|
||||
# CONFIG_MMU is not set
|
||||
CONFIG_EXPERIMENTAL=y
|
||||
CONFIG_LOG_BUF_SHIFT=14
|
||||
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
|
||||
@ -36,6 +37,7 @@ CONFIG_INET=y
|
||||
# CONFIG_INET_LRO is not set
|
||||
# CONFIG_INET_DIAG is not set
|
||||
# CONFIG_IPV6 is not set
|
||||
# CONFIG_FW_LOADER is not set
|
||||
CONFIG_MTD=y
|
||||
CONFIG_MTD_PARTITIONS=y
|
||||
CONFIG_MTD_CHAR=y
|
@ -1,3 +1,4 @@
|
||||
# CONFIG_MMU is not set
|
||||
CONFIG_EXPERIMENTAL=y
|
||||
CONFIG_LOG_BUF_SHIFT=14
|
||||
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
|
||||
@ -35,6 +36,7 @@ CONFIG_INET=y
|
||||
# CONFIG_INET_LRO is not set
|
||||
# CONFIG_INET_DIAG is not set
|
||||
# CONFIG_IPV6 is not set
|
||||
# CONFIG_FW_LOADER is not set
|
||||
CONFIG_MTD=y
|
||||
CONFIG_MTD_PARTITIONS=y
|
||||
CONFIG_MTD_CHAR=y
|
@ -1,3 +1,4 @@
|
||||
# CONFIG_MMU is not set
|
||||
CONFIG_EXPERIMENTAL=y
|
||||
CONFIG_LOG_BUF_SHIFT=14
|
||||
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
|
||||
@ -35,6 +36,7 @@ CONFIG_INET=y
|
||||
# CONFIG_INET_LRO is not set
|
||||
# CONFIG_INET_DIAG is not set
|
||||
# CONFIG_IPV6 is not set
|
||||
# CONFIG_FW_LOADER is not set
|
||||
CONFIG_MTD=y
|
||||
CONFIG_MTD_PARTITIONS=y
|
||||
CONFIG_MTD_CHAR=y
|
@ -1,17 +1,5 @@
|
||||
#
|
||||
# Makefile for the linux kernel.
|
||||
#
|
||||
|
||||
ifndef CONFIG_SUN3
|
||||
extra-y := head.o
|
||||
ifdef CONFIG_MMU
|
||||
include arch/m68k/kernel/Makefile_mm
|
||||
else
|
||||
extra-y := sun3-head.o
|
||||
include arch/m68k/kernel/Makefile_no
|
||||
endif
|
||||
extra-y += vmlinux.lds
|
||||
|
||||
obj-y := entry.o process.o traps.o ints.o signal.o ptrace.o module.o \
|
||||
sys_m68k.o time.o setup.o m68k_ksyms.o devres.o
|
||||
|
||||
devres-y = ../../../kernel/irq/devres.o
|
||||
|
||||
obj-y$(CONFIG_MMU_SUN3) += dma.o # no, it's not a typo
|
||||
|
17
arch/m68k/kernel/Makefile_mm
Normal file
17
arch/m68k/kernel/Makefile_mm
Normal file
@ -0,0 +1,17 @@
|
||||
#
|
||||
# Makefile for the linux kernel.
|
||||
#
|
||||
|
||||
ifndef CONFIG_SUN3
|
||||
extra-y := head.o
|
||||
else
|
||||
extra-y := sun3-head.o
|
||||
endif
|
||||
extra-y += vmlinux.lds
|
||||
|
||||
obj-y := entry.o process.o traps.o ints.o signal.o ptrace.o module.o \
|
||||
sys_m68k.o time.o setup.o m68k_ksyms.o devres.o
|
||||
|
||||
devres-y = ../../../kernel/irq/devres.o
|
||||
|
||||
obj-y$(CONFIG_MMU_SUN3) += dma.o # no, it's not a typo
|
@ -1,100 +1,5 @@
|
||||
/*
|
||||
* This program is used to generate definitions needed by
|
||||
* assembly language modules.
|
||||
*
|
||||
* We use the technique used in the OSF Mach kernel code:
|
||||
* generate asm statements containing #defines,
|
||||
* compile this file to assembler, and then extract the
|
||||
* #defines from the assembly-language output.
|
||||
*/
|
||||
|
||||
#define ASM_OFFSETS_C
|
||||
|
||||
#include <linux/stddef.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/kernel_stat.h>
|
||||
#include <linux/kbuild.h>
|
||||
#include <asm/bootinfo.h>
|
||||
#include <asm/irq.h>
|
||||
#include <asm/amigahw.h>
|
||||
#include <linux/font.h>
|
||||
|
||||
int main(void)
|
||||
{
|
||||
/* offsets into the task struct */
|
||||
DEFINE(TASK_THREAD, offsetof(struct task_struct, thread));
|
||||
DEFINE(TASK_INFO, offsetof(struct task_struct, thread.info));
|
||||
DEFINE(TASK_MM, offsetof(struct task_struct, mm));
|
||||
#ifdef CONFIG_MMU
|
||||
DEFINE(TASK_TINFO, offsetof(struct task_struct, thread.info));
|
||||
#include "asm-offsets_mm.c"
|
||||
#else
|
||||
#include "asm-offsets_no.c"
|
||||
#endif
|
||||
|
||||
/* offsets into the thread struct */
|
||||
DEFINE(THREAD_KSP, offsetof(struct thread_struct, ksp));
|
||||
DEFINE(THREAD_USP, offsetof(struct thread_struct, usp));
|
||||
DEFINE(THREAD_SR, offsetof(struct thread_struct, sr));
|
||||
DEFINE(THREAD_FS, offsetof(struct thread_struct, fs));
|
||||
DEFINE(THREAD_CRP, offsetof(struct thread_struct, crp));
|
||||
DEFINE(THREAD_ESP0, offsetof(struct thread_struct, esp0));
|
||||
DEFINE(THREAD_FPREG, offsetof(struct thread_struct, fp));
|
||||
DEFINE(THREAD_FPCNTL, offsetof(struct thread_struct, fpcntl));
|
||||
DEFINE(THREAD_FPSTATE, offsetof(struct thread_struct, fpstate));
|
||||
|
||||
/* offsets into the thread_info struct */
|
||||
DEFINE(TINFO_PREEMPT, offsetof(struct thread_info, preempt_count));
|
||||
DEFINE(TINFO_FLAGS, offsetof(struct thread_info, flags));
|
||||
|
||||
/* offsets into the pt_regs */
|
||||
DEFINE(PT_OFF_D0, offsetof(struct pt_regs, d0));
|
||||
DEFINE(PT_OFF_ORIG_D0, offsetof(struct pt_regs, orig_d0));
|
||||
DEFINE(PT_OFF_D1, offsetof(struct pt_regs, d1));
|
||||
DEFINE(PT_OFF_D2, offsetof(struct pt_regs, d2));
|
||||
DEFINE(PT_OFF_D3, offsetof(struct pt_regs, d3));
|
||||
DEFINE(PT_OFF_D4, offsetof(struct pt_regs, d4));
|
||||
DEFINE(PT_OFF_D5, offsetof(struct pt_regs, d5));
|
||||
DEFINE(PT_OFF_A0, offsetof(struct pt_regs, a0));
|
||||
DEFINE(PT_OFF_A1, offsetof(struct pt_regs, a1));
|
||||
DEFINE(PT_OFF_A2, offsetof(struct pt_regs, a2));
|
||||
DEFINE(PT_OFF_PC, offsetof(struct pt_regs, pc));
|
||||
DEFINE(PT_OFF_SR, offsetof(struct pt_regs, sr));
|
||||
/* bitfields are a bit difficult */
|
||||
DEFINE(PT_OFF_FORMATVEC, offsetof(struct pt_regs, pc) + 4);
|
||||
|
||||
/* offsets into the irq_cpustat_t struct */
|
||||
DEFINE(CPUSTAT_SOFTIRQ_PENDING, offsetof(irq_cpustat_t, __softirq_pending));
|
||||
|
||||
/* offsets into the bi_record struct */
|
||||
DEFINE(BIR_TAG, offsetof(struct bi_record, tag));
|
||||
DEFINE(BIR_SIZE, offsetof(struct bi_record, size));
|
||||
DEFINE(BIR_DATA, offsetof(struct bi_record, data));
|
||||
|
||||
/* offsets into font_desc (drivers/video/console/font.h) */
|
||||
DEFINE(FONT_DESC_IDX, offsetof(struct font_desc, idx));
|
||||
DEFINE(FONT_DESC_NAME, offsetof(struct font_desc, name));
|
||||
DEFINE(FONT_DESC_WIDTH, offsetof(struct font_desc, width));
|
||||
DEFINE(FONT_DESC_HEIGHT, offsetof(struct font_desc, height));
|
||||
DEFINE(FONT_DESC_DATA, offsetof(struct font_desc, data));
|
||||
DEFINE(FONT_DESC_PREF, offsetof(struct font_desc, pref));
|
||||
|
||||
/* signal defines */
|
||||
DEFINE(LSIGSEGV, SIGSEGV);
|
||||
DEFINE(LSEGV_MAPERR, SEGV_MAPERR);
|
||||
DEFINE(LSIGTRAP, SIGTRAP);
|
||||
DEFINE(LTRAP_TRACE, TRAP_TRACE);
|
||||
|
||||
/* offsets into the custom struct */
|
||||
DEFINE(CUSTOMBASE, &amiga_custom);
|
||||
DEFINE(C_INTENAR, offsetof(struct CUSTOM, intenar));
|
||||
DEFINE(C_INTREQR, offsetof(struct CUSTOM, intreqr));
|
||||
DEFINE(C_INTENA, offsetof(struct CUSTOM, intena));
|
||||
DEFINE(C_INTREQ, offsetof(struct CUSTOM, intreq));
|
||||
DEFINE(C_SERDATR, offsetof(struct CUSTOM, serdatr));
|
||||
DEFINE(C_SERDAT, offsetof(struct CUSTOM, serdat));
|
||||
DEFINE(C_SERPER, offsetof(struct CUSTOM, serper));
|
||||
DEFINE(CIAABASE, &ciaa);
|
||||
DEFINE(CIABBASE, &ciab);
|
||||
DEFINE(C_PRA, offsetof(struct CIA, pra));
|
||||
DEFINE(ZTWOBASE, zTwoBase);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
100
arch/m68k/kernel/asm-offsets_mm.c
Normal file
100
arch/m68k/kernel/asm-offsets_mm.c
Normal file
@ -0,0 +1,100 @@
|
||||
/*
|
||||
* This program is used to generate definitions needed by
|
||||
* assembly language modules.
|
||||
*
|
||||
* We use the technique used in the OSF Mach kernel code:
|
||||
* generate asm statements containing #defines,
|
||||
* compile this file to assembler, and then extract the
|
||||
* #defines from the assembly-language output.
|
||||
*/
|
||||
|
||||
#define ASM_OFFSETS_C
|
||||
|
||||
#include <linux/stddef.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/kernel_stat.h>
|
||||
#include <linux/kbuild.h>
|
||||
#include <asm/bootinfo.h>
|
||||
#include <asm/irq.h>
|
||||
#include <asm/amigahw.h>
|
||||
#include <linux/font.h>
|
||||
|
||||
int main(void)
|
||||
{
|
||||
/* offsets into the task struct */
|
||||
DEFINE(TASK_THREAD, offsetof(struct task_struct, thread));
|
||||
DEFINE(TASK_INFO, offsetof(struct task_struct, thread.info));
|
||||
DEFINE(TASK_MM, offsetof(struct task_struct, mm));
|
||||
#ifdef CONFIG_MMU
|
||||
DEFINE(TASK_TINFO, offsetof(struct task_struct, thread.info));
|
||||
#endif
|
||||
|
||||
/* offsets into the thread struct */
|
||||
DEFINE(THREAD_KSP, offsetof(struct thread_struct, ksp));
|
||||
DEFINE(THREAD_USP, offsetof(struct thread_struct, usp));
|
||||
DEFINE(THREAD_SR, offsetof(struct thread_struct, sr));
|
||||
DEFINE(THREAD_FS, offsetof(struct thread_struct, fs));
|
||||
DEFINE(THREAD_CRP, offsetof(struct thread_struct, crp));
|
||||
DEFINE(THREAD_ESP0, offsetof(struct thread_struct, esp0));
|
||||
DEFINE(THREAD_FPREG, offsetof(struct thread_struct, fp));
|
||||
DEFINE(THREAD_FPCNTL, offsetof(struct thread_struct, fpcntl));
|
||||
DEFINE(THREAD_FPSTATE, offsetof(struct thread_struct, fpstate));
|
||||
|
||||
/* offsets into the thread_info struct */
|
||||
DEFINE(TINFO_PREEMPT, offsetof(struct thread_info, preempt_count));
|
||||
DEFINE(TINFO_FLAGS, offsetof(struct thread_info, flags));
|
||||
|
||||
/* offsets into the pt_regs */
|
||||
DEFINE(PT_OFF_D0, offsetof(struct pt_regs, d0));
|
||||
DEFINE(PT_OFF_ORIG_D0, offsetof(struct pt_regs, orig_d0));
|
||||
DEFINE(PT_OFF_D1, offsetof(struct pt_regs, d1));
|
||||
DEFINE(PT_OFF_D2, offsetof(struct pt_regs, d2));
|
||||
DEFINE(PT_OFF_D3, offsetof(struct pt_regs, d3));
|
||||
DEFINE(PT_OFF_D4, offsetof(struct pt_regs, d4));
|
||||
DEFINE(PT_OFF_D5, offsetof(struct pt_regs, d5));
|
||||
DEFINE(PT_OFF_A0, offsetof(struct pt_regs, a0));
|
||||
DEFINE(PT_OFF_A1, offsetof(struct pt_regs, a1));
|
||||
DEFINE(PT_OFF_A2, offsetof(struct pt_regs, a2));
|
||||
DEFINE(PT_OFF_PC, offsetof(struct pt_regs, pc));
|
||||
DEFINE(PT_OFF_SR, offsetof(struct pt_regs, sr));
|
||||
/* bitfields are a bit difficult */
|
||||
DEFINE(PT_OFF_FORMATVEC, offsetof(struct pt_regs, pc) + 4);
|
||||
|
||||
/* offsets into the irq_cpustat_t struct */
|
||||
DEFINE(CPUSTAT_SOFTIRQ_PENDING, offsetof(irq_cpustat_t, __softirq_pending));
|
||||
|
||||
/* offsets into the bi_record struct */
|
||||
DEFINE(BIR_TAG, offsetof(struct bi_record, tag));
|
||||
DEFINE(BIR_SIZE, offsetof(struct bi_record, size));
|
||||
DEFINE(BIR_DATA, offsetof(struct bi_record, data));
|
||||
|
||||
/* offsets into font_desc (drivers/video/console/font.h) */
|
||||
DEFINE(FONT_DESC_IDX, offsetof(struct font_desc, idx));
|
||||
DEFINE(FONT_DESC_NAME, offsetof(struct font_desc, name));
|
||||
DEFINE(FONT_DESC_WIDTH, offsetof(struct font_desc, width));
|
||||
DEFINE(FONT_DESC_HEIGHT, offsetof(struct font_desc, height));
|
||||
DEFINE(FONT_DESC_DATA, offsetof(struct font_desc, data));
|
||||
DEFINE(FONT_DESC_PREF, offsetof(struct font_desc, pref));
|
||||
|
||||
/* signal defines */
|
||||
DEFINE(LSIGSEGV, SIGSEGV);
|
||||
DEFINE(LSEGV_MAPERR, SEGV_MAPERR);
|
||||
DEFINE(LSIGTRAP, SIGTRAP);
|
||||
DEFINE(LTRAP_TRACE, TRAP_TRACE);
|
||||
|
||||
/* offsets into the custom struct */
|
||||
DEFINE(CUSTOMBASE, &amiga_custom);
|
||||
DEFINE(C_INTENAR, offsetof(struct CUSTOM, intenar));
|
||||
DEFINE(C_INTREQR, offsetof(struct CUSTOM, intreqr));
|
||||
DEFINE(C_INTENA, offsetof(struct CUSTOM, intena));
|
||||
DEFINE(C_INTREQ, offsetof(struct CUSTOM, intreq));
|
||||
DEFINE(C_SERDATR, offsetof(struct CUSTOM, serdatr));
|
||||
DEFINE(C_SERDAT, offsetof(struct CUSTOM, serdat));
|
||||
DEFINE(C_SERPER, offsetof(struct CUSTOM, serper));
|
||||
DEFINE(CIAABASE, &ciaa);
|
||||
DEFINE(CIABBASE, &ciab);
|
||||
DEFINE(C_PRA, offsetof(struct CIA, pra));
|
||||
DEFINE(ZTWOBASE, zTwoBase);
|
||||
|
||||
return 0;
|
||||
}
|
@ -1,130 +1,5 @@
|
||||
/*
|
||||
* This file is subject to the terms and conditions of the GNU General Public
|
||||
* License. See the file COPYING in the main directory of this archive
|
||||
* for more details.
|
||||
*/
|
||||
|
||||
#undef DEBUG
|
||||
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/scatterlist.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/vmalloc.h>
|
||||
|
||||
#include <asm/pgalloc.h>
|
||||
|
||||
void *dma_alloc_coherent(struct device *dev, size_t size,
|
||||
dma_addr_t *handle, gfp_t flag)
|
||||
{
|
||||
struct page *page, **map;
|
||||
pgprot_t pgprot;
|
||||
void *addr;
|
||||
int i, order;
|
||||
|
||||
pr_debug("dma_alloc_coherent: %d,%x\n", size, flag);
|
||||
|
||||
size = PAGE_ALIGN(size);
|
||||
order = get_order(size);
|
||||
|
||||
page = alloc_pages(flag, order);
|
||||
if (!page)
|
||||
return NULL;
|
||||
|
||||
*handle = page_to_phys(page);
|
||||
map = kmalloc(sizeof(struct page *) << order, flag & ~__GFP_DMA);
|
||||
if (!map) {
|
||||
__free_pages(page, order);
|
||||
return NULL;
|
||||
}
|
||||
split_page(page, order);
|
||||
|
||||
order = 1 << order;
|
||||
size >>= PAGE_SHIFT;
|
||||
map[0] = page;
|
||||
for (i = 1; i < size; i++)
|
||||
map[i] = page + i;
|
||||
for (; i < order; i++)
|
||||
__free_page(page + i);
|
||||
pgprot = __pgprot(_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_DIRTY);
|
||||
if (CPU_IS_040_OR_060)
|
||||
pgprot_val(pgprot) |= _PAGE_GLOBAL040 | _PAGE_NOCACHE_S;
|
||||
else
|
||||
pgprot_val(pgprot) |= _PAGE_NOCACHE030;
|
||||
addr = vmap(map, size, VM_MAP, pgprot);
|
||||
kfree(map);
|
||||
|
||||
return addr;
|
||||
}
|
||||
EXPORT_SYMBOL(dma_alloc_coherent);
|
||||
|
||||
void dma_free_coherent(struct device *dev, size_t size,
|
||||
void *addr, dma_addr_t handle)
|
||||
{
|
||||
pr_debug("dma_free_coherent: %p, %x\n", addr, handle);
|
||||
vfree(addr);
|
||||
}
|
||||
EXPORT_SYMBOL(dma_free_coherent);
|
||||
|
||||
void dma_sync_single_for_device(struct device *dev, dma_addr_t handle,
|
||||
size_t size, enum dma_data_direction dir)
|
||||
{
|
||||
switch (dir) {
|
||||
case DMA_TO_DEVICE:
|
||||
cache_push(handle, size);
|
||||
break;
|
||||
case DMA_FROM_DEVICE:
|
||||
cache_clear(handle, size);
|
||||
break;
|
||||
default:
|
||||
if (printk_ratelimit())
|
||||
printk("dma_sync_single_for_device: unsupported dir %u\n", dir);
|
||||
break;
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(dma_sync_single_for_device);
|
||||
|
||||
void dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, int nents,
|
||||
enum dma_data_direction dir)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < nents; sg++, i++)
|
||||
dma_sync_single_for_device(dev, sg->dma_address, sg->length, dir);
|
||||
}
|
||||
EXPORT_SYMBOL(dma_sync_sg_for_device);
|
||||
|
||||
dma_addr_t dma_map_single(struct device *dev, void *addr, size_t size,
|
||||
enum dma_data_direction dir)
|
||||
{
|
||||
dma_addr_t handle = virt_to_bus(addr);
|
||||
|
||||
dma_sync_single_for_device(dev, handle, size, dir);
|
||||
return handle;
|
||||
}
|
||||
EXPORT_SYMBOL(dma_map_single);
|
||||
|
||||
dma_addr_t dma_map_page(struct device *dev, struct page *page,
|
||||
unsigned long offset, size_t size,
|
||||
enum dma_data_direction dir)
|
||||
{
|
||||
dma_addr_t handle = page_to_phys(page) + offset;
|
||||
|
||||
dma_sync_single_for_device(dev, handle, size, dir);
|
||||
return handle;
|
||||
}
|
||||
EXPORT_SYMBOL(dma_map_page);
|
||||
|
||||
int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
|
||||
enum dma_data_direction dir)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < nents; sg++, i++) {
|
||||
sg->dma_address = sg_phys(sg);
|
||||
dma_sync_single_for_device(dev, sg->dma_address, sg->length, dir);
|
||||
}
|
||||
return nents;
|
||||
}
|
||||
EXPORT_SYMBOL(dma_map_sg);
|
||||
#ifdef CONFIG_MMU
|
||||
#include "dma_mm.c"
|
||||
#else
|
||||
#include "dma_no.c"
|
||||
#endif
|
||||
|
130
arch/m68k/kernel/dma_mm.c
Normal file
130
arch/m68k/kernel/dma_mm.c
Normal file
@ -0,0 +1,130 @@
|
||||
/*
|
||||
* This file is subject to the terms and conditions of the GNU General Public
|
||||
* License. See the file COPYING in the main directory of this archive
|
||||
* for more details.
|
||||
*/
|
||||
|
||||
#undef DEBUG
|
||||
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/scatterlist.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/vmalloc.h>
|
||||
|
||||
#include <asm/pgalloc.h>
|
||||
|
||||
void *dma_alloc_coherent(struct device *dev, size_t size,
|
||||
dma_addr_t *handle, gfp_t flag)
|
||||
{
|
||||
struct page *page, **map;
|
||||
pgprot_t pgprot;
|
||||
void *addr;
|
||||
int i, order;
|
||||
|
||||
pr_debug("dma_alloc_coherent: %d,%x\n", size, flag);
|
||||
|
||||
size = PAGE_ALIGN(size);
|
||||
order = get_order(size);
|
||||
|
||||
page = alloc_pages(flag, order);
|
||||
if (!page)
|
||||
return NULL;
|
||||
|
||||
*handle = page_to_phys(page);
|
||||
map = kmalloc(sizeof(struct page *) << order, flag & ~__GFP_DMA);
|
||||
if (!map) {
|
||||
__free_pages(page, order);
|
||||
return NULL;
|
||||
}
|
||||
split_page(page, order);
|
||||
|
||||
order = 1 << order;
|
||||
size >>= PAGE_SHIFT;
|
||||
map[0] = page;
|
||||
for (i = 1; i < size; i++)
|
||||
map[i] = page + i;
|
||||
for (; i < order; i++)
|
||||
__free_page(page + i);
|
||||
pgprot = __pgprot(_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_DIRTY);
|
||||
if (CPU_IS_040_OR_060)
|
||||
pgprot_val(pgprot) |= _PAGE_GLOBAL040 | _PAGE_NOCACHE_S;
|
||||
else
|
||||
pgprot_val(pgprot) |= _PAGE_NOCACHE030;
|
||||
addr = vmap(map, size, VM_MAP, pgprot);
|
||||
kfree(map);
|
||||
|
||||
return addr;
|
||||
}
|
||||
EXPORT_SYMBOL(dma_alloc_coherent);
|
||||
|
||||
void dma_free_coherent(struct device *dev, size_t size,
|
||||
void *addr, dma_addr_t handle)
|
||||
{
|
||||
pr_debug("dma_free_coherent: %p, %x\n", addr, handle);
|
||||
vfree(addr);
|
||||
}
|
||||
EXPORT_SYMBOL(dma_free_coherent);
|
||||
|
||||
void dma_sync_single_for_device(struct device *dev, dma_addr_t handle,
|
||||
size_t size, enum dma_data_direction dir)
|
||||
{
|
||||
switch (dir) {
|
||||
case DMA_TO_DEVICE:
|
||||
cache_push(handle, size);
|
||||
break;
|
||||
case DMA_FROM_DEVICE:
|
||||
cache_clear(handle, size);
|
||||
break;
|
||||
default:
|
||||
if (printk_ratelimit())
|
||||
printk("dma_sync_single_for_device: unsupported dir %u\n", dir);
|
||||
break;
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(dma_sync_single_for_device);
|
||||
|
||||
void dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, int nents,
|
||||
enum dma_data_direction dir)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < nents; sg++, i++)
|
||||
dma_sync_single_for_device(dev, sg->dma_address, sg->length, dir);
|
||||
}
|
||||
EXPORT_SYMBOL(dma_sync_sg_for_device);
|
||||
|
||||
dma_addr_t dma_map_single(struct device *dev, void *addr, size_t size,
|
||||
enum dma_data_direction dir)
|
||||
{
|
||||
dma_addr_t handle = virt_to_bus(addr);
|
||||
|
||||
dma_sync_single_for_device(dev, handle, size, dir);
|
||||
return handle;
|
||||
}
|
||||
EXPORT_SYMBOL(dma_map_single);
|
||||
|
||||
dma_addr_t dma_map_page(struct device *dev, struct page *page,
|
||||
unsigned long offset, size_t size,
|
||||
enum dma_data_direction dir)
|
||||
{
|
||||
dma_addr_t handle = page_to_phys(page) + offset;
|
||||
|
||||
dma_sync_single_for_device(dev, handle, size, dir);
|
||||
return handle;
|
||||
}
|
||||
EXPORT_SYMBOL(dma_map_page);
|
||||
|
||||
int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
|
||||
enum dma_data_direction dir)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < nents; sg++, i++) {
|
||||
sg->dma_address = sg_phys(sg);
|
||||
dma_sync_single_for_device(dev, sg->dma_address, sg->length, dir);
|
||||
}
|
||||
return nents;
|
||||
}
|
||||
EXPORT_SYMBOL(dma_map_sg);
|
@ -1,753 +1,5 @@
|
||||
/* -*- mode: asm -*-
|
||||
*
|
||||
* linux/arch/m68k/kernel/entry.S
|
||||
*
|
||||
* Copyright (C) 1991, 1992 Linus Torvalds
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU General Public
|
||||
* License. See the file README.legal in the main directory of this archive
|
||||
* for more details.
|
||||
*
|
||||
* Linux/m68k support by Hamish Macdonald
|
||||
*
|
||||
* 68060 fixes by Jesper Skov
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* entry.S contains the system-call and fault low-level handling routines.
|
||||
* This also contains the timer-interrupt handler, as well as all interrupts
|
||||
* and faults that can result in a task-switch.
|
||||
*
|
||||
* NOTE: This code handles signal-recognition, which happens every time
|
||||
* after a timer-interrupt and after each system call.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* 12/03/96 Jes: Currently we only support m68k single-cpu systems, so
|
||||
* all pointers that used to be 'current' are now entry
|
||||
* number 0 in the 'current_set' list.
|
||||
*
|
||||
* 6/05/00 RZ: addedd writeback completion after return from sighandler
|
||||
* for 68040
|
||||
*/
|
||||
|
||||
#include <linux/linkage.h>
|
||||
#include <asm/entry.h>
|
||||
#include <asm/errno.h>
|
||||
#include <asm/setup.h>
|
||||
#include <asm/segment.h>
|
||||
#include <asm/traps.h>
|
||||
#include <asm/unistd.h>
|
||||
|
||||
#include <asm/asm-offsets.h>
|
||||
|
||||
.globl system_call, buserr, trap, resume
|
||||
.globl sys_call_table
|
||||
.globl sys_fork, sys_clone, sys_vfork
|
||||
.globl ret_from_interrupt, bad_interrupt
|
||||
.globl auto_irqhandler_fixup
|
||||
.globl user_irqvec_fixup, user_irqhandler_fixup
|
||||
|
||||
.text
|
||||
ENTRY(buserr)
|
||||
SAVE_ALL_INT
|
||||
GET_CURRENT(%d0)
|
||||
movel %sp,%sp@- | stack frame pointer argument
|
||||
bsrl buserr_c
|
||||
addql #4,%sp
|
||||
jra .Lret_from_exception
|
||||
|
||||
ENTRY(trap)
|
||||
SAVE_ALL_INT
|
||||
GET_CURRENT(%d0)
|
||||
movel %sp,%sp@- | stack frame pointer argument
|
||||
bsrl trap_c
|
||||
addql #4,%sp
|
||||
jra .Lret_from_exception
|
||||
|
||||
| After a fork we jump here directly from resume,
|
||||
| so that %d1 contains the previous task
|
||||
| schedule_tail now used regardless of CONFIG_SMP
|
||||
ENTRY(ret_from_fork)
|
||||
movel %d1,%sp@-
|
||||
jsr schedule_tail
|
||||
addql #4,%sp
|
||||
jra .Lret_from_exception
|
||||
|
||||
do_trace_entry:
|
||||
movel #-ENOSYS,%sp@(PT_OFF_D0)| needed for strace
|
||||
subql #4,%sp
|
||||
SAVE_SWITCH_STACK
|
||||
jbsr syscall_trace
|
||||
RESTORE_SWITCH_STACK
|
||||
addql #4,%sp
|
||||
movel %sp@(PT_OFF_ORIG_D0),%d0
|
||||
cmpl #NR_syscalls,%d0
|
||||
jcs syscall
|
||||
badsys:
|
||||
movel #-ENOSYS,%sp@(PT_OFF_D0)
|
||||
jra ret_from_syscall
|
||||
|
||||
do_trace_exit:
|
||||
subql #4,%sp
|
||||
SAVE_SWITCH_STACK
|
||||
jbsr syscall_trace
|
||||
RESTORE_SWITCH_STACK
|
||||
addql #4,%sp
|
||||
jra .Lret_from_exception
|
||||
|
||||
ENTRY(ret_from_signal)
|
||||
tstb %curptr@(TASK_INFO+TINFO_FLAGS+2)
|
||||
jge 1f
|
||||
jbsr syscall_trace
|
||||
1: RESTORE_SWITCH_STACK
|
||||
addql #4,%sp
|
||||
/* on 68040 complete pending writebacks if any */
|
||||
#ifdef CONFIG_M68040
|
||||
bfextu %sp@(PT_OFF_FORMATVEC){#0,#4},%d0
|
||||
subql #7,%d0 | bus error frame ?
|
||||
jbne 1f
|
||||
movel %sp,%sp@-
|
||||
jbsr berr_040cleanup
|
||||
addql #4,%sp
|
||||
1:
|
||||
#ifdef CONFIG_MMU
|
||||
#include "entry_mm.S"
|
||||
#else
|
||||
#include "entry_no.S"
|
||||
#endif
|
||||
jra .Lret_from_exception
|
||||
|
||||
ENTRY(system_call)
|
||||
SAVE_ALL_SYS
|
||||
|
||||
GET_CURRENT(%d1)
|
||||
| save top of frame
|
||||
movel %sp,%curptr@(TASK_THREAD+THREAD_ESP0)
|
||||
|
||||
| syscall trace?
|
||||
tstb %curptr@(TASK_INFO+TINFO_FLAGS+2)
|
||||
jmi do_trace_entry
|
||||
cmpl #NR_syscalls,%d0
|
||||
jcc badsys
|
||||
syscall:
|
||||
jbsr @(sys_call_table,%d0:l:4)@(0)
|
||||
movel %d0,%sp@(PT_OFF_D0) | save the return value
|
||||
ret_from_syscall:
|
||||
|oriw #0x0700,%sr
|
||||
movew %curptr@(TASK_INFO+TINFO_FLAGS+2),%d0
|
||||
jne syscall_exit_work
|
||||
1: RESTORE_ALL
|
||||
|
||||
syscall_exit_work:
|
||||
btst #5,%sp@(PT_OFF_SR) | check if returning to kernel
|
||||
bnes 1b | if so, skip resched, signals
|
||||
lslw #1,%d0
|
||||
jcs do_trace_exit
|
||||
jmi do_delayed_trace
|
||||
lslw #8,%d0
|
||||
jmi do_signal_return
|
||||
pea resume_userspace
|
||||
jra schedule
|
||||
|
||||
|
||||
ENTRY(ret_from_exception)
|
||||
.Lret_from_exception:
|
||||
btst #5,%sp@(PT_OFF_SR) | check if returning to kernel
|
||||
bnes 1f | if so, skip resched, signals
|
||||
| only allow interrupts when we are really the last one on the
|
||||
| kernel stack, otherwise stack overflow can occur during
|
||||
| heavy interrupt load
|
||||
andw #ALLOWINT,%sr
|
||||
|
||||
resume_userspace:
|
||||
moveb %curptr@(TASK_INFO+TINFO_FLAGS+3),%d0
|
||||
jne exit_work
|
||||
1: RESTORE_ALL
|
||||
|
||||
exit_work:
|
||||
| save top of frame
|
||||
movel %sp,%curptr@(TASK_THREAD+THREAD_ESP0)
|
||||
lslb #1,%d0
|
||||
jmi do_signal_return
|
||||
pea resume_userspace
|
||||
jra schedule
|
||||
|
||||
|
||||
do_signal_return:
|
||||
|andw #ALLOWINT,%sr
|
||||
subql #4,%sp | dummy return address
|
||||
SAVE_SWITCH_STACK
|
||||
pea %sp@(SWITCH_STACK_SIZE)
|
||||
bsrl do_signal
|
||||
addql #4,%sp
|
||||
RESTORE_SWITCH_STACK
|
||||
addql #4,%sp
|
||||
jbra resume_userspace
|
||||
|
||||
do_delayed_trace:
|
||||
bclr #7,%sp@(PT_OFF_SR) | clear trace bit in SR
|
||||
pea 1 | send SIGTRAP
|
||||
movel %curptr,%sp@-
|
||||
pea LSIGTRAP
|
||||
jbsr send_sig
|
||||
addql #8,%sp
|
||||
addql #4,%sp
|
||||
jbra resume_userspace
|
||||
|
||||
|
||||
/* This is the main interrupt handler for autovector interrupts */
|
||||
|
||||
ENTRY(auto_inthandler)
|
||||
SAVE_ALL_INT
|
||||
GET_CURRENT(%d0)
|
||||
addqb #1,%curptr@(TASK_INFO+TINFO_PREEMPT+1)
|
||||
| put exception # in d0
|
||||
bfextu %sp@(PT_OFF_FORMATVEC){#4,#10},%d0
|
||||
subw #VEC_SPUR,%d0
|
||||
|
||||
movel %sp,%sp@-
|
||||
movel %d0,%sp@- | put vector # on stack
|
||||
auto_irqhandler_fixup = . + 2
|
||||
jsr __m68k_handle_int | process the IRQ
|
||||
addql #8,%sp | pop parameters off stack
|
||||
|
||||
ret_from_interrupt:
|
||||
subqb #1,%curptr@(TASK_INFO+TINFO_PREEMPT+1)
|
||||
jeq ret_from_last_interrupt
|
||||
2: RESTORE_ALL
|
||||
|
||||
ALIGN
|
||||
ret_from_last_interrupt:
|
||||
moveq #(~ALLOWINT>>8)&0xff,%d0
|
||||
andb %sp@(PT_OFF_SR),%d0
|
||||
jne 2b
|
||||
|
||||
/* check if we need to do software interrupts */
|
||||
tstl irq_stat+CPUSTAT_SOFTIRQ_PENDING
|
||||
jeq .Lret_from_exception
|
||||
pea ret_from_exception
|
||||
jra do_softirq
|
||||
|
||||
/* Handler for user defined interrupt vectors */
|
||||
|
||||
ENTRY(user_inthandler)
|
||||
SAVE_ALL_INT
|
||||
GET_CURRENT(%d0)
|
||||
addqb #1,%curptr@(TASK_INFO+TINFO_PREEMPT+1)
|
||||
| put exception # in d0
|
||||
bfextu %sp@(PT_OFF_FORMATVEC){#4,#10},%d0
|
||||
user_irqvec_fixup = . + 2
|
||||
subw #VEC_USER,%d0
|
||||
|
||||
movel %sp,%sp@-
|
||||
movel %d0,%sp@- | put vector # on stack
|
||||
user_irqhandler_fixup = . + 2
|
||||
jsr __m68k_handle_int | process the IRQ
|
||||
addql #8,%sp | pop parameters off stack
|
||||
|
||||
subqb #1,%curptr@(TASK_INFO+TINFO_PREEMPT+1)
|
||||
jeq ret_from_last_interrupt
|
||||
RESTORE_ALL
|
||||
|
||||
/* Handler for uninitialized and spurious interrupts */
|
||||
|
||||
ENTRY(bad_inthandler)
|
||||
SAVE_ALL_INT
|
||||
GET_CURRENT(%d0)
|
||||
addqb #1,%curptr@(TASK_INFO+TINFO_PREEMPT+1)
|
||||
|
||||
movel %sp,%sp@-
|
||||
jsr handle_badint
|
||||
addql #4,%sp
|
||||
|
||||
subqb #1,%curptr@(TASK_INFO+TINFO_PREEMPT+1)
|
||||
jeq ret_from_last_interrupt
|
||||
RESTORE_ALL
|
||||
|
||||
|
||||
ENTRY(sys_fork)
|
||||
SAVE_SWITCH_STACK
|
||||
pea %sp@(SWITCH_STACK_SIZE)
|
||||
jbsr m68k_fork
|
||||
addql #4,%sp
|
||||
RESTORE_SWITCH_STACK
|
||||
rts
|
||||
|
||||
ENTRY(sys_clone)
|
||||
SAVE_SWITCH_STACK
|
||||
pea %sp@(SWITCH_STACK_SIZE)
|
||||
jbsr m68k_clone
|
||||
addql #4,%sp
|
||||
RESTORE_SWITCH_STACK
|
||||
rts
|
||||
|
||||
ENTRY(sys_vfork)
|
||||
SAVE_SWITCH_STACK
|
||||
pea %sp@(SWITCH_STACK_SIZE)
|
||||
jbsr m68k_vfork
|
||||
addql #4,%sp
|
||||
RESTORE_SWITCH_STACK
|
||||
rts
|
||||
|
||||
ENTRY(sys_sigreturn)
|
||||
SAVE_SWITCH_STACK
|
||||
jbsr do_sigreturn
|
||||
RESTORE_SWITCH_STACK
|
||||
rts
|
||||
|
||||
ENTRY(sys_rt_sigreturn)
|
||||
SAVE_SWITCH_STACK
|
||||
jbsr do_rt_sigreturn
|
||||
RESTORE_SWITCH_STACK
|
||||
rts
|
||||
|
||||
resume:
|
||||
/*
|
||||
* Beware - when entering resume, prev (the current task) is
|
||||
* in a0, next (the new task) is in a1,so don't change these
|
||||
* registers until their contents are no longer needed.
|
||||
*/
|
||||
|
||||
/* save sr */
|
||||
movew %sr,%a0@(TASK_THREAD+THREAD_SR)
|
||||
|
||||
/* save fs (sfc,%dfc) (may be pointing to kernel memory) */
|
||||
movec %sfc,%d0
|
||||
movew %d0,%a0@(TASK_THREAD+THREAD_FS)
|
||||
|
||||
/* save usp */
|
||||
/* it is better to use a movel here instead of a movew 8*) */
|
||||
movec %usp,%d0
|
||||
movel %d0,%a0@(TASK_THREAD+THREAD_USP)
|
||||
|
||||
/* save non-scratch registers on stack */
|
||||
SAVE_SWITCH_STACK
|
||||
|
||||
/* save current kernel stack pointer */
|
||||
movel %sp,%a0@(TASK_THREAD+THREAD_KSP)
|
||||
|
||||
/* save floating point context */
|
||||
#ifndef CONFIG_M68KFPU_EMU_ONLY
|
||||
#ifdef CONFIG_M68KFPU_EMU
|
||||
tstl m68k_fputype
|
||||
jeq 3f
|
||||
#endif
|
||||
fsave %a0@(TASK_THREAD+THREAD_FPSTATE)
|
||||
|
||||
#if defined(CONFIG_M68060)
|
||||
#if !defined(CPU_M68060_ONLY)
|
||||
btst #3,m68k_cputype+3
|
||||
beqs 1f
|
||||
#endif
|
||||
/* The 060 FPU keeps status in bits 15-8 of the first longword */
|
||||
tstb %a0@(TASK_THREAD+THREAD_FPSTATE+2)
|
||||
jeq 3f
|
||||
#if !defined(CPU_M68060_ONLY)
|
||||
jra 2f
|
||||
#endif
|
||||
#endif /* CONFIG_M68060 */
|
||||
#if !defined(CPU_M68060_ONLY)
|
||||
1: tstb %a0@(TASK_THREAD+THREAD_FPSTATE)
|
||||
jeq 3f
|
||||
#endif
|
||||
2: fmovemx %fp0-%fp7,%a0@(TASK_THREAD+THREAD_FPREG)
|
||||
fmoveml %fpcr/%fpsr/%fpiar,%a0@(TASK_THREAD+THREAD_FPCNTL)
|
||||
3:
|
||||
#endif /* CONFIG_M68KFPU_EMU_ONLY */
|
||||
/* Return previous task in %d1 */
|
||||
movel %curptr,%d1
|
||||
|
||||
/* switch to new task (a1 contains new task) */
|
||||
movel %a1,%curptr
|
||||
|
||||
/* restore floating point context */
|
||||
#ifndef CONFIG_M68KFPU_EMU_ONLY
|
||||
#ifdef CONFIG_M68KFPU_EMU
|
||||
tstl m68k_fputype
|
||||
jeq 4f
|
||||
#endif
|
||||
#if defined(CONFIG_M68060)
|
||||
#if !defined(CPU_M68060_ONLY)
|
||||
btst #3,m68k_cputype+3
|
||||
beqs 1f
|
||||
#endif
|
||||
/* The 060 FPU keeps status in bits 15-8 of the first longword */
|
||||
tstb %a1@(TASK_THREAD+THREAD_FPSTATE+2)
|
||||
jeq 3f
|
||||
#if !defined(CPU_M68060_ONLY)
|
||||
jra 2f
|
||||
#endif
|
||||
#endif /* CONFIG_M68060 */
|
||||
#if !defined(CPU_M68060_ONLY)
|
||||
1: tstb %a1@(TASK_THREAD+THREAD_FPSTATE)
|
||||
jeq 3f
|
||||
#endif
|
||||
2: fmovemx %a1@(TASK_THREAD+THREAD_FPREG),%fp0-%fp7
|
||||
fmoveml %a1@(TASK_THREAD+THREAD_FPCNTL),%fpcr/%fpsr/%fpiar
|
||||
3: frestore %a1@(TASK_THREAD+THREAD_FPSTATE)
|
||||
4:
|
||||
#endif /* CONFIG_M68KFPU_EMU_ONLY */
|
||||
|
||||
/* restore the kernel stack pointer */
|
||||
movel %a1@(TASK_THREAD+THREAD_KSP),%sp
|
||||
|
||||
/* restore non-scratch registers */
|
||||
RESTORE_SWITCH_STACK
|
||||
|
||||
/* restore user stack pointer */
|
||||
movel %a1@(TASK_THREAD+THREAD_USP),%a0
|
||||
movel %a0,%usp
|
||||
|
||||
/* restore fs (sfc,%dfc) */
|
||||
movew %a1@(TASK_THREAD+THREAD_FS),%a0
|
||||
movec %a0,%sfc
|
||||
movec %a0,%dfc
|
||||
|
||||
/* restore status register */
|
||||
movew %a1@(TASK_THREAD+THREAD_SR),%sr
|
||||
|
||||
rts
|
||||
|
||||
.data
|
||||
ALIGN
|
||||
sys_call_table:
|
||||
.long sys_restart_syscall /* 0 - old "setup()" system call, used for restarting */
|
||||
.long sys_exit
|
||||
.long sys_fork
|
||||
.long sys_read
|
||||
.long sys_write
|
||||
.long sys_open /* 5 */
|
||||
.long sys_close
|
||||
.long sys_waitpid
|
||||
.long sys_creat
|
||||
.long sys_link
|
||||
.long sys_unlink /* 10 */
|
||||
.long sys_execve
|
||||
.long sys_chdir
|
||||
.long sys_time
|
||||
.long sys_mknod
|
||||
.long sys_chmod /* 15 */
|
||||
.long sys_chown16
|
||||
.long sys_ni_syscall /* old break syscall holder */
|
||||
.long sys_stat
|
||||
.long sys_lseek
|
||||
.long sys_getpid /* 20 */
|
||||
.long sys_mount
|
||||
.long sys_oldumount
|
||||
.long sys_setuid16
|
||||
.long sys_getuid16
|
||||
.long sys_stime /* 25 */
|
||||
.long sys_ptrace
|
||||
.long sys_alarm
|
||||
.long sys_fstat
|
||||
.long sys_pause
|
||||
.long sys_utime /* 30 */
|
||||
.long sys_ni_syscall /* old stty syscall holder */
|
||||
.long sys_ni_syscall /* old gtty syscall holder */
|
||||
.long sys_access
|
||||
.long sys_nice
|
||||
.long sys_ni_syscall /* 35 */ /* old ftime syscall holder */
|
||||
.long sys_sync
|
||||
.long sys_kill
|
||||
.long sys_rename
|
||||
.long sys_mkdir
|
||||
.long sys_rmdir /* 40 */
|
||||
.long sys_dup
|
||||
.long sys_pipe
|
||||
.long sys_times
|
||||
.long sys_ni_syscall /* old prof syscall holder */
|
||||
.long sys_brk /* 45 */
|
||||
.long sys_setgid16
|
||||
.long sys_getgid16
|
||||
.long sys_signal
|
||||
.long sys_geteuid16
|
||||
.long sys_getegid16 /* 50 */
|
||||
.long sys_acct
|
||||
.long sys_umount /* recycled never used phys() */
|
||||
.long sys_ni_syscall /* old lock syscall holder */
|
||||
.long sys_ioctl
|
||||
.long sys_fcntl /* 55 */
|
||||
.long sys_ni_syscall /* old mpx syscall holder */
|
||||
.long sys_setpgid
|
||||
.long sys_ni_syscall /* old ulimit syscall holder */
|
||||
.long sys_ni_syscall
|
||||
.long sys_umask /* 60 */
|
||||
.long sys_chroot
|
||||
.long sys_ustat
|
||||
.long sys_dup2
|
||||
.long sys_getppid
|
||||
.long sys_getpgrp /* 65 */
|
||||
.long sys_setsid
|
||||
.long sys_sigaction
|
||||
.long sys_sgetmask
|
||||
.long sys_ssetmask
|
||||
.long sys_setreuid16 /* 70 */
|
||||
.long sys_setregid16
|
||||
.long sys_sigsuspend
|
||||
.long sys_sigpending
|
||||
.long sys_sethostname
|
||||
.long sys_setrlimit /* 75 */
|
||||
.long sys_old_getrlimit
|
||||
.long sys_getrusage
|
||||
.long sys_gettimeofday
|
||||
.long sys_settimeofday
|
||||
.long sys_getgroups16 /* 80 */
|
||||
.long sys_setgroups16
|
||||
.long sys_old_select
|
||||
.long sys_symlink
|
||||
.long sys_lstat
|
||||
.long sys_readlink /* 85 */
|
||||
.long sys_uselib
|
||||
.long sys_swapon
|
||||
.long sys_reboot
|
||||
.long sys_old_readdir
|
||||
.long sys_old_mmap /* 90 */
|
||||
.long sys_munmap
|
||||
.long sys_truncate
|
||||
.long sys_ftruncate
|
||||
.long sys_fchmod
|
||||
.long sys_fchown16 /* 95 */
|
||||
.long sys_getpriority
|
||||
.long sys_setpriority
|
||||
.long sys_ni_syscall /* old profil syscall holder */
|
||||
.long sys_statfs
|
||||
.long sys_fstatfs /* 100 */
|
||||
.long sys_ni_syscall /* ioperm for i386 */
|
||||
.long sys_socketcall
|
||||
.long sys_syslog
|
||||
.long sys_setitimer
|
||||
.long sys_getitimer /* 105 */
|
||||
.long sys_newstat
|
||||
.long sys_newlstat
|
||||
.long sys_newfstat
|
||||
.long sys_ni_syscall
|
||||
.long sys_ni_syscall /* 110 */ /* iopl for i386 */
|
||||
.long sys_vhangup
|
||||
.long sys_ni_syscall /* obsolete idle() syscall */
|
||||
.long sys_ni_syscall /* vm86old for i386 */
|
||||
.long sys_wait4
|
||||
.long sys_swapoff /* 115 */
|
||||
.long sys_sysinfo
|
||||
.long sys_ipc
|
||||
.long sys_fsync
|
||||
.long sys_sigreturn
|
||||
.long sys_clone /* 120 */
|
||||
.long sys_setdomainname
|
||||
.long sys_newuname
|
||||
.long sys_cacheflush /* modify_ldt for i386 */
|
||||
.long sys_adjtimex
|
||||
.long sys_mprotect /* 125 */
|
||||
.long sys_sigprocmask
|
||||
.long sys_ni_syscall /* old "create_module" */
|
||||
.long sys_init_module
|
||||
.long sys_delete_module
|
||||
.long sys_ni_syscall /* 130 - old "get_kernel_syms" */
|
||||
.long sys_quotactl
|
||||
.long sys_getpgid
|
||||
.long sys_fchdir
|
||||
.long sys_bdflush
|
||||
.long sys_sysfs /* 135 */
|
||||
.long sys_personality
|
||||
.long sys_ni_syscall /* for afs_syscall */
|
||||
.long sys_setfsuid16
|
||||
.long sys_setfsgid16
|
||||
.long sys_llseek /* 140 */
|
||||
.long sys_getdents
|
||||
.long sys_select
|
||||
.long sys_flock
|
||||
.long sys_msync
|
||||
.long sys_readv /* 145 */
|
||||
.long sys_writev
|
||||
.long sys_getsid
|
||||
.long sys_fdatasync
|
||||
.long sys_sysctl
|
||||
.long sys_mlock /* 150 */
|
||||
.long sys_munlock
|
||||
.long sys_mlockall
|
||||
.long sys_munlockall
|
||||
.long sys_sched_setparam
|
||||
.long sys_sched_getparam /* 155 */
|
||||
.long sys_sched_setscheduler
|
||||
.long sys_sched_getscheduler
|
||||
.long sys_sched_yield
|
||||
.long sys_sched_get_priority_max
|
||||
.long sys_sched_get_priority_min /* 160 */
|
||||
.long sys_sched_rr_get_interval
|
||||
.long sys_nanosleep
|
||||
.long sys_mremap
|
||||
.long sys_setresuid16
|
||||
.long sys_getresuid16 /* 165 */
|
||||
.long sys_getpagesize
|
||||
.long sys_ni_syscall /* old sys_query_module */
|
||||
.long sys_poll
|
||||
.long sys_nfsservctl
|
||||
.long sys_setresgid16 /* 170 */
|
||||
.long sys_getresgid16
|
||||
.long sys_prctl
|
||||
.long sys_rt_sigreturn
|
||||
.long sys_rt_sigaction
|
||||
.long sys_rt_sigprocmask /* 175 */
|
||||
.long sys_rt_sigpending
|
||||
.long sys_rt_sigtimedwait
|
||||
.long sys_rt_sigqueueinfo
|
||||
.long sys_rt_sigsuspend
|
||||
.long sys_pread64 /* 180 */
|
||||
.long sys_pwrite64
|
||||
.long sys_lchown16;
|
||||
.long sys_getcwd
|
||||
.long sys_capget
|
||||
.long sys_capset /* 185 */
|
||||
.long sys_sigaltstack
|
||||
.long sys_sendfile
|
||||
.long sys_ni_syscall /* streams1 */
|
||||
.long sys_ni_syscall /* streams2 */
|
||||
.long sys_vfork /* 190 */
|
||||
.long sys_getrlimit
|
||||
.long sys_mmap2
|
||||
.long sys_truncate64
|
||||
.long sys_ftruncate64
|
||||
.long sys_stat64 /* 195 */
|
||||
.long sys_lstat64
|
||||
.long sys_fstat64
|
||||
.long sys_chown
|
||||
.long sys_getuid
|
||||
.long sys_getgid /* 200 */
|
||||
.long sys_geteuid
|
||||
.long sys_getegid
|
||||
.long sys_setreuid
|
||||
.long sys_setregid
|
||||
.long sys_getgroups /* 205 */
|
||||
.long sys_setgroups
|
||||
.long sys_fchown
|
||||
.long sys_setresuid
|
||||
.long sys_getresuid
|
||||
.long sys_setresgid /* 210 */
|
||||
.long sys_getresgid
|
||||
.long sys_lchown
|
||||
.long sys_setuid
|
||||
.long sys_setgid
|
||||
.long sys_setfsuid /* 215 */
|
||||
.long sys_setfsgid
|
||||
.long sys_pivot_root
|
||||
.long sys_ni_syscall
|
||||
.long sys_ni_syscall
|
||||
.long sys_getdents64 /* 220 */
|
||||
.long sys_gettid
|
||||
.long sys_tkill
|
||||
.long sys_setxattr
|
||||
.long sys_lsetxattr
|
||||
.long sys_fsetxattr /* 225 */
|
||||
.long sys_getxattr
|
||||
.long sys_lgetxattr
|
||||
.long sys_fgetxattr
|
||||
.long sys_listxattr
|
||||
.long sys_llistxattr /* 230 */
|
||||
.long sys_flistxattr
|
||||
.long sys_removexattr
|
||||
.long sys_lremovexattr
|
||||
.long sys_fremovexattr
|
||||
.long sys_futex /* 235 */
|
||||
.long sys_sendfile64
|
||||
.long sys_mincore
|
||||
.long sys_madvise
|
||||
.long sys_fcntl64
|
||||
.long sys_readahead /* 240 */
|
||||
.long sys_io_setup
|
||||
.long sys_io_destroy
|
||||
.long sys_io_getevents
|
||||
.long sys_io_submit
|
||||
.long sys_io_cancel /* 245 */
|
||||
.long sys_fadvise64
|
||||
.long sys_exit_group
|
||||
.long sys_lookup_dcookie
|
||||
.long sys_epoll_create
|
||||
.long sys_epoll_ctl /* 250 */
|
||||
.long sys_epoll_wait
|
||||
.long sys_remap_file_pages
|
||||
.long sys_set_tid_address
|
||||
.long sys_timer_create
|
||||
.long sys_timer_settime /* 255 */
|
||||
.long sys_timer_gettime
|
||||
.long sys_timer_getoverrun
|
||||
.long sys_timer_delete
|
||||
.long sys_clock_settime
|
||||
.long sys_clock_gettime /* 260 */
|
||||
.long sys_clock_getres
|
||||
.long sys_clock_nanosleep
|
||||
.long sys_statfs64
|
||||
.long sys_fstatfs64
|
||||
.long sys_tgkill /* 265 */
|
||||
.long sys_utimes
|
||||
.long sys_fadvise64_64
|
||||
.long sys_mbind
|
||||
.long sys_get_mempolicy
|
||||
.long sys_set_mempolicy /* 270 */
|
||||
.long sys_mq_open
|
||||
.long sys_mq_unlink
|
||||
.long sys_mq_timedsend
|
||||
.long sys_mq_timedreceive
|
||||
.long sys_mq_notify /* 275 */
|
||||
.long sys_mq_getsetattr
|
||||
.long sys_waitid
|
||||
.long sys_ni_syscall /* for sys_vserver */
|
||||
.long sys_add_key
|
||||
.long sys_request_key /* 280 */
|
||||
.long sys_keyctl
|
||||
.long sys_ioprio_set
|
||||
.long sys_ioprio_get
|
||||
.long sys_inotify_init
|
||||
.long sys_inotify_add_watch /* 285 */
|
||||
.long sys_inotify_rm_watch
|
||||
.long sys_migrate_pages
|
||||
.long sys_openat
|
||||
.long sys_mkdirat
|
||||
.long sys_mknodat /* 290 */
|
||||
.long sys_fchownat
|
||||
.long sys_futimesat
|
||||
.long sys_fstatat64
|
||||
.long sys_unlinkat
|
||||
.long sys_renameat /* 295 */
|
||||
.long sys_linkat
|
||||
.long sys_symlinkat
|
||||
.long sys_readlinkat
|
||||
.long sys_fchmodat
|
||||
.long sys_faccessat /* 300 */
|
||||
.long sys_ni_syscall /* Reserved for pselect6 */
|
||||
.long sys_ni_syscall /* Reserved for ppoll */
|
||||
.long sys_unshare
|
||||
.long sys_set_robust_list
|
||||
.long sys_get_robust_list /* 305 */
|
||||
.long sys_splice
|
||||
.long sys_sync_file_range
|
||||
.long sys_tee
|
||||
.long sys_vmsplice
|
||||
.long sys_move_pages /* 310 */
|
||||
.long sys_sched_setaffinity
|
||||
.long sys_sched_getaffinity
|
||||
.long sys_kexec_load
|
||||
.long sys_getcpu
|
||||
.long sys_epoll_pwait /* 315 */
|
||||
.long sys_utimensat
|
||||
.long sys_signalfd
|
||||
.long sys_timerfd_create
|
||||
.long sys_eventfd
|
||||
.long sys_fallocate /* 320 */
|
||||
.long sys_timerfd_settime
|
||||
.long sys_timerfd_gettime
|
||||
.long sys_signalfd4
|
||||
.long sys_eventfd2
|
||||
.long sys_epoll_create1 /* 325 */
|
||||
.long sys_dup3
|
||||
.long sys_pipe2
|
||||
.long sys_inotify_init1
|
||||
.long sys_preadv
|
||||
.long sys_pwritev /* 330 */
|
||||
.long sys_rt_tgsigqueueinfo
|
||||
.long sys_perf_event_open
|
||||
.long sys_get_thread_area
|
||||
.long sys_set_thread_area
|
||||
.long sys_atomic_cmpxchg_32 /* 335 */
|
||||
.long sys_atomic_barrier
|
||||
.long sys_fanotify_init
|
||||
.long sys_fanotify_mark
|
||||
.long sys_prlimit64
|
||||
|
||||
|
753
arch/m68k/kernel/entry_mm.S
Normal file
753
arch/m68k/kernel/entry_mm.S
Normal file
@ -0,0 +1,753 @@
|
||||
/* -*- mode: asm -*-
|
||||
*
|
||||
* linux/arch/m68k/kernel/entry.S
|
||||
*
|
||||
* Copyright (C) 1991, 1992 Linus Torvalds
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU General Public
|
||||
* License. See the file README.legal in the main directory of this archive
|
||||
* for more details.
|
||||
*
|
||||
* Linux/m68k support by Hamish Macdonald
|
||||
*
|
||||
* 68060 fixes by Jesper Skov
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* entry.S contains the system-call and fault low-level handling routines.
|
||||
* This also contains the timer-interrupt handler, as well as all interrupts
|
||||
* and faults that can result in a task-switch.
|
||||
*
|
||||
* NOTE: This code handles signal-recognition, which happens every time
|
||||
* after a timer-interrupt and after each system call.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* 12/03/96 Jes: Currently we only support m68k single-cpu systems, so
|
||||
* all pointers that used to be 'current' are now entry
|
||||
* number 0 in the 'current_set' list.
|
||||
*
|
||||
* 6/05/00 RZ: addedd writeback completion after return from sighandler
|
||||
* for 68040
|
||||
*/
|
||||
|
||||
#include <linux/linkage.h>
|
||||
#include <asm/entry.h>
|
||||
#include <asm/errno.h>
|
||||
#include <asm/setup.h>
|
||||
#include <asm/segment.h>
|
||||
#include <asm/traps.h>
|
||||
#include <asm/unistd.h>
|
||||
|
||||
#include <asm/asm-offsets.h>
|
||||
|
||||
.globl system_call, buserr, trap, resume
|
||||
.globl sys_call_table
|
||||
.globl sys_fork, sys_clone, sys_vfork
|
||||
.globl ret_from_interrupt, bad_interrupt
|
||||
.globl auto_irqhandler_fixup
|
||||
.globl user_irqvec_fixup, user_irqhandler_fixup
|
||||
|
||||
.text
|
||||
ENTRY(buserr)
|
||||
SAVE_ALL_INT
|
||||
GET_CURRENT(%d0)
|
||||
movel %sp,%sp@- | stack frame pointer argument
|
||||
bsrl buserr_c
|
||||
addql #4,%sp
|
||||
jra .Lret_from_exception
|
||||
|
||||
ENTRY(trap)
|
||||
SAVE_ALL_INT
|
||||
GET_CURRENT(%d0)
|
||||
movel %sp,%sp@- | stack frame pointer argument
|
||||
bsrl trap_c
|
||||
addql #4,%sp
|
||||
jra .Lret_from_exception
|
||||
|
||||
| After a fork we jump here directly from resume,
|
||||
| so that %d1 contains the previous task
|
||||
| schedule_tail now used regardless of CONFIG_SMP
|
||||
ENTRY(ret_from_fork)
|
||||
movel %d1,%sp@-
|
||||
jsr schedule_tail
|
||||
addql #4,%sp
|
||||
jra .Lret_from_exception
|
||||
|
||||
do_trace_entry:
|
||||
movel #-ENOSYS,%sp@(PT_OFF_D0)| needed for strace
|
||||
subql #4,%sp
|
||||
SAVE_SWITCH_STACK
|
||||
jbsr syscall_trace
|
||||
RESTORE_SWITCH_STACK
|
||||
addql #4,%sp
|
||||
movel %sp@(PT_OFF_ORIG_D0),%d0
|
||||
cmpl #NR_syscalls,%d0
|
||||
jcs syscall
|
||||
badsys:
|
||||
movel #-ENOSYS,%sp@(PT_OFF_D0)
|
||||
jra ret_from_syscall
|
||||
|
||||
do_trace_exit:
|
||||
subql #4,%sp
|
||||
SAVE_SWITCH_STACK
|
||||
jbsr syscall_trace
|
||||
RESTORE_SWITCH_STACK
|
||||
addql #4,%sp
|
||||
jra .Lret_from_exception
|
||||
|
||||
ENTRY(ret_from_signal)
|
||||
tstb %curptr@(TASK_INFO+TINFO_FLAGS+2)
|
||||
jge 1f
|
||||
jbsr syscall_trace
|
||||
1: RESTORE_SWITCH_STACK
|
||||
addql #4,%sp
|
||||
/* on 68040 complete pending writebacks if any */
|
||||
#ifdef CONFIG_M68040
|
||||
bfextu %sp@(PT_OFF_FORMATVEC){#0,#4},%d0
|
||||
subql #7,%d0 | bus error frame ?
|
||||
jbne 1f
|
||||
movel %sp,%sp@-
|
||||
jbsr berr_040cleanup
|
||||
addql #4,%sp
|
||||
1:
|
||||
#endif
|
||||
jra .Lret_from_exception
|
||||
|
||||
ENTRY(system_call)
|
||||
SAVE_ALL_SYS
|
||||
|
||||
GET_CURRENT(%d1)
|
||||
| save top of frame
|
||||
movel %sp,%curptr@(TASK_THREAD+THREAD_ESP0)
|
||||
|
||||
| syscall trace?
|
||||
tstb %curptr@(TASK_INFO+TINFO_FLAGS+2)
|
||||
jmi do_trace_entry
|
||||
cmpl #NR_syscalls,%d0
|
||||
jcc badsys
|
||||
syscall:
|
||||
jbsr @(sys_call_table,%d0:l:4)@(0)
|
||||
movel %d0,%sp@(PT_OFF_D0) | save the return value
|
||||
ret_from_syscall:
|
||||
|oriw #0x0700,%sr
|
||||
movew %curptr@(TASK_INFO+TINFO_FLAGS+2),%d0
|
||||
jne syscall_exit_work
|
||||
1: RESTORE_ALL
|
||||
|
||||
syscall_exit_work:
|
||||
btst #5,%sp@(PT_OFF_SR) | check if returning to kernel
|
||||
bnes 1b | if so, skip resched, signals
|
||||
lslw #1,%d0
|
||||
jcs do_trace_exit
|
||||
jmi do_delayed_trace
|
||||
lslw #8,%d0
|
||||
jmi do_signal_return
|
||||
pea resume_userspace
|
||||
jra schedule
|
||||
|
||||
|
||||
ENTRY(ret_from_exception)
|
||||
.Lret_from_exception:
|
||||
btst #5,%sp@(PT_OFF_SR) | check if returning to kernel
|
||||
bnes 1f | if so, skip resched, signals
|
||||
| only allow interrupts when we are really the last one on the
|
||||
| kernel stack, otherwise stack overflow can occur during
|
||||
| heavy interrupt load
|
||||
andw #ALLOWINT,%sr
|
||||
|
||||
resume_userspace:
|
||||
moveb %curptr@(TASK_INFO+TINFO_FLAGS+3),%d0
|
||||
jne exit_work
|
||||
1: RESTORE_ALL
|
||||
|
||||
exit_work:
|
||||
| save top of frame
|
||||
movel %sp,%curptr@(TASK_THREAD+THREAD_ESP0)
|
||||
lslb #1,%d0
|
||||
jmi do_signal_return
|
||||
pea resume_userspace
|
||||
jra schedule
|
||||
|
||||
|
||||
do_signal_return:
|
||||
|andw #ALLOWINT,%sr
|
||||
subql #4,%sp | dummy return address
|
||||
SAVE_SWITCH_STACK
|
||||
pea %sp@(SWITCH_STACK_SIZE)
|
||||
bsrl do_signal
|
||||
addql #4,%sp
|
||||
RESTORE_SWITCH_STACK
|
||||
addql #4,%sp
|
||||
jbra resume_userspace
|
||||
|
||||
do_delayed_trace:
|
||||
bclr #7,%sp@(PT_OFF_SR) | clear trace bit in SR
|
||||
pea 1 | send SIGTRAP
|
||||
movel %curptr,%sp@-
|
||||
pea LSIGTRAP
|
||||
jbsr send_sig
|
||||
addql #8,%sp
|
||||
addql #4,%sp
|
||||
jbra resume_userspace
|
||||
|
||||
|
||||
/* This is the main interrupt handler for autovector interrupts */
|
||||
|
||||
ENTRY(auto_inthandler)
|
||||
SAVE_ALL_INT
|
||||
GET_CURRENT(%d0)
|
||||
addqb #1,%curptr@(TASK_INFO+TINFO_PREEMPT+1)
|
||||
| put exception # in d0
|
||||
bfextu %sp@(PT_OFF_FORMATVEC){#4,#10},%d0
|
||||
subw #VEC_SPUR,%d0
|
||||
|
||||
movel %sp,%sp@-
|
||||
movel %d0,%sp@- | put vector # on stack
|
||||
auto_irqhandler_fixup = . + 2
|
||||
jsr __m68k_handle_int | process the IRQ
|
||||
addql #8,%sp | pop parameters off stack
|
||||
|
||||
ret_from_interrupt:
|
||||
subqb #1,%curptr@(TASK_INFO+TINFO_PREEMPT+1)
|
||||
jeq ret_from_last_interrupt
|
||||
2: RESTORE_ALL
|
||||
|
||||
ALIGN
|
||||
ret_from_last_interrupt:
|
||||
moveq #(~ALLOWINT>>8)&0xff,%d0
|
||||
andb %sp@(PT_OFF_SR),%d0
|
||||
jne 2b
|
||||
|
||||
/* check if we need to do software interrupts */
|
||||
tstl irq_stat+CPUSTAT_SOFTIRQ_PENDING
|
||||
jeq .Lret_from_exception
|
||||
pea ret_from_exception
|
||||
jra do_softirq
|
||||
|
||||
/* Handler for user defined interrupt vectors */
|
||||
|
||||
ENTRY(user_inthandler)
|
||||
SAVE_ALL_INT
|
||||
GET_CURRENT(%d0)
|
||||
addqb #1,%curptr@(TASK_INFO+TINFO_PREEMPT+1)
|
||||
| put exception # in d0
|
||||
bfextu %sp@(PT_OFF_FORMATVEC){#4,#10},%d0
|
||||
user_irqvec_fixup = . + 2
|
||||
subw #VEC_USER,%d0
|
||||
|
||||
movel %sp,%sp@-
|
||||
movel %d0,%sp@- | put vector # on stack
|
||||
user_irqhandler_fixup = . + 2
|
||||
jsr __m68k_handle_int | process the IRQ
|
||||
addql #8,%sp | pop parameters off stack
|
||||
|
||||
subqb #1,%curptr@(TASK_INFO+TINFO_PREEMPT+1)
|
||||
jeq ret_from_last_interrupt
|
||||
RESTORE_ALL
|
||||
|
||||
/* Handler for uninitialized and spurious interrupts */
|
||||
|
||||
ENTRY(bad_inthandler)
|
||||
SAVE_ALL_INT
|
||||
GET_CURRENT(%d0)
|
||||
addqb #1,%curptr@(TASK_INFO+TINFO_PREEMPT+1)
|
||||
|
||||
movel %sp,%sp@-
|
||||
jsr handle_badint
|
||||
addql #4,%sp
|
||||
|
||||
subqb #1,%curptr@(TASK_INFO+TINFO_PREEMPT+1)
|
||||
jeq ret_from_last_interrupt
|
||||
RESTORE_ALL
|
||||
|
||||
|
||||
ENTRY(sys_fork)
|
||||
SAVE_SWITCH_STACK
|
||||
pea %sp@(SWITCH_STACK_SIZE)
|
||||
jbsr m68k_fork
|
||||
addql #4,%sp
|
||||
RESTORE_SWITCH_STACK
|
||||
rts
|
||||
|
||||
ENTRY(sys_clone)
|
||||
SAVE_SWITCH_STACK
|
||||
pea %sp@(SWITCH_STACK_SIZE)
|
||||
jbsr m68k_clone
|
||||
addql #4,%sp
|
||||
RESTORE_SWITCH_STACK
|
||||
rts
|
||||
|
||||
ENTRY(sys_vfork)
|
||||
SAVE_SWITCH_STACK
|
||||
pea %sp@(SWITCH_STACK_SIZE)
|
||||
jbsr m68k_vfork
|
||||
addql #4,%sp
|
||||
RESTORE_SWITCH_STACK
|
||||
rts
|
||||
|
||||
ENTRY(sys_sigreturn)
|
||||
SAVE_SWITCH_STACK
|
||||
jbsr do_sigreturn
|
||||
RESTORE_SWITCH_STACK
|
||||
rts
|
||||
|
||||
ENTRY(sys_rt_sigreturn)
|
||||
SAVE_SWITCH_STACK
|
||||
jbsr do_rt_sigreturn
|
||||
RESTORE_SWITCH_STACK
|
||||
rts
|
||||
|
||||
resume:
|
||||
/*
|
||||
* Beware - when entering resume, prev (the current task) is
|
||||
* in a0, next (the new task) is in a1,so don't change these
|
||||
* registers until their contents are no longer needed.
|
||||
*/
|
||||
|
||||
/* save sr */
|
||||
movew %sr,%a0@(TASK_THREAD+THREAD_SR)
|
||||
|
||||
/* save fs (sfc,%dfc) (may be pointing to kernel memory) */
|
||||
movec %sfc,%d0
|
||||
movew %d0,%a0@(TASK_THREAD+THREAD_FS)
|
||||
|
||||
/* save usp */
|
||||
/* it is better to use a movel here instead of a movew 8*) */
|
||||
movec %usp,%d0
|
||||
movel %d0,%a0@(TASK_THREAD+THREAD_USP)
|
||||
|
||||
/* save non-scratch registers on stack */
|
||||
SAVE_SWITCH_STACK
|
||||
|
||||
/* save current kernel stack pointer */
|
||||
movel %sp,%a0@(TASK_THREAD+THREAD_KSP)
|
||||
|
||||
/* save floating point context */
|
||||
#ifndef CONFIG_M68KFPU_EMU_ONLY
|
||||
#ifdef CONFIG_M68KFPU_EMU
|
||||
tstl m68k_fputype
|
||||
jeq 3f
|
||||
#endif
|
||||
fsave %a0@(TASK_THREAD+THREAD_FPSTATE)
|
||||
|
||||
#if defined(CONFIG_M68060)
|
||||
#if !defined(CPU_M68060_ONLY)
|
||||
btst #3,m68k_cputype+3
|
||||
beqs 1f
|
||||
#endif
|
||||
/* The 060 FPU keeps status in bits 15-8 of the first longword */
|
||||
tstb %a0@(TASK_THREAD+THREAD_FPSTATE+2)
|
||||
jeq 3f
|
||||
#if !defined(CPU_M68060_ONLY)
|
||||
jra 2f
|
||||
#endif
|
||||
#endif /* CONFIG_M68060 */
|
||||
#if !defined(CPU_M68060_ONLY)
|
||||
1: tstb %a0@(TASK_THREAD+THREAD_FPSTATE)
|
||||
jeq 3f
|
||||
#endif
|
||||
2: fmovemx %fp0-%fp7,%a0@(TASK_THREAD+THREAD_FPREG)
|
||||
fmoveml %fpcr/%fpsr/%fpiar,%a0@(TASK_THREAD+THREAD_FPCNTL)
|
||||
3:
|
||||
#endif /* CONFIG_M68KFPU_EMU_ONLY */
|
||||
/* Return previous task in %d1 */
|
||||
movel %curptr,%d1
|
||||
|
||||
/* switch to new task (a1 contains new task) */
|
||||
movel %a1,%curptr
|
||||
|
||||
/* restore floating point context */
|
||||
#ifndef CONFIG_M68KFPU_EMU_ONLY
|
||||
#ifdef CONFIG_M68KFPU_EMU
|
||||
tstl m68k_fputype
|
||||
jeq 4f
|
||||
#endif
|
||||
#if defined(CONFIG_M68060)
|
||||
#if !defined(CPU_M68060_ONLY)
|
||||
btst #3,m68k_cputype+3
|
||||
beqs 1f
|
||||
#endif
|
||||
/* The 060 FPU keeps status in bits 15-8 of the first longword */
|
||||
tstb %a1@(TASK_THREAD+THREAD_FPSTATE+2)
|
||||
jeq 3f
|
||||
#if !defined(CPU_M68060_ONLY)
|
||||
jra 2f
|
||||
#endif
|
||||
#endif /* CONFIG_M68060 */
|
||||
#if !defined(CPU_M68060_ONLY)
|
||||
1: tstb %a1@(TASK_THREAD+THREAD_FPSTATE)
|
||||
jeq 3f
|
||||
#endif
|
||||
2: fmovemx %a1@(TASK_THREAD+THREAD_FPREG),%fp0-%fp7
|
||||
fmoveml %a1@(TASK_THREAD+THREAD_FPCNTL),%fpcr/%fpsr/%fpiar
|
||||
3: frestore %a1@(TASK_THREAD+THREAD_FPSTATE)
|
||||
4:
|
||||
#endif /* CONFIG_M68KFPU_EMU_ONLY */
|
||||
|
||||
/* restore the kernel stack pointer */
|
||||
movel %a1@(TASK_THREAD+THREAD_KSP),%sp
|
||||
|
||||
/* restore non-scratch registers */
|
||||
RESTORE_SWITCH_STACK
|
||||
|
||||
/* restore user stack pointer */
|
||||
movel %a1@(TASK_THREAD+THREAD_USP),%a0
|
||||
movel %a0,%usp
|
||||
|
||||
/* restore fs (sfc,%dfc) */
|
||||
movew %a1@(TASK_THREAD+THREAD_FS),%a0
|
||||
movec %a0,%sfc
|
||||
movec %a0,%dfc
|
||||
|
||||
/* restore status register */
|
||||
movew %a1@(TASK_THREAD+THREAD_SR),%sr
|
||||
|
||||
rts
|
||||
|
||||
.data
|
||||
ALIGN
|
||||
sys_call_table:
|
||||
.long sys_restart_syscall /* 0 - old "setup()" system call, used for restarting */
|
||||
.long sys_exit
|
||||
.long sys_fork
|
||||
.long sys_read
|
||||
.long sys_write
|
||||
.long sys_open /* 5 */
|
||||
.long sys_close
|
||||
.long sys_waitpid
|
||||
.long sys_creat
|
||||
.long sys_link
|
||||
.long sys_unlink /* 10 */
|
||||
.long sys_execve
|
||||
.long sys_chdir
|
||||
.long sys_time
|
||||
.long sys_mknod
|
||||
.long sys_chmod /* 15 */
|
||||
.long sys_chown16
|
||||
.long sys_ni_syscall /* old break syscall holder */
|
||||
.long sys_stat
|
||||
.long sys_lseek
|
||||
.long sys_getpid /* 20 */
|
||||
.long sys_mount
|
||||
.long sys_oldumount
|
||||
.long sys_setuid16
|
||||
.long sys_getuid16
|
||||
.long sys_stime /* 25 */
|
||||
.long sys_ptrace
|
||||
.long sys_alarm
|
||||
.long sys_fstat
|
||||
.long sys_pause
|
||||
.long sys_utime /* 30 */
|
||||
.long sys_ni_syscall /* old stty syscall holder */
|
||||
.long sys_ni_syscall /* old gtty syscall holder */
|
||||
.long sys_access
|
||||
.long sys_nice
|
||||
.long sys_ni_syscall /* 35 */ /* old ftime syscall holder */
|
||||
.long sys_sync
|
||||
.long sys_kill
|
||||
.long sys_rename
|
||||
.long sys_mkdir
|
||||
.long sys_rmdir /* 40 */
|
||||
.long sys_dup
|
||||
.long sys_pipe
|
||||
.long sys_times
|
||||
.long sys_ni_syscall /* old prof syscall holder */
|
||||
.long sys_brk /* 45 */
|
||||
.long sys_setgid16
|
||||
.long sys_getgid16
|
||||
.long sys_signal
|
||||
.long sys_geteuid16
|
||||
.long sys_getegid16 /* 50 */
|
||||
.long sys_acct
|
||||
.long sys_umount /* recycled never used phys() */
|
||||
.long sys_ni_syscall /* old lock syscall holder */
|
||||
.long sys_ioctl
|
||||
.long sys_fcntl /* 55 */
|
||||
.long sys_ni_syscall /* old mpx syscall holder */
|
||||
.long sys_setpgid
|
||||
.long sys_ni_syscall /* old ulimit syscall holder */
|
||||
.long sys_ni_syscall
|
||||
.long sys_umask /* 60 */
|
||||
.long sys_chroot
|
||||
.long sys_ustat
|
||||
.long sys_dup2
|
||||
.long sys_getppid
|
||||
.long sys_getpgrp /* 65 */
|
||||
.long sys_setsid
|
||||
.long sys_sigaction
|
||||
.long sys_sgetmask
|
||||
.long sys_ssetmask
|
||||
.long sys_setreuid16 /* 70 */
|
||||
.long sys_setregid16
|
||||
.long sys_sigsuspend
|
||||
.long sys_sigpending
|
||||
.long sys_sethostname
|
||||
.long sys_setrlimit /* 75 */
|
||||
.long sys_old_getrlimit
|
||||
.long sys_getrusage
|
||||
.long sys_gettimeofday
|
||||
.long sys_settimeofday
|
||||
.long sys_getgroups16 /* 80 */
|
||||
.long sys_setgroups16
|
||||
.long sys_old_select
|
||||
.long sys_symlink
|
||||
.long sys_lstat
|
||||
.long sys_readlink /* 85 */
|
||||
.long sys_uselib
|
||||
.long sys_swapon
|
||||
.long sys_reboot
|
||||
.long sys_old_readdir
|
||||
.long sys_old_mmap /* 90 */
|
||||
.long sys_munmap
|
||||
.long sys_truncate
|
||||
.long sys_ftruncate
|
||||
.long sys_fchmod
|
||||
.long sys_fchown16 /* 95 */
|
||||
.long sys_getpriority
|
||||
.long sys_setpriority
|
||||
.long sys_ni_syscall /* old profil syscall holder */
|
||||
.long sys_statfs
|
||||
.long sys_fstatfs /* 100 */
|
||||
.long sys_ni_syscall /* ioperm for i386 */
|
||||
.long sys_socketcall
|
||||
.long sys_syslog
|
||||
.long sys_setitimer
|
||||
.long sys_getitimer /* 105 */
|
||||
.long sys_newstat
|
||||
.long sys_newlstat
|
||||
.long sys_newfstat
|
||||
.long sys_ni_syscall
|
||||
.long sys_ni_syscall /* 110 */ /* iopl for i386 */
|
||||
.long sys_vhangup
|
||||
.long sys_ni_syscall /* obsolete idle() syscall */
|
||||
.long sys_ni_syscall /* vm86old for i386 */
|
||||
.long sys_wait4
|
||||
.long sys_swapoff /* 115 */
|
||||
.long sys_sysinfo
|
||||
.long sys_ipc
|
||||
.long sys_fsync
|
||||
.long sys_sigreturn
|
||||
.long sys_clone /* 120 */
|
||||
.long sys_setdomainname
|
||||
.long sys_newuname
|
||||
.long sys_cacheflush /* modify_ldt for i386 */
|
||||
.long sys_adjtimex
|
||||
.long sys_mprotect /* 125 */
|
||||
.long sys_sigprocmask
|
||||
.long sys_ni_syscall /* old "create_module" */
|
||||
.long sys_init_module
|
||||
.long sys_delete_module
|
||||
.long sys_ni_syscall /* 130 - old "get_kernel_syms" */
|
||||
.long sys_quotactl
|
||||
.long sys_getpgid
|
||||
.long sys_fchdir
|
||||
.long sys_bdflush
|
||||
.long sys_sysfs /* 135 */
|
||||
.long sys_personality
|
||||
.long sys_ni_syscall /* for afs_syscall */
|
||||
.long sys_setfsuid16
|
||||
.long sys_setfsgid16
|
||||
.long sys_llseek /* 140 */
|
||||
.long sys_getdents
|
||||
.long sys_select
|
||||
.long sys_flock
|
||||
.long sys_msync
|
||||
.long sys_readv /* 145 */
|
||||
.long sys_writev
|
||||
.long sys_getsid
|
||||
.long sys_fdatasync
|
||||
.long sys_sysctl
|
||||
.long sys_mlock /* 150 */
|
||||
.long sys_munlock
|
||||
.long sys_mlockall
|
||||
.long sys_munlockall
|
||||
.long sys_sched_setparam
|
||||
.long sys_sched_getparam /* 155 */
|
||||
.long sys_sched_setscheduler
|
||||
.long sys_sched_getscheduler
|
||||
.long sys_sched_yield
|
||||
.long sys_sched_get_priority_max
|
||||
.long sys_sched_get_priority_min /* 160 */
|
||||
.long sys_sched_rr_get_interval
|
||||
.long sys_nanosleep
|
||||
.long sys_mremap
|
||||
.long sys_setresuid16
|
||||
.long sys_getresuid16 /* 165 */
|
||||
.long sys_getpagesize
|
||||
.long sys_ni_syscall /* old sys_query_module */
|
||||
.long sys_poll
|
||||
.long sys_nfsservctl
|
||||
.long sys_setresgid16 /* 170 */
|
||||
.long sys_getresgid16
|
||||
.long sys_prctl
|
||||
.long sys_rt_sigreturn
|
||||
.long sys_rt_sigaction
|
||||
.long sys_rt_sigprocmask /* 175 */
|
||||
.long sys_rt_sigpending
|
||||
.long sys_rt_sigtimedwait
|
||||
.long sys_rt_sigqueueinfo
|
||||
.long sys_rt_sigsuspend
|
||||
.long sys_pread64 /* 180 */
|
||||
.long sys_pwrite64
|
||||
.long sys_lchown16;
|
||||
.long sys_getcwd
|
||||
.long sys_capget
|
||||
.long sys_capset /* 185 */
|
||||
.long sys_sigaltstack
|
||||
.long sys_sendfile
|
||||
.long sys_ni_syscall /* streams1 */
|
||||
.long sys_ni_syscall /* streams2 */
|
||||
.long sys_vfork /* 190 */
|
||||
.long sys_getrlimit
|
||||
.long sys_mmap2
|
||||
.long sys_truncate64
|
||||
.long sys_ftruncate64
|
||||
.long sys_stat64 /* 195 */
|
||||
.long sys_lstat64
|
||||
.long sys_fstat64
|
||||
.long sys_chown
|
||||
.long sys_getuid
|
||||
.long sys_getgid /* 200 */
|
||||
.long sys_geteuid
|
||||
.long sys_getegid
|
||||
.long sys_setreuid
|
||||
.long sys_setregid
|
||||
.long sys_getgroups /* 205 */
|
||||
.long sys_setgroups
|
||||
.long sys_fchown
|
||||
.long sys_setresuid
|
||||
.long sys_getresuid
|
||||
.long sys_setresgid /* 210 */
|
||||
.long sys_getresgid
|
||||
.long sys_lchown
|
||||
.long sys_setuid
|
||||
.long sys_setgid
|
||||
.long sys_setfsuid /* 215 */
|
||||
.long sys_setfsgid
|
||||
.long sys_pivot_root
|
||||
.long sys_ni_syscall
|
||||
.long sys_ni_syscall
|
||||
.long sys_getdents64 /* 220 */
|
||||
.long sys_gettid
|
||||
.long sys_tkill
|
||||
.long sys_setxattr
|
||||
.long sys_lsetxattr
|
||||
.long sys_fsetxattr /* 225 */
|
||||
.long sys_getxattr
|
||||
.long sys_lgetxattr
|
||||
.long sys_fgetxattr
|
||||
.long sys_listxattr
|
||||
.long sys_llistxattr /* 230 */
|
||||
.long sys_flistxattr
|
||||
.long sys_removexattr
|
||||
.long sys_lremovexattr
|
||||
.long sys_fremovexattr
|
||||
.long sys_futex /* 235 */
|
||||
.long sys_sendfile64
|
||||
.long sys_mincore
|
||||
.long sys_madvise
|
||||
.long sys_fcntl64
|
||||
.long sys_readahead /* 240 */
|
||||
.long sys_io_setup
|
||||
.long sys_io_destroy
|
||||
.long sys_io_getevents
|
||||
.long sys_io_submit
|
||||
.long sys_io_cancel /* 245 */
|
||||
.long sys_fadvise64
|
||||
.long sys_exit_group
|
||||
.long sys_lookup_dcookie
|
||||
.long sys_epoll_create
|
||||
.long sys_epoll_ctl /* 250 */
|
||||
.long sys_epoll_wait
|
||||
.long sys_remap_file_pages
|
||||
.long sys_set_tid_address
|
||||
.long sys_timer_create
|
||||
.long sys_timer_settime /* 255 */
|
||||
.long sys_timer_gettime
|
||||
.long sys_timer_getoverrun
|
||||
.long sys_timer_delete
|
||||
.long sys_clock_settime
|
||||
.long sys_clock_gettime /* 260 */
|
||||
.long sys_clock_getres
|
||||
.long sys_clock_nanosleep
|
||||
.long sys_statfs64
|
||||
.long sys_fstatfs64
|
||||
.long sys_tgkill /* 265 */
|
||||
.long sys_utimes
|
||||
.long sys_fadvise64_64
|
||||
.long sys_mbind
|
||||
.long sys_get_mempolicy
|
||||
.long sys_set_mempolicy /* 270 */
|
||||
.long sys_mq_open
|
||||
.long sys_mq_unlink
|
||||
.long sys_mq_timedsend
|
||||
.long sys_mq_timedreceive
|
||||
.long sys_mq_notify /* 275 */
|
||||
.long sys_mq_getsetattr
|
||||
.long sys_waitid
|
||||
.long sys_ni_syscall /* for sys_vserver */
|
||||
.long sys_add_key
|
||||
.long sys_request_key /* 280 */
|
||||
.long sys_keyctl
|
||||
.long sys_ioprio_set
|
||||
.long sys_ioprio_get
|
||||
.long sys_inotify_init
|
||||
.long sys_inotify_add_watch /* 285 */
|
||||
.long sys_inotify_rm_watch
|
||||
.long sys_migrate_pages
|
||||
.long sys_openat
|
||||
.long sys_mkdirat
|
||||
.long sys_mknodat /* 290 */
|
||||
.long sys_fchownat
|
||||
.long sys_futimesat
|
||||
.long sys_fstatat64
|
||||
.long sys_unlinkat
|
||||
.long sys_renameat /* 295 */
|
||||
.long sys_linkat
|
||||
.long sys_symlinkat
|
||||
.long sys_readlinkat
|
||||
.long sys_fchmodat
|
||||
.long sys_faccessat /* 300 */
|
||||
.long sys_ni_syscall /* Reserved for pselect6 */
|
||||
.long sys_ni_syscall /* Reserved for ppoll */
|
||||
.long sys_unshare
|
||||
.long sys_set_robust_list
|
||||
.long sys_get_robust_list /* 305 */
|
||||
.long sys_splice
|
||||
.long sys_sync_file_range
|
||||
.long sys_tee
|
||||
.long sys_vmsplice
|
||||
.long sys_move_pages /* 310 */
|
||||
.long sys_sched_setaffinity
|
||||
.long sys_sched_getaffinity
|
||||
.long sys_kexec_load
|
||||
.long sys_getcpu
|
||||
.long sys_epoll_pwait /* 315 */
|
||||
.long sys_utimensat
|
||||
.long sys_signalfd
|
||||
.long sys_timerfd_create
|
||||
.long sys_eventfd
|
||||
.long sys_fallocate /* 320 */
|
||||
.long sys_timerfd_settime
|
||||
.long sys_timerfd_gettime
|
||||
.long sys_signalfd4
|
||||
.long sys_eventfd2
|
||||
.long sys_epoll_create1 /* 325 */
|
||||
.long sys_dup3
|
||||
.long sys_pipe2
|
||||
.long sys_inotify_init1
|
||||
.long sys_preadv
|
||||
.long sys_pwritev /* 330 */
|
||||
.long sys_rt_tgsigqueueinfo
|
||||
.long sys_perf_event_open
|
||||
.long sys_get_thread_area
|
||||
.long sys_set_thread_area
|
||||
.long sys_atomic_cmpxchg_32 /* 335 */
|
||||
.long sys_atomic_barrier
|
||||
.long sys_fanotify_init
|
||||
.long sys_fanotify_mark
|
||||
.long sys_prlimit64
|
||||
|
@ -1,16 +1,5 @@
|
||||
#include <linux/module.h>
|
||||
|
||||
asmlinkage long long __ashldi3 (long long, int);
|
||||
asmlinkage long long __ashrdi3 (long long, int);
|
||||
asmlinkage long long __lshrdi3 (long long, int);
|
||||
asmlinkage long long __muldi3 (long long, long long);
|
||||
|
||||
/* The following are special because they're not called
|
||||
explicitly (the C compiler generates them). Fortunately,
|
||||
their interface isn't gonna change any time soon now, so
|
||||
it's OK to leave it out of version control. */
|
||||
EXPORT_SYMBOL(__ashldi3);
|
||||
EXPORT_SYMBOL(__ashrdi3);
|
||||
EXPORT_SYMBOL(__lshrdi3);
|
||||
EXPORT_SYMBOL(__muldi3);
|
||||
|
||||
#ifdef CONFIG_MMU
|
||||
#include "m68k_ksyms_mm.c"
|
||||
#else
|
||||
#include "m68k_ksyms_no.c"
|
||||
#endif
|
||||
|
16
arch/m68k/kernel/m68k_ksyms_mm.c
Normal file
16
arch/m68k/kernel/m68k_ksyms_mm.c
Normal file
@ -0,0 +1,16 @@
|
||||
#include <linux/module.h>
|
||||
|
||||
asmlinkage long long __ashldi3 (long long, int);
|
||||
asmlinkage long long __ashrdi3 (long long, int);
|
||||
asmlinkage long long __lshrdi3 (long long, int);
|
||||
asmlinkage long long __muldi3 (long long, long long);
|
||||
|
||||
/* The following are special because they're not called
|
||||
explicitly (the C compiler generates them). Fortunately,
|
||||
their interface isn't gonna change any time soon now, so
|
||||
it's OK to leave it out of version control. */
|
||||
EXPORT_SYMBOL(__ashldi3);
|
||||
EXPORT_SYMBOL(__ashrdi3);
|
||||
EXPORT_SYMBOL(__lshrdi3);
|
||||
EXPORT_SYMBOL(__muldi3);
|
||||
|
@ -1,155 +1,5 @@
|
||||
/*
|
||||
* This file is subject to the terms and conditions of the GNU General Public
|
||||
* License. See the file COPYING in the main directory of this archive
|
||||
* for more details.
|
||||
*/
|
||||
|
||||
#include <linux/moduleloader.h>
|
||||
#include <linux/elf.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/kernel.h>
|
||||
|
||||
#if 0
|
||||
#define DEBUGP printk
|
||||
#ifdef CONFIG_MMU
|
||||
#include "module_mm.c"
|
||||
#else
|
||||
#define DEBUGP(fmt...)
|
||||
#include "module_no.c"
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_MODULES
|
||||
|
||||
void *module_alloc(unsigned long size)
|
||||
{
|
||||
if (size == 0)
|
||||
return NULL;
|
||||
return vmalloc(size);
|
||||
}
|
||||
|
||||
|
||||
/* Free memory returned from module_alloc */
|
||||
void module_free(struct module *mod, void *module_region)
|
||||
{
|
||||
vfree(module_region);
|
||||
}
|
||||
|
||||
/* We don't need anything special. */
|
||||
int module_frob_arch_sections(Elf_Ehdr *hdr,
|
||||
Elf_Shdr *sechdrs,
|
||||
char *secstrings,
|
||||
struct module *mod)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int apply_relocate(Elf32_Shdr *sechdrs,
|
||||
const char *strtab,
|
||||
unsigned int symindex,
|
||||
unsigned int relsec,
|
||||
struct module *me)
|
||||
{
|
||||
unsigned int i;
|
||||
Elf32_Rel *rel = (void *)sechdrs[relsec].sh_addr;
|
||||
Elf32_Sym *sym;
|
||||
uint32_t *location;
|
||||
|
||||
DEBUGP("Applying relocate section %u to %u\n", relsec,
|
||||
sechdrs[relsec].sh_info);
|
||||
for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) {
|
||||
/* This is where to make the change */
|
||||
location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr
|
||||
+ rel[i].r_offset;
|
||||
/* This is the symbol it is referring to. Note that all
|
||||
undefined symbols have been resolved. */
|
||||
sym = (Elf32_Sym *)sechdrs[symindex].sh_addr
|
||||
+ ELF32_R_SYM(rel[i].r_info);
|
||||
|
||||
switch (ELF32_R_TYPE(rel[i].r_info)) {
|
||||
case R_68K_32:
|
||||
/* We add the value into the location given */
|
||||
*location += sym->st_value;
|
||||
break;
|
||||
case R_68K_PC32:
|
||||
/* Add the value, subtract its postition */
|
||||
*location += sym->st_value - (uint32_t)location;
|
||||
break;
|
||||
default:
|
||||
printk(KERN_ERR "module %s: Unknown relocation: %u\n",
|
||||
me->name, ELF32_R_TYPE(rel[i].r_info));
|
||||
return -ENOEXEC;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int apply_relocate_add(Elf32_Shdr *sechdrs,
|
||||
const char *strtab,
|
||||
unsigned int symindex,
|
||||
unsigned int relsec,
|
||||
struct module *me)
|
||||
{
|
||||
unsigned int i;
|
||||
Elf32_Rela *rel = (void *)sechdrs[relsec].sh_addr;
|
||||
Elf32_Sym *sym;
|
||||
uint32_t *location;
|
||||
|
||||
DEBUGP("Applying relocate_add section %u to %u\n", relsec,
|
||||
sechdrs[relsec].sh_info);
|
||||
for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) {
|
||||
/* This is where to make the change */
|
||||
location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr
|
||||
+ rel[i].r_offset;
|
||||
/* This is the symbol it is referring to. Note that all
|
||||
undefined symbols have been resolved. */
|
||||
sym = (Elf32_Sym *)sechdrs[symindex].sh_addr
|
||||
+ ELF32_R_SYM(rel[i].r_info);
|
||||
|
||||
switch (ELF32_R_TYPE(rel[i].r_info)) {
|
||||
case R_68K_32:
|
||||
/* We add the value into the location given */
|
||||
*location = rel[i].r_addend + sym->st_value;
|
||||
break;
|
||||
case R_68K_PC32:
|
||||
/* Add the value, subtract its postition */
|
||||
*location = rel[i].r_addend + sym->st_value - (uint32_t)location;
|
||||
break;
|
||||
default:
|
||||
printk(KERN_ERR "module %s: Unknown relocation: %u\n",
|
||||
me->name, ELF32_R_TYPE(rel[i].r_info));
|
||||
return -ENOEXEC;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int module_finalize(const Elf_Ehdr *hdr,
|
||||
const Elf_Shdr *sechdrs,
|
||||
struct module *mod)
|
||||
{
|
||||
module_fixup(mod, mod->arch.fixup_start, mod->arch.fixup_end);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void module_arch_cleanup(struct module *mod)
|
||||
{
|
||||
}
|
||||
|
||||
#endif /* CONFIG_MODULES */
|
||||
|
||||
void module_fixup(struct module *mod, struct m68k_fixup_info *start,
|
||||
struct m68k_fixup_info *end)
|
||||
{
|
||||
struct m68k_fixup_info *fixup;
|
||||
|
||||
for (fixup = start; fixup < end; fixup++) {
|
||||
switch (fixup->type) {
|
||||
case m68k_fixup_memoffset:
|
||||
*(u32 *)fixup->addr = m68k_memoffset;
|
||||
break;
|
||||
case m68k_fixup_vnode_shift:
|
||||
*(u16 *)fixup->addr += m68k_virt_to_node_shift;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
155
arch/m68k/kernel/module_mm.c
Normal file
155
arch/m68k/kernel/module_mm.c
Normal file
@ -0,0 +1,155 @@
|
||||
/*
|
||||
* This file is subject to the terms and conditions of the GNU General Public
|
||||
* License. See the file COPYING in the main directory of this archive
|
||||
* for more details.
|
||||
*/
|
||||
|
||||
#include <linux/moduleloader.h>
|
||||
#include <linux/elf.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/kernel.h>
|
||||
|
||||
#if 0
|
||||
#define DEBUGP printk
|
||||
#else
|
||||
#define DEBUGP(fmt...)
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_MODULES
|
||||
|
||||
void *module_alloc(unsigned long size)
|
||||
{
|
||||
if (size == 0)
|
||||
return NULL;
|
||||
return vmalloc(size);
|
||||
}
|
||||
|
||||
|
||||
/* Free memory returned from module_alloc */
|
||||
void module_free(struct module *mod, void *module_region)
|
||||
{
|
||||
vfree(module_region);
|
||||
}
|
||||
|
||||
/* We don't need anything special. */
|
||||
int module_frob_arch_sections(Elf_Ehdr *hdr,
|
||||
Elf_Shdr *sechdrs,
|
||||
char *secstrings,
|
||||
struct module *mod)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int apply_relocate(Elf32_Shdr *sechdrs,
|
||||
const char *strtab,
|
||||
unsigned int symindex,
|
||||
unsigned int relsec,
|
||||
struct module *me)
|
||||
{
|
||||
unsigned int i;
|
||||
Elf32_Rel *rel = (void *)sechdrs[relsec].sh_addr;
|
||||
Elf32_Sym *sym;
|
||||
uint32_t *location;
|
||||
|
||||
DEBUGP("Applying relocate section %u to %u\n", relsec,
|
||||
sechdrs[relsec].sh_info);
|
||||
for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) {
|
||||
/* This is where to make the change */
|
||||
location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr
|
||||
+ rel[i].r_offset;
|
||||
/* This is the symbol it is referring to. Note that all
|
||||
undefined symbols have been resolved. */
|
||||
sym = (Elf32_Sym *)sechdrs[symindex].sh_addr
|
||||
+ ELF32_R_SYM(rel[i].r_info);
|
||||
|
||||
switch (ELF32_R_TYPE(rel[i].r_info)) {
|
||||
case R_68K_32:
|
||||
/* We add the value into the location given */
|
||||
*location += sym->st_value;
|
||||
break;
|
||||
case R_68K_PC32:
|
||||
/* Add the value, subtract its postition */
|
||||
*location += sym->st_value - (uint32_t)location;
|
||||
break;
|
||||
default:
|
||||
printk(KERN_ERR "module %s: Unknown relocation: %u\n",
|
||||
me->name, ELF32_R_TYPE(rel[i].r_info));
|
||||
return -ENOEXEC;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int apply_relocate_add(Elf32_Shdr *sechdrs,
|
||||
const char *strtab,
|
||||
unsigned int symindex,
|
||||
unsigned int relsec,
|
||||
struct module *me)
|
||||
{
|
||||
unsigned int i;
|
||||
Elf32_Rela *rel = (void *)sechdrs[relsec].sh_addr;
|
||||
Elf32_Sym *sym;
|
||||
uint32_t *location;
|
||||
|
||||
DEBUGP("Applying relocate_add section %u to %u\n", relsec,
|
||||
sechdrs[relsec].sh_info);
|
||||
for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) {
|
||||
/* This is where to make the change */
|
||||
location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr
|
||||
+ rel[i].r_offset;
|
||||
/* This is the symbol it is referring to. Note that all
|
||||
undefined symbols have been resolved. */
|
||||
sym = (Elf32_Sym *)sechdrs[symindex].sh_addr
|
||||
+ ELF32_R_SYM(rel[i].r_info);
|
||||
|
||||
switch (ELF32_R_TYPE(rel[i].r_info)) {
|
||||
case R_68K_32:
|
||||
/* We add the value into the location given */
|
||||
*location = rel[i].r_addend + sym->st_value;
|
||||
break;
|
||||
case R_68K_PC32:
|
||||
/* Add the value, subtract its postition */
|
||||
*location = rel[i].r_addend + sym->st_value - (uint32_t)location;
|
||||
break;
|
||||
default:
|
||||
printk(KERN_ERR "module %s: Unknown relocation: %u\n",
|
||||
me->name, ELF32_R_TYPE(rel[i].r_info));
|
||||
return -ENOEXEC;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int module_finalize(const Elf_Ehdr *hdr,
|
||||
const Elf_Shdr *sechdrs,
|
||||
struct module *mod)
|
||||
{
|
||||
module_fixup(mod, mod->arch.fixup_start, mod->arch.fixup_end);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void module_arch_cleanup(struct module *mod)
|
||||
{
|
||||
}
|
||||
|
||||
#endif /* CONFIG_MODULES */
|
||||
|
||||
void module_fixup(struct module *mod, struct m68k_fixup_info *start,
|
||||
struct m68k_fixup_info *end)
|
||||
{
|
||||
struct m68k_fixup_info *fixup;
|
||||
|
||||
for (fixup = start; fixup < end; fixup++) {
|
||||
switch (fixup->type) {
|
||||
case m68k_fixup_memoffset:
|
||||
*(u32 *)fixup->addr = m68k_memoffset;
|
||||
break;
|
||||
case m68k_fixup_vnode_shift:
|
||||
*(u16 *)fixup->addr += m68k_virt_to_node_shift;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,354 +1,5 @@
|
||||
/*
|
||||
* linux/arch/m68k/kernel/process.c
|
||||
*
|
||||
* Copyright (C) 1995 Hamish Macdonald
|
||||
*
|
||||
* 68060 fixes by Jesper Skov
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file handles the architecture-dependent parts of process handling..
|
||||
*/
|
||||
|
||||
#include <linux/errno.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/smp.h>
|
||||
#include <linux/stddef.h>
|
||||
#include <linux/unistd.h>
|
||||
#include <linux/ptrace.h>
|
||||
#include <linux/user.h>
|
||||
#include <linux/reboot.h>
|
||||
#include <linux/init_task.h>
|
||||
#include <linux/mqueue.h>
|
||||
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/system.h>
|
||||
#include <asm/traps.h>
|
||||
#include <asm/machdep.h>
|
||||
#include <asm/setup.h>
|
||||
#include <asm/pgtable.h>
|
||||
|
||||
/*
|
||||
* Initial task/thread structure. Make this a per-architecture thing,
|
||||
* because different architectures tend to have different
|
||||
* alignment requirements and potentially different initial
|
||||
* setup.
|
||||
*/
|
||||
static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
|
||||
static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
|
||||
union thread_union init_thread_union __init_task_data
|
||||
__attribute__((aligned(THREAD_SIZE))) =
|
||||
{ INIT_THREAD_INFO(init_task) };
|
||||
|
||||
/* initial task structure */
|
||||
struct task_struct init_task = INIT_TASK(init_task);
|
||||
|
||||
EXPORT_SYMBOL(init_task);
|
||||
|
||||
asmlinkage void ret_from_fork(void);
|
||||
|
||||
|
||||
/*
|
||||
* Return saved PC from a blocked thread
|
||||
*/
|
||||
unsigned long thread_saved_pc(struct task_struct *tsk)
|
||||
{
|
||||
struct switch_stack *sw = (struct switch_stack *)tsk->thread.ksp;
|
||||
/* Check whether the thread is blocked in resume() */
|
||||
if (in_sched_functions(sw->retpc))
|
||||
return ((unsigned long *)sw->a6)[1];
|
||||
else
|
||||
return sw->retpc;
|
||||
}
|
||||
|
||||
/*
|
||||
* The idle loop on an m68k..
|
||||
*/
|
||||
static void default_idle(void)
|
||||
{
|
||||
if (!need_resched())
|
||||
#if defined(MACH_ATARI_ONLY)
|
||||
/* block out HSYNC on the atari (falcon) */
|
||||
__asm__("stop #0x2200" : : : "cc");
|
||||
#ifdef CONFIG_MMU
|
||||
#include "process_mm.c"
|
||||
#else
|
||||
__asm__("stop #0x2000" : : : "cc");
|
||||
#include "process_no.c"
|
||||
#endif
|
||||
}
|
||||
|
||||
void (*idle)(void) = default_idle;
|
||||
|
||||
/*
|
||||
* The idle thread. There's no useful work to be
|
||||
* done, so just try to conserve power and have a
|
||||
* low exit latency (ie sit in a loop waiting for
|
||||
* somebody to say that they'd like to reschedule)
|
||||
*/
|
||||
void cpu_idle(void)
|
||||
{
|
||||
/* endless idle loop with no priority at all */
|
||||
while (1) {
|
||||
while (!need_resched())
|
||||
idle();
|
||||
preempt_enable_no_resched();
|
||||
schedule();
|
||||
preempt_disable();
|
||||
}
|
||||
}
|
||||
|
||||
void machine_restart(char * __unused)
|
||||
{
|
||||
if (mach_reset)
|
||||
mach_reset();
|
||||
for (;;);
|
||||
}
|
||||
|
||||
void machine_halt(void)
|
||||
{
|
||||
if (mach_halt)
|
||||
mach_halt();
|
||||
for (;;);
|
||||
}
|
||||
|
||||
void machine_power_off(void)
|
||||
{
|
||||
if (mach_power_off)
|
||||
mach_power_off();
|
||||
for (;;);
|
||||
}
|
||||
|
||||
void (*pm_power_off)(void) = machine_power_off;
|
||||
EXPORT_SYMBOL(pm_power_off);
|
||||
|
||||
void show_regs(struct pt_regs * regs)
|
||||
{
|
||||
printk("\n");
|
||||
printk("Format %02x Vector: %04x PC: %08lx Status: %04x %s\n",
|
||||
regs->format, regs->vector, regs->pc, regs->sr, print_tainted());
|
||||
printk("ORIG_D0: %08lx D0: %08lx A2: %08lx A1: %08lx\n",
|
||||
regs->orig_d0, regs->d0, regs->a2, regs->a1);
|
||||
printk("A0: %08lx D5: %08lx D4: %08lx\n",
|
||||
regs->a0, regs->d5, regs->d4);
|
||||
printk("D3: %08lx D2: %08lx D1: %08lx\n",
|
||||
regs->d3, regs->d2, regs->d1);
|
||||
if (!(regs->sr & PS_S))
|
||||
printk("USP: %08lx\n", rdusp());
|
||||
}
|
||||
|
||||
/*
|
||||
* Create a kernel thread
|
||||
*/
|
||||
int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
|
||||
{
|
||||
int pid;
|
||||
mm_segment_t fs;
|
||||
|
||||
fs = get_fs();
|
||||
set_fs (KERNEL_DS);
|
||||
|
||||
{
|
||||
register long retval __asm__ ("d0");
|
||||
register long clone_arg __asm__ ("d1") = flags | CLONE_VM | CLONE_UNTRACED;
|
||||
|
||||
retval = __NR_clone;
|
||||
__asm__ __volatile__
|
||||
("clrl %%d2\n\t"
|
||||
"trap #0\n\t" /* Linux/m68k system call */
|
||||
"tstl %0\n\t" /* child or parent */
|
||||
"jne 1f\n\t" /* parent - jump */
|
||||
"lea %%sp@(%c7),%6\n\t" /* reload current */
|
||||
"movel %6@,%6\n\t"
|
||||
"movel %3,%%sp@-\n\t" /* push argument */
|
||||
"jsr %4@\n\t" /* call fn */
|
||||
"movel %0,%%d1\n\t" /* pass exit value */
|
||||
"movel %2,%%d0\n\t" /* exit */
|
||||
"trap #0\n"
|
||||
"1:"
|
||||
: "+d" (retval)
|
||||
: "i" (__NR_clone), "i" (__NR_exit),
|
||||
"r" (arg), "a" (fn), "d" (clone_arg), "r" (current),
|
||||
"i" (-THREAD_SIZE)
|
||||
: "d2");
|
||||
|
||||
pid = retval;
|
||||
}
|
||||
|
||||
set_fs (fs);
|
||||
return pid;
|
||||
}
|
||||
EXPORT_SYMBOL(kernel_thread);
|
||||
|
||||
void flush_thread(void)
|
||||
{
|
||||
unsigned long zero = 0;
|
||||
set_fs(USER_DS);
|
||||
current->thread.fs = __USER_DS;
|
||||
if (!FPU_IS_EMU)
|
||||
asm volatile (".chip 68k/68881\n\t"
|
||||
"frestore %0@\n\t"
|
||||
".chip 68k" : : "a" (&zero));
|
||||
}
|
||||
|
||||
/*
|
||||
* "m68k_fork()".. By the time we get here, the
|
||||
* non-volatile registers have also been saved on the
|
||||
* stack. We do some ugly pointer stuff here.. (see
|
||||
* also copy_thread)
|
||||
*/
|
||||
|
||||
asmlinkage int m68k_fork(struct pt_regs *regs)
|
||||
{
|
||||
return do_fork(SIGCHLD, rdusp(), regs, 0, NULL, NULL);
|
||||
}
|
||||
|
||||
asmlinkage int m68k_vfork(struct pt_regs *regs)
|
||||
{
|
||||
return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, rdusp(), regs, 0,
|
||||
NULL, NULL);
|
||||
}
|
||||
|
||||
asmlinkage int m68k_clone(struct pt_regs *regs)
|
||||
{
|
||||
unsigned long clone_flags;
|
||||
unsigned long newsp;
|
||||
int __user *parent_tidptr, *child_tidptr;
|
||||
|
||||
/* syscall2 puts clone_flags in d1 and usp in d2 */
|
||||
clone_flags = regs->d1;
|
||||
newsp = regs->d2;
|
||||
parent_tidptr = (int __user *)regs->d3;
|
||||
child_tidptr = (int __user *)regs->d4;
|
||||
if (!newsp)
|
||||
newsp = rdusp();
|
||||
return do_fork(clone_flags, newsp, regs, 0,
|
||||
parent_tidptr, child_tidptr);
|
||||
}
|
||||
|
||||
int copy_thread(unsigned long clone_flags, unsigned long usp,
|
||||
unsigned long unused,
|
||||
struct task_struct * p, struct pt_regs * regs)
|
||||
{
|
||||
struct pt_regs * childregs;
|
||||
struct switch_stack * childstack, *stack;
|
||||
unsigned long *retp;
|
||||
|
||||
childregs = (struct pt_regs *) (task_stack_page(p) + THREAD_SIZE) - 1;
|
||||
|
||||
*childregs = *regs;
|
||||
childregs->d0 = 0;
|
||||
|
||||
retp = ((unsigned long *) regs);
|
||||
stack = ((struct switch_stack *) retp) - 1;
|
||||
|
||||
childstack = ((struct switch_stack *) childregs) - 1;
|
||||
*childstack = *stack;
|
||||
childstack->retpc = (unsigned long)ret_from_fork;
|
||||
|
||||
p->thread.usp = usp;
|
||||
p->thread.ksp = (unsigned long)childstack;
|
||||
|
||||
if (clone_flags & CLONE_SETTLS)
|
||||
task_thread_info(p)->tp_value = regs->d5;
|
||||
|
||||
/*
|
||||
* Must save the current SFC/DFC value, NOT the value when
|
||||
* the parent was last descheduled - RGH 10-08-96
|
||||
*/
|
||||
p->thread.fs = get_fs().seg;
|
||||
|
||||
if (!FPU_IS_EMU) {
|
||||
/* Copy the current fpu state */
|
||||
asm volatile ("fsave %0" : : "m" (p->thread.fpstate[0]) : "memory");
|
||||
|
||||
if (!CPU_IS_060 ? p->thread.fpstate[0] : p->thread.fpstate[2])
|
||||
asm volatile ("fmovemx %/fp0-%/fp7,%0\n\t"
|
||||
"fmoveml %/fpiar/%/fpcr/%/fpsr,%1"
|
||||
: : "m" (p->thread.fp[0]), "m" (p->thread.fpcntl[0])
|
||||
: "memory");
|
||||
/* Restore the state in case the fpu was busy */
|
||||
asm volatile ("frestore %0" : : "m" (p->thread.fpstate[0]));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Fill in the fpu structure for a core dump. */
|
||||
|
||||
int dump_fpu (struct pt_regs *regs, struct user_m68kfp_struct *fpu)
|
||||
{
|
||||
char fpustate[216];
|
||||
|
||||
if (FPU_IS_EMU) {
|
||||
int i;
|
||||
|
||||
memcpy(fpu->fpcntl, current->thread.fpcntl, 12);
|
||||
memcpy(fpu->fpregs, current->thread.fp, 96);
|
||||
/* Convert internal fpu reg representation
|
||||
* into long double format
|
||||
*/
|
||||
for (i = 0; i < 24; i += 3)
|
||||
fpu->fpregs[i] = ((fpu->fpregs[i] & 0xffff0000) << 15) |
|
||||
((fpu->fpregs[i] & 0x0000ffff) << 16);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* First dump the fpu context to avoid protocol violation. */
|
||||
asm volatile ("fsave %0" :: "m" (fpustate[0]) : "memory");
|
||||
if (!CPU_IS_060 ? !fpustate[0] : !fpustate[2])
|
||||
return 0;
|
||||
|
||||
asm volatile ("fmovem %/fpiar/%/fpcr/%/fpsr,%0"
|
||||
:: "m" (fpu->fpcntl[0])
|
||||
: "memory");
|
||||
asm volatile ("fmovemx %/fp0-%/fp7,%0"
|
||||
:: "m" (fpu->fpregs[0])
|
||||
: "memory");
|
||||
return 1;
|
||||
}
|
||||
EXPORT_SYMBOL(dump_fpu);
|
||||
|
||||
/*
|
||||
* sys_execve() executes a new program.
|
||||
*/
|
||||
asmlinkage int sys_execve(const char __user *name,
|
||||
const char __user *const __user *argv,
|
||||
const char __user *const __user *envp)
|
||||
{
|
||||
int error;
|
||||
char * filename;
|
||||
struct pt_regs *regs = (struct pt_regs *) &name;
|
||||
|
||||
filename = getname(name);
|
||||
error = PTR_ERR(filename);
|
||||
if (IS_ERR(filename))
|
||||
return error;
|
||||
error = do_execve(filename, argv, envp, regs);
|
||||
putname(filename);
|
||||
return error;
|
||||
}
|
||||
|
||||
unsigned long get_wchan(struct task_struct *p)
|
||||
{
|
||||
unsigned long fp, pc;
|
||||
unsigned long stack_page;
|
||||
int count = 0;
|
||||
if (!p || p == current || p->state == TASK_RUNNING)
|
||||
return 0;
|
||||
|
||||
stack_page = (unsigned long)task_stack_page(p);
|
||||
fp = ((struct switch_stack *)p->thread.ksp)->a6;
|
||||
do {
|
||||
if (fp < stack_page+sizeof(struct thread_info) ||
|
||||
fp >= 8184+stack_page)
|
||||
return 0;
|
||||
pc = ((unsigned long *)fp)[1];
|
||||
if (!in_sched_functions(pc))
|
||||
return pc;
|
||||
fp = *(unsigned long *) fp;
|
||||
} while (count++ < 16);
|
||||
return 0;
|
||||
}
|
||||
|
354
arch/m68k/kernel/process_mm.c
Normal file
354
arch/m68k/kernel/process_mm.c
Normal file
@ -0,0 +1,354 @@
|
||||
/*
|
||||
* linux/arch/m68k/kernel/process.c
|
||||
*
|
||||
* Copyright (C) 1995 Hamish Macdonald
|
||||
*
|
||||
* 68060 fixes by Jesper Skov
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file handles the architecture-dependent parts of process handling..
|
||||
*/
|
||||
|
||||
#include <linux/errno.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/smp.h>
|
||||
#include <linux/stddef.h>
|
||||
#include <linux/unistd.h>
|
||||
#include <linux/ptrace.h>
|
||||
#include <linux/user.h>
|
||||
#include <linux/reboot.h>
|
||||
#include <linux/init_task.h>
|
||||
#include <linux/mqueue.h>
|
||||
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/system.h>
|
||||
#include <asm/traps.h>
|
||||
#include <asm/machdep.h>
|
||||
#include <asm/setup.h>
|
||||
#include <asm/pgtable.h>
|
||||
|
||||
/*
|
||||
* Initial task/thread structure. Make this a per-architecture thing,
|
||||
* because different architectures tend to have different
|
||||
* alignment requirements and potentially different initial
|
||||
* setup.
|
||||
*/
|
||||
static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
|
||||
static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
|
||||
union thread_union init_thread_union __init_task_data
|
||||
__attribute__((aligned(THREAD_SIZE))) =
|
||||
{ INIT_THREAD_INFO(init_task) };
|
||||
|
||||
/* initial task structure */
|
||||
struct task_struct init_task = INIT_TASK(init_task);
|
||||
|
||||
EXPORT_SYMBOL(init_task);
|
||||
|
||||
asmlinkage void ret_from_fork(void);
|
||||
|
||||
|
||||
/*
|
||||
* Return saved PC from a blocked thread
|
||||
*/
|
||||
unsigned long thread_saved_pc(struct task_struct *tsk)
|
||||
{
|
||||
struct switch_stack *sw = (struct switch_stack *)tsk->thread.ksp;
|
||||
/* Check whether the thread is blocked in resume() */
|
||||
if (in_sched_functions(sw->retpc))
|
||||
return ((unsigned long *)sw->a6)[1];
|
||||
else
|
||||
return sw->retpc;
|
||||
}
|
||||
|
||||
/*
|
||||
* The idle loop on an m68k..
|
||||
*/
|
||||
static void default_idle(void)
|
||||
{
|
||||
if (!need_resched())
|
||||
#if defined(MACH_ATARI_ONLY)
|
||||
/* block out HSYNC on the atari (falcon) */
|
||||
__asm__("stop #0x2200" : : : "cc");
|
||||
#else
|
||||
__asm__("stop #0x2000" : : : "cc");
|
||||
#endif
|
||||
}
|
||||
|
||||
void (*idle)(void) = default_idle;
|
||||
|
||||
/*
|
||||
* The idle thread. There's no useful work to be
|
||||
* done, so just try to conserve power and have a
|
||||
* low exit latency (ie sit in a loop waiting for
|
||||
* somebody to say that they'd like to reschedule)
|
||||
*/
|
||||
void cpu_idle(void)
|
||||
{
|
||||
/* endless idle loop with no priority at all */
|
||||
while (1) {
|
||||
while (!need_resched())
|
||||
idle();
|
||||
preempt_enable_no_resched();
|
||||
schedule();
|
||||
preempt_disable();
|
||||
}
|
||||
}
|
||||
|
||||
void machine_restart(char * __unused)
|
||||
{
|
||||
if (mach_reset)
|
||||
mach_reset();
|
||||
for (;;);
|
||||
}
|
||||
|
||||
void machine_halt(void)
|
||||
{
|
||||
if (mach_halt)
|
||||
mach_halt();
|
||||
for (;;);
|
||||
}
|
||||
|
||||
void machine_power_off(void)
|
||||
{
|
||||
if (mach_power_off)
|
||||
mach_power_off();
|
||||
for (;;);
|
||||
}
|
||||
|
||||
void (*pm_power_off)(void) = machine_power_off;
|
||||
EXPORT_SYMBOL(pm_power_off);
|
||||
|
||||
void show_regs(struct pt_regs * regs)
|
||||
{
|
||||
printk("\n");
|
||||
printk("Format %02x Vector: %04x PC: %08lx Status: %04x %s\n",
|
||||
regs->format, regs->vector, regs->pc, regs->sr, print_tainted());
|
||||
printk("ORIG_D0: %08lx D0: %08lx A2: %08lx A1: %08lx\n",
|
||||
regs->orig_d0, regs->d0, regs->a2, regs->a1);
|
||||
printk("A0: %08lx D5: %08lx D4: %08lx\n",
|
||||
regs->a0, regs->d5, regs->d4);
|
||||
printk("D3: %08lx D2: %08lx D1: %08lx\n",
|
||||
regs->d3, regs->d2, regs->d1);
|
||||
if (!(regs->sr & PS_S))
|
||||
printk("USP: %08lx\n", rdusp());
|
||||
}
|
||||
|
||||
/*
|
||||
* Create a kernel thread
|
||||
*/
|
||||
int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
|
||||
{
|
||||
int pid;
|
||||
mm_segment_t fs;
|
||||
|
||||
fs = get_fs();
|
||||
set_fs (KERNEL_DS);
|
||||
|
||||
{
|
||||
register long retval __asm__ ("d0");
|
||||
register long clone_arg __asm__ ("d1") = flags | CLONE_VM | CLONE_UNTRACED;
|
||||
|
||||
retval = __NR_clone;
|
||||
__asm__ __volatile__
|
||||
("clrl %%d2\n\t"
|
||||
"trap #0\n\t" /* Linux/m68k system call */
|
||||
"tstl %0\n\t" /* child or parent */
|
||||
"jne 1f\n\t" /* parent - jump */
|
||||
"lea %%sp@(%c7),%6\n\t" /* reload current */
|
||||
"movel %6@,%6\n\t"
|
||||
"movel %3,%%sp@-\n\t" /* push argument */
|
||||
"jsr %4@\n\t" /* call fn */
|
||||
"movel %0,%%d1\n\t" /* pass exit value */
|
||||
"movel %2,%%d0\n\t" /* exit */
|
||||
"trap #0\n"
|
||||
"1:"
|
||||
: "+d" (retval)
|
||||
: "i" (__NR_clone), "i" (__NR_exit),
|
||||
"r" (arg), "a" (fn), "d" (clone_arg), "r" (current),
|
||||
"i" (-THREAD_SIZE)
|
||||
: "d2");
|
||||
|
||||
pid = retval;
|
||||
}
|
||||
|
||||
set_fs (fs);
|
||||
return pid;
|
||||
}
|
||||
EXPORT_SYMBOL(kernel_thread);
|
||||
|
||||
void flush_thread(void)
|
||||
{
|
||||
unsigned long zero = 0;
|
||||
set_fs(USER_DS);
|
||||
current->thread.fs = __USER_DS;
|
||||
if (!FPU_IS_EMU)
|
||||
asm volatile (".chip 68k/68881\n\t"
|
||||
"frestore %0@\n\t"
|
||||
".chip 68k" : : "a" (&zero));
|
||||
}
|
||||
|
||||
/*
|
||||
* "m68k_fork()".. By the time we get here, the
|
||||
* non-volatile registers have also been saved on the
|
||||
* stack. We do some ugly pointer stuff here.. (see
|
||||
* also copy_thread)
|
||||
*/
|
||||
|
||||
asmlinkage int m68k_fork(struct pt_regs *regs)
|
||||
{
|
||||
return do_fork(SIGCHLD, rdusp(), regs, 0, NULL, NULL);
|
||||
}
|
||||
|
||||
asmlinkage int m68k_vfork(struct pt_regs *regs)
|
||||
{
|
||||
return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, rdusp(), regs, 0,
|
||||
NULL, NULL);
|
||||
}
|
||||
|
||||
asmlinkage int m68k_clone(struct pt_regs *regs)
|
||||
{
|
||||
unsigned long clone_flags;
|
||||
unsigned long newsp;
|
||||
int __user *parent_tidptr, *child_tidptr;
|
||||
|
||||
/* syscall2 puts clone_flags in d1 and usp in d2 */
|
||||
clone_flags = regs->d1;
|
||||
newsp = regs->d2;
|
||||
parent_tidptr = (int __user *)regs->d3;
|
||||
child_tidptr = (int __user *)regs->d4;
|
||||
if (!newsp)
|
||||
newsp = rdusp();
|
||||
return do_fork(clone_flags, newsp, regs, 0,
|
||||
parent_tidptr, child_tidptr);
|
||||
}
|
||||
|
||||
int copy_thread(unsigned long clone_flags, unsigned long usp,
|
||||
unsigned long unused,
|
||||
struct task_struct * p, struct pt_regs * regs)
|
||||
{
|
||||
struct pt_regs * childregs;
|
||||
struct switch_stack * childstack, *stack;
|
||||
unsigned long *retp;
|
||||
|
||||
childregs = (struct pt_regs *) (task_stack_page(p) + THREAD_SIZE) - 1;
|
||||
|
||||
*childregs = *regs;
|
||||
childregs->d0 = 0;
|
||||
|
||||
retp = ((unsigned long *) regs);
|
||||
stack = ((struct switch_stack *) retp) - 1;
|
||||
|
||||
childstack = ((struct switch_stack *) childregs) - 1;
|
||||
*childstack = *stack;
|
||||
childstack->retpc = (unsigned long)ret_from_fork;
|
||||
|
||||
p->thread.usp = usp;
|
||||
p->thread.ksp = (unsigned long)childstack;
|
||||
|
||||
if (clone_flags & CLONE_SETTLS)
|
||||
task_thread_info(p)->tp_value = regs->d5;
|
||||
|
||||
/*
|
||||
* Must save the current SFC/DFC value, NOT the value when
|
||||
* the parent was last descheduled - RGH 10-08-96
|
||||
*/
|
||||
p->thread.fs = get_fs().seg;
|
||||
|
||||
if (!FPU_IS_EMU) {
|
||||
/* Copy the current fpu state */
|
||||
asm volatile ("fsave %0" : : "m" (p->thread.fpstate[0]) : "memory");
|
||||
|
||||
if (!CPU_IS_060 ? p->thread.fpstate[0] : p->thread.fpstate[2])
|
||||
asm volatile ("fmovemx %/fp0-%/fp7,%0\n\t"
|
||||
"fmoveml %/fpiar/%/fpcr/%/fpsr,%1"
|
||||
: : "m" (p->thread.fp[0]), "m" (p->thread.fpcntl[0])
|
||||
: "memory");
|
||||
/* Restore the state in case the fpu was busy */
|
||||
asm volatile ("frestore %0" : : "m" (p->thread.fpstate[0]));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Fill in the fpu structure for a core dump. */
|
||||
|
||||
int dump_fpu (struct pt_regs *regs, struct user_m68kfp_struct *fpu)
|
||||
{
|
||||
char fpustate[216];
|
||||
|
||||
if (FPU_IS_EMU) {
|
||||
int i;
|
||||
|
||||
memcpy(fpu->fpcntl, current->thread.fpcntl, 12);
|
||||
memcpy(fpu->fpregs, current->thread.fp, 96);
|
||||
/* Convert internal fpu reg representation
|
||||
* into long double format
|
||||
*/
|
||||
for (i = 0; i < 24; i += 3)
|
||||
fpu->fpregs[i] = ((fpu->fpregs[i] & 0xffff0000) << 15) |
|
||||
((fpu->fpregs[i] & 0x0000ffff) << 16);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* First dump the fpu context to avoid protocol violation. */
|
||||
asm volatile ("fsave %0" :: "m" (fpustate[0]) : "memory");
|
||||
if (!CPU_IS_060 ? !fpustate[0] : !fpustate[2])
|
||||
return 0;
|
||||
|
||||
asm volatile ("fmovem %/fpiar/%/fpcr/%/fpsr,%0"
|
||||
:: "m" (fpu->fpcntl[0])
|
||||
: "memory");
|
||||
asm volatile ("fmovemx %/fp0-%/fp7,%0"
|
||||
:: "m" (fpu->fpregs[0])
|
||||
: "memory");
|
||||
return 1;
|
||||
}
|
||||
EXPORT_SYMBOL(dump_fpu);
|
||||
|
||||
/*
|
||||
* sys_execve() executes a new program.
|
||||
*/
|
||||
asmlinkage int sys_execve(const char __user *name,
|
||||
const char __user *const __user *argv,
|
||||
const char __user *const __user *envp)
|
||||
{
|
||||
int error;
|
||||
char * filename;
|
||||
struct pt_regs *regs = (struct pt_regs *) &name;
|
||||
|
||||
filename = getname(name);
|
||||
error = PTR_ERR(filename);
|
||||
if (IS_ERR(filename))
|
||||
return error;
|
||||
error = do_execve(filename, argv, envp, regs);
|
||||
putname(filename);
|
||||
return error;
|
||||
}
|
||||
|
||||
unsigned long get_wchan(struct task_struct *p)
|
||||
{
|
||||
unsigned long fp, pc;
|
||||
unsigned long stack_page;
|
||||
int count = 0;
|
||||
if (!p || p == current || p->state == TASK_RUNNING)
|
||||
return 0;
|
||||
|
||||
stack_page = (unsigned long)task_stack_page(p);
|
||||
fp = ((struct switch_stack *)p->thread.ksp)->a6;
|
||||
do {
|
||||
if (fp < stack_page+sizeof(struct thread_info) ||
|
||||
fp >= 8184+stack_page)
|
||||
return 0;
|
||||
pc = ((unsigned long *)fp)[1];
|
||||
if (!in_sched_functions(pc))
|
||||
return pc;
|
||||
fp = *(unsigned long *) fp;
|
||||
} while (count++ < 16);
|
||||
return 0;
|
||||
}
|
@ -1,277 +1,5 @@
|
||||
/*
|
||||
* linux/arch/m68k/kernel/ptrace.c
|
||||
*
|
||||
* Copyright (C) 1994 by Hamish Macdonald
|
||||
* Taken from linux/kernel/ptrace.c and modified for M680x0.
|
||||
* linux/kernel/ptrace.c is by Ross Biro 1/23/92, edited by Linus Torvalds
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU General
|
||||
* Public License. See the file COPYING in the main directory of
|
||||
* this archive for more details.
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/smp.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/ptrace.h>
|
||||
#include <linux/user.h>
|
||||
#include <linux/signal.h>
|
||||
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/page.h>
|
||||
#include <asm/pgtable.h>
|
||||
#include <asm/system.h>
|
||||
#include <asm/processor.h>
|
||||
|
||||
/*
|
||||
* does not yet catch signals sent when the child dies.
|
||||
* in exit.c or in signal.c.
|
||||
*/
|
||||
|
||||
/* determines which bits in the SR the user has access to. */
|
||||
/* 1 = access 0 = no access */
|
||||
#define SR_MASK 0x001f
|
||||
|
||||
/* sets the trace bits. */
|
||||
#define TRACE_BITS 0xC000
|
||||
#define T1_BIT 0x8000
|
||||
#define T0_BIT 0x4000
|
||||
|
||||
/* Find the stack offset for a register, relative to thread.esp0. */
|
||||
#define PT_REG(reg) ((long)&((struct pt_regs *)0)->reg)
|
||||
#define SW_REG(reg) ((long)&((struct switch_stack *)0)->reg \
|
||||
- sizeof(struct switch_stack))
|
||||
/* Mapping from PT_xxx to the stack offset at which the register is
|
||||
saved. Notice that usp has no stack-slot and needs to be treated
|
||||
specially (see get_reg/put_reg below). */
|
||||
static const int regoff[] = {
|
||||
[0] = PT_REG(d1),
|
||||
[1] = PT_REG(d2),
|
||||
[2] = PT_REG(d3),
|
||||
[3] = PT_REG(d4),
|
||||
[4] = PT_REG(d5),
|
||||
[5] = SW_REG(d6),
|
||||
[6] = SW_REG(d7),
|
||||
[7] = PT_REG(a0),
|
||||
[8] = PT_REG(a1),
|
||||
[9] = PT_REG(a2),
|
||||
[10] = SW_REG(a3),
|
||||
[11] = SW_REG(a4),
|
||||
[12] = SW_REG(a5),
|
||||
[13] = SW_REG(a6),
|
||||
[14] = PT_REG(d0),
|
||||
[15] = -1,
|
||||
[16] = PT_REG(orig_d0),
|
||||
[17] = PT_REG(sr),
|
||||
[18] = PT_REG(pc),
|
||||
};
|
||||
|
||||
/*
|
||||
* Get contents of register REGNO in task TASK.
|
||||
*/
|
||||
static inline long get_reg(struct task_struct *task, int regno)
|
||||
{
|
||||
unsigned long *addr;
|
||||
|
||||
if (regno == PT_USP)
|
||||
addr = &task->thread.usp;
|
||||
else if (regno < ARRAY_SIZE(regoff))
|
||||
addr = (unsigned long *)(task->thread.esp0 + regoff[regno]);
|
||||
else
|
||||
return 0;
|
||||
/* Need to take stkadj into account. */
|
||||
if (regno == PT_SR || regno == PT_PC) {
|
||||
long stkadj = *(long *)(task->thread.esp0 + PT_REG(stkadj));
|
||||
addr = (unsigned long *) ((unsigned long)addr + stkadj);
|
||||
/* The sr is actually a 16 bit register. */
|
||||
if (regno == PT_SR)
|
||||
return *(unsigned short *)addr;
|
||||
}
|
||||
return *addr;
|
||||
}
|
||||
|
||||
/*
|
||||
* Write contents of register REGNO in task TASK.
|
||||
*/
|
||||
static inline int put_reg(struct task_struct *task, int regno,
|
||||
unsigned long data)
|
||||
{
|
||||
unsigned long *addr;
|
||||
|
||||
if (regno == PT_USP)
|
||||
addr = &task->thread.usp;
|
||||
else if (regno < ARRAY_SIZE(regoff))
|
||||
addr = (unsigned long *)(task->thread.esp0 + regoff[regno]);
|
||||
else
|
||||
return -1;
|
||||
/* Need to take stkadj into account. */
|
||||
if (regno == PT_SR || regno == PT_PC) {
|
||||
long stkadj = *(long *)(task->thread.esp0 + PT_REG(stkadj));
|
||||
addr = (unsigned long *) ((unsigned long)addr + stkadj);
|
||||
/* The sr is actually a 16 bit register. */
|
||||
if (regno == PT_SR) {
|
||||
*(unsigned short *)addr = data;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
*addr = data;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Make sure the single step bit is not set.
|
||||
*/
|
||||
static inline void singlestep_disable(struct task_struct *child)
|
||||
{
|
||||
unsigned long tmp = get_reg(child, PT_SR) & ~TRACE_BITS;
|
||||
put_reg(child, PT_SR, tmp);
|
||||
clear_tsk_thread_flag(child, TIF_DELAYED_TRACE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Called by kernel/ptrace.c when detaching..
|
||||
*/
|
||||
void ptrace_disable(struct task_struct *child)
|
||||
{
|
||||
singlestep_disable(child);
|
||||
}
|
||||
|
||||
void user_enable_single_step(struct task_struct *child)
|
||||
{
|
||||
unsigned long tmp = get_reg(child, PT_SR) & ~TRACE_BITS;
|
||||
put_reg(child, PT_SR, tmp | T1_BIT);
|
||||
set_tsk_thread_flag(child, TIF_DELAYED_TRACE);
|
||||
}
|
||||
|
||||
void user_enable_block_step(struct task_struct *child)
|
||||
{
|
||||
unsigned long tmp = get_reg(child, PT_SR) & ~TRACE_BITS;
|
||||
put_reg(child, PT_SR, tmp | T0_BIT);
|
||||
}
|
||||
|
||||
void user_disable_single_step(struct task_struct *child)
|
||||
{
|
||||
singlestep_disable(child);
|
||||
}
|
||||
|
||||
long arch_ptrace(struct task_struct *child, long request,
|
||||
unsigned long addr, unsigned long data)
|
||||
{
|
||||
unsigned long tmp;
|
||||
int i, ret = 0;
|
||||
int regno = addr >> 2; /* temporary hack. */
|
||||
unsigned long __user *datap = (unsigned long __user *) data;
|
||||
|
||||
switch (request) {
|
||||
/* read the word at location addr in the USER area. */
|
||||
case PTRACE_PEEKUSR:
|
||||
if (addr & 3)
|
||||
goto out_eio;
|
||||
|
||||
if (regno >= 0 && regno < 19) {
|
||||
tmp = get_reg(child, regno);
|
||||
} else if (regno >= 21 && regno < 49) {
|
||||
tmp = child->thread.fp[regno - 21];
|
||||
/* Convert internal fpu reg representation
|
||||
* into long double format
|
||||
*/
|
||||
if (FPU_IS_EMU && (regno < 45) && !(regno % 3))
|
||||
tmp = ((tmp & 0xffff0000) << 15) |
|
||||
((tmp & 0x0000ffff) << 16);
|
||||
} else
|
||||
goto out_eio;
|
||||
ret = put_user(tmp, datap);
|
||||
break;
|
||||
|
||||
case PTRACE_POKEUSR:
|
||||
/* write the word at location addr in the USER area */
|
||||
if (addr & 3)
|
||||
goto out_eio;
|
||||
|
||||
if (regno == PT_SR) {
|
||||
data &= SR_MASK;
|
||||
data |= get_reg(child, PT_SR) & ~SR_MASK;
|
||||
}
|
||||
if (regno >= 0 && regno < 19) {
|
||||
if (put_reg(child, regno, data))
|
||||
goto out_eio;
|
||||
} else if (regno >= 21 && regno < 48) {
|
||||
/* Convert long double format
|
||||
* into internal fpu reg representation
|
||||
*/
|
||||
if (FPU_IS_EMU && (regno < 45) && !(regno % 3)) {
|
||||
data <<= 15;
|
||||
data = (data & 0xffff0000) |
|
||||
((data & 0x0000ffff) >> 1);
|
||||
}
|
||||
child->thread.fp[regno - 21] = data;
|
||||
} else
|
||||
goto out_eio;
|
||||
break;
|
||||
|
||||
case PTRACE_GETREGS: /* Get all gp regs from the child. */
|
||||
for (i = 0; i < 19; i++) {
|
||||
tmp = get_reg(child, i);
|
||||
ret = put_user(tmp, datap);
|
||||
if (ret)
|
||||
break;
|
||||
datap++;
|
||||
}
|
||||
break;
|
||||
|
||||
case PTRACE_SETREGS: /* Set all gp regs in the child. */
|
||||
for (i = 0; i < 19; i++) {
|
||||
ret = get_user(tmp, datap);
|
||||
if (ret)
|
||||
break;
|
||||
if (i == PT_SR) {
|
||||
tmp &= SR_MASK;
|
||||
tmp |= get_reg(child, PT_SR) & ~SR_MASK;
|
||||
}
|
||||
put_reg(child, i, tmp);
|
||||
datap++;
|
||||
}
|
||||
break;
|
||||
|
||||
case PTRACE_GETFPREGS: /* Get the child FPU state. */
|
||||
if (copy_to_user(datap, &child->thread.fp,
|
||||
sizeof(struct user_m68kfp_struct)))
|
||||
ret = -EFAULT;
|
||||
break;
|
||||
|
||||
case PTRACE_SETFPREGS: /* Set the child FPU state. */
|
||||
if (copy_from_user(&child->thread.fp, datap,
|
||||
sizeof(struct user_m68kfp_struct)))
|
||||
ret = -EFAULT;
|
||||
break;
|
||||
|
||||
case PTRACE_GET_THREAD_AREA:
|
||||
ret = put_user(task_thread_info(child)->tp_value, datap);
|
||||
break;
|
||||
|
||||
default:
|
||||
ret = ptrace_request(child, request, addr, data);
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
out_eio:
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
asmlinkage void syscall_trace(void)
|
||||
{
|
||||
ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
|
||||
? 0x80 : 0));
|
||||
/*
|
||||
* this isn't the same as continuing with a signal, but it will do
|
||||
* for normal use. strace only continues with a signal if the
|
||||
* stopping signal is not SIGTRAP. -brl
|
||||
*/
|
||||
if (current->exit_code) {
|
||||
send_sig(current->exit_code, current, 1);
|
||||
current->exit_code = 0;
|
||||
}
|
||||
}
|
||||
#ifdef CONFIG_MMU
|
||||
#include "ptrace_mm.c"
|
||||
#else
|
||||
#include "ptrace_no.c"
|
||||
#endif
|
||||
|
277
arch/m68k/kernel/ptrace_mm.c
Normal file
277
arch/m68k/kernel/ptrace_mm.c
Normal file
@ -0,0 +1,277 @@
|
||||
/*
|
||||
* linux/arch/m68k/kernel/ptrace.c
|
||||
*
|
||||
* Copyright (C) 1994 by Hamish Macdonald
|
||||
* Taken from linux/kernel/ptrace.c and modified for M680x0.
|
||||
* linux/kernel/ptrace.c is by Ross Biro 1/23/92, edited by Linus Torvalds
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU General
|
||||
* Public License. See the file COPYING in the main directory of
|
||||
* this archive for more details.
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/smp.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/ptrace.h>
|
||||
#include <linux/user.h>
|
||||
#include <linux/signal.h>
|
||||
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/page.h>
|
||||
#include <asm/pgtable.h>
|
||||
#include <asm/system.h>
|
||||
#include <asm/processor.h>
|
||||
|
||||
/*
|
||||
* does not yet catch signals sent when the child dies.
|
||||
* in exit.c or in signal.c.
|
||||
*/
|
||||
|
||||
/* determines which bits in the SR the user has access to. */
|
||||
/* 1 = access 0 = no access */
|
||||
#define SR_MASK 0x001f
|
||||
|
||||
/* sets the trace bits. */
|
||||
#define TRACE_BITS 0xC000
|
||||
#define T1_BIT 0x8000
|
||||
#define T0_BIT 0x4000
|
||||
|
||||
/* Find the stack offset for a register, relative to thread.esp0. */
|
||||
#define PT_REG(reg) ((long)&((struct pt_regs *)0)->reg)
|
||||
#define SW_REG(reg) ((long)&((struct switch_stack *)0)->reg \
|
||||
- sizeof(struct switch_stack))
|
||||
/* Mapping from PT_xxx to the stack offset at which the register is
|
||||
saved. Notice that usp has no stack-slot and needs to be treated
|
||||
specially (see get_reg/put_reg below). */
|
||||
static const int regoff[] = {
|
||||
[0] = PT_REG(d1),
|
||||
[1] = PT_REG(d2),
|
||||
[2] = PT_REG(d3),
|
||||
[3] = PT_REG(d4),
|
||||
[4] = PT_REG(d5),
|
||||
[5] = SW_REG(d6),
|
||||
[6] = SW_REG(d7),
|
||||
[7] = PT_REG(a0),
|
||||
[8] = PT_REG(a1),
|
||||
[9] = PT_REG(a2),
|
||||
[10] = SW_REG(a3),
|
||||
[11] = SW_REG(a4),
|
||||
[12] = SW_REG(a5),
|
||||
[13] = SW_REG(a6),
|
||||
[14] = PT_REG(d0),
|
||||
[15] = -1,
|
||||
[16] = PT_REG(orig_d0),
|
||||
[17] = PT_REG(sr),
|
||||
[18] = PT_REG(pc),
|
||||
};
|
||||
|
||||
/*
|
||||
* Get contents of register REGNO in task TASK.
|
||||
*/
|
||||
static inline long get_reg(struct task_struct *task, int regno)
|
||||
{
|
||||
unsigned long *addr;
|
||||
|
||||
if (regno == PT_USP)
|
||||
addr = &task->thread.usp;
|
||||
else if (regno < ARRAY_SIZE(regoff))
|
||||
addr = (unsigned long *)(task->thread.esp0 + regoff[regno]);
|
||||
else
|
||||
return 0;
|
||||
/* Need to take stkadj into account. */
|
||||
if (regno == PT_SR || regno == PT_PC) {
|
||||
long stkadj = *(long *)(task->thread.esp0 + PT_REG(stkadj));
|
||||
addr = (unsigned long *) ((unsigned long)addr + stkadj);
|
||||
/* The sr is actually a 16 bit register. */
|
||||
if (regno == PT_SR)
|
||||
return *(unsigned short *)addr;
|
||||
}
|
||||
return *addr;
|
||||
}
|
||||
|
||||
/*
|
||||
* Write contents of register REGNO in task TASK.
|
||||
*/
|
||||
static inline int put_reg(struct task_struct *task, int regno,
|
||||
unsigned long data)
|
||||
{
|
||||
unsigned long *addr;
|
||||
|
||||
if (regno == PT_USP)
|
||||
addr = &task->thread.usp;
|
||||
else if (regno < ARRAY_SIZE(regoff))
|
||||
addr = (unsigned long *)(task->thread.esp0 + regoff[regno]);
|
||||
else
|
||||
return -1;
|
||||
/* Need to take stkadj into account. */
|
||||
if (regno == PT_SR || regno == PT_PC) {
|
||||
long stkadj = *(long *)(task->thread.esp0 + PT_REG(stkadj));
|
||||
addr = (unsigned long *) ((unsigned long)addr + stkadj);
|
||||
/* The sr is actually a 16 bit register. */
|
||||
if (regno == PT_SR) {
|
||||
*(unsigned short *)addr = data;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
*addr = data;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Make sure the single step bit is not set.
|
||||
*/
|
||||
static inline void singlestep_disable(struct task_struct *child)
|
||||
{
|
||||
unsigned long tmp = get_reg(child, PT_SR) & ~TRACE_BITS;
|
||||
put_reg(child, PT_SR, tmp);
|
||||
clear_tsk_thread_flag(child, TIF_DELAYED_TRACE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Called by kernel/ptrace.c when detaching..
|
||||
*/
|
||||
void ptrace_disable(struct task_struct *child)
|
||||
{
|
||||
singlestep_disable(child);
|
||||
}
|
||||
|
||||
void user_enable_single_step(struct task_struct *child)
|
||||
{
|
||||
unsigned long tmp = get_reg(child, PT_SR) & ~TRACE_BITS;
|
||||
put_reg(child, PT_SR, tmp | T1_BIT);
|
||||
set_tsk_thread_flag(child, TIF_DELAYED_TRACE);
|
||||
}
|
||||
|
||||
void user_enable_block_step(struct task_struct *child)
|
||||
{
|
||||
unsigned long tmp = get_reg(child, PT_SR) & ~TRACE_BITS;
|
||||
put_reg(child, PT_SR, tmp | T0_BIT);
|
||||
}
|
||||
|
||||
void user_disable_single_step(struct task_struct *child)
|
||||
{
|
||||
singlestep_disable(child);
|
||||
}
|
||||
|
||||
long arch_ptrace(struct task_struct *child, long request,
|
||||
unsigned long addr, unsigned long data)
|
||||
{
|
||||
unsigned long tmp;
|
||||
int i, ret = 0;
|
||||
int regno = addr >> 2; /* temporary hack. */
|
||||
unsigned long __user *datap = (unsigned long __user *) data;
|
||||
|
||||
switch (request) {
|
||||
/* read the word at location addr in the USER area. */
|
||||
case PTRACE_PEEKUSR:
|
||||
if (addr & 3)
|
||||
goto out_eio;
|
||||
|
||||
if (regno >= 0 && regno < 19) {
|
||||
tmp = get_reg(child, regno);
|
||||
} else if (regno >= 21 && regno < 49) {
|
||||
tmp = child->thread.fp[regno - 21];
|
||||
/* Convert internal fpu reg representation
|
||||
* into long double format
|
||||
*/
|
||||
if (FPU_IS_EMU && (regno < 45) && !(regno % 3))
|
||||
tmp = ((tmp & 0xffff0000) << 15) |
|
||||
((tmp & 0x0000ffff) << 16);
|
||||
} else
|
||||
goto out_eio;
|
||||
ret = put_user(tmp, datap);
|
||||
break;
|
||||
|
||||
case PTRACE_POKEUSR:
|
||||
/* write the word at location addr in the USER area */
|
||||
if (addr & 3)
|
||||
goto out_eio;
|
||||
|
||||
if (regno == PT_SR) {
|
||||
data &= SR_MASK;
|
||||
data |= get_reg(child, PT_SR) & ~SR_MASK;
|
||||
}
|
||||
if (regno >= 0 && regno < 19) {
|
||||
if (put_reg(child, regno, data))
|
||||
goto out_eio;
|
||||
} else if (regno >= 21 && regno < 48) {
|
||||
/* Convert long double format
|
||||
* into internal fpu reg representation
|
||||
*/
|
||||
if (FPU_IS_EMU && (regno < 45) && !(regno % 3)) {
|
||||
data <<= 15;
|
||||
data = (data & 0xffff0000) |
|
||||
((data & 0x0000ffff) >> 1);
|
||||
}
|
||||
child->thread.fp[regno - 21] = data;
|
||||
} else
|
||||
goto out_eio;
|
||||
break;
|
||||
|
||||
case PTRACE_GETREGS: /* Get all gp regs from the child. */
|
||||
for (i = 0; i < 19; i++) {
|
||||
tmp = get_reg(child, i);
|
||||
ret = put_user(tmp, datap);
|
||||
if (ret)
|
||||
break;
|
||||
datap++;
|
||||
}
|
||||
break;
|
||||
|
||||
case PTRACE_SETREGS: /* Set all gp regs in the child. */
|
||||
for (i = 0; i < 19; i++) {
|
||||
ret = get_user(tmp, datap);
|
||||
if (ret)
|
||||
break;
|
||||
if (i == PT_SR) {
|
||||
tmp &= SR_MASK;
|
||||
tmp |= get_reg(child, PT_SR) & ~SR_MASK;
|
||||
}
|
||||
put_reg(child, i, tmp);
|
||||
datap++;
|
||||
}
|
||||
break;
|
||||
|
||||
case PTRACE_GETFPREGS: /* Get the child FPU state. */
|
||||
if (copy_to_user(datap, &child->thread.fp,
|
||||
sizeof(struct user_m68kfp_struct)))
|
||||
ret = -EFAULT;
|
||||
break;
|
||||
|
||||
case PTRACE_SETFPREGS: /* Set the child FPU state. */
|
||||
if (copy_from_user(&child->thread.fp, datap,
|
||||
sizeof(struct user_m68kfp_struct)))
|
||||
ret = -EFAULT;
|
||||
break;
|
||||
|
||||
case PTRACE_GET_THREAD_AREA:
|
||||
ret = put_user(task_thread_info(child)->tp_value, datap);
|
||||
break;
|
||||
|
||||
default:
|
||||
ret = ptrace_request(child, request, addr, data);
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
out_eio:
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
asmlinkage void syscall_trace(void)
|
||||
{
|
||||
ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
|
||||
? 0x80 : 0));
|
||||
/*
|
||||
* this isn't the same as continuing with a signal, but it will do
|
||||
* for normal use. strace only continues with a signal if the
|
||||
* stopping signal is not SIGTRAP. -brl
|
||||
*/
|
||||
if (current->exit_code) {
|
||||
send_sig(current->exit_code, current, 1);
|
||||
current->exit_code = 0;
|
||||
}
|
||||
}
|
@ -1,533 +1,5 @@
|
||||
/*
|
||||
* linux/arch/m68k/kernel/setup.c
|
||||
*
|
||||
* Copyright (C) 1995 Hamish Macdonald
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file handles the architecture-dependent parts of system setup
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/console.h>
|
||||
#include <linux/genhd.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/bootmem.h>
|
||||
#include <linux/proc_fs.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/initrd.h>
|
||||
|
||||
#include <asm/bootinfo.h>
|
||||
#include <asm/sections.h>
|
||||
#include <asm/setup.h>
|
||||
#include <asm/fpu.h>
|
||||
#include <asm/irq.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/machdep.h>
|
||||
#ifdef CONFIG_AMIGA
|
||||
#include <asm/amigahw.h>
|
||||
#endif
|
||||
#ifdef CONFIG_ATARI
|
||||
#include <asm/atarihw.h>
|
||||
#include <asm/atari_stram.h>
|
||||
#endif
|
||||
#ifdef CONFIG_SUN3X
|
||||
#include <asm/dvma.h>
|
||||
#endif
|
||||
#include <asm/natfeat.h>
|
||||
|
||||
#if !FPSTATESIZE || !NR_IRQS
|
||||
#warning No CPU/platform type selected, your kernel will not work!
|
||||
#warning Are you building an allnoconfig kernel?
|
||||
#endif
|
||||
|
||||
unsigned long m68k_machtype;
|
||||
EXPORT_SYMBOL(m68k_machtype);
|
||||
unsigned long m68k_cputype;
|
||||
EXPORT_SYMBOL(m68k_cputype);
|
||||
unsigned long m68k_fputype;
|
||||
unsigned long m68k_mmutype;
|
||||
EXPORT_SYMBOL(m68k_mmutype);
|
||||
#ifdef CONFIG_VME
|
||||
unsigned long vme_brdtype;
|
||||
EXPORT_SYMBOL(vme_brdtype);
|
||||
#endif
|
||||
|
||||
int m68k_is040or060;
|
||||
EXPORT_SYMBOL(m68k_is040or060);
|
||||
|
||||
extern unsigned long availmem;
|
||||
|
||||
int m68k_num_memory;
|
||||
EXPORT_SYMBOL(m68k_num_memory);
|
||||
int m68k_realnum_memory;
|
||||
EXPORT_SYMBOL(m68k_realnum_memory);
|
||||
unsigned long m68k_memoffset;
|
||||
struct mem_info m68k_memory[NUM_MEMINFO];
|
||||
EXPORT_SYMBOL(m68k_memory);
|
||||
|
||||
struct mem_info m68k_ramdisk;
|
||||
|
||||
static char m68k_command_line[CL_SIZE];
|
||||
|
||||
void (*mach_sched_init) (irq_handler_t handler) __initdata = NULL;
|
||||
/* machine dependent irq functions */
|
||||
void (*mach_init_IRQ) (void) __initdata = NULL;
|
||||
void (*mach_get_model) (char *model);
|
||||
void (*mach_get_hardware_list) (struct seq_file *m);
|
||||
/* machine dependent timer functions */
|
||||
unsigned long (*mach_gettimeoffset) (void);
|
||||
int (*mach_hwclk) (int, struct rtc_time*);
|
||||
EXPORT_SYMBOL(mach_hwclk);
|
||||
int (*mach_set_clock_mmss) (unsigned long);
|
||||
unsigned int (*mach_get_ss)(void);
|
||||
int (*mach_get_rtc_pll)(struct rtc_pll_info *);
|
||||
int (*mach_set_rtc_pll)(struct rtc_pll_info *);
|
||||
EXPORT_SYMBOL(mach_get_ss);
|
||||
EXPORT_SYMBOL(mach_get_rtc_pll);
|
||||
EXPORT_SYMBOL(mach_set_rtc_pll);
|
||||
void (*mach_reset)( void );
|
||||
void (*mach_halt)( void );
|
||||
void (*mach_power_off)( void );
|
||||
long mach_max_dma_address = 0x00ffffff; /* default set to the lower 16MB */
|
||||
#ifdef CONFIG_HEARTBEAT
|
||||
void (*mach_heartbeat) (int);
|
||||
EXPORT_SYMBOL(mach_heartbeat);
|
||||
#endif
|
||||
#ifdef CONFIG_M68K_L2_CACHE
|
||||
void (*mach_l2_flush) (int);
|
||||
#endif
|
||||
#if defined(CONFIG_INPUT_M68K_BEEP) || defined(CONFIG_INPUT_M68K_BEEP_MODULE)
|
||||
void (*mach_beep)(unsigned int, unsigned int);
|
||||
EXPORT_SYMBOL(mach_beep);
|
||||
#endif
|
||||
#if defined(CONFIG_ISA) && defined(MULTI_ISA)
|
||||
int isa_type;
|
||||
int isa_sex;
|
||||
EXPORT_SYMBOL(isa_type);
|
||||
EXPORT_SYMBOL(isa_sex);
|
||||
#endif
|
||||
|
||||
extern int amiga_parse_bootinfo(const struct bi_record *);
|
||||
extern int atari_parse_bootinfo(const struct bi_record *);
|
||||
extern int mac_parse_bootinfo(const struct bi_record *);
|
||||
extern int q40_parse_bootinfo(const struct bi_record *);
|
||||
extern int bvme6000_parse_bootinfo(const struct bi_record *);
|
||||
extern int mvme16x_parse_bootinfo(const struct bi_record *);
|
||||
extern int mvme147_parse_bootinfo(const struct bi_record *);
|
||||
extern int hp300_parse_bootinfo(const struct bi_record *);
|
||||
extern int apollo_parse_bootinfo(const struct bi_record *);
|
||||
|
||||
extern void config_amiga(void);
|
||||
extern void config_atari(void);
|
||||
extern void config_mac(void);
|
||||
extern void config_sun3(void);
|
||||
extern void config_apollo(void);
|
||||
extern void config_mvme147(void);
|
||||
extern void config_mvme16x(void);
|
||||
extern void config_bvme6000(void);
|
||||
extern void config_hp300(void);
|
||||
extern void config_q40(void);
|
||||
extern void config_sun3x(void);
|
||||
|
||||
#define MASK_256K 0xfffc0000
|
||||
|
||||
extern void paging_init(void);
|
||||
|
||||
static void __init m68k_parse_bootinfo(const struct bi_record *record)
|
||||
{
|
||||
while (record->tag != BI_LAST) {
|
||||
int unknown = 0;
|
||||
const unsigned long *data = record->data;
|
||||
|
||||
switch (record->tag) {
|
||||
case BI_MACHTYPE:
|
||||
case BI_CPUTYPE:
|
||||
case BI_FPUTYPE:
|
||||
case BI_MMUTYPE:
|
||||
/* Already set up by head.S */
|
||||
break;
|
||||
|
||||
case BI_MEMCHUNK:
|
||||
if (m68k_num_memory < NUM_MEMINFO) {
|
||||
m68k_memory[m68k_num_memory].addr = data[0];
|
||||
m68k_memory[m68k_num_memory].size = data[1];
|
||||
m68k_num_memory++;
|
||||
} else
|
||||
printk("m68k_parse_bootinfo: too many memory chunks\n");
|
||||
break;
|
||||
|
||||
case BI_RAMDISK:
|
||||
m68k_ramdisk.addr = data[0];
|
||||
m68k_ramdisk.size = data[1];
|
||||
break;
|
||||
|
||||
case BI_COMMAND_LINE:
|
||||
strlcpy(m68k_command_line, (const char *)data,
|
||||
sizeof(m68k_command_line));
|
||||
break;
|
||||
|
||||
default:
|
||||
if (MACH_IS_AMIGA)
|
||||
unknown = amiga_parse_bootinfo(record);
|
||||
else if (MACH_IS_ATARI)
|
||||
unknown = atari_parse_bootinfo(record);
|
||||
else if (MACH_IS_MAC)
|
||||
unknown = mac_parse_bootinfo(record);
|
||||
else if (MACH_IS_Q40)
|
||||
unknown = q40_parse_bootinfo(record);
|
||||
else if (MACH_IS_BVME6000)
|
||||
unknown = bvme6000_parse_bootinfo(record);
|
||||
else if (MACH_IS_MVME16x)
|
||||
unknown = mvme16x_parse_bootinfo(record);
|
||||
else if (MACH_IS_MVME147)
|
||||
unknown = mvme147_parse_bootinfo(record);
|
||||
else if (MACH_IS_HP300)
|
||||
unknown = hp300_parse_bootinfo(record);
|
||||
else if (MACH_IS_APOLLO)
|
||||
unknown = apollo_parse_bootinfo(record);
|
||||
else
|
||||
unknown = 1;
|
||||
}
|
||||
if (unknown)
|
||||
printk("m68k_parse_bootinfo: unknown tag 0x%04x ignored\n",
|
||||
record->tag);
|
||||
record = (struct bi_record *)((unsigned long)record +
|
||||
record->size);
|
||||
}
|
||||
|
||||
m68k_realnum_memory = m68k_num_memory;
|
||||
#ifdef CONFIG_SINGLE_MEMORY_CHUNK
|
||||
if (m68k_num_memory > 1) {
|
||||
printk("Ignoring last %i chunks of physical memory\n",
|
||||
(m68k_num_memory - 1));
|
||||
m68k_num_memory = 1;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void __init setup_arch(char **cmdline_p)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* The bootinfo is located right after the kernel bss */
|
||||
m68k_parse_bootinfo((const struct bi_record *)_end);
|
||||
|
||||
if (CPU_IS_040)
|
||||
m68k_is040or060 = 4;
|
||||
else if (CPU_IS_060)
|
||||
m68k_is040or060 = 6;
|
||||
|
||||
/* FIXME: m68k_fputype is passed in by Penguin booter, which can
|
||||
* be confused by software FPU emulation. BEWARE.
|
||||
* We should really do our own FPU check at startup.
|
||||
* [what do we do with buggy 68LC040s? if we have problems
|
||||
* with them, we should add a test to check_bugs() below] */
|
||||
#ifndef CONFIG_M68KFPU_EMU_ONLY
|
||||
/* clear the fpu if we have one */
|
||||
if (m68k_fputype & (FPU_68881|FPU_68882|FPU_68040|FPU_68060)) {
|
||||
volatile int zero = 0;
|
||||
asm volatile ("frestore %0" : : "m" (zero));
|
||||
}
|
||||
#endif
|
||||
|
||||
if (CPU_IS_060) {
|
||||
u32 pcr;
|
||||
|
||||
asm (".chip 68060; movec %%pcr,%0; .chip 68k"
|
||||
: "=d" (pcr));
|
||||
if (((pcr >> 8) & 0xff) <= 5) {
|
||||
printk("Enabling workaround for errata I14\n");
|
||||
asm (".chip 68060; movec %0,%%pcr; .chip 68k"
|
||||
: : "d" (pcr | 0x20));
|
||||
}
|
||||
}
|
||||
|
||||
init_mm.start_code = PAGE_OFFSET;
|
||||
init_mm.end_code = (unsigned long)_etext;
|
||||
init_mm.end_data = (unsigned long)_edata;
|
||||
init_mm.brk = (unsigned long)_end;
|
||||
|
||||
*cmdline_p = m68k_command_line;
|
||||
memcpy(boot_command_line, *cmdline_p, CL_SIZE);
|
||||
|
||||
parse_early_param();
|
||||
|
||||
#ifdef CONFIG_DUMMY_CONSOLE
|
||||
conswitchp = &dummy_con;
|
||||
#endif
|
||||
|
||||
switch (m68k_machtype) {
|
||||
#ifdef CONFIG_AMIGA
|
||||
case MACH_AMIGA:
|
||||
config_amiga();
|
||||
break;
|
||||
#endif
|
||||
#ifdef CONFIG_ATARI
|
||||
case MACH_ATARI:
|
||||
config_atari();
|
||||
break;
|
||||
#endif
|
||||
#ifdef CONFIG_MAC
|
||||
case MACH_MAC:
|
||||
config_mac();
|
||||
break;
|
||||
#endif
|
||||
#ifdef CONFIG_SUN3
|
||||
case MACH_SUN3:
|
||||
config_sun3();
|
||||
break;
|
||||
#endif
|
||||
#ifdef CONFIG_APOLLO
|
||||
case MACH_APOLLO:
|
||||
config_apollo();
|
||||
break;
|
||||
#endif
|
||||
#ifdef CONFIG_MVME147
|
||||
case MACH_MVME147:
|
||||
config_mvme147();
|
||||
break;
|
||||
#endif
|
||||
#ifdef CONFIG_MVME16x
|
||||
case MACH_MVME16x:
|
||||
config_mvme16x();
|
||||
break;
|
||||
#endif
|
||||
#ifdef CONFIG_BVME6000
|
||||
case MACH_BVME6000:
|
||||
config_bvme6000();
|
||||
break;
|
||||
#endif
|
||||
#ifdef CONFIG_HP300
|
||||
case MACH_HP300:
|
||||
config_hp300();
|
||||
break;
|
||||
#endif
|
||||
#ifdef CONFIG_Q40
|
||||
case MACH_Q40:
|
||||
config_q40();
|
||||
break;
|
||||
#endif
|
||||
#ifdef CONFIG_SUN3X
|
||||
case MACH_SUN3X:
|
||||
config_sun3x();
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
panic("No configuration setup");
|
||||
}
|
||||
|
||||
#ifdef CONFIG_NATFEAT
|
||||
nf_init();
|
||||
#endif
|
||||
|
||||
paging_init();
|
||||
|
||||
#ifndef CONFIG_SUN3
|
||||
for (i = 1; i < m68k_num_memory; i++)
|
||||
free_bootmem_node(NODE_DATA(i), m68k_memory[i].addr,
|
||||
m68k_memory[i].size);
|
||||
#ifdef CONFIG_BLK_DEV_INITRD
|
||||
if (m68k_ramdisk.size) {
|
||||
reserve_bootmem_node(__virt_to_node(phys_to_virt(m68k_ramdisk.addr)),
|
||||
m68k_ramdisk.addr, m68k_ramdisk.size,
|
||||
BOOTMEM_DEFAULT);
|
||||
initrd_start = (unsigned long)phys_to_virt(m68k_ramdisk.addr);
|
||||
initrd_end = initrd_start + m68k_ramdisk.size;
|
||||
printk("initrd: %08lx - %08lx\n", initrd_start, initrd_end);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ATARI
|
||||
if (MACH_IS_ATARI)
|
||||
atari_stram_reserve_pages((void *)availmem);
|
||||
#endif
|
||||
#ifdef CONFIG_SUN3X
|
||||
if (MACH_IS_SUN3X) {
|
||||
dvma_init();
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* !CONFIG_SUN3 */
|
||||
|
||||
/* set ISA defs early as possible */
|
||||
#if defined(CONFIG_ISA) && defined(MULTI_ISA)
|
||||
if (MACH_IS_Q40) {
|
||||
isa_type = ISA_TYPE_Q40;
|
||||
isa_sex = 0;
|
||||
}
|
||||
#ifdef CONFIG_AMIGA_PCMCIA
|
||||
if (MACH_IS_AMIGA && AMIGAHW_PRESENT(PCMCIA)) {
|
||||
isa_type = ISA_TYPE_AG;
|
||||
isa_sex = 1;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
static int show_cpuinfo(struct seq_file *m, void *v)
|
||||
{
|
||||
const char *cpu, *mmu, *fpu;
|
||||
unsigned long clockfreq, clockfactor;
|
||||
|
||||
#define LOOP_CYCLES_68020 (8)
|
||||
#define LOOP_CYCLES_68030 (8)
|
||||
#define LOOP_CYCLES_68040 (3)
|
||||
#define LOOP_CYCLES_68060 (1)
|
||||
|
||||
if (CPU_IS_020) {
|
||||
cpu = "68020";
|
||||
clockfactor = LOOP_CYCLES_68020;
|
||||
} else if (CPU_IS_030) {
|
||||
cpu = "68030";
|
||||
clockfactor = LOOP_CYCLES_68030;
|
||||
} else if (CPU_IS_040) {
|
||||
cpu = "68040";
|
||||
clockfactor = LOOP_CYCLES_68040;
|
||||
} else if (CPU_IS_060) {
|
||||
cpu = "68060";
|
||||
clockfactor = LOOP_CYCLES_68060;
|
||||
} else {
|
||||
cpu = "680x0";
|
||||
clockfactor = 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_M68KFPU_EMU_ONLY
|
||||
fpu = "none(soft float)";
|
||||
#ifdef CONFIG_MMU
|
||||
#include "setup_mm.c"
|
||||
#else
|
||||
if (m68k_fputype & FPU_68881)
|
||||
fpu = "68881";
|
||||
else if (m68k_fputype & FPU_68882)
|
||||
fpu = "68882";
|
||||
else if (m68k_fputype & FPU_68040)
|
||||
fpu = "68040";
|
||||
else if (m68k_fputype & FPU_68060)
|
||||
fpu = "68060";
|
||||
else if (m68k_fputype & FPU_SUNFPA)
|
||||
fpu = "Sun FPA";
|
||||
else
|
||||
fpu = "none";
|
||||
#include "setup_no.c"
|
||||
#endif
|
||||
|
||||
if (m68k_mmutype & MMU_68851)
|
||||
mmu = "68851";
|
||||
else if (m68k_mmutype & MMU_68030)
|
||||
mmu = "68030";
|
||||
else if (m68k_mmutype & MMU_68040)
|
||||
mmu = "68040";
|
||||
else if (m68k_mmutype & MMU_68060)
|
||||
mmu = "68060";
|
||||
else if (m68k_mmutype & MMU_SUN3)
|
||||
mmu = "Sun-3";
|
||||
else if (m68k_mmutype & MMU_APOLLO)
|
||||
mmu = "Apollo";
|
||||
else
|
||||
mmu = "unknown";
|
||||
|
||||
clockfreq = loops_per_jiffy * HZ * clockfactor;
|
||||
|
||||
seq_printf(m, "CPU:\t\t%s\n"
|
||||
"MMU:\t\t%s\n"
|
||||
"FPU:\t\t%s\n"
|
||||
"Clocking:\t%lu.%1luMHz\n"
|
||||
"BogoMips:\t%lu.%02lu\n"
|
||||
"Calibration:\t%lu loops\n",
|
||||
cpu, mmu, fpu,
|
||||
clockfreq/1000000,(clockfreq/100000)%10,
|
||||
loops_per_jiffy/(500000/HZ),(loops_per_jiffy/(5000/HZ))%100,
|
||||
loops_per_jiffy);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void *c_start(struct seq_file *m, loff_t *pos)
|
||||
{
|
||||
return *pos < 1 ? (void *)1 : NULL;
|
||||
}
|
||||
static void *c_next(struct seq_file *m, void *v, loff_t *pos)
|
||||
{
|
||||
++*pos;
|
||||
return NULL;
|
||||
}
|
||||
static void c_stop(struct seq_file *m, void *v)
|
||||
{
|
||||
}
|
||||
const struct seq_operations cpuinfo_op = {
|
||||
.start = c_start,
|
||||
.next = c_next,
|
||||
.stop = c_stop,
|
||||
.show = show_cpuinfo,
|
||||
};
|
||||
|
||||
#ifdef CONFIG_PROC_HARDWARE
|
||||
static int hardware_proc_show(struct seq_file *m, void *v)
|
||||
{
|
||||
char model[80];
|
||||
unsigned long mem;
|
||||
int i;
|
||||
|
||||
if (mach_get_model)
|
||||
mach_get_model(model);
|
||||
else
|
||||
strcpy(model, "Unknown m68k");
|
||||
|
||||
seq_printf(m, "Model:\t\t%s\n", model);
|
||||
for (mem = 0, i = 0; i < m68k_num_memory; i++)
|
||||
mem += m68k_memory[i].size;
|
||||
seq_printf(m, "System Memory:\t%ldK\n", mem >> 10);
|
||||
|
||||
if (mach_get_hardware_list)
|
||||
mach_get_hardware_list(m);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int hardware_proc_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
return single_open(file, hardware_proc_show, NULL);
|
||||
}
|
||||
|
||||
static const struct file_operations hardware_proc_fops = {
|
||||
.open = hardware_proc_open,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
.release = single_release,
|
||||
};
|
||||
|
||||
static int __init proc_hardware_init(void)
|
||||
{
|
||||
proc_create("hardware", 0, NULL, &hardware_proc_fops);
|
||||
return 0;
|
||||
}
|
||||
module_init(proc_hardware_init);
|
||||
#endif
|
||||
|
||||
void check_bugs(void)
|
||||
{
|
||||
#ifndef CONFIG_M68KFPU_EMU
|
||||
if (m68k_fputype == 0) {
|
||||
printk(KERN_EMERG "*** YOU DO NOT HAVE A FLOATING POINT UNIT, "
|
||||
"WHICH IS REQUIRED BY LINUX/M68K ***\n");
|
||||
printk(KERN_EMERG "Upgrade your hardware or join the FPU "
|
||||
"emulation project\n");
|
||||
panic("no FPU");
|
||||
}
|
||||
#endif /* !CONFIG_M68KFPU_EMU */
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ADB
|
||||
static int __init adb_probe_sync_enable (char *str) {
|
||||
extern int __adb_probe_sync;
|
||||
__adb_probe_sync = 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
__setup("adb_sync", adb_probe_sync_enable);
|
||||
#endif /* CONFIG_ADB */
|
||||
|
533
arch/m68k/kernel/setup_mm.c
Normal file
533
arch/m68k/kernel/setup_mm.c
Normal file
@ -0,0 +1,533 @@
|
||||
/*
|
||||
* linux/arch/m68k/kernel/setup.c
|
||||
*
|
||||
* Copyright (C) 1995 Hamish Macdonald
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file handles the architecture-dependent parts of system setup
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/console.h>
|
||||
#include <linux/genhd.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/bootmem.h>
|
||||
#include <linux/proc_fs.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/initrd.h>
|
||||
|
||||
#include <asm/bootinfo.h>
|
||||
#include <asm/sections.h>
|
||||
#include <asm/setup.h>
|
||||
#include <asm/fpu.h>
|
||||
#include <asm/irq.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/machdep.h>
|
||||
#ifdef CONFIG_AMIGA
|
||||
#include <asm/amigahw.h>
|
||||
#endif
|
||||
#ifdef CONFIG_ATARI
|
||||
#include <asm/atarihw.h>
|
||||
#include <asm/atari_stram.h>
|
||||
#endif
|
||||
#ifdef CONFIG_SUN3X
|
||||
#include <asm/dvma.h>
|
||||
#endif
|
||||
#include <asm/natfeat.h>
|
||||
|
||||
#if !FPSTATESIZE || !NR_IRQS
|
||||
#warning No CPU/platform type selected, your kernel will not work!
|
||||
#warning Are you building an allnoconfig kernel?
|
||||
#endif
|
||||
|
||||
unsigned long m68k_machtype;
|
||||
EXPORT_SYMBOL(m68k_machtype);
|
||||
unsigned long m68k_cputype;
|
||||
EXPORT_SYMBOL(m68k_cputype);
|
||||
unsigned long m68k_fputype;
|
||||
unsigned long m68k_mmutype;
|
||||
EXPORT_SYMBOL(m68k_mmutype);
|
||||
#ifdef CONFIG_VME
|
||||
unsigned long vme_brdtype;
|
||||
EXPORT_SYMBOL(vme_brdtype);
|
||||
#endif
|
||||
|
||||
int m68k_is040or060;
|
||||
EXPORT_SYMBOL(m68k_is040or060);
|
||||
|
||||
extern unsigned long availmem;
|
||||
|
||||
int m68k_num_memory;
|
||||
EXPORT_SYMBOL(m68k_num_memory);
|
||||
int m68k_realnum_memory;
|
||||
EXPORT_SYMBOL(m68k_realnum_memory);
|
||||
unsigned long m68k_memoffset;
|
||||
struct mem_info m68k_memory[NUM_MEMINFO];
|
||||
EXPORT_SYMBOL(m68k_memory);
|
||||
|
||||
struct mem_info m68k_ramdisk;
|
||||
|
||||
static char m68k_command_line[CL_SIZE];
|
||||
|
||||
void (*mach_sched_init) (irq_handler_t handler) __initdata = NULL;
|
||||
/* machine dependent irq functions */
|
||||
void (*mach_init_IRQ) (void) __initdata = NULL;
|
||||
void (*mach_get_model) (char *model);
|
||||
void (*mach_get_hardware_list) (struct seq_file *m);
|
||||
/* machine dependent timer functions */
|
||||
unsigned long (*mach_gettimeoffset) (void);
|
||||
int (*mach_hwclk) (int, struct rtc_time*);
|
||||
EXPORT_SYMBOL(mach_hwclk);
|
||||
int (*mach_set_clock_mmss) (unsigned long);
|
||||
unsigned int (*mach_get_ss)(void);
|
||||
int (*mach_get_rtc_pll)(struct rtc_pll_info *);
|
||||
int (*mach_set_rtc_pll)(struct rtc_pll_info *);
|
||||
EXPORT_SYMBOL(mach_get_ss);
|
||||
EXPORT_SYMBOL(mach_get_rtc_pll);
|
||||
EXPORT_SYMBOL(mach_set_rtc_pll);
|
||||
void (*mach_reset)( void );
|
||||
void (*mach_halt)( void );
|
||||
void (*mach_power_off)( void );
|
||||
long mach_max_dma_address = 0x00ffffff; /* default set to the lower 16MB */
|
||||
#ifdef CONFIG_HEARTBEAT
|
||||
void (*mach_heartbeat) (int);
|
||||
EXPORT_SYMBOL(mach_heartbeat);
|
||||
#endif
|
||||
#ifdef CONFIG_M68K_L2_CACHE
|
||||
void (*mach_l2_flush) (int);
|
||||
#endif
|
||||
#if defined(CONFIG_INPUT_M68K_BEEP) || defined(CONFIG_INPUT_M68K_BEEP_MODULE)
|
||||
void (*mach_beep)(unsigned int, unsigned int);
|
||||
EXPORT_SYMBOL(mach_beep);
|
||||
#endif
|
||||
#if defined(CONFIG_ISA) && defined(MULTI_ISA)
|
||||
int isa_type;
|
||||
int isa_sex;
|
||||
EXPORT_SYMBOL(isa_type);
|
||||
EXPORT_SYMBOL(isa_sex);
|
||||
#endif
|
||||
|
||||
extern int amiga_parse_bootinfo(const struct bi_record *);
|
||||
extern int atari_parse_bootinfo(const struct bi_record *);
|
||||
extern int mac_parse_bootinfo(const struct bi_record *);
|
||||
extern int q40_parse_bootinfo(const struct bi_record *);
|
||||
extern int bvme6000_parse_bootinfo(const struct bi_record *);
|
||||
extern int mvme16x_parse_bootinfo(const struct bi_record *);
|
||||
extern int mvme147_parse_bootinfo(const struct bi_record *);
|
||||
extern int hp300_parse_bootinfo(const struct bi_record *);
|
||||
extern int apollo_parse_bootinfo(const struct bi_record *);
|
||||
|
||||
extern void config_amiga(void);
|
||||
extern void config_atari(void);
|
||||
extern void config_mac(void);
|
||||
extern void config_sun3(void);
|
||||
extern void config_apollo(void);
|
||||
extern void config_mvme147(void);
|
||||
extern void config_mvme16x(void);
|
||||
extern void config_bvme6000(void);
|
||||
extern void config_hp300(void);
|
||||
extern void config_q40(void);
|
||||
extern void config_sun3x(void);
|
||||
|
||||
#define MASK_256K 0xfffc0000
|
||||
|
||||
extern void paging_init(void);
|
||||
|
||||
static void __init m68k_parse_bootinfo(const struct bi_record *record)
|
||||
{
|
||||
while (record->tag != BI_LAST) {
|
||||
int unknown = 0;
|
||||
const unsigned long *data = record->data;
|
||||
|
||||
switch (record->tag) {
|
||||
case BI_MACHTYPE:
|
||||
case BI_CPUTYPE:
|
||||
case BI_FPUTYPE:
|
||||
case BI_MMUTYPE:
|
||||
/* Already set up by head.S */
|
||||
break;
|
||||
|
||||
case BI_MEMCHUNK:
|
||||
if (m68k_num_memory < NUM_MEMINFO) {
|
||||
m68k_memory[m68k_num_memory].addr = data[0];
|
||||
m68k_memory[m68k_num_memory].size = data[1];
|
||||
m68k_num_memory++;
|
||||
} else
|
||||
printk("m68k_parse_bootinfo: too many memory chunks\n");
|
||||
break;
|
||||
|
||||
case BI_RAMDISK:
|
||||
m68k_ramdisk.addr = data[0];
|
||||
m68k_ramdisk.size = data[1];
|
||||
break;
|
||||
|
||||
case BI_COMMAND_LINE:
|
||||
strlcpy(m68k_command_line, (const char *)data,
|
||||
sizeof(m68k_command_line));
|
||||
break;
|
||||
|
||||
default:
|
||||
if (MACH_IS_AMIGA)
|
||||
unknown = amiga_parse_bootinfo(record);
|
||||
else if (MACH_IS_ATARI)
|
||||
unknown = atari_parse_bootinfo(record);
|
||||
else if (MACH_IS_MAC)
|
||||
unknown = mac_parse_bootinfo(record);
|
||||
else if (MACH_IS_Q40)
|
||||
unknown = q40_parse_bootinfo(record);
|
||||
else if (MACH_IS_BVME6000)
|
||||
unknown = bvme6000_parse_bootinfo(record);
|
||||
else if (MACH_IS_MVME16x)
|
||||
unknown = mvme16x_parse_bootinfo(record);
|
||||
else if (MACH_IS_MVME147)
|
||||
unknown = mvme147_parse_bootinfo(record);
|
||||
else if (MACH_IS_HP300)
|
||||
unknown = hp300_parse_bootinfo(record);
|
||||
else if (MACH_IS_APOLLO)
|
||||
unknown = apollo_parse_bootinfo(record);
|
||||
else
|
||||
unknown = 1;
|
||||
}
|
||||
if (unknown)
|
||||
printk("m68k_parse_bootinfo: unknown tag 0x%04x ignored\n",
|
||||
record->tag);
|
||||
record = (struct bi_record *)((unsigned long)record +
|
||||
record->size);
|
||||
}
|
||||
|
||||
m68k_realnum_memory = m68k_num_memory;
|
||||
#ifdef CONFIG_SINGLE_MEMORY_CHUNK
|
||||
if (m68k_num_memory > 1) {
|
||||
printk("Ignoring last %i chunks of physical memory\n",
|
||||
(m68k_num_memory - 1));
|
||||
m68k_num_memory = 1;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void __init setup_arch(char **cmdline_p)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* The bootinfo is located right after the kernel bss */
|
||||
m68k_parse_bootinfo((const struct bi_record *)_end);
|
||||
|
||||
if (CPU_IS_040)
|
||||
m68k_is040or060 = 4;
|
||||
else if (CPU_IS_060)
|
||||
m68k_is040or060 = 6;
|
||||
|
||||
/* FIXME: m68k_fputype is passed in by Penguin booter, which can
|
||||
* be confused by software FPU emulation. BEWARE.
|
||||
* We should really do our own FPU check at startup.
|
||||
* [what do we do with buggy 68LC040s? if we have problems
|
||||
* with them, we should add a test to check_bugs() below] */
|
||||
#ifndef CONFIG_M68KFPU_EMU_ONLY
|
||||
/* clear the fpu if we have one */
|
||||
if (m68k_fputype & (FPU_68881|FPU_68882|FPU_68040|FPU_68060)) {
|
||||
volatile int zero = 0;
|
||||
asm volatile ("frestore %0" : : "m" (zero));
|
||||
}
|
||||
#endif
|
||||
|
||||
if (CPU_IS_060) {
|
||||
u32 pcr;
|
||||
|
||||
asm (".chip 68060; movec %%pcr,%0; .chip 68k"
|
||||
: "=d" (pcr));
|
||||
if (((pcr >> 8) & 0xff) <= 5) {
|
||||
printk("Enabling workaround for errata I14\n");
|
||||
asm (".chip 68060; movec %0,%%pcr; .chip 68k"
|
||||
: : "d" (pcr | 0x20));
|
||||
}
|
||||
}
|
||||
|
||||
init_mm.start_code = PAGE_OFFSET;
|
||||
init_mm.end_code = (unsigned long)_etext;
|
||||
init_mm.end_data = (unsigned long)_edata;
|
||||
init_mm.brk = (unsigned long)_end;
|
||||
|
||||
*cmdline_p = m68k_command_line;
|
||||
memcpy(boot_command_line, *cmdline_p, CL_SIZE);
|
||||
|
||||
parse_early_param();
|
||||
|
||||
#ifdef CONFIG_DUMMY_CONSOLE
|
||||
conswitchp = &dummy_con;
|
||||
#endif
|
||||
|
||||
switch (m68k_machtype) {
|
||||
#ifdef CONFIG_AMIGA
|
||||
case MACH_AMIGA:
|
||||
config_amiga();
|
||||
break;
|
||||
#endif
|
||||
#ifdef CONFIG_ATARI
|
||||
case MACH_ATARI:
|
||||
config_atari();
|
||||
break;
|
||||
#endif
|
||||
#ifdef CONFIG_MAC
|
||||
case MACH_MAC:
|
||||
config_mac();
|
||||
break;
|
||||
#endif
|
||||
#ifdef CONFIG_SUN3
|
||||
case MACH_SUN3:
|
||||
config_sun3();
|
||||
break;
|
||||
#endif
|
||||
#ifdef CONFIG_APOLLO
|
||||
case MACH_APOLLO:
|
||||
config_apollo();
|
||||
break;
|
||||
#endif
|
||||
#ifdef CONFIG_MVME147
|
||||
case MACH_MVME147:
|
||||
config_mvme147();
|
||||
break;
|
||||
#endif
|
||||
#ifdef CONFIG_MVME16x
|
||||
case MACH_MVME16x:
|
||||
config_mvme16x();
|
||||
break;
|
||||
#endif
|
||||
#ifdef CONFIG_BVME6000
|
||||
case MACH_BVME6000:
|
||||
config_bvme6000();
|
||||
break;
|
||||
#endif
|
||||
#ifdef CONFIG_HP300
|
||||
case MACH_HP300:
|
||||
config_hp300();
|
||||
break;
|
||||
#endif
|
||||
#ifdef CONFIG_Q40
|
||||
case MACH_Q40:
|
||||
config_q40();
|
||||
break;
|
||||
#endif
|
||||
#ifdef CONFIG_SUN3X
|
||||
case MACH_SUN3X:
|
||||
config_sun3x();
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
panic("No configuration setup");
|
||||
}
|
||||
|
||||
#ifdef CONFIG_NATFEAT
|
||||
nf_init();
|
||||
#endif
|
||||
|
||||
paging_init();
|
||||
|
||||
#ifndef CONFIG_SUN3
|
||||
for (i = 1; i < m68k_num_memory; i++)
|
||||
free_bootmem_node(NODE_DATA(i), m68k_memory[i].addr,
|
||||
m68k_memory[i].size);
|
||||
#ifdef CONFIG_BLK_DEV_INITRD
|
||||
if (m68k_ramdisk.size) {
|
||||
reserve_bootmem_node(__virt_to_node(phys_to_virt(m68k_ramdisk.addr)),
|
||||
m68k_ramdisk.addr, m68k_ramdisk.size,
|
||||
BOOTMEM_DEFAULT);
|
||||
initrd_start = (unsigned long)phys_to_virt(m68k_ramdisk.addr);
|
||||
initrd_end = initrd_start + m68k_ramdisk.size;
|
||||
printk("initrd: %08lx - %08lx\n", initrd_start, initrd_end);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ATARI
|
||||
if (MACH_IS_ATARI)
|
||||
atari_stram_reserve_pages((void *)availmem);
|
||||
#endif
|
||||
#ifdef CONFIG_SUN3X
|
||||
if (MACH_IS_SUN3X) {
|
||||
dvma_init();
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* !CONFIG_SUN3 */
|
||||
|
||||
/* set ISA defs early as possible */
|
||||
#if defined(CONFIG_ISA) && defined(MULTI_ISA)
|
||||
if (MACH_IS_Q40) {
|
||||
isa_type = ISA_TYPE_Q40;
|
||||
isa_sex = 0;
|
||||
}
|
||||
#ifdef CONFIG_AMIGA_PCMCIA
|
||||
if (MACH_IS_AMIGA && AMIGAHW_PRESENT(PCMCIA)) {
|
||||
isa_type = ISA_TYPE_AG;
|
||||
isa_sex = 1;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
static int show_cpuinfo(struct seq_file *m, void *v)
|
||||
{
|
||||
const char *cpu, *mmu, *fpu;
|
||||
unsigned long clockfreq, clockfactor;
|
||||
|
||||
#define LOOP_CYCLES_68020 (8)
|
||||
#define LOOP_CYCLES_68030 (8)
|
||||
#define LOOP_CYCLES_68040 (3)
|
||||
#define LOOP_CYCLES_68060 (1)
|
||||
|
||||
if (CPU_IS_020) {
|
||||
cpu = "68020";
|
||||
clockfactor = LOOP_CYCLES_68020;
|
||||
} else if (CPU_IS_030) {
|
||||
cpu = "68030";
|
||||
clockfactor = LOOP_CYCLES_68030;
|
||||
} else if (CPU_IS_040) {
|
||||
cpu = "68040";
|
||||
clockfactor = LOOP_CYCLES_68040;
|
||||
} else if (CPU_IS_060) {
|
||||
cpu = "68060";
|
||||
clockfactor = LOOP_CYCLES_68060;
|
||||
} else {
|
||||
cpu = "680x0";
|
||||
clockfactor = 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_M68KFPU_EMU_ONLY
|
||||
fpu = "none(soft float)";
|
||||
#else
|
||||
if (m68k_fputype & FPU_68881)
|
||||
fpu = "68881";
|
||||
else if (m68k_fputype & FPU_68882)
|
||||
fpu = "68882";
|
||||
else if (m68k_fputype & FPU_68040)
|
||||
fpu = "68040";
|
||||
else if (m68k_fputype & FPU_68060)
|
||||
fpu = "68060";
|
||||
else if (m68k_fputype & FPU_SUNFPA)
|
||||
fpu = "Sun FPA";
|
||||
else
|
||||
fpu = "none";
|
||||
#endif
|
||||
|
||||
if (m68k_mmutype & MMU_68851)
|
||||
mmu = "68851";
|
||||
else if (m68k_mmutype & MMU_68030)
|
||||
mmu = "68030";
|
||||
else if (m68k_mmutype & MMU_68040)
|
||||
mmu = "68040";
|
||||
else if (m68k_mmutype & MMU_68060)
|
||||
mmu = "68060";
|
||||
else if (m68k_mmutype & MMU_SUN3)
|
||||
mmu = "Sun-3";
|
||||
else if (m68k_mmutype & MMU_APOLLO)
|
||||
mmu = "Apollo";
|
||||
else
|
||||
mmu = "unknown";
|
||||
|
||||
clockfreq = loops_per_jiffy * HZ * clockfactor;
|
||||
|
||||
seq_printf(m, "CPU:\t\t%s\n"
|
||||
"MMU:\t\t%s\n"
|
||||
"FPU:\t\t%s\n"
|
||||
"Clocking:\t%lu.%1luMHz\n"
|
||||
"BogoMips:\t%lu.%02lu\n"
|
||||
"Calibration:\t%lu loops\n",
|
||||
cpu, mmu, fpu,
|
||||
clockfreq/1000000,(clockfreq/100000)%10,
|
||||
loops_per_jiffy/(500000/HZ),(loops_per_jiffy/(5000/HZ))%100,
|
||||
loops_per_jiffy);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void *c_start(struct seq_file *m, loff_t *pos)
|
||||
{
|
||||
return *pos < 1 ? (void *)1 : NULL;
|
||||
}
|
||||
static void *c_next(struct seq_file *m, void *v, loff_t *pos)
|
||||
{
|
||||
++*pos;
|
||||
return NULL;
|
||||
}
|
||||
static void c_stop(struct seq_file *m, void *v)
|
||||
{
|
||||
}
|
||||
const struct seq_operations cpuinfo_op = {
|
||||
.start = c_start,
|
||||
.next = c_next,
|
||||
.stop = c_stop,
|
||||
.show = show_cpuinfo,
|
||||
};
|
||||
|
||||
#ifdef CONFIG_PROC_HARDWARE
|
||||
static int hardware_proc_show(struct seq_file *m, void *v)
|
||||
{
|
||||
char model[80];
|
||||
unsigned long mem;
|
||||
int i;
|
||||
|
||||
if (mach_get_model)
|
||||
mach_get_model(model);
|
||||
else
|
||||
strcpy(model, "Unknown m68k");
|
||||
|
||||
seq_printf(m, "Model:\t\t%s\n", model);
|
||||
for (mem = 0, i = 0; i < m68k_num_memory; i++)
|
||||
mem += m68k_memory[i].size;
|
||||
seq_printf(m, "System Memory:\t%ldK\n", mem >> 10);
|
||||
|
||||
if (mach_get_hardware_list)
|
||||
mach_get_hardware_list(m);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int hardware_proc_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
return single_open(file, hardware_proc_show, NULL);
|
||||
}
|
||||
|
||||
static const struct file_operations hardware_proc_fops = {
|
||||
.open = hardware_proc_open,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
.release = single_release,
|
||||
};
|
||||
|
||||
static int __init proc_hardware_init(void)
|
||||
{
|
||||
proc_create("hardware", 0, NULL, &hardware_proc_fops);
|
||||
return 0;
|
||||
}
|
||||
module_init(proc_hardware_init);
|
||||
#endif
|
||||
|
||||
void check_bugs(void)
|
||||
{
|
||||
#ifndef CONFIG_M68KFPU_EMU
|
||||
if (m68k_fputype == 0) {
|
||||
printk(KERN_EMERG "*** YOU DO NOT HAVE A FLOATING POINT UNIT, "
|
||||
"WHICH IS REQUIRED BY LINUX/M68K ***\n");
|
||||
printk(KERN_EMERG "Upgrade your hardware or join the FPU "
|
||||
"emulation project\n");
|
||||
panic("no FPU");
|
||||
}
|
||||
#endif /* !CONFIG_M68KFPU_EMU */
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ADB
|
||||
static int __init adb_probe_sync_enable (char *str) {
|
||||
extern int __adb_probe_sync;
|
||||
__adb_probe_sync = 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
__setup("adb_sync", adb_probe_sync_enable);
|
||||
#endif /* CONFIG_ADB */
|
File diff suppressed because it is too large
Load Diff
1017
arch/m68k/kernel/signal_mm.c
Normal file
1017
arch/m68k/kernel/signal_mm.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,546 +1,5 @@
|
||||
/*
|
||||
* linux/arch/m68k/kernel/sys_m68k.c
|
||||
*
|
||||
* This file contains various random system calls that
|
||||
* have a non-standard calling sequence on the Linux/m68k
|
||||
* platform.
|
||||
*/
|
||||
|
||||
#include <linux/capability.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/smp.h>
|
||||
#include <linux/sem.h>
|
||||
#include <linux/msg.h>
|
||||
#include <linux/shm.h>
|
||||
#include <linux/stat.h>
|
||||
#include <linux/syscalls.h>
|
||||
#include <linux/mman.h>
|
||||
#include <linux/file.h>
|
||||
#include <linux/ipc.h>
|
||||
|
||||
#include <asm/setup.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/cachectl.h>
|
||||
#include <asm/traps.h>
|
||||
#include <asm/page.h>
|
||||
#include <asm/unistd.h>
|
||||
#include <linux/elf.h>
|
||||
#include <asm/tlb.h>
|
||||
|
||||
asmlinkage int do_page_fault(struct pt_regs *regs, unsigned long address,
|
||||
unsigned long error_code);
|
||||
|
||||
asmlinkage long sys_mmap2(unsigned long addr, unsigned long len,
|
||||
unsigned long prot, unsigned long flags,
|
||||
unsigned long fd, unsigned long pgoff)
|
||||
{
|
||||
/*
|
||||
* This is wrong for sun3 - there PAGE_SIZE is 8Kb,
|
||||
* so we need to shift the argument down by 1; m68k mmap64(3)
|
||||
* (in libc) expects the last argument of mmap2 in 4Kb units.
|
||||
*/
|
||||
return sys_mmap_pgoff(addr, len, prot, flags, fd, pgoff);
|
||||
}
|
||||
|
||||
/* Convert virtual (user) address VADDR to physical address PADDR */
|
||||
#define virt_to_phys_040(vaddr) \
|
||||
({ \
|
||||
unsigned long _mmusr, _paddr; \
|
||||
\
|
||||
__asm__ __volatile__ (".chip 68040\n\t" \
|
||||
"ptestr (%1)\n\t" \
|
||||
"movec %%mmusr,%0\n\t" \
|
||||
".chip 68k" \
|
||||
: "=r" (_mmusr) \
|
||||
: "a" (vaddr)); \
|
||||
_paddr = (_mmusr & MMU_R_040) ? (_mmusr & PAGE_MASK) : 0; \
|
||||
_paddr; \
|
||||
})
|
||||
|
||||
static inline int
|
||||
cache_flush_040 (unsigned long addr, int scope, int cache, unsigned long len)
|
||||
{
|
||||
unsigned long paddr, i;
|
||||
|
||||
switch (scope)
|
||||
{
|
||||
case FLUSH_SCOPE_ALL:
|
||||
switch (cache)
|
||||
{
|
||||
case FLUSH_CACHE_DATA:
|
||||
/* This nop is needed for some broken versions of the 68040. */
|
||||
__asm__ __volatile__ ("nop\n\t"
|
||||
".chip 68040\n\t"
|
||||
"cpusha %dc\n\t"
|
||||
".chip 68k");
|
||||
break;
|
||||
case FLUSH_CACHE_INSN:
|
||||
__asm__ __volatile__ ("nop\n\t"
|
||||
".chip 68040\n\t"
|
||||
"cpusha %ic\n\t"
|
||||
".chip 68k");
|
||||
break;
|
||||
default:
|
||||
case FLUSH_CACHE_BOTH:
|
||||
__asm__ __volatile__ ("nop\n\t"
|
||||
".chip 68040\n\t"
|
||||
"cpusha %bc\n\t"
|
||||
".chip 68k");
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case FLUSH_SCOPE_LINE:
|
||||
/* Find the physical address of the first mapped page in the
|
||||
address range. */
|
||||
if ((paddr = virt_to_phys_040(addr))) {
|
||||
paddr += addr & ~(PAGE_MASK | 15);
|
||||
len = (len + (addr & 15) + 15) >> 4;
|
||||
} else {
|
||||
unsigned long tmp = PAGE_SIZE - (addr & ~PAGE_MASK);
|
||||
|
||||
if (len <= tmp)
|
||||
return 0;
|
||||
addr += tmp;
|
||||
len -= tmp;
|
||||
tmp = PAGE_SIZE;
|
||||
for (;;)
|
||||
{
|
||||
if ((paddr = virt_to_phys_040(addr)))
|
||||
break;
|
||||
if (len <= tmp)
|
||||
return 0;
|
||||
addr += tmp;
|
||||
len -= tmp;
|
||||
}
|
||||
len = (len + 15) >> 4;
|
||||
}
|
||||
i = (PAGE_SIZE - (paddr & ~PAGE_MASK)) >> 4;
|
||||
while (len--)
|
||||
{
|
||||
switch (cache)
|
||||
{
|
||||
case FLUSH_CACHE_DATA:
|
||||
__asm__ __volatile__ ("nop\n\t"
|
||||
".chip 68040\n\t"
|
||||
"cpushl %%dc,(%0)\n\t"
|
||||
".chip 68k"
|
||||
: : "a" (paddr));
|
||||
break;
|
||||
case FLUSH_CACHE_INSN:
|
||||
__asm__ __volatile__ ("nop\n\t"
|
||||
".chip 68040\n\t"
|
||||
"cpushl %%ic,(%0)\n\t"
|
||||
".chip 68k"
|
||||
: : "a" (paddr));
|
||||
break;
|
||||
default:
|
||||
case FLUSH_CACHE_BOTH:
|
||||
__asm__ __volatile__ ("nop\n\t"
|
||||
".chip 68040\n\t"
|
||||
"cpushl %%bc,(%0)\n\t"
|
||||
".chip 68k"
|
||||
: : "a" (paddr));
|
||||
break;
|
||||
}
|
||||
if (!--i && len)
|
||||
{
|
||||
/*
|
||||
* No need to page align here since it is done by
|
||||
* virt_to_phys_040().
|
||||
*/
|
||||
addr += PAGE_SIZE;
|
||||
i = PAGE_SIZE / 16;
|
||||
/* Recompute physical address when crossing a page
|
||||
boundary. */
|
||||
for (;;)
|
||||
{
|
||||
if ((paddr = virt_to_phys_040(addr)))
|
||||
break;
|
||||
if (len <= i)
|
||||
return 0;
|
||||
len -= i;
|
||||
addr += PAGE_SIZE;
|
||||
}
|
||||
}
|
||||
else
|
||||
paddr += 16;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
case FLUSH_SCOPE_PAGE:
|
||||
len += (addr & ~PAGE_MASK) + (PAGE_SIZE - 1);
|
||||
for (len >>= PAGE_SHIFT; len--; addr += PAGE_SIZE)
|
||||
{
|
||||
if (!(paddr = virt_to_phys_040(addr)))
|
||||
continue;
|
||||
switch (cache)
|
||||
{
|
||||
case FLUSH_CACHE_DATA:
|
||||
__asm__ __volatile__ ("nop\n\t"
|
||||
".chip 68040\n\t"
|
||||
"cpushp %%dc,(%0)\n\t"
|
||||
".chip 68k"
|
||||
: : "a" (paddr));
|
||||
break;
|
||||
case FLUSH_CACHE_INSN:
|
||||
__asm__ __volatile__ ("nop\n\t"
|
||||
".chip 68040\n\t"
|
||||
"cpushp %%ic,(%0)\n\t"
|
||||
".chip 68k"
|
||||
: : "a" (paddr));
|
||||
break;
|
||||
default:
|
||||
case FLUSH_CACHE_BOTH:
|
||||
__asm__ __volatile__ ("nop\n\t"
|
||||
".chip 68040\n\t"
|
||||
"cpushp %%bc,(%0)\n\t"
|
||||
".chip 68k"
|
||||
: : "a" (paddr));
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define virt_to_phys_060(vaddr) \
|
||||
({ \
|
||||
unsigned long paddr; \
|
||||
__asm__ __volatile__ (".chip 68060\n\t" \
|
||||
"plpar (%0)\n\t" \
|
||||
".chip 68k" \
|
||||
: "=a" (paddr) \
|
||||
: "0" (vaddr)); \
|
||||
(paddr); /* XXX */ \
|
||||
})
|
||||
|
||||
static inline int
|
||||
cache_flush_060 (unsigned long addr, int scope, int cache, unsigned long len)
|
||||
{
|
||||
unsigned long paddr, i;
|
||||
|
||||
/*
|
||||
* 68060 manual says:
|
||||
* cpush %dc : flush DC, remains valid (with our %cacr setup)
|
||||
* cpush %ic : invalidate IC
|
||||
* cpush %bc : flush DC + invalidate IC
|
||||
*/
|
||||
switch (scope)
|
||||
{
|
||||
case FLUSH_SCOPE_ALL:
|
||||
switch (cache)
|
||||
{
|
||||
case FLUSH_CACHE_DATA:
|
||||
__asm__ __volatile__ (".chip 68060\n\t"
|
||||
"cpusha %dc\n\t"
|
||||
".chip 68k");
|
||||
break;
|
||||
case FLUSH_CACHE_INSN:
|
||||
__asm__ __volatile__ (".chip 68060\n\t"
|
||||
"cpusha %ic\n\t"
|
||||
".chip 68k");
|
||||
break;
|
||||
default:
|
||||
case FLUSH_CACHE_BOTH:
|
||||
__asm__ __volatile__ (".chip 68060\n\t"
|
||||
"cpusha %bc\n\t"
|
||||
".chip 68k");
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case FLUSH_SCOPE_LINE:
|
||||
/* Find the physical address of the first mapped page in the
|
||||
address range. */
|
||||
len += addr & 15;
|
||||
addr &= -16;
|
||||
if (!(paddr = virt_to_phys_060(addr))) {
|
||||
unsigned long tmp = PAGE_SIZE - (addr & ~PAGE_MASK);
|
||||
|
||||
if (len <= tmp)
|
||||
return 0;
|
||||
addr += tmp;
|
||||
len -= tmp;
|
||||
tmp = PAGE_SIZE;
|
||||
for (;;)
|
||||
{
|
||||
if ((paddr = virt_to_phys_060(addr)))
|
||||
break;
|
||||
if (len <= tmp)
|
||||
return 0;
|
||||
addr += tmp;
|
||||
len -= tmp;
|
||||
}
|
||||
}
|
||||
len = (len + 15) >> 4;
|
||||
i = (PAGE_SIZE - (paddr & ~PAGE_MASK)) >> 4;
|
||||
while (len--)
|
||||
{
|
||||
switch (cache)
|
||||
{
|
||||
case FLUSH_CACHE_DATA:
|
||||
__asm__ __volatile__ (".chip 68060\n\t"
|
||||
"cpushl %%dc,(%0)\n\t"
|
||||
".chip 68k"
|
||||
: : "a" (paddr));
|
||||
break;
|
||||
case FLUSH_CACHE_INSN:
|
||||
__asm__ __volatile__ (".chip 68060\n\t"
|
||||
"cpushl %%ic,(%0)\n\t"
|
||||
".chip 68k"
|
||||
: : "a" (paddr));
|
||||
break;
|
||||
default:
|
||||
case FLUSH_CACHE_BOTH:
|
||||
__asm__ __volatile__ (".chip 68060\n\t"
|
||||
"cpushl %%bc,(%0)\n\t"
|
||||
".chip 68k"
|
||||
: : "a" (paddr));
|
||||
break;
|
||||
}
|
||||
if (!--i && len)
|
||||
{
|
||||
|
||||
/*
|
||||
* We just want to jump to the first cache line
|
||||
* in the next page.
|
||||
*/
|
||||
addr += PAGE_SIZE;
|
||||
addr &= PAGE_MASK;
|
||||
|
||||
i = PAGE_SIZE / 16;
|
||||
/* Recompute physical address when crossing a page
|
||||
boundary. */
|
||||
for (;;)
|
||||
{
|
||||
if ((paddr = virt_to_phys_060(addr)))
|
||||
break;
|
||||
if (len <= i)
|
||||
return 0;
|
||||
len -= i;
|
||||
addr += PAGE_SIZE;
|
||||
}
|
||||
}
|
||||
else
|
||||
paddr += 16;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
case FLUSH_SCOPE_PAGE:
|
||||
len += (addr & ~PAGE_MASK) + (PAGE_SIZE - 1);
|
||||
addr &= PAGE_MASK; /* Workaround for bug in some
|
||||
revisions of the 68060 */
|
||||
for (len >>= PAGE_SHIFT; len--; addr += PAGE_SIZE)
|
||||
{
|
||||
if (!(paddr = virt_to_phys_060(addr)))
|
||||
continue;
|
||||
switch (cache)
|
||||
{
|
||||
case FLUSH_CACHE_DATA:
|
||||
__asm__ __volatile__ (".chip 68060\n\t"
|
||||
"cpushp %%dc,(%0)\n\t"
|
||||
".chip 68k"
|
||||
: : "a" (paddr));
|
||||
break;
|
||||
case FLUSH_CACHE_INSN:
|
||||
__asm__ __volatile__ (".chip 68060\n\t"
|
||||
"cpushp %%ic,(%0)\n\t"
|
||||
".chip 68k"
|
||||
: : "a" (paddr));
|
||||
break;
|
||||
default:
|
||||
case FLUSH_CACHE_BOTH:
|
||||
__asm__ __volatile__ (".chip 68060\n\t"
|
||||
"cpushp %%bc,(%0)\n\t"
|
||||
".chip 68k"
|
||||
: : "a" (paddr));
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* sys_cacheflush -- flush (part of) the processor cache. */
|
||||
asmlinkage int
|
||||
sys_cacheflush (unsigned long addr, int scope, int cache, unsigned long len)
|
||||
{
|
||||
struct vm_area_struct *vma;
|
||||
int ret = -EINVAL;
|
||||
|
||||
if (scope < FLUSH_SCOPE_LINE || scope > FLUSH_SCOPE_ALL ||
|
||||
cache & ~FLUSH_CACHE_BOTH)
|
||||
goto out;
|
||||
|
||||
if (scope == FLUSH_SCOPE_ALL) {
|
||||
/* Only the superuser may explicitly flush the whole cache. */
|
||||
ret = -EPERM;
|
||||
if (!capable(CAP_SYS_ADMIN))
|
||||
goto out;
|
||||
} else {
|
||||
/*
|
||||
* Verify that the specified address region actually belongs
|
||||
* to this process.
|
||||
*/
|
||||
vma = find_vma (current->mm, addr);
|
||||
ret = -EINVAL;
|
||||
/* Check for overflow. */
|
||||
if (addr + len < addr)
|
||||
goto out;
|
||||
if (vma == NULL || addr < vma->vm_start || addr + len > vma->vm_end)
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (CPU_IS_020_OR_030) {
|
||||
if (scope == FLUSH_SCOPE_LINE && len < 256) {
|
||||
unsigned long cacr;
|
||||
__asm__ ("movec %%cacr, %0" : "=r" (cacr));
|
||||
if (cache & FLUSH_CACHE_INSN)
|
||||
cacr |= 4;
|
||||
if (cache & FLUSH_CACHE_DATA)
|
||||
cacr |= 0x400;
|
||||
len >>= 2;
|
||||
while (len--) {
|
||||
__asm__ __volatile__ ("movec %1, %%caar\n\t"
|
||||
"movec %0, %%cacr"
|
||||
: /* no outputs */
|
||||
: "r" (cacr), "r" (addr));
|
||||
addr += 4;
|
||||
}
|
||||
} else {
|
||||
/* Flush the whole cache, even if page granularity requested. */
|
||||
unsigned long cacr;
|
||||
__asm__ ("movec %%cacr, %0" : "=r" (cacr));
|
||||
if (cache & FLUSH_CACHE_INSN)
|
||||
cacr |= 8;
|
||||
if (cache & FLUSH_CACHE_DATA)
|
||||
cacr |= 0x800;
|
||||
__asm__ __volatile__ ("movec %0, %%cacr" : : "r" (cacr));
|
||||
}
|
||||
ret = 0;
|
||||
goto out;
|
||||
} else {
|
||||
/*
|
||||
* 040 or 060: don't blindly trust 'scope', someone could
|
||||
* try to flush a few megs of memory.
|
||||
*/
|
||||
|
||||
if (len>=3*PAGE_SIZE && scope<FLUSH_SCOPE_PAGE)
|
||||
scope=FLUSH_SCOPE_PAGE;
|
||||
if (len>=10*PAGE_SIZE && scope<FLUSH_SCOPE_ALL)
|
||||
scope=FLUSH_SCOPE_ALL;
|
||||
if (CPU_IS_040) {
|
||||
ret = cache_flush_040 (addr, scope, cache, len);
|
||||
} else if (CPU_IS_060) {
|
||||
ret = cache_flush_060 (addr, scope, cache, len);
|
||||
}
|
||||
}
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
asmlinkage int sys_getpagesize(void)
|
||||
{
|
||||
return PAGE_SIZE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Do a system call from kernel instead of calling sys_execve so we
|
||||
* end up with proper pt_regs.
|
||||
*/
|
||||
int kernel_execve(const char *filename,
|
||||
const char *const argv[],
|
||||
const char *const envp[])
|
||||
{
|
||||
register long __res asm ("%d0") = __NR_execve;
|
||||
register long __a asm ("%d1") = (long)(filename);
|
||||
register long __b asm ("%d2") = (long)(argv);
|
||||
register long __c asm ("%d3") = (long)(envp);
|
||||
asm volatile ("trap #0" : "+d" (__res)
|
||||
: "d" (__a), "d" (__b), "d" (__c));
|
||||
return __res;
|
||||
}
|
||||
|
||||
asmlinkage unsigned long sys_get_thread_area(void)
|
||||
{
|
||||
return current_thread_info()->tp_value;
|
||||
}
|
||||
|
||||
asmlinkage int sys_set_thread_area(unsigned long tp)
|
||||
{
|
||||
current_thread_info()->tp_value = tp;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* This syscall gets its arguments in A0 (mem), D2 (oldval) and
|
||||
D1 (newval). */
|
||||
asmlinkage int
|
||||
sys_atomic_cmpxchg_32(unsigned long newval, int oldval, int d3, int d4, int d5,
|
||||
unsigned long __user * mem)
|
||||
{
|
||||
/* This was borrowed from ARM's implementation. */
|
||||
for (;;) {
|
||||
struct mm_struct *mm = current->mm;
|
||||
pgd_t *pgd;
|
||||
pmd_t *pmd;
|
||||
pte_t *pte;
|
||||
spinlock_t *ptl;
|
||||
unsigned long mem_value;
|
||||
|
||||
down_read(&mm->mmap_sem);
|
||||
pgd = pgd_offset(mm, (unsigned long)mem);
|
||||
if (!pgd_present(*pgd))
|
||||
goto bad_access;
|
||||
pmd = pmd_offset(pgd, (unsigned long)mem);
|
||||
if (!pmd_present(*pmd))
|
||||
goto bad_access;
|
||||
pte = pte_offset_map_lock(mm, pmd, (unsigned long)mem, &ptl);
|
||||
if (!pte_present(*pte) || !pte_dirty(*pte)
|
||||
|| !pte_write(*pte)) {
|
||||
pte_unmap_unlock(pte, ptl);
|
||||
goto bad_access;
|
||||
}
|
||||
|
||||
mem_value = *mem;
|
||||
if (mem_value == oldval)
|
||||
*mem = newval;
|
||||
|
||||
pte_unmap_unlock(pte, ptl);
|
||||
up_read(&mm->mmap_sem);
|
||||
return mem_value;
|
||||
|
||||
bad_access:
|
||||
up_read(&mm->mmap_sem);
|
||||
/* This is not necessarily a bad access, we can get here if
|
||||
a memory we're trying to write to should be copied-on-write.
|
||||
Make the kernel do the necessary page stuff, then re-iterate.
|
||||
Simulate a write access fault to do that. */
|
||||
{
|
||||
/* The first argument of the function corresponds to
|
||||
D1, which is the first field of struct pt_regs. */
|
||||
struct pt_regs *fp = (struct pt_regs *)&newval;
|
||||
|
||||
/* '3' is an RMW flag. */
|
||||
if (do_page_fault(fp, (unsigned long)mem, 3))
|
||||
/* If the do_page_fault() failed, we don't
|
||||
have anything meaningful to return.
|
||||
There should be a SIGSEGV pending for
|
||||
the process. */
|
||||
return 0xdeadbeef;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
asmlinkage int sys_atomic_barrier(void)
|
||||
{
|
||||
/* no code needed for uniprocs */
|
||||
return 0;
|
||||
}
|
||||
#ifdef CONFIG_MMU
|
||||
#include "sys_m68k_mm.c"
|
||||
#else
|
||||
#include "sys_m68k_no.c"
|
||||
#endif
|
||||
|
546
arch/m68k/kernel/sys_m68k_mm.c
Normal file
546
arch/m68k/kernel/sys_m68k_mm.c
Normal file
@ -0,0 +1,546 @@
|
||||
/*
|
||||
* linux/arch/m68k/kernel/sys_m68k.c
|
||||
*
|
||||
* This file contains various random system calls that
|
||||
* have a non-standard calling sequence on the Linux/m68k
|
||||
* platform.
|
||||
*/
|
||||
|
||||
#include <linux/capability.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/smp.h>
|
||||
#include <linux/sem.h>
|
||||
#include <linux/msg.h>
|
||||
#include <linux/shm.h>
|
||||
#include <linux/stat.h>
|
||||
#include <linux/syscalls.h>
|
||||
#include <linux/mman.h>
|
||||
#include <linux/file.h>
|
||||
#include <linux/ipc.h>
|
||||
|
||||
#include <asm/setup.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/cachectl.h>
|
||||
#include <asm/traps.h>
|
||||
#include <asm/page.h>
|
||||
#include <asm/unistd.h>
|
||||
#include <linux/elf.h>
|
||||
#include <asm/tlb.h>
|
||||
|
||||
asmlinkage int do_page_fault(struct pt_regs *regs, unsigned long address,
|
||||
unsigned long error_code);
|
||||
|
||||
asmlinkage long sys_mmap2(unsigned long addr, unsigned long len,
|
||||
unsigned long prot, unsigned long flags,
|
||||
unsigned long fd, unsigned long pgoff)
|
||||
{
|
||||
/*
|
||||
* This is wrong for sun3 - there PAGE_SIZE is 8Kb,
|
||||
* so we need to shift the argument down by 1; m68k mmap64(3)
|
||||
* (in libc) expects the last argument of mmap2 in 4Kb units.
|
||||
*/
|
||||
return sys_mmap_pgoff(addr, len, prot, flags, fd, pgoff);
|
||||
}
|
||||
|
||||
/* Convert virtual (user) address VADDR to physical address PADDR */
|
||||
#define virt_to_phys_040(vaddr) \
|
||||
({ \
|
||||
unsigned long _mmusr, _paddr; \
|
||||
\
|
||||
__asm__ __volatile__ (".chip 68040\n\t" \
|
||||
"ptestr (%1)\n\t" \
|
||||
"movec %%mmusr,%0\n\t" \
|
||||
".chip 68k" \
|
||||
: "=r" (_mmusr) \
|
||||
: "a" (vaddr)); \
|
||||
_paddr = (_mmusr & MMU_R_040) ? (_mmusr & PAGE_MASK) : 0; \
|
||||
_paddr; \
|
||||
})
|
||||
|
||||
static inline int
|
||||
cache_flush_040 (unsigned long addr, int scope, int cache, unsigned long len)
|
||||
{
|
||||
unsigned long paddr, i;
|
||||
|
||||
switch (scope)
|
||||
{
|
||||
case FLUSH_SCOPE_ALL:
|
||||
switch (cache)
|
||||
{
|
||||
case FLUSH_CACHE_DATA:
|
||||
/* This nop is needed for some broken versions of the 68040. */
|
||||
__asm__ __volatile__ ("nop\n\t"
|
||||
".chip 68040\n\t"
|
||||
"cpusha %dc\n\t"
|
||||
".chip 68k");
|
||||
break;
|
||||
case FLUSH_CACHE_INSN:
|
||||
__asm__ __volatile__ ("nop\n\t"
|
||||
".chip 68040\n\t"
|
||||
"cpusha %ic\n\t"
|
||||
".chip 68k");
|
||||
break;
|
||||
default:
|
||||
case FLUSH_CACHE_BOTH:
|
||||
__asm__ __volatile__ ("nop\n\t"
|
||||
".chip 68040\n\t"
|
||||
"cpusha %bc\n\t"
|
||||
".chip 68k");
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case FLUSH_SCOPE_LINE:
|
||||
/* Find the physical address of the first mapped page in the
|
||||
address range. */
|
||||
if ((paddr = virt_to_phys_040(addr))) {
|
||||
paddr += addr & ~(PAGE_MASK | 15);
|
||||
len = (len + (addr & 15) + 15) >> 4;
|
||||
} else {
|
||||
unsigned long tmp = PAGE_SIZE - (addr & ~PAGE_MASK);
|
||||
|
||||
if (len <= tmp)
|
||||
return 0;
|
||||
addr += tmp;
|
||||
len -= tmp;
|
||||
tmp = PAGE_SIZE;
|
||||
for (;;)
|
||||
{
|
||||
if ((paddr = virt_to_phys_040(addr)))
|
||||
break;
|
||||
if (len <= tmp)
|
||||
return 0;
|
||||
addr += tmp;
|
||||
len -= tmp;
|
||||
}
|
||||
len = (len + 15) >> 4;
|
||||
}
|
||||
i = (PAGE_SIZE - (paddr & ~PAGE_MASK)) >> 4;
|
||||
while (len--)
|
||||
{
|
||||
switch (cache)
|
||||
{
|
||||
case FLUSH_CACHE_DATA:
|
||||
__asm__ __volatile__ ("nop\n\t"
|
||||
".chip 68040\n\t"
|
||||
"cpushl %%dc,(%0)\n\t"
|
||||
".chip 68k"
|
||||
: : "a" (paddr));
|
||||
break;
|
||||
case FLUSH_CACHE_INSN:
|
||||
__asm__ __volatile__ ("nop\n\t"
|
||||
".chip 68040\n\t"
|
||||
"cpushl %%ic,(%0)\n\t"
|
||||
".chip 68k"
|
||||
: : "a" (paddr));
|
||||
break;
|
||||
default:
|
||||
case FLUSH_CACHE_BOTH:
|
||||
__asm__ __volatile__ ("nop\n\t"
|
||||
".chip 68040\n\t"
|
||||
"cpushl %%bc,(%0)\n\t"
|
||||
".chip 68k"
|
||||
: : "a" (paddr));
|
||||
break;
|
||||
}
|
||||
if (!--i && len)
|
||||
{
|
||||
/*
|
||||
* No need to page align here since it is done by
|
||||
* virt_to_phys_040().
|
||||
*/
|
||||
addr += PAGE_SIZE;
|
||||
i = PAGE_SIZE / 16;
|
||||
/* Recompute physical address when crossing a page
|
||||
boundary. */
|
||||
for (;;)
|
||||
{
|
||||
if ((paddr = virt_to_phys_040(addr)))
|
||||
break;
|
||||
if (len <= i)
|
||||
return 0;
|
||||
len -= i;
|
||||
addr += PAGE_SIZE;
|
||||
}
|
||||
}
|
||||
else
|
||||
paddr += 16;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
case FLUSH_SCOPE_PAGE:
|
||||
len += (addr & ~PAGE_MASK) + (PAGE_SIZE - 1);
|
||||
for (len >>= PAGE_SHIFT; len--; addr += PAGE_SIZE)
|
||||
{
|
||||
if (!(paddr = virt_to_phys_040(addr)))
|
||||
continue;
|
||||
switch (cache)
|
||||
{
|
||||
case FLUSH_CACHE_DATA:
|
||||
__asm__ __volatile__ ("nop\n\t"
|
||||
".chip 68040\n\t"
|
||||
"cpushp %%dc,(%0)\n\t"
|
||||
".chip 68k"
|
||||
: : "a" (paddr));
|
||||
break;
|
||||
case FLUSH_CACHE_INSN:
|
||||
__asm__ __volatile__ ("nop\n\t"
|
||||
".chip 68040\n\t"
|
||||
"cpushp %%ic,(%0)\n\t"
|
||||
".chip 68k"
|
||||
: : "a" (paddr));
|
||||
break;
|
||||
default:
|
||||
case FLUSH_CACHE_BOTH:
|
||||
__asm__ __volatile__ ("nop\n\t"
|
||||
".chip 68040\n\t"
|
||||
"cpushp %%bc,(%0)\n\t"
|
||||
".chip 68k"
|
||||
: : "a" (paddr));
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define virt_to_phys_060(vaddr) \
|
||||
({ \
|
||||
unsigned long paddr; \
|
||||
__asm__ __volatile__ (".chip 68060\n\t" \
|
||||
"plpar (%0)\n\t" \
|
||||
".chip 68k" \
|
||||
: "=a" (paddr) \
|
||||
: "0" (vaddr)); \
|
||||
(paddr); /* XXX */ \
|
||||
})
|
||||
|
||||
static inline int
|
||||
cache_flush_060 (unsigned long addr, int scope, int cache, unsigned long len)
|
||||
{
|
||||
unsigned long paddr, i;
|
||||
|
||||
/*
|
||||
* 68060 manual says:
|
||||
* cpush %dc : flush DC, remains valid (with our %cacr setup)
|
||||
* cpush %ic : invalidate IC
|
||||
* cpush %bc : flush DC + invalidate IC
|
||||
*/
|
||||
switch (scope)
|
||||
{
|
||||
case FLUSH_SCOPE_ALL:
|
||||
switch (cache)
|
||||
{
|
||||
case FLUSH_CACHE_DATA:
|
||||
__asm__ __volatile__ (".chip 68060\n\t"
|
||||
"cpusha %dc\n\t"
|
||||
".chip 68k");
|
||||
break;
|
||||
case FLUSH_CACHE_INSN:
|
||||
__asm__ __volatile__ (".chip 68060\n\t"
|
||||
"cpusha %ic\n\t"
|
||||
".chip 68k");
|
||||
break;
|
||||
default:
|
||||
case FLUSH_CACHE_BOTH:
|
||||
__asm__ __volatile__ (".chip 68060\n\t"
|
||||
"cpusha %bc\n\t"
|
||||
".chip 68k");
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case FLUSH_SCOPE_LINE:
|
||||
/* Find the physical address of the first mapped page in the
|
||||
address range. */
|
||||
len += addr & 15;
|
||||
addr &= -16;
|
||||
if (!(paddr = virt_to_phys_060(addr))) {
|
||||
unsigned long tmp = PAGE_SIZE - (addr & ~PAGE_MASK);
|
||||
|
||||
if (len <= tmp)
|
||||
return 0;
|
||||
addr += tmp;
|
||||
len -= tmp;
|
||||
tmp = PAGE_SIZE;
|
||||
for (;;)
|
||||
{
|
||||
if ((paddr = virt_to_phys_060(addr)))
|
||||
break;
|
||||
if (len <= tmp)
|
||||
return 0;
|
||||
addr += tmp;
|
||||
len -= tmp;
|
||||
}
|
||||
}
|
||||
len = (len + 15) >> 4;
|
||||
i = (PAGE_SIZE - (paddr & ~PAGE_MASK)) >> 4;
|
||||
while (len--)
|
||||
{
|
||||
switch (cache)
|
||||
{
|
||||
case FLUSH_CACHE_DATA:
|
||||
__asm__ __volatile__ (".chip 68060\n\t"
|
||||
"cpushl %%dc,(%0)\n\t"
|
||||
".chip 68k"
|
||||
: : "a" (paddr));
|
||||
break;
|
||||
case FLUSH_CACHE_INSN:
|
||||
__asm__ __volatile__ (".chip 68060\n\t"
|
||||
"cpushl %%ic,(%0)\n\t"
|
||||
".chip 68k"
|
||||
: : "a" (paddr));
|
||||
break;
|
||||
default:
|
||||
case FLUSH_CACHE_BOTH:
|
||||
__asm__ __volatile__ (".chip 68060\n\t"
|
||||
"cpushl %%bc,(%0)\n\t"
|
||||
".chip 68k"
|
||||
: : "a" (paddr));
|
||||
break;
|
||||
}
|
||||
if (!--i && len)
|
||||
{
|
||||
|
||||
/*
|
||||
* We just want to jump to the first cache line
|
||||
* in the next page.
|
||||
*/
|
||||
addr += PAGE_SIZE;
|
||||
addr &= PAGE_MASK;
|
||||
|
||||
i = PAGE_SIZE / 16;
|
||||
/* Recompute physical address when crossing a page
|
||||
boundary. */
|
||||
for (;;)
|
||||
{
|
||||
if ((paddr = virt_to_phys_060(addr)))
|
||||
break;
|
||||
if (len <= i)
|
||||
return 0;
|
||||
len -= i;
|
||||
addr += PAGE_SIZE;
|
||||
}
|
||||
}
|
||||
else
|
||||
paddr += 16;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
case FLUSH_SCOPE_PAGE:
|
||||
len += (addr & ~PAGE_MASK) + (PAGE_SIZE - 1);
|
||||
addr &= PAGE_MASK; /* Workaround for bug in some
|
||||
revisions of the 68060 */
|
||||
for (len >>= PAGE_SHIFT; len--; addr += PAGE_SIZE)
|
||||
{
|
||||
if (!(paddr = virt_to_phys_060(addr)))
|
||||
continue;
|
||||
switch (cache)
|
||||
{
|
||||
case FLUSH_CACHE_DATA:
|
||||
__asm__ __volatile__ (".chip 68060\n\t"
|
||||
"cpushp %%dc,(%0)\n\t"
|
||||
".chip 68k"
|
||||
: : "a" (paddr));
|
||||
break;
|
||||
case FLUSH_CACHE_INSN:
|
||||
__asm__ __volatile__ (".chip 68060\n\t"
|
||||
"cpushp %%ic,(%0)\n\t"
|
||||
".chip 68k"
|
||||
: : "a" (paddr));
|
||||
break;
|
||||
default:
|
||||
case FLUSH_CACHE_BOTH:
|
||||
__asm__ __volatile__ (".chip 68060\n\t"
|
||||
"cpushp %%bc,(%0)\n\t"
|
||||
".chip 68k"
|
||||
: : "a" (paddr));
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* sys_cacheflush -- flush (part of) the processor cache. */
|
||||
asmlinkage int
|
||||
sys_cacheflush (unsigned long addr, int scope, int cache, unsigned long len)
|
||||
{
|
||||
struct vm_area_struct *vma;
|
||||
int ret = -EINVAL;
|
||||
|
||||
if (scope < FLUSH_SCOPE_LINE || scope > FLUSH_SCOPE_ALL ||
|
||||
cache & ~FLUSH_CACHE_BOTH)
|
||||
goto out;
|
||||
|
||||
if (scope == FLUSH_SCOPE_ALL) {
|
||||
/* Only the superuser may explicitly flush the whole cache. */
|
||||
ret = -EPERM;
|
||||
if (!capable(CAP_SYS_ADMIN))
|
||||
goto out;
|
||||
} else {
|
||||
/*
|
||||
* Verify that the specified address region actually belongs
|
||||
* to this process.
|
||||
*/
|
||||
vma = find_vma (current->mm, addr);
|
||||
ret = -EINVAL;
|
||||
/* Check for overflow. */
|
||||
if (addr + len < addr)
|
||||
goto out;
|
||||
if (vma == NULL || addr < vma->vm_start || addr + len > vma->vm_end)
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (CPU_IS_020_OR_030) {
|
||||
if (scope == FLUSH_SCOPE_LINE && len < 256) {
|
||||
unsigned long cacr;
|
||||
__asm__ ("movec %%cacr, %0" : "=r" (cacr));
|
||||
if (cache & FLUSH_CACHE_INSN)
|
||||
cacr |= 4;
|
||||
if (cache & FLUSH_CACHE_DATA)
|
||||
cacr |= 0x400;
|
||||
len >>= 2;
|
||||
while (len--) {
|
||||
__asm__ __volatile__ ("movec %1, %%caar\n\t"
|
||||
"movec %0, %%cacr"
|
||||
: /* no outputs */
|
||||
: "r" (cacr), "r" (addr));
|
||||
addr += 4;
|
||||
}
|
||||
} else {
|
||||
/* Flush the whole cache, even if page granularity requested. */
|
||||
unsigned long cacr;
|
||||
__asm__ ("movec %%cacr, %0" : "=r" (cacr));
|
||||
if (cache & FLUSH_CACHE_INSN)
|
||||
cacr |= 8;
|
||||
if (cache & FLUSH_CACHE_DATA)
|
||||
cacr |= 0x800;
|
||||
__asm__ __volatile__ ("movec %0, %%cacr" : : "r" (cacr));
|
||||
}
|
||||
ret = 0;
|
||||
goto out;
|
||||
} else {
|
||||
/*
|
||||
* 040 or 060: don't blindly trust 'scope', someone could
|
||||
* try to flush a few megs of memory.
|
||||
*/
|
||||
|
||||
if (len>=3*PAGE_SIZE && scope<FLUSH_SCOPE_PAGE)
|
||||
scope=FLUSH_SCOPE_PAGE;
|
||||
if (len>=10*PAGE_SIZE && scope<FLUSH_SCOPE_ALL)
|
||||
scope=FLUSH_SCOPE_ALL;
|
||||
if (CPU_IS_040) {
|
||||
ret = cache_flush_040 (addr, scope, cache, len);
|
||||
} else if (CPU_IS_060) {
|
||||
ret = cache_flush_060 (addr, scope, cache, len);
|
||||
}
|
||||
}
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
asmlinkage int sys_getpagesize(void)
|
||||
{
|
||||
return PAGE_SIZE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Do a system call from kernel instead of calling sys_execve so we
|
||||
* end up with proper pt_regs.
|
||||
*/
|
||||
int kernel_execve(const char *filename,
|
||||
const char *const argv[],
|
||||
const char *const envp[])
|
||||
{
|
||||
register long __res asm ("%d0") = __NR_execve;
|
||||
register long __a asm ("%d1") = (long)(filename);
|
||||
register long __b asm ("%d2") = (long)(argv);
|
||||
register long __c asm ("%d3") = (long)(envp);
|
||||
asm volatile ("trap #0" : "+d" (__res)
|
||||
: "d" (__a), "d" (__b), "d" (__c));
|
||||
return __res;
|
||||
}
|
||||
|
||||
asmlinkage unsigned long sys_get_thread_area(void)
|
||||
{
|
||||
return current_thread_info()->tp_value;
|
||||
}
|
||||
|
||||
asmlinkage int sys_set_thread_area(unsigned long tp)
|
||||
{
|
||||
current_thread_info()->tp_value = tp;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* This syscall gets its arguments in A0 (mem), D2 (oldval) and
|
||||
D1 (newval). */
|
||||
asmlinkage int
|
||||
sys_atomic_cmpxchg_32(unsigned long newval, int oldval, int d3, int d4, int d5,
|
||||
unsigned long __user * mem)
|
||||
{
|
||||
/* This was borrowed from ARM's implementation. */
|
||||
for (;;) {
|
||||
struct mm_struct *mm = current->mm;
|
||||
pgd_t *pgd;
|
||||
pmd_t *pmd;
|
||||
pte_t *pte;
|
||||
spinlock_t *ptl;
|
||||
unsigned long mem_value;
|
||||
|
||||
down_read(&mm->mmap_sem);
|
||||
pgd = pgd_offset(mm, (unsigned long)mem);
|
||||
if (!pgd_present(*pgd))
|
||||
goto bad_access;
|
||||
pmd = pmd_offset(pgd, (unsigned long)mem);
|
||||
if (!pmd_present(*pmd))
|
||||
goto bad_access;
|
||||
pte = pte_offset_map_lock(mm, pmd, (unsigned long)mem, &ptl);
|
||||
if (!pte_present(*pte) || !pte_dirty(*pte)
|
||||
|| !pte_write(*pte)) {
|
||||
pte_unmap_unlock(pte, ptl);
|
||||
goto bad_access;
|
||||
}
|
||||
|
||||
mem_value = *mem;
|
||||
if (mem_value == oldval)
|
||||
*mem = newval;
|
||||
|
||||
pte_unmap_unlock(pte, ptl);
|
||||
up_read(&mm->mmap_sem);
|
||||
return mem_value;
|
||||
|
||||
bad_access:
|
||||
up_read(&mm->mmap_sem);
|
||||
/* This is not necessarily a bad access, we can get here if
|
||||
a memory we're trying to write to should be copied-on-write.
|
||||
Make the kernel do the necessary page stuff, then re-iterate.
|
||||
Simulate a write access fault to do that. */
|
||||
{
|
||||
/* The first argument of the function corresponds to
|
||||
D1, which is the first field of struct pt_regs. */
|
||||
struct pt_regs *fp = (struct pt_regs *)&newval;
|
||||
|
||||
/* '3' is an RMW flag. */
|
||||
if (do_page_fault(fp, (unsigned long)mem, 3))
|
||||
/* If the do_page_fault() failed, we don't
|
||||
have anything meaningful to return.
|
||||
There should be a SIGSEGV pending for
|
||||
the process. */
|
||||
return 0xdeadbeef;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
asmlinkage int sys_atomic_barrier(void)
|
||||
{
|
||||
/* no code needed for uniprocs */
|
||||
return 0;
|
||||
}
|
@ -1,114 +1,5 @@
|
||||
/*
|
||||
* linux/arch/m68k/kernel/time.c
|
||||
*
|
||||
* Copyright (C) 1991, 1992, 1995 Linus Torvalds
|
||||
*
|
||||
* This file contains the m68k-specific time handling details.
|
||||
* Most of the stuff is located in the machine specific files.
|
||||
*
|
||||
* 1997-09-10 Updated NTP code according to technical memorandum Jan '96
|
||||
* "A Kernel Model for Precision Timekeeping" by Dave Mills
|
||||
*/
|
||||
|
||||
#include <linux/errno.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/param.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/rtc.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#include <asm/machdep.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/irq_regs.h>
|
||||
|
||||
#include <linux/time.h>
|
||||
#include <linux/timex.h>
|
||||
#include <linux/profile.h>
|
||||
|
||||
static inline int set_rtc_mmss(unsigned long nowtime)
|
||||
{
|
||||
if (mach_set_clock_mmss)
|
||||
return mach_set_clock_mmss (nowtime);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* timer_interrupt() needs to keep up the real-time clock,
|
||||
* as well as call the "xtime_update()" routine every clocktick
|
||||
*/
|
||||
static irqreturn_t timer_interrupt(int irq, void *dummy)
|
||||
{
|
||||
xtime_update(1);
|
||||
update_process_times(user_mode(get_irq_regs()));
|
||||
profile_tick(CPU_PROFILING);
|
||||
|
||||
#ifdef CONFIG_HEARTBEAT
|
||||
/* use power LED as a heartbeat instead -- much more useful
|
||||
for debugging -- based on the version for PReP by Cort */
|
||||
/* acts like an actual heart beat -- ie thump-thump-pause... */
|
||||
if (mach_heartbeat) {
|
||||
static unsigned cnt = 0, period = 0, dist = 0;
|
||||
|
||||
if (cnt == 0 || cnt == dist)
|
||||
mach_heartbeat( 1 );
|
||||
else if (cnt == 7 || cnt == dist+7)
|
||||
mach_heartbeat( 0 );
|
||||
|
||||
if (++cnt > period) {
|
||||
cnt = 0;
|
||||
/* The hyperbolic function below modifies the heartbeat period
|
||||
* length in dependency of the current (5min) load. It goes
|
||||
* through the points f(0)=126, f(1)=86, f(5)=51,
|
||||
* f(inf)->30. */
|
||||
period = ((672<<FSHIFT)/(5*avenrun[0]+(7<<FSHIFT))) + 30;
|
||||
dist = period / 4;
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_HEARTBEAT */
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
void read_persistent_clock(struct timespec *ts)
|
||||
{
|
||||
struct rtc_time time;
|
||||
ts->tv_sec = 0;
|
||||
ts->tv_nsec = 0;
|
||||
|
||||
if (mach_hwclk) {
|
||||
mach_hwclk(0, &time);
|
||||
|
||||
if ((time.tm_year += 1900) < 1970)
|
||||
time.tm_year += 100;
|
||||
ts->tv_sec = mktime(time.tm_year, time.tm_mon, time.tm_mday,
|
||||
time.tm_hour, time.tm_min, time.tm_sec);
|
||||
}
|
||||
}
|
||||
|
||||
void __init time_init(void)
|
||||
{
|
||||
mach_sched_init(timer_interrupt);
|
||||
}
|
||||
|
||||
u32 arch_gettimeoffset(void)
|
||||
{
|
||||
return mach_gettimeoffset() * 1000;
|
||||
}
|
||||
|
||||
static int __init rtc_init(void)
|
||||
{
|
||||
struct platform_device *pdev;
|
||||
|
||||
if (!mach_hwclk)
|
||||
return -ENODEV;
|
||||
|
||||
pdev = platform_device_register_simple("rtc-generic", -1, NULL, 0);
|
||||
if (IS_ERR(pdev))
|
||||
return PTR_ERR(pdev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
module_init(rtc_init);
|
||||
#ifdef CONFIG_MMU
|
||||
#include "time_mm.c"
|
||||
#else
|
||||
#include "time_no.c"
|
||||
#endif
|
||||
|
114
arch/m68k/kernel/time_mm.c
Normal file
114
arch/m68k/kernel/time_mm.c
Normal file
@ -0,0 +1,114 @@
|
||||
/*
|
||||
* linux/arch/m68k/kernel/time.c
|
||||
*
|
||||
* Copyright (C) 1991, 1992, 1995 Linus Torvalds
|
||||
*
|
||||
* This file contains the m68k-specific time handling details.
|
||||
* Most of the stuff is located in the machine specific files.
|
||||
*
|
||||
* 1997-09-10 Updated NTP code according to technical memorandum Jan '96
|
||||
* "A Kernel Model for Precision Timekeeping" by Dave Mills
|
||||
*/
|
||||
|
||||
#include <linux/errno.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/param.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/rtc.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#include <asm/machdep.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/irq_regs.h>
|
||||
|
||||
#include <linux/time.h>
|
||||
#include <linux/timex.h>
|
||||
#include <linux/profile.h>
|
||||
|
||||
static inline int set_rtc_mmss(unsigned long nowtime)
|
||||
{
|
||||
if (mach_set_clock_mmss)
|
||||
return mach_set_clock_mmss (nowtime);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* timer_interrupt() needs to keep up the real-time clock,
|
||||
* as well as call the "xtime_update()" routine every clocktick
|
||||
*/
|
||||
static irqreturn_t timer_interrupt(int irq, void *dummy)
|
||||
{
|
||||
xtime_update(1);
|
||||
update_process_times(user_mode(get_irq_regs()));
|
||||
profile_tick(CPU_PROFILING);
|
||||
|
||||
#ifdef CONFIG_HEARTBEAT
|
||||
/* use power LED as a heartbeat instead -- much more useful
|
||||
for debugging -- based on the version for PReP by Cort */
|
||||
/* acts like an actual heart beat -- ie thump-thump-pause... */
|
||||
if (mach_heartbeat) {
|
||||
static unsigned cnt = 0, period = 0, dist = 0;
|
||||
|
||||
if (cnt == 0 || cnt == dist)
|
||||
mach_heartbeat( 1 );
|
||||
else if (cnt == 7 || cnt == dist+7)
|
||||
mach_heartbeat( 0 );
|
||||
|
||||
if (++cnt > period) {
|
||||
cnt = 0;
|
||||
/* The hyperbolic function below modifies the heartbeat period
|
||||
* length in dependency of the current (5min) load. It goes
|
||||
* through the points f(0)=126, f(1)=86, f(5)=51,
|
||||
* f(inf)->30. */
|
||||
period = ((672<<FSHIFT)/(5*avenrun[0]+(7<<FSHIFT))) + 30;
|
||||
dist = period / 4;
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_HEARTBEAT */
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
void read_persistent_clock(struct timespec *ts)
|
||||
{
|
||||
struct rtc_time time;
|
||||
ts->tv_sec = 0;
|
||||
ts->tv_nsec = 0;
|
||||
|
||||
if (mach_hwclk) {
|
||||
mach_hwclk(0, &time);
|
||||
|
||||
if ((time.tm_year += 1900) < 1970)
|
||||
time.tm_year += 100;
|
||||
ts->tv_sec = mktime(time.tm_year, time.tm_mon, time.tm_mday,
|
||||
time.tm_hour, time.tm_min, time.tm_sec);
|
||||
}
|
||||
}
|
||||
|
||||
void __init time_init(void)
|
||||
{
|
||||
mach_sched_init(timer_interrupt);
|
||||
}
|
||||
|
||||
u32 arch_gettimeoffset(void)
|
||||
{
|
||||
return mach_gettimeoffset() * 1000;
|
||||
}
|
||||
|
||||
static int __init rtc_init(void)
|
||||
{
|
||||
struct platform_device *pdev;
|
||||
|
||||
if (!mach_hwclk)
|
||||
return -ENODEV;
|
||||
|
||||
pdev = platform_device_register_simple("rtc-generic", -1, NULL, 0);
|
||||
if (IS_ERR(pdev))
|
||||
return PTR_ERR(pdev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
module_init(rtc_init);
|
File diff suppressed because it is too large
Load Diff
1207
arch/m68k/kernel/traps_mm.c
Normal file
1207
arch/m68k/kernel/traps_mm.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,10 +1,5 @@
|
||||
PHDRS
|
||||
{
|
||||
text PT_LOAD FILEHDR PHDRS FLAGS (7);
|
||||
data PT_LOAD FLAGS (7);
|
||||
}
|
||||
#ifdef CONFIG_SUN3
|
||||
#include "vmlinux-sun3.lds"
|
||||
#ifdef CONFIG_MMU
|
||||
#include "vmlinux.lds_mm.S"
|
||||
#else
|
||||
#include "vmlinux-std.lds"
|
||||
#include "vmlinux.lds_no.S"
|
||||
#endif
|
||||
|
10
arch/m68k/kernel/vmlinux.lds_mm.S
Normal file
10
arch/m68k/kernel/vmlinux.lds_mm.S
Normal file
@ -0,0 +1,10 @@
|
||||
PHDRS
|
||||
{
|
||||
text PT_LOAD FILEHDR PHDRS FLAGS (7);
|
||||
data PT_LOAD FLAGS (7);
|
||||
}
|
||||
#ifdef CONFIG_SUN3
|
||||
#include "vmlinux-sun3.lds"
|
||||
#else
|
||||
#include "vmlinux-std.lds"
|
||||
#endif
|
@ -1,6 +1,5 @@
|
||||
#
|
||||
# Makefile for m68k-specific library files..
|
||||
#
|
||||
|
||||
lib-y := ashldi3.o ashrdi3.o lshrdi3.o muldi3.o \
|
||||
checksum.o string.o uaccess.o
|
||||
ifdef CONFIG_MMU
|
||||
include arch/m68k/lib/Makefile_mm
|
||||
else
|
||||
include arch/m68k/lib/Makefile_no
|
||||
endif
|
||||
|
6
arch/m68k/lib/Makefile_mm
Normal file
6
arch/m68k/lib/Makefile_mm
Normal file
@ -0,0 +1,6 @@
|
||||
#
|
||||
# Makefile for m68k-specific library files..
|
||||
#
|
||||
|
||||
lib-y := ashldi3.o ashrdi3.o lshrdi3.o muldi3.o \
|
||||
checksum.o string.o uaccess.o
|
@ -1,425 +1,5 @@
|
||||
/*
|
||||
* INET An implementation of the TCP/IP protocol suite for the LINUX
|
||||
* operating system. INET is implemented using the BSD Socket
|
||||
* interface as the means of communication with the user level.
|
||||
*
|
||||
* IP/TCP/UDP checksumming routines
|
||||
*
|
||||
* Authors: Jorge Cwik, <jorge@laser.satlink.net>
|
||||
* Arnt Gulbrandsen, <agulbra@nvg.unit.no>
|
||||
* Tom May, <ftom@netcom.com>
|
||||
* Andreas Schwab, <schwab@issan.informatik.uni-dortmund.de>
|
||||
* Lots of code moved from tcp.c and ip.c; see those files
|
||||
* for more names.
|
||||
*
|
||||
* 03/02/96 Jes Sorensen, Andreas Schwab, Roman Hodek:
|
||||
* Fixed some nasty bugs, causing some horrible crashes.
|
||||
* A: At some points, the sum (%0) was used as
|
||||
* length-counter instead of the length counter
|
||||
* (%1). Thanks to Roman Hodek for pointing this out.
|
||||
* B: GCC seems to mess up if one uses too many
|
||||
* data-registers to hold input values and one tries to
|
||||
* specify d0 and d1 as scratch registers. Letting gcc
|
||||
* choose these registers itself solves the problem.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version
|
||||
* 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* 1998/8/31 Andreas Schwab:
|
||||
* Zero out rest of buffer on exception in
|
||||
* csum_partial_copy_from_user.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <net/checksum.h>
|
||||
|
||||
/*
|
||||
* computes a partial checksum, e.g. for TCP/UDP fragments
|
||||
*/
|
||||
|
||||
__wsum csum_partial(const void *buff, int len, __wsum sum)
|
||||
{
|
||||
unsigned long tmp1, tmp2;
|
||||
/*
|
||||
* Experiments with ethernet and slip connections show that buff
|
||||
* is aligned on either a 2-byte or 4-byte boundary.
|
||||
*/
|
||||
__asm__("movel %2,%3\n\t"
|
||||
"btst #1,%3\n\t" /* Check alignment */
|
||||
"jeq 2f\n\t"
|
||||
"subql #2,%1\n\t" /* buff%4==2: treat first word */
|
||||
"jgt 1f\n\t"
|
||||
"addql #2,%1\n\t" /* len was == 2, treat only rest */
|
||||
"jra 4f\n"
|
||||
"1:\t"
|
||||
"addw %2@+,%0\n\t" /* add first word to sum */
|
||||
"clrl %3\n\t"
|
||||
"addxl %3,%0\n" /* add X bit */
|
||||
"2:\t"
|
||||
/* unrolled loop for the main part: do 8 longs at once */
|
||||
"movel %1,%3\n\t" /* save len in tmp1 */
|
||||
"lsrl #5,%1\n\t" /* len/32 */
|
||||
"jeq 2f\n\t" /* not enough... */
|
||||
"subql #1,%1\n"
|
||||
"1:\t"
|
||||
"movel %2@+,%4\n\t"
|
||||
"addxl %4,%0\n\t"
|
||||
"movel %2@+,%4\n\t"
|
||||
"addxl %4,%0\n\t"
|
||||
"movel %2@+,%4\n\t"
|
||||
"addxl %4,%0\n\t"
|
||||
"movel %2@+,%4\n\t"
|
||||
"addxl %4,%0\n\t"
|
||||
"movel %2@+,%4\n\t"
|
||||
"addxl %4,%0\n\t"
|
||||
"movel %2@+,%4\n\t"
|
||||
"addxl %4,%0\n\t"
|
||||
"movel %2@+,%4\n\t"
|
||||
"addxl %4,%0\n\t"
|
||||
"movel %2@+,%4\n\t"
|
||||
"addxl %4,%0\n\t"
|
||||
"dbra %1,1b\n\t"
|
||||
"clrl %4\n\t"
|
||||
"addxl %4,%0\n\t" /* add X bit */
|
||||
"clrw %1\n\t"
|
||||
"subql #1,%1\n\t"
|
||||
"jcc 1b\n"
|
||||
"2:\t"
|
||||
"movel %3,%1\n\t" /* restore len from tmp1 */
|
||||
"andw #0x1c,%3\n\t" /* number of rest longs */
|
||||
"jeq 4f\n\t"
|
||||
"lsrw #2,%3\n\t"
|
||||
"subqw #1,%3\n"
|
||||
"3:\t"
|
||||
/* loop for rest longs */
|
||||
"movel %2@+,%4\n\t"
|
||||
"addxl %4,%0\n\t"
|
||||
"dbra %3,3b\n\t"
|
||||
"clrl %4\n\t"
|
||||
"addxl %4,%0\n" /* add X bit */
|
||||
"4:\t"
|
||||
/* now check for rest bytes that do not fit into longs */
|
||||
"andw #3,%1\n\t"
|
||||
"jeq 7f\n\t"
|
||||
"clrl %4\n\t" /* clear tmp2 for rest bytes */
|
||||
"subqw #2,%1\n\t"
|
||||
"jlt 5f\n\t"
|
||||
"movew %2@+,%4\n\t" /* have rest >= 2: get word */
|
||||
"swap %4\n\t" /* into bits 16..31 */
|
||||
"tstw %1\n\t" /* another byte? */
|
||||
"jeq 6f\n"
|
||||
"5:\t"
|
||||
"moveb %2@,%4\n\t" /* have odd rest: get byte */
|
||||
"lslw #8,%4\n\t" /* into bits 8..15; 16..31 untouched */
|
||||
"6:\t"
|
||||
"addl %4,%0\n\t" /* now add rest long to sum */
|
||||
"clrl %4\n\t"
|
||||
"addxl %4,%0\n" /* add X bit */
|
||||
"7:\t"
|
||||
: "=d" (sum), "=d" (len), "=a" (buff),
|
||||
"=&d" (tmp1), "=&d" (tmp2)
|
||||
: "0" (sum), "1" (len), "2" (buff)
|
||||
);
|
||||
return(sum);
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(csum_partial);
|
||||
|
||||
|
||||
/*
|
||||
* copy from user space while checksumming, with exception handling.
|
||||
*/
|
||||
|
||||
__wsum
|
||||
csum_partial_copy_from_user(const void __user *src, void *dst,
|
||||
int len, __wsum sum, int *csum_err)
|
||||
{
|
||||
/*
|
||||
* GCC doesn't like more than 10 operands for the asm
|
||||
* statements so we have to use tmp2 for the error
|
||||
* code.
|
||||
*/
|
||||
unsigned long tmp1, tmp2;
|
||||
|
||||
__asm__("movel %2,%4\n\t"
|
||||
"btst #1,%4\n\t" /* Check alignment */
|
||||
"jeq 2f\n\t"
|
||||
"subql #2,%1\n\t" /* buff%4==2: treat first word */
|
||||
"jgt 1f\n\t"
|
||||
"addql #2,%1\n\t" /* len was == 2, treat only rest */
|
||||
"jra 4f\n"
|
||||
"1:\n"
|
||||
"10:\t"
|
||||
"movesw %2@+,%4\n\t" /* add first word to sum */
|
||||
"addw %4,%0\n\t"
|
||||
"movew %4,%3@+\n\t"
|
||||
"clrl %4\n\t"
|
||||
"addxl %4,%0\n" /* add X bit */
|
||||
"2:\t"
|
||||
/* unrolled loop for the main part: do 8 longs at once */
|
||||
"movel %1,%4\n\t" /* save len in tmp1 */
|
||||
"lsrl #5,%1\n\t" /* len/32 */
|
||||
"jeq 2f\n\t" /* not enough... */
|
||||
"subql #1,%1\n"
|
||||
"1:\n"
|
||||
"11:\t"
|
||||
"movesl %2@+,%5\n\t"
|
||||
"addxl %5,%0\n\t"
|
||||
"movel %5,%3@+\n\t"
|
||||
"12:\t"
|
||||
"movesl %2@+,%5\n\t"
|
||||
"addxl %5,%0\n\t"
|
||||
"movel %5,%3@+\n\t"
|
||||
"13:\t"
|
||||
"movesl %2@+,%5\n\t"
|
||||
"addxl %5,%0\n\t"
|
||||
"movel %5,%3@+\n\t"
|
||||
"14:\t"
|
||||
"movesl %2@+,%5\n\t"
|
||||
"addxl %5,%0\n\t"
|
||||
"movel %5,%3@+\n\t"
|
||||
"15:\t"
|
||||
"movesl %2@+,%5\n\t"
|
||||
"addxl %5,%0\n\t"
|
||||
"movel %5,%3@+\n\t"
|
||||
"16:\t"
|
||||
"movesl %2@+,%5\n\t"
|
||||
"addxl %5,%0\n\t"
|
||||
"movel %5,%3@+\n\t"
|
||||
"17:\t"
|
||||
"movesl %2@+,%5\n\t"
|
||||
"addxl %5,%0\n\t"
|
||||
"movel %5,%3@+\n\t"
|
||||
"18:\t"
|
||||
"movesl %2@+,%5\n\t"
|
||||
"addxl %5,%0\n\t"
|
||||
"movel %5,%3@+\n\t"
|
||||
"dbra %1,1b\n\t"
|
||||
"clrl %5\n\t"
|
||||
"addxl %5,%0\n\t" /* add X bit */
|
||||
"clrw %1\n\t"
|
||||
"subql #1,%1\n\t"
|
||||
"jcc 1b\n"
|
||||
"2:\t"
|
||||
"movel %4,%1\n\t" /* restore len from tmp1 */
|
||||
"andw #0x1c,%4\n\t" /* number of rest longs */
|
||||
"jeq 4f\n\t"
|
||||
"lsrw #2,%4\n\t"
|
||||
"subqw #1,%4\n"
|
||||
"3:\n"
|
||||
/* loop for rest longs */
|
||||
"19:\t"
|
||||
"movesl %2@+,%5\n\t"
|
||||
"addxl %5,%0\n\t"
|
||||
"movel %5,%3@+\n\t"
|
||||
"dbra %4,3b\n\t"
|
||||
"clrl %5\n\t"
|
||||
"addxl %5,%0\n" /* add X bit */
|
||||
"4:\t"
|
||||
/* now check for rest bytes that do not fit into longs */
|
||||
"andw #3,%1\n\t"
|
||||
"jeq 7f\n\t"
|
||||
"clrl %5\n\t" /* clear tmp2 for rest bytes */
|
||||
"subqw #2,%1\n\t"
|
||||
"jlt 5f\n\t"
|
||||
"20:\t"
|
||||
"movesw %2@+,%5\n\t" /* have rest >= 2: get word */
|
||||
"movew %5,%3@+\n\t"
|
||||
"swap %5\n\t" /* into bits 16..31 */
|
||||
"tstw %1\n\t" /* another byte? */
|
||||
"jeq 6f\n"
|
||||
"5:\n"
|
||||
"21:\t"
|
||||
"movesb %2@,%5\n\t" /* have odd rest: get byte */
|
||||
"moveb %5,%3@+\n\t"
|
||||
"lslw #8,%5\n\t" /* into bits 8..15; 16..31 untouched */
|
||||
"6:\t"
|
||||
"addl %5,%0\n\t" /* now add rest long to sum */
|
||||
"clrl %5\n\t"
|
||||
"addxl %5,%0\n\t" /* add X bit */
|
||||
"7:\t"
|
||||
"clrl %5\n" /* no error - clear return value */
|
||||
"8:\n"
|
||||
".section .fixup,\"ax\"\n"
|
||||
".even\n"
|
||||
/* If any exception occurs zero out the rest.
|
||||
Similarities with the code above are intentional :-) */
|
||||
"90:\t"
|
||||
"clrw %3@+\n\t"
|
||||
"movel %1,%4\n\t"
|
||||
"lsrl #5,%1\n\t"
|
||||
"jeq 1f\n\t"
|
||||
"subql #1,%1\n"
|
||||
"91:\t"
|
||||
"clrl %3@+\n"
|
||||
"92:\t"
|
||||
"clrl %3@+\n"
|
||||
"93:\t"
|
||||
"clrl %3@+\n"
|
||||
"94:\t"
|
||||
"clrl %3@+\n"
|
||||
"95:\t"
|
||||
"clrl %3@+\n"
|
||||
"96:\t"
|
||||
"clrl %3@+\n"
|
||||
"97:\t"
|
||||
"clrl %3@+\n"
|
||||
"98:\t"
|
||||
"clrl %3@+\n\t"
|
||||
"dbra %1,91b\n\t"
|
||||
"clrw %1\n\t"
|
||||
"subql #1,%1\n\t"
|
||||
"jcc 91b\n"
|
||||
"1:\t"
|
||||
"movel %4,%1\n\t"
|
||||
"andw #0x1c,%4\n\t"
|
||||
"jeq 1f\n\t"
|
||||
"lsrw #2,%4\n\t"
|
||||
"subqw #1,%4\n"
|
||||
"99:\t"
|
||||
"clrl %3@+\n\t"
|
||||
"dbra %4,99b\n\t"
|
||||
"1:\t"
|
||||
"andw #3,%1\n\t"
|
||||
"jeq 9f\n"
|
||||
"100:\t"
|
||||
"clrw %3@+\n\t"
|
||||
"tstw %1\n\t"
|
||||
"jeq 9f\n"
|
||||
"101:\t"
|
||||
"clrb %3@+\n"
|
||||
"9:\t"
|
||||
#define STR(X) STR1(X)
|
||||
#define STR1(X) #X
|
||||
"moveq #-" STR(EFAULT) ",%5\n\t"
|
||||
"jra 8b\n"
|
||||
".previous\n"
|
||||
".section __ex_table,\"a\"\n"
|
||||
".long 10b,90b\n"
|
||||
".long 11b,91b\n"
|
||||
".long 12b,92b\n"
|
||||
".long 13b,93b\n"
|
||||
".long 14b,94b\n"
|
||||
".long 15b,95b\n"
|
||||
".long 16b,96b\n"
|
||||
".long 17b,97b\n"
|
||||
".long 18b,98b\n"
|
||||
".long 19b,99b\n"
|
||||
".long 20b,100b\n"
|
||||
".long 21b,101b\n"
|
||||
".previous"
|
||||
: "=d" (sum), "=d" (len), "=a" (src), "=a" (dst),
|
||||
"=&d" (tmp1), "=d" (tmp2)
|
||||
: "0" (sum), "1" (len), "2" (src), "3" (dst)
|
||||
);
|
||||
|
||||
*csum_err = tmp2;
|
||||
|
||||
return(sum);
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(csum_partial_copy_from_user);
|
||||
|
||||
|
||||
/*
|
||||
* copy from kernel space while checksumming, otherwise like csum_partial
|
||||
*/
|
||||
|
||||
__wsum
|
||||
csum_partial_copy_nocheck(const void *src, void *dst, int len, __wsum sum)
|
||||
{
|
||||
unsigned long tmp1, tmp2;
|
||||
__asm__("movel %2,%4\n\t"
|
||||
"btst #1,%4\n\t" /* Check alignment */
|
||||
"jeq 2f\n\t"
|
||||
"subql #2,%1\n\t" /* buff%4==2: treat first word */
|
||||
"jgt 1f\n\t"
|
||||
"addql #2,%1\n\t" /* len was == 2, treat only rest */
|
||||
"jra 4f\n"
|
||||
"1:\t"
|
||||
"movew %2@+,%4\n\t" /* add first word to sum */
|
||||
"addw %4,%0\n\t"
|
||||
"movew %4,%3@+\n\t"
|
||||
"clrl %4\n\t"
|
||||
"addxl %4,%0\n" /* add X bit */
|
||||
"2:\t"
|
||||
/* unrolled loop for the main part: do 8 longs at once */
|
||||
"movel %1,%4\n\t" /* save len in tmp1 */
|
||||
"lsrl #5,%1\n\t" /* len/32 */
|
||||
"jeq 2f\n\t" /* not enough... */
|
||||
"subql #1,%1\n"
|
||||
"1:\t"
|
||||
"movel %2@+,%5\n\t"
|
||||
"addxl %5,%0\n\t"
|
||||
"movel %5,%3@+\n\t"
|
||||
"movel %2@+,%5\n\t"
|
||||
"addxl %5,%0\n\t"
|
||||
"movel %5,%3@+\n\t"
|
||||
"movel %2@+,%5\n\t"
|
||||
"addxl %5,%0\n\t"
|
||||
"movel %5,%3@+\n\t"
|
||||
"movel %2@+,%5\n\t"
|
||||
"addxl %5,%0\n\t"
|
||||
"movel %5,%3@+\n\t"
|
||||
"movel %2@+,%5\n\t"
|
||||
"addxl %5,%0\n\t"
|
||||
"movel %5,%3@+\n\t"
|
||||
"movel %2@+,%5\n\t"
|
||||
"addxl %5,%0\n\t"
|
||||
"movel %5,%3@+\n\t"
|
||||
"movel %2@+,%5\n\t"
|
||||
"addxl %5,%0\n\t"
|
||||
"movel %5,%3@+\n\t"
|
||||
"movel %2@+,%5\n\t"
|
||||
"addxl %5,%0\n\t"
|
||||
"movel %5,%3@+\n\t"
|
||||
"dbra %1,1b\n\t"
|
||||
"clrl %5\n\t"
|
||||
"addxl %5,%0\n\t" /* add X bit */
|
||||
"clrw %1\n\t"
|
||||
"subql #1,%1\n\t"
|
||||
"jcc 1b\n"
|
||||
"2:\t"
|
||||
"movel %4,%1\n\t" /* restore len from tmp1 */
|
||||
"andw #0x1c,%4\n\t" /* number of rest longs */
|
||||
"jeq 4f\n\t"
|
||||
"lsrw #2,%4\n\t"
|
||||
"subqw #1,%4\n"
|
||||
"3:\t"
|
||||
/* loop for rest longs */
|
||||
"movel %2@+,%5\n\t"
|
||||
"addxl %5,%0\n\t"
|
||||
"movel %5,%3@+\n\t"
|
||||
"dbra %4,3b\n\t"
|
||||
"clrl %5\n\t"
|
||||
"addxl %5,%0\n" /* add X bit */
|
||||
"4:\t"
|
||||
/* now check for rest bytes that do not fit into longs */
|
||||
"andw #3,%1\n\t"
|
||||
"jeq 7f\n\t"
|
||||
"clrl %5\n\t" /* clear tmp2 for rest bytes */
|
||||
"subqw #2,%1\n\t"
|
||||
"jlt 5f\n\t"
|
||||
"movew %2@+,%5\n\t" /* have rest >= 2: get word */
|
||||
"movew %5,%3@+\n\t"
|
||||
"swap %5\n\t" /* into bits 16..31 */
|
||||
"tstw %1\n\t" /* another byte? */
|
||||
"jeq 6f\n"
|
||||
"5:\t"
|
||||
"moveb %2@,%5\n\t" /* have odd rest: get byte */
|
||||
"moveb %5,%3@+\n\t"
|
||||
"lslw #8,%5\n" /* into bits 8..15; 16..31 untouched */
|
||||
"6:\t"
|
||||
"addl %5,%0\n\t" /* now add rest long to sum */
|
||||
"clrl %5\n\t"
|
||||
"addxl %5,%0\n" /* add X bit */
|
||||
"7:\t"
|
||||
: "=d" (sum), "=d" (len), "=a" (src), "=a" (dst),
|
||||
"=&d" (tmp1), "=&d" (tmp2)
|
||||
: "0" (sum), "1" (len), "2" (src), "3" (dst)
|
||||
);
|
||||
return(sum);
|
||||
}
|
||||
EXPORT_SYMBOL(csum_partial_copy_nocheck);
|
||||
#ifdef CONFIG_MMU
|
||||
#include "checksum_mm.c"
|
||||
#else
|
||||
#include "checksum_no.c"
|
||||
#endif
|
||||
|
425
arch/m68k/lib/checksum_mm.c
Normal file
425
arch/m68k/lib/checksum_mm.c
Normal file
@ -0,0 +1,425 @@
|
||||
/*
|
||||
* INET An implementation of the TCP/IP protocol suite for the LINUX
|
||||
* operating system. INET is implemented using the BSD Socket
|
||||
* interface as the means of communication with the user level.
|
||||
*
|
||||
* IP/TCP/UDP checksumming routines
|
||||
*
|
||||
* Authors: Jorge Cwik, <jorge@laser.satlink.net>
|
||||
* Arnt Gulbrandsen, <agulbra@nvg.unit.no>
|
||||
* Tom May, <ftom@netcom.com>
|
||||
* Andreas Schwab, <schwab@issan.informatik.uni-dortmund.de>
|
||||
* Lots of code moved from tcp.c and ip.c; see those files
|
||||
* for more names.
|
||||
*
|
||||
* 03/02/96 Jes Sorensen, Andreas Schwab, Roman Hodek:
|
||||
* Fixed some nasty bugs, causing some horrible crashes.
|
||||
* A: At some points, the sum (%0) was used as
|
||||
* length-counter instead of the length counter
|
||||
* (%1). Thanks to Roman Hodek for pointing this out.
|
||||
* B: GCC seems to mess up if one uses too many
|
||||
* data-registers to hold input values and one tries to
|
||||
* specify d0 and d1 as scratch registers. Letting gcc
|
||||
* choose these registers itself solves the problem.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version
|
||||
* 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* 1998/8/31 Andreas Schwab:
|
||||
* Zero out rest of buffer on exception in
|
||||
* csum_partial_copy_from_user.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <net/checksum.h>
|
||||
|
||||
/*
|
||||
* computes a partial checksum, e.g. for TCP/UDP fragments
|
||||
*/
|
||||
|
||||
__wsum csum_partial(const void *buff, int len, __wsum sum)
|
||||
{
|
||||
unsigned long tmp1, tmp2;
|
||||
/*
|
||||
* Experiments with ethernet and slip connections show that buff
|
||||
* is aligned on either a 2-byte or 4-byte boundary.
|
||||
*/
|
||||
__asm__("movel %2,%3\n\t"
|
||||
"btst #1,%3\n\t" /* Check alignment */
|
||||
"jeq 2f\n\t"
|
||||
"subql #2,%1\n\t" /* buff%4==2: treat first word */
|
||||
"jgt 1f\n\t"
|
||||
"addql #2,%1\n\t" /* len was == 2, treat only rest */
|
||||
"jra 4f\n"
|
||||
"1:\t"
|
||||
"addw %2@+,%0\n\t" /* add first word to sum */
|
||||
"clrl %3\n\t"
|
||||
"addxl %3,%0\n" /* add X bit */
|
||||
"2:\t"
|
||||
/* unrolled loop for the main part: do 8 longs at once */
|
||||
"movel %1,%3\n\t" /* save len in tmp1 */
|
||||
"lsrl #5,%1\n\t" /* len/32 */
|
||||
"jeq 2f\n\t" /* not enough... */
|
||||
"subql #1,%1\n"
|
||||
"1:\t"
|
||||
"movel %2@+,%4\n\t"
|
||||
"addxl %4,%0\n\t"
|
||||
"movel %2@+,%4\n\t"
|
||||
"addxl %4,%0\n\t"
|
||||
"movel %2@+,%4\n\t"
|
||||
"addxl %4,%0\n\t"
|
||||
"movel %2@+,%4\n\t"
|
||||
"addxl %4,%0\n\t"
|
||||
"movel %2@+,%4\n\t"
|
||||
"addxl %4,%0\n\t"
|
||||
"movel %2@+,%4\n\t"
|
||||
"addxl %4,%0\n\t"
|
||||
"movel %2@+,%4\n\t"
|
||||
"addxl %4,%0\n\t"
|
||||
"movel %2@+,%4\n\t"
|
||||
"addxl %4,%0\n\t"
|
||||
"dbra %1,1b\n\t"
|
||||
"clrl %4\n\t"
|
||||
"addxl %4,%0\n\t" /* add X bit */
|
||||
"clrw %1\n\t"
|
||||
"subql #1,%1\n\t"
|
||||
"jcc 1b\n"
|
||||
"2:\t"
|
||||
"movel %3,%1\n\t" /* restore len from tmp1 */
|
||||
"andw #0x1c,%3\n\t" /* number of rest longs */
|
||||
"jeq 4f\n\t"
|
||||
"lsrw #2,%3\n\t"
|
||||
"subqw #1,%3\n"
|
||||
"3:\t"
|
||||
/* loop for rest longs */
|
||||
"movel %2@+,%4\n\t"
|
||||
"addxl %4,%0\n\t"
|
||||
"dbra %3,3b\n\t"
|
||||
"clrl %4\n\t"
|
||||
"addxl %4,%0\n" /* add X bit */
|
||||
"4:\t"
|
||||
/* now check for rest bytes that do not fit into longs */
|
||||
"andw #3,%1\n\t"
|
||||
"jeq 7f\n\t"
|
||||
"clrl %4\n\t" /* clear tmp2 for rest bytes */
|
||||
"subqw #2,%1\n\t"
|
||||
"jlt 5f\n\t"
|
||||
"movew %2@+,%4\n\t" /* have rest >= 2: get word */
|
||||
"swap %4\n\t" /* into bits 16..31 */
|
||||
"tstw %1\n\t" /* another byte? */
|
||||
"jeq 6f\n"
|
||||
"5:\t"
|
||||
"moveb %2@,%4\n\t" /* have odd rest: get byte */
|
||||
"lslw #8,%4\n\t" /* into bits 8..15; 16..31 untouched */
|
||||
"6:\t"
|
||||
"addl %4,%0\n\t" /* now add rest long to sum */
|
||||
"clrl %4\n\t"
|
||||
"addxl %4,%0\n" /* add X bit */
|
||||
"7:\t"
|
||||
: "=d" (sum), "=d" (len), "=a" (buff),
|
||||
"=&d" (tmp1), "=&d" (tmp2)
|
||||
: "0" (sum), "1" (len), "2" (buff)
|
||||
);
|
||||
return(sum);
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(csum_partial);
|
||||
|
||||
|
||||
/*
|
||||
* copy from user space while checksumming, with exception handling.
|
||||
*/
|
||||
|
||||
__wsum
|
||||
csum_partial_copy_from_user(const void __user *src, void *dst,
|
||||
int len, __wsum sum, int *csum_err)
|
||||
{
|
||||
/*
|
||||
* GCC doesn't like more than 10 operands for the asm
|
||||
* statements so we have to use tmp2 for the error
|
||||
* code.
|
||||
*/
|
||||
unsigned long tmp1, tmp2;
|
||||
|
||||
__asm__("movel %2,%4\n\t"
|
||||
"btst #1,%4\n\t" /* Check alignment */
|
||||
"jeq 2f\n\t"
|
||||
"subql #2,%1\n\t" /* buff%4==2: treat first word */
|
||||
"jgt 1f\n\t"
|
||||
"addql #2,%1\n\t" /* len was == 2, treat only rest */
|
||||
"jra 4f\n"
|
||||
"1:\n"
|
||||
"10:\t"
|
||||
"movesw %2@+,%4\n\t" /* add first word to sum */
|
||||
"addw %4,%0\n\t"
|
||||
"movew %4,%3@+\n\t"
|
||||
"clrl %4\n\t"
|
||||
"addxl %4,%0\n" /* add X bit */
|
||||
"2:\t"
|
||||
/* unrolled loop for the main part: do 8 longs at once */
|
||||
"movel %1,%4\n\t" /* save len in tmp1 */
|
||||
"lsrl #5,%1\n\t" /* len/32 */
|
||||
"jeq 2f\n\t" /* not enough... */
|
||||
"subql #1,%1\n"
|
||||
"1:\n"
|
||||
"11:\t"
|
||||
"movesl %2@+,%5\n\t"
|
||||
"addxl %5,%0\n\t"
|
||||
"movel %5,%3@+\n\t"
|
||||
"12:\t"
|
||||
"movesl %2@+,%5\n\t"
|
||||
"addxl %5,%0\n\t"
|
||||
"movel %5,%3@+\n\t"
|
||||
"13:\t"
|
||||
"movesl %2@+,%5\n\t"
|
||||
"addxl %5,%0\n\t"
|
||||
"movel %5,%3@+\n\t"
|
||||
"14:\t"
|
||||
"movesl %2@+,%5\n\t"
|
||||
"addxl %5,%0\n\t"
|
||||
"movel %5,%3@+\n\t"
|
||||
"15:\t"
|
||||
"movesl %2@+,%5\n\t"
|
||||
"addxl %5,%0\n\t"
|
||||
"movel %5,%3@+\n\t"
|
||||
"16:\t"
|
||||
"movesl %2@+,%5\n\t"
|
||||
"addxl %5,%0\n\t"
|
||||
"movel %5,%3@+\n\t"
|
||||
"17:\t"
|
||||
"movesl %2@+,%5\n\t"
|
||||
"addxl %5,%0\n\t"
|
||||
"movel %5,%3@+\n\t"
|
||||
"18:\t"
|
||||
"movesl %2@+,%5\n\t"
|
||||
"addxl %5,%0\n\t"
|
||||
"movel %5,%3@+\n\t"
|
||||
"dbra %1,1b\n\t"
|
||||
"clrl %5\n\t"
|
||||
"addxl %5,%0\n\t" /* add X bit */
|
||||
"clrw %1\n\t"
|
||||
"subql #1,%1\n\t"
|
||||
"jcc 1b\n"
|
||||
"2:\t"
|
||||
"movel %4,%1\n\t" /* restore len from tmp1 */
|
||||
"andw #0x1c,%4\n\t" /* number of rest longs */
|
||||
"jeq 4f\n\t"
|
||||
"lsrw #2,%4\n\t"
|
||||
"subqw #1,%4\n"
|
||||
"3:\n"
|
||||
/* loop for rest longs */
|
||||
"19:\t"
|
||||
"movesl %2@+,%5\n\t"
|
||||
"addxl %5,%0\n\t"
|
||||
"movel %5,%3@+\n\t"
|
||||
"dbra %4,3b\n\t"
|
||||
"clrl %5\n\t"
|
||||
"addxl %5,%0\n" /* add X bit */
|
||||
"4:\t"
|
||||
/* now check for rest bytes that do not fit into longs */
|
||||
"andw #3,%1\n\t"
|
||||
"jeq 7f\n\t"
|
||||
"clrl %5\n\t" /* clear tmp2 for rest bytes */
|
||||
"subqw #2,%1\n\t"
|
||||
"jlt 5f\n\t"
|
||||
"20:\t"
|
||||
"movesw %2@+,%5\n\t" /* have rest >= 2: get word */
|
||||
"movew %5,%3@+\n\t"
|
||||
"swap %5\n\t" /* into bits 16..31 */
|
||||
"tstw %1\n\t" /* another byte? */
|
||||
"jeq 6f\n"
|
||||
"5:\n"
|
||||
"21:\t"
|
||||
"movesb %2@,%5\n\t" /* have odd rest: get byte */
|
||||
"moveb %5,%3@+\n\t"
|
||||
"lslw #8,%5\n\t" /* into bits 8..15; 16..31 untouched */
|
||||
"6:\t"
|
||||
"addl %5,%0\n\t" /* now add rest long to sum */
|
||||
"clrl %5\n\t"
|
||||
"addxl %5,%0\n\t" /* add X bit */
|
||||
"7:\t"
|
||||
"clrl %5\n" /* no error - clear return value */
|
||||
"8:\n"
|
||||
".section .fixup,\"ax\"\n"
|
||||
".even\n"
|
||||
/* If any exception occurs zero out the rest.
|
||||
Similarities with the code above are intentional :-) */
|
||||
"90:\t"
|
||||
"clrw %3@+\n\t"
|
||||
"movel %1,%4\n\t"
|
||||
"lsrl #5,%1\n\t"
|
||||
"jeq 1f\n\t"
|
||||
"subql #1,%1\n"
|
||||
"91:\t"
|
||||
"clrl %3@+\n"
|
||||
"92:\t"
|
||||
"clrl %3@+\n"
|
||||
"93:\t"
|
||||
"clrl %3@+\n"
|
||||
"94:\t"
|
||||
"clrl %3@+\n"
|
||||
"95:\t"
|
||||
"clrl %3@+\n"
|
||||
"96:\t"
|
||||
"clrl %3@+\n"
|
||||
"97:\t"
|
||||
"clrl %3@+\n"
|
||||
"98:\t"
|
||||
"clrl %3@+\n\t"
|
||||
"dbra %1,91b\n\t"
|
||||
"clrw %1\n\t"
|
||||
"subql #1,%1\n\t"
|
||||
"jcc 91b\n"
|
||||
"1:\t"
|
||||
"movel %4,%1\n\t"
|
||||
"andw #0x1c,%4\n\t"
|
||||
"jeq 1f\n\t"
|
||||
"lsrw #2,%4\n\t"
|
||||
"subqw #1,%4\n"
|
||||
"99:\t"
|
||||
"clrl %3@+\n\t"
|
||||
"dbra %4,99b\n\t"
|
||||
"1:\t"
|
||||
"andw #3,%1\n\t"
|
||||
"jeq 9f\n"
|
||||
"100:\t"
|
||||
"clrw %3@+\n\t"
|
||||
"tstw %1\n\t"
|
||||
"jeq 9f\n"
|
||||
"101:\t"
|
||||
"clrb %3@+\n"
|
||||
"9:\t"
|
||||
#define STR(X) STR1(X)
|
||||
#define STR1(X) #X
|
||||
"moveq #-" STR(EFAULT) ",%5\n\t"
|
||||
"jra 8b\n"
|
||||
".previous\n"
|
||||
".section __ex_table,\"a\"\n"
|
||||
".long 10b,90b\n"
|
||||
".long 11b,91b\n"
|
||||
".long 12b,92b\n"
|
||||
".long 13b,93b\n"
|
||||
".long 14b,94b\n"
|
||||
".long 15b,95b\n"
|
||||
".long 16b,96b\n"
|
||||
".long 17b,97b\n"
|
||||
".long 18b,98b\n"
|
||||
".long 19b,99b\n"
|
||||
".long 20b,100b\n"
|
||||
".long 21b,101b\n"
|
||||
".previous"
|
||||
: "=d" (sum), "=d" (len), "=a" (src), "=a" (dst),
|
||||
"=&d" (tmp1), "=d" (tmp2)
|
||||
: "0" (sum), "1" (len), "2" (src), "3" (dst)
|
||||
);
|
||||
|
||||
*csum_err = tmp2;
|
||||
|
||||
return(sum);
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(csum_partial_copy_from_user);
|
||||
|
||||
|
||||
/*
|
||||
* copy from kernel space while checksumming, otherwise like csum_partial
|
||||
*/
|
||||
|
||||
__wsum
|
||||
csum_partial_copy_nocheck(const void *src, void *dst, int len, __wsum sum)
|
||||
{
|
||||
unsigned long tmp1, tmp2;
|
||||
__asm__("movel %2,%4\n\t"
|
||||
"btst #1,%4\n\t" /* Check alignment */
|
||||
"jeq 2f\n\t"
|
||||
"subql #2,%1\n\t" /* buff%4==2: treat first word */
|
||||
"jgt 1f\n\t"
|
||||
"addql #2,%1\n\t" /* len was == 2, treat only rest */
|
||||
"jra 4f\n"
|
||||
"1:\t"
|
||||
"movew %2@+,%4\n\t" /* add first word to sum */
|
||||
"addw %4,%0\n\t"
|
||||
"movew %4,%3@+\n\t"
|
||||
"clrl %4\n\t"
|
||||
"addxl %4,%0\n" /* add X bit */
|
||||
"2:\t"
|
||||
/* unrolled loop for the main part: do 8 longs at once */
|
||||
"movel %1,%4\n\t" /* save len in tmp1 */
|
||||
"lsrl #5,%1\n\t" /* len/32 */
|
||||
"jeq 2f\n\t" /* not enough... */
|
||||
"subql #1,%1\n"
|
||||
"1:\t"
|
||||
"movel %2@+,%5\n\t"
|
||||
"addxl %5,%0\n\t"
|
||||
"movel %5,%3@+\n\t"
|
||||
"movel %2@+,%5\n\t"
|
||||
"addxl %5,%0\n\t"
|
||||
"movel %5,%3@+\n\t"
|
||||
"movel %2@+,%5\n\t"
|
||||
"addxl %5,%0\n\t"
|
||||
"movel %5,%3@+\n\t"
|
||||
"movel %2@+,%5\n\t"
|
||||
"addxl %5,%0\n\t"
|
||||
"movel %5,%3@+\n\t"
|
||||
"movel %2@+,%5\n\t"
|
||||
"addxl %5,%0\n\t"
|
||||
"movel %5,%3@+\n\t"
|
||||
"movel %2@+,%5\n\t"
|
||||
"addxl %5,%0\n\t"
|
||||
"movel %5,%3@+\n\t"
|
||||
"movel %2@+,%5\n\t"
|
||||
"addxl %5,%0\n\t"
|
||||
"movel %5,%3@+\n\t"
|
||||
"movel %2@+,%5\n\t"
|
||||
"addxl %5,%0\n\t"
|
||||
"movel %5,%3@+\n\t"
|
||||
"dbra %1,1b\n\t"
|
||||
"clrl %5\n\t"
|
||||
"addxl %5,%0\n\t" /* add X bit */
|
||||
"clrw %1\n\t"
|
||||
"subql #1,%1\n\t"
|
||||
"jcc 1b\n"
|
||||
"2:\t"
|
||||
"movel %4,%1\n\t" /* restore len from tmp1 */
|
||||
"andw #0x1c,%4\n\t" /* number of rest longs */
|
||||
"jeq 4f\n\t"
|
||||
"lsrw #2,%4\n\t"
|
||||
"subqw #1,%4\n"
|
||||
"3:\t"
|
||||
/* loop for rest longs */
|
||||
"movel %2@+,%5\n\t"
|
||||
"addxl %5,%0\n\t"
|
||||
"movel %5,%3@+\n\t"
|
||||
"dbra %4,3b\n\t"
|
||||
"clrl %5\n\t"
|
||||
"addxl %5,%0\n" /* add X bit */
|
||||
"4:\t"
|
||||
/* now check for rest bytes that do not fit into longs */
|
||||
"andw #3,%1\n\t"
|
||||
"jeq 7f\n\t"
|
||||
"clrl %5\n\t" /* clear tmp2 for rest bytes */
|
||||
"subqw #2,%1\n\t"
|
||||
"jlt 5f\n\t"
|
||||
"movew %2@+,%5\n\t" /* have rest >= 2: get word */
|
||||
"movew %5,%3@+\n\t"
|
||||
"swap %5\n\t" /* into bits 16..31 */
|
||||
"tstw %1\n\t" /* another byte? */
|
||||
"jeq 6f\n"
|
||||
"5:\t"
|
||||
"moveb %2@,%5\n\t" /* have odd rest: get byte */
|
||||
"moveb %5,%3@+\n\t"
|
||||
"lslw #8,%5\n" /* into bits 8..15; 16..31 untouched */
|
||||
"6:\t"
|
||||
"addl %5,%0\n\t" /* now add rest long to sum */
|
||||
"clrl %5\n\t"
|
||||
"addxl %5,%0\n" /* add X bit */
|
||||
"7:\t"
|
||||
: "=d" (sum), "=d" (len), "=a" (src), "=a" (dst),
|
||||
"=&d" (tmp1), "=&d" (tmp2)
|
||||
: "0" (sum), "1" (len), "2" (src), "3" (dst)
|
||||
);
|
||||
return(sum);
|
||||
}
|
||||
EXPORT_SYMBOL(csum_partial_copy_nocheck);
|
@ -1,63 +1,5 @@
|
||||
/* muldi3.c extracted from gcc-2.7.2.3/libgcc2.c and
|
||||
gcc-2.7.2.3/longlong.h which is: */
|
||||
/* Copyright (C) 1989, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU CC.
|
||||
|
||||
GNU CC is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU CC is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU CC; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
#define BITS_PER_UNIT 8
|
||||
|
||||
#define umul_ppmm(w1, w0, u, v) \
|
||||
__asm__ ("mulu%.l %3,%1:%0" \
|
||||
: "=d" ((USItype)(w0)), \
|
||||
"=d" ((USItype)(w1)) \
|
||||
: "%0" ((USItype)(u)), \
|
||||
"dmi" ((USItype)(v)))
|
||||
|
||||
#define __umulsidi3(u, v) \
|
||||
({DIunion __w; \
|
||||
umul_ppmm (__w.s.high, __w.s.low, u, v); \
|
||||
__w.ll; })
|
||||
|
||||
typedef int SItype __attribute__ ((mode (SI)));
|
||||
typedef unsigned int USItype __attribute__ ((mode (SI)));
|
||||
typedef int DItype __attribute__ ((mode (DI)));
|
||||
typedef int word_type __attribute__ ((mode (__word__)));
|
||||
|
||||
struct DIstruct {SItype high, low;};
|
||||
|
||||
typedef union
|
||||
{
|
||||
struct DIstruct s;
|
||||
DItype ll;
|
||||
} DIunion;
|
||||
|
||||
DItype
|
||||
__muldi3 (DItype u, DItype v)
|
||||
{
|
||||
DIunion w;
|
||||
DIunion uu, vv;
|
||||
|
||||
uu.ll = u,
|
||||
vv.ll = v;
|
||||
|
||||
w.ll = __umulsidi3 (uu.s.low, vv.s.low);
|
||||
w.s.high += ((USItype) uu.s.low * (USItype) vv.s.high
|
||||
+ (USItype) uu.s.high * (USItype) vv.s.low);
|
||||
|
||||
return w.ll;
|
||||
}
|
||||
#ifdef CONFIG_MMU
|
||||
#include "muldi3_mm.c"
|
||||
#else
|
||||
#include "muldi3_no.c"
|
||||
#endif
|
||||
|
@ -1,4 +1,5 @@
|
||||
/* ashrdi3.c extracted from gcc-2.7.2/libgcc2.c which is: */
|
||||
/* muldi3.c extracted from gcc-2.7.2.3/libgcc2.c and
|
||||
gcc-2.7.2.3/longlong.h which is: */
|
||||
/* Copyright (C) 1989, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU CC.
|
||||
@ -20,7 +21,19 @@ Boston, MA 02111-1307, USA. */
|
||||
|
||||
#define BITS_PER_UNIT 8
|
||||
|
||||
typedef int SItype __attribute__ ((mode (SI)));
|
||||
#define umul_ppmm(w1, w0, u, v) \
|
||||
__asm__ ("mulu%.l %3,%1:%0" \
|
||||
: "=d" ((USItype)(w0)), \
|
||||
"=d" ((USItype)(w1)) \
|
||||
: "%0" ((USItype)(u)), \
|
||||
"dmi" ((USItype)(v)))
|
||||
|
||||
#define __umulsidi3(u, v) \
|
||||
({DIunion __w; \
|
||||
umul_ppmm (__w.s.high, __w.s.low, u, v); \
|
||||
__w.ll; })
|
||||
|
||||
typedef int SItype __attribute__ ((mode (SI)));
|
||||
typedef unsigned int USItype __attribute__ ((mode (SI)));
|
||||
typedef int DItype __attribute__ ((mode (DI)));
|
||||
typedef int word_type __attribute__ ((mode (__word__)));
|
||||
@ -34,30 +47,17 @@ typedef union
|
||||
} DIunion;
|
||||
|
||||
DItype
|
||||
__ashrdi3 (DItype u, word_type b)
|
||||
__muldi3 (DItype u, DItype v)
|
||||
{
|
||||
DIunion w;
|
||||
word_type bm;
|
||||
DIunion uu;
|
||||
DIunion uu, vv;
|
||||
|
||||
if (b == 0)
|
||||
return u;
|
||||
uu.ll = u,
|
||||
vv.ll = v;
|
||||
|
||||
uu.ll = u;
|
||||
|
||||
bm = (sizeof (SItype) * BITS_PER_UNIT) - b;
|
||||
if (bm <= 0)
|
||||
{
|
||||
/* w.s.high = 1..1 or 0..0 */
|
||||
w.s.high = uu.s.high >> (sizeof (SItype) * BITS_PER_UNIT - 1);
|
||||
w.s.low = uu.s.high >> -bm;
|
||||
}
|
||||
else
|
||||
{
|
||||
USItype carries = (USItype)uu.s.high << bm;
|
||||
w.s.high = uu.s.high >> b;
|
||||
w.s.low = ((USItype)uu.s.low >> b) | carries;
|
||||
}
|
||||
w.ll = __umulsidi3 (uu.s.low, vv.s.low);
|
||||
w.s.high += ((USItype) uu.s.low * (USItype) vv.s.high
|
||||
+ (USItype) uu.s.high * (USItype) vv.s.low);
|
||||
|
||||
return w.ll;
|
||||
}
|
@ -1,8 +1,5 @@
|
||||
#
|
||||
# Makefile for the linux m68k-specific parts of the memory manager.
|
||||
#
|
||||
|
||||
obj-y := cache.o init.o fault.o hwtest.o
|
||||
|
||||
obj-$(CONFIG_MMU_MOTOROLA) += kmap.o memory.o motorola.o
|
||||
obj-$(CONFIG_MMU_SUN3) += sun3kmap.o sun3mmu.o
|
||||
ifdef CONFIG_MMU
|
||||
include arch/m68k/mm/Makefile_mm
|
||||
else
|
||||
include arch/m68k/mm/Makefile_no
|
||||
endif
|
||||
|
8
arch/m68k/mm/Makefile_mm
Normal file
8
arch/m68k/mm/Makefile_mm
Normal file
@ -0,0 +1,8 @@
|
||||
#
|
||||
# Makefile for the linux m68k-specific parts of the memory manager.
|
||||
#
|
||||
|
||||
obj-y := cache.o init.o fault.o hwtest.o
|
||||
|
||||
obj-$(CONFIG_MMU_MOTOROLA) += kmap.o memory.o motorola.o
|
||||
obj-$(CONFIG_MMU_SUN3) += sun3kmap.o sun3mmu.o
|
@ -1,150 +1,5 @@
|
||||
/*
|
||||
* linux/arch/m68k/mm/init.c
|
||||
*
|
||||
* Copyright (C) 1995 Hamish Macdonald
|
||||
*
|
||||
* Contains common initialization routines, specific init code moved
|
||||
* to motorola.c and sun3mmu.c
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/signal.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/swap.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/bootmem.h>
|
||||
#include <linux/gfp.h>
|
||||
|
||||
#include <asm/setup.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/page.h>
|
||||
#include <asm/pgalloc.h>
|
||||
#include <asm/system.h>
|
||||
#include <asm/machdep.h>
|
||||
#include <asm/io.h>
|
||||
#ifdef CONFIG_ATARI
|
||||
#include <asm/atari_stram.h>
|
||||
#endif
|
||||
#include <asm/sections.h>
|
||||
#include <asm/tlb.h>
|
||||
|
||||
DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
|
||||
|
||||
pg_data_t pg_data_map[MAX_NUMNODES];
|
||||
EXPORT_SYMBOL(pg_data_map);
|
||||
|
||||
int m68k_virt_to_node_shift;
|
||||
|
||||
#ifndef CONFIG_SINGLE_MEMORY_CHUNK
|
||||
pg_data_t *pg_data_table[65];
|
||||
EXPORT_SYMBOL(pg_data_table);
|
||||
#endif
|
||||
|
||||
void __init m68k_setup_node(int node)
|
||||
{
|
||||
#ifndef CONFIG_SINGLE_MEMORY_CHUNK
|
||||
struct mem_info *info = m68k_memory + node;
|
||||
int i, end;
|
||||
|
||||
i = (unsigned long)phys_to_virt(info->addr) >> __virt_to_node_shift();
|
||||
end = (unsigned long)phys_to_virt(info->addr + info->size - 1) >> __virt_to_node_shift();
|
||||
for (; i <= end; i++) {
|
||||
if (pg_data_table[i])
|
||||
printk("overlap at %u for chunk %u\n", i, node);
|
||||
pg_data_table[i] = pg_data_map + node;
|
||||
}
|
||||
#endif
|
||||
pg_data_map[node].bdata = bootmem_node_data + node;
|
||||
node_set_online(node);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* ZERO_PAGE is a special page that is used for zero-initialized
|
||||
* data and COW.
|
||||
*/
|
||||
|
||||
void *empty_zero_page;
|
||||
EXPORT_SYMBOL(empty_zero_page);
|
||||
|
||||
extern void init_pointer_table(unsigned long ptable);
|
||||
|
||||
/* References to section boundaries */
|
||||
|
||||
extern pmd_t *zero_pgtable;
|
||||
|
||||
void __init mem_init(void)
|
||||
{
|
||||
pg_data_t *pgdat;
|
||||
int codepages = 0;
|
||||
int datapages = 0;
|
||||
int initpages = 0;
|
||||
int i;
|
||||
|
||||
#ifdef CONFIG_ATARI
|
||||
if (MACH_IS_ATARI)
|
||||
atari_stram_mem_init_hook();
|
||||
#endif
|
||||
|
||||
/* this will put all memory onto the freelists */
|
||||
totalram_pages = num_physpages = 0;
|
||||
for_each_online_pgdat(pgdat) {
|
||||
num_physpages += pgdat->node_present_pages;
|
||||
|
||||
totalram_pages += free_all_bootmem_node(pgdat);
|
||||
for (i = 0; i < pgdat->node_spanned_pages; i++) {
|
||||
struct page *page = pgdat->node_mem_map + i;
|
||||
char *addr = page_to_virt(page);
|
||||
|
||||
if (!PageReserved(page))
|
||||
continue;
|
||||
if (addr >= _text &&
|
||||
addr < _etext)
|
||||
codepages++;
|
||||
else if (addr >= __init_begin &&
|
||||
addr < __init_end)
|
||||
initpages++;
|
||||
else
|
||||
datapages++;
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef CONFIG_SUN3
|
||||
/* insert pointer tables allocated so far into the tablelist */
|
||||
init_pointer_table((unsigned long)kernel_pg_dir);
|
||||
for (i = 0; i < PTRS_PER_PGD; i++) {
|
||||
if (pgd_present(kernel_pg_dir[i]))
|
||||
init_pointer_table(__pgd_page(kernel_pg_dir[i]));
|
||||
}
|
||||
|
||||
/* insert also pointer table that we used to unmap the zero page */
|
||||
if (zero_pgtable)
|
||||
init_pointer_table((unsigned long)zero_pgtable);
|
||||
#endif
|
||||
|
||||
printk("Memory: %luk/%luk available (%dk kernel code, %dk data, %dk init)\n",
|
||||
nr_free_pages() << (PAGE_SHIFT-10),
|
||||
totalram_pages << (PAGE_SHIFT-10),
|
||||
codepages << (PAGE_SHIFT-10),
|
||||
datapages << (PAGE_SHIFT-10),
|
||||
initpages << (PAGE_SHIFT-10));
|
||||
}
|
||||
|
||||
#ifdef CONFIG_BLK_DEV_INITRD
|
||||
void free_initrd_mem(unsigned long start, unsigned long end)
|
||||
{
|
||||
int pages = 0;
|
||||
for (; start < end; start += PAGE_SIZE) {
|
||||
ClearPageReserved(virt_to_page(start));
|
||||
init_page_count(virt_to_page(start));
|
||||
free_page(start);
|
||||
totalram_pages++;
|
||||
pages++;
|
||||
}
|
||||
printk ("Freeing initrd memory: %dk freed\n", pages);
|
||||
}
|
||||
#ifdef CONFIG_MMU
|
||||
#include "init_mm.c"
|
||||
#else
|
||||
#include "init_no.c"
|
||||
#endif
|
||||
|
150
arch/m68k/mm/init_mm.c
Normal file
150
arch/m68k/mm/init_mm.c
Normal file
@ -0,0 +1,150 @@
|
||||
/*
|
||||
* linux/arch/m68k/mm/init.c
|
||||
*
|
||||
* Copyright (C) 1995 Hamish Macdonald
|
||||
*
|
||||
* Contains common initialization routines, specific init code moved
|
||||
* to motorola.c and sun3mmu.c
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/signal.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/swap.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/bootmem.h>
|
||||
#include <linux/gfp.h>
|
||||
|
||||
#include <asm/setup.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/page.h>
|
||||
#include <asm/pgalloc.h>
|
||||
#include <asm/system.h>
|
||||
#include <asm/machdep.h>
|
||||
#include <asm/io.h>
|
||||
#ifdef CONFIG_ATARI
|
||||
#include <asm/atari_stram.h>
|
||||
#endif
|
||||
#include <asm/sections.h>
|
||||
#include <asm/tlb.h>
|
||||
|
||||
DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
|
||||
|
||||
pg_data_t pg_data_map[MAX_NUMNODES];
|
||||
EXPORT_SYMBOL(pg_data_map);
|
||||
|
||||
int m68k_virt_to_node_shift;
|
||||
|
||||
#ifndef CONFIG_SINGLE_MEMORY_CHUNK
|
||||
pg_data_t *pg_data_table[65];
|
||||
EXPORT_SYMBOL(pg_data_table);
|
||||
#endif
|
||||
|
||||
void __init m68k_setup_node(int node)
|
||||
{
|
||||
#ifndef CONFIG_SINGLE_MEMORY_CHUNK
|
||||
struct mem_info *info = m68k_memory + node;
|
||||
int i, end;
|
||||
|
||||
i = (unsigned long)phys_to_virt(info->addr) >> __virt_to_node_shift();
|
||||
end = (unsigned long)phys_to_virt(info->addr + info->size - 1) >> __virt_to_node_shift();
|
||||
for (; i <= end; i++) {
|
||||
if (pg_data_table[i])
|
||||
printk("overlap at %u for chunk %u\n", i, node);
|
||||
pg_data_table[i] = pg_data_map + node;
|
||||
}
|
||||
#endif
|
||||
pg_data_map[node].bdata = bootmem_node_data + node;
|
||||
node_set_online(node);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* ZERO_PAGE is a special page that is used for zero-initialized
|
||||
* data and COW.
|
||||
*/
|
||||
|
||||
void *empty_zero_page;
|
||||
EXPORT_SYMBOL(empty_zero_page);
|
||||
|
||||
extern void init_pointer_table(unsigned long ptable);
|
||||
|
||||
/* References to section boundaries */
|
||||
|
||||
extern pmd_t *zero_pgtable;
|
||||
|
||||
void __init mem_init(void)
|
||||
{
|
||||
pg_data_t *pgdat;
|
||||
int codepages = 0;
|
||||
int datapages = 0;
|
||||
int initpages = 0;
|
||||
int i;
|
||||
|
||||
#ifdef CONFIG_ATARI
|
||||
if (MACH_IS_ATARI)
|
||||
atari_stram_mem_init_hook();
|
||||
#endif
|
||||
|
||||
/* this will put all memory onto the freelists */
|
||||
totalram_pages = num_physpages = 0;
|
||||
for_each_online_pgdat(pgdat) {
|
||||
num_physpages += pgdat->node_present_pages;
|
||||
|
||||
totalram_pages += free_all_bootmem_node(pgdat);
|
||||
for (i = 0; i < pgdat->node_spanned_pages; i++) {
|
||||
struct page *page = pgdat->node_mem_map + i;
|
||||
char *addr = page_to_virt(page);
|
||||
|
||||
if (!PageReserved(page))
|
||||
continue;
|
||||
if (addr >= _text &&
|
||||
addr < _etext)
|
||||
codepages++;
|
||||
else if (addr >= __init_begin &&
|
||||
addr < __init_end)
|
||||
initpages++;
|
||||
else
|
||||
datapages++;
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef CONFIG_SUN3
|
||||
/* insert pointer tables allocated so far into the tablelist */
|
||||
init_pointer_table((unsigned long)kernel_pg_dir);
|
||||
for (i = 0; i < PTRS_PER_PGD; i++) {
|
||||
if (pgd_present(kernel_pg_dir[i]))
|
||||
init_pointer_table(__pgd_page(kernel_pg_dir[i]));
|
||||
}
|
||||
|
||||
/* insert also pointer table that we used to unmap the zero page */
|
||||
if (zero_pgtable)
|
||||
init_pointer_table((unsigned long)zero_pgtable);
|
||||
#endif
|
||||
|
||||
printk("Memory: %luk/%luk available (%dk kernel code, %dk data, %dk init)\n",
|
||||
nr_free_pages() << (PAGE_SHIFT-10),
|
||||
totalram_pages << (PAGE_SHIFT-10),
|
||||
codepages << (PAGE_SHIFT-10),
|
||||
datapages << (PAGE_SHIFT-10),
|
||||
initpages << (PAGE_SHIFT-10));
|
||||
}
|
||||
|
||||
#ifdef CONFIG_BLK_DEV_INITRD
|
||||
void free_initrd_mem(unsigned long start, unsigned long end)
|
||||
{
|
||||
int pages = 0;
|
||||
for (; start < end; start += PAGE_SIZE) {
|
||||
ClearPageReserved(virt_to_page(start));
|
||||
init_page_count(virt_to_page(start));
|
||||
free_page(start);
|
||||
totalram_pages++;
|
||||
pages++;
|
||||
}
|
||||
printk ("Freeing initrd memory: %dk freed\n", pages);
|
||||
}
|
||||
#endif
|
@ -1,367 +1,5 @@
|
||||
/*
|
||||
* linux/arch/m68k/mm/kmap.c
|
||||
*
|
||||
* Copyright (C) 1997 Roman Hodek
|
||||
*
|
||||
* 10/01/99 cleaned up the code and changing to the same interface
|
||||
* used by other architectures /Roman Zippel
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/vmalloc.h>
|
||||
|
||||
#include <asm/setup.h>
|
||||
#include <asm/segment.h>
|
||||
#include <asm/page.h>
|
||||
#include <asm/pgalloc.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/system.h>
|
||||
|
||||
#undef DEBUG
|
||||
|
||||
#define PTRTREESIZE (256*1024)
|
||||
|
||||
/*
|
||||
* For 040/060 we can use the virtual memory area like other architectures,
|
||||
* but for 020/030 we want to use early termination page descriptor and we
|
||||
* can't mix this with normal page descriptors, so we have to copy that code
|
||||
* (mm/vmalloc.c) and return appriorate aligned addresses.
|
||||
*/
|
||||
|
||||
#ifdef CPU_M68040_OR_M68060_ONLY
|
||||
|
||||
#define IO_SIZE PAGE_SIZE
|
||||
|
||||
static inline struct vm_struct *get_io_area(unsigned long size)
|
||||
{
|
||||
return get_vm_area(size, VM_IOREMAP);
|
||||
}
|
||||
|
||||
|
||||
static inline void free_io_area(void *addr)
|
||||
{
|
||||
vfree((void *)(PAGE_MASK & (unsigned long)addr));
|
||||
}
|
||||
|
||||
#ifdef CONFIG_MMU
|
||||
#include "kmap_mm.c"
|
||||
#else
|
||||
|
||||
#define IO_SIZE (256*1024)
|
||||
|
||||
static struct vm_struct *iolist;
|
||||
|
||||
static struct vm_struct *get_io_area(unsigned long size)
|
||||
{
|
||||
unsigned long addr;
|
||||
struct vm_struct **p, *tmp, *area;
|
||||
|
||||
area = kmalloc(sizeof(*area), GFP_KERNEL);
|
||||
if (!area)
|
||||
return NULL;
|
||||
addr = KMAP_START;
|
||||
for (p = &iolist; (tmp = *p) ; p = &tmp->next) {
|
||||
if (size + addr < (unsigned long)tmp->addr)
|
||||
break;
|
||||
if (addr > KMAP_END-size) {
|
||||
kfree(area);
|
||||
return NULL;
|
||||
}
|
||||
addr = tmp->size + (unsigned long)tmp->addr;
|
||||
}
|
||||
area->addr = (void *)addr;
|
||||
area->size = size + IO_SIZE;
|
||||
area->next = *p;
|
||||
*p = area;
|
||||
return area;
|
||||
}
|
||||
|
||||
static inline void free_io_area(void *addr)
|
||||
{
|
||||
struct vm_struct **p, *tmp;
|
||||
|
||||
if (!addr)
|
||||
return;
|
||||
addr = (void *)((unsigned long)addr & -IO_SIZE);
|
||||
for (p = &iolist ; (tmp = *p) ; p = &tmp->next) {
|
||||
if (tmp->addr == addr) {
|
||||
*p = tmp->next;
|
||||
__iounmap(tmp->addr, tmp->size);
|
||||
kfree(tmp);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#include "kmap_no.c"
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Map some physical address range into the kernel address space.
|
||||
*/
|
||||
/* Rewritten by Andreas Schwab to remove all races. */
|
||||
|
||||
void __iomem *__ioremap(unsigned long physaddr, unsigned long size, int cacheflag)
|
||||
{
|
||||
struct vm_struct *area;
|
||||
unsigned long virtaddr, retaddr;
|
||||
long offset;
|
||||
pgd_t *pgd_dir;
|
||||
pmd_t *pmd_dir;
|
||||
pte_t *pte_dir;
|
||||
|
||||
/*
|
||||
* Don't allow mappings that wrap..
|
||||
*/
|
||||
if (!size || physaddr > (unsigned long)(-size))
|
||||
return NULL;
|
||||
|
||||
#ifdef CONFIG_AMIGA
|
||||
if (MACH_IS_AMIGA) {
|
||||
if ((physaddr >= 0x40000000) && (physaddr + size < 0x60000000)
|
||||
&& (cacheflag == IOMAP_NOCACHE_SER))
|
||||
return (void __iomem *)physaddr;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG
|
||||
printk("ioremap: 0x%lx,0x%lx(%d) - ", physaddr, size, cacheflag);
|
||||
#endif
|
||||
/*
|
||||
* Mappings have to be aligned
|
||||
*/
|
||||
offset = physaddr & (IO_SIZE - 1);
|
||||
physaddr &= -IO_SIZE;
|
||||
size = (size + offset + IO_SIZE - 1) & -IO_SIZE;
|
||||
|
||||
/*
|
||||
* Ok, go for it..
|
||||
*/
|
||||
area = get_io_area(size);
|
||||
if (!area)
|
||||
return NULL;
|
||||
|
||||
virtaddr = (unsigned long)area->addr;
|
||||
retaddr = virtaddr + offset;
|
||||
#ifdef DEBUG
|
||||
printk("0x%lx,0x%lx,0x%lx", physaddr, virtaddr, retaddr);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* add cache and table flags to physical address
|
||||
*/
|
||||
if (CPU_IS_040_OR_060) {
|
||||
physaddr |= (_PAGE_PRESENT | _PAGE_GLOBAL040 |
|
||||
_PAGE_ACCESSED | _PAGE_DIRTY);
|
||||
switch (cacheflag) {
|
||||
case IOMAP_FULL_CACHING:
|
||||
physaddr |= _PAGE_CACHE040;
|
||||
break;
|
||||
case IOMAP_NOCACHE_SER:
|
||||
default:
|
||||
physaddr |= _PAGE_NOCACHE_S;
|
||||
break;
|
||||
case IOMAP_NOCACHE_NONSER:
|
||||
physaddr |= _PAGE_NOCACHE;
|
||||
break;
|
||||
case IOMAP_WRITETHROUGH:
|
||||
physaddr |= _PAGE_CACHE040W;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
physaddr |= (_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_DIRTY);
|
||||
switch (cacheflag) {
|
||||
case IOMAP_NOCACHE_SER:
|
||||
case IOMAP_NOCACHE_NONSER:
|
||||
default:
|
||||
physaddr |= _PAGE_NOCACHE030;
|
||||
break;
|
||||
case IOMAP_FULL_CACHING:
|
||||
case IOMAP_WRITETHROUGH:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
while ((long)size > 0) {
|
||||
#ifdef DEBUG
|
||||
if (!(virtaddr & (PTRTREESIZE-1)))
|
||||
printk ("\npa=%#lx va=%#lx ", physaddr, virtaddr);
|
||||
#endif
|
||||
pgd_dir = pgd_offset_k(virtaddr);
|
||||
pmd_dir = pmd_alloc(&init_mm, pgd_dir, virtaddr);
|
||||
if (!pmd_dir) {
|
||||
printk("ioremap: no mem for pmd_dir\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (CPU_IS_020_OR_030) {
|
||||
pmd_dir->pmd[(virtaddr/PTRTREESIZE) & 15] = physaddr;
|
||||
physaddr += PTRTREESIZE;
|
||||
virtaddr += PTRTREESIZE;
|
||||
size -= PTRTREESIZE;
|
||||
} else {
|
||||
pte_dir = pte_alloc_kernel(pmd_dir, virtaddr);
|
||||
if (!pte_dir) {
|
||||
printk("ioremap: no mem for pte_dir\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pte_val(*pte_dir) = physaddr;
|
||||
virtaddr += PAGE_SIZE;
|
||||
physaddr += PAGE_SIZE;
|
||||
size -= PAGE_SIZE;
|
||||
}
|
||||
}
|
||||
#ifdef DEBUG
|
||||
printk("\n");
|
||||
#endif
|
||||
flush_tlb_all();
|
||||
|
||||
return (void __iomem *)retaddr;
|
||||
}
|
||||
EXPORT_SYMBOL(__ioremap);
|
||||
|
||||
/*
|
||||
* Unmap a ioremap()ed region again
|
||||
*/
|
||||
void iounmap(void __iomem *addr)
|
||||
{
|
||||
#ifdef CONFIG_AMIGA
|
||||
if ((!MACH_IS_AMIGA) ||
|
||||
(((unsigned long)addr < 0x40000000) ||
|
||||
((unsigned long)addr > 0x60000000)))
|
||||
free_io_area((__force void *)addr);
|
||||
#else
|
||||
free_io_area((__force void *)addr);
|
||||
#endif
|
||||
}
|
||||
EXPORT_SYMBOL(iounmap);
|
||||
|
||||
/*
|
||||
* __iounmap unmaps nearly everything, so be careful
|
||||
* it doesn't free currently pointer/page tables anymore but it
|
||||
* wans't used anyway and might be added later.
|
||||
*/
|
||||
void __iounmap(void *addr, unsigned long size)
|
||||
{
|
||||
unsigned long virtaddr = (unsigned long)addr;
|
||||
pgd_t *pgd_dir;
|
||||
pmd_t *pmd_dir;
|
||||
pte_t *pte_dir;
|
||||
|
||||
while ((long)size > 0) {
|
||||
pgd_dir = pgd_offset_k(virtaddr);
|
||||
if (pgd_bad(*pgd_dir)) {
|
||||
printk("iounmap: bad pgd(%08lx)\n", pgd_val(*pgd_dir));
|
||||
pgd_clear(pgd_dir);
|
||||
return;
|
||||
}
|
||||
pmd_dir = pmd_offset(pgd_dir, virtaddr);
|
||||
|
||||
if (CPU_IS_020_OR_030) {
|
||||
int pmd_off = (virtaddr/PTRTREESIZE) & 15;
|
||||
int pmd_type = pmd_dir->pmd[pmd_off] & _DESCTYPE_MASK;
|
||||
|
||||
if (pmd_type == _PAGE_PRESENT) {
|
||||
pmd_dir->pmd[pmd_off] = 0;
|
||||
virtaddr += PTRTREESIZE;
|
||||
size -= PTRTREESIZE;
|
||||
continue;
|
||||
} else if (pmd_type == 0)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (pmd_bad(*pmd_dir)) {
|
||||
printk("iounmap: bad pmd (%08lx)\n", pmd_val(*pmd_dir));
|
||||
pmd_clear(pmd_dir);
|
||||
return;
|
||||
}
|
||||
pte_dir = pte_offset_kernel(pmd_dir, virtaddr);
|
||||
|
||||
pte_val(*pte_dir) = 0;
|
||||
virtaddr += PAGE_SIZE;
|
||||
size -= PAGE_SIZE;
|
||||
}
|
||||
|
||||
flush_tlb_all();
|
||||
}
|
||||
|
||||
/*
|
||||
* Set new cache mode for some kernel address space.
|
||||
* The caller must push data for that range itself, if such data may already
|
||||
* be in the cache.
|
||||
*/
|
||||
void kernel_set_cachemode(void *addr, unsigned long size, int cmode)
|
||||
{
|
||||
unsigned long virtaddr = (unsigned long)addr;
|
||||
pgd_t *pgd_dir;
|
||||
pmd_t *pmd_dir;
|
||||
pte_t *pte_dir;
|
||||
|
||||
if (CPU_IS_040_OR_060) {
|
||||
switch (cmode) {
|
||||
case IOMAP_FULL_CACHING:
|
||||
cmode = _PAGE_CACHE040;
|
||||
break;
|
||||
case IOMAP_NOCACHE_SER:
|
||||
default:
|
||||
cmode = _PAGE_NOCACHE_S;
|
||||
break;
|
||||
case IOMAP_NOCACHE_NONSER:
|
||||
cmode = _PAGE_NOCACHE;
|
||||
break;
|
||||
case IOMAP_WRITETHROUGH:
|
||||
cmode = _PAGE_CACHE040W;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
switch (cmode) {
|
||||
case IOMAP_NOCACHE_SER:
|
||||
case IOMAP_NOCACHE_NONSER:
|
||||
default:
|
||||
cmode = _PAGE_NOCACHE030;
|
||||
break;
|
||||
case IOMAP_FULL_CACHING:
|
||||
case IOMAP_WRITETHROUGH:
|
||||
cmode = 0;
|
||||
}
|
||||
}
|
||||
|
||||
while ((long)size > 0) {
|
||||
pgd_dir = pgd_offset_k(virtaddr);
|
||||
if (pgd_bad(*pgd_dir)) {
|
||||
printk("iocachemode: bad pgd(%08lx)\n", pgd_val(*pgd_dir));
|
||||
pgd_clear(pgd_dir);
|
||||
return;
|
||||
}
|
||||
pmd_dir = pmd_offset(pgd_dir, virtaddr);
|
||||
|
||||
if (CPU_IS_020_OR_030) {
|
||||
int pmd_off = (virtaddr/PTRTREESIZE) & 15;
|
||||
|
||||
if ((pmd_dir->pmd[pmd_off] & _DESCTYPE_MASK) == _PAGE_PRESENT) {
|
||||
pmd_dir->pmd[pmd_off] = (pmd_dir->pmd[pmd_off] &
|
||||
_CACHEMASK040) | cmode;
|
||||
virtaddr += PTRTREESIZE;
|
||||
size -= PTRTREESIZE;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (pmd_bad(*pmd_dir)) {
|
||||
printk("iocachemode: bad pmd (%08lx)\n", pmd_val(*pmd_dir));
|
||||
pmd_clear(pmd_dir);
|
||||
return;
|
||||
}
|
||||
pte_dir = pte_offset_kernel(pmd_dir, virtaddr);
|
||||
|
||||
pte_val(*pte_dir) = (pte_val(*pte_dir) & _CACHEMASK040) | cmode;
|
||||
virtaddr += PAGE_SIZE;
|
||||
size -= PAGE_SIZE;
|
||||
}
|
||||
|
||||
flush_tlb_all();
|
||||
}
|
||||
EXPORT_SYMBOL(kernel_set_cachemode);
|
||||
|
367
arch/m68k/mm/kmap_mm.c
Normal file
367
arch/m68k/mm/kmap_mm.c
Normal file
@ -0,0 +1,367 @@
|
||||
/*
|
||||
* linux/arch/m68k/mm/kmap.c
|
||||
*
|
||||
* Copyright (C) 1997 Roman Hodek
|
||||
*
|
||||
* 10/01/99 cleaned up the code and changing to the same interface
|
||||
* used by other architectures /Roman Zippel
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/vmalloc.h>
|
||||
|
||||
#include <asm/setup.h>
|
||||
#include <asm/segment.h>
|
||||
#include <asm/page.h>
|
||||
#include <asm/pgalloc.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/system.h>
|
||||
|
||||
#undef DEBUG
|
||||
|
||||
#define PTRTREESIZE (256*1024)
|
||||
|
||||
/*
|
||||
* For 040/060 we can use the virtual memory area like other architectures,
|
||||
* but for 020/030 we want to use early termination page descriptor and we
|
||||
* can't mix this with normal page descriptors, so we have to copy that code
|
||||
* (mm/vmalloc.c) and return appriorate aligned addresses.
|
||||
*/
|
||||
|
||||
#ifdef CPU_M68040_OR_M68060_ONLY
|
||||
|
||||
#define IO_SIZE PAGE_SIZE
|
||||
|
||||
static inline struct vm_struct *get_io_area(unsigned long size)
|
||||
{
|
||||
return get_vm_area(size, VM_IOREMAP);
|
||||
}
|
||||
|
||||
|
||||
static inline void free_io_area(void *addr)
|
||||
{
|
||||
vfree((void *)(PAGE_MASK & (unsigned long)addr));
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#define IO_SIZE (256*1024)
|
||||
|
||||
static struct vm_struct *iolist;
|
||||
|
||||
static struct vm_struct *get_io_area(unsigned long size)
|
||||
{
|
||||
unsigned long addr;
|
||||
struct vm_struct **p, *tmp, *area;
|
||||
|
||||
area = kmalloc(sizeof(*area), GFP_KERNEL);
|
||||
if (!area)
|
||||
return NULL;
|
||||
addr = KMAP_START;
|
||||
for (p = &iolist; (tmp = *p) ; p = &tmp->next) {
|
||||
if (size + addr < (unsigned long)tmp->addr)
|
||||
break;
|
||||
if (addr > KMAP_END-size) {
|
||||
kfree(area);
|
||||
return NULL;
|
||||
}
|
||||
addr = tmp->size + (unsigned long)tmp->addr;
|
||||
}
|
||||
area->addr = (void *)addr;
|
||||
area->size = size + IO_SIZE;
|
||||
area->next = *p;
|
||||
*p = area;
|
||||
return area;
|
||||
}
|
||||
|
||||
static inline void free_io_area(void *addr)
|
||||
{
|
||||
struct vm_struct **p, *tmp;
|
||||
|
||||
if (!addr)
|
||||
return;
|
||||
addr = (void *)((unsigned long)addr & -IO_SIZE);
|
||||
for (p = &iolist ; (tmp = *p) ; p = &tmp->next) {
|
||||
if (tmp->addr == addr) {
|
||||
*p = tmp->next;
|
||||
__iounmap(tmp->addr, tmp->size);
|
||||
kfree(tmp);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Map some physical address range into the kernel address space.
|
||||
*/
|
||||
/* Rewritten by Andreas Schwab to remove all races. */
|
||||
|
||||
void __iomem *__ioremap(unsigned long physaddr, unsigned long size, int cacheflag)
|
||||
{
|
||||
struct vm_struct *area;
|
||||
unsigned long virtaddr, retaddr;
|
||||
long offset;
|
||||
pgd_t *pgd_dir;
|
||||
pmd_t *pmd_dir;
|
||||
pte_t *pte_dir;
|
||||
|
||||
/*
|
||||
* Don't allow mappings that wrap..
|
||||
*/
|
||||
if (!size || physaddr > (unsigned long)(-size))
|
||||
return NULL;
|
||||
|
||||
#ifdef CONFIG_AMIGA
|
||||
if (MACH_IS_AMIGA) {
|
||||
if ((physaddr >= 0x40000000) && (physaddr + size < 0x60000000)
|
||||
&& (cacheflag == IOMAP_NOCACHE_SER))
|
||||
return (void __iomem *)physaddr;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG
|
||||
printk("ioremap: 0x%lx,0x%lx(%d) - ", physaddr, size, cacheflag);
|
||||
#endif
|
||||
/*
|
||||
* Mappings have to be aligned
|
||||
*/
|
||||
offset = physaddr & (IO_SIZE - 1);
|
||||
physaddr &= -IO_SIZE;
|
||||
size = (size + offset + IO_SIZE - 1) & -IO_SIZE;
|
||||
|
||||
/*
|
||||
* Ok, go for it..
|
||||
*/
|
||||
area = get_io_area(size);
|
||||
if (!area)
|
||||
return NULL;
|
||||
|
||||
virtaddr = (unsigned long)area->addr;
|
||||
retaddr = virtaddr + offset;
|
||||
#ifdef DEBUG
|
||||
printk("0x%lx,0x%lx,0x%lx", physaddr, virtaddr, retaddr);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* add cache and table flags to physical address
|
||||
*/
|
||||
if (CPU_IS_040_OR_060) {
|
||||
physaddr |= (_PAGE_PRESENT | _PAGE_GLOBAL040 |
|
||||
_PAGE_ACCESSED | _PAGE_DIRTY);
|
||||
switch (cacheflag) {
|
||||
case IOMAP_FULL_CACHING:
|
||||
physaddr |= _PAGE_CACHE040;
|
||||
break;
|
||||
case IOMAP_NOCACHE_SER:
|
||||
default:
|
||||
physaddr |= _PAGE_NOCACHE_S;
|
||||
break;
|
||||
case IOMAP_NOCACHE_NONSER:
|
||||
physaddr |= _PAGE_NOCACHE;
|
||||
break;
|
||||
case IOMAP_WRITETHROUGH:
|
||||
physaddr |= _PAGE_CACHE040W;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
physaddr |= (_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_DIRTY);
|
||||
switch (cacheflag) {
|
||||
case IOMAP_NOCACHE_SER:
|
||||
case IOMAP_NOCACHE_NONSER:
|
||||
default:
|
||||
physaddr |= _PAGE_NOCACHE030;
|
||||
break;
|
||||
case IOMAP_FULL_CACHING:
|
||||
case IOMAP_WRITETHROUGH:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
while ((long)size > 0) {
|
||||
#ifdef DEBUG
|
||||
if (!(virtaddr & (PTRTREESIZE-1)))
|
||||
printk ("\npa=%#lx va=%#lx ", physaddr, virtaddr);
|
||||
#endif
|
||||
pgd_dir = pgd_offset_k(virtaddr);
|
||||
pmd_dir = pmd_alloc(&init_mm, pgd_dir, virtaddr);
|
||||
if (!pmd_dir) {
|
||||
printk("ioremap: no mem for pmd_dir\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (CPU_IS_020_OR_030) {
|
||||
pmd_dir->pmd[(virtaddr/PTRTREESIZE) & 15] = physaddr;
|
||||
physaddr += PTRTREESIZE;
|
||||
virtaddr += PTRTREESIZE;
|
||||
size -= PTRTREESIZE;
|
||||
} else {
|
||||
pte_dir = pte_alloc_kernel(pmd_dir, virtaddr);
|
||||
if (!pte_dir) {
|
||||
printk("ioremap: no mem for pte_dir\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pte_val(*pte_dir) = physaddr;
|
||||
virtaddr += PAGE_SIZE;
|
||||
physaddr += PAGE_SIZE;
|
||||
size -= PAGE_SIZE;
|
||||
}
|
||||
}
|
||||
#ifdef DEBUG
|
||||
printk("\n");
|
||||
#endif
|
||||
flush_tlb_all();
|
||||
|
||||
return (void __iomem *)retaddr;
|
||||
}
|
||||
EXPORT_SYMBOL(__ioremap);
|
||||
|
||||
/*
|
||||
* Unmap a ioremap()ed region again
|
||||
*/
|
||||
void iounmap(void __iomem *addr)
|
||||
{
|
||||
#ifdef CONFIG_AMIGA
|
||||
if ((!MACH_IS_AMIGA) ||
|
||||
(((unsigned long)addr < 0x40000000) ||
|
||||
((unsigned long)addr > 0x60000000)))
|
||||
free_io_area((__force void *)addr);
|
||||
#else
|
||||
free_io_area((__force void *)addr);
|
||||
#endif
|
||||
}
|
||||
EXPORT_SYMBOL(iounmap);
|
||||
|
||||
/*
|
||||
* __iounmap unmaps nearly everything, so be careful
|
||||
* it doesn't free currently pointer/page tables anymore but it
|
||||
* wans't used anyway and might be added later.
|
||||
*/
|
||||
void __iounmap(void *addr, unsigned long size)
|
||||
{
|
||||
unsigned long virtaddr = (unsigned long)addr;
|
||||
pgd_t *pgd_dir;
|
||||
pmd_t *pmd_dir;
|
||||
pte_t *pte_dir;
|
||||
|
||||
while ((long)size > 0) {
|
||||
pgd_dir = pgd_offset_k(virtaddr);
|
||||
if (pgd_bad(*pgd_dir)) {
|
||||
printk("iounmap: bad pgd(%08lx)\n", pgd_val(*pgd_dir));
|
||||
pgd_clear(pgd_dir);
|
||||
return;
|
||||
}
|
||||
pmd_dir = pmd_offset(pgd_dir, virtaddr);
|
||||
|
||||
if (CPU_IS_020_OR_030) {
|
||||
int pmd_off = (virtaddr/PTRTREESIZE) & 15;
|
||||
int pmd_type = pmd_dir->pmd[pmd_off] & _DESCTYPE_MASK;
|
||||
|
||||
if (pmd_type == _PAGE_PRESENT) {
|
||||
pmd_dir->pmd[pmd_off] = 0;
|
||||
virtaddr += PTRTREESIZE;
|
||||
size -= PTRTREESIZE;
|
||||
continue;
|
||||
} else if (pmd_type == 0)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (pmd_bad(*pmd_dir)) {
|
||||
printk("iounmap: bad pmd (%08lx)\n", pmd_val(*pmd_dir));
|
||||
pmd_clear(pmd_dir);
|
||||
return;
|
||||
}
|
||||
pte_dir = pte_offset_kernel(pmd_dir, virtaddr);
|
||||
|
||||
pte_val(*pte_dir) = 0;
|
||||
virtaddr += PAGE_SIZE;
|
||||
size -= PAGE_SIZE;
|
||||
}
|
||||
|
||||
flush_tlb_all();
|
||||
}
|
||||
|
||||
/*
|
||||
* Set new cache mode for some kernel address space.
|
||||
* The caller must push data for that range itself, if such data may already
|
||||
* be in the cache.
|
||||
*/
|
||||
void kernel_set_cachemode(void *addr, unsigned long size, int cmode)
|
||||
{
|
||||
unsigned long virtaddr = (unsigned long)addr;
|
||||
pgd_t *pgd_dir;
|
||||
pmd_t *pmd_dir;
|
||||
pte_t *pte_dir;
|
||||
|
||||
if (CPU_IS_040_OR_060) {
|
||||
switch (cmode) {
|
||||
case IOMAP_FULL_CACHING:
|
||||
cmode = _PAGE_CACHE040;
|
||||
break;
|
||||
case IOMAP_NOCACHE_SER:
|
||||
default:
|
||||
cmode = _PAGE_NOCACHE_S;
|
||||
break;
|
||||
case IOMAP_NOCACHE_NONSER:
|
||||
cmode = _PAGE_NOCACHE;
|
||||
break;
|
||||
case IOMAP_WRITETHROUGH:
|
||||
cmode = _PAGE_CACHE040W;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
switch (cmode) {
|
||||
case IOMAP_NOCACHE_SER:
|
||||
case IOMAP_NOCACHE_NONSER:
|
||||
default:
|
||||
cmode = _PAGE_NOCACHE030;
|
||||
break;
|
||||
case IOMAP_FULL_CACHING:
|
||||
case IOMAP_WRITETHROUGH:
|
||||
cmode = 0;
|
||||
}
|
||||
}
|
||||
|
||||
while ((long)size > 0) {
|
||||
pgd_dir = pgd_offset_k(virtaddr);
|
||||
if (pgd_bad(*pgd_dir)) {
|
||||
printk("iocachemode: bad pgd(%08lx)\n", pgd_val(*pgd_dir));
|
||||
pgd_clear(pgd_dir);
|
||||
return;
|
||||
}
|
||||
pmd_dir = pmd_offset(pgd_dir, virtaddr);
|
||||
|
||||
if (CPU_IS_020_OR_030) {
|
||||
int pmd_off = (virtaddr/PTRTREESIZE) & 15;
|
||||
|
||||
if ((pmd_dir->pmd[pmd_off] & _DESCTYPE_MASK) == _PAGE_PRESENT) {
|
||||
pmd_dir->pmd[pmd_off] = (pmd_dir->pmd[pmd_off] &
|
||||
_CACHEMASK040) | cmode;
|
||||
virtaddr += PTRTREESIZE;
|
||||
size -= PTRTREESIZE;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (pmd_bad(*pmd_dir)) {
|
||||
printk("iocachemode: bad pmd (%08lx)\n", pmd_val(*pmd_dir));
|
||||
pmd_clear(pmd_dir);
|
||||
return;
|
||||
}
|
||||
pte_dir = pte_offset_kernel(pmd_dir, virtaddr);
|
||||
|
||||
pte_val(*pte_dir) = (pte_val(*pte_dir) & _CACHEMASK040) | cmode;
|
||||
virtaddr += PAGE_SIZE;
|
||||
size -= PAGE_SIZE;
|
||||
}
|
||||
|
||||
flush_tlb_all();
|
||||
}
|
||||
EXPORT_SYMBOL(kernel_set_cachemode);
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user