linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 3/14] FRV: Fujitsu FR-V arch documentation
       [not found] <76b4a884-2c3c-11d9-91a1-0002b3163499@redhat.com>
  2004-11-01 19:30 ` [PATCH 4/14] FRV: Bitops fixes dhowells
@ 2004-11-01 19:30 ` dhowells
  2004-11-01 19:30 ` [PATCH 5/14] FRV: Fork fixes dhowells
                   ` (14 subsequent siblings)
  16 siblings, 0 replies; 87+ messages in thread
From: dhowells @ 2004-11-01 19:30 UTC (permalink / raw)
  To: torvalds, akpm, davidm; +Cc: linux-kernel, uclinux-dev

The attached patch provides the arch-specific documentation for the Fujitsu
FR-V CPU arch.

Signed-Off-By: dhowells@redhat.com
---
diffstat frv-doc-2610rc1bk10.diff
 README.txt      |   51 +++++++++
 atomic-ops.txt  |  134 ++++++++++++++++++++++++
 booting.txt     |  181 ++++++++++++++++++++++++++++++++
 clock.txt       |   65 +++++++++++
 configuring.txt |  125 ++++++++++++++++++++++
 features.txt    |  310 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 gdbinit         |  102 ++++++++++++++++++
 gdbstub.txt     |  130 +++++++++++++++++++++++
 mmu-layout.txt  |  306 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 9 files changed, 1404 insertions(+)

diff -uNr /warthog/kernels/linux-2.6.10-rc1-bk10/Documentation/fujitsu/frv/atomic-ops.txt linux-2.6.10-rc1-bk10-frv/Documentation/fujitsu/frv/atomic-ops.txt
--- /warthog/kernels/linux-2.6.10-rc1-bk10/Documentation/fujitsu/frv/atomic-ops.txt	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-bk10-frv/Documentation/fujitsu/frv/atomic-ops.txt	2004-11-01 11:47:04.000000000 +0000
@@ -0,0 +1,134 @@
+			       =====================================
+			       FUJITSU FR-V KERNEL ATOMIC OPERATIONS
+			       =====================================
+
+On the FR-V CPUs, there is only one atomic Read-Modify-Write operation: the SWAP/SWAPI
+instruction. Unfortunately, this alone can't be used to implement the following operations:
+
+ (*) Atomic add to memory
+
+ (*) Atomic subtract from memory
+
+ (*) Atomic bit modification (set, clear or invert)
+
+ (*) Atomic compare and exchange
+
+On such CPUs, the standard way of emulating such operations in uniprocessor mode is to disable
+interrupts, but on the FR-V CPUs, modifying the PSR takes a lot of clock cycles, and it has to be
+done twice. This means the CPU runs for a relatively long time with interrupts disabled,
+potentially having a great effect on interrupt latency.
+
+
+=============
+NEW ALGORITHM
+=============
+
+To get around this, the following algorithm has been implemented. It operates in a way similar to
+the LL/SC instruction pairs supported on a number of platforms.
+
+ (*) The CCCR.CC3 register is reserved within the kernel to act as an atomic modify abort flag.
+
+ (*) In the exception prologues run on kernel->kernel entry, CCCR.CC3 is set to 0 (Undefined
+     state).
+
+ (*) All atomic operations can then be broken down into the following algorithm:
+
+     (1) Set ICC3.Z to true and set CC3 to True (ORCC/CKEQ/ORCR).
+
+     (2) Load the value currently in the memory to be modified into a register.
+
+     (3) Make changes to the value.
+
+     (4) If CC3 is still True, simultaneously and atomically (by VLIW packing):
+
+	 (a) Store the modified value back to memory.
+
+	 (b) Set ICC3.Z to false (CORCC on GR29 is sufficient for this - GR29 holds the current
+	     task pointer in the kernel, and so is guaranteed to be non-zero).
+
+     (5) If ICC3.Z is still true, go back to step (1).
+
+This works in a non-SMP environment because any interrupt or other exception that happens between
+steps (1) and (4) will set CC3 to the Undefined, thus aborting the store in (4a), and causing the
+condition in ICC3 to remain with the Z flag set, thus causing step (5) to loop back to step (1).
+
+
+This algorithm suffers from two problems:
+
+ (1) The condition CCCR.CC3 is cleared unconditionally by an exception, irrespective of whether or
+     not any changes were made to the target memory location during that exception.
+
+ (2) The branch from step (5) back to step (1) may have to happen more than once until the store
+     manages to take place. In theory, this loop could cycle forever because there are too many
+     interrupts coming in, but it's unlikely.
+
+
+=======
+EXAMPLE
+=======
+
+Taking an example from include/asm-frv/atomic.h:
+
+	static inline int atomic_add_return(int i, atomic_t *v)
+	{
+		unsigned long val;
+
+		asm("0:						\n"
+
+It starts by setting ICC3.Z to true for later use, and also transforming that into CC3 being in the
+True state.
+
+		    "	orcc		gr0,gr0,gr0,icc3	\n"	<-- (1)
+		    "	ckeq		icc3,cc7		\n"	<-- (1)
+
+Then it does the load. Note that the final phase of step (1) is done at the same time as the
+load. The VLIW packing ensures they are done simultaneously. The ".p" on the load must not be
+removed without swapping the order of these two instructions.
+
+		    "	ld.p		%M0,%1			\n"	<-- (2)
+		    "	orcr		cc7,cc7,cc3		\n"	<-- (1)
+
+Then the proposed modification is generated. Note that the old value can be retained if required
+(such as in test_and_set_bit()).
+
+		    "	add%I2		%1,%2,%1		\n"	<-- (3)
+
+Then it attempts to store the value back, contingent on no exception having cleared CC3 since it
+was set to True.
+
+		    "	cst.p		%1,%M0		,cc3,#1	\n"	<-- (4a)
+
+It simultaneously records the success or failure of the store in ICC3.Z.
+
+		    "	corcc		gr29,gr29,gr0	,cc3,#1	\n"	<-- (4b)
+
+Such that the branch can then be taken if the operation was aborted.
+
+		    "	beq		icc3,#0,0b		\n"	<-- (5)
+		    : "+U"(v->counter), "=&r"(val)
+		    : "NPr"(i)
+		    : "memory", "cc7", "cc3", "icc3"
+		    );
+
+		return val;
+	}
+
+
+=============
+CONFIGURATION
+=============
+
+The atomic ops implementation can be made inline or out-of-line by changing the
+CONFIG_FRV_OUTOFLINE_ATOMIC_OPS configuration variable. Making it out-of-line has a number of
+advantages:
+
+ - The resulting kernel image may be smaller
+ - Debugging is easier as atomic ops can just be stepped over and they can be breakpointed
+
+Keeping it inline also has a number of advantages:
+
+ - The resulting kernel may be Faster
+   - no out-of-line function calls need to be made
+   - the compiler doesn't have half its registers clobbered by making a call
+
+The out-of-line implementations live in arch/frv/lib/atomic-ops.S.
diff -uNr /warthog/kernels/linux-2.6.10-rc1-bk10/Documentation/fujitsu/frv/booting.txt linux-2.6.10-rc1-bk10-frv/Documentation/fujitsu/frv/booting.txt
--- /warthog/kernels/linux-2.6.10-rc1-bk10/Documentation/fujitsu/frv/booting.txt	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-bk10-frv/Documentation/fujitsu/frv/booting.txt	2004-11-01 11:47:04.000000000 +0000
@@ -0,0 +1,181 @@
+			  =========================
+			  BOOTING FR-V LINUX KERNEL
+			  =========================
+
+======================
+PROVIDING A FILESYSTEM
+======================
+
+First of all, a root filesystem must be made available. This can be done in
+one of two ways:
+
+  (1) NFS Export
+
+      A filesystem should be constructed in a directory on an NFS server that
+      the target board can reach. This directory should then be NFS exported
+      such that the target board can read and write into it as root.
+
+  (2) Flash Filesystem (JFFS2 Recommended)
+
+      In this case, the image must be stored or built up on flash before it
+      can be used. A complete image can be built using the mkfs.jffs2 or
+      similar program and then downloaded and stored into flash by RedBoot.
+
+
+========================
+LOADING THE KERNEL IMAGE
+========================
+
+The kernel will need to be loaded into RAM by RedBoot (or by some alternative
+boot loader) before it can be run. The kernel image (arch/frv/boot/Image) may
+be loaded in one of three ways:
+
+  (1) Load from Flash
+
+      This is the simplest. RedBoot can store an image in the flash (see the
+      RedBoot documentation) and then load it back into RAM. RedBoot keeps
+      track of the load address, entry point and size, so the command to do
+      this is simply:
+
+	fis load linux
+
+      The image is then ready to be executed.
+
+  (2) Load by TFTP
+
+      The following command will download a raw binary kernel image from the
+      default server (as negotiated by BOOTP) and store it into RAM:
+      
+	load -b 0x00100000 -r /tftpboot/image.bin
+
+      The image is then ready to be executed.
+
+  (3) Load by Y-Modem
+
+      The following command will download a raw binary kernel image across the
+      serial port that RedBoot is currently using:
+      
+	load -m ymodem -b 0x00100000 -r zImage
+
+      The serial client (such as minicom) must then be told to transmit the
+      program by Y-Modem.
+
+      When finished, the image will then be ready to be executed.
+
+
+==================
+BOOTING THE KERNEL
+==================
+
+Boot the image with the following RedBoot command:
+
+	exec -c "<CMDLINE>" 0x00100000
+
+For example:
+
+	exec -c "console=ttySM0,115200 ip=:::::dhcp root=/dev/mtdblock2 rw"
+
+This will start the kernel running. Note that if the GDB-stub is compiled in,
+then the kernel will immediately wait for GDB to connect over serial before
+doing anything else. See the section on kernel debugging with GDB.
+
+The kernel command line <CMDLINE> tells the kernel where its console is and
+how to find its root filesystem. This is made up of the following components,
+separated by spaces:
+
+  (*) console=ttyS<x>[,<baud>[<parity>[<bits>[<flow>]]]]
+
+      This specifies that the system console should output through on-chip
+      serial port <x> (which can be "0" or "1").
+
+      <baud> is a standard baud rate between 1200 and 115200 (default 9600).
+
+      <parity> is a parity setting of "N", "O", "E", "M" or "S" for None, Odd,
+      Even, Mark or Space. "None" is the default.
+
+      <stop> is "7" or "8" for the number of bits per character. "8" is the
+      default.
+
+      <flow> is "r" to use flow control (XCTS on serial port 2 only). The
+      default is to not use flow control.
+
+      For example:
+
+	console=ttyS0,115200
+
+      To use the first on-chip serial port at baud rate 115200, no parity, 8
+      bits, and no flow control.
+
+  (*) root=/dev/<xxxx>
+
+      This specifies the device upon which the root filesystem resides. For
+      example:
+
+	/dev/nfs	NFS root filesystem
+	/dev/mtdblock3	Fourth RedBoot partition on the System Flash
+
+  (*) rw
+
+      Start with the root filesystem mounted Read/Write.
+
+  The remaining components are all optional:
+
+  (*) ip=<ip>::::<host>:<iface>:<cfg>
+
+      Configure the network interface. If <cfg> is "off" then <ip> should
+      specify the IP address for the network device <iface>. <host> provide
+      the hostname for the device.
+
+      If <cfg> is "bootp" or "dhcp", then all of these parameters will be
+      discovered by consulting a BOOTP or DHCP server.
+
+      For example, the following might be used:
+
+	ip=192.168.73.12::::frv:eth0:off
+
+      This sets the IP address on the VDK motherboard RTL8029 ethernet chipset
+      (eth0) to be 192.168.73.12, and sets the board's hostname to be "frv".
+
+  (*) nfsroot=<server>:<dir>[,v<vers>]
+
+      This is mandatory if "root=/dev/nfs" is given as an option. It tells the
+      kernel the IP address of the NFS server providing its root filesystem,
+      and the pathname on that server of the filesystem.
+
+      The NFS version to use can also be specified. v2 and v3 are supported by
+      Linux.
+
+      For example:
+
+	nfsroot=192.168.73.1:/nfsroot-frv
+
+  (*) profile=1
+
+      Turns on the kernel profiler (accessible through /proc/profile).
+
+  (*) console=gdb0
+
+      This can be used as an alternative to the "console=ttyS..." listed
+      above. I tells the kernel to pass the console output to GDB if the
+      gdbstub is compiled in to the kernel.
+
+      If this is used, then the gdbstub passes the text to GDB, which then
+      simply dumps it to its standard output.
+
+  (*) mem=<xxx>M
+
+      Normally the kernel will work out how much SDRAM it has by reading the
+      SDRAM controller registers. That can be overridden with this
+      option. This allows the kernel to be told that it has <xxx> megabytes of
+      memory available.
+
+  (*) init=<prog> [<arg> [<arg> [<arg> ...]]]
+
+      This tells the kernel what program to run initially. By default this is
+      /sbin/init, but /sbin/sash or /bin/sh are common alternatives.
+
+  (*) vdc=...
+
+      This option configures the MB93493 companion chip visual display
+      driver. Please see Documentation/fujitsu/mb93493/vdc.txt for more
+      information.
diff -uNr /warthog/kernels/linux-2.6.10-rc1-bk10/Documentation/fujitsu/frv/clock.txt linux-2.6.10-rc1-bk10-frv/Documentation/fujitsu/frv/clock.txt
--- /warthog/kernels/linux-2.6.10-rc1-bk10/Documentation/fujitsu/frv/clock.txt	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-bk10-frv/Documentation/fujitsu/frv/clock.txt	2004-11-01 11:47:04.000000000 +0000
@@ -0,0 +1,65 @@
+Clock scaling
+-------------
+
+The kernel supports scaling of CLCK.CMODE, CLCK.CM and CLKC.P0 clock
+registers. If built with CONFIG_PM and CONFIG_SYSCTL options enabled, four
+extra files will appear in the directory /proc/sys/pm/. Reading these files
+will show:
+
+      p0		-- current value of the P0 bit in CLKC register.
+      cm		-- current value of the CM bits in CLKC register.
+      cmode		-- current value of the CMODE bits in CLKC register.
+
+On all boards, the 'p0' file should also be writable, and either '1' or '0'
+can be rewritten, to set or clear the CLKC_P0 bit respectively, hence
+controlling whether the resource bus rate clock is halved.
+
+The 'cm' file should also be available on all boards. '0' can be written to it
+to shift the board into High-Speed mode (normal), and '1' can be written to
+shift the board into Medium-Speed mode. Selecting Low-Speed mode is not
+supported by this interface, even though some CPUs do support it.
+
+On the boards with FR405 CPU (i.e. CB60 and CB70), the 'cmode' file is also
+writable, allowing the CPU core speed (and other clock speeds) to be
+controlled from userspace.
+
+
+Determining current and possible settings
+-----------------------------------------
+
+The current state and the available masks can be found in /proc/cpuinfo. For
+example, on the CB70:
+
+	# cat /proc/cpuinfo
+	CPU-Series:     fr400
+	CPU-Core:       fr405, gr0-31, BE, CCCR
+	CPU:            mb93405
+	MMU:            Prot
+	FP-Media:       fr0-31, Media
+	System:         mb93091-cb70, mb93090-mb00
+	PM-Controls:    cmode=0xd31f, cm=0x3, p0=0x3, suspend=0x9
+	PM-Status:      cmode=3, cm=0, p0=0
+	Clock-In:       50.00 MHz
+	Clock-Core:     300.00 MHz
+	Clock-SDRAM:    100.00 MHz
+	Clock-CBus:     100.00 MHz
+	Clock-Res:      50.00 MHz
+	Clock-Ext:      50.00 MHz
+	Clock-DSU:      25.00 MHz
+	BogoMips:       300.00
+
+And on the PDK, the PM lines look like the following:
+
+	PM-Controls:    cm=0x3, p0=0x3, suspend=0x9
+	PM-Status:      cmode=9, cm=0, p0=0
+
+The PM-Controls line, if present, will indicate which /proc/sys/pm files can
+be set to what values. The specification values are bitmasks; so, for example,
+"suspend=0x9" indicates that 0 and 3 can be written validly to
+/proc/sys/pm/suspend.
+
+The PM-Controls line will only be present if CONFIG_PM is configured to Y.
+
+The PM-Status line indicates which clock controls are set to which value. If
+the file can be read, then the suspend value must be 0, and so that's not
+included.
diff -uNr /warthog/kernels/linux-2.6.10-rc1-bk10/Documentation/fujitsu/frv/configuring.txt linux-2.6.10-rc1-bk10-frv/Documentation/fujitsu/frv/configuring.txt
--- /warthog/kernels/linux-2.6.10-rc1-bk10/Documentation/fujitsu/frv/configuring.txt	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-bk10-frv/Documentation/fujitsu/frv/configuring.txt	2004-11-01 11:47:04.000000000 +0000
@@ -0,0 +1,125 @@
+		   =======================================
+		   FUJITSU FR-V LINUX KERNEL CONFIGURATION
+		   =======================================
+
+=====================
+CONFIGURATION OPTIONS
+=====================
+
+The most important setting is in the "MMU support options" tab (the first
+presented in the configuration tools available):
+
+ (*) "Kernel Type"
+
+     This options allows selection of normal, MMU-requiring linux, and uClinux
+     (which doesn't require an MMU and doesn't have inter-process protection).
+
+There are a number of settings in the "Processor type and features" section of
+the kernel configuration that need to be considered.
+
+ (*) "CPU"
+
+     The register and instruction sets at the core of the processor. This can
+     only be set to "FR40x/45x/55x" at the moment - but this permits usage of
+     the kernel with MB93091 CB10, CB11, CB30, CB41, CB60, CB70 and CB451
+     CPU boards, and with the MB93093 PDK board.
+
+ (*) "System"
+
+     This option allows a choice of basic system. This governs the peripherals
+     that are expected to be available.
+
+ (*) "Motherboard"
+
+     This specifies the type of motherboard being used, and the peripherals
+     upon it. Currently only "MB93090-MB00" can be set here.
+
+ (*) "Default cache-write mode"
+
+     This controls the initial data cache write management mode. By default
+     Write-Through is selected, but Write-Back (Copy-Back) can also be
+     selected. This can be changed dynamically once the kernel is running (see
+     features.txt).
+
+There are some architecture specific configuration options in the "General
+Setup" section of the kernel configuration too:
+
+ (*) "Reserve memory uncached for (PCI) DMA"
+
+     This requests that a uClinux kernel set aside some memory in an uncached
+     window for the use as consistent DMA memory (mainly for PCI). At least a
+     megabyte will be allocated in this way, possibly more. Any memory so
+     reserved will not be available for normal allocations.
+
+ (*) "Kernel support for ELF-FDPIC binaries"
+
+     This enables the binary-format driver for the new FDPIC ELF binaries that
+     this platform normally uses. These binaries are totally relocatable -
+     their separate sections can relocated independently, allowing them to be
+     shared on uClinux where possible. This should normally be enabled.
+
+ (*) "Kernel image protection"
+
+     This makes the protection register governing access to the core kernel
+     image prohibit access by userspace programs. This option is available on
+     uClinux only.
+
+There are also a number of settings in the "Kernel Hacking" section of the
+kernel configuration especially for debugging a kernel on this
+architecture. See the "gdbstub.txt" file for information about those.
+
+
+======================
+DEFAULT CONFIGURATIONS
+======================
+
+The kernel sources include a number of example default configurations:
+
+ (*) defconfig-mb93091
+
+     Default configuration for the MB93091-VDK with both CPU board and
+     MB93090-MB00 motherboard running uClinux.
+
+
+ (*) defconfig-mb93091-fb
+
+     Default configuration for the MB93091-VDK with CPU board,
+     MB93090-MB00 motherboard, and DAV board running uClinux.
+     Includes framebuffer driver.
+
+
+ (*) defconfig-mb93093
+
+     Default configuration for the MB93093-PDK board running uClinux.
+
+
+ (*) defconfig-cb70-standalone
+
+     Default configuration for the MB93091-VDK with only CB70 CPU board
+     running uClinux. This will use the CB70's DM9000 for network access.
+
+
+ (*) defconfig-mmu
+
+     Default configuration for the MB93091-VDK with both CB451 CPU board and
+     MB93090-MB00 motherboard running MMU linux.
+
+ (*) defconfig-mmu-audio
+
+     Default configuration for the MB93091-VDK with CB451 CPU board, DAV
+     board, and MB93090-MB00 motherboard running MMU linux. Includes
+     audio driver.
+
+ (*) defconfig-mmu-fb
+
+     Default configuration for the MB93091-VDK with CB451 CPU board, DAV
+     board, and MB93090-MB00 motherboard running MMU linux. Includes
+     framebuffer driver.
+
+ (*) defconfig-mmu-standalone
+
+     Default configuration for the MB93091-VDK with only CB451 CPU board
+     running MMU linux.
+
+
+
diff -uNr /warthog/kernels/linux-2.6.10-rc1-bk10/Documentation/fujitsu/frv/features.txt linux-2.6.10-rc1-bk10-frv/Documentation/fujitsu/frv/features.txt
--- /warthog/kernels/linux-2.6.10-rc1-bk10/Documentation/fujitsu/frv/features.txt	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-bk10-frv/Documentation/fujitsu/frv/features.txt	2004-11-01 11:47:04.000000000 +0000
@@ -0,0 +1,310 @@
+			 ===========================
+			 FUJITSU FR-V LINUX FEATURES
+			 ===========================
+
+This kernel port has a number of features of which the user should be aware:
+
+ (*) Linux and uClinux
+
+     The FR-V architecture port supports both normal MMU linux and uClinux out
+     of the same sources.
+
+
+ (*) CPU support
+
+     Support for the FR401, FR403, FR405, FR451 and FR555 CPUs should work with
+     the same uClinux kernel configuration.
+
+     In normal (MMU) Linux mode, only the FR451 CPU will work as that is the
+     only one with a suitably featured CPU.
+
+     The kernel is written and compiled with the assumption that only the
+     bottom 32 GR registers and no FR registers will be used by the kernel
+     itself, however all extra userspace registers will be saved on context
+     switch. Note that since most CPUs can't support lazy switching, no attempt
+     is made to do lazy register saving where that would be possible (FR555
+     only currently).
+
+
+ (*) Board support
+
+     The board on which the kernel will run can be configured on the "Processor
+     type and features" configuration tab.
+
+     Set the System to "MB93093-PDK" to boot from the MB93093 (FR403) PDK.
+
+     Set the System to "MB93091-VDK" to boot from the CB11, CB30, CB41, CB60,
+     CB70 or CB451 VDK boards. Set the Motherboard setting to "MB93090-MB00" to
+     boot with the standard ATA90590B VDK motherboard, and set it to "None" to
+     boot without any motherboard.
+
+
+ (*) Binary Formats
+
+     The only userspace binary format supported is FDPIC ELF. Normal ELF, FLAT
+     and AOUT binaries are not supported for this architecture.
+
+     FDPIC ELF supports shared library and program interpreter facilities.
+
+
+ (*) Scheduler Speed
+
+     The kernel scheduler runs at 100Hz irrespective of the clock speed on this
+     architecture. This value is set in asm/param.h (see the HZ macro defined
+     there).
+
+
+ (*) Normal (MMU) Linux Memory Layout.
+
+     See mmu-layout.txt in this directory for a description of the normal linux
+     memory layout
+
+     See include/asm-frv/mem-layout.h for constants pertaining to the memory
+     layout.
+
+     See include/asm-frv/mb-regs.h for the constants pertaining to the I/O bus
+     controller configuration.
+
+
+ (*) uClinux Memory Layout
+
+     The memory layout used by the uClinux kernel is as follows:
+
+	0x00000000 - 0x00000FFF		Null pointer catch page
+	0x20000000 - 0x200FFFFF CS2#    [PDK] FPGA
+	0xC0000000 - 0xCFFFFFFF		SDRAM
+	0xC0000000			Base of Linux kernel image
+	0xE0000000 - 0xEFFFFFFF	CS2#	[VDK] SLBUS/PCI window
+	0xF0000000 - 0xF0FFFFFF	CS5#	MB93493 CSC area (DAV daughter board)
+	0xF1000000 - 0xF1FFFFFF	CS7#	[CB70/CB451] CPU-card PCMCIA port space
+	0xFC000000 - 0xFC0FFFFF	CS1#	[VDK] MB86943 config space
+	0xFC100000 - 0xFC1FFFFF	CS6#	[CB70/CB451] CPU-card DM9000 NIC space
+	0xFC100000 - 0xFC1FFFFF	CS6#	[PDK] AX88796 NIC space
+	0xFC200000 - 0xFC2FFFFF	CS3#	MB93493 CSR area (DAV daughter board)
+	0xFD000000 - 0xFDFFFFFF	CS4#	[CB70/CB451] CPU-card extra flash space
+	0xFE000000 - 0xFEFFFFFF		Internal CPU peripherals
+	0xFF000000 - 0xFF1FFFFF	CS0#	Flash 1
+	0xFF200000 - 0xFF3FFFFF	CS0#	Flash 2
+	0xFFC00000 - 0xFFC0001F	CS0#	[VDK] FPGA
+
+     The kernel reads the size of the SDRAM from the memory bus controller
+     registers by default.
+
+     The kernel initialisation code (1) adjusts the SDRAM base addresses to
+     move the SDRAM to desired address, (2) moves the kernel image down to the
+     bottom of SDRAM, (3) adjusts the bus controller registers to move I/O
+     windows, and (4) rearranges the protection registers to protect all of
+     this.
+
+     The reasons for doing this are: (1) the page at address 0 should be
+     inaccessible so that NULL pointer errors can be caught; and (2) the bottom
+     three quarters are left unoccupied so that an FR-V CPU with an MMU can use
+     it for virtual userspace mappings.
+
+     See include/asm-frv/mem-layout.h for constants pertaining to the memory
+     layout.
+
+     See include/asm-frv/mb-regs.h for the constants pertaining to the I/O bus
+     controller configuration.
+
+
+ (*) uClinux Memory Protection
+
+     A DAMPR register is used to cover the entire region used for I/O
+     (0xE0000000 - 0xFFFFFFFF). This permits the kernel to make uncached
+     accesses to this region. Userspace is not permitted to access it.
+
+     The DAMPR/IAMPR protection registers not in use for any other purpose are
+     tiled over the top of the SDRAM such that:
+
+	(1) The core kernel image is covered by as small a tile as possible
+            granting only the kernel access to the underlying data, whilst
+            making sure no SDRAM is actually made unavailable by this approach.
+
+	(2) All other tiles are arranged to permit userspace access to the rest
+            of the SDRAM.
+
+     Barring point (1), there is nothing to protect kernel data against
+     userspace damage - but this is uClinux.
+
+
+ (*) Exceptions and Fixups
+
+     Since the FR40x and FR55x CPUs that do not have full MMUs generate
+     imprecise data error exceptions, there are currently no automatic fixup
+     services available in uClinux. This includes misaligned memory access
+     fixups.
+
+     Userspace EFAULT errors can be trapped by issuing a MEMBAR instruction and
+     forcing the fault to happen there.
+
+     On the FR451, however, data exceptions are mostly precise, and so
+     exception fixup handling is implemented as normal.
+
+
+ (*) Userspace Breakpoints
+
+     The ptrace() system call supports the following userspace debugging
+     features:
+
+	(1) Hardware assisted single step.
+
+	(2) Breakpoint via the FR-V "BREAK" instruction.
+
+	(3) Breakpoint via the FR-V "TIRA GR0, #1" instruction.
+
+	(4) Syscall entry/exit trap.
+
+     Each of the above generates a SIGTRAP.
+
+
+ (*) On-Chip Serial Ports
+
+     The FR-V on-chip serial ports are made available as ttyS0 and ttyS1. Note
+     that if the GDB stub is compiled in, ttyS1 will not actually be available
+     as it will be being used for the GDB stub.
+
+     These ports can be made by:
+
+	mknod /dev/ttyS0 c 4 64
+	mknod /dev/ttyS1 c 4 65
+
+
+ (*) Maskable Interrupts
+
+     Level 15 (Non-maskable) interrupts are dealt with by the GDB stub if
+     present, and cause a panic if not. If the GDB stub is present, ttyS1's
+     interrupts are rated at level 15.
+
+     All other interrupts are distributed over the set of available priorities
+     so that no IRQs are shared where possible. The arch interrupt handling
+     routines attempt to disentangle the various sources available through the
+     CPU's own multiplexor, and those on off-CPU peripherals.
+
+
+ (*) Accessing PCI Devices
+
+     Where PCI is available, care must be taken when dealing with drivers that
+     access PCI devices. PCI devices present their data in little-endian form,
+     but the CPU sees it in big-endian form. The macros in asm/io.h try to get
+     this right, but may not under all circumstances...
+
+
+ (*) Ax88796 Ethernet Driver
+
+     The MB93093 PDK board has an Ax88796 ethernet chipset (an NE2000 clone). A
+     driver has been written to deal specifically with this. The driver
+     provides MII services for the card.
+
+     The driver can be configured by running make xconfig, and going to:
+
+	(*) Network device support
+	    - turn on "Network device support"
+	    (*) Ethernet (10 or 100Mbit)
+		- turn on "Ethernet (10 or 100Mbit)"
+		- turn on "AX88796 NE2000 compatible chipset"
+
+     The driver can be found in:
+
+	drivers/net/ax88796.c
+	include/asm/ax88796.h
+
+
+ (*) WorkRAM Driver
+
+     This driver provides a character device that permits access to the WorkRAM
+     that can be found on the FR451 CPU. Each page is accessible through a
+     separate minor number, thereby permitting each page to have its own
+     filesystem permissions set on the device file.
+
+     The device files should be:
+
+	mknod /dev/frv/workram0 c 240 0
+	mknod /dev/frv/workram1 c 240 1
+	mknod /dev/frv/workram2 c 240 2
+	...
+
+     The driver will not permit the opening of any device file that does not
+     correspond to at least a partial page of WorkRAM. So the first device file
+     is the only one available on the FR451. If any other CPU is detected, none
+     of the devices will be openable.
+
+     The devices can be accessed with read, write and llseek, and can also be
+     mmapped. If they're mmapped, they will only map at the appropriate
+     0x7e8nnnnn address on linux and at the 0xfe8nnnnn address on uClinux. If
+     MAP_FIXED is not specified, the appropriate address will be chosen anyway.
+
+     The mappings must be MAP_SHARED not MAP_PRIVATE, and must not be
+     PROT_EXEC. They must also start at file offset 0, and must not be longer
+     than one page in size.
+
+     This driver can be configured by running make xconfig, and going to:
+
+	(*) Character devices
+	    - turn on "Fujitsu FR-V CPU WorkRAM support"
+
+
+ (*) Dynamic data cache write mode changing
+
+     It is possible to view and to change the data cache's write mode through
+     the /proc/sys/frv/cache-mode file while the kernel is running. There are
+     two modes available:
+
+	NAME	MEANING
+	=====	==========================================
+	wthru	Data cache is in Write-Through mode
+	wback	Data cache is in Write-Back/Copy-Back mode
+
+     To read the cache mode:
+
+	# cat /proc/sys/frv/cache-mode
+	wthru
+
+     To change the cache mode:
+
+	# echo wback >/proc/sys/frv/cache-mode
+	# cat /proc/sys/frv/cache-mode
+	wback
+
+
+ (*) MMU Context IDs and Pinning
+
+     On MMU Linux the CPU supports the concept of a context ID in its MMU to
+     make it more efficient (TLB entries are labelled with a context ID to link
+     them to specific tasks).
+
+     Normally once a context ID is allocated, it will remain affixed to a task
+     or CLONE_VM'd group of tasks for as long as it exists. However, since the
+     kernel is capable of supporting more tasks than there are possible ID
+     numbers, the kernel will pass context IDs from one task to another if
+     there are insufficient available.
+
+     The context ID currently in use by a task can be viewed in /proc:
+
+	# grep CXNR /proc/1/status
+	CXNR: 1
+
+     Note that kernel threads do not have a userspace context, and so will not
+     show a CXNR entry in that file.
+
+     Under some circumstances, however, it is desirable to pin a context ID on
+     a process such that the kernel won't pass it on. This can be done by
+     writing the process ID of the target process to a special file:
+
+	# echo 17 >/proc/sys/frv/pin-cxnr
+
+     Reading from the file will then show the context ID pinned.
+
+	# cat /proc/sys/frv/pin-cxnr
+	4
+
+     The context ID will remain pinned as long as any process is using that
+     context, i.e.: when the all the subscribing processes have exited or
+     exec'd; or when an unpinning request happens:
+
+	# echo 0 >/proc/sys/frv/pin-cxnr
+
+     When there isn't a pinned context, the file shows -1:
+
+	# cat /proc/sys/frv/pin-cxnr
+	-1
diff -uNr /warthog/kernels/linux-2.6.10-rc1-bk10/Documentation/fujitsu/frv/gdbinit linux-2.6.10-rc1-bk10-frv/Documentation/fujitsu/frv/gdbinit
--- /warthog/kernels/linux-2.6.10-rc1-bk10/Documentation/fujitsu/frv/gdbinit	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-bk10-frv/Documentation/fujitsu/frv/gdbinit	2004-11-01 11:47:04.000000000 +0000
@@ -0,0 +1,102 @@
+set remotebreak 1
+
+define _amr
+
+printf "AMRx           DAMR                    IAMR         \n"
+printf "====   =====================   =====================\n"
+printf "amr0 : L:%08lx P:%08lx : L:%08lx P:%08lx\n",__debug_mmu.damr[0x0].L,__debug_mmu.damr[0x0].P,__debug_mmu.iamr[0x0].L,__debug_mmu.iamr[0x0].P
+printf "amr1 : L:%08lx P:%08lx : L:%08lx P:%08lx\n",__debug_mmu.damr[0x1].L,__debug_mmu.damr[0x1].P,__debug_mmu.iamr[0x1].L,__debug_mmu.iamr[0x1].P
+printf "amr2 : L:%08lx P:%08lx : L:%08lx P:%08lx\n",__debug_mmu.damr[0x2].L,__debug_mmu.damr[0x2].P,__debug_mmu.iamr[0x2].L,__debug_mmu.iamr[0x2].P
+printf "amr3 : L:%08lx P:%08lx : L:%08lx P:%08lx\n",__debug_mmu.damr[0x3].L,__debug_mmu.damr[0x3].P,__debug_mmu.iamr[0x3].L,__debug_mmu.iamr[0x3].P
+printf "amr4 : L:%08lx P:%08lx : L:%08lx P:%08lx\n",__debug_mmu.damr[0x4].L,__debug_mmu.damr[0x4].P,__debug_mmu.iamr[0x4].L,__debug_mmu.iamr[0x4].P
+printf "amr5 : L:%08lx P:%08lx : L:%08lx P:%08lx\n",__debug_mmu.damr[0x5].L,__debug_mmu.damr[0x5].P,__debug_mmu.iamr[0x5].L,__debug_mmu.iamr[0x5].P
+printf "amr6 : L:%08lx P:%08lx : L:%08lx P:%08lx\n",__debug_mmu.damr[0x6].L,__debug_mmu.damr[0x6].P,__debug_mmu.iamr[0x6].L,__debug_mmu.iamr[0x6].P
+printf "amr7 : L:%08lx P:%08lx : L:%08lx P:%08lx\n",__debug_mmu.damr[0x7].L,__debug_mmu.damr[0x7].P,__debug_mmu.iamr[0x7].L,__debug_mmu.iamr[0x7].P
+
+printf "amr8 : L:%08lx P:%08lx\n",__debug_mmu.damr[0x8].L,__debug_mmu.damr[0x8].P
+printf "amr9 : L:%08lx P:%08lx\n",__debug_mmu.damr[0x9].L,__debug_mmu.damr[0x9].P
+printf "amr10: L:%08lx P:%08lx\n",__debug_mmu.damr[0xa].L,__debug_mmu.damr[0xa].P
+printf "amr11: L:%08lx P:%08lx\n",__debug_mmu.damr[0xb].L,__debug_mmu.damr[0xb].P
+
+end
+
+
+define _tlb
+printf "tlb[0x00]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x0].L,__debug_mmu.tlb[0x0].P,__debug_mmu.tlb[0x40+0x0].L,__debug_mmu.tlb[0x40+0x0].P
+printf "tlb[0x01]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x1].L,__debug_mmu.tlb[0x1].P,__debug_mmu.tlb[0x40+0x1].L,__debug_mmu.tlb[0x40+0x1].P
+printf "tlb[0x02]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x2].L,__debug_mmu.tlb[0x2].P,__debug_mmu.tlb[0x40+0x2].L,__debug_mmu.tlb[0x40+0x2].P
+printf "tlb[0x03]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x3].L,__debug_mmu.tlb[0x3].P,__debug_mmu.tlb[0x40+0x3].L,__debug_mmu.tlb[0x40+0x3].P
+printf "tlb[0x04]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x4].L,__debug_mmu.tlb[0x4].P,__debug_mmu.tlb[0x40+0x4].L,__debug_mmu.tlb[0x40+0x4].P
+printf "tlb[0x05]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x5].L,__debug_mmu.tlb[0x5].P,__debug_mmu.tlb[0x40+0x5].L,__debug_mmu.tlb[0x40+0x5].P
+printf "tlb[0x06]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x6].L,__debug_mmu.tlb[0x6].P,__debug_mmu.tlb[0x40+0x6].L,__debug_mmu.tlb[0x40+0x6].P
+printf "tlb[0x07]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x7].L,__debug_mmu.tlb[0x7].P,__debug_mmu.tlb[0x40+0x7].L,__debug_mmu.tlb[0x40+0x7].P
+printf "tlb[0x08]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x8].L,__debug_mmu.tlb[0x8].P,__debug_mmu.tlb[0x40+0x8].L,__debug_mmu.tlb[0x40+0x8].P
+printf "tlb[0x09]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x9].L,__debug_mmu.tlb[0x9].P,__debug_mmu.tlb[0x40+0x9].L,__debug_mmu.tlb[0x40+0x9].P
+printf "tlb[0x0a]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0xa].L,__debug_mmu.tlb[0xa].P,__debug_mmu.tlb[0x40+0xa].L,__debug_mmu.tlb[0x40+0xa].P
+printf "tlb[0x0b]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0xb].L,__debug_mmu.tlb[0xb].P,__debug_mmu.tlb[0x40+0xb].L,__debug_mmu.tlb[0x40+0xb].P
+printf "tlb[0x0c]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0xc].L,__debug_mmu.tlb[0xc].P,__debug_mmu.tlb[0x40+0xc].L,__debug_mmu.tlb[0x40+0xc].P
+printf "tlb[0x0d]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0xd].L,__debug_mmu.tlb[0xd].P,__debug_mmu.tlb[0x40+0xd].L,__debug_mmu.tlb[0x40+0xd].P
+printf "tlb[0x0e]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0xe].L,__debug_mmu.tlb[0xe].P,__debug_mmu.tlb[0x40+0xe].L,__debug_mmu.tlb[0x40+0xe].P
+printf "tlb[0x0f]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0xf].L,__debug_mmu.tlb[0xf].P,__debug_mmu.tlb[0x40+0xf].L,__debug_mmu.tlb[0x40+0xf].P
+printf "tlb[0x10]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x10].L,__debug_mmu.tlb[0x10].P,__debug_mmu.tlb[0x40+0x10].L,__debug_mmu.tlb[0x40+0x10].P
+printf "tlb[0x11]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x11].L,__debug_mmu.tlb[0x11].P,__debug_mmu.tlb[0x40+0x11].L,__debug_mmu.tlb[0x40+0x11].P
+printf "tlb[0x12]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x12].L,__debug_mmu.tlb[0x12].P,__debug_mmu.tlb[0x40+0x12].L,__debug_mmu.tlb[0x40+0x12].P
+printf "tlb[0x13]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x13].L,__debug_mmu.tlb[0x13].P,__debug_mmu.tlb[0x40+0x13].L,__debug_mmu.tlb[0x40+0x13].P
+printf "tlb[0x14]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x14].L,__debug_mmu.tlb[0x14].P,__debug_mmu.tlb[0x40+0x14].L,__debug_mmu.tlb[0x40+0x14].P
+printf "tlb[0x15]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x15].L,__debug_mmu.tlb[0x15].P,__debug_mmu.tlb[0x40+0x15].L,__debug_mmu.tlb[0x40+0x15].P
+printf "tlb[0x16]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x16].L,__debug_mmu.tlb[0x16].P,__debug_mmu.tlb[0x40+0x16].L,__debug_mmu.tlb[0x40+0x16].P
+printf "tlb[0x17]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x17].L,__debug_mmu.tlb[0x17].P,__debug_mmu.tlb[0x40+0x17].L,__debug_mmu.tlb[0x40+0x17].P
+printf "tlb[0x18]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x18].L,__debug_mmu.tlb[0x18].P,__debug_mmu.tlb[0x40+0x18].L,__debug_mmu.tlb[0x40+0x18].P
+printf "tlb[0x19]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x19].L,__debug_mmu.tlb[0x19].P,__debug_mmu.tlb[0x40+0x19].L,__debug_mmu.tlb[0x40+0x19].P
+printf "tlb[0x1a]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x1a].L,__debug_mmu.tlb[0x1a].P,__debug_mmu.tlb[0x40+0x1a].L,__debug_mmu.tlb[0x40+0x1a].P
+printf "tlb[0x1b]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x1b].L,__debug_mmu.tlb[0x1b].P,__debug_mmu.tlb[0x40+0x1b].L,__debug_mmu.tlb[0x40+0x1b].P
+printf "tlb[0x1c]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x1c].L,__debug_mmu.tlb[0x1c].P,__debug_mmu.tlb[0x40+0x1c].L,__debug_mmu.tlb[0x40+0x1c].P
+printf "tlb[0x1d]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x1d].L,__debug_mmu.tlb[0x1d].P,__debug_mmu.tlb[0x40+0x1d].L,__debug_mmu.tlb[0x40+0x1d].P
+printf "tlb[0x1e]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x1e].L,__debug_mmu.tlb[0x1e].P,__debug_mmu.tlb[0x40+0x1e].L,__debug_mmu.tlb[0x40+0x1e].P
+printf "tlb[0x1f]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x1f].L,__debug_mmu.tlb[0x1f].P,__debug_mmu.tlb[0x40+0x1f].L,__debug_mmu.tlb[0x40+0x1f].P
+printf "tlb[0x20]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x20].L,__debug_mmu.tlb[0x20].P,__debug_mmu.tlb[0x40+0x20].L,__debug_mmu.tlb[0x40+0x20].P
+printf "tlb[0x21]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x21].L,__debug_mmu.tlb[0x21].P,__debug_mmu.tlb[0x40+0x21].L,__debug_mmu.tlb[0x40+0x21].P
+printf "tlb[0x22]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x22].L,__debug_mmu.tlb[0x22].P,__debug_mmu.tlb[0x40+0x22].L,__debug_mmu.tlb[0x40+0x22].P
+printf "tlb[0x23]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x23].L,__debug_mmu.tlb[0x23].P,__debug_mmu.tlb[0x40+0x23].L,__debug_mmu.tlb[0x40+0x23].P
+printf "tlb[0x24]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x24].L,__debug_mmu.tlb[0x24].P,__debug_mmu.tlb[0x40+0x24].L,__debug_mmu.tlb[0x40+0x24].P
+printf "tlb[0x25]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x25].L,__debug_mmu.tlb[0x25].P,__debug_mmu.tlb[0x40+0x25].L,__debug_mmu.tlb[0x40+0x25].P
+printf "tlb[0x26]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x26].L,__debug_mmu.tlb[0x26].P,__debug_mmu.tlb[0x40+0x26].L,__debug_mmu.tlb[0x40+0x26].P
+printf "tlb[0x27]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x27].L,__debug_mmu.tlb[0x27].P,__debug_mmu.tlb[0x40+0x27].L,__debug_mmu.tlb[0x40+0x27].P
+printf "tlb[0x28]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x28].L,__debug_mmu.tlb[0x28].P,__debug_mmu.tlb[0x40+0x28].L,__debug_mmu.tlb[0x40+0x28].P
+printf "tlb[0x29]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x29].L,__debug_mmu.tlb[0x29].P,__debug_mmu.tlb[0x40+0x29].L,__debug_mmu.tlb[0x40+0x29].P
+printf "tlb[0x2a]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x2a].L,__debug_mmu.tlb[0x2a].P,__debug_mmu.tlb[0x40+0x2a].L,__debug_mmu.tlb[0x40+0x2a].P
+printf "tlb[0x2b]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x2b].L,__debug_mmu.tlb[0x2b].P,__debug_mmu.tlb[0x40+0x2b].L,__debug_mmu.tlb[0x40+0x2b].P
+printf "tlb[0x2c]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x2c].L,__debug_mmu.tlb[0x2c].P,__debug_mmu.tlb[0x40+0x2c].L,__debug_mmu.tlb[0x40+0x2c].P
+printf "tlb[0x2d]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x2d].L,__debug_mmu.tlb[0x2d].P,__debug_mmu.tlb[0x40+0x2d].L,__debug_mmu.tlb[0x40+0x2d].P
+printf "tlb[0x2e]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x2e].L,__debug_mmu.tlb[0x2e].P,__debug_mmu.tlb[0x40+0x2e].L,__debug_mmu.tlb[0x40+0x2e].P
+printf "tlb[0x2f]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x2f].L,__debug_mmu.tlb[0x2f].P,__debug_mmu.tlb[0x40+0x2f].L,__debug_mmu.tlb[0x40+0x2f].P
+printf "tlb[0x30]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x30].L,__debug_mmu.tlb[0x30].P,__debug_mmu.tlb[0x40+0x30].L,__debug_mmu.tlb[0x40+0x30].P
+printf "tlb[0x31]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x31].L,__debug_mmu.tlb[0x31].P,__debug_mmu.tlb[0x40+0x31].L,__debug_mmu.tlb[0x40+0x31].P
+printf "tlb[0x32]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x32].L,__debug_mmu.tlb[0x32].P,__debug_mmu.tlb[0x40+0x32].L,__debug_mmu.tlb[0x40+0x32].P
+printf "tlb[0x33]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x33].L,__debug_mmu.tlb[0x33].P,__debug_mmu.tlb[0x40+0x33].L,__debug_mmu.tlb[0x40+0x33].P
+printf "tlb[0x34]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x34].L,__debug_mmu.tlb[0x34].P,__debug_mmu.tlb[0x40+0x34].L,__debug_mmu.tlb[0x40+0x34].P
+printf "tlb[0x35]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x35].L,__debug_mmu.tlb[0x35].P,__debug_mmu.tlb[0x40+0x35].L,__debug_mmu.tlb[0x40+0x35].P
+printf "tlb[0x36]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x36].L,__debug_mmu.tlb[0x36].P,__debug_mmu.tlb[0x40+0x36].L,__debug_mmu.tlb[0x40+0x36].P
+printf "tlb[0x37]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x37].L,__debug_mmu.tlb[0x37].P,__debug_mmu.tlb[0x40+0x37].L,__debug_mmu.tlb[0x40+0x37].P
+printf "tlb[0x38]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x38].L,__debug_mmu.tlb[0x38].P,__debug_mmu.tlb[0x40+0x38].L,__debug_mmu.tlb[0x40+0x38].P
+printf "tlb[0x39]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x39].L,__debug_mmu.tlb[0x39].P,__debug_mmu.tlb[0x40+0x39].L,__debug_mmu.tlb[0x40+0x39].P
+printf "tlb[0x3a]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x3a].L,__debug_mmu.tlb[0x3a].P,__debug_mmu.tlb[0x40+0x3a].L,__debug_mmu.tlb[0x40+0x3a].P
+printf "tlb[0x3b]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x3b].L,__debug_mmu.tlb[0x3b].P,__debug_mmu.tlb[0x40+0x3b].L,__debug_mmu.tlb[0x40+0x3b].P
+printf "tlb[0x3c]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x3c].L,__debug_mmu.tlb[0x3c].P,__debug_mmu.tlb[0x40+0x3c].L,__debug_mmu.tlb[0x40+0x3c].P
+printf "tlb[0x3d]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x3d].L,__debug_mmu.tlb[0x3d].P,__debug_mmu.tlb[0x40+0x3d].L,__debug_mmu.tlb[0x40+0x3d].P
+printf "tlb[0x3e]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x3e].L,__debug_mmu.tlb[0x3e].P,__debug_mmu.tlb[0x40+0x3e].L,__debug_mmu.tlb[0x40+0x3e].P
+printf "tlb[0x3f]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x3f].L,__debug_mmu.tlb[0x3f].P,__debug_mmu.tlb[0x40+0x3f].L,__debug_mmu.tlb[0x40+0x3f].P
+end
+
+
+define _pgd
+p (pgd_t[0x40])*(pgd_t*)(__debug_mmu.damr[0x3].L)
+end
+
+define _ptd_i
+p (pte_t[0x1000])*(pte_t*)(__debug_mmu.damr[0x4].L)
+end
+
+define _ptd_d
+p (pte_t[0x1000])*(pte_t*)(__debug_mmu.damr[0x5].L)
+end
diff -uNr /warthog/kernels/linux-2.6.10-rc1-bk10/Documentation/fujitsu/frv/gdbstub.txt linux-2.6.10-rc1-bk10-frv/Documentation/fujitsu/frv/gdbstub.txt
--- /warthog/kernels/linux-2.6.10-rc1-bk10/Documentation/fujitsu/frv/gdbstub.txt	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-bk10-frv/Documentation/fujitsu/frv/gdbstub.txt	2004-11-01 11:47:04.000000000 +0000
@@ -0,0 +1,130 @@
+			     ====================
+			     DEBUGGING FR-V LINUX
+			     ====================
+
+
+The kernel contains a GDB stub that talks GDB remote protocol across a serial
+port. This permits GDB to single step through the kernel, set breakpoints and
+trap exceptions that happen in kernel space and interrupt execution. It also
+permits the NMI interrupt button or serial port events to jump the kernel into
+the debugger.
+
+On the CPUs that have on-chip UARTs (FR400, FR403, FR405, FR555), the
+GDB stub hijacks a serial port for its own purposes, and makes it
+generate level 15 interrupts (NMI). The kernel proper cannot see the serial
+port in question under these conditions.
+
+On the MB93091-VDK CPU boards, the GDB stub uses UART1, which would otherwise
+be /dev/ttyS1. On the MB93093-PDK, the GDB stub uses UART0. Therefore, on the
+PDK there is no externally accessible serial port and the serial port to
+which the touch screen is attached becomes /dev/ttyS0.
+
+Note that the GDB stub runs entirely within CPU debug mode, and so should not
+incur any exceptions or interrupts whilst it is active. In particular, note
+that the clock will lose time since it is implemented in software.
+
+
+==================
+KERNEL PREPARATION
+==================
+
+Firstly, a debuggable kernel must be built. To do this, unpack the kernel tree
+and copy the configuration that you wish to use to .config. Then reconfigure
+the following things on the "Kernel Hacking" tab:
+
+  (*) "Include debugging information"
+
+      Set this to "Y". This causes all C and Assembly files to be compiled
+      to include debugging information.
+
+  (*) "In-kernel GDB stub"
+
+      Set this to "Y". This causes the GDB stub to be compiled into the
+      kernel.
+
+  (*) "Immediate activation"
+
+      Set this to "Y" if you want the GDB stub to activate as soon as possible
+      and wait for GDB to connect. This allows you to start tracing right from
+      the beginning of start_kernel() in init/main.c.
+
+  (*) "Console through GDB stub"
+
+      Set this to "Y" if you wish to be able to use "console=gdb0" on the
+      command line. That tells the kernel to pass system console messages to
+      GDB (which then prints them on its standard output). This is useful when
+      debugging the serial drivers that'd otherwise be used to pass console
+      messages to the outside world.
+
+Then build as usual, download to the board and execute. Note that if
+"Immediate activation" was selected, then the kernel will wait for GDB to
+attach. If not, then the kernel will boot immediately and GDB will have to
+interupt it or wait for an exception to occur if before doing anything with
+the kernel.
+
+
+=========================
+KERNEL DEBUGGING WITH GDB
+=========================
+
+Set the serial port on the computer that's going to run GDB to the appropriate
+baud rate. Assuming the board's debug port is connected to ttyS0/COM1 on the
+computer doing the debugging:
+
+	stty -F /dev/ttyS0 115200
+
+Then start GDB in the base of the kernel tree:
+
+	frv-uclinux-gdb linux		[uClinux]
+
+Or:
+
+	frv-uclinux-gdb vmlinux		[MMU linux]
+
+When the prompt appears:
+
+	GNU gdb frv-031024
+	Copyright 2003 Free Software Foundation, Inc.
+	GDB is free software, covered by the GNU General Public License, and you are
+	welcome to change it and/or distribute copies of it under certain conditions.
+	Type "show copying" to see the conditions.
+	There is absolutely no warranty for GDB.  Type "show warranty" for details.
+	This GDB was configured as "--host=i686-pc-linux-gnu --target=frv-uclinux"...
+	(gdb) 
+
+Attach to the board like this:
+
+        (gdb) target remote /dev/ttyS0
+	Remote debugging using /dev/ttyS0
+	start_kernel () at init/main.c:395
+	(gdb) 
+
+This should show the appropriate lines from the source too. The kernel can
+then be debugged almost as if it's any other program.
+
+
+===============================
+INTERRUPTING THE RUNNING KERNEL
+===============================
+
+The kernel can be interrupted whilst it is running, causing a jump back to the
+GDB stub and the debugger:
+
+  (*) Pressing Ctrl-C in GDB. This will cause GDB to try and interrupt the
+      kernel by sending an RS232 BREAK over the serial line to the GDB
+      stub. This will (mostly) immediately interrupt the kernel and return it
+      to the debugger.
+
+  (*) Pressing the NMI button on the board will also cause a jump into the
+      debugger.
+
+  (*) Setting a software breakpoint. This sets a break instruction at the
+      desired location which the GDB stub then traps the exception for.
+
+  (*) Setting a hardware breakpoint. The GDB stub is capable of using the IBAR
+      and DBAR registers to assist debugging.
+
+Furthermore, the GDB stub will intercept a number of exceptions automatically
+if they are caused by kernel execution. It will also intercept BUG() macro
+invokation.
+
diff -uNr /warthog/kernels/linux-2.6.10-rc1-bk10/Documentation/fujitsu/frv/mmu-layout.txt linux-2.6.10-rc1-bk10-frv/Documentation/fujitsu/frv/mmu-layout.txt
--- /warthog/kernels/linux-2.6.10-rc1-bk10/Documentation/fujitsu/frv/mmu-layout.txt	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-bk10-frv/Documentation/fujitsu/frv/mmu-layout.txt	2004-11-01 11:47:04.000000000 +0000
@@ -0,0 +1,306 @@
+				 =================================
+				 FR451 MMU LINUX MEMORY MANAGEMENT
+				 =================================
+
+============
+MMU HARDWARE
+============
+
+FR451 MMU Linux puts the MMU into EDAT mode whilst running. This means that it uses both the SAT
+registers and the DAT TLB to perform address translation.
+
+There are 8 IAMLR/IAMPR register pairs and 16 DAMLR/DAMPR register pairs for SAT mode.
+
+In DAT mode, there is also a TLB organised in cache format as 64 lines x 2 ways. Each line spans a
+16KB range of addresses, but can match a larger region.
+
+
+===========================
+MEMORY MANAGEMENT REGISTERS
+===========================
+
+Certain control registers are used by the kernel memory management routines:
+
+	REGISTERS		USAGE
+	======================	==================================================
+	IAMR0, DAMR0		Kernel image and data mappings
+	IAMR1, DAMR1		First-chance TLB lookup mapping
+	DAMR2			Page attachment for cache flush by page
+	DAMR3			Current PGD mapping
+	SCR0, DAMR4		Instruction TLB PGE/PTD cache
+	SCR1, DAMR5		Data TLB PGE/PTD cache
+	DAMR6-10		kmap_atomic() mappings
+	DAMR11			I/O mapping
+	CXNR			mm_struct context ID
+	TTBR			Page directory (PGD) pointer (physical address)
+
+
+=====================
+GENERAL MEMORY LAYOUT
+=====================
+
+The physical memory layout is as follows:
+
+  PHYSICAL ADDRESS	CONTROLLER	DEVICE
+  ===================	==============	=======================================
+  00000000 - BFFFFFFF	SDRAM		SDRAM area
+  E0000000 - EFFFFFFF	L-BUS CS2#	VDK SLBUS/PCI window
+  F0000000 - F0FFFFFF	L-BUS CS5#	MB93493 CSC area (DAV daughter board)
+  F1000000 - F1FFFFFF	L-BUS CS7#	(CB70 CPU-card PCMCIA port I/O space)
+  FC000000 - FC0FFFFF	L-BUS CS1#	VDK MB86943 config space
+  FC100000 - FC1FFFFF	L-BUS CS6#	DM9000 NIC I/O space
+  FC200000 - FC2FFFFF	L-BUS CS3#	MB93493 CSR area (DAV daughter board)
+  FD000000 - FDFFFFFF	L-BUS CS4#	(CB70 CPU-card extra flash space)
+  FE000000 - FEFFFFFF			Internal CPU peripherals
+  FF000000 - FF1FFFFF	L-BUS CS0#	Flash 1
+  FF200000 - FF3FFFFF	L-BUS CS0#	Flash 2
+  FFC00000 - FFC0001F	L-BUS CS0#	FPGA
+
+The virtual memory layout is:
+
+  VIRTUAL ADDRESS    PHYSICAL	TRANSLATOR	FLAGS	SIZE	OCCUPATION
+  =================  ========	==============	=======	=======	===================================
+  00004000-BFFFFFFF  various	TLB,xAMR1	D-N-??V	3GB	Userspace
+  C0000000-CFFFFFFF  00000000	xAMPR0		-L-S--V	256MB	Kernel image and data
+  D0000000-D7FFFFFF  various	TLB,xAMR1	D-NS??V	128MB	vmalloc area
+  D8000000-DBFFFFFF  various	TLB,xAMR1	D-NS??V	64MB	kmap() area
+  DC000000-DCFFFFFF  various	TLB			1MB	Secondary kmap_atomic() frame
+  DD000000-DD27FFFF  various	DAMR			160KB	Primary kmap_atomic() frame
+  DD040000			DAMR2/IAMR2	-L-S--V	page	Page cache flush attachment point
+  DD080000			DAMR3		-L-SC-V	page	Page Directory (PGD)
+  DD0C0000			DAMR4		-L-SC-V	page	Cached insn TLB Page Table lookup
+  DD100000			DAMR5		-L-SC-V	page	Cached data TLB Page Table lookup
+  DD140000			DAMR6		-L-S--V	page	kmap_atomic(KM_BOUNCE_READ)
+  DD180000			DAMR7		-L-S--V	page	kmap_atomic(KM_SKB_SUNRPC_DATA)
+  DD1C0000			DAMR8		-L-S--V	page	kmap_atomic(KM_SKB_DATA_SOFTIRQ)
+  DD200000			DAMR9		-L-S--V	page	kmap_atomic(KM_USER0)
+  DD240000			DAMR10		-L-S--V	page	kmap_atomic(KM_USER1)
+  E0000000-FFFFFFFF  E0000000	DAMR11		-L-SC-V	512MB	I/O region
+
+IAMPR1 and DAMPR1 are used as an extension to the TLB.
+
+
+====================
+KMAP AND KMAP_ATOMIC
+====================
+
+To access pages in the page cache (which may not be directly accessible if highmem is available),
+the kernel calls kmap(), does the access and then calls kunmap(); or it calls kmap_atomic(), does
+the access and then calls kunmap_atomic().
+
+kmap() creates an attachment between an arbitrary inaccessible page and a range of virtual
+addresses by installing a PTE in a special page table. The kernel can then access this page as it
+wills. When it's finished, the kernel calls kunmap() to clear the PTE.
+
+kmap_atomic() does something slightly different. In the interests of speed, it chooses one of two
+strategies:
+
+ (1) If possible, kmap_atomic() attaches the requested page to one of DAMPR5 through DAMPR10
+     register pairs; and the matching kunmap_atomic() clears the DAMPR. This makes high memory
+     support really fast as there's no need to flush the TLB or modify the page tables. The DAMLR
+     registers being used for this are preset during boot and don't change over the lifetime of the
+     process. There's a direct mapping between the first few kmap_atomic() types, DAMR number and
+     virtual address slot.
+
+     However, there are more kmap_atomic() types defined than there are DAMR registers available,
+     so we fall back to:
+
+ (2) kmap_atomic() uses a slot in the secondary frame (determined by the type parameter), and then
+     locks an entry in the TLB to translate that slot to the specified page. The number of slots is
+     obviously limited, and their positions are controlled such that each slot is matched by a
+     different line in the TLB. kunmap() ejects the entry from the TLB.
+
+Note that the first three kmap atomic types are really just declared as placeholders. The DAMPR
+registers involved are actually modified directly.
+
+Also note that kmap() itself may sleep, kmap_atomic() may never sleep and both always succeed;
+furthermore, a driver using kmap() may sleep before calling kunmap(), but may not sleep before
+calling kunmap_atomic() if it had previously called kmap_atomic().
+
+
+===============================
+USING MORE THAN 256MB OF MEMORY
+===============================
+
+The kernel cannot access more than 256MB of memory directly. The physical layout, however, permits
+up to 3GB of SDRAM (possibly 3.25GB) to be made available. By using CONFIG_HIGHMEM, the kernel can
+allow userspace (by way of page tables) and itself (by way of kmap) to deal with the memory
+allocation.
+
+External devices can, of course, still DMA to and from all of the SDRAM, even if the kernel can't
+see it directly. The kernel translates page references into real addresses for communicating to the
+devices.
+
+
+===================
+PAGE TABLE TOPOLOGY
+===================
+
+The page tables are arranged in 2-layer format. There is a middle layer (PMD) that would be used in
+3-layer format tables but that is folded into the top layer (PGD) and so consumes no extra memory
+or processing power.
+
+  +------+     PGD    PMD
+  | TTBR |--->+-------------------+
+  +------+    |      |      : STE |
+              | PGE0 | PME0 : STE |
+              |      |      : STE |
+              +-------------------+              Page Table
+              |      |      : STE -------------->+--------+ +0x0000
+              | PGE1 | PME0 : STE -----------+   | PTE0   |
+              |      |      : STE -------+   |   +--------+
+              +-------------------+      |   |   | PTE63  |
+              |      |      : STE |      |   +-->+--------+ +0x0100
+              | PGE2 | PME0 : STE |      |       | PTE64  |
+              |      |      : STE |      |       +--------+
+              +-------------------+      |       | PTE127 |
+              |      |      : STE |      +------>+--------+ +0x0200
+              | PGE3 | PME0 : STE |              | PTE128 |
+              |      |      : STE |              +--------+
+              +-------------------+              | PTE191 |
+                                                 +--------+ +0x0300
+
+Each Page Directory (PGD) is 16KB (page size) in size and is divided into 64 entries (PGEs). Each
+PGE contains one Page Mid Directory (PMD).
+
+Each PMD is 256 bytes in size and contains a single entry (PME). Each PME holds 64 FR451 MMU
+segment table entries of 4 bytes apiece. Each PME "points to" a page table. In practice, each STE
+points to a subset of the page table, the first to PT+0x0000, the second to PT+0x0100, the third to
+PT+0x200, and so on.
+
+Each PGE and PME covers 64MB of the total virtual address space.
+
+Each Page Table (PTD) is 16KB (page size) in size, and is divided into 4096 entries (PTEs). Each
+entry can point to one 16KB page. In practice, each Linux page table is subdivided into 64 FR451
+MMU page tables. But they are all grouped together to make management easier, in particular rmap
+support is then trivial.
+
+Grouping page tables in this fashion makes PGE caching in SCR0/SCR1 more efficient because the
+coverage of the cached item is greater.
+
+Page tables for the vmalloc area are allocated at boot time and shared between all mm_structs.
+
+
+=================
+USER SPACE LAYOUT
+=================
+
+For MMU capable Linux, the regions userspace code are allowed to access are kept entirely separate
+from those dedicated to the kernel:
+
+	VIRTUAL ADDRESS    SIZE   PURPOSE
+	=================  =====  ===================================
+	00000000-00003fff  4KB    NULL pointer access trap
+	00004000-01ffffff  ~32MB  lower mmap space (grows up)
+	02000000-021fffff  2MB    Stack space (grows down from top)
+	02200000-nnnnnnnn         Executable mapping
+        nnnnnnnn-                 brk space (grows up)
+	        -bfffffff         upper mmap space (grows down)
+
+This is so arranged so as to make best use of the 16KB page tables and the way in which PGEs/PMEs
+are cached by the TLB handler. The lower mmap space is filled first, and then the upper mmap space
+is filled.
+
+
+===============================
+GDB-STUB MMU DEBUGGING SERVICES
+===============================
+
+The gdb-stub included in this kernel provides a number of services to aid in the debugging of MMU
+related kernel services:
+
+ (*) Every time the kernel stops, certain state information is dumped into __debug_mmu. This
+     variable is defined in arch/frv/kernel/gdb-stub.c. Note that the gdbinit file in this
+     directory has some useful macros for dealing with this.
+
+     (*) __debug_mmu.tlb[]
+
+	 This receives the current TLB contents. This can be viewed with the _tlb GDB macro:
+
+		(gdb) _tlb
+		tlb[0x00]: 01000005 00718203  01000002 00718203
+		tlb[0x01]: 01004002 006d4201  01004005 006d4203
+		tlb[0x02]: 01008002 006d0201  01008006 00004200
+		tlb[0x03]: 0100c006 007f4202  0100c002 0064c202
+		tlb[0x04]: 01110005 00774201  01110002 00774201
+		tlb[0x05]: 01114005 00770201  01114002 00770201
+		tlb[0x06]: 01118002 0076c201  01118005 0076c201
+		...
+		tlb[0x3d]: 010f4002 00790200  001f4002 0054ca02
+		tlb[0x3e]: 010f8005 0078c201  010f8002 0078c201
+		tlb[0x3f]: 001fc002 0056ca01  001fc005 00538a01
+
+     (*) __debug_mmu.iamr[]
+     (*) __debug_mmu.damr[]
+
+	 These receive the current IAMR and DAMR contents. These can be viewed with with the _amr
+	 GDB macro:
+
+		(gdb) _amr
+		AMRx           DAMR                    IAMR         
+		====   =====================   =====================
+		amr0 : L:c0000000 P:00000cb9 : L:c0000000 P:000004b9
+		amr1 : L:01070005 P:006f9203 : L:0102c005 P:006a1201
+		amr2 : L:d8d00000 P:00000000 : L:d8d00000 P:00000000
+		amr3 : L:d8d04000 P:00534c0d : L:00000000 P:00000000
+		amr4 : L:d8d08000 P:00554c0d : L:00000000 P:00000000
+		amr5 : L:d8d0c000 P:00554c0d : L:00000000 P:00000000
+		amr6 : L:d8d10000 P:00000000 : L:00000000 P:00000000
+		amr7 : L:d8d14000 P:00000000 : L:00000000 P:00000000
+		amr8 : L:d8d18000 P:00000000
+		amr9 : L:d8d1c000 P:00000000
+		amr10: L:d8d20000 P:00000000
+		amr11: L:e0000000 P:e0000ccd
+
+ (*) The current task's page directory is bound to DAMR3.
+
+     This can be viewed with the _pgd GDB macro:
+	
+	(gdb) _pgd
+	$3 = {{pge = {{ste = {0x554001, 0x554101, 0x554201, 0x554301, 0x554401, 
+		  0x554501, 0x554601, 0x554701, 0x554801, 0x554901, 0x554a01, 
+		  0x554b01, 0x554c01, 0x554d01, 0x554e01, 0x554f01, 0x555001, 
+		  0x555101, 0x555201, 0x555301, 0x555401, 0x555501, 0x555601, 
+		  0x555701, 0x555801, 0x555901, 0x555a01, 0x555b01, 0x555c01, 
+		  0x555d01, 0x555e01, 0x555f01, 0x556001, 0x556101, 0x556201, 
+		  0x556301, 0x556401, 0x556501, 0x556601, 0x556701, 0x556801, 
+		  0x556901, 0x556a01, 0x556b01, 0x556c01, 0x556d01, 0x556e01, 
+		  0x556f01, 0x557001, 0x557101, 0x557201, 0x557301, 0x557401, 
+		  0x557501, 0x557601, 0x557701, 0x557801, 0x557901, 0x557a01, 
+		  0x557b01, 0x557c01, 0x557d01, 0x557e01, 0x557f01}}}}, {pge = {{
+		ste = {0x0 <repeats 64 times>}}}} <repeats 51 times>, {pge = {{ste = {
+		  0x248001, 0x248101, 0x248201, 0x248301, 0x248401, 0x248501, 
+		  0x248601, 0x248701, 0x248801, 0x248901, 0x248a01, 0x248b01, 
+		  0x248c01, 0x248d01, 0x248e01, 0x248f01, 0x249001, 0x249101, 
+		  0x249201, 0x249301, 0x249401, 0x249501, 0x249601, 0x249701, 
+		  0x249801, 0x249901, 0x249a01, 0x249b01, 0x249c01, 0x249d01, 
+		  0x249e01, 0x249f01, 0x24a001, 0x24a101, 0x24a201, 0x24a301, 
+		  0x24a401, 0x24a501, 0x24a601, 0x24a701, 0x24a801, 0x24a901, 
+		  0x24aa01, 0x24ab01, 0x24ac01, 0x24ad01, 0x24ae01, 0x24af01, 
+		  0x24b001, 0x24b101, 0x24b201, 0x24b301, 0x24b401, 0x24b501, 
+		  0x24b601, 0x24b701, 0x24b801, 0x24b901, 0x24ba01, 0x24bb01, 
+		  0x24bc01, 0x24bd01, 0x24be01, 0x24bf01}}}}, {pge = {{ste = {
+		  0x0 <repeats 64 times>}}}} <repeats 11 times>}
+
+ (*) The PTD last used by the instruction TLB miss handler is attached to DAMR4.
+ (*) The PTD last used by the data TLB miss handler is attached to DAMR5.
+
+     These can be viewed with the _ptd_i and _ptd_d GDB macros:
+
+	(gdb) _ptd_d
+	$5 = {{pte = 0x0} <repeats 127 times>, {pte = 0x539b01}, {
+	    pte = 0x0} <repeats 896 times>, {pte = 0x719303}, {pte = 0x6d5303}, {
+	    pte = 0x0}, {pte = 0x0}, {pte = 0x0}, {pte = 0x0}, {pte = 0x0}, {
+	    pte = 0x0}, {pte = 0x0}, {pte = 0x0}, {pte = 0x0}, {pte = 0x6a1303}, {
+	    pte = 0x0} <repeats 12 times>, {pte = 0x709303}, {pte = 0x0}, {pte = 0x0}, 
+	  {pte = 0x6fd303}, {pte = 0x6f9303}, {pte = 0x6f5303}, {pte = 0x0}, {
+	    pte = 0x6ed303}, {pte = 0x531b01}, {pte = 0x50db01}, {
+	    pte = 0x0} <repeats 13 times>, {pte = 0x5303}, {pte = 0x7f5303}, {
+	    pte = 0x509b01}, {pte = 0x505b01}, {pte = 0x7c9303}, {pte = 0x7b9303}, {
+	    pte = 0x7b5303}, {pte = 0x7b1303}, {pte = 0x7ad303}, {pte = 0x0}, {
+	    pte = 0x0}, {pte = 0x7a1303}, {pte = 0x0}, {pte = 0x795303}, {pte = 0x0}, {
+	    pte = 0x78d303}, {pte = 0x0}, {pte = 0x0}, {pte = 0x0}, {pte = 0x0}, {
+	    pte = 0x0}, {pte = 0x775303}, {pte = 0x771303}, {pte = 0x76d303}, {
+	    pte = 0x0}, {pte = 0x765303}, {pte = 0x7c5303}, {pte = 0x501b01}, {
+	    pte = 0x4f1b01}, {pte = 0x4edb01}, {pte = 0x0}, {pte = 0x4f9b01}, {
+	    pte = 0x4fdb01}, {pte = 0x0} <repeats 2992 times>}
diff -uNr /warthog/kernels/linux-2.6.10-rc1-bk10/Documentation/fujitsu/frv/README.txt linux-2.6.10-rc1-bk10-frv/Documentation/fujitsu/frv/README.txt
--- /warthog/kernels/linux-2.6.10-rc1-bk10/Documentation/fujitsu/frv/README.txt	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-bk10-frv/Documentation/fujitsu/frv/README.txt	2004-11-01 11:47:04.000000000 +0000
@@ -0,0 +1,51 @@
+		       ================================
+		       Fujitsu FR-V LINUX DOCUMENTATION
+		       ================================
+
+This directory contains documentation for the Fujitsu FR-V CPU architecture
+port of Linux.
+
+The following documents are available:
+
+ (*) features.txt
+
+     A description of the basic features inherent in this architecture port.
+
+
+ (*) configuring.txt
+
+     A summary of the configuration options particular to this architecture.
+
+
+ (*) booting.txt
+
+     A description of how to boot the kernel image and a summary of the kernel
+     command line options.
+
+
+ (*) gdbstub.txt
+
+     A description of how to debug the kernel using GDB attached by serial
+     port, and a summary of the services available.
+
+
+ (*) mmu-layout.txt
+
+     A description of the virtual and physical memory layout used in the
+     MMU linux kernel, and the registers used to support it.
+
+
+ (*) gdbinit
+
+     An example .gdbinit file for use with GDB. It includes macros for viewing
+     MMU state on the FR451. See mmu-layout.txt for more information.
+
+
+ (*) clock.txt
+
+     A description of the CPU clock scaling interface.
+
+
+ (*) atomic-ops.txt
+
+     A description of how the FR-V kernel's atomic operations work.

^ permalink raw reply	[flat|nested] 87+ messages in thread

* [PATCH 4/14] FRV: Bitops fixes
       [not found] <76b4a884-2c3c-11d9-91a1-0002b3163499@redhat.com>
@ 2004-11-01 19:30 ` dhowells
  2004-11-02  8:19   ` Andrew Morton
  2004-11-01 19:30 ` [PATCH 3/14] FRV: Fujitsu FR-V arch documentation dhowells
                   ` (15 subsequent siblings)
  16 siblings, 1 reply; 87+ messages in thread
From: dhowells @ 2004-11-01 19:30 UTC (permalink / raw)
  To: torvalds, akpm, davidm; +Cc: linux-kernel, uclinux-dev

The attached patch provides an out-of-line implementation of find_next_bit(),
and rearranges linux/bitops.h to avoid a dependency loop between inline
functions in there and in asm/bitops.h trying to include one another.

Signed-Off-By: dhowells@redhat.com
---
diffstat frv-bitops-2610rc1bk10.diff
 include/linux/bitops.h |    3 +-
 lib/Makefile           |    2 -
 lib/find_next_bit.c    |   55 +++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 58 insertions(+), 2 deletions(-)

diff -uNr /warthog/kernels/linux-2.6.10-rc1-bk10/include/linux/bitops.h linux-2.6.10-rc1-bk10-frv/include/linux/bitops.h
--- /warthog/kernels/linux-2.6.10-rc1-bk10/include/linux/bitops.h	2004-06-18 13:42:16.000000000 +0100
+++ linux-2.6.10-rc1-bk10-frv/include/linux/bitops.h	2004-11-01 11:47:05.091638567 +0000
@@ -1,7 +1,6 @@
 #ifndef _LINUX_BITOPS_H
 #define _LINUX_BITOPS_H
 #include <asm/types.h>
-#include <asm/bitops.h>
 
 /*
  * ffs: find first bit set. This is defined the same way as
@@ -71,6 +70,8 @@
 	return r;
 }
 
+#include <asm/bitops.h>
+
 extern __inline__ int get_bitmask_order(unsigned int count)
 {
 	int order;
diff -uNr /warthog/kernels/linux-2.6.10-rc1-bk10/lib/find_next_bit.c linux-2.6.10-rc1-bk10-frv/lib/find_next_bit.c
--- /warthog/kernels/linux-2.6.10-rc1-bk10/lib/find_next_bit.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-bk10-frv/lib/find_next_bit.c	2004-11-01 11:47:05.188630493 +0000
@@ -0,0 +1,55 @@
+/* find_next_bit.c: fallback find next bit implementation
+ *
+ * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * 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.
+ */
+
+#include <linux/bitops.h>
+
+int find_next_bit(const unsigned long *addr, int size, int offset)
+{
+	const unsigned long *base;
+	const int NBITS = sizeof(*addr) * 8;
+	unsigned long tmp;
+
+	base = addr;
+	if (offset) {
+		int suboffset;
+
+		addr += offset / NBITS;
+
+		suboffset = offset % NBITS;
+		if (suboffset) {
+			tmp = *addr;
+			tmp >>= suboffset;
+			if (tmp)
+				goto finish;
+		}
+
+		addr++;
+	}
+
+	while ((tmp = *addr) == 0)
+		addr++;
+
+	offset = (addr - base) * NBITS;
+
+ finish:
+	/* count the remaining bits without using __ffs() since that takes a 32-bit arg */
+	while (!(tmp & 0xff)) {
+		offset += 8;
+		tmp >>= 8;
+	}
+
+	while (!(tmp & 1)) {
+		offset++;
+		tmp >>= 1;
+	}
+
+	return offset;
+}
diff -uNr /warthog/kernels/linux-2.6.10-rc1-bk10/lib/Makefile linux-2.6.10-rc1-bk10-frv/lib/Makefile
--- /warthog/kernels/linux-2.6.10-rc1-bk10/lib/Makefile	2004-11-01 11:45:34.000000000 +0000
+++ linux-2.6.10-rc1-bk10-frv/lib/Makefile	2004-11-01 12:00:25.742993383 +0000
@@ -5,7 +5,7 @@
 lib-y := errno.o ctype.o string.o vsprintf.o cmdline.o \
 	 bust_spinlocks.o rbtree.o radix-tree.o dump_stack.o \
 	 kobject.o kref.o idr.o div64.o parser.o int_sqrt.o \
-	 bitmap.o extable.o kobject_uevent.o
+	 bitmap.o extable.o kobject_uevent.o find_next_bit.o
 
 ifeq ($(CONFIG_DEBUG_KOBJECT),y)
 CFLAGS_kobject.o += -DDEBUG

^ permalink raw reply	[flat|nested] 87+ messages in thread

* [PATCH 7/14] FRV: GDB stub dependent additional BUG()'s
       [not found] <76b4a884-2c3c-11d9-91a1-0002b3163499@redhat.com>
                   ` (6 preceding siblings ...)
  2004-11-01 19:30 ` [PATCH 9/14] FRV: CONFIG_MMU fixes dhowells
@ 2004-11-01 19:30 ` dhowells
  2004-11-02  9:34   ` Christoph Hellwig
  2004-11-02 16:09   ` David Howells
  2004-11-01 19:30 ` [PATCH 6/14] FRV: IDE fixes dhowells
                   ` (8 subsequent siblings)
  16 siblings, 2 replies; 87+ messages in thread
From: dhowells @ 2004-11-01 19:30 UTC (permalink / raw)
  To: torvalds, akpm, davidm; +Cc: linux-kernel, uclinux-dev

The attached patch adds a couple of extra BUG() calls if a GDB stub is
configured in the kernel. These allow the GDB stub to catch bad_page() and
panic().

Signed-Off-By: dhowells@redhat.com
---
diffstat frv-gdbstub-2610rc1bk10.diff
 kernel/panic.c  |    3 +++
 mm/page_alloc.c |    3 +++
 2 files changed, 6 insertions(+)

diff -uNr /warthog/kernels/linux-2.6.10-rc1-bk10/kernel/panic.c linux-2.6.10-rc1-bk10-frv/kernel/panic.c
--- /warthog/kernels/linux-2.6.10-rc1-bk10/kernel/panic.c	2004-10-27 17:32:38.000000000 +0100
+++ linux-2.6.10-rc1-bk10-frv/kernel/panic.c	2004-11-01 11:47:05.162632657 +0000
@@ -59,6 +59,9 @@
 	vsnprintf(buf, sizeof(buf), fmt, args);
 	va_end(args);
 	printk(KERN_EMERG "Kernel panic - not syncing: %s\n",buf);
+#ifdef CONFIG_GDBSTUB
+	BUG();
+#endif
 	bust_spinlocks(0);
 
 #ifdef CONFIG_SMP
diff -uNr /warthog/kernels/linux-2.6.10-rc1-bk10/mm/page_alloc.c linux-2.6.10-rc1-bk10-frv/mm/page_alloc.c
--- /warthog/kernels/linux-2.6.10-rc1-bk10/mm/page_alloc.c	2004-11-01 11:45:35.000000000 +0000
+++ linux-2.6.10-rc1-bk10-frv/mm/page_alloc.c	2004-11-01 11:47:05.230626996 +0000
@@ -83,6 +83,9 @@
 		page->mapping, page_mapcount(page), page_count(page));
 	printk(KERN_EMERG "Backtrace:\n");
 	dump_stack();
+#ifdef CONFIG_GDBSTUB
+	BUG();
+#endif
 	printk(KERN_EMERG "Trying to fix it up, but a reboot is needed\n");
 	page->flags &= ~(1 << PG_private	|
 			1 << PG_locked	|

^ permalink raw reply	[flat|nested] 87+ messages in thread

* [PATCH 10/14] FRV: Make calibrate_delay() optional
       [not found] <76b4a884-2c3c-11d9-91a1-0002b3163499@redhat.com>
                   ` (4 preceding siblings ...)
  2004-11-01 19:30 ` [PATCH 11/14] FRV: Add FDPIC ELF binary format driver dhowells
@ 2004-11-01 19:30 ` dhowells
  2004-11-02  0:06   ` john stultz
                     ` (4 more replies)
  2004-11-01 19:30 ` [PATCH 9/14] FRV: CONFIG_MMU fixes dhowells
                   ` (10 subsequent siblings)
  16 siblings, 5 replies; 87+ messages in thread
From: dhowells @ 2004-11-01 19:30 UTC (permalink / raw)
  To: torvalds, akpm, davidm; +Cc: linux-kernel, uclinux-dev

The attached patch makes calibrate_delay() optional. In this architecture, it's
a waste of time since we can predict exactly what it's going to come up with
just by looking at the CPU's hardware clock registers. Thus far, we haven't
seem a board with any clock not dependent on the CPU's clock.

Signed-Off-By: dhowells@redhat.com
---
diffstat frv-calibrate-2610rc1bk10.diff
 init/main.c     |   70 ---------------------------------------------
 lib/Makefile    |    3 +
 lib/calibrate.c |   86 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 88 insertions(+), 71 deletions(-)

diff -uNr /warthog/kernels/linux-2.6.10-rc1-bk10/init/main.c linux-2.6.10-rc1-bk10-frv/init/main.c
--- /warthog/kernels/linux-2.6.10-rc1-bk10/init/main.c	2004-11-01 11:45:34.000000000 +0000
+++ linux-2.6.10-rc1-bk10-frv/init/main.c	2004-11-01 11:47:05.147633905 +0000
@@ -182,15 +178,6 @@
 	return 0;
 }
 
-static unsigned long preset_lpj;
-static int __init lpj_setup(char *str)
-{
-	preset_lpj = simple_strtoul(str,NULL,0);
-	return 1;
-}
-
-__setup("lpj=", lpj_setup);
-
 /*
  * This should be approx 2 Bo*oMips to start (note initial shift), and will
  * still work even if initially too large, it will just take slightly longer
@@ -199,67 +190,6 @@
 
 EXPORT_SYMBOL(loops_per_jiffy);
 
-/*
- * This is the number of bits of precision for the loops_per_jiffy.  Each
- * bit takes on average 1.5/HZ seconds.  This (like the original) is a little
- * better than 1%
- */
-#define LPS_PREC 8
-
-void __devinit calibrate_delay(void)
-{
-	unsigned long ticks, loopbit;
-	int lps_precision = LPS_PREC;
-
-	if (preset_lpj) {
-		loops_per_jiffy = preset_lpj;
-		printk("Calibrating delay loop (skipped)... "
-			"%lu.%02lu BogoMIPS preset\n",
-			loops_per_jiffy/(500000/HZ),
-			(loops_per_jiffy/(5000/HZ)) % 100);
-	} else {
-		loops_per_jiffy = (1<<12);
-
-		printk(KERN_DEBUG "Calibrating delay loop... ");
-		while ((loops_per_jiffy <<= 1) != 0) {
-			/* wait for "start of" clock tick */
-			ticks = jiffies;
-			while (ticks == jiffies)
-				/* nothing */;
-			/* Go .. */
-			ticks = jiffies;
-			__delay(loops_per_jiffy);
-			ticks = jiffies - ticks;
-			if (ticks)
-				break;
-		}
-
-		/*
-		 * Do a binary approximation to get loops_per_jiffy set to
-		 * equal one clock (up to lps_precision bits)
-		 */
-		loops_per_jiffy >>= 1;
-		loopbit = loops_per_jiffy;
-		while (lps_precision-- && (loopbit >>= 1)) {
-			loops_per_jiffy |= loopbit;
-			ticks = jiffies;
-			while (ticks == jiffies)
-				/* nothing */;
-			ticks = jiffies;
-			__delay(loops_per_jiffy);
-			if (jiffies != ticks)	/* longer than 1 tick */
-				loops_per_jiffy &= ~loopbit;
-		}
-
-		/* Round the value and print it */
-		printk("%lu.%02lu BogoMIPS (lpj=%lu)\n",
-			loops_per_jiffy/(500000/HZ),
-			(loops_per_jiffy/(5000/HZ)) % 100,
-			loops_per_jiffy);
-	}
-
-}
-
 static int __init debug_kernel(char *str)
 {
 	if (*str)
diff -uNr /warthog/kernels/linux-2.6.10-rc1-bk10/lib/calibrate.c linux-2.6.10-rc1-bk10-frv/lib/calibrate.c
--- /warthog/kernels/linux-2.6.10-rc1-bk10/lib/calibrate.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-bk10-frv/lib/calibrate.c	2004-11-01 11:47:05.186630659 +0000
@@ -0,0 +1,86 @@
+/* calibrate.c: default delay calibration
+ *
+ * Excised from init/main.c
+ *
+ *  Copyright (C) 1991, 1992  Linus Torvalds
+ *
+ *  GK 2/5/95  -  Changed to support mounting root fs via NFS
+ *  Added initrd & change_root: Werner Almesberger & Hans Lermen, Feb '96
+ *  Moan early if gcc is old, avoiding bogus kernels - Paul Gortmaker, May '96
+ *  Simplified starting of init:  Michael A. Griffith <grif@acm.org> 
+ *
+ */
+
+#include <linux/sched.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+
+static unsigned long preset_lpj;
+static int __init lpj_setup(char *str)
+{
+	preset_lpj = simple_strtoul(str,NULL,0);
+	return 1;
+}
+
+__setup("lpj=", lpj_setup);
+
+/*
+ * This is the number of bits of precision for the loops_per_jiffy.  Each
+ * bit takes on average 1.5/HZ seconds.  This (like the original) is a little
+ * better than 1%
+ */
+#define LPS_PREC 8
+
+void __devinit calibrate_delay(void)
+{
+	unsigned long ticks, loopbit;
+	int lps_precision = LPS_PREC;
+
+	if (preset_lpj) {
+		loops_per_jiffy = preset_lpj;
+		printk("Calibrating delay loop (skipped)... "
+			"%lu.%02lu BogoMIPS preset\n",
+			loops_per_jiffy/(500000/HZ),
+			(loops_per_jiffy/(5000/HZ)) % 100);
+	} else {
+		loops_per_jiffy = (1<<12);
+
+		printk(KERN_DEBUG "Calibrating delay loop... ");
+		while ((loops_per_jiffy <<= 1) != 0) {
+			/* wait for "start of" clock tick */
+			ticks = jiffies;
+			while (ticks == jiffies)
+				/* nothing */;
+			/* Go .. */
+			ticks = jiffies;
+			__delay(loops_per_jiffy);
+			ticks = jiffies - ticks;
+			if (ticks)
+				break;
+		}
+
+		/*
+		 * Do a binary approximation to get loops_per_jiffy set to
+		 * equal one clock (up to lps_precision bits)
+		 */
+		loops_per_jiffy >>= 1;
+		loopbit = loops_per_jiffy;
+		while (lps_precision-- && (loopbit >>= 1)) {
+			loops_per_jiffy |= loopbit;
+			ticks = jiffies;
+			while (ticks == jiffies)
+				/* nothing */;
+			ticks = jiffies;
+			__delay(loops_per_jiffy);
+			if (jiffies != ticks)	/* longer than 1 tick */
+				loops_per_jiffy &= ~loopbit;
+		}
+
+		/* Round the value and print it */
+		printk("%lu.%02lu BogoMIPS (lpj=%lu)\n",
+			loops_per_jiffy/(500000/HZ),
+			(loops_per_jiffy/(5000/HZ)) % 100,
+			loops_per_jiffy);
+	}
+
+}
diff -uNr /warthog/kernels/linux-2.6.10-rc1-bk10/lib/Makefile linux-2.6.10-rc1-bk10-frv/lib/Makefile
--- /warthog/kernels/linux-2.6.10-rc1-bk10/lib/Makefile	2004-11-01 11:45:34.000000000 +0000
+++ linux-2.6.10-rc1-bk10-frv/lib/Makefile	2004-11-01 12:00:25.742993383 +0000
@@ -5,7 +5,8 @@
 lib-y := errno.o ctype.o string.o vsprintf.o cmdline.o \
 	 bust_spinlocks.o rbtree.o radix-tree.o dump_stack.o \
 	 kobject.o kref.o idr.o div64.o parser.o int_sqrt.o \
-	 bitmap.o extable.o kobject_uevent.o find_next_bit.o
+	 bitmap.o extable.o kobject_uevent.o find_next_bit.o \
+	 calibrate.o
 
 ifeq ($(CONFIG_DEBUG_KOBJECT),y)
 CFLAGS_kobject.o += -DDEBUG

^ permalink raw reply	[flat|nested] 87+ messages in thread

* [PATCH 9/14] FRV: CONFIG_MMU fixes
       [not found] <76b4a884-2c3c-11d9-91a1-0002b3163499@redhat.com>
                   ` (5 preceding siblings ...)
  2004-11-01 19:30 ` [PATCH 10/14] FRV: Make calibrate_delay() optional dhowells
@ 2004-11-01 19:30 ` dhowells
  2004-11-02  9:43   ` Christoph Hellwig
  2004-11-03 15:06   ` David Howells
  2004-11-01 19:30 ` [PATCH 7/14] FRV: GDB stub dependent additional BUG()'s dhowells
                   ` (9 subsequent siblings)
  16 siblings, 2 replies; 87+ messages in thread
From: dhowells @ 2004-11-01 19:30 UTC (permalink / raw)
  To: torvalds, akpm, davidm; +Cc: linux-kernel, uclinux-dev

The attached patch adds dependencies on CONFIG_MMU being #defined in some extra
places that need it.

Signed-Off-By: dhowells@redhat.com
---
diffstat frv-mmu-fixes-2610rc1bk10.diff
 fs/proc/kcore.c     |    2 ++
 fs/proc/proc_misc.c |    8 ++++++++
 include/linux/mm.h  |    5 +++++
 init/Kconfig        |    4 ++--
 init/main.c         |    2 ++
 kernel/sysctl.c     |    2 ++
 mm/Makefile         |    4 ++--
 7 files changed, 23 insertions(+), 4 deletions(-)

diff -uNr /warthog/kernels/linux-2.6.10-rc1-bk10/fs/proc/kcore.c linux-2.6.10-rc1-bk10-frv/fs/proc/kcore.c
--- /warthog/kernels/linux-2.6.10-rc1-bk10/fs/proc/kcore.c	2004-09-16 12:06:14.000000000 +0100
+++ linux-2.6.10-rc1-bk10-frv/fs/proc/kcore.c	2004-11-01 11:47:04.872656796 +0000
@@ -344,6 +344,7 @@
 		if (m == NULL) {
 			if (clear_user(buffer, tsz))
 				return -EFAULT;
+#ifdef CONFIG_MMU
 		} else if ((start >= VMALLOC_START) && (start < VMALLOC_END)) {
 			char * elf_buf;
 			struct vm_struct *m;
@@ -389,6 +390,7 @@
 				return -EFAULT;
 			}
 			kfree(elf_buf);
+#endif
 		} else {
 			if (kern_addr_valid(start)) {
 				unsigned long n;
diff -uNr /warthog/kernels/linux-2.6.10-rc1-bk10/fs/proc/proc_misc.c linux-2.6.10-rc1-bk10-frv/fs/proc/proc_misc.c
--- /warthog/kernels/linux-2.6.10-rc1-bk10/fs/proc/proc_misc.c	2004-11-01 11:45:28.000000000 +0000
+++ linux-2.6.10-rc1-bk10-frv/fs/proc/proc_misc.c	2004-11-01 11:47:04.873656713 +0000
@@ -100,6 +100,7 @@
 	unsigned long largest_chunk;
 };
 
+#ifdef CONFIG_MMU
 static struct vmalloc_info get_vmalloc_info(void)
 {
 	unsigned long prev_end = VMALLOC_START;
@@ -129,6 +130,7 @@
 	read_unlock(&vmlist_lock);
 	return vmi;
 }
+#endif
 
 static int uptime_read_proc(char *page, char **start, off_t off,
 				 int count, int *eof, void *data)
@@ -176,10 +178,16 @@
 	allowed = ((totalram_pages - hugetlb_total_pages())
 		* sysctl_overcommit_ratio / 100) + total_swap_pages;
 
+#ifdef CONFIG_MMU
 	vmtot = (VMALLOC_END-VMALLOC_START)>>10;
 	vmi = get_vmalloc_info();
 	vmi.used >>= 10;
 	vmi.largest_chunk >>= 10;
+#else
+	vmtot = 0;
+	vmi.used = 0;
+	vmi.largest_chunk = 0;
+#endif
 
 	/*
 	 * Tagged format, for easy grepping and expansion.
diff -uNr /warthog/kernels/linux-2.6.10-rc1-bk10/include/linux/mm.h linux-2.6.10-rc1-bk10-frv/include/linux/mm.h
--- /warthog/kernels/linux-2.6.10-rc1-bk10/include/linux/mm.h	2004-11-01 11:45:33.371274107 +0000
+++ linux-2.6.10-rc1-bk10-frv/include/linux/mm.h	2004-11-01 14:16:26.408497251 +0000
@@ -58,6 +58,7 @@
  * space that has a special rule for the page-fault handlers (ie a shared
  * library, the executable area etc).
  */
+#ifdef CONFIG_MMU
 struct vm_area_struct {
 	struct mm_struct * vm_mm;	/* The address space we belong to. */
 	unsigned long vm_start;		/* Our start address within vm_mm. */
@@ -658,12 +688,14 @@
 	for (prio_tree_iter_init(iter, root, begin, end), vma = NULL;	\
 		(vma = vma_prio_tree_next(vma, iter)); )
 
+#ifdef CONFIG_MMU
 static inline void vma_nonlinear_insert(struct vm_area_struct *vma,
 					struct list_head *list)
 {
 	vma->shared.vm_set.parent = NULL;
 	list_add_tail(&vma->shared.vm_set.list, list);
 }
+#endif
 
 /* mmap.c */
 extern void vma_adjust(struct vm_area_struct *vma, unsigned long start,
@@ -780,6 +812,7 @@
 }
 #endif /* CONFIG_PROC_FS */
 
+#ifdef CONFIG_MMU
 static inline void vm_stat_account(struct vm_area_struct *vma)
 {
 	__vm_stat_account(vma->vm_mm, vma->vm_flags, vma->vm_file,
@@ -791,6 +824,7 @@
 	__vm_stat_account(vma->vm_mm, vma->vm_flags, vma->vm_file,
 							-vma_pages(vma));
 }
+#endif
 
 #ifndef CONFIG_DEBUG_PAGEALLOC
 static inline void
diff -uNr /warthog/kernels/linux-2.6.10-rc1-bk10/init/main.c linux-2.6.10-rc1-bk10-frv/init/main.c
--- /warthog/kernels/linux-2.6.10-rc1-bk10/init/main.c	2004-11-01 11:45:34.000000000 +0000
+++ linux-2.6.10-rc1-bk10-frv/init/main.c	2004-11-01 11:47:05.147633905 +0000
@@ -550,8 +478,10 @@
 		late_time_init();
 	calibrate_delay();
 	pidmap_init();
+#ifdef CONFIG_MMU
 	pgtable_cache_init();
 	prio_tree_init();
+#endif
 	anon_vma_init();
 #ifdef CONFIG_X86
 	if (efi_enabled)
diff -uNr /warthog/kernels/linux-2.6.10-rc1-bk10/init/Kconfig linux-2.6.10-rc1-bk10-frv/init/Kconfig
--- /warthog/kernels/linux-2.6.10-rc1-bk10/init/Kconfig	2004-11-01 11:45:34.655167224 +0000
+++ linux-2.6.10-rc1-bk10-frv/init/Kconfig	2004-11-01 14:22:25.047043376 +0000
@@ -316,8 +316,8 @@
 	  If unsure, say N.
 
 config SHMEM
-	default y
-	bool "Use full shmem filesystem" if EMBEDDED && MMU
+	bool "Use full shmem filesystem"
+	default y if EMBEDDED && MMU
 	help
 	  The shmem is an internal filesystem used to manage shared memory.
 	  It is backed by swap and manages resource limits. It is also exported
diff -uNr /warthog/kernels/linux-2.6.10-rc1-bk10/kernel/sysctl.c linux-2.6.10-rc1-bk10-frv/kernel/sysctl.c
--- /warthog/kernels/linux-2.6.10-rc1-bk10/kernel/sysctl.c	2004-11-01 11:45:34.879148578 +0000
+++ linux-2.6.10-rc1-bk10-frv/kernel/sysctl.c	2004-11-01 11:47:05.181631075 +0000
@@ -755,6 +755,7 @@
 		.strategy	= &sysctl_intvec,
 		.extra1		= &zero,
 	},
+#ifdef CONFIG_MMU
 	{
 		.ctl_name	= VM_MAX_MAP_COUNT,
 		.procname	= "max_map_count",
@@ -763,6 +764,7 @@
 		.mode		= 0644,
 		.proc_handler	= &proc_dointvec
 	},
+#endif
 	{
 		.ctl_name	= VM_LAPTOP_MODE,
 		.procname	= "laptop_mode",
diff -uNr /warthog/kernels/linux-2.6.10-rc1-bk10/mm/Makefile linux-2.6.10-rc1-bk10-frv/mm/Makefile
--- /warthog/kernels/linux-2.6.10-rc1-bk10/mm/Makefile	2004-10-19 10:42:19.000000000 +0100
+++ linux-2.6.10-rc1-bk10-frv/mm/Makefile	2004-11-01 14:18:47.213937144 +0000
@@ -5,10 +5,10 @@
 mmu-y			:= nommu.o
 mmu-$(CONFIG_MMU)	:= fremap.o highmem.o madvise.o memory.o mincore.o \
 			   mlock.o mmap.o mprotect.o mremap.o msync.o rmap.o \
-			   vmalloc.o
+			   vmalloc.o prio_tree.o
 
 obj-y			:= bootmem.o filemap.o mempool.o oom_kill.o fadvise.o \
-			   page_alloc.o page-writeback.o pdflush.o prio_tree.o \
+			   page_alloc.o page-writeback.o pdflush.o \
 			   readahead.o slab.o swap.o truncate.o vmscan.o \
 			   $(mmu-y)
 

^ permalink raw reply	[flat|nested] 87+ messages in thread

* [PATCH 6/14] FRV: IDE fixes
       [not found] <76b4a884-2c3c-11d9-91a1-0002b3163499@redhat.com>
                   ` (7 preceding siblings ...)
  2004-11-01 19:30 ` [PATCH 7/14] FRV: GDB stub dependent additional BUG()'s dhowells
@ 2004-11-01 19:30 ` dhowells
  2004-11-01 22:53   ` Alan Cox
  2004-11-01 19:30 ` [PATCH 13/14] FRV: Convert extern inline -> static inline dhowells
                   ` (7 subsequent siblings)
  16 siblings, 1 reply; 87+ messages in thread
From: dhowells @ 2004-11-01 19:30 UTC (permalink / raw)
  To: torvalds, akpm, davidm; +Cc: linux-kernel, uclinux-dev

The attached patch fixes the IDE driver to initialise correctly in the case
that IDE_ARCH_OBSOLETE_INIT is not defined.

Signed-Off-By: dhowells@redhat.com
---
diffstat frv-ide-2610rc1bk10.diff
 setup-pci.c |    5 +++++
 1 files changed, 5 insertions(+)

diff -uNr /warthog/kernels/linux-2.6.10-rc1-bk10/drivers/ide/setup-pci.c linux-2.6.10-rc1-bk10-frv/drivers/ide/setup-pci.c
--- /warthog/kernels/linux-2.6.10-rc1-bk10/drivers/ide/setup-pci.c	2004-11-01 11:45:23.000000000 +0000
+++ linux-2.6.10-rc1-bk10-frv/drivers/ide/setup-pci.c	2004-11-01 11:47:04.826660626 +0000
@@ -425,7 +425,12 @@
 	if (hwif->io_ports[IDE_DATA_OFFSET] != base ||
 	    hwif->io_ports[IDE_CONTROL_OFFSET] != (ctl | 2)) {
 		memset(&hwif->hw, 0, sizeof(hwif->hw));
+#ifndef IDE_ARCH_OBSOLETE_INIT
+		ide_std_init_ports(&hwif->hw, base, (ctl | 2));
+		hwif->hw.io_ports[IDE_IRQ_OFFSET] = 0;
+#else
 		ide_init_hwif_ports(&hwif->hw, base, (ctl | 2), NULL);
+#endif
 		memcpy(hwif->io_ports, hwif->hw.io_ports, sizeof(hwif->io_ports));
 		hwif->noprobe = !hwif->io_ports[IDE_DATA_OFFSET];
 	}

^ permalink raw reply	[flat|nested] 87+ messages in thread

* [PATCH 11/14] FRV: Add FDPIC ELF binary format driver
       [not found] <76b4a884-2c3c-11d9-91a1-0002b3163499@redhat.com>
                   ` (3 preceding siblings ...)
  2004-11-01 19:30 ` [PATCH 8/14] FRV: GP-REL data support dhowells
@ 2004-11-01 19:30 ` dhowells
  2004-11-02  8:18   ` Andrew Morton
                     ` (2 more replies)
  2004-11-01 19:30 ` [PATCH 10/14] FRV: Make calibrate_delay() optional dhowells
                   ` (11 subsequent siblings)
  16 siblings, 3 replies; 87+ messages in thread
From: dhowells @ 2004-11-01 19:30 UTC (permalink / raw)
  To: torvalds, akpm, davidm; +Cc: linux-kernel, uclinux-dev

The attached patch adds a new binary format driver that allows a special
variety of ELF to be used that permits the dynamic sections that comprise an
executable, its dynamic loader and its shared libaries and its stack and data
to be located anywhere within the address space.

This is used to provide shared libraries and shared executables (at least, as
far as the read-only dynamic sections go) on uClinux. Not only that, but the
same binaries can be run on MMU linux without a problem.

This is achieved by:

 (1) Passing loadmaps to the dynamic loader (or to a statically linked
     executable) to indicate the whereabouts of the various dynamic sections.

 (2) Using a GOT inside the program.

 (3) Passing setup_arg_pages() the stack pointer to be.

 (4) Allowing the arch greated control over how an executable is laid out in
     memory in MMU Linux.

 (5) Rewriting mm/nommu.c to support MAP_PRIVATE on files, thus allowing _mmap_
     to handle sharing of private-readonly mappings.

Signed-Off-By: dhowells@redhat.com
---
diffstat frv-binfmt-2610rc1bk10.diff
 fs/Kconfig.binfmt           |   12 
 fs/Makefile                 |    1 
 fs/binfmt_aout.c            |    2 
 fs/binfmt_elf.c             |    2 
 fs/binfmt_elf_fdpic.c       | 1087 ++++++++++++++++++++++++++++++++++++++++++++
 fs/binfmt_som.c             |    2 
 fs/exec.c                   |   12 
 include/linux/binfmts.h     |    4 
 include/linux/elf-fdpic.h   |   67 ++
 include/linux/elf.h         |    7 
 include/linux/personality.h |    4 
 11 files changed, 1189 insertions(+), 11 deletions(-)

diff -uNr /warthog/kernels/linux-2.6.10-rc1-bk10/include/linux/personality.h linux-2.6.10-rc1-bk10-frv/include/linux/personality.h
--- /warthog/kernels/linux-2.6.10-rc1-bk10/include/linux/personality.h	2004-10-19 10:42:17.000000000 +0100
+++ linux-2.6.10-rc1-bk10-frv/include/linux/personality.h	2004-11-01 11:47:05.125635737 +0000
@@ -18,6 +18,9 @@
  * These occupy the top three bytes.
  */
 enum {
+	FDPIC_FUNCPTRS =	0x0080000,	/* userspace function ptrs point to descriptors
+						 * (signal handling)
+						 */
 	MMAP_PAGE_ZERO =	0x0100000,
 	ADDR_COMPAT_LAYOUT =	0x0200000,
 	READ_IMPLIES_EXEC =	0x0400000,
@@ -43,6 +46,7 @@
 enum {
 	PER_LINUX =		0x0000,
 	PER_LINUX_32BIT =	0x0000 | ADDR_LIMIT_32BIT,
+	PER_LINUX_FDPIC =	0x0000 | FDPIC_FUNCPTRS,
 	PER_SVR4 =		0x0001 | STICKY_TIMEOUTS | MMAP_PAGE_ZERO,
 	PER_SVR3 =		0x0002 | STICKY_TIMEOUTS | SHORT_INODE,
 	PER_SCOSVR3 =		0x0003 | STICKY_TIMEOUTS |
diff -uNr /warthog/kernels/linux-2.6.10-rc1-bk10/include/linux/elf-fdpic.h linux-2.6.10-rc1-bk10-frv/include/linux/elf-fdpic.h
--- /warthog/kernels/linux-2.6.10-rc1-bk10/include/linux/elf-fdpic.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-bk10-frv/include/linux/elf-fdpic.h	2004-11-01 11:47:05.101637734 +0000
@@ -0,0 +1,67 @@
+/* elf-fdpic.h: FDPIC ELF load map
+ *
+ * Copyright (C) 2003 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * 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.
+ */
+
+#ifndef _LINUX_ELF_FDPIC_H
+#define _LINUX_ELF_FDPIC_H
+
+#include <linux/elf.h>
+
+#define PT_GNU_STACK    (PT_LOOS + 0x474e551)
+
+/* segment mappings for ELF FDPIC libraries/executables/interpreters */
+struct elf32_fdpic_loadseg {
+	Elf32_Addr	addr;		/* core address to which mapped */
+	Elf32_Addr	p_vaddr;	/* VMA recorded in file */
+	Elf32_Word	p_memsz;	/* allocation size recorded in file */
+};
+
+struct elf32_fdpic_loadmap {
+	Elf32_Half	version;	/* version of these structures, just in case... */
+	Elf32_Half	nsegs;		/* number of segments */
+	struct elf32_fdpic_loadseg segs[];
+};
+
+#define ELF32_FDPIC_LOADMAP_VERSION	0x0000
+
+/*
+ * binfmt binary parameters structure
+ */
+struct elf_fdpic_params {
+	struct elfhdr			hdr;		/* ref copy of ELF header */
+	struct elf_phdr			*phdrs;		/* ref copy of PT_PHDR table */
+	struct elf32_fdpic_loadmap	*loadmap;	/* loadmap to be passed to userspace */
+	unsigned long			elfhdr_addr;	/* mapped ELF header user address */
+	unsigned long			ph_addr;	/* mapped PT_PHDR user address */
+	unsigned long			map_addr;	/* mapped loadmap user address */
+	unsigned long			entry_addr;	/* mapped entry user address */
+	unsigned long			stack_size;	/* stack size requested (PT_GNU_STACK) */
+	unsigned long			dynamic_addr;	/* mapped PT_DYNAMIC user address */
+	unsigned long			load_addr;	/* user address at which to map binary */
+	unsigned long			flags;
+#define ELF_FDPIC_FLAG_ARRANGEMENT	0x0000000f	/* PT_LOAD arrangement flags */
+#define ELF_FDPIC_FLAG_INDEPENDENT	0x00000000	/* PT_LOADs can be put anywhere */
+#define ELF_FDPIC_FLAG_HONOURVADDR	0x00000001	/* PT_LOAD.vaddr must be honoured */
+#define ELF_FDPIC_FLAG_CONSTDISP	0x00000002	/* PT_LOADs require constant
+							 * displacement */
+#define ELF_FDPIC_FLAG_CONTIGUOUS	0x00000003	/* PT_LOADs should be contiguous */
+#define ELF_FDPIC_FLAG_EXEC_STACK	0x00000010	/* T if stack to be executable */
+#define ELF_FDPIC_FLAG_NOEXEC_STACK	0x00000020	/* T if stack not to be executable */
+#define ELF_FDPIC_FLAG_PRESENT		0x80000000	/* T if this object is present */
+};
+
+#ifdef CONFIG_MMU
+extern void elf_fdpic_arch_lay_out_mm(struct elf_fdpic_params *exec_params,
+				      struct elf_fdpic_params *interp_params,
+				      unsigned long *start_stack,
+				      unsigned long *start_brk);
+#endif
+
+#endif /* _LINUX_ELF_FDPIC_H */
diff -uNr /warthog/kernels/linux-2.6.10-rc1-bk10/include/linux/elf.h linux-2.6.10-rc1-bk10-frv/include/linux/elf.h
--- /warthog/kernels/linux-2.6.10-rc1-bk10/include/linux/elf.h	2004-10-19 10:42:16.000000000 +0100
+++ linux-2.6.10-rc1-bk10-frv/include/linux/elf.h	2004-11-01 11:47:05.104637485 +0000
@@ -36,8 +36,9 @@
 #define PT_NOTE    4
 #define PT_SHLIB   5
 #define PT_PHDR    6
-#define PT_LOOS	   0x60000000
-#define PT_HIOS	   0x6fffffff
+#define PT_TLS     7               /* Thread local storage segment */
+#define PT_LOOS    0x60000000      /* OS-specific */
+#define PT_HIOS    0x6fffffff      /* OS-specific */
 #define PT_LOPROC  0x70000000
 #define PT_HIPROC  0x7fffffff
 #define PT_GNU_EH_FRAME		0x6474e550
@@ -109,6 +110,8 @@
  */
 #define EM_S390_OLD     0xA390
 
+#define EM_FRV		0x5441		/* Fujitsu FR-V */
+
 /* This is the info that is needed to parse the dynamic section of the file */
 #define DT_NULL		0
 #define DT_NEEDED	1
diff -uNr /warthog/kernels/linux-2.6.10-rc1-bk10/include/linux/binfmts.h linux-2.6.10-rc1-bk10-frv/include/linux/binfmts.h
--- /warthog/kernels/linux-2.6.10-rc1-bk10/include/linux/binfmts.h	2004-09-16 12:06:20.000000000 +0100
+++ linux-2.6.10-rc1-bk10-frv/include/linux/binfmts.h	2004-11-01 11:47:05.087638900 +0000
@@ -74,7 +74,9 @@
 #define EXSTACK_DISABLE_X 1	/* Disable executable stacks */
 #define EXSTACK_ENABLE_X  2	/* Enable executable stacks */
 
-extern int setup_arg_pages(struct linux_binprm * bprm, int executable_stack);
+extern int setup_arg_pages(struct linux_binprm * bprm,
+			   unsigned long stack_top,
+			   int executable_stack);
 extern int copy_strings(int argc,char __user * __user * argv,struct linux_binprm *bprm); 
 extern int copy_strings_kernel(int argc,char ** argv,struct linux_binprm *bprm);
 extern void compute_creds(struct linux_binprm *binprm);
diff -uNr /warthog/kernels/linux-2.6.10-rc1-bk10/fs/binfmt_aout.c linux-2.6.10-rc1-bk10-frv/fs/binfmt_aout.c
--- /warthog/kernels/linux-2.6.10-rc1-bk10/fs/binfmt_aout.c	2004-10-27 17:32:30.000000000 +0100
+++ linux-2.6.10-rc1-bk10-frv/fs/binfmt_aout.c	2004-11-01 11:47:04.000000000 +0000
@@ -415,7 +415,7 @@
 
 	set_brk(current->mm->start_brk, current->mm->brk);
 
-	retval = setup_arg_pages(bprm, EXSTACK_DEFAULT);
+	retval = setup_arg_pages(bprm, STACK_TOP, EXSTACK_DEFAULT);
 	if (retval < 0) { 
 		/* Someone check-me: is this error path enough? */ 
 		send_sig(SIGKILL, current, 0); 
diff -uNr /warthog/kernels/linux-2.6.10-rc1-bk10/fs/binfmt_elf.c linux-2.6.10-rc1-bk10-frv/fs/binfmt_elf.c
--- /warthog/kernels/linux-2.6.10-rc1-bk10/fs/binfmt_elf.c	2004-10-27 17:32:30.000000000 +0100
+++ linux-2.6.10-rc1-bk10-frv/fs/binfmt_elf.c	2004-11-01 11:47:04.000000000 +0000
@@ -718,7 +718,7 @@
 	   change some of these later */
 	current->mm->rss = 0;
 	current->mm->free_area_cache = current->mm->mmap_base;
-	retval = setup_arg_pages(bprm, executable_stack);
+	retval = setup_arg_pages(bprm, STACK_TOP, executable_stack);
 	if (retval < 0) {
 		send_sig(SIGKILL, current, 0);
 		goto out_free_dentry;
diff -uNr /warthog/kernels/linux-2.6.10-rc1-bk10/fs/binfmt_elf_fdpic.c linux-2.6.10-rc1-bk10-frv/fs/binfmt_elf_fdpic.c
--- /warthog/kernels/linux-2.6.10-rc1-bk10/fs/binfmt_elf_fdpic.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-bk10-frv/fs/binfmt_elf_fdpic.c	2004-11-01 15:19:44.950293037 +0000
@@ -0,0 +1,1087 @@
+/* binfmt_elf_fdpic.c: FDPIC ELF binary format
+ *
+ * Copyright (C) 2003, 2004 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ * Derived from binfmt_elf.c
+ *
+ * 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.
+ */
+
+#include <linux/module.h>
+
+#include <linux/fs.h>
+#include <linux/stat.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/mman.h>
+#include <linux/errno.h>
+#include <linux/signal.h>
+#include <linux/binfmts.h>
+#include <linux/string.h>
+#include <linux/file.h>
+#include <linux/fcntl.h>
+#include <linux/slab.h>
+#include <linux/highmem.h>
+#include <linux/personality.h>
+#include <linux/ptrace.h>
+#include <linux/init.h>
+#include <linux/smp_lock.h>
+#include <linux/elf.h>
+#include <linux/elf-fdpic.h>
+#include <linux/elfcore.h>
+
+#include <asm/uaccess.h>
+#include <asm/param.h>
+#include <asm/pgalloc.h>
+
+typedef char *elf_caddr_t;
+#ifndef elf_addr_t
+#define elf_addr_t unsigned long
+#endif
+
+#if 0
+#define kdebug(fmt, ...) printk("FDPIC "fmt"\n" ,##__VA_ARGS__ )
+#else
+#define kdebug(fmt, ...) do {} while(0)
+#endif
+
+MODULE_LICENSE("GPL");
+
+static int load_elf_fdpic_binary(struct linux_binprm *bprm, struct pt_regs *regs);
+//static int load_elf_fdpic_library(struct file *);
+static int elf_fdpic_fetch_phdrs(struct elf_fdpic_params *params, struct file *file);
+static int elf_fdpic_map_file(struct elf_fdpic_params *params,
+			      struct file *file,
+			      struct mm_struct *mm,
+			      const char *what);
+
+static int create_elf_fdpic_tables(struct linux_binprm *bprm,
+				   struct mm_struct *mm,
+				   struct elf_fdpic_params *exec_params,
+				   struct elf_fdpic_params *interp_params);
+
+#ifndef CONFIG_MMU
+static int elf_fdpic_transfer_args_to_stack(struct linux_binprm *bprm, unsigned long *_sp);
+static int elf_fdpic_map_file_constdisp_on_uclinux(struct elf_fdpic_params *params,
+						   struct file *file,
+						   struct mm_struct *mm);
+#endif
+
+static int elf_fdpic_map_file_by_direct_mmap(struct elf_fdpic_params *params,
+					     struct file *file,
+					     struct mm_struct *mm);
+
+static struct linux_binfmt elf_fdpic_format = {
+	.module		= THIS_MODULE,
+	.load_binary	= load_elf_fdpic_binary,
+//	.load_shlib	= load_elf_fdpic_library,
+//	.core_dump	= elf_fdpic_core_dump,
+	.min_coredump	= ELF_EXEC_PAGESIZE,
+};
+
+static int __init init_elf_fdpic_binfmt(void)  { return register_binfmt(&elf_fdpic_format); }
+static void __exit exit_elf_fdpic_binfmt(void) { unregister_binfmt(&elf_fdpic_format); }
+
+module_init(init_elf_fdpic_binfmt)
+module_exit(exit_elf_fdpic_binfmt)
+
+static int is_elf_fdpic(struct elfhdr *hdr, struct file *file)
+{
+	if (memcmp(hdr->e_ident, ELFMAG, SELFMAG) != 0)
+		return 0;
+	if (hdr->e_type != ET_EXEC && hdr->e_type != ET_DYN)
+		return 0;
+	if (!elf_check_arch(hdr) || !elf_check_fdpic(hdr))
+		return 0;
+	if (!file->f_op || !file->f_op->mmap)
+		return 0;
+	return 1;
+}
+
+/*****************************************************************************/
+/*
+ * read the program headers table into memory
+ */
+static int elf_fdpic_fetch_phdrs(struct elf_fdpic_params *params, struct file *file)
+{
+	struct elf32_phdr *phdr;
+	unsigned long size;
+	int retval, loop;
+
+	if (params->hdr.e_phentsize != sizeof(struct elf_phdr))
+		return -ENOMEM;
+	if (params->hdr.e_phnum > 65536U / sizeof(struct elf_phdr))
+		return -ENOMEM;
+
+	size = params->hdr.e_phnum * sizeof(struct elf_phdr);
+	params->phdrs = kmalloc(size, GFP_KERNEL);
+	if (!params->phdrs)
+		return -ENOMEM;
+
+	retval = kernel_read(file, params->hdr.e_phoff, (char *) params->phdrs, size);
+	if (retval < 0)
+		return retval;
+
+	/* determine stack size for this binary */
+	phdr = params->phdrs;
+	for (loop = 0; loop < params->hdr.e_phnum; loop++, phdr++) {
+		if (phdr->p_type != PT_GNU_STACK)
+			continue;
+
+		if (phdr->p_flags & PF_X)
+			params->flags |= ELF_FDPIC_FLAG_EXEC_STACK;
+		else
+			params->flags |= ELF_FDPIC_FLAG_NOEXEC_STACK;
+
+		params->stack_size = phdr->p_memsz;
+		break;
+	}
+
+	return 0;
+} /* end elf_fdpic_fetch_phdrs() */
+
+/*****************************************************************************/
+/*
+ * load an fdpic binary into various bits of memory
+ */
+static int load_elf_fdpic_binary(struct linux_binprm *bprm, struct pt_regs *regs)
+{
+	struct elf_fdpic_params exec_params, interp_params;
+	struct elf_phdr *phdr;
+	unsigned long stack_size;
+	struct file *interpreter = NULL; /* to shut gcc up */
+	char *interpreter_name = NULL;
+	int executable_stack;
+	int retval, i;
+
+	memset(&exec_params, 0, sizeof(exec_params));
+	memset(&interp_params, 0, sizeof(interp_params));
+
+	exec_params.hdr = *(struct elfhdr *) bprm->buf;
+	exec_params.flags = ELF_FDPIC_FLAG_PRESENT;
+
+	/* check that this is a binary we know how to deal with */
+	retval = -ENOEXEC;
+	if (!is_elf_fdpic(&exec_params.hdr, bprm->file))
+		goto error;
+
+	/* read the program header table */
+	retval = elf_fdpic_fetch_phdrs(&exec_params, bprm->file);
+	if (retval < 0)
+		goto error;
+
+	/* scan for a program header that specifies an interpreter */
+	phdr = exec_params.phdrs;
+
+	for (i = 0; i < exec_params.hdr.e_phnum; i++, phdr++) {
+		switch (phdr->p_type) {
+		case PT_INTERP:
+			retval = -ENOMEM;
+			if (phdr->p_filesz > PATH_MAX)
+				goto error;
+			retval = -ENOENT;
+			if (phdr->p_filesz < 2)
+				goto error;
+
+			/* read the name of the interpreter into memory */
+			interpreter_name = (char *) kmalloc(phdr->p_filesz, GFP_KERNEL);
+			if (!interpreter_name)
+				goto error;
+
+			retval = kernel_read(bprm->file,
+					     phdr->p_offset,
+					     interpreter_name,
+					     phdr->p_filesz);
+			if (retval < 0)
+				goto error;
+
+			retval = -ENOENT;
+			if (interpreter_name[phdr->p_filesz - 1] != '\0')
+				goto error;
+
+			kdebug("Using ELF interpreter %s", interpreter_name);
+
+			/* replace the program with the interpreter */
+			interpreter = open_exec(interpreter_name);
+			retval = PTR_ERR(interpreter);
+			if (IS_ERR(interpreter)) {
+				interpreter = NULL;
+				goto error;
+			}
+
+			retval = kernel_read(interpreter, 0, bprm->buf, BINPRM_BUF_SIZE);
+			if (retval < 0)
+				goto error;
+
+			interp_params.hdr = *((struct elfhdr *) bprm->buf);
+			break;
+
+		case PT_LOAD:
+#ifdef CONFIG_MMU
+			if (exec_params.load_addr == 0)
+				exec_params.load_addr = phdr->p_vaddr;
+#endif
+			break;
+		}
+
+	}
+
+	if (elf_check_const_displacement(&exec_params.hdr))
+		exec_params.flags |= ELF_FDPIC_FLAG_CONSTDISP;
+
+	/* perform insanity checks on the interpreter */
+	if (interpreter_name) {
+		retval = -ELIBBAD;
+		if (!is_elf_fdpic(&interp_params.hdr, interpreter))
+			goto error;
+
+		interp_params.flags = ELF_FDPIC_FLAG_PRESENT;
+
+		/* read the interpreter's program header table */
+		retval = elf_fdpic_fetch_phdrs(&interp_params, interpreter);
+		if (retval < 0)
+			goto error;
+	}
+
+	stack_size = exec_params.stack_size;
+	if (stack_size < interp_params.stack_size)
+		stack_size = interp_params.stack_size;
+
+	if (exec_params.flags & ELF_FDPIC_FLAG_EXEC_STACK)
+		executable_stack = EXSTACK_ENABLE_X;
+	else if (exec_params.flags & ELF_FDPIC_FLAG_NOEXEC_STACK)
+		executable_stack = EXSTACK_DISABLE_X;
+	else if (interp_params.flags & ELF_FDPIC_FLAG_EXEC_STACK)
+		executable_stack = EXSTACK_ENABLE_X;
+	else if (interp_params.flags & ELF_FDPIC_FLAG_NOEXEC_STACK)
+		executable_stack = EXSTACK_DISABLE_X;
+	else
+		executable_stack = EXSTACK_DEFAULT;
+
+	retval = -ENOEXEC;
+	if (stack_size == 0)
+		goto error;
+
+	if (elf_check_const_displacement(&interp_params.hdr))
+		interp_params.flags |= ELF_FDPIC_FLAG_CONSTDISP;
+
+	/* flush all traces of the currently running executable */
+	retval = flush_old_exec(bprm);
+	if (retval)
+		goto error;
+
+	/* there's now no turning back... the old userspace image is dead,
+	 * defunct, deceased, etc. after this point we have to exit via
+	 * error_kill */
+	set_personality(PER_LINUX_FDPIC);
+	set_binfmt(&elf_fdpic_format);
+
+	current->mm->start_code = 0;
+	current->mm->end_code = 0;
+	current->mm->start_stack = 0;
+	current->mm->start_data = 0;
+	current->mm->end_data = 0;
+	current->mm->context.exec_fdpic_loadmap = 0;
+	current->mm->context.interp_fdpic_loadmap = 0;
+
+	current->flags &= ~PF_FORKNOEXEC;
+
+#ifdef CONFIG_MMU
+	elf_fdpic_arch_lay_out_mm(&exec_params,
+				  &interp_params,
+				  &current->mm->start_stack,
+				  &current->mm->start_brk);
+#endif
+
+	/* do this so that we can load the interpreter, if need be
+	 * - we will change some of these later
+	 */
+	current->mm->rss = 0;
+
+#ifdef CONFIG_MMU
+	retval = setup_arg_pages(bprm, current->mm->start_stack, executable_stack);
+	if (retval < 0) {
+		send_sig(SIGKILL, current, 0);
+		goto error_kill;
+	}
+#endif
+
+	/* load the executable and interpreter into memory */
+	retval = elf_fdpic_map_file(&exec_params, bprm->file, current->mm, "executable");
+	if (retval < 0)
+		goto error_kill;
+
+	if (interpreter_name) {
+		retval = elf_fdpic_map_file(&interp_params, interpreter, NULL, "interpreter");
+		if (retval < 0) {
+			printk(KERN_ERR "Unable to load interpreter\n");
+			goto error_kill;
+		}
+
+		allow_write_access(interpreter);
+		fput(interpreter);
+		interpreter = NULL;
+	}
+
+#ifdef CONFIG_MMU
+	if (!current->mm->start_brk)
+		current->mm->start_brk = current->mm->end_data;
+
+	current->mm->brk = current->mm->start_brk = PAGE_ALIGN(current->mm->start_brk);
+
+#else
+	/* create a stack and brk area big enough for everyone
+	 * - the brk heap starts at the bottom and works up
+	 * - the stack starts at the top and works down
+	 */
+	stack_size = (stack_size + PAGE_SIZE - 1) & PAGE_MASK;
+	if (stack_size < PAGE_SIZE * 2)
+		stack_size = PAGE_SIZE * 2;
+
+	current->mm->start_brk = do_mmap(NULL,
+					 0,
+					 stack_size,
+					 PROT_READ | PROT_WRITE | PROT_EXEC,
+					 MAP_PRIVATE | MAP_ANON | MAP_GROWSDOWN,
+					 0);
+
+	if (IS_ERR((void *) current->mm->start_brk)) {
+		retval = current->mm->start_brk;
+		current->mm->start_brk = 0;
+		goto error_kill;
+	}
+
+	down_write(&current->mm->mmap_sem);
+	if (do_mremap(current->mm->start_brk,
+		      stack_size,
+		      ksize((char *) current->mm->start_brk),
+		      0, 0
+		      ) == current->mm->start_brk
+	    )
+		stack_size = ksize((char *) current->mm->start_brk);
+	up_write(&current->mm->mmap_sem);
+
+	current->mm->brk = current->mm->start_brk;
+	current->mm->context.end_brk = current->mm->start_brk;
+	current->mm->context.end_brk += (stack_size > PAGE_SIZE) ? (stack_size - PAGE_SIZE) : 0;
+	current->mm->start_stack = current->mm->start_brk + stack_size;
+#endif
+
+	compute_creds(bprm);
+	current->flags &= ~PF_FORKNOEXEC;
+	if (create_elf_fdpic_tables(bprm, current->mm, &exec_params, &interp_params) < 0)
+		goto error_kill;
+
+	kdebug("- start_code  %lx",	(long) current->mm->start_code);
+	kdebug("- end_code    %lx",	(long) current->mm->end_code);
+	kdebug("- start_data  %lx",	(long) current->mm->start_data);
+	kdebug("- end_data    %lx",	(long) current->mm->end_data);
+	kdebug("- start_brk   %lx",	(long) current->mm->start_brk);
+	kdebug("- brk         %lx",	(long) current->mm->brk);
+#ifndef CONFIG_MMU
+	kdebug("- end_brk     %lx",	(long) current->mm->end_brk);
+#endif
+	kdebug("- start_stack %lx",	(long) current->mm->start_stack);
+
+#ifdef ELF_FDPIC_PLAT_INIT
+	/*
+	 * The ABI may specify that certain registers be set up in special
+	 * ways (on i386 %edx is the address of a DT_FINI function, for
+	 * example.  This macro performs whatever initialization to
+	 * the regs structure is required.
+	 */
+	ELF_FDPIC_PLAT_INIT(regs,
+			    exec_params.map_addr,
+			    interp_params.map_addr,
+			    interp_params.dynamic_addr ?: exec_params.dynamic_addr
+			    );
+#endif
+
+	/* everything is now ready... get the userspace context ready to roll */
+	start_thread(regs,
+		     interp_params.entry_addr ?: exec_params.entry_addr,
+		     current->mm->start_stack);
+
+	if (unlikely(current->ptrace & PT_PTRACED)) {
+		if (current->ptrace & PT_TRACE_EXEC)
+			ptrace_notify ((PTRACE_EVENT_EXEC << 8) | SIGTRAP);
+		else
+			send_sig(SIGTRAP, current, 0);
+	}
+
+	retval = 0;
+
+error:
+	if (interpreter) {
+		allow_write_access(interpreter);
+		fput(interpreter);
+	}
+	if (interpreter_name)
+		kfree(interpreter_name);
+	if (exec_params.phdrs)
+		kfree(exec_params.phdrs);
+	if (exec_params.loadmap)
+		kfree(exec_params.loadmap);
+	if (interp_params.phdrs)
+		kfree(interp_params.phdrs);
+	if (interp_params.loadmap)
+		kfree(interp_params.loadmap);
+	return retval;
+
+	/* unrecoverable error - kill the process */
+ error_kill:
+	send_sig(SIGSEGV, current, 0);
+	goto error;
+
+} /* end load_elf_fdpic_binary() */
+
+/*****************************************************************************/
+/*
+ * present useful information to the program
+ */
+static int create_elf_fdpic_tables(struct linux_binprm *bprm,
+				   struct mm_struct *mm,
+				   struct elf_fdpic_params *exec_params,
+				   struct elf_fdpic_params *interp_params)
+{
+	unsigned long sp, csp, nitems;
+	elf_caddr_t *argv, *envp;
+	size_t platform_len = 0, len;
+	char *k_platform, *u_platform, *p;
+	long hwcap;
+	int loop;
+
+	/* we're going to shovel a whole load of stuff onto the stack */
+#ifdef CONFIG_MMU
+	sp = bprm->p;
+#else
+	sp = mm->start_stack;
+
+	/* stack the program arguments and environment */
+	if (elf_fdpic_transfer_args_to_stack(bprm, &sp) < 0)
+		return -EFAULT;
+#endif
+
+	/* get hold of platform and hardware capabilities masks for the machine
+	 * we are running on.  In some cases (Sparc), this info is impossible
+	 * to get, in others (i386) it is merely difficult.
+	 */
+	hwcap = ELF_HWCAP;
+	k_platform = ELF_PLATFORM;
+
+	if (k_platform) {
+		platform_len = strlen(k_platform) + 1;
+		sp -= platform_len;
+		if (__copy_to_user(u_platform, k_platform, platform_len) != 0)
+			return -EFAULT;
+	}
+
+	u_platform = (char *) sp;
+
+#if defined(__i386__) && defined(CONFIG_SMP)
+	/* in some cases (e.g. Hyper-Threading), we want to avoid L1 evictions
+	 * by the processes running on the same package. One thing we can do
+	 * is to shuffle the initial stack for them.
+	 *
+	 * the conditionals here are unneeded, but kept in to make the
+	 * code behaviour the same as pre change unless we have hyperthreaded
+	 * processors. This keeps Mr Marcelo Person happier but should be
+	 * removed for 2.5
+	 */
+	if (smp_num_siblings > 1)
+		sp = sp - ((current->pid % 64) << 7);
+#endif
+
+	sp &= ~7UL;
+
+	/* stack the load map(s) */
+	len = sizeof(struct elf32_fdpic_loadmap);
+	len += sizeof(struct elf32_fdpic_loadseg) * exec_params->loadmap->nsegs;
+	sp = (sp - len) & ~7UL;
+	exec_params->map_addr = sp;
+
+	if (copy_to_user((void *) sp, exec_params->loadmap, len) != 0)
+		return -EFAULT;
+
+	current->mm->context.exec_fdpic_loadmap = (unsigned long) sp;
+
+	if (interp_params->loadmap) {
+		len = sizeof(struct elf32_fdpic_loadmap);
+		len += sizeof(struct elf32_fdpic_loadseg) * interp_params->loadmap->nsegs;
+		sp = (sp - len) & ~7UL;
+		interp_params->map_addr = sp;
+
+		if (copy_to_user((void *) sp, interp_params->loadmap, len) != 0)
+			return -EFAULT;
+
+		current->mm->context.interp_fdpic_loadmap = (unsigned long) sp;
+	}
+
+	/* force 16 byte _final_ alignment here for generality */
+#define DLINFO_ITEMS 13
+
+	nitems = 1 + DLINFO_ITEMS + (k_platform ? 1 : 0);
+#ifdef DLINFO_ARCH_ITEMS
+	nitems += DLINFO_ARCH_ITEMS;
+#endif
+
+	csp = sp;
+	sp -= nitems * 2 * sizeof(unsigned long);
+	sp -= (bprm->envc + 1) * sizeof(char *);	/* envv[] */
+	sp -= (bprm->argc + 1) * sizeof(char *);	/* argv[] */
+	sp -= 1 * sizeof(unsigned long);		/* argc */
+
+	csp -= sp & 15UL;
+	sp -= sp & 15UL;
+
+	/* put the ELF interpreter info on the stack */
+#define NEW_AUX_ENT(nr, id, val)						\
+	do {									\
+		struct { unsigned long _id, _val; } *ent = (void *) csp;	\
+		__put_user((id), &ent[nr]._id);					\
+		__put_user((val), &ent[nr]._val);				\
+	} while (0)
+
+	csp -= 2 * sizeof(unsigned long);
+	NEW_AUX_ENT(0, AT_NULL, 0);
+	if (k_platform) {
+		csp -= 2 * sizeof(unsigned long);
+		NEW_AUX_ENT(0, AT_PLATFORM, (elf_addr_t)(unsigned long) u_platform);
+	}
+
+	csp -= DLINFO_ITEMS * 2 * sizeof(unsigned long);
+	NEW_AUX_ENT( 0, AT_HWCAP,		hwcap);
+	NEW_AUX_ENT( 1, AT_PAGESZ,		PAGE_SIZE);
+	NEW_AUX_ENT( 2, AT_CLKTCK,		CLOCKS_PER_SEC);
+	NEW_AUX_ENT( 3, AT_PHDR,		exec_params->ph_addr);
+	NEW_AUX_ENT( 4, AT_PHENT,		sizeof(struct elf_phdr));
+	NEW_AUX_ENT( 5, AT_PHNUM,		exec_params->hdr.e_phnum);
+	NEW_AUX_ENT( 6,	AT_BASE,		interp_params->elfhdr_addr);
+	NEW_AUX_ENT( 7, AT_FLAGS,		0);
+	NEW_AUX_ENT( 8, AT_ENTRY,		exec_params->entry_addr);
+	NEW_AUX_ENT( 9, AT_UID,			(elf_addr_t) current->uid);
+	NEW_AUX_ENT(10, AT_EUID,		(elf_addr_t) current->euid);
+	NEW_AUX_ENT(11, AT_GID,			(elf_addr_t) current->gid);
+	NEW_AUX_ENT(12, AT_EGID,		(elf_addr_t) current->egid);
+
+#ifdef ARCH_DLINFO
+	/* ARCH_DLINFO must come last so platform specific code can enforce
+	 * special alignment requirements on the AUXV if necessary (eg. PPC).
+	 */
+	ARCH_DLINFO;
+#endif
+#undef NEW_AUX_ENT
+
+	/* allocate room for argv[] and envv[] */
+	csp -= (bprm->envc + 1) * sizeof(elf_caddr_t);
+	envp = (elf_caddr_t *) csp;
+	csp -= (bprm->argc + 1) * sizeof(elf_caddr_t);
+	argv = (elf_caddr_t *) csp;
+
+	/* stack argc */
+	csp -= sizeof(unsigned long);
+	__put_user(bprm->argc, (unsigned long *) csp);
+
+	if (csp != sp)
+		BUG();
+
+	/* fill in the argv[] array */
+#ifdef CONFIG_MMU
+	current->mm->arg_start = bprm->p;
+#else
+	current->mm->arg_start = current->mm->start_stack - (MAX_ARG_PAGES * PAGE_SIZE - bprm->p);
+#endif
+
+	p = (char *) current->mm->arg_start;
+	for (loop = bprm->argc; loop > 0; loop--) {
+		__put_user((elf_caddr_t) p, argv++);
+		len = strnlen_user(p, PAGE_SIZE * MAX_ARG_PAGES);
+		if (!len || len > PAGE_SIZE * MAX_ARG_PAGES)
+			return -EINVAL;
+		p += len;
+	}
+	__put_user(NULL, argv);
+	current->mm->arg_end = (unsigned long) p;
+
+	/* fill in the envv[] array */
+	current->mm->env_start = (unsigned long) p;
+	for (loop = bprm->envc; loop > 0; loop--) {
+		__put_user((elf_caddr_t)(unsigned long) p, envp++);
+		len = strnlen_user(p, PAGE_SIZE * MAX_ARG_PAGES);
+		if (!len || len > PAGE_SIZE * MAX_ARG_PAGES)
+			return -EINVAL;
+		p += len;
+	}
+	__put_user(NULL, envp);
+	current->mm->env_end = (unsigned long) p;
+
+	mm->start_stack = (unsigned long) sp;
+	return 0;
+} /* end create_elf_fdpic_tables() */
+
+/*****************************************************************************/
+/*
+ * transfer the program arguments and environment from the holding pages onto
+ * the stack
+ */
+#ifndef CONFIG_MMU
+static int elf_fdpic_transfer_args_to_stack(struct linux_binprm *bprm, unsigned long *_sp)
+{
+	unsigned long index, stop, sp;
+	char *src;
+	int ret = 0;
+
+	stop = bprm->p >> PAGE_SHIFT;
+	sp = *_sp;
+
+	for (index = MAX_ARG_PAGES - 1; index >= stop; index--) {
+		src = kmap(bprm->page[index]);
+		sp -= PAGE_SIZE;
+		if (copy_to_user((void *) sp, src, PAGE_SIZE) != 0)
+			ret = -EFAULT;
+		kunmap(bprm->page[index]);
+		if (ret < 0)
+			goto out;
+	}
+
+	*_sp = (*_sp - (MAX_ARG_PAGES * PAGE_SIZE - bprm->p)) & ~15;
+
+ out:
+	return ret;
+} /* end elf_fdpic_transfer_args_to_stack() */
+#endif
+
+/*****************************************************************************/
+/*
+ * load the appropriate binary image (executable or interpreter) into memory
+ * - we assume no MMU is available
+ * - if no other PIC bits are set in params->hdr->e_flags
+ *   - we assume that the LOADable segments in the binary are independently relocatable
+ *   - we assume R/O executable segments are shareable
+ * - else
+ *   - we assume the loadable parts of the image to require fixed displacement
+ *   - the image is not shareable
+ */
+static int elf_fdpic_map_file(struct elf_fdpic_params *params,
+			      struct file *file,
+			      struct mm_struct *mm,
+			      const char *what)
+{
+	struct elf32_fdpic_loadmap *loadmap;
+#ifdef CONFIG_MMU
+	struct elf32_fdpic_loadseg *mseg;
+#endif
+	struct elf32_fdpic_loadseg *seg;
+	struct elf32_phdr *phdr;
+	unsigned long load_addr, stop;
+	unsigned nloads, tmp;
+	size_t size;
+	int loop, ret;
+
+	/* allocate a load map table */
+	nloads = 0;
+	for (loop = 0; loop < params->hdr.e_phnum; loop++)
+		if (params->phdrs[loop].p_type == PT_LOAD)
+			nloads++;
+
+	if (nloads == 0)
+		return -ELIBBAD;
+
+	size = sizeof(*loadmap) + nloads * sizeof(*seg);
+	loadmap = kmalloc(size, GFP_KERNEL);
+	if (!loadmap)
+		return -ENOMEM;
+
+	params->loadmap = loadmap;
+	memset(loadmap, 0, size);
+
+	loadmap->version = ELF32_FDPIC_LOADMAP_VERSION;
+	loadmap->nsegs = nloads;
+
+	load_addr = params->load_addr;
+	seg = loadmap->segs;
+
+	/* map the requested LOADs into the memory space */
+	switch (params->flags & ELF_FDPIC_FLAG_ARRANGEMENT) {
+	case ELF_FDPIC_FLAG_CONSTDISP:
+	case ELF_FDPIC_FLAG_CONTIGUOUS:
+#ifndef CONFIG_MMU
+		ret = elf_fdpic_map_file_constdisp_on_uclinux(params, file, mm);
+		if (ret < 0)
+			return ret;
+		break;
+#endif
+	default:
+		ret = elf_fdpic_map_file_by_direct_mmap(params, file, mm);
+		if (ret < 0)
+			return ret;
+		break;
+	}
+
+	/* map the entry point */
+	if (params->hdr.e_entry) {
+		seg = loadmap->segs;
+		for (loop = loadmap->nsegs; loop > 0; loop--, seg++) {
+			if (params->hdr.e_entry >= seg->p_vaddr &&
+			    params->hdr.e_entry < seg->p_vaddr + seg->p_memsz
+			    ) {
+				params->entry_addr =
+					(params->hdr.e_entry - seg->p_vaddr) + seg->addr;
+				break;
+			}
+		}
+	}
+
+	/* determine where the program header table has wound up if mapped */
+	stop = params->hdr.e_phoff + params->hdr.e_phnum * sizeof (struct elf_phdr);
+	phdr = params->phdrs;
+
+	for (loop = 0; loop < params->hdr.e_phnum; loop++, phdr++) {
+		if (phdr->p_type != PT_LOAD)
+			continue;
+
+		if (phdr->p_offset > params->hdr.e_phoff ||
+		    phdr->p_offset + phdr->p_filesz < stop)
+			continue;
+
+		seg = loadmap->segs;
+		for (loop = loadmap->nsegs; loop > 0; loop--, seg++) {
+			if (phdr->p_vaddr >= seg->p_vaddr &&
+			    phdr->p_vaddr + phdr->p_filesz <= seg->p_vaddr + seg->p_memsz
+			    ) {
+				params->ph_addr = (phdr->p_vaddr - seg->p_vaddr) + seg->addr +
+					params->hdr.e_phoff - phdr->p_offset;
+				break;
+			}
+		}
+		break;
+	}
+
+	/* determine where the dynamic section has wound up if there is one */
+	phdr = params->phdrs;
+	for (loop = 0; loop < params->hdr.e_phnum; loop++, phdr++) {
+		if (phdr->p_type != PT_DYNAMIC)
+			continue;
+
+		seg = loadmap->segs;
+		for (loop = loadmap->nsegs; loop > 0; loop--, seg++) {
+			if (phdr->p_vaddr >= seg->p_vaddr &&
+			    phdr->p_vaddr + phdr->p_memsz <= seg->p_vaddr + seg->p_memsz
+			    ) {
+				params->dynamic_addr = (phdr->p_vaddr - seg->p_vaddr) + seg->addr;
+
+				/* check the dynamic section contains at least one item, and that
+				 * the last item is a NULL entry */
+				if (phdr->p_memsz == 0 ||
+				    phdr->p_memsz % sizeof(Elf32_Dyn) != 0)
+					goto dynamic_error;
+
+				tmp = phdr->p_memsz / sizeof(Elf32_Dyn);
+				if (((Elf32_Dyn *) params->dynamic_addr)[tmp - 1].d_tag != 0)
+					goto dynamic_error;
+				break;
+			}
+		}
+		break;
+	}
+
+	/* now elide adjacent segments in the load map on MMU linux
+	 * - on uClinux the holes between may actually be filled with system stuff or stuff from
+	 *   other processes
+	 */
+#ifdef CONFIG_MMU
+	nloads = loadmap->nsegs;
+	mseg = loadmap->segs;
+	seg = mseg + 1;
+	for (loop = 1; loop < nloads; loop++) {
+		/* see if we have a candidate for merging */
+		if (seg->p_vaddr - mseg->p_vaddr == seg->addr - mseg->addr) {
+			load_addr = PAGE_ALIGN(mseg->addr + mseg->p_memsz);
+			if (load_addr == (seg->addr & PAGE_MASK)) {
+				mseg->p_memsz += load_addr - (mseg->addr + mseg->p_memsz);
+				mseg->p_memsz += seg->addr & ~PAGE_MASK;
+				mseg->p_memsz += seg->p_memsz;
+				loadmap->nsegs--;
+				continue;
+			}
+		}
+
+		mseg++;
+		if (mseg != seg)
+			*mseg = *seg;
+	}
+#endif
+
+	kdebug("Mapped Object [%s]:", what);
+	kdebug("- elfhdr   : %lx", params->elfhdr_addr);
+	kdebug("- entry    : %lx", params->entry_addr);
+	kdebug("- PHDR[]   : %lx", params->ph_addr);
+	kdebug("- DYNAMIC[]: %lx", params->dynamic_addr);
+	seg = loadmap->segs;
+	for (loop = 0; loop < loadmap->nsegs; loop++, seg++)
+		kdebug("- LOAD[%d] : %08x-%08x [va=%x ms=%x]",
+		       loop,
+		       seg->addr, seg->addr + seg->p_memsz - 1,
+		       seg->p_vaddr, seg->p_memsz);
+
+	return 0;
+
+ dynamic_error:
+	printk("ELF FDPIC %s with invalid DYNAMIC section (inode=%lu)\n",
+	       what, file->f_dentry->d_inode->i_ino);
+	return -ELIBBAD;
+} /* end elf_fdpic_map_file() */
+
+/*****************************************************************************/
+/*
+ * map a file with constant displacement under uClinux
+ */
+#ifndef CONFIG_MMU
+static int elf_fdpic_map_file_constdisp_on_uclinux(struct elf_fdpic_params *params,
+						   struct file *file,
+						   struct mm_struct *mm)
+{
+	struct elf32_fdpic_loadseg *seg;
+	struct elf32_phdr *phdr;
+	unsigned long load_addr, base = ULONG_MAX, top = 0, maddr = 0;
+	loff_t fpos;
+	int loop, ret;
+
+	load_addr = params->load_addr;
+	seg = params->loadmap->segs;
+
+	/* determine the bounds of the contiguous overall allocation we must make */
+	phdr = params->phdrs;
+	for (loop = 0; loop < params->hdr.e_phnum; loop++, phdr++) {
+		if (params->phdrs[loop].p_type != PT_LOAD)
+			continue;
+
+		if (base > phdr->p_vaddr)
+			base = phdr->p_vaddr;
+		if (top < phdr->p_vaddr + phdr->p_memsz)
+			top = phdr->p_vaddr + phdr->p_memsz;
+	}
+
+	/* allocate one big anon block for everything */
+	maddr = do_mmap(NULL, load_addr, top - base,
+			PROT_READ | PROT_WRITE | PROT_EXEC,
+			MAP_PRIVATE | MAP_EXECUTABLE, 0);
+	if (IS_ERR((void *) maddr))
+		return (int) maddr;
+
+	if (load_addr != 0)
+		load_addr += PAGE_ALIGN(top - base);
+
+	/* and then load the file segments into it */
+	phdr = params->phdrs;
+	for (loop = 0; loop < params->hdr.e_phnum; loop++, phdr++) {
+		if (params->phdrs[loop].p_type != PT_LOAD)
+			continue;
+
+		fpos = phdr->p_offset;
+
+		seg->addr = maddr + (phdr->p_vaddr - base);
+		seg->p_vaddr = phdr->p_vaddr;
+		seg->p_memsz = phdr->p_memsz;
+
+		ret = file->f_op->read(file, (void *) seg->addr, phdr->p_filesz, &fpos);
+		if (ret < 0)
+			return ret;
+
+		/* map the ELF header address if in this segment */
+		if (phdr->p_offset == 0)
+			params->elfhdr_addr = seg->addr;
+
+		/* clear any space allocated but not loaded */
+		if (phdr->p_filesz < phdr->p_memsz)
+			clear_user((void *) (seg->addr + phdr->p_filesz),
+				   phdr->p_memsz - phdr->p_filesz);
+
+		if (mm) {
+			if (phdr->p_flags & PF_X) {
+				mm->start_code = seg->addr;
+				mm->end_code = seg->addr + phdr->p_memsz;
+			}
+			else if (!mm->start_data) {
+				mm->start_data = seg->addr;
+#ifndef CONFIG_MMU
+				mm->end_data = seg->addr + phdr->p_memsz;
+#endif
+			}
+
+#ifdef CONFIG_MMU
+			if (seg->addr + phdr->p_memsz > mm->end_data)
+				mm->end_data = seg->addr + phdr->p_memsz;
+#endif
+		}
+
+		seg++;
+	}
+
+	return 0;
+} /* end elf_fdpic_map_file_constdisp_on_uclinux() */
+#endif
+
+/*****************************************************************************/
+/*
+ * map a binary by direct mmap() of the individual PT_LOAD segments
+ */
+static int elf_fdpic_map_file_by_direct_mmap(struct elf_fdpic_params *params,
+					     struct file *file,
+					     struct mm_struct *mm)
+{
+	struct elf32_fdpic_loadseg *seg;
+	struct elf32_phdr *phdr;
+	unsigned long load_addr, delta_vaddr;
+	int loop, dvset;
+
+	load_addr = params->load_addr;
+	delta_vaddr = 0;
+	dvset = 0;
+
+	seg = params->loadmap->segs;
+
+	/* deal with each load segment separately */
+	phdr = params->phdrs;
+	for (loop = 0; loop < params->hdr.e_phnum; loop++, phdr++) {
+		unsigned long maddr, disp, excess, excess1;
+		int prot = 0, flags;
+
+		if (phdr->p_type != PT_LOAD)
+			continue;
+
+		kdebug("[LOAD] va=%lx of=%lx fs=%lx ms=%lx",
+		       phdr->p_vaddr, phdr->p_offset, phdr->p_filesz, phdr->p_memsz);
+
+		/* determine the mapping parameters */
+		if (phdr->p_flags & PF_R) prot |= PROT_READ;
+		if (phdr->p_flags & PF_W) prot |= PROT_WRITE;
+		if (phdr->p_flags & PF_X) prot |= PROT_EXEC;
+
+		flags = MAP_PRIVATE | MAP_DENYWRITE | MAP_EXECUTABLE;
+		maddr = 0;
+
+		switch (params->flags & ELF_FDPIC_FLAG_ARRANGEMENT) {
+		case ELF_FDPIC_FLAG_INDEPENDENT:
+			/* PT_LOADs are independently locatable */
+			break;
+
+		case ELF_FDPIC_FLAG_HONOURVADDR:
+			/* the specified virtual address must be honoured */
+			maddr = phdr->p_vaddr;
+			flags |= MAP_FIXED;
+			break;
+
+		case ELF_FDPIC_FLAG_CONSTDISP:
+			/* constant displacement
+			 * - can be mapped anywhere, but must be mapped as a unit
+			 */
+			if (!dvset) {
+				maddr = load_addr;
+				delta_vaddr = phdr->p_vaddr;
+				dvset = 1;
+			}
+			else {
+				maddr = load_addr + phdr->p_vaddr - delta_vaddr;
+				flags |= MAP_FIXED;
+			}
+			break;
+
+		case ELF_FDPIC_FLAG_CONTIGUOUS:
+			/* contiguity handled later */
+			break;
+
+		default:
+			BUG();
+		}
+
+		maddr &= PAGE_MASK;
+
+		/* create the mapping */
+		disp = phdr->p_vaddr & ~PAGE_MASK;
+		maddr = do_mmap(file, maddr, phdr->p_memsz + disp, prot, flags,
+				phdr->p_offset - disp);
+
+		kdebug("mmap[%d] <file> sz=%lx pr=%x fl=%x of=%lx --> %08lx",
+		       loop, phdr->p_memsz + disp, prot, flags, phdr->p_offset - disp,
+		       maddr);
+
+		if (IS_ERR((void *) maddr))
+			return (int) maddr;
+
+		if ((params->flags & ELF_FDPIC_FLAG_ARRANGEMENT) == ELF_FDPIC_FLAG_CONTIGUOUS)
+			load_addr += PAGE_ALIGN(phdr->p_memsz + disp);
+
+		seg->addr = maddr + disp;
+		seg->p_vaddr = phdr->p_vaddr;
+		seg->p_memsz = phdr->p_memsz;
+
+		/* map the ELF header address if in this segment */
+		if (phdr->p_offset == 0)
+			params->elfhdr_addr = seg->addr;
+
+		/* clear the bit between beginning of mapping and beginning of PT_LOAD */
+		if (prot & PROT_WRITE && disp > 0) {
+			kdebug("clear[%d] ad=%lx sz=%lx", loop, maddr, disp);
+			clear_user((void *) maddr, disp);
+			maddr += disp;
+		}
+
+		/* clear any space allocated but not loaded
+		 * - on uClinux we can just clear the lot
+		 * - on MMU linux we'll get a SIGBUS beyond the last page
+		 *   extant in the file
+		 */
+		excess = phdr->p_memsz - phdr->p_filesz;
+		excess1 = PAGE_SIZE - ((maddr + phdr->p_filesz) & ~PAGE_MASK);
+
+#ifdef CONFIG_MMU
+
+		if (excess > excess1) {
+			unsigned long xaddr = maddr + phdr->p_filesz + excess1;
+			unsigned long xmaddr;
+
+			flags |= MAP_FIXED | MAP_ANONYMOUS;
+			xmaddr = do_mmap(NULL, xaddr, excess - excess1, prot, flags, 0);
+
+			kdebug("mmap[%d] <anon>"
+			       " ad=%lx sz=%lx pr=%x fl=%x of=0 --> %08lx",
+			       loop, xaddr, excess - excess1, prot, flags, xmaddr);
+
+			if (xmaddr != xaddr)
+				return -ENOMEM;
+		}
+
+		if (prot & PROT_WRITE && excess1 > 0) {
+			kdebug("clear[%d] ad=%lx sz=%lx",
+			       loop, maddr + phdr->p_filesz, excess1);
+			clear_user((void *) maddr + phdr->p_filesz, excess1);
+		}
+
+#else
+		if (excess > 0) {
+			kdebug("clear[%d] ad=%lx sz=%lx",
+			       loop, maddr + phdr->p_filesz, excess);
+			clear_user((void *) maddr + phdr->p_filesz, excess);
+		}
+#endif
+
+		if (mm) {
+			if (phdr->p_flags & PF_X) {
+				mm->start_code = maddr;
+				mm->end_code = maddr + phdr->p_memsz;
+			}
+			else if (!mm->start_data) {
+				mm->start_data = maddr;
+				mm->end_data = maddr + phdr->p_memsz;
+			}
+		}
+
+		seg++;
+	}
+
+	return 0;
+} /* end elf_fdpic_map_file_by_direct_mmap() */
diff -uNr /warthog/kernels/linux-2.6.10-rc1-bk10/fs/binfmt_som.c linux-2.6.10-rc1-bk10-frv/fs/binfmt_som.c
--- /warthog/kernels/linux-2.6.10-rc1-bk10/fs/binfmt_som.c	2004-06-18 13:43:59.000000000 +0100
+++ linux-2.6.10-rc1-bk10-frv/fs/binfmt_som.c	2004-11-01 11:47:04.000000000 +0000
@@ -254,7 +254,7 @@
 
 	set_binfmt(&som_format);
 	compute_creds(bprm);
-	setup_arg_pages(bprm, EXSTACK_DEFAULT);
+	setup_arg_pages(bprm, STACK_TOP, EXSTACK_DEFAULT);
 
 	create_som_tables(bprm);
 
diff -uNr /warthog/kernels/linux-2.6.10-rc1-bk10/fs/exec.c linux-2.6.10-rc1-bk10-frv/fs/exec.c
--- /warthog/kernels/linux-2.6.10-rc1-bk10/fs/exec.c	2004-11-01 11:45:28.000000000 +0000
+++ linux-2.6.10-rc1-bk10-frv/fs/exec.c	2004-11-01 11:47:04.856658128 +0000
@@ -337,7 +337,9 @@
 	force_sig(SIGKILL, current);
 }
 
-int setup_arg_pages(struct linux_binprm *bprm, int executable_stack)
+int setup_arg_pages(struct linux_binprm *bprm,
+		    unsigned long stack_top,
+		    int executable_stack)
 {
 	unsigned long stack_base;
 	struct vm_area_struct *mpnt;
@@ -381,7 +383,7 @@
 	stack_base = current->signal->rlim[RLIMIT_STACK].rlim_max;
 	if (stack_base > (1 << 30))
 		stack_base = 1 << 30;
-	stack_base = PAGE_ALIGN(STACK_TOP - stack_base);
+	stack_base = PAGE_ALIGN(stack_top - stack_base);
 
 	mm->arg_start = stack_base;
 	arg_size = i << PAGE_SHIFT;
@@ -390,9 +392,9 @@
 	while (i < MAX_ARG_PAGES)
 		bprm->page[i++] = NULL;
 #else
-	stack_base = STACK_TOP - MAX_ARG_PAGES * PAGE_SIZE;
+	stack_base = stack_top - MAX_ARG_PAGES * PAGE_SIZE;
 	mm->arg_start = bprm->p + stack_base;
-	arg_size = STACK_TOP - (PAGE_MASK & (unsigned long) mm->arg_start);
+	arg_size = stack_top - (PAGE_MASK & (unsigned long) mm->arg_start);
 #endif
 
 	bprm->p += stack_base;
@@ -420,7 +422,7 @@
 			(PAGE_SIZE - 1 + (unsigned long) bprm->p);
 #else
 		mpnt->vm_start = PAGE_MASK & (unsigned long) bprm->p;
-		mpnt->vm_end = STACK_TOP;
+		mpnt->vm_end = stack_top;
 #endif
 		/* Adjust stack execute permissions; explicitly enable
 		 * for EXSTACK_ENABLE_X, disable for EXSTACK_DISABLE_X
diff -uNr /warthog/kernels/linux-2.6.10-rc1-bk10/fs/Kconfig.binfmt linux-2.6.10-rc1-bk10-frv/fs/Kconfig.binfmt
--- /warthog/kernels/linux-2.6.10-rc1-bk10/fs/Kconfig.binfmt	2004-06-18 13:41:29.000000000 +0100
+++ linux-2.6.10-rc1-bk10-frv/fs/Kconfig.binfmt	2004-11-01 11:47:04.860657795 +0000
@@ -23,6 +23,18 @@
 	  ld.so (check the file <file:Documentation/Changes> for location and
 	  latest version).
 
+config BINFMT_ELF_FDPIC
+	bool "Kernel support for FDPIC ELF binaries"
+	default y
+	help
+	  ELF FDPIC binaries are based on ELF, but allow the individual load
+	  segments of a binary to be located in memory independently of each
+	  other. This makes this format ideal for use in environments where no
+	  MMU is available as it still permits text segments to be shared,
+	  even if data segments are not.
+
+	  It is also possible to run FDPIC ELF binaries on MMU linux also.
+
 config BINFMT_FLAT
 	tristate "Kernel support for flat binaries"
 	depends on !MMU || SUPERH
diff -uNr /warthog/kernels/linux-2.6.10-rc1-bk10/fs/Makefile linux-2.6.10-rc1-bk10-frv/fs/Makefile
--- /warthog/kernels/linux-2.6.10-rc1-bk10/fs/Makefile	2004-11-01 11:45:28.000000000 +0000
+++ linux-2.6.10-rc1-bk10-frv/fs/Makefile	2004-11-01 11:47:04.863657546 +0000
@@ -25,6 +25,7 @@
 obj-y				+= binfmt_script.o
 
 obj-$(CONFIG_BINFMT_ELF)	+= binfmt_elf.o
+obj-$(CONFIG_BINFMT_ELF_FDPIC)	+= binfmt_elf_fdpic.o
 obj-$(CONFIG_BINFMT_SOM)	+= binfmt_som.o
 obj-$(CONFIG_BINFMT_FLAT)	+= binfmt_flat.o
 

^ permalink raw reply	[flat|nested] 87+ messages in thread

* [PATCH 8/14] FRV: GP-REL data support
       [not found] <76b4a884-2c3c-11d9-91a1-0002b3163499@redhat.com>
                   ` (2 preceding siblings ...)
  2004-11-01 19:30 ` [PATCH 5/14] FRV: Fork fixes dhowells
@ 2004-11-01 19:30 ` dhowells
  2004-11-02  8:18   ` Andrew Morton
                     ` (2 more replies)
  2004-11-01 19:30 ` [PATCH 11/14] FRV: Add FDPIC ELF binary format driver dhowells
                   ` (12 subsequent siblings)
  16 siblings, 3 replies; 87+ messages in thread
From: dhowells @ 2004-11-01 19:30 UTC (permalink / raw)
  To: torvalds, akpm, davidm; +Cc: linux-kernel, uclinux-dev

The attached patch makes it possible to support gp-rel addressing for small
variables. Since the FR-V cpu's have fixed-length instructions and plenty of
general-purpose registers, one register is nominated as a base for the small
data area. This makes it possible to use single-insn accesses to access global
and static variables instead of having to use multiple instructions.

This, however, causes problems with small variables used to pinpoint the
beginning and end of sections. The compiler assumes it can use gp-rel
addressing for these, but the linker then complains because the displacement is
out of range.

By declaring certain variables as arrays or by forcing them into named
sections, the compiler is persuaded to access them as if they can be outside
the displacement range. Declaring the variables as "const void" type also
works.

Signed-Off-By: dhowells@redhat.com
---
diffstat frv-gprel-2610rc1bk10.diff
 drivers/char/tty_io.c   |    4 ++--
 fs/proc/proc_misc.c     |    1 -
 include/linux/init.h    |    4 ++--
 include/linux/jiffies.h |   14 ++++++++++++--
 include/linux/linkage.h |    4 ++++
 init/initramfs.c        |    6 +++---
 init/main.c             |   16 +++++++---------
 init/version.c          |    2 +-
 kernel/kallsyms.c       |    6 ++----
 kernel/power/swsusp.c   |    3 ++-
 10 files changed, 35 insertions(+), 25 deletions(-)

diff -uNr /warthog/kernels/linux-2.6.10-rc1-bk10/drivers/char/tty_io.c linux-2.6.10-rc1-bk10-frv/drivers/char/tty_io.c
--- /warthog/kernels/linux-2.6.10-rc1-bk10/drivers/char/tty_io.c	2004-11-01 11:45:23.000000000 +0000
+++ linux-2.6.10-rc1-bk10-frv/drivers/char/tty_io.c	2004-11-01 11:47:04.819661208 +0000
@@ -2903,8 +2903,8 @@
 	   So I haven't moved it. dwmw2 */
         rs_360_init();
 #endif
-	call = &__con_initcall_start;
-	while (call < &__con_initcall_end) {
+	call = __con_initcall_start;
+	while (call < __con_initcall_end) {
 		(*call)();
 		call++;
 	}
diff -uNr /warthog/kernels/linux-2.6.10-rc1-bk10/include/linux/init.h linux-2.6.10-rc1-bk10-frv/include/linux/init.h
--- /warthog/kernels/linux-2.6.10-rc1-bk10/include/linux/init.h	2004-09-16 12:06:21.000000000 +0100
+++ linux-2.6.10-rc1-bk10-frv/include/linux/init.h	2004-11-01 11:47:05.106637318 +0000
@@ -64,8 +64,8 @@
 typedef int (*initcall_t)(void);
 typedef void (*exitcall_t)(void);
 
-extern initcall_t __con_initcall_start, __con_initcall_end;
-extern initcall_t __security_initcall_start, __security_initcall_end;
+extern initcall_t __con_initcall_start[], __con_initcall_end[];
+extern initcall_t __security_initcall_start[], __security_initcall_end[];
 
 /* Defined in init/main.c */
 extern char saved_command_line[];
diff -uNr /warthog/kernels/linux-2.6.10-rc1-bk10/include/linux/jiffies.h linux-2.6.10-rc1-bk10-frv/include/linux/jiffies.h
--- /warthog/kernels/linux-2.6.10-rc1-bk10/include/linux/jiffies.h	2004-10-27 17:32:36.000000000 +0100
+++ linux-2.6.10-rc1-bk10-frv/include/linux/jiffies.h	2004-11-01 11:47:05.112636819 +0000
@@ -70,13 +70,23 @@
 /* a value TUSEC for TICK_USEC (can be set bij adjtimex)		*/
 #define TICK_USEC_TO_NSEC(TUSEC) (SH_DIV (TUSEC * USER_HZ * 1000, ACTHZ, 8))
 
+/* some arch's have a small-data section that can be accessed register-relative
+ * but that can only take up to, say, 4-byte variables. jiffies being part of
+ * an 8-byte variable may not be correctly accessed unless we force the issue
+ */
+#ifdef CONFIG_FRV
+#define __jiffy_data  __attribute__((section(".data")))
+#else
+#define __jiffy_data
+#endif
+
 /*
  * The 64-bit value is not volatile - you MUST NOT read it
  * without sampling the sequence number in xtime_lock.
  * get_jiffies_64() will do this for you as appropriate.
  */
-extern u64 jiffies_64;
-extern unsigned long volatile jiffies;
+extern u64 __jiffy_data jiffies_64;
+extern unsigned long volatile __jiffy_data jiffies;
 
 #if (BITS_PER_LONG < 64)
 u64 get_jiffies_64(void);
diff -uNr /warthog/kernels/linux-2.6.10-rc1-bk10/include/linux/linkage.h linux-2.6.10-rc1-bk10-frv/include/linux/linkage.h
--- /warthog/kernels/linux-2.6.10-rc1-bk10/include/linux/linkage.h	2004-10-19 10:42:16.000000000 +0100
+++ linux-2.6.10-rc1-bk10-frv/include/linux/linkage.h	2004-11-01 11:47:05.114636652 +0000
@@ -44,4 +44,8 @@
 #define fastcall
 #endif
 
+#ifndef __ASSEMBLY__
+extern const char linux_banner[];
+#endif
+
 #endif
diff -uNr /warthog/kernels/linux-2.6.10-rc1-bk10/init/initramfs.c linux-2.6.10-rc1-bk10-frv/init/initramfs.c
--- /warthog/kernels/linux-2.6.10-rc1-bk10/init/initramfs.c	2004-09-16 12:06:23.000000000 +0100
+++ linux-2.6.10-rc1-bk10-frv/init/initramfs.c	2004-11-01 11:47:05.135634904 +0000
@@ -460,15 +460,15 @@
 	return message;
 }
 
-extern char __initramfs_start, __initramfs_end;
+extern char __initramfs_start[], __initramfs_end[];
 #ifdef CONFIG_BLK_DEV_INITRD
 #include <linux/initrd.h>
 #endif
 
 void __init populate_rootfs(void)
 {
-	char *err = unpack_to_rootfs(&__initramfs_start,
-			 &__initramfs_end - &__initramfs_start, 0);
+	char *err = unpack_to_rootfs(__initramfs_start,
+			 __initramfs_end - __initramfs_start, 0);
 	if (err)
 		panic(err);
 #ifdef CONFIG_BLK_DEV_INITRD
diff -uNr /warthog/kernels/linux-2.6.10-rc1-bk10/init/main.c linux-2.6.10-rc1-bk10-frv/init/main.c
--- /warthog/kernels/linux-2.6.10-rc1-bk10/init/main.c	2004-11-01 11:45:34.000000000 +0000
+++ linux-2.6.10-rc1-bk10-frv/init/main.c	2004-11-01 11:47:05.147633905 +0000
@@ -75,8 +75,6 @@
 #error Sorry, your GCC is too old. It builds incorrect kernels.
 #endif
 
-extern char *linux_banner;
-
 static int init(void *);
 
 extern void init_IRQ(void);
@@ -157,12 +155,13 @@
 char * envp_init[MAX_INIT_ENVS+2] = { "HOME=/", "TERM=linux", NULL, };
 static const char *panic_later, *panic_param;
 
+extern struct obs_kernel_param __setup_start[], __setup_end[];
+
 static int __init obsolete_checksetup(char *line)
 {
 	struct obs_kernel_param *p;
-	extern struct obs_kernel_param __setup_start, __setup_end;
 
-	p = &__setup_start;
+	p = __setup_start;
 	do {
 		int n = strlen(p->str);
 		if (!strncmp(line, p->str, n)) {
@@ -179,7 +178,7 @@
 				return 1;
 		}
 		p++;
-	} while (p < &__setup_end);
+	} while (p < __setup_end);
 	return 0;
 }
 
@@ -452,9 +381,8 @@
 static int __init do_early_param(char *param, char *val)
 {
 	struct obs_kernel_param *p;
-	extern struct obs_kernel_param __setup_start, __setup_end;
 
-	for (p = &__setup_start; p < &__setup_end; p++) {
+	for (p = __setup_start; p < __setup_end; p++) {
 		if (p->early && strcmp(param, p->str) == 0) {
 			if (p->setup_func(val) != 0)
 				printk(KERN_WARNING
@@ -591,14 +521,14 @@
 
 struct task_struct *child_reaper = &init_task;
 
-extern initcall_t __initcall_start, __initcall_end;
+extern initcall_t __initcall_start[], __initcall_end[];
 
 static void __init do_initcalls(void)
 {
 	initcall_t *call;
 	int count = preempt_count();
 
-	for (call = &__initcall_start; call < &__initcall_end; call++) {
+	for (call = __initcall_start; call < __initcall_end; call++) {
 		char *msg;
 
 		if (initcall_debug) {
diff -uNr /warthog/kernels/linux-2.6.10-rc1-bk10/init/version.c linux-2.6.10-rc1-bk10-frv/init/version.c
--- /warthog/kernels/linux-2.6.10-rc1-bk10/init/version.c	2004-06-18 13:42:40.000000000 +0100
+++ linux-2.6.10-rc1-bk10-frv/init/version.c	2004-11-01 11:47:05.148633822 +0000
@@ -28,6 +28,6 @@
 
 EXPORT_SYMBOL(system_utsname);
 
-const char *linux_banner = 
+const char linux_banner[] = 
 	"Linux version " UTS_RELEASE " (" LINUX_COMPILE_BY "@"
 	LINUX_COMPILE_HOST ") (" LINUX_COMPILER ") " UTS_VERSION "\n";
diff -uNr /warthog/kernels/linux-2.6.10-rc1-bk10/kernel/kallsyms.c linux-2.6.10-rc1-bk10-frv/kernel/kallsyms.c
--- /warthog/kernels/linux-2.6.10-rc1-bk10/kernel/kallsyms.c	2004-10-27 17:32:38.000000000 +0100
+++ linux-2.6.10-rc1-bk10-frv/kernel/kallsyms.c	2004-11-01 12:03:26.733929658 +0000
@@ -18,10 +18,11 @@
 #include <linux/fs.h>
 #include <linux/err.h>
 #include <linux/proc_fs.h>
+#include <asm/sections.h>
 
 /* These will be re-linked against their real values during the second link stage */
 extern unsigned long kallsyms_addresses[] __attribute__((weak));
-extern unsigned long kallsyms_num_syms __attribute__((weak));
+extern unsigned long kallsyms_num_syms __attribute__((weak,section("data")));
 extern u8 kallsyms_names[] __attribute__((weak));
 
 extern u8 kallsyms_token_table[] __attribute__((weak));
@@ -29,9 +30,6 @@
 
 extern unsigned long kallsyms_markers[] __attribute__((weak));
 
-/* Defined by the linker script. */
-extern char _stext[], _etext[], _sinittext[], _einittext[];
-
 static inline int is_kernel_inittext(unsigned long addr)
 {
 	if (addr >= (unsigned long)_sinittext
diff -uNr /warthog/kernels/linux-2.6.10-rc1-bk10/kernel/power/swsusp.c linux-2.6.10-rc1-bk10-frv/kernel/power/swsusp.c
--- /warthog/kernels/linux-2.6.10-rc1-bk10/kernel/power/swsusp.c	2004-11-01 11:45:34.000000000 +0000
+++ linux-2.6.10-rc1-bk10-frv/kernel/power/swsusp.c	2004-11-01 11:47:05.165632407 +0000
@@ -67,12 +67,13 @@
 #include <asm/uaccess.h>
 #include <asm/mmu_context.h>
 #include <asm/pgtable.h>
+#include <asm/tlbflush.h>
 #include <asm/io.h>
 
 #include "power.h"
 
 /* References to section boundaries */
-extern char __nosave_begin, __nosave_end;
+extern const void __nosave_begin, __nosave_end;
 
 extern int is_head_of_free_region(struct page *);
 
diff -uNr /warthog/kernels/linux-2.6.10-rc1-bk10/fs/proc/proc_misc.c linux-2.6.10-rc1-bk10-frv/fs/proc/proc_misc.c
--- /warthog/kernels/linux-2.6.10-rc1-bk10/fs/proc/proc_misc.c	2004-11-01 11:45:28.000000000 +0000
+++ linux-2.6.10-rc1-bk10-frv/fs/proc/proc_misc.c	2004-11-01 11:47:04.873656713 +0000
@@ -256,7 +264,6 @@
 static int version_read_proc(char *page, char **start, off_t off,
 				 int count, int *eof, void *data)
 {
-	extern char *linux_banner;
 	int len;
 
 	strcpy(page, linux_banner);

^ permalink raw reply	[flat|nested] 87+ messages in thread

* [PATCH 5/14] FRV: Fork fixes
       [not found] <76b4a884-2c3c-11d9-91a1-0002b3163499@redhat.com>
  2004-11-01 19:30 ` [PATCH 4/14] FRV: Bitops fixes dhowells
  2004-11-01 19:30 ` [PATCH 3/14] FRV: Fujitsu FR-V arch documentation dhowells
@ 2004-11-01 19:30 ` dhowells
  2004-11-01 19:30 ` [PATCH 8/14] FRV: GP-REL data support dhowells
                   ` (13 subsequent siblings)
  16 siblings, 0 replies; 87+ messages in thread
From: dhowells @ 2004-11-01 19:30 UTC (permalink / raw)
  To: torvalds, akpm, davidm; +Cc: linux-kernel, uclinux-dev

The attached patch fixes fork to get rid of the assumption that THREAD_SIZE >=
PAGE_SIZE (on the FR-V the smallest available page size is 16KB).

Signed-Off-By: dhowells@redhat.com
---
diffstat frv-fork-2610rc1bk10.diff
 fork.c |    5 +++++
 1 files changed, 5 insertions(+)

diff -uNr /warthog/kernels/linux-2.6.10-rc1-bk10/kernel/fork.c linux-2.6.10-rc1-bk10-frv/kernel/fork.c
--- /warthog/kernels/linux-2.6.10-rc1-bk10/kernel/fork.c	2004-11-01 11:45:34.740160149 +0000
+++ linux-2.6.10-rc1-bk10-frv/kernel/fork.c	2004-11-01 11:47:05.153633406 +0000
@@ -118,7 +118,12 @@
 	 * value: the thread structures can take up at most half
 	 * of memory.
 	 */
+#if THREAD_SIZE >= PAGE_SIZE
 	max_threads = mempages / (THREAD_SIZE/PAGE_SIZE) / 8;
+#else
+	max_threads = mempages / 8;
+#endif
+
 	/*
 	 * we need to allow at least 20 threads to boot a system
 	 */

^ permalink raw reply	[flat|nested] 87+ messages in thread

* [PATCH 13/14] FRV: Convert extern inline -> static inline
       [not found] <76b4a884-2c3c-11d9-91a1-0002b3163499@redhat.com>
                   ` (8 preceding siblings ...)
  2004-11-01 19:30 ` [PATCH 6/14] FRV: IDE fixes dhowells
@ 2004-11-01 19:30 ` dhowells
  2004-11-01 19:30 ` [PATCH 12/14] FRV: Generate more useful debug info dhowells
                   ` (6 subsequent siblings)
  16 siblings, 0 replies; 87+ messages in thread
From: dhowells @ 2004-11-01 19:30 UTC (permalink / raw)
  To: torvalds, akpm, davidm; +Cc: linux-kernel, uclinux-dev

The attached patch converts a bunch of extern inline functions to be static
inline to permit the kernel to be compiled with -O0 for easier debugging.

Signed-Off-By: dhowells@redhat.com
---
diffstat frv-inline-2610rc1bk10.diff
 bio.h               |    8 ++++----
 blkdev.h            |    2 +-
 byteorder/generic.h |    2 +-
 quotaops.h          |   36 ++++++++++++++++++------------------
 sysrq.h             |    4 ++--
 5 files changed, 26 insertions(+), 26 deletions(-)

diff -uNr /warthog/kernels/linux-2.6.10-rc1-bk10/include/linux/bio.h linux-2.6.10-rc1-bk10-frv/include/linux/bio.h
--- /warthog/kernels/linux-2.6.10-rc1-bk10/include/linux/bio.h	2004-10-19 10:42:16.000000000 +0100
+++ linux-2.6.10-rc1-bk10-frv/include/linux/bio.h	2004-11-01 11:47:05.089638733 +0000
@@ -280,9 +280,9 @@
  * bvec_kmap_irq and bvec_kunmap_irq!!
  *
  * This function MUST be inlined - it plays with the CPU interrupt flags.
- * Hence the `extern inline'.
+ * Hence the `static inline'.
  */
-extern inline char *bvec_kmap_irq(struct bio_vec *bvec, unsigned long *flags)
+static inline char *bvec_kmap_irq(struct bio_vec *bvec, unsigned long *flags)
 {
 	unsigned long addr;
 
@@ -298,7 +298,7 @@
 	return (char *) addr + bvec->bv_offset;
 }
 
-extern inline void bvec_kunmap_irq(char *buffer, unsigned long *flags)
+static inline void bvec_kunmap_irq(char *buffer, unsigned long *flags)
 {
 	unsigned long ptr = (unsigned long) buffer & PAGE_MASK;
 
@@ -311,7 +311,7 @@
 #define bvec_kunmap_irq(buf, flags)	do { *(flags) = 0; } while (0)
 #endif
 
-extern inline char *__bio_kmap_irq(struct bio *bio, unsigned short idx,
+static inline char *__bio_kmap_irq(struct bio *bio, unsigned short idx,
 				   unsigned long *flags)
 {
 	return bvec_kmap_irq(bio_iovec_idx(bio, idx), flags);
diff -uNr /warthog/kernels/linux-2.6.10-rc1-bk10/include/linux/blkdev.h linux-2.6.10-rc1-bk10-frv/include/linux/blkdev.h
--- /warthog/kernels/linux-2.6.10-rc1-bk10/include/linux/blkdev.h	2004-11-01 11:45:33.000000000 +0000
+++ linux-2.6.10-rc1-bk10-frv/include/linux/blkdev.h	2004-11-01 11:47:05.097638067 +0000
@@ -685,7 +685,7 @@
 	return bits;
 }
 
-extern inline unsigned int block_size(struct block_device *bdev)
+static inline unsigned int block_size(struct block_device *bdev)
 {
 	return bdev->bd_block_size;
 }
diff -uNr /warthog/kernels/linux-2.6.10-rc1-bk10/include/linux/byteorder/generic.h linux-2.6.10-rc1-bk10-frv/include/linux/byteorder/generic.h
--- /warthog/kernels/linux-2.6.10-rc1-bk10/include/linux/byteorder/generic.h	2004-10-19 10:42:16.000000000 +0100
+++ linux-2.6.10-rc1-bk10-frv/include/linux/byteorder/generic.h	2004-11-01 11:47:05.099637901 +0000
@@ -152,7 +152,7 @@
 extern __u16			ntohs(__be16);
 extern __be16			htons(__u16);
 
-#if defined(__GNUC__) && (__GNUC__ >= 2) && defined(__OPTIMIZE__)
+#if defined(__GNUC__) && (__GNUC__ >= 2) // && defined(__OPTIMIZE__)
 
 #define ___htonl(x) __cpu_to_be32(x)
 #define ___htons(x) __cpu_to_be16(x)
diff -uNr /warthog/kernels/linux-2.6.10-rc1-bk10/include/linux/quotaops.h linux-2.6.10-rc1-bk10-frv/include/linux/quotaops.h
--- /warthog/kernels/linux-2.6.10-rc1-bk10/include/linux/quotaops.h	2004-09-16 12:06:22.000000000 +0100
+++ linux-2.6.10-rc1-bk10-frv/include/linux/quotaops.h	2004-11-01 11:47:05.127635570 +0000
@@ -59,7 +59,7 @@
 
 /* It is better to call this function outside of any transaction as it might
  * need a lot of space in journal for dquot structure allocation. */
-static __inline__ void DQUOT_INIT(struct inode *inode)
+static inline void DQUOT_INIT(struct inode *inode)
 {
 	BUG_ON(!inode->i_sb);
 	if (sb_any_quota_enabled(inode->i_sb) && !IS_NOQUOTA(inode))
@@ -67,7 +67,7 @@
 }
 
 /* The same as with DQUOT_INIT */
-static __inline__ void DQUOT_DROP(struct inode *inode)
+static inline void DQUOT_DROP(struct inode *inode)
 {
 	/* Here we can get arbitrary inode from clear_inode() so we have
 	 * to be careful. OTOH we don't need locking as quota operations
@@ -90,7 +90,7 @@
 
 /* The following allocation/freeing/transfer functions *must* be called inside
  * a transaction (deadlocks possible otherwise) */
-static __inline__ int DQUOT_PREALLOC_SPACE_NODIRTY(struct inode *inode, qsize_t nr)
+static inline int DQUOT_PREALLOC_SPACE_NODIRTY(struct inode *inode, qsize_t nr)
 {
 	if (sb_any_quota_enabled(inode->i_sb)) {
 		/* Used space is updated in alloc_space() */
@@ -102,7 +102,7 @@
 	return 0;
 }
 
-static __inline__ int DQUOT_PREALLOC_SPACE(struct inode *inode, qsize_t nr)
+static inline int DQUOT_PREALLOC_SPACE(struct inode *inode, qsize_t nr)
 {
 	int ret;
         if (!(ret =  DQUOT_PREALLOC_SPACE_NODIRTY(inode, nr)))
@@ -110,7 +110,7 @@
 	return ret;
 }
 
-static __inline__ int DQUOT_ALLOC_SPACE_NODIRTY(struct inode *inode, qsize_t nr)
+static inline int DQUOT_ALLOC_SPACE_NODIRTY(struct inode *inode, qsize_t nr)
 {
 	if (sb_any_quota_enabled(inode->i_sb)) {
 		/* Used space is updated in alloc_space() */
@@ -122,7 +122,7 @@
 	return 0;
 }
 
-static __inline__ int DQUOT_ALLOC_SPACE(struct inode *inode, qsize_t nr)
+static inline int DQUOT_ALLOC_SPACE(struct inode *inode, qsize_t nr)
 {
 	int ret;
 	if (!(ret = DQUOT_ALLOC_SPACE_NODIRTY(inode, nr)))
@@ -130,7 +130,7 @@
 	return ret;
 }
 
-static __inline__ int DQUOT_ALLOC_INODE(struct inode *inode)
+static inline int DQUOT_ALLOC_INODE(struct inode *inode)
 {
 	if (sb_any_quota_enabled(inode->i_sb)) {
 		DQUOT_INIT(inode);
@@ -140,7 +140,7 @@
 	return 0;
 }
 
-static __inline__ void DQUOT_FREE_SPACE_NODIRTY(struct inode *inode, qsize_t nr)
+static inline void DQUOT_FREE_SPACE_NODIRTY(struct inode *inode, qsize_t nr)
 {
 	if (sb_any_quota_enabled(inode->i_sb))
 		inode->i_sb->dq_op->free_space(inode, nr);
@@ -148,19 +148,19 @@
 		inode_sub_bytes(inode, nr);
 }
 
-static __inline__ void DQUOT_FREE_SPACE(struct inode *inode, qsize_t nr)
+static inline void DQUOT_FREE_SPACE(struct inode *inode, qsize_t nr)
 {
 	DQUOT_FREE_SPACE_NODIRTY(inode, nr);
 	mark_inode_dirty(inode);
 }
 
-static __inline__ void DQUOT_FREE_INODE(struct inode *inode)
+static inline void DQUOT_FREE_INODE(struct inode *inode)
 {
 	if (sb_any_quota_enabled(inode->i_sb))
 		inode->i_sb->dq_op->free_inode(inode, 1);
 }
 
-static __inline__ int DQUOT_TRANSFER(struct inode *inode, struct iattr *iattr)
+static inline int DQUOT_TRANSFER(struct inode *inode, struct iattr *iattr)
 {
 	if (sb_any_quota_enabled(inode->i_sb) && !IS_NOQUOTA(inode)) {
 		DQUOT_INIT(inode);
@@ -173,7 +173,7 @@
 /* The following two functions cannot be called inside a transaction */
 #define DQUOT_SYNC(sb)	sync_dquots(sb, -1)
 
-static __inline__ int DQUOT_OFF(struct super_block *sb)
+static inline int DQUOT_OFF(struct super_block *sb)
 {
 	int ret = -ENOSYS;
 
@@ -197,38 +197,38 @@
 #define DQUOT_SYNC(sb)				do { } while(0)
 #define DQUOT_OFF(sb)				do { } while(0)
 #define DQUOT_TRANSFER(inode, iattr)		(0)
-extern __inline__ int DQUOT_PREALLOC_SPACE_NODIRTY(struct inode *inode, qsize_t nr)
+static inline int DQUOT_PREALLOC_SPACE_NODIRTY(struct inode *inode, qsize_t nr)
 {
 	inode_add_bytes(inode, nr);
 	return 0;
 }
 
-extern __inline__ int DQUOT_PREALLOC_SPACE(struct inode *inode, qsize_t nr)
+static inline int DQUOT_PREALLOC_SPACE(struct inode *inode, qsize_t nr)
 {
 	DQUOT_PREALLOC_SPACE_NODIRTY(inode, nr);
 	mark_inode_dirty(inode);
 	return 0;
 }
 
-extern __inline__ int DQUOT_ALLOC_SPACE_NODIRTY(struct inode *inode, qsize_t nr)
+static inline int DQUOT_ALLOC_SPACE_NODIRTY(struct inode *inode, qsize_t nr)
 {
 	inode_add_bytes(inode, nr);
 	return 0;
 }
 
-extern __inline__ int DQUOT_ALLOC_SPACE(struct inode *inode, qsize_t nr)
+static inline int DQUOT_ALLOC_SPACE(struct inode *inode, qsize_t nr)
 {
 	DQUOT_ALLOC_SPACE_NODIRTY(inode, nr);
 	mark_inode_dirty(inode);
 	return 0;
 }
 
-extern __inline__ void DQUOT_FREE_SPACE_NODIRTY(struct inode *inode, qsize_t nr)
+static inline void DQUOT_FREE_SPACE_NODIRTY(struct inode *inode, qsize_t nr)
 {
 	inode_sub_bytes(inode, nr);
 }
 
-extern __inline__ void DQUOT_FREE_SPACE(struct inode *inode, qsize_t nr)
+static inline void DQUOT_FREE_SPACE(struct inode *inode, qsize_t nr)
 {
 	DQUOT_FREE_SPACE_NODIRTY(inode, nr);
 	mark_inode_dirty(inode);
diff -uNr /warthog/kernels/linux-2.6.10-rc1-bk10/include/linux/sysrq.h linux-2.6.10-rc1-bk10-frv/include/linux/sysrq.h
--- /warthog/kernels/linux-2.6.10-rc1-bk10/include/linux/sysrq.h	2004-06-18 13:44:05.000000000 +0100
+++ linux-2.6.10-rc1-bk10-frv/include/linux/sysrq.h	2004-11-01 11:47:05.133635071 +0000
@@ -41,7 +41,7 @@
 struct sysrq_key_op *__sysrq_get_key_op (int key);
 void __sysrq_put_key_op (int key, struct sysrq_key_op *op_p);
 
-extern __inline__ int
+static inline int
 __sysrq_swap_key_ops_nolock(int key, struct sysrq_key_op *insert_op_p,
 				struct sysrq_key_op *remove_op_p)
 {
@@ -55,7 +55,7 @@
 	return retval;
 }
 
-extern __inline__ int
+static inline int
 __sysrq_swap_key_ops(int key, struct sysrq_key_op *insert_op_p,
 				struct sysrq_key_op *remove_op_p) {
 	int retval;

^ permalink raw reply	[flat|nested] 87+ messages in thread

* [PATCH 12/14] FRV: Generate more useful debug info
       [not found] <76b4a884-2c3c-11d9-91a1-0002b3163499@redhat.com>
                   ` (9 preceding siblings ...)
  2004-11-01 19:30 ` [PATCH 13/14] FRV: Convert extern inline -> static inline dhowells
@ 2004-11-01 19:30 ` dhowells
  2004-11-02  0:29   ` Andrew Morton
  2004-11-02 11:21   ` David Howells
       [not found] ` <20040401020550.GG3150@beast>
                   ` (5 subsequent siblings)
  16 siblings, 2 replies; 87+ messages in thread
From: dhowells @ 2004-11-01 19:30 UTC (permalink / raw)
  To: torvalds, akpm, davidm; +Cc: linux-kernel, uclinux-dev

The attached patch permits the generation of more useful debugging information
by reducing the optimisation level and by telling the assembler to produce
debug info too.

Signed-Off-By: dhowells@redhat.com
---
diffstat frv-debuginfo-2610rc1bk10.diff
 Makefile |   11 +++++++----
 1 files changed, 7 insertions(+), 4 deletions(-)

diff -uNr /warthog/kernels/linux-2.6.10-rc1-bk10/Makefile linux-2.6.10-rc1-bk10-frv/Makefile
--- /warthog/kernels/linux-2.6.10-rc1-bk10/Makefile	2004-11-01 11:45:20.000000000 +0000
+++ linux-2.6.10-rc1-bk10-frv/Makefile	2004-11-01 11:48:36.397037723 +0000
@@ -497,11 +497,18 @@
 # Defaults vmlinux but it is usually overriden in the arch makefile
 all: vmlinux
 
+
+ifdef CONFIG_DEBUG_INFO
+CFLAGS		+= -g -O1
+AFLAGS		+= -Wa,--gdwarf2
+ASFLAGS		+= -Wa,--gdwarf2
+else
 ifdef CONFIG_CC_OPTIMIZE_FOR_SIZE
 CFLAGS		+= -Os
 else
 CFLAGS		+= -O2
 endif
+endif
 
 #Add align options if CONFIG_CC_* is not equal to 0
 add-align = $(if $(filter-out 0,$($(1))),$(cc-option-align)$(2)=$($(1)))
@@ -516,10 +523,6 @@
 CFLAGS		+= -fomit-frame-pointer
 endif
 
-ifdef CONFIG_DEBUG_INFO
-CFLAGS		+= -g
-endif
-
 include $(srctree)/arch/$(ARCH)/Makefile
 
 # warn about C99 declaration after statement

^ permalink raw reply	[flat|nested] 87+ messages in thread

* [PATCH 14/14] FRV: Better mmap support in uClinux
       [not found] ` <20040401020550.GG3150@beast>
@ 2004-11-01 19:30   ` dhowells
  2004-11-02  9:54     ` Christoph Hellwig
  2004-11-02 16:43     ` David Howells
  2004-11-08 14:34   ` [PATCH 17/20] " dhowells
  1 sibling, 2 replies; 87+ messages in thread
From: dhowells @ 2004-11-01 19:30 UTC (permalink / raw)
  To: torvalds, akpm, davidm; +Cc: linux-kernel, uclinux-dev

The attached patch changes mm/nommu.c to better support mmap() when MMU support
is disabled (as it is in uClinux).

This was discussed on the uclibc mailing list in a thread revolving around the
following message:

	Date: Thu, 1 Apr 2004 12:05:50 +1000
	From: David McCullough <davidm@snapgear.com>
	To: David Howells <dhowells@redhat.com>
	Cc: Alexandre Oliva <aoliva@redhat.com>, uclibc@uclibc.org
	Subject: Re: [uClibc] mmaps for malloc should be private
	Message-ID: <20040401020550.GG3150@beast>

The revised rules are:

 (1) Anonymous mappings can be shared or private, read or write.

 (2) Chardevs can be mapped shared, provided they supply a get_unmapped_area()
     file operation and use that to set the address of the mapping (as a frame
     buffer driver might do, for instance).

 (3) Files (and blockdevs) cannot be mapped shared since it is not really
     possible to honour this by writing any changes back to the backing device.

 (4) Files (or sections thereof) can be mapped read-only private, in which case
     the mapped bit will be read into memory and shared, and its address will
     be returned. Any excess beyond EOF will be cleared.

 (5) Files (or sections thereof) can be mapped writable private, in which case
     a private copy of the mapped bit will be read into a new bit memory, and
     its address will be returned. Any excess beyond EOF will be cleared.

Mappings are per MM structure still. You can only unmap what you've mapped.

Fork semantics are irrelevant, since there's no fork.

A global list of VMA's is maintained to keep track of the bits of memory
currently mapped on the system.

The new binfmt makes use of (4) to implement shared libraries.

Signed-Off-By: dhowells@redhat.com
---
diffstat frv-nommu-2610rc1bk10.diff
 fs/proc/base.c       |   30 ++-
 fs/proc/task_nommu.c |   35 +--
 include/linux/mm.h   |   29 +++
 mm/nommu.c           |  483 ++++++++++++++++++++++++++++++++++-----------------
 mm/tiny-shmem.c      |    2 
 5 files changed, 397 insertions(+), 182 deletions(-)

diff -uNr /warthog/kernels/linux-2.6.10-rc1-bk10/fs/proc/base.c linux-2.6.10-rc1-bk10-frv/fs/proc/base.c
--- /warthog/kernels/linux-2.6.10-rc1-bk10/fs/proc/base.c	2004-10-27 17:32:31.000000000 +0100
+++ linux-2.6.10-rc1-bk10-frv/fs/proc/base.c	2004-11-01 11:47:04.870656963 +0000
@@ -220,6 +220,9 @@
 
 static int proc_exe_link(struct inode *inode, struct dentry **dentry, struct vfsmount **mnt)
 {
+#ifndef CONFIG_MMU
+	struct mm_tblock_struct *tblock;
+#endif
 	struct vm_area_struct * vma;
 	int result = -ENOENT;
 	struct task_struct *task = proc_task(inode);
@@ -228,17 +231,32 @@
 	if (!mm)
 		goto out;
 	down_read(&mm->mmap_sem);
+
+#ifdef CONFIG_MMU
 	vma = mm->mmap;
 	while (vma) {
-		if ((vma->vm_flags & VM_EXECUTABLE) && 
-		    vma->vm_file) {
-			*mnt = mntget(vma->vm_file->f_vfsmnt);
-			*dentry = dget(vma->vm_file->f_dentry);
-			result = 0;
+		if ((vma->vm_flags & VM_EXECUTABLE) && vma->vm_file)
 			break;
-		}
 		vma = vma->vm_next;
 	}
+#else
+	tblock = mm->context.tblock;
+	vma = NULL;
+	while (tblock) {
+		if ((tblock->vma->vm_flags & VM_EXECUTABLE) && tblock->vma->vm_file) {
+			vma = tblock->vma;
+			break;
+		}
+		tblock = tblock->next;
+	}
+#endif
+
+	if (vma) {
+		*mnt = mntget(vma->vm_file->f_vfsmnt);
+		*dentry = dget(vma->vm_file->f_dentry);
+		result = 0;
+	}
+
 	up_read(&mm->mmap_sem);
 	mmput(mm);
 out:
diff -uNr /warthog/kernels/linux-2.6.10-rc1-bk10/fs/proc/task_nommu.c linux-2.6.10-rc1-bk10-frv/fs/proc/task_nommu.c
--- /warthog/kernels/linux-2.6.10-rc1-bk10/fs/proc/task_nommu.c	2004-10-19 10:42:09.000000000 +0100
+++ linux-2.6.10-rc1-bk10-frv/fs/proc/task_nommu.c	2004-11-01 11:47:04.000000000 +0000
@@ -15,19 +15,19 @@
 	struct mm_tblock_struct *tblock;
         
 	down_read(&mm->mmap_sem);
-	for (tblock = &mm->context.tblock; tblock; tblock = tblock->next) {
-		if (!tblock->rblock)
+	for (tblock = mm->context.tblock; tblock; tblock = tblock->next) {
+		if (!tblock->vma)
 			continue;
 		bytes += kobjsize(tblock);
 		if (atomic_read(&mm->mm_count) > 1 ||
-		    tblock->rblock->refcount > 1) {
-			sbytes += kobjsize(tblock->rblock->kblock);
-			sbytes += kobjsize(tblock->rblock);
+		    atomic_read(&tblock->vma->vm_usage) > 1) {
+			sbytes += kobjsize((void *) tblock->vma->vm_start);
+			sbytes += kobjsize(tblock->vma);
 		} else {
-			bytes += kobjsize(tblock->rblock->kblock);
-			bytes += kobjsize(tblock->rblock);
-			slack += kobjsize(tblock->rblock->kblock) -
-					tblock->rblock->size;
+			bytes += kobjsize((void *) tblock->vma->vm_start);
+			bytes += kobjsize(tblock->vma);
+			slack += kobjsize((void *) tblock->vma->vm_start) -
+				(tblock->vma->vm_end - tblock->vma->vm_start);
 		}
 	}
 
@@ -69,9 +69,9 @@
 	unsigned long vsize = 0;
 
 	down_read(&mm->mmap_sem);
-	for (tbp = &mm->context.tblock; tbp; tbp = tbp->next) {
-		if (tbp->rblock)
-			vsize += kobjsize(tbp->rblock->kblock);
+	for (tbp = mm->context.tblock; tbp; tbp = tbp->next) {
+		if (tbp->vma)
+			vsize += kobjsize((void *) tbp->vma->vm_start);
 	}
 	up_read(&mm->mmap_sem);
 	return vsize;
@@ -84,12 +84,11 @@
 	int size = kobjsize(mm);
 
 	down_read(&mm->mmap_sem);
-	for (tbp = &mm->context.tblock; tbp; tbp = tbp->next) {
-		if (tbp->next)
-			size += kobjsize(tbp->next);
-		if (tbp->rblock) {
-			size += kobjsize(tbp->rblock);
-			size += kobjsize(tbp->rblock->kblock);
+	for (tbp = mm->context.tblock; tbp; tbp = tbp->next) {
+		size += kobjsize(tbp);
+		if (tbp->vma) {
+			size += kobjsize(tbp->vma);
+			size += kobjsize((void *) tbp->vma->vm_start);
 		}
 	}
 
diff -uNr /warthog/kernels/linux-2.6.10-rc1-bk10/mm/nommu.c linux-2.6.10-rc1-bk10-frv/mm/nommu.c
--- /warthog/kernels/linux-2.6.10-rc1-bk10/mm/nommu.c	2004-11-01 11:45:34.991139255 +0000
+++ linux-2.6.10-rc1-bk10-frv/mm/nommu.c	2004-11-01 14:31:33.105719990 +0000
@@ -4,6 +4,7 @@
  *  Replacement code for mm functions to support CPU's that don't
  *  have any form of memory management unit (thus no virtual memory).
  *
+ *  Copyright (c) 2004      David Howells <dhowells@redhat.com>
  *  Copyright (c) 2000-2003 David McCullough <davidm@snapgear.com>
  *  Copyright (c) 2000-2001 D Jeff Dionne <jeff@uClinux.org>
  *  Copyright (c) 2002      Greg Ungerer <gerg@snapgear.com>
@@ -12,11 +13,12 @@
 #include <linux/mm.h>
 #include <linux/mman.h>
 #include <linux/swap.h>
-#include <linux/smp_lock.h>
+#include <linux/file.h>
 #include <linux/highmem.h>
 #include <linux/pagemap.h>
 #include <linux/slab.h>
 #include <linux/vmalloc.h>
+#include <linux/ptrace.h>
 #include <linux/blkdev.h>
 #include <linux/backing-dev.h>
 #include <linux/syscalls.h>
@@ -38,6 +40,10 @@
 EXPORT_SYMBOL(sysctl_max_map_count);
 EXPORT_SYMBOL(mem_map);
 
+/* list of shareable VMAs */
+LIST_HEAD(shareable_vma_list);
+DECLARE_RWSEM(shareable_vma_sem);
+
 /*
  * Handle all mappings that got truncated by a "truncate()"
  * system call.
@@ -161,7 +167,7 @@
 	/* Don't allow overflow */
 	if ((unsigned long) addr + count < count)
 		count = -(unsigned long) addr;
-	
+
 	memcpy(addr, buf, count);
 	return(count);
 }
@@ -217,7 +223,7 @@
 {
 	struct mm_struct *mm = current->mm;
 
-	if (brk < mm->end_code || brk < mm->start_brk || brk > mm->context.end_brk)
+	if (brk < mm->start_brk || brk > mm->context.end_brk)
 		return mm->brk;
 
 	if (mm->brk == brk)
@@ -276,33 +282,38 @@
 }
 #endif /* DEBUG */
 
-unsigned long do_mmap_pgoff(
-	struct file * file,
-	unsigned long addr,
-	unsigned long len,
-	unsigned long prot,
-	unsigned long flags,
-	unsigned long pgoff)
+unsigned long do_mmap_pgoff(struct file *file,
+			    unsigned long addr,
+			    unsigned long len,
+			    unsigned long prot,
+			    unsigned long flags,
+			    unsigned long pgoff)
 {
-	void * result;
-	struct mm_tblock_struct * tblock;
+	struct mm_tblock_struct *tblock = NULL;
+	struct vm_area_struct *vma = NULL;
 	unsigned int vm_flags;
+	void *result;
+	int ret, chrdev;
 
 	/*
 	 * Get the !CONFIG_MMU specific checks done first
 	 */
-	if ((flags & MAP_SHARED) && (prot & PROT_WRITE) && (file)) {
-		printk("MAP_SHARED not supported (cannot write mappings to disk)\n");
+	chrdev = 0;
+	if (file)
+		chrdev = S_ISCHR(file->f_dentry->d_inode->i_mode);
+
+	if ((flags & MAP_SHARED) && (prot & PROT_WRITE) && file && !chrdev) {
+		printk("MAP_SHARED not completely supported (cannot detect page dirtying)\n");
 		return -EINVAL;
 	}
-	
-	if ((prot & PROT_WRITE) && (flags & MAP_PRIVATE)) {
-		printk("Private writable mappings not supported\n");
+
+	if (flags & MAP_FIXED || addr) {
+//		printk("can't do fixed-address/overlay mmap of RAM\n");
 		return -EINVAL;
 	}
-	
+
 	/*
-	 *	now all the standard checks
+	 * now all the standard checks
 	 */
 	if (file && (!file->f_op || !file->f_op->mmap))
 		return -ENODEV;
@@ -317,148 +328,283 @@
 	if ((pgoff + (len >> PAGE_SHIFT)) < pgoff)
 		return -EINVAL;
 
+	/* we're going to need to record the mapping if it works */
+	tblock = kmalloc(sizeof(struct mm_tblock_struct), GFP_KERNEL);
+	if (!tblock)
+		goto error_getting_tblock;
+	memset(tblock, 0, sizeof(*tblock));
+
 	/* Do simple checking here so the lower-level routines won't have
 	 * to. we assume access permissions have been handled by the open
 	 * of the memory object, so we don't do any here.
 	 */
-	vm_flags = calc_vm_flags(prot,flags) /* | mm->def_flags */ | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC;
+	vm_flags = calc_vm_flags(prot,flags) /* | mm->def_flags */
+		| VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC;
+
+	if (!chrdev) {
+		/* share any file segment that's mapped read-only */
+		if (((flags & MAP_PRIVATE) && !(prot & PROT_WRITE) && file) ||
+		    ((flags & MAP_SHARED) && !(prot & PROT_WRITE) && file))
+			vm_flags |= VM_SHARED | VM_MAYSHARE;
+
+		/* refuse to let anyone share files with this process if it's being traced -
+		 * otherwise breakpoints set in it may interfere with another untraced process
+		 */
+		if (!chrdev && current->ptrace & PT_PTRACED)
+			vm_flags &= ~(VM_SHARED | VM_MAYSHARE);
+	}
+	else {
+		/* permit sharing of character devices at any time */
+		vm_flags |= VM_MAYSHARE;
+		if (flags & MAP_SHARED)
+			vm_flags |= VM_SHARED;
+	}
+
+	/* if we want to share, we need to search for VMAs created by another mmap() call that
+	 * overlap with our proposed mapping
+	 * - we can only share with an exact match on regular files
+	 * - shared mappings on character devices are permitted to overlap inexactly as far as we
+	 *   are concerned, but in that case, sharing is handled in the driver rather than here
+	 */
+	down_write(&shareable_vma_sem);
+	if (!chrdev && vm_flags & VM_SHARED) {
+		unsigned long pglen = (len + PAGE_SIZE - 1) >> PAGE_SHIFT;
+		unsigned long vmpglen;
+
+		list_for_each_entry(vma, &shareable_vma_list, vm_shlink) {
+			if (vma->vm_file->f_dentry->d_inode != file->f_dentry->d_inode)
+				continue;
+
+			if (vma->vm_pgoff >= pgoff + pglen)
+				continue;
+
+			vmpglen = (vma->vm_end - vma->vm_start + PAGE_SIZE - 1) >> PAGE_SHIFT;
+			if (pgoff >= vma->vm_pgoff + vmpglen)
+				continue;
+
+			if (vmpglen != pglen || vma->vm_pgoff != pgoff) {
+				if (flags & MAP_SHARED)
+					goto sharing_violation;
+				continue;
+			}
+
+			/* we've found a VMA we can share */
+			atomic_inc(&vma->vm_usage);
+
+			tblock->vma = vma;
+			result = (void *) vma->vm_start;
+			goto shared;
+		}
+	}
+
+	/* Obtain the address to map to. we verify (or select) it and ensure
+	 * that it represents a valid section of the address space.
+	 */
+	if (file && file->f_op && file->f_op->get_unmapped_area)
+		addr = file->f_op->get_unmapped_area(file, addr, len, pgoff, flags);
+
+	if (IS_ERR((void *) addr)) {
+		ret = addr;
+		goto error;
+	}
+
+	/* we're going to need a VMA struct as well */
+	vma = kmalloc(sizeof(struct vm_area_struct), GFP_KERNEL);
+	if (!vma)
+		goto error_getting_vma;
+
+	INIT_LIST_HEAD(&vma->vm_shlink);
+	atomic_set(&vma->vm_usage, 1);
+	if (file)
+		get_file(file);
+	vma->vm_file	= file;
+	vma->vm_flags	= vm_flags;
+	vma->vm_start	= addr;
+	vma->vm_end	= addr + len;
+	vma->vm_pgoff	= pgoff;
+
+	tblock->vma = vma;
 
 	/*
 	 * determine the object being mapped and call the appropriate
-	 * specific mapper. 
+	 * specific mapper.
 	 */
 	if (file) {
-		struct vm_area_struct vma;
-		int error;
-
+		ret = -ENODEV;
 		if (!file->f_op)
-			return -ENODEV;
-
-		vma.vm_start = addr;
-		vma.vm_end = addr + len;
-		vma.vm_flags = vm_flags;
-		vma.vm_pgoff = pgoff;
+			goto error;
 
 #ifdef MAGIC_ROM_PTR
 		/* First, try simpler routine designed to give us a ROM pointer. */
 
 		if (file->f_op->romptr && !(prot & PROT_WRITE)) {
-			error = file->f_op->romptr(file, &vma);
+			ret = file->f_op->romptr(file, vma);
 #ifdef DEBUG
-			printk("romptr mmap returned %d, start 0x%.8x\n", error,
-					vma.vm_start);
+			printk("romptr mmap returned %d (st=%lx)\n",
+			       ret, vma->vm_start);
 #endif
-			if (!error)
-				return vma.vm_start;
-			else if (error != -ENOSYS)
-				return error;
+			result = (void *) vma->vm_start;
+			if (!ret)
+				goto done;
+			else if (ret != -ENOSYS)
+				goto error;
 		} else
 #endif /* MAGIC_ROM_PTR */
 		/* Then try full mmap routine, which might return a RAM pointer,
 		   or do something truly complicated. */
-		   
+
 		if (file->f_op->mmap) {
-			error = file->f_op->mmap(file, &vma);
-				   
+			ret = file->f_op->mmap(file, vma);
+
 #ifdef DEBUG
-			printk("f_op->mmap() returned %d/%lx\n", error, vma.vm_start);
+			printk("f_op->mmap() returned %d (st=%lx)\n",
+			       ret, vma->vm_start);
 #endif
-			if (!error)
-				return vma.vm_start;
-			else if (error != -ENOSYS)
-				return error;
-		} else
-			return -ENODEV; /* No mapping operations defined */
+			result = (void *) vma->vm_start;
+			if (!ret)
+				goto done;
+			else if (ret != -ENOSYS)
+				goto error;
+		} else {
+			ret = -ENODEV; /* No mapping operations defined */
+			goto error;
+		}
 
 		/* An ENOSYS error indicates that mmap isn't possible (as opposed to
 		   tried but failed) so we'll fall through to the copy. */
 	}
 
-	tblock = (struct mm_tblock_struct *)
-                        kmalloc(sizeof(struct mm_tblock_struct), GFP_KERNEL);
-	if (!tblock) {
-		printk("Allocation of tblock for %lu byte allocation from process %d failed\n", len, current->pid);
-		show_free_areas();
-		return -ENOMEM;
-	}
-
-	tblock->rblock = (struct mm_rblock_struct *)
-			kmalloc(sizeof(struct mm_rblock_struct), GFP_KERNEL);
-
-	if (!tblock->rblock) {
-		printk("Allocation of rblock for %lu byte allocation from process %d failed\n", len, current->pid);
-		show_free_areas();
-		kfree(tblock);
-		return -ENOMEM;
-	}
-
+	/* allocate some memory to hold the mapping */
+	ret = -ENOMEM;
 	result = kmalloc(len, GFP_KERNEL);
 	if (!result) {
-		printk("Allocation of length %lu from process %d failed\n", len,
-				current->pid);
+		printk("Allocation of length %lu from process %d failed\n",
+		       len, current->pid);
 		show_free_areas();
-		kfree(tblock->rblock);
-		kfree(tblock);
-		return -ENOMEM;
+		goto error;
 	}
 
-	tblock->rblock->refcount = 1;
-	tblock->rblock->kblock = result;
-	tblock->rblock->size = len;
-	
-	realalloc += kobjsize(result);
-	askedalloc += len;
+	vma->vm_start = (unsigned long) result;
+	vma->vm_end = vma->vm_start + len;
 
-#ifdef WARN_ON_SLACK	
-	if ((len+WARN_ON_SLACK) <= kobjsize(result))
-		printk("Allocation of %lu bytes from process %d has %lu bytes of slack\n", len, current->pid, kobjsize(result)-len);
+#ifdef WARN_ON_SLACK
+	if (len + WARN_ON_SLACK <= kobjsize(result))
+		printk("Allocation of %lu bytes from process %d has %lu bytes of slack\n",
+		       len, current->pid, kobjsize(result) - len);
 #endif
-	
+
 	if (file) {
-		int error;
 		mm_segment_t old_fs = get_fs();
+		loff_t fpos;
+
+		fpos = pgoff;
+		fpos <<= PAGE_SHIFT;
+
 		set_fs(KERNEL_DS);
-		error = file->f_op->read(file, (char *) result, len, &file->f_pos);
+		ret = file->f_op->read(file, (char *) result, len, &fpos);
 		set_fs(old_fs);
-		if (error < 0) {
-			kfree(result);
-			kfree(tblock->rblock);
-			kfree(tblock);
-			return error;
-		}
-		if (error < len)
-			memset(result+error, '\0', len-error);
+
+		if (ret < 0)
+			goto error2;
+		if (ret < len)
+			memset(result + ret, 0, len - ret);
 	} else {
-		memset(result, '\0', len);
+		memset(result, 0, len);
 	}
 
-	realalloc += kobjsize(tblock);
-	askedalloc += sizeof(struct mm_tblock_struct);
+	if (prot & PROT_EXEC)
+		flush_icache_range((unsigned long) result, (unsigned long) result + len);
 
-	realalloc += kobjsize(tblock->rblock);
-	askedalloc += sizeof(struct mm_rblock_struct);
+ done:
+	realalloc += kobjsize(result);
+	askedalloc += len;
+
+	realalloc += kobjsize(vma);
+	askedalloc += sizeof(*vma);
 
-	tblock->next = current->mm->context.tblock.next;
-	current->mm->context.tblock.next = tblock;
 	current->mm->total_vm += len >> PAGE_SHIFT;
 
+	if (vm_flags & VM_SHARED)
+		list_add(&vma->vm_shlink, &shareable_vma_list);
+
+ shared:
+	realalloc += kobjsize(tblock);
+	askedalloc += sizeof(*tblock);
+
+	tblock->next = current->mm->context.tblock;
+	current->mm->context.tblock = tblock;
+
+	up_write(&shareable_vma_sem);
+
 #ifdef DEBUG
 	printk("do_mmap:\n");
 	show_process_blocks();
-#endif	  
+#endif
+
+	return (unsigned long) result;
+
+ error2:
+	kfree(result);
+ error:
+	up_write(&shareable_vma_sem);
+	kfree(tblock);
+	if (vma) {
+		fput(vma->vm_file);
+		kfree(vma);
+	}
+	return ret;
+
+ sharing_violation:
+	up_write(&shareable_vma_sem);
+	printk("Attempt to share mismatched mappings\n");
+	kfree(tblock);
+	return -EINVAL;
 
-	return (unsigned long)result;
+ error_getting_vma:
+	up_write(&shareable_vma_sem);
+	kfree(tblock);
+	printk("Allocation of tblock for %lu byte allocation from process %d failed\n",
+	       len, current->pid);
+	show_free_areas();
+	return -ENOMEM;
+
+ error_getting_tblock:
+	printk("Allocation of tblock for %lu byte allocation from process %d failed\n",
+	       len, current->pid);
+	show_free_areas();
+	return -ENOMEM;
+}
+
+static void put_vma(struct vm_area_struct *vma)
+{
+	if (vma) {
+		down_write(&shareable_vma_sem);
+		if (atomic_dec_and_test(&vma->vm_usage)) {
+			list_del_init(&vma->vm_shlink);
+
+			if (!(vma->vm_flags & VM_IO) && vma->vm_start) {
+				realalloc -= kobjsize((void *) vma->vm_start);
+				askedalloc -= vma->vm_end - vma->vm_start;
+				if (vma->vm_file)
+					fput(vma->vm_file);
+				kfree((void *) vma->vm_start);
+			}
+
+			realalloc -= kobjsize(vma);
+			askedalloc -= sizeof(*vma);
+			kfree(vma);
+		}
+		up_write(&shareable_vma_sem);
+	}
 }
 
-int do_munmap(struct mm_struct * mm, unsigned long addr, size_t len)
+int do_munmap(struct mm_struct *mm, unsigned long addr, size_t len)
 {
-	struct mm_tblock_struct * tblock, *tmp;
+	struct mm_tblock_struct *tblock, **parent;
 
 #ifdef MAGIC_ROM_PTR
-	/*
-	 * For efficiency's sake, if the pointer is obviously in ROM,
-	 * don't bother walking the lists to free it.
-	 */
+	/* For efficiency's sake, if the pointer is obviously in ROM,
+	   don't bother walking the lists to free it */
 	if (is_in_rom(addr))
 		return 0;
 #endif
@@ -467,38 +613,28 @@
 	printk("do_munmap:\n");
 #endif
 
-	tmp = &mm->context.tblock; /* dummy head */
-	while ((tblock=tmp->next) && tblock->rblock &&
-			tblock->rblock->kblock != (void*)addr) 
-		tmp = tblock;
-		
+	for (parent = &mm->context.tblock; *parent; parent = &(*parent)->next)
+		if ((*parent)->vma->vm_start == addr)
+			break;
+	tblock = *parent;
+
 	if (!tblock) {
 		printk("munmap of non-mmaped memory by process %d (%s): %p\n",
-				current->pid, current->comm, (void*)addr);
+		       current->pid, current->comm, (void *) addr);
 		return -EINVAL;
 	}
-	if (tblock->rblock) {
-		if (!--tblock->rblock->refcount) {
-			if (tblock->rblock->kblock) {
-				realalloc -= kobjsize(tblock->rblock->kblock);
-				askedalloc -= tblock->rblock->size;
-				kfree(tblock->rblock->kblock);
-			}
-			
-			realalloc -= kobjsize(tblock->rblock);
-			askedalloc -= sizeof(struct mm_rblock_struct);
-			kfree(tblock->rblock);
-		}
-	}
-	tmp->next = tblock->next;
+
+	put_vma(tblock->vma);
+
+	*parent = tblock->next;
 	realalloc -= kobjsize(tblock);
-	askedalloc -= sizeof(struct mm_tblock_struct);
+	askedalloc -= sizeof(*tblock);
 	kfree(tblock);
 	mm->total_vm -= len >> PAGE_SHIFT;
 
 #ifdef DEBUG
 	show_process_blocks();
-#endif	  
+#endif
 
 	return 0;
 }
@@ -507,38 +643,27 @@
 void exit_mmap(struct mm_struct * mm)
 {
 	struct mm_tblock_struct *tmp;
-	mm->total_vm = 0;
-
-	if (!mm)
-		return;
 
+	if (mm) {
 #ifdef DEBUG
-	printk("Exit_mmap:\n");
+		printk("Exit_mmap:\n");
 #endif
 
-	while((tmp = mm->context.tblock.next)) {
-		if (tmp->rblock) {
-			if (!--tmp->rblock->refcount) {
-				if (tmp->rblock->kblock) {
-					realalloc -= kobjsize(tmp->rblock->kblock);
-					askedalloc -= tmp->rblock->size;
-					kfree(tmp->rblock->kblock);
-				}
-				realalloc -= kobjsize(tmp->rblock);
-				askedalloc -= sizeof(struct mm_rblock_struct);
-				kfree(tmp->rblock);
-			}
-			tmp->rblock = 0;
+		mm->total_vm = 0;
+
+		while ((tmp = mm->context.tblock)) {
+			mm->context.tblock = tmp->next;
+			put_vma(tmp->vma);
+
+			realalloc -= kobjsize(tmp);
+			askedalloc -= sizeof(*tmp);
+			kfree(tmp);
 		}
-		mm->context.tblock.next = tmp->next;
-		realalloc -= kobjsize(tmp);
-		askedalloc -= sizeof(struct mm_tblock_struct);
-		kfree(tmp);
-	}
 
 #ifdef DEBUG
-	show_process_blocks();
-#endif	  
+		show_process_blocks();
+#endif
+	}
 }
 
 asmlinkage long sys_munmap(unsigned long addr, size_t len)
@@ -557,6 +682,54 @@
 	return -ENOMEM;
 }
 
+/*
+ * Expand (or shrink) an existing mapping, potentially moving it at the
+ * same time (controlled by the MREMAP_MAYMOVE flag and available VM space)
+ *
+ * MREMAP_FIXED option added 5-Dec-1999 by Benjamin LaHaise
+ * This option implies MREMAP_MAYMOVE.
+ *
+ * on uClinux, we only permit changing a mapping's size, and only as long as it stays within the
+ * hole allocated by the kmalloc() call in do_mmap_pgoff() and the block is not shareable
+ */
+unsigned long do_mremap(unsigned long addr,
+			unsigned long old_len, unsigned long new_len,
+			unsigned long flags, unsigned long new_addr)
+{
+	struct mm_tblock_struct *tblock = NULL;
+
+	/* insanity checks first */
+	if (new_len == 0)
+		return (unsigned long) -EINVAL;
+
+	if (flags & MREMAP_FIXED && new_addr != addr)
+		return (unsigned long) -EINVAL;
+
+	for (tblock = current->mm->context.tblock; tblock; tblock = tblock->next)
+		if (tblock->vma->vm_start == addr)
+			goto found;
+
+	return (unsigned long) -EINVAL;
+
+ found:
+	if (tblock->vma->vm_end != tblock->vma->vm_start + old_len)
+		return (unsigned long) -EFAULT;
+
+	if (tblock->vma->vm_flags & VM_MAYSHARE)
+		return (unsigned long) -EPERM;
+
+	if (new_len > kobjsize((void *) addr))
+		return (unsigned long) -ENOMEM;
+
+	/* all checks complete - do it */
+	tblock->vma->vm_end = tblock->vma->vm_start + new_len;
+
+	askedalloc -= old_len;
+	askedalloc += new_len;
+
+	return tblock->vma->vm_start;
+}
+
 struct vm_area_struct * find_vma(struct mm_struct * mm, unsigned long addr)
 {
 	return NULL;
@@ -578,12 +751,6 @@
 	return -EPERM;
 }
 
-unsigned long get_unmapped_area(struct file *file, unsigned long addr,
-	unsigned long len, unsigned long pgoff, unsigned long flags)
-{
-	return -ENOMEM;
-}
-
 void swap_unplug_io_fn(struct backing_dev_info *bdi, struct page *page)
 {
 }
diff -uNr /warthog/kernels/linux-2.6.10-rc1-bk10/mm/tiny-shmem.c linux-2.6.10-rc1-bk10-frv/mm/tiny-shmem.c
--- /warthog/kernels/linux-2.6.10-rc1-bk10/mm/tiny-shmem.c	2004-10-27 17:32:38.000000000 +0100
+++ linux-2.6.10-rc1-bk10-frv/mm/tiny-shmem.c	2004-11-01 14:24:49.419177784 +0000
@@ -112,7 +112,9 @@
 	if (vma->vm_file)
 		fput(vma->vm_file);
 	vma->vm_file = file;
+#ifdef CONFIG_MMU
 	vma->vm_ops = &generic_file_vm_ops;
+#endif
 	return 0;
 }
 
diff -uNr /warthog/kernels/linux-2.6.10-rc1-bk10/include/linux/mm.h linux-2.6.10-rc1-bk10-frv/include/linux/mm.h
--- /warthog/kernels/linux-2.6.10-rc1-bk10/include/linux/mm.h	2004-11-01 11:45:33.371274107 +0000
+++ linux-2.6.10-rc1-bk10-frv/include/linux/mm.h	2004-11-01 14:16:26.408497251 +0000
@@ -112,6 +112,31 @@
 #endif
 };
 
+#else
+
+struct vm_area_struct {
+	struct list_head	vm_shlink;	/* system shared object list */
+	atomic_t		vm_usage;	/* count of refs */
+	unsigned long		vm_start;
+	unsigned long		vm_end;
+	pgprot_t		vm_page_prot;	/* access permissions of this VMA */
+	unsigned long		vm_flags;
+	unsigned long		vm_pgoff;
+	struct file		*vm_file;	/* file or device mapped */
+};
+
+struct mm_tblock_struct {
+	struct mm_tblock_struct	*next;
+	struct vm_area_struct	*vma;
+};
+
+extern struct list_head shareable_vma_list;
+extern struct rw_semaphore shareable_vma_sem;
+
+extern unsigned int kobjsize(const void *objp);
+
+#endif
+
 /*
  * vm_flags..
  */
@@ -603,6 +628,10 @@
 int set_page_dirty_lock(struct page *page);
 int clear_page_dirty_for_io(struct page *page);
 
+extern unsigned long do_mremap(unsigned long addr,
+			       unsigned long old_len, unsigned long new_len,
+			       unsigned long flags, unsigned long new_addr);
+
 /*
  * Prototype to add a shrinker callback for ageable caches.
  * 

^ permalink raw reply	[flat|nested] 87+ messages in thread

* Re: [PATCH 6/14] FRV: IDE fixes
  2004-11-01 19:30 ` [PATCH 6/14] FRV: IDE fixes dhowells
@ 2004-11-01 22:53   ` Alan Cox
  2004-11-02  0:13     ` Bartlomiej Zolnierkiewicz
  2004-11-02 10:57     ` David Howells
  0 siblings, 2 replies; 87+ messages in thread
From: Alan Cox @ 2004-11-01 22:53 UTC (permalink / raw)
  To: dhowells; +Cc: torvalds, akpm, davidm, Linux Kernel Mailing List, uclinux-dev

On Llu, 2004-11-01 at 19:30, dhowells@redhat.com wrote:
>  		memset(&hwif->hw, 0, sizeof(hwif->hw));
> +#ifndef IDE_ARCH_OBSOLETE_INIT
> +		ide_std_init_ports(&hwif->hw, base, (ctl | 2));
> +		hwif->hw.io_ports[IDE_IRQ_OFFSET] = 0;
> +#else
>  		ide_init_hwif_ports(&hwif->hw, base, (ctl | 2), NULL);
> +#endif

Do you really need this, and if so please why ?


^ permalink raw reply	[flat|nested] 87+ messages in thread

* Re: [PATCH 10/14] FRV: Make calibrate_delay() optional
  2004-11-01 19:30 ` [PATCH 10/14] FRV: Make calibrate_delay() optional dhowells
@ 2004-11-02  0:06   ` john stultz
  2004-11-02  8:17   ` Andrew Morton
                     ` (3 subsequent siblings)
  4 siblings, 0 replies; 87+ messages in thread
From: john stultz @ 2004-11-02  0:06 UTC (permalink / raw)
  To: dhowells; +Cc: Linus Torvalds, Andrew Morton, davidm, lkml, uclinux-dev

On Mon, 2004-11-01 at 11:30, dhowells@redhat.com wrote:
> The attached patch makes calibrate_delay() optional. In this architecture, it's
> a waste of time since we can predict exactly what it's going to come up with
> just by looking at the CPU's hardware clock registers. Thus far, we haven't
> seem a board with any clock not dependent on the CPU's clock.

Just doing a quick skim, the patch looks good. Making a whole new file
for just one function is a bit heavy handed, but I don't feel that code
needed to be in main.c

My only nit would be to save the tabs and switch the code from:

if (preset_lpj) {
	newstuff
} else {
	oldstuff
}

to

if (preset_lpj) {
	newstuff
	return
}
oldstuff


thanks
-john


^ permalink raw reply	[flat|nested] 87+ messages in thread

* Re: [PATCH 6/14] FRV: IDE fixes
  2004-11-01 22:53   ` Alan Cox
@ 2004-11-02  0:13     ` Bartlomiej Zolnierkiewicz
  2004-11-02 10:57     ` David Howells
  1 sibling, 0 replies; 87+ messages in thread
From: Bartlomiej Zolnierkiewicz @ 2004-11-02  0:13 UTC (permalink / raw)
  To: Alan Cox
  Cc: dhowells, torvalds, akpm, davidm, Linux Kernel Mailing List, uclinux-dev

On Mon, 01 Nov 2004 22:53:06 +0000, Alan Cox <alan@lxorguk.ukuu.org.uk> wrote:
> On Llu, 2004-11-01 at 19:30, dhowells@redhat.com wrote:
> >               memset(&hwif->hw, 0, sizeof(hwif->hw));
> > +#ifndef IDE_ARCH_OBSOLETE_INIT
> > +             ide_std_init_ports(&hwif->hw, base, (ctl | 2));
> > +             hwif->hw.io_ports[IDE_IRQ_OFFSET] = 0;
> > +#else
> >               ide_init_hwif_ports(&hwif->hw, base, (ctl | 2), NULL);
> > +#endif
> 
> Do you really need this, and if so please why ?

Because IDE_ARCH_OBSOLETE_INIT is not defined? [ See ide.h. ]

^ permalink raw reply	[flat|nested] 87+ messages in thread

* Re: [PATCH 1/14] FRV: Fujitsu FR-V CPU arch implementation
       [not found] <76b4a884-2c3c-11d9-91a1-0002b3163499@redhat.com>
                   ` (11 preceding siblings ...)
       [not found] ` <20040401020550.GG3150@beast>
@ 2004-11-02  0:21 ` Andrew Morton
  2004-11-02 23:46 ` [uClinux-dev] " Christoph Hellwig
                   ` (3 subsequent siblings)
  16 siblings, 0 replies; 87+ messages in thread
From: Andrew Morton @ 2004-11-02  0:21 UTC (permalink / raw)
  To: dhowells; +Cc: torvalds, davidm, linux-kernel, uclinux-dev

dhowells@redhat.com wrote:
>
> The attached patch provides an architecture implementation for the Fujitsu FR-V
> CPU series, configurably as Linux or uClinux.

Who developed this?

Who is maintaining it, and via what mailing list?

I didn't notice a MAINTAINERS record.  Was there one?

How widespread is the usage of this architecture?

Please convince us that this is not a piece of code which nobody will use
and which will fall into an unmaintained lump.

Thanks.

^ permalink raw reply	[flat|nested] 87+ messages in thread

* Re: [PATCH 12/14] FRV: Generate more useful debug info
  2004-11-01 19:30 ` [PATCH 12/14] FRV: Generate more useful debug info dhowells
@ 2004-11-02  0:29   ` Andrew Morton
  2004-11-02 11:21   ` David Howells
  1 sibling, 0 replies; 87+ messages in thread
From: Andrew Morton @ 2004-11-02  0:29 UTC (permalink / raw)
  To: dhowells; +Cc: torvalds, davidm, linux-kernel, uclinux-dev

dhowells@redhat.com wrote:
>
> The attached patch permits the generation of more useful debugging information
> by reducing the optimisation level and by telling the assembler to produce
> debug info too.

Generates rejects against Sam's tree and appears to be unrelated to FRV,
yes?

I'd prefer that this be worked through Sam's tree as a separate enhancement
please.


+ifdef CONFIG_DEBUG_INFO
+CFLAGS		+= -g -O1
+AFLAGS		+= -Wa,--gdwarf2
+ASFLAGS		+= -Wa,--gdwarf2
+else

Are you sure that all architectures want this?  And that their toolchains
will continue to work correctly?  And that it doesn't break older gcc's and
that kgdb will continue to work correctly, etc?

I'm not...

^ permalink raw reply	[flat|nested] 87+ messages in thread

* Re: [PATCH 10/14] FRV: Make calibrate_delay() optional
  2004-11-01 19:30 ` [PATCH 10/14] FRV: Make calibrate_delay() optional dhowells
  2004-11-02  0:06   ` john stultz
@ 2004-11-02  8:17   ` Andrew Morton
  2004-11-02  9:36   ` Christoph Hellwig
                     ` (2 subsequent siblings)
  4 siblings, 0 replies; 87+ messages in thread
From: Andrew Morton @ 2004-11-02  8:17 UTC (permalink / raw)
  To: dhowells; +Cc: torvalds, davidm, linux-kernel, uclinux-dev



init/main.c: In function `start_kernel':
init/main.c:494: warning: implicit declaration of function `calibrate_delay'

Move the calibrate_delay() prototype into linux/delay.h

Signed-off-by: Andrew Morton <akpm@osdl.org>
---

 25-akpm/include/asm-frv/delay.h    |    1 -
 25-akpm/include/asm-m32r/smp.h     |    1 -
 25-akpm/include/asm-x86_64/proto.h |    1 -
 25-akpm/include/linux/delay.h      |    1 +
 4 files changed, 1 insertion(+), 3 deletions(-)

diff -puN include/linux/delay.h~frv-make-calibrate_delay-optional-warning-fix include/linux/delay.h
--- 25/include/linux/delay.h~frv-make-calibrate_delay-optional-warning-fix	2004-11-01 23:20:40.736445936 -0800
+++ 25-akpm/include/linux/delay.h	2004-11-01 23:21:09.070138560 -0800
@@ -38,6 +38,7 @@ extern unsigned long loops_per_jiffy;
 #define ndelay(x)	udelay(((x)+999)/1000)
 #endif
 
+void calibrate_delay(void);
 void msleep(unsigned int msecs);
 unsigned long msleep_interruptible(unsigned int msecs);
 
diff -puN include/asm-m32r/smp.h~frv-make-calibrate_delay-optional-warning-fix include/asm-m32r/smp.h
--- 25/include/asm-m32r/smp.h~frv-make-calibrate_delay-optional-warning-fix	2004-11-01 23:20:40.752443504 -0800
+++ 25-akpm/include/asm-m32r/smp.h	2004-11-01 23:20:54.544346816 -0800
@@ -92,7 +92,6 @@ static __inline__ unsigned int num_booti
 }
 
 extern void smp_send_timer(void);
-extern void calibrate_delay(void);
 extern unsigned long send_IPI_mask_phys(cpumask_t, int, int);
 
 #endif	/* not __ASSEMBLY__ */
diff -puN include/asm-x86_64/proto.h~frv-make-calibrate_delay-optional-warning-fix include/asm-x86_64/proto.h
--- 25/include/asm-x86_64/proto.h~frv-make-calibrate_delay-optional-warning-fix	2004-11-01 23:20:40.769440920 -0800
+++ 25-akpm/include/asm-x86_64/proto.h	2004-11-01 23:21:13.197511104 -0800
@@ -25,7 +25,6 @@ extern void ia32_syscall(void);
 extern void ia32_cstar_target(void); 
 extern void ia32_sysenter_target(void); 
 
-extern void calibrate_delay(void);
 extern void cpu_idle(void);
 extern void config_acpi_tables(void);
 extern void ia32_syscall(void);
diff -puN include/asm-frv/delay.h~frv-make-calibrate_delay-optional-warning-fix include/asm-frv/delay.h
--- 25/include/asm-frv/delay.h~frv-make-calibrate_delay-optional-warning-fix	2004-11-01 23:20:40.785438488 -0800
+++ 25-akpm/include/asm-frv/delay.h	2004-11-01 23:21:19.580540736 -0800
@@ -18,7 +18,6 @@
  * delay loop - runs at __core_clock_speed_HZ / 2 [there are 2 insns in the loop]
  */
 extern unsigned long __delay_loops_MHz;
-extern void calibrate_delay(void);
 
 static inline void __delay(unsigned long loops)
 {
_


^ permalink raw reply	[flat|nested] 87+ messages in thread

* Re: [PATCH 8/14] FRV: GP-REL data support
  2004-11-01 19:30 ` [PATCH 8/14] FRV: GP-REL data support dhowells
@ 2004-11-02  8:18   ` Andrew Morton
  2004-11-02  9:48   ` Christoph Hellwig
  2004-11-02 16:34   ` David Howells
  2 siblings, 0 replies; 87+ messages in thread
From: Andrew Morton @ 2004-11-02  8:18 UTC (permalink / raw)
  To: dhowells; +Cc: torvalds, davidm, linux-kernel, uclinux-dev



security/security.c: In function `do_security_initcalls':
security/security.c:41: warning: assignment from incompatible pointer type
security/security.c:42: warning: comparison of distinct pointer types lacks a cast


Signed-off-by: Andrew Morton <akpm@osdl.org>
---

 25-akpm/security/security.c |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

diff -puN security/security.c~frv-gp-rel-data-support-fix security/security.c
--- 25/security/security.c~frv-gp-rel-data-support-fix	2004-11-01 23:25:22.304641064 -0800
+++ 25-akpm/security/security.c	2004-11-01 23:25:49.663481888 -0800
@@ -38,8 +38,8 @@ static inline int verify(struct security
 static void __init do_security_initcalls(void)
 {
 	initcall_t *call;
-	call = &__security_initcall_start;
-	while (call < &__security_initcall_end) {
+	call = __security_initcall_start;
+	while (call < __security_initcall_end) {
 		(*call) ();
 		call++;
 	}
_


^ permalink raw reply	[flat|nested] 87+ messages in thread

* Re: [PATCH 11/14] FRV: Add FDPIC ELF binary format driver
  2004-11-01 19:30 ` [PATCH 11/14] FRV: Add FDPIC ELF binary format driver dhowells
@ 2004-11-02  8:18   ` Andrew Morton
  2004-11-02 11:07   ` Andrew Morton
  2004-11-02 16:47   ` David Howells
  2 siblings, 0 replies; 87+ messages in thread
From: Andrew Morton @ 2004-11-02  8:18 UTC (permalink / raw)
  To: dhowells; +Cc: torvalds, davidm, linux-kernel, uclinux-dev



It doesn't compile on x86.

Signed-off-by: Andrew Morton <akpm@osdl.org>
---

 25-akpm/fs/Kconfig.binfmt |    1 +
 1 files changed, 1 insertion(+)

diff -puN fs/Kconfig.binfmt~frv-add-fdpic-elf-binary-format-driver-fix fs/Kconfig.binfmt
--- 25/fs/Kconfig.binfmt~frv-add-fdpic-elf-binary-format-driver-fix	2004-11-01 23:27:54.951435224 -0800
+++ 25-akpm/fs/Kconfig.binfmt	2004-11-01 23:28:38.771773520 -0800
@@ -26,6 +26,7 @@ config BINFMT_ELF
 config BINFMT_ELF_FDPIC
 	bool "Kernel support for FDPIC ELF binaries"
 	default y
+	depends on FRV
 	help
 	  ELF FDPIC binaries are based on ELF, but allow the individual load
 	  segments of a binary to be located in memory independently of each
_


^ permalink raw reply	[flat|nested] 87+ messages in thread

* Re: [PATCH 4/14] FRV: Bitops fixes
  2004-11-01 19:30 ` [PATCH 4/14] FRV: Bitops fixes dhowells
@ 2004-11-02  8:19   ` Andrew Morton
  0 siblings, 0 replies; 87+ messages in thread
From: Andrew Morton @ 2004-11-02  8:19 UTC (permalink / raw)
  To: dhowells; +Cc: torvalds, davidm, linux-kernel, uclinux-dev


I'm just going to drop this one.  Please test and fix
it on x86?

^ permalink raw reply	[flat|nested] 87+ messages in thread

* Re: [PATCH 7/14] FRV: GDB stub dependent additional BUG()'s
  2004-11-01 19:30 ` [PATCH 7/14] FRV: GDB stub dependent additional BUG()'s dhowells
@ 2004-11-02  9:34   ` Christoph Hellwig
  2004-11-02 16:09   ` David Howells
  1 sibling, 0 replies; 87+ messages in thread
From: Christoph Hellwig @ 2004-11-02  9:34 UTC (permalink / raw)
  To: dhowells; +Cc: torvalds, akpm, davidm, linux-kernel, uclinux-dev

On Mon, Nov 01, 2004 at 07:30:21PM +0000, dhowells@redhat.com wrote:
> The attached patch adds a couple of extra BUG() calls if a GDB stub is
> configured in the kernel. These allow the GDB stub to catch bad_page() and
> panic().
> 
> Signed-Off-By: dhowells@redhat.com
> ---
> diffstat frv-gdbstub-2610rc1bk10.diff
>  kernel/panic.c  |    3 +++
>  mm/page_alloc.c |    3 +++
>  2 files changed, 6 insertions(+)
> 
> diff -uNr /warthog/kernels/linux-2.6.10-rc1-bk10/kernel/panic.c linux-2.6.10-rc1-bk10-frv/kernel/panic.c
> --- /warthog/kernels/linux-2.6.10-rc1-bk10/kernel/panic.c	2004-10-27 17:32:38.000000000 +0100
> +++ linux-2.6.10-rc1-bk10-frv/kernel/panic.c	2004-11-01 11:47:05.162632657 +0000
> @@ -59,6 +59,9 @@
>  	vsnprintf(buf, sizeof(buf), fmt, args);
>  	va_end(args);
>  	printk(KERN_EMERG "Kernel panic - not syncing: %s\n",buf);
> +#ifdef CONFIG_GDBSTUB
> +	BUG();
> +#endif
>  	bust_spinlocks(0);
>  
>  #ifdef CONFIG_SMP

please avoid the ifdef mess and add some invoke_debugger or whatever macro
burried in some header.

> diff -uNr /warthog/kernels/linux-2.6.10-rc1-bk10/mm/page_alloc.c linux-2.6.10-rc1-bk10-frv/mm/page_alloc.c
> --- /warthog/kernels/linux-2.6.10-rc1-bk10/mm/page_alloc.c	2004-11-01 11:45:35.000000000 +0000
> +++ linux-2.6.10-rc1-bk10-frv/mm/page_alloc.c	2004-11-01 11:47:05.230626996 +0000
> @@ -83,6 +83,9 @@
>  		page->mapping, page_mapcount(page), page_count(page));
>  	printk(KERN_EMERG "Backtrace:\n");
>  	dump_stack();
> +#ifdef CONFIG_GDBSTUB
> +	BUG();
> +#endif

besides the ifdef mess this changes behaviour as it didn't BUG without,
please skip this hunk completely.


^ permalink raw reply	[flat|nested] 87+ messages in thread

* Re: [PATCH 10/14] FRV: Make calibrate_delay() optional
  2004-11-01 19:30 ` [PATCH 10/14] FRV: Make calibrate_delay() optional dhowells
  2004-11-02  0:06   ` john stultz
  2004-11-02  8:17   ` Andrew Morton
@ 2004-11-02  9:36   ` Christoph Hellwig
  2004-11-02 11:01   ` David Howells
  2004-11-02 16:29   ` David Howells
  4 siblings, 0 replies; 87+ messages in thread
From: Christoph Hellwig @ 2004-11-02  9:36 UTC (permalink / raw)
  To: dhowells; +Cc: torvalds, akpm, davidm, linux-kernel, uclinux-dev

> + *  GK 2/5/95  -  Changed to support mounting root fs via NFS
> + *  Added initrd & change_root: Werner Almesberger & Hans Lermen, Feb '96
> + *  Moan early if gcc is old, avoiding bogus kernels - Paul Gortmaker, May '96
> + *  Simplified starting of init:  Michael A. Griffith <grif@acm.org> 

this changelog certainly does not apply to the delay loop calibration.

>  lib-y := errno.o ctype.o string.o vsprintf.o cmdline.o \
>  	 bust_spinlocks.o rbtree.o radix-tree.o dump_stack.o \
>  	 kobject.o kref.o idr.o div64.o parser.o int_sqrt.o \
> -	 bitmap.o extable.o kobject_uevent.o find_next_bit.o
> +	 bitmap.o extable.o kobject_uevent.o find_next_bit.o \
> +	 calibrate.o

any reason it's in lib?  Better move this to kernel and properly compile
it conditionally.


^ permalink raw reply	[flat|nested] 87+ messages in thread

* Re: [PATCH 9/14] FRV: CONFIG_MMU fixes
  2004-11-01 19:30 ` [PATCH 9/14] FRV: CONFIG_MMU fixes dhowells
@ 2004-11-02  9:43   ` Christoph Hellwig
  2004-11-03 15:06   ` David Howells
  1 sibling, 0 replies; 87+ messages in thread
From: Christoph Hellwig @ 2004-11-02  9:43 UTC (permalink / raw)
  To: dhowells; +Cc: torvalds, akpm, davidm, linux-kernel, uclinux-dev

this is a real ifdef mess, let's sort this out better (aka on file
boundaries)

> 
> diff -uNr /warthog/kernels/linux-2.6.10-rc1-bk10/fs/proc/kcore.c linux-2.6.10-rc1-bk10-frv/fs/proc/kcore.c
> --- /warthog/kernels/linux-2.6.10-rc1-bk10/fs/proc/kcore.c	2004-09-16 12:06:14.000000000 +0100
> +++ linux-2.6.10-rc1-bk10-frv/fs/proc/kcore.c	2004-11-01 11:47:04.872656796 +0000
> @@ -344,6 +344,7 @@
>  		if (m == NULL) {
>  			if (clear_user(buffer, tsz))
>  				return -EFAULT;
> +#ifdef CONFIG_MMU
>  		} else if ((start >= VMALLOC_START) && (start < VMALLOC_END)) {
>  			char * elf_buf;
>  			struct vm_struct *m;
> @@ -389,6 +390,7 @@
>  				return -EFAULT;
>  			}
>  			kfree(elf_buf);
> +#endif

move this into a helper function that can be compiled away for the !MMU case

> --- /warthog/kernels/linux-2.6.10-rc1-bk10/fs/proc/proc_misc.c	2004-11-01 11:45:28.000000000 +0000
> +++ linux-2.6.10-rc1-bk10-frv/fs/proc/proc_misc.c	2004-11-01 11:47:04.873656713 +0000
> @@ -100,6 +100,7 @@
>  	unsigned long largest_chunk;
>  };
>  
> +#ifdef CONFIG_MMU
>  static struct vmalloc_info get_vmalloc_info(void)
>  {
>  	unsigned long prev_end = VMALLOC_START;
> @@ -129,6 +130,7 @@
>  	read_unlock(&vmlist_lock);
>  	return vmi;
>  }
> +#endif

move the whole function to a CONFIG_MMU-only file

>  static int uptime_read_proc(char *page, char **start, off_t off,
>  				 int count, int *eof, void *data)
> @@ -176,10 +178,16 @@
>  	allowed = ((totalram_pages - hugetlb_total_pages())
>  		* sysctl_overcommit_ratio / 100) + total_swap_pages;
>  
> +#ifdef CONFIG_MMU
>  	vmtot = (VMALLOC_END-VMALLOC_START)>>10;
>  	vmi = get_vmalloc_info();
>  	vmi.used >>= 10;
>  	vmi.largest_chunk >>= 10;
> +#else
> +	vmtot = 0;
> +	vmi.used = 0;
> +	vmi.largest_chunk = 0;
> +#endif

add a small helper for this.  In fact it's the only caller of get_vmalloc_info,
so that could be merged into the helper, ala:


void get_vmalloc_info(struct vmalloc_info vmi *vmi)
{
	/* contents of old get_vmalloc_info here */
	vmi->used = 0;
	vmi->largest_chunk = 0;
	}
}

and define both VMALLOC_START and VMALLOC_END to 0 for !MMU

> --- /warthog/kernels/linux-2.6.10-rc1-bk10/include/linux/mm.h	2004-11-01 11:45:33.371274107 +0000
> +++ linux-2.6.10-rc1-bk10-frv/include/linux/mm.h	2004-11-01 14:16:26.408497251 +0000
> @@ -58,6 +58,7 @@
>   * space that has a special rule for the page-fault handlers (ie a shared
>   * library, the executable area etc).
>   */
> +#ifdef CONFIG_MMU
>  struct vm_area_struct {
>  	struct mm_struct * vm_mm;	/* The address space we belong to. */
>  	unsigned long vm_start;		/* Our start address within vm_mm. */
> @@ -658,12 +688,14 @@

you're missing an endif.

>  	for (prio_tree_iter_init(iter, root, begin, end), vma = NULL;	\
>  		(vma = vma_prio_tree_next(vma, iter)); )
>  
> +#ifdef CONFIG_MMU
>  static inline void vma_nonlinear_insert(struct vm_area_struct *vma,
>  					struct list_head *list)
>  {
>  	vma->shared.vm_set.parent = NULL;
>  	list_add_tail(&vma->shared.vm_set.list, list);
>  }
> +#endif

I's day just move this out of line into a MMU-only file.

>  /* mmap.c */
>  extern void vma_adjust(struct vm_area_struct *vma, unsigned long start,
> @@ -780,6 +812,7 @@
>  }
>  #endif /* CONFIG_PROC_FS */
>  
> +#ifdef CONFIG_MMU
>  static inline void vm_stat_account(struct vm_area_struct *vma)
>  {
>  	__vm_stat_account(vma->vm_mm, vma->vm_flags, vma->vm_file,
> @@ -791,6 +824,7 @@
>  	__vm_stat_account(vma->vm_mm, vma->vm_flags, vma->vm_file,
>  							-vma_pages(vma));
>  }
> +#endif

or at least keep a single MMU ifdef block per file

> +#ifdef CONFIG_MMU
>  	pgtable_cache_init();
>  	prio_tree_init();
> +#endif

provide stubs please.  pgtable_cache_init is a per-arch things anyway.

> diff -uNr /warthog/kernels/linux-2.6.10-rc1-bk10/kernel/sysctl.c linux-2.6.10-rc1-bk10-frv/kernel/sysctl.c
> --- /warthog/kernels/linux-2.6.10-rc1-bk10/kernel/sysctl.c	2004-11-01 11:45:34.879148578 +0000
> +++ linux-2.6.10-rc1-bk10-frv/kernel/sysctl.c	2004-11-01 11:47:05.181631075 +0000
> @@ -755,6 +755,7 @@
>  		.strategy	= &sysctl_intvec,
>  		.extra1		= &zero,
>  	},
> +#ifdef CONFIG_MMU
>  	{
>  		.ctl_name	= VM_MAX_MAP_COUNT,
>  		.procname	= "max_map_count",
> @@ -763,6 +764,7 @@
>  		.mode		= 0644,
>  		.proc_handler	= &proc_dointvec
>  	},
> +#endif

just move the whole systctl registration into a MMU-only file

also please split this patch up into individual, small ones

^ permalink raw reply	[flat|nested] 87+ messages in thread

* Re: [PATCH 8/14] FRV: GP-REL data support
  2004-11-01 19:30 ` [PATCH 8/14] FRV: GP-REL data support dhowells
  2004-11-02  8:18   ` Andrew Morton
@ 2004-11-02  9:48   ` Christoph Hellwig
  2004-11-02 16:34   ` David Howells
  2 siblings, 0 replies; 87+ messages in thread
From: Christoph Hellwig @ 2004-11-02  9:48 UTC (permalink / raw)
  To: dhowells; +Cc: torvalds, akpm, davidm, linux-kernel, uclinux-dev

> --- /warthog/kernels/linux-2.6.10-rc1-bk10/include/linux/jiffies.h	2004-10-27 17:32:36.000000000 +0100
> +++ linux-2.6.10-rc1-bk10-frv/include/linux/jiffies.h	2004-11-01 11:47:05.112636819 +0000
> @@ -70,13 +70,23 @@
>  /* a value TUSEC for TICK_USEC (can be set bij adjtimex)		*/
>  #define TICK_USEC_TO_NSEC(TUSEC) (SH_DIV (TUSEC * USER_HZ * 1000, ACTHZ, 8))
>  
> +/* some arch's have a small-data section that can be accessed register-relative
> + * but that can only take up to, say, 4-byte variables. jiffies being part of
> + * an 8-byte variable may not be correctly accessed unless we force the issue
> + */
> +#ifdef CONFIG_FRV
> +#define __jiffy_data  __attribute__((section(".data")))
> +#else
> +#define __jiffy_data
> +#endif

please avoid per-arch ifdefs in common code, this needs to go into some asm/
header, or and __ARCH_HAVE_FOO ifdef.  Anyway, would doing this
unconditionally cause any problems?

> diff -uNr /warthog/kernels/linux-2.6.10-rc1-bk10/include/linux/linkage.h linux-2.6.10-rc1-bk10-frv/include/linux/linkage.h
> --- /warthog/kernels/linux-2.6.10-rc1-bk10/include/linux/linkage.h	2004-10-19 10:42:16.000000000 +0100
> +++ linux-2.6.10-rc1-bk10-frv/include/linux/linkage.h	2004-11-01 11:47:05.114636652 +0000
> @@ -44,4 +44,8 @@
>  #define fastcall
>  #endif
>  
> +#ifndef __ASSEMBLY__
> +extern const char linux_banner[];
> +#endif

totally wrong place.  this is not about linkage at all.


^ permalink raw reply	[flat|nested] 87+ messages in thread

* Re: [PATCH 14/14] FRV: Better mmap support in uClinux
  2004-11-01 19:30   ` [PATCH 14/14] FRV: Better mmap support in uClinux dhowells
@ 2004-11-02  9:54     ` Christoph Hellwig
  2004-11-02 16:43     ` David Howells
  1 sibling, 0 replies; 87+ messages in thread
From: Christoph Hellwig @ 2004-11-02  9:54 UTC (permalink / raw)
  To: dhowells; +Cc: torvalds, akpm, davidm, linux-kernel, uclinux-dev

> diff -uNr /warthog/kernels/linux-2.6.10-rc1-bk10/fs/proc/base.c linux-2.6.10-rc1-bk10-frv/fs/proc/base.c
> --- /warthog/kernels/linux-2.6.10-rc1-bk10/fs/proc/base.c	2004-10-27 17:32:31.000000000 +0100
> +++ linux-2.6.10-rc1-bk10-frv/fs/proc/base.c	2004-11-01 11:47:04.870656963 +0000
> @@ -220,6 +220,9 @@
>  
>  static int proc_exe_link(struct inode *inode, struct dentry **dentry, struct vfsmount **mnt)
>  {
> +#ifndef CONFIG_MMU
> +	struct mm_tblock_struct *tblock;
> +#endif
>  	struct vm_area_struct * vma;
>  	int result = -ENOENT;
>  	struct task_struct *task = proc_task(inode);
> @@ -228,17 +231,32 @@
>  	if (!mm)
>  		goto out;
>  	down_read(&mm->mmap_sem);
> +
> +#ifdef CONFIG_MMU
>  	vma = mm->mmap;
>  	while (vma) {
> -		if ((vma->vm_flags & VM_EXECUTABLE) && 
> -		    vma->vm_file) {
> -			*mnt = mntget(vma->vm_file->f_vfsmnt);
> -			*dentry = dget(vma->vm_file->f_dentry);
> -			result = 0;
> +		if ((vma->vm_flags & VM_EXECUTABLE) && vma->vm_file)
>  			break;
> -		}
>  		vma = vma->vm_next;
>  	}
> +#else
> +	tblock = mm->context.tblock;
> +	vma = NULL;
> +	while (tblock) {
> +		if ((tblock->vma->vm_flags & VM_EXECUTABLE) && tblock->vma->vm_file) {
> +			vma = tblock->vma;
> +			break;
> +		}
> +		tblock = tblock->next;
> +	}
> +#endif
> +
> +	if (vma) {
> +		*mnt = mntget(vma->vm_file->f_vfsmnt);
> +		*dentry = dget(vma->vm_file->f_dentry);
> +		result = 0;
> +	}
> +
>  	up_read(&mm->mmap_sem);
>  	mmput(mm);

please split this up into a mmu and a no-mmu function, in a mmu and nommu
file respectively.

>  #include <linux/pagemap.h>
>  #include <linux/slab.h>
>  #include <linux/vmalloc.h>
> +#include <linux/ptrace.h>
>  #include <linux/blkdev.h>
>  #include <linux/backing-dev.h>
>  #include <linux/syscalls.h>
> @@ -38,6 +40,10 @@
>  EXPORT_SYMBOL(sysctl_max_map_count);
>  EXPORT_SYMBOL(mem_map);
>  
> +/* list of shareable VMAs */
> +LIST_HEAD(shareable_vma_list);
> +DECLARE_RWSEM(shareable_vma_sem);

the should both be static

> +	if (flags & MAP_FIXED || addr) {
> +//		printk("can't do fixed-address/overlay mmap of RAM\n");

please avoid C++-style comments in core kernel code.

> diff -uNr /warthog/kernels/linux-2.6.10-rc1-bk10/mm/tiny-shmem.c linux-2.6.10-rc1-bk10-frv/mm/tiny-shmem.c
> --- /warthog/kernels/linux-2.6.10-rc1-bk10/mm/tiny-shmem.c	2004-10-27 17:32:38.000000000 +0100
> +++ linux-2.6.10-rc1-bk10-frv/mm/tiny-shmem.c	2004-11-01 14:24:49.419177784 +0000
> @@ -112,7 +112,9 @@
>  	if (vma->vm_file)
>  		fput(vma->vm_file);
>  	vma->vm_file = file;
> +#ifdef CONFIG_MMU
>  	vma->vm_ops = &generic_file_vm_ops;
> +#endif

please find a nice way to abstract this out without the ifdefs here.


^ permalink raw reply	[flat|nested] 87+ messages in thread

* Re: [PATCH 6/14] FRV: IDE fixes
  2004-11-01 22:53   ` Alan Cox
  2004-11-02  0:13     ` Bartlomiej Zolnierkiewicz
@ 2004-11-02 10:57     ` David Howells
  1 sibling, 0 replies; 87+ messages in thread
From: David Howells @ 2004-11-02 10:57 UTC (permalink / raw)
  To: Bartlomiej Zolnierkiewicz
  Cc: Alan Cox, torvalds, akpm, davidm, Linux Kernel Mailing List, uclinux-dev


> > Do you really need this, and if so please why ?
> 
> Because IDE_ARCH_OBSOLETE_INIT is not defined? [ See ide.h. ]

Exactly. Doing so is, apparently, obsolete. However, the IDE register pointers
aren't then initialised and the kernel crashes with a null pointer exception,
IIRC.

David

^ permalink raw reply	[flat|nested] 87+ messages in thread

* Re: [PATCH 10/14] FRV: Make calibrate_delay() optional
  2004-11-01 19:30 ` [PATCH 10/14] FRV: Make calibrate_delay() optional dhowells
                     ` (2 preceding siblings ...)
  2004-11-02  9:36   ` Christoph Hellwig
@ 2004-11-02 11:01   ` David Howells
  2004-11-02 16:29   ` David Howells
  4 siblings, 0 replies; 87+ messages in thread
From: David Howells @ 2004-11-02 11:01 UTC (permalink / raw)
  To: john stultz; +Cc: Linus Torvalds, Andrew Morton, davidm, lkml, uclinux-dev


> Just doing a quick skim, the patch looks good. Making a whole new file
> for just one function is a bit heavy handed, but I don't feel that code
> needed to be in main.c

Doing it this way means that we can use the linker's handling of archive
libraries to decide whether to actually use this function or not.

> My only nit would be to save the tabs and switch the code from:

And then it'll be argued that I should switch it back... Different people have
different opinions on how this should be arranged (of course, they're wrong if
they don't agree with my opinion:-).

David

^ permalink raw reply	[flat|nested] 87+ messages in thread

* Re: [PATCH 11/14] FRV: Add FDPIC ELF binary format driver
  2004-11-01 19:30 ` [PATCH 11/14] FRV: Add FDPIC ELF binary format driver dhowells
  2004-11-02  8:18   ` Andrew Morton
@ 2004-11-02 11:07   ` Andrew Morton
  2004-11-02 16:47   ` David Howells
  2 siblings, 0 replies; 87+ messages in thread
From: Andrew Morton @ 2004-11-02 11:07 UTC (permalink / raw)
  To: dhowells; +Cc: torvalds, davidm, linux-kernel, uclinux-dev


This patch breaks the x86_64 build in gruesome ways.

^ permalink raw reply	[flat|nested] 87+ messages in thread

* Re: [PATCH 12/14] FRV: Generate more useful debug info
  2004-11-01 19:30 ` [PATCH 12/14] FRV: Generate more useful debug info dhowells
  2004-11-02  0:29   ` Andrew Morton
@ 2004-11-02 11:21   ` David Howells
  2004-11-03  1:48     ` Linus Torvalds
                       ` (2 more replies)
  1 sibling, 3 replies; 87+ messages in thread
From: David Howells @ 2004-11-02 11:21 UTC (permalink / raw)
  To: Andrew Morton; +Cc: torvalds, davidm, linux-kernel, uclinux-dev


> Generates rejects against Sam's tree and appears to be unrelated to FRV,
> yes?

I know not Sam's tree.

It's a generic thing. "gcc -g" does not cause compiled .S files to include
debugging information, and -O1 optimised code is more debuggable than -O2
optimised code.

> Are you sure that all architectures want this?  And that their toolchains
> will continue to work correctly?  And that it doesn't break older gcc's and
> that kgdb will continue to work correctly, etc?

-O1: Dunno; if they don't they're buggy, and if they don't they're buggy.

-Wa,--gdwarf2: No, no and no.

I can move the -Wa flag back into the frv arch if you insist, but moving the
-O1 flag there is more tricky, since it'd then be overridden in master
Makefile.

David

^ permalink raw reply	[flat|nested] 87+ messages in thread

* Re: [PATCH 7/14] FRV: GDB stub dependent additional BUG()'s
  2004-11-01 19:30 ` [PATCH 7/14] FRV: GDB stub dependent additional BUG()'s dhowells
  2004-11-02  9:34   ` Christoph Hellwig
@ 2004-11-02 16:09   ` David Howells
  2004-11-03 10:39     ` Christoph Hellwig
  2004-11-03 13:41     ` David Howells
  1 sibling, 2 replies; 87+ messages in thread
From: David Howells @ 2004-11-02 16:09 UTC (permalink / raw)
  To: Christoph Hellwig; +Cc: torvalds, akpm, davidm, linux-kernel, uclinux-dev


> please avoid the ifdef mess and add some invoke_debugger or whatever macro
> burried in some header.

Having an invoke_debugger() function is not a bad idea; perhaps something like
this would do:

		vsnprintf(buf, sizeof(buf), fmt, args);
		va_end(args);
		printk(KERN_EMERG "Kernel panic - not syncing: %s\n",buf);
	+	invoke_debugger(SIGKILL);
		bust_spinlocks(0);

	 #ifdef CONFIG_SMP

What's the best way to add an invoke_debugger() function without having to
change every arch? #ifdef/#endif in kernel/panic.c maybe...

> besides the ifdef mess this changes behaviour as it didn't BUG without,
> please skip this hunk completely.

Why? If you've got a debugger attached, it'd seem reasonable to want it to
jump into the debugger in these circumstances; after all, your system is
probably stuffed after this point.

Perhaps I should make it do:

			page->mapping, page_mapcount(page), page_count(page));
		printk(KERN_EMERG "Backtrace:\n");
		dump_stack();
	+	invoke_debugger(SIGABRT);

Which the arch can then use or ignore as it wills; and the if the arch passes
it on to the debugger, the debugger can use or ignore as it wills.

David

^ permalink raw reply	[flat|nested] 87+ messages in thread

* Re: [PATCH 10/14] FRV: Make calibrate_delay() optional
  2004-11-01 19:30 ` [PATCH 10/14] FRV: Make calibrate_delay() optional dhowells
                     ` (3 preceding siblings ...)
  2004-11-02 11:01   ` David Howells
@ 2004-11-02 16:29   ` David Howells
  2004-11-03 10:40     ` Christoph Hellwig
  4 siblings, 1 reply; 87+ messages in thread
From: David Howells @ 2004-11-02 16:29 UTC (permalink / raw)
  To: Christoph Hellwig; +Cc: torvalds, akpm, davidm, linux-kernel, uclinux-dev


> this changelog certainly does not apply to the delay loop calibration.

I just duplicated the banners from init/main.c and tacked some extra bits on
the front.

> any reason it's in lib?  Better move this to kernel and properly compile
> it conditionally.

So that it get built and placed in an archive library, thus allowing the
linker to decide whether to include it or not, without having to use
conditional stuff and without having to change every other arch to enable it.

I suppose I could do something like this in init/Makefile:

	if ($(CONFIG_DISABLE_GENERIC_CALIBRATE_DELAY),y)
	obj-y += calibrate.o
	endif

That would allow me to avoid having to change all the archs.

David

^ permalink raw reply	[flat|nested] 87+ messages in thread

* Re: [PATCH 8/14] FRV: GP-REL data support
  2004-11-01 19:30 ` [PATCH 8/14] FRV: GP-REL data support dhowells
  2004-11-02  8:18   ` Andrew Morton
  2004-11-02  9:48   ` Christoph Hellwig
@ 2004-11-02 16:34   ` David Howells
  2004-11-03 10:42     ` Christoph Hellwig
  2 siblings, 1 reply; 87+ messages in thread
From: David Howells @ 2004-11-02 16:34 UTC (permalink / raw)
  To: Christoph Hellwig; +Cc: torvalds, akpm, davidm, linux-kernel, uclinux-dev


> > +#ifdef CONFIG_FRV
> > +#define __jiffy_data  __attribute__((section(".data")))
> > +#else
> > +#define __jiffy_data
> > +#endif
> 
> please avoid per-arch ifdefs in common code, this needs to go into some asm/
> header, or and __ARCH_HAVE_FOO ifdef.

You're advocating using an ifdef? I thought you hated the things...

I want to avoid changing every other arch.

> Anyway, would doing this unconditionally cause any problems?

Not as far as I know.

> > +#ifndef __ASSEMBLY__
> > +extern const char linux_banner[];
> > +#endif
> 
> totally wrong place.  this is not about linkage at all.

Actually, it's almost entirely about linkage:-) But in this case, you may be
right. Anyone any suggestions as to the right place for this? linux/kernel.h
perhaps?

David

^ permalink raw reply	[flat|nested] 87+ messages in thread

* Re: [PATCH 14/14] FRV: Better mmap support in uClinux
  2004-11-01 19:30   ` [PATCH 14/14] FRV: Better mmap support in uClinux dhowells
  2004-11-02  9:54     ` Christoph Hellwig
@ 2004-11-02 16:43     ` David Howells
  2004-11-03 10:45       ` Christoph Hellwig
  1 sibling, 1 reply; 87+ messages in thread
From: David Howells @ 2004-11-02 16:43 UTC (permalink / raw)
  To: Christoph Hellwig; +Cc: torvalds, akpm, davidm, linux-kernel, uclinux-dev


> > diff -uNr /warthog/kernels/linux-2.6.10-rc1-bk10/fs/proc/base.c linux-2.6.10-rc1-bk10-frv/fs/proc/base.c
> ...
> 
> please split this up into a mmu and a no-mmu function, in a mmu and nommu
> file respectively.

What would you say to this function being moved into the mm/ directory?
Perhaps in mm/proc.c.

> > +/* list of shareable VMAs */
> > +LIST_HEAD(shareable_vma_list);
> > +DECLARE_RWSEM(shareable_vma_sem);
> 
> the should both be static

I'm intending to do a /proc file to allow this list to be viewed.

> > +	if (flags & MAP_FIXED || addr) {
> > +//		printk("can't do fixed-address/overlay mmap of RAM\n");
> 
> please avoid C++-style comments in core kernel code.

I should make this #ifdef'd on a CONFIG_DEBUG_ option.

> > +#ifdef CONFIG_MMU
> >  	vma->vm_ops = &generic_file_vm_ops;
> > +#endif
> 
> please find a nice way to abstract this out without the ifdefs here.

Why? The #ifdef tells you exactly what you need to know. This _is_ the right
way to do it. Doing otherwise just makes the code less obvious. However, if
you can come up with a better way, I'll review the patch for you.

David

^ permalink raw reply	[flat|nested] 87+ messages in thread

* Re: [PATCH 11/14] FRV: Add FDPIC ELF binary format driver
  2004-11-01 19:30 ` [PATCH 11/14] FRV: Add FDPIC ELF binary format driver dhowells
  2004-11-02  8:18   ` Andrew Morton
  2004-11-02 11:07   ` Andrew Morton
@ 2004-11-02 16:47   ` David Howells
  2004-11-02 17:23     ` Andi Kleen
  2 siblings, 1 reply; 87+ messages in thread
From: David Howells @ 2004-11-02 16:47 UTC (permalink / raw)
  To: Andrew Morton, ak; +Cc: torvalds, davidm, linux-kernel, uclinux-dev


> This patch breaks the x86_64 build in gruesome ways.

So I see. It seems x86_64 overrides the setup_arg_pages() function in the IA32
emulator.

Andi: Would you be willing to take an arch patch to change this? Or would you
rather fix it yourself?

David

^ permalink raw reply	[flat|nested] 87+ messages in thread

* Re: [PATCH 11/14] FRV: Add FDPIC ELF binary format driver
  2004-11-02 16:47   ` David Howells
@ 2004-11-02 17:23     ` Andi Kleen
  0 siblings, 0 replies; 87+ messages in thread
From: Andi Kleen @ 2004-11-02 17:23 UTC (permalink / raw)
  To: David Howells
  Cc: Andrew Morton, ak, torvalds, davidm, linux-kernel, uclinux-dev

On Tue, Nov 02, 2004 at 04:47:12PM +0000, David Howells wrote:
> 
> > This patch breaks the x86_64 build in gruesome ways.
> 
> So I see. It seems x86_64 overrides the setup_arg_pages() function in the IA32
> emulator.
> 
> Andi: Would you be willing to take an arch patch to change this? Or would you
> rather fix it yourself?

Just submit a patch to fix it together with your patch. Also you
should use grep -r, there are other architectures who do 32bit ELF
emulation in the same way.

-Andi

^ permalink raw reply	[flat|nested] 87+ messages in thread

* Re: [uClinux-dev] [PATCH 2/14] FRV: Fujitsu FR-V arch include files
       [not found] ` <200411011930.iA1JUKFH023161@warthog.cambridge.redhat.com>
@ 2004-11-02 23:24   ` Christoph Hellwig
  2004-11-03 17:26   ` David Howells
  1 sibling, 0 replies; 87+ messages in thread
From: Christoph Hellwig @ 2004-11-02 23:24 UTC (permalink / raw)
  To: uClinux development list; +Cc: torvalds, akpm, davidm, linux-kernel

> --- /warthog/kernels/linux-2.6.10-rc1-bk10/include/asm-frv/a.out.h	1970-01-01 01:00:00.000000000 +0100
> +++ linux-2.6.10-rc1-bk10-frv/include/asm-frv/a.out.h	2004-11-01 11:47:04.877656380 +0000

do you really want to support a.out binaries on a new port?

> --- /warthog/kernels/linux-2.6.10-rc1-bk10/include/asm-frv/bootinfo.h	1970-01-01 01:00:00.000000000 +0100
> +++ linux-2.6.10-rc1-bk10-frv/include/asm-frv/bootinfo.h	2004-11-01 11:47:04.888655465 +0000
> @@ -0,0 +1,2 @@
> +
> +/* Nothing for m68knommu */

did you just copy & paste this maybe?

> diff -uNr /warthog/kernels/linux-2.6.10-rc1-bk10/include/asm-frv/errno.h linux-2.6.10-rc1-bk10-frv/include/asm-frv/errno.h
> --- /warthog/kernels/linux-2.6.10-rc1-bk10/include/asm-frv/errno.h	1970-01-01 01:00:00.000000000 +0100
> +++ linux-2.6.10-rc1-bk10-frv/include/asm-frv/errno.h	2004-11-01 11:47:04.915653217 +0000
> @@ -0,0 +1,133 @@
> +#ifndef _ASM_ERRNO_H
> +#define _ASM_ERRNO_H
> +
> +#define	EPERM		 1	/* Operation not permitted */

please use the asm-generic/ errno defintions for new ports.

> +#define hardirq_count()	(preempt_count() & HARDIRQ_MASK)
> +#define softirq_count()	(preempt_count() & SOFTIRQ_MASK)
> +#define irq_count()	(preempt_count() & (HARDIRQ_MASK | SOFTIRQ_MASK))

this moved out of arch code long ago.

> + * Are we doing bottom half or hardware interrupt processing?
> + * Are we in a softirq context? Interrupt context?
> + */
> +#define in_irq()		(hardirq_count())
> +#define in_softirq()		(softirq_count())
> +#define in_interrupt()		(irq_count())
> +
> +#define hardirq_trylock()	(!in_interrupt())
> +#define hardirq_endlock()	do { } while (0)

dito..

> +#ifdef CONFIG_PREEMPT
> +# include <linux/smp_lock.h>
> +# define in_atomic()		((preempt_count() & ~PREEMPT_ACTIVE) != kernel_locked())
> +# define IRQ_EXIT_OFFSET	(HARDIRQ_OFFSET-1)
> +#else
> +# define in_atomic()		(preempt_count() != 0)
> +# define IRQ_EXIT_OFFSET	HARDIRQ_OFFSET
> +#endif

dito..

> +#ifndef CONFIG_SMP
> +#define synchronize_irq(irq)	barrier()
> +#else
> +#error SMP not available on FR-V
> +#endif /* CONFIG_SMP */

dito..

> +#endif /* _ASM_IRQ_ROUTING_H */
> diff -uNr /warthog/kernels/linux-2.6.10-rc1-bk10/include/asm-frv/keyboard.h linux-2.6.10-rc1-bk10-frv/include/asm-frv/keyboard.h
> --- /warthog/kernels/linux-2.6.10-rc1-bk10/include/asm-frv/keyboard.h	1970-01-01 01:00:00.000000000 +0100
> +++ linux-2.6.10-rc1-bk10-frv/include/asm-frv/keyboard.h	2004-11-01 11:47:04.935651552 +0000

<asm/keyboard.h> isn't needed anymore in 2.6

> --- /warthog/kernels/linux-2.6.10-rc1-bk10/include/asm-frv/linux_logo.h	1970-01-01 01:00:00.000000000 +0100
> +++ linux-2.6.10-rc1-bk10-frv/include/asm-frv/linux_logo.h	2004-11-01 11:47:04.947650553 +0000

dito for <asm/linux_logo.h>

> +//#define MAP_NR(addr)		(((unsigned long)(addr) - PAGE_OFFSET) >> PAGE_SHIFT)
> +//#define VALID_PAGE(page)	((page - mem_map) < max_mapnr)

this has no place in a 2.6 port, not even commented out..

> + * and that's it. There's no excuse for not highmem enabling YOUR driver. /jens
> + */
> +struct scatterlist {
> +	char		*address;	/* Location data is to be transferred to, NULL for

In 2.6 struct scatterlist should not have an address member.

> +/* format on the sun3 is similar, but bits 30, 31 are set to zero and all
> +   others are reduced by 2. --m */
> +
> +#ifndef CONFIG_SUN3
> +#define SHM_ID_SHIFT	9
> +#else
> +#define SHM_ID_SHIFT	7
> +#endif

WTF?

> --- /warthog/kernels/linux-2.6.10-rc1-bk10/include/asm-frv/smplock.h	1970-01-01 01:00:00.000000000 +0100
> +++ linux-2.6.10-rc1-bk10-frv/include/asm-frv/smplock.h	2004-11-01 11:47:05.033643395 +0000

<asm/smplock.h> is long gone.

> +struct __old_kernel_stat {
> +	unsigned short st_dev;
> +	unsigned short st_ino;
> +	unsigned short st_mode;
> +	unsigned short st_nlink;
> +	unsigned short st_uid;
> +	unsigned short st_gid;
> +	unsigned short st_rdev;
> +	unsigned long  st_size;
> +	unsigned long  st_atime;
> +	unsigned long  st_mtime;
> +	unsigned long  st_ctime;
> +};

no need to implement an old stat in a new port.

> + */
> +#define kernel_termios_to_user_termio(termio, termios) \
> +({ \
> +	put_user((termios)->c_iflag, &(termio)->c_iflag); \
> +	put_user((termios)->c_oflag, &(termio)->c_oflag); \
> +	put_user((termios)->c_cflag, &(termio)->c_cflag); \
> +	put_user((termios)->c_lflag, &(termio)->c_lflag); \
> +	put_user((termios)->c_line,  &(termio)->c_line); \
> +	copy_to_user((termio)->c_cc, (termios)->c_cc, NCC); \

no error checking at all?

> +#ifdef __KERNEL__
> +#define __ARCH_WANT_IPC_PARSE_VERSION
> +/* #define __ARCH_WANT_OLD_READDIR */
> +#define __ARCH_WANT_OLD_STAT
> +#define __ARCH_WANT_STAT64
> +#define __ARCH_WANT_SYS_ALARM
> +/* #define __ARCH_WANT_SYS_GETHOSTNAME */
> +#define __ARCH_WANT_SYS_PAUSE
> +/* #define __ARCH_WANT_SYS_SGETMASK */
> +/* #define __ARCH_WANT_SYS_SIGNAL */
> +#define __ARCH_WANT_SYS_TIME
> +#define __ARCH_WANT_SYS_UTIME
> +#define __ARCH_WANT_SYS_WAITPID
> +#define __ARCH_WANT_SYS_SOCKETCALL
> +#define __ARCH_WANT_SYS_FADVISE64
> +#define __ARCH_WANT_SYS_GETPGRP
> +#define __ARCH_WANT_SYS_LLSEEK
> +#define __ARCH_WANT_SYS_NICE
> +/* #define __ARCH_WANT_SYS_OLD_GETRLIMIT */
> +#define __ARCH_WANT_SYS_OLDUMOUNT
> +/* #define __ARCH_WANT_SYS_SIGPENDING */
> +#define __ARCH_WANT_SYS_SIGPROCMASK
> +#define __ARCH_WANT_SYS_RT_SIGACTION
> +#endif

most of this should go.  new architectures are not supposed to implement
obsolete syscalls.

> diff -uNr /warthog/kernels/linux-2.6.10-rc1-bk10/include/linux/swap.h linux-2.6.10-rc1-bk10-frv/include/linux/swap.h
> --- /warthog/kernels/linux-2.6.10-rc1-bk10/include/linux/swap.h	2004-10-27 17:32:36.000000000 +0100
> +++ linux-2.6.10-rc1-bk10-frv/include/linux/swap.h	2004-11-01 11:47:05.131635237 +0000
> @@ -7,6 +7,7 @@
>  #include <linux/mmzone.h>
>  #include <linux/list.h>
>  #include <linux/sched.h>
> +#include <linux/pagemap.h>

this creates too much of an include file mess.  Just include it in the
few files that need it for !MMU


^ permalink raw reply	[flat|nested] 87+ messages in thread

* Re: [uClinux-dev] [PATCH 1/14] FRV: Fujitsu FR-V CPU arch implementation
       [not found] <76b4a884-2c3c-11d9-91a1-0002b3163499@redhat.com>
                   ` (12 preceding siblings ...)
  2004-11-02  0:21 ` [PATCH 1/14] FRV: Fujitsu FR-V CPU arch implementation Andrew Morton
@ 2004-11-02 23:46 ` Christoph Hellwig
       [not found] ` <200411011930.iA1JUKFH023161@warthog.cambridge.redhat.com>
                   ` (2 subsequent siblings)
  16 siblings, 0 replies; 87+ messages in thread
From: Christoph Hellwig @ 2004-11-02 23:46 UTC (permalink / raw)
  To: uClinux development list; +Cc: torvalds, akpm, davidm, linux-kernel

> --- /warthog/kernels/linux-2.6.10-rc1-bk10/arch/frv/boot/install.sh	1970-01-01 01:00:00.000000000 +0100
> +++ linux-2.6.10-rc1-bk10-frv/arch/frv/boot/install.sh	2004-11-01 11:47:04.635676524 +0000

please don't copy the horrible boot decompressor cludges to new arches.
Why can't your loader support vmlinux.gz files for a new port?

> diff -uNr /warthog/kernels/linux-2.6.10-rc1-bk10/arch/frv/kernel/irq.c linux-2.6.10-rc1-bk10-frv/arch/frv/kernel/irq.c
> --- /warthog/kernels/linux-2.6.10-rc1-bk10/arch/frv/kernel/irq.c	1970-01-01 01:00:00.000000000 +0100
> +++ linux-2.6.10-rc1-bk10-frv/arch/frv/kernel/irq.c	2004-11-01 14:09:42.825602343 +0000
> @@ -0,0 +1,1062 @@
> +/* irq.c: FRV IRQ handling
> + *
> + * Copyright (C) 2003, 2004 Red Hat, Inc. All Rights Reserved.
> + * Written by David Howells (dhowells@redhat.com)
> + *
> + * 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.
> + */
> +
> +/*
> + * (mostly architecture independent, will move to kernel/irq.c in 2.5.)
> + *
> + * IRQs are in fact implemented a bit like signal handlers for the kernel.
> + * Naturally it's not a 1:1 relation, but there are similarities.
> + */

Please use the generic kernel/irq/* code.

> +void __global_cli(void)
> +{
> +	unsigned int flags;
> +
> +	__save_flags(flags);
> +	if (flags & (1 << EFLAGS_IF_SHIFT)) {
> +		int cpu;
> +		__cli();
> +		cpu = smp_processor_id();
> +		if (!local_irq_count(cpu))
> +			get_irqlock(cpu);
> +	}
> +}

HTF did you managed to get this into a 2.6.x code submission?

> --- /warthog/kernels/linux-2.6.10-rc1-bk10/arch/frv/kernel/nmi.c	1970-01-01 01:00:00.000000000 +0100
> +++ linux-2.6.10-rc1-bk10-frv/arch/frv/kernel/nmi.c	2004-11-01 11:47:04.683672529 +0000
> @@ -0,0 +1,42 @@
> +/* nmi.c: FRV NMI handler (level 15 external interrupt)
> + *
> + * Copyright (C) 2003 Red Hat, Inc. All Rights Reserved.
> + * Written by David Howells (dhowells@redhat.com)
> + *
> + * 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.
> + */
> +
> +#include <linux/config.h>
> +#include <linux/ptrace.h>
> +#include <linux/errno.h>
> +#include <linux/signal.h>
> +#include <linux/sched.h>
> +#include <linux/ioport.h>
> +#include <linux/interrupt.h>
> +#include <linux/timex.h>
> +#include <linux/smp_lock.h>
> +#include <linux/init.h>
> +#include <linux/kernel_stat.h>
> +#include <linux/irq.h>
> +#include <linux/proc_fs.h>
> +
> +#include <asm/atomic.h>
> +#include <asm/io.h>
> +#include <asm/smp.h>
> +#include <asm/system.h>
> +#include <asm/bitops.h>
> +#include <asm/pgalloc.h>
> +#include <asm/delay.h>
> +#include <asm/irq.h>
> +#include <asm/gdb-stub.h>
> +
> +/*****************************************************************************/
> +/*
> + * deal with the NMI
> + */
> +asmlinkage void do_NMI(void)
> +{
> +} /* end do_IRQ() */

I can't see this beeing called from generic code ever, why do you
implement it?

> +#
> +# If you want the kernel build to build modules outside of the tree
> +# then define this and pass it to the main linux makefile
> +#
> +ifdef EXTRA_MODULE_DIRS
> +SUBDIRS += $(EXTRA_MODULE_DIRS)
> +endif

this is not something that belongs into arch code.

> +#ifdef CONFIG_MMU
> +
> +void *dma_alloc_coherent(struct device *hwdev, size_t size, dma_addr_t *dma_handle, int flag)
> +{
> +	void *ret;
> +	int gfp = GFP_ATOMIC;

the last argument is the gfp mask.

> +	if (hwdev == NULL || hwdev->coherent_dma_mask < 0xffffffff)
> +		gfp |= GFP_DMA;

does GFP_DMA really hae the same meaning as on i386 here?

> --- /warthog/kernels/linux-2.6.10-rc1-bk10/fs/proc/array.c	2004-10-27 17:32:31.000000000 +0100
> +++ linux-2.6.10-rc1-bk10-frv/fs/proc/array.c	2004-11-01 11:47:04.866657296 +0000
> @@ -289,6 +289,9 @@
>  	buffer = task_state(task, buffer);
>   
>  	if (mm) {
> +#if defined(CONFIG_FRV) && defined(CONFIG_MMU)
> +		buffer = proc_pid_status_frv_cxnr(mm, buffer);
> +#endif
>  		buffer = task_mem(mm, buffer);
>  		mmput(mm);

Don't mess with per-arch fields in common procfs files.  And don't ever
try to hide such a change again after an enormous patch otherwise only
adding new code.


^ permalink raw reply	[flat|nested] 87+ messages in thread

* Re: [PATCH 12/14] FRV: Generate more useful debug info
  2004-11-02 11:21   ` David Howells
@ 2004-11-03  1:48     ` Linus Torvalds
  2004-11-03  1:52       ` Linus Torvalds
  2004-11-03 13:38       ` David Howells
  2004-11-12 14:57     ` Daniel Jacobowitz
  2004-11-12 15:15     ` David Howells
  2 siblings, 2 replies; 87+ messages in thread
From: Linus Torvalds @ 2004-11-03  1:48 UTC (permalink / raw)
  To: David Howells; +Cc: Andrew Morton, davidm, linux-kernel, uclinux-dev



On Tue, 2 Nov 2004, David Howells wrote:
> 
> -O1: Dunno; if they don't they're buggy, and if they don't they're buggy.

No. It used to be that inlining was only done with -O2 if I remember 
correctly. The kernel _needed_ to be compiled with -O2.

That may not be true today, but what is true is that -O1 is not a light 
thing to just do.

		Linus 

^ permalink raw reply	[flat|nested] 87+ messages in thread

* Re: [PATCH 12/14] FRV: Generate more useful debug info
  2004-11-03  1:48     ` Linus Torvalds
@ 2004-11-03  1:52       ` Linus Torvalds
  2004-11-03 20:40         ` Florian Weimer
  2004-11-03 13:38       ` David Howells
  1 sibling, 1 reply; 87+ messages in thread
From: Linus Torvalds @ 2004-11-03  1:52 UTC (permalink / raw)
  To: David Howells; +Cc: Andrew Morton, davidm, linux-kernel, uclinux-dev



On Tue, 2 Nov 2004, Linus Torvalds wrote:
> 
> That may not be true today, but what is true is that -O1 is not a light 
> thing to just do.

And btw, in some cases the inlining used to be a correcness issue, so no,
just making it be "static inline" doesn't necessarily fix the basic issue. 

Again, whether that is necessarily true today is not something I'm ready 
to guarantee one way or the other, so this is just an observation that 
things can be a lot more subtle than you seem to assume.

		Linus

^ permalink raw reply	[flat|nested] 87+ messages in thread

* Re: [PATCH 7/14] FRV: GDB stub dependent additional BUG()'s
  2004-11-02 16:09   ` David Howells
@ 2004-11-03 10:39     ` Christoph Hellwig
  2004-11-03 13:41     ` David Howells
  1 sibling, 0 replies; 87+ messages in thread
From: Christoph Hellwig @ 2004-11-03 10:39 UTC (permalink / raw)
  To: David Howells
  Cc: Christoph Hellwig, torvalds, akpm, davidm, linux-kernel, uclinux-dev

On Tue, Nov 02, 2004 at 04:09:58PM +0000, David Howells wrote:
> What's the best way to add an invoke_debugger() function without having to
> change every arch? #ifdef/#endif in kernel/panic.c maybe...

just put it in every arch.  Or even better drop your gdbstub for now
and integrate it with the common kgdb code in -mm.

Actually I think you should do thata anyway.

> Why? If you've got a debugger attached, it'd seem reasonable to want it to
> jump into the debugger in these circumstances; after all, your system is
> probably stuffed after this point.

Because it's not fatal without your debugger, so it shouldn't magically
get fatal.  If you think this is fatal convience Andrew to add a BUG() here.


^ permalink raw reply	[flat|nested] 87+ messages in thread

* Re: [PATCH 10/14] FRV: Make calibrate_delay() optional
  2004-11-02 16:29   ` David Howells
@ 2004-11-03 10:40     ` Christoph Hellwig
  0 siblings, 0 replies; 87+ messages in thread
From: Christoph Hellwig @ 2004-11-03 10:40 UTC (permalink / raw)
  To: David Howells
  Cc: Christoph Hellwig, torvalds, akpm, davidm, linux-kernel, uclinux-dev

On Tue, Nov 02, 2004 at 04:29:39PM +0000, David Howells wrote:
> 
> > this changelog certainly does not apply to the delay loop calibration.
> 
> I just duplicated the banners from init/main.c and tacked some extra bits on
> the front.
> 
> > any reason it's in lib?  Better move this to kernel and properly compile
> > it conditionally.
> 
> So that it get built and placed in an archive library, thus allowing the
> linker to decide whether to include it or not, without having to use
> conditional stuff and without having to change every other arch to enable it.
> 
> I suppose I could do something like this in init/Makefile:
> 
> 	if ($(CONFIG_DISABLE_GENERIC_CALIBRATE_DELAY),y)
> 	obj-y += calibrate.o
> 	endif
> 
> That would allow me to avoid having to change all the archs.

Use CONFIG_CALIBRATE_DELAY and add it to all other ports.  Remember Linux
is not about least intrusive changes but about what's easiest maintainable.


^ permalink raw reply	[flat|nested] 87+ messages in thread

* Re: [PATCH 8/14] FRV: GP-REL data support
  2004-11-02 16:34   ` David Howells
@ 2004-11-03 10:42     ` Christoph Hellwig
  0 siblings, 0 replies; 87+ messages in thread
From: Christoph Hellwig @ 2004-11-03 10:42 UTC (permalink / raw)
  To: David Howells
  Cc: Christoph Hellwig, torvalds, akpm, davidm, linux-kernel, uclinux-dev

On Tue, Nov 02, 2004 at 04:34:01PM +0000, David Howells wrote:
> 
> > > +#ifdef CONFIG_FRV
> > > +#define __jiffy_data  __attribute__((section(".data")))
> > > +#else
> > > +#define __jiffy_data
> > > +#endif
> > 
> > please avoid per-arch ifdefs in common code, this needs to go into some asm/
> > header, or and __ARCH_HAVE_FOO ifdef.
> 
> You're advocating using an ifdef? I thought you hated the things...

You have an ifdef already.  Using the right symbol at least avoids this
into turning to

#if define(foo) || defined(bar) || (defined(baz) && !defined(foobar))

> I want to avoid changing every other arch.
> 
> > Anyway, would doing this unconditionally cause any problems?
> 
> Not as far as I know.

So go for that.

> > > +#ifndef __ASSEMBLY__
> > > +extern const char linux_banner[];
> > > +#endif
> > 
> > totally wrong place.  this is not about linkage at all.
> 
> Actually, it's almost entirely about linkage:-) But in this case, you may be
> right.

So how is the linux banner about linkage?

> Anyone any suggestions as to the right place for this? linux/kernel.h
> perhaps?

Maybe.

^ permalink raw reply	[flat|nested] 87+ messages in thread

* Re: [PATCH 14/14] FRV: Better mmap support in uClinux
  2004-11-02 16:43     ` David Howells
@ 2004-11-03 10:45       ` Christoph Hellwig
  0 siblings, 0 replies; 87+ messages in thread
From: Christoph Hellwig @ 2004-11-03 10:45 UTC (permalink / raw)
  To: David Howells
  Cc: Christoph Hellwig, torvalds, akpm, davidm, linux-kernel, uclinux-dev

On Tue, Nov 02, 2004 at 04:43:25PM +0000, David Howells wrote:
> 
> > > diff -uNr /warthog/kernels/linux-2.6.10-rc1-bk10/fs/proc/base.c linux-2.6.10-rc1-bk10-frv/fs/proc/base.c
> > ...
> > 
> > please split this up into a mmu and a no-mmu function, in a mmu and nommu
> > file respectively.
> 
> What would you say to this function being moved into the mm/ directory?
> Perhaps in mm/proc.c.

I think it should stay in procfs.  And we already have an mmu and a no-mmu
function there.

> > > +/* list of shareable VMAs */
> > > +LIST_HEAD(shareable_vma_list);
> > > +DECLARE_RWSEM(shareable_vma_sem);
> > 
> > the should both be static
> 
> I'm intending to do a /proc file to allow this list to be viewed.

So provide a proper iterator once you do that.  Global lists are very
bad coding style.

> > >  	vma->vm_ops = &generic_file_vm_ops;
> > > +#endif
> > 
> > please find a nice way to abstract this out without the ifdefs here.
> 
> Why? The #ifdef tells you exactly what you need to know. This _is_ the right
> way to do it. Doing otherwise just makes the code less obvious. However, if
> you can come up with a better way, I'll review the patch for you.

shmem_zero_setup is already duplicated in shmem.c and tiny-shmem.c just
with different vm_ops.

So yes, please provide a set_devzero_vmops macro that is NULL for no-MMU
ports and allows to merge the existing two copies of the function.


^ permalink raw reply	[flat|nested] 87+ messages in thread

* Re: [PATCH 12/14] FRV: Generate more useful debug info
  2004-11-03  1:48     ` Linus Torvalds
  2004-11-03  1:52       ` Linus Torvalds
@ 2004-11-03 13:38       ` David Howells
  2004-11-03 15:32         ` Linus Torvalds
  1 sibling, 1 reply; 87+ messages in thread
From: David Howells @ 2004-11-03 13:38 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: Andrew Morton, davidm, linux-kernel, uclinux-dev


> > That may not be true today, but what is true is that -O1 is not a light 
> > thing to just do.
> 
> And btw, in some cases the inlining used to be a correcness issue, so no,
> just making it be "static inline" doesn't necessarily fix the basic issue. 
> 
> Again, whether that is necessarily true today is not something I'm ready 
> to guarantee one way or the other, so this is just an observation that 
> things can be a lot more subtle than you seem to assume.

I've been able to run a range of 2.4 and 2.6 kernels compiled with -O1 and
without any -O flag at all, and with all "extern inline" changed to "static
inline". It doesn't seem to be a problem on i386, x86_64, frv (which I'm
trying to add) and am33 (which I haven't tried to add yet).

When debugging, -O2 makes for a real problem because, amongst other
inconvenient things, it enables the explicit parallelisation features that frv
cpus support.

Would you object to making it possible for the arch to override the
optimisation level when debugging?

David

^ permalink raw reply	[flat|nested] 87+ messages in thread

* Re: [PATCH 7/14] FRV: GDB stub dependent additional BUG()'s
  2004-11-02 16:09   ` David Howells
  2004-11-03 10:39     ` Christoph Hellwig
@ 2004-11-03 13:41     ` David Howells
  1 sibling, 0 replies; 87+ messages in thread
From: David Howells @ 2004-11-03 13:41 UTC (permalink / raw)
  To: Christoph Hellwig; +Cc: torvalds, akpm, davidm, linux-kernel, uclinux-dev


> just put it in every arch.  Or even better drop your gdbstub for now
> and integrate it with the common kgdb code in -mm.

Ummm... what common kgdb code? It seems to be almost all per-arch anyway.

Besides, on this arch the gdbstub runs in a different CPU mode from the rest
of the kernel, which makes life more interesting.

> Because it's not fatal without your debugger, so it shouldn't magically
> get fatal.  If you think this is fatal convience Andrew to add a BUG() here.

It could be made contingent on a debugger being attached rather than being a
mandatory BUG.

David

^ permalink raw reply	[flat|nested] 87+ messages in thread

* Re: [PATCH 9/14] FRV: CONFIG_MMU fixes
  2004-11-01 19:30 ` [PATCH 9/14] FRV: CONFIG_MMU fixes dhowells
  2004-11-02  9:43   ` Christoph Hellwig
@ 2004-11-03 15:06   ` David Howells
  2004-11-03 15:13     ` Christoph Hellwig
  2004-11-03 15:30     ` David Howells
  1 sibling, 2 replies; 87+ messages in thread
From: David Howells @ 2004-11-03 15:06 UTC (permalink / raw)
  To: Christoph Hellwig; +Cc: torvalds, akpm, davidm, linux-kernel, uclinux-dev


> > +++ linux-2.6.10-rc1-bk10-frv/fs/proc/kcore.c	2004-11-01 11:47:04.872656796 +0000
> > @@ -344,6 +344,7 @@
> >  		if (m == NULL) {
> >  			if (clear_user(buffer, tsz))
> >  				return -EFAULT;
> > +#ifdef CONFIG_MMU
>  		} else if ((start >= VMALLOC_START) && (start < VMALLOC_END)) {
> ...
> > +#endif
> 
> move this into a helper function that can be compiled away for the !MMU case

That won't work. The else-if clause has to be within the context of the parent
function in which it now resides.

It might actually be better to make /proc/kcore conditional on CONFIG_MMU.

> > +#ifdef CONFIG_MMU
> >  static struct vmalloc_info get_vmalloc_info(void)
> ...
> > +#endif
> 
> move the whole function to a CONFIG_MMU-only file

No. The compiler can, if it wishes, inline this function as it is now. Putting
it in a separate file removes that option.

> add a small helper for this.  In fact it's the only caller of
> get_vmalloc_info, so that could be merged into the helper, ala:

No. The compiler, if it inlines get_vmalloc_info() can avoid allocating a
whole struct vmalloc_info if it wishes in the current scheme of things, and
can generate better code by inserting the constants when it needs them.

> and define both VMALLOC_START and VMALLOC_END to 0 for !MMU

Most definitely not! What these are is a per-arch decision, and m68knommu at
least has things set up differently. FRV doesn't even define these for !MMU.

> you're missing an endif.

Good point. That ended up in the nommu patch, where this CONFIG_MMU should've
been.

> I's day just move this out of line into a MMU-only file.
> ...
> or at least keep a single MMU ifdef block per file

I think, perhaps, some of linux/mm.h should perhaps be split out into separate
MMU and !MMU header files, which then get included as appropriate by
linux/mm.h.

> provide stubs please.  pgtable_cache_init is a per-arch things anyway.

*sigh*. I'm trying to keep the time things take to boot and the amount of
space the kernel image occupies down, and you're trying to push both back
up. All these empty stubs consume time and space.

> just move the whole systctl registration into a MMU-only file

How's that going to help? A few of the VM options may still apply to !MMU.

David

^ permalink raw reply	[flat|nested] 87+ messages in thread

* Re: [PATCH 9/14] FRV: CONFIG_MMU fixes
  2004-11-03 15:06   ` David Howells
@ 2004-11-03 15:13     ` Christoph Hellwig
  2004-11-03 15:30     ` David Howells
  1 sibling, 0 replies; 87+ messages in thread
From: Christoph Hellwig @ 2004-11-03 15:13 UTC (permalink / raw)
  To: David Howells; +Cc: torvalds, akpm, davidm, linux-kernel, uclinux-dev

On Wed, Nov 03, 2004 at 03:06:44PM +0000, David Howells wrote:
> 
> > > +++ linux-2.6.10-rc1-bk10-frv/fs/proc/kcore.c	2004-11-01 11:47:04.872656796 +0000
> > > @@ -344,6 +344,7 @@
> > >  		if (m == NULL) {
> > >  			if (clear_user(buffer, tsz))
> > >  				return -EFAULT;
> > > +#ifdef CONFIG_MMU
> >  		} else if ((start >= VMALLOC_START) && (start < VMALLOC_END)) {
> > ...
> > > +#endif
> > 
> > move this into a helper function that can be compiled away for the !MMU case
> 
> That won't work. The else-if clause has to be within the context of the parent
> function in which it now resides.

but you can still have the body of the if clause a noop for !MMU

> It might actually be better to make /proc/kcore conditional on CONFIG_MMU.

Yupp.  In fact I'm pretty sure it can't be selected for m68knommu currently.

> > > +#ifdef CONFIG_MMU
> > >  static struct vmalloc_info get_vmalloc_info(void)
> > ...
> > > +#endif
> > 
> > move the whole function to a CONFIG_MMU-only file
> 
> No. The compiler can, if it wishes, inline this function as it is now. Putting
> it in a separate file removes that option.

Who cares?  This is absolutley not a fastpath.

> > add a small helper for this.  In fact it's the only caller of
> > get_vmalloc_info, so that could be merged into the helper, ala:
> 
> No. The compiler, if it inlines get_vmalloc_info() can avoid allocating a
> whole struct vmalloc_info if it wishes in the current scheme of things, and
> can generate better code by inserting the constants when it needs them.

Dito.

> > I's day just move this out of line into a MMU-only file.
> > ...
> > or at least keep a single MMU ifdef block per file
> 
> I think, perhaps, some of linux/mm.h should perhaps be split out into separate
> MMU and !MMU header files, which then get included as appropriate by
> linux/mm.h.

Probably makes sense.

> > provide stubs please.  pgtable_cache_init is a per-arch things anyway.
> 
> *sigh*. I'm trying to keep the time things take to boot and the amount of
> space the kernel image occupies down, and you're trying to push both back
> up. All these empty stubs consume time and space.

Since when does a noop macro or inline take up space in the kernel image.

> > just move the whole systctl registration into a MMU-only file
> 
> How's that going to help? A few of the VM options may still apply to !MMU.

I meant the registration of the sysctls not relevant for MMU-less systems.


^ permalink raw reply	[flat|nested] 87+ messages in thread

* Re: [PATCH 9/14] FRV: CONFIG_MMU fixes
  2004-11-03 15:06   ` David Howells
  2004-11-03 15:13     ` Christoph Hellwig
@ 2004-11-03 15:30     ` David Howells
  1 sibling, 0 replies; 87+ messages in thread
From: David Howells @ 2004-11-03 15:30 UTC (permalink / raw)
  To: Christoph Hellwig; +Cc: torvalds, akpm, davidm, linux-kernel, uclinux-dev


> > That won't work. The else-if clause has to be within the context of the
> > parent function in which it now resides.
> 
> but you can still have the body of the if clause a noop for !MMU

No, you can't. That else-if clause mustn't be there at all for !MMU. It'd be
too permissive on some nommu archs and wouldn't compile on others.

> > It might actually be better to make /proc/kcore conditional on CONFIG_MMU.
> 
> Yupp.  In fact I'm pretty sure it can't be selected for m68knommu currently.

I'll do that, and that renders the whole argument moot anyway.

David

^ permalink raw reply	[flat|nested] 87+ messages in thread

* Re: [PATCH 12/14] FRV: Generate more useful debug info
  2004-11-03 13:38       ` David Howells
@ 2004-11-03 15:32         ` Linus Torvalds
  0 siblings, 0 replies; 87+ messages in thread
From: Linus Torvalds @ 2004-11-03 15:32 UTC (permalink / raw)
  To: David Howells; +Cc: Andrew Morton, davidm, linux-kernel, uclinux-dev



On Wed, 3 Nov 2004, David Howells wrote:
> 
> I've been able to run a range of 2.4 and 2.6 kernels compiled with -O1 and
> without any -O flag at all, and with all "extern inline" changed to "static
> inline". It doesn't seem to be a problem on i386, x86_64, frv (which I'm
> trying to add) and am33 (which I haven't tried to add yet).

sparc64 was one of the things that definitely depended on it. Also, early
init/main.c depended on the stack not getting clobbered by the initial
fork, but that thankfully was cleaned up with the kernel threads
interfaces.

> Would you object to making it possible for the arch to override the
> optimisation level when debugging?

Quite frankly, I'd prefer developers to do it by just editing the 
Makefile, or doing it entirely statically for some architecture. 

For something like FRV in its current stages it simply doesn't _matter_,
but in architectures that get actual real usage, I absolutely hate the
idea of having different optimization options and wildly different code.
It just results in bugs being harder to reproduce.

And for architectures that don't have enough users to matter, arguably you 
shouldn't then need to have a config option that is visible to the rest of 
the world.

		Linus

^ permalink raw reply	[flat|nested] 87+ messages in thread

* Re: [uClinux-dev] [PATCH 2/14] FRV: Fujitsu FR-V arch include files
       [not found] ` <200411011930.iA1JUKFH023161@warthog.cambridge.redhat.com>
  2004-11-02 23:24   ` [uClinux-dev] [PATCH 2/14] FRV: Fujitsu FR-V arch include files Christoph Hellwig
@ 2004-11-03 17:26   ` David Howells
  1 sibling, 0 replies; 87+ messages in thread
From: David Howells @ 2004-11-03 17:26 UTC (permalink / raw)
  To: uClinux development list; +Cc: akpm, torvalds, linux-kernel


> > +#define kernel_termios_to_user_termio(termio, termios) \
> 
> no error checking at all?

This doesn't appear to be error checked in _any_ arch.

David

^ permalink raw reply	[flat|nested] 87+ messages in thread

* Re: [uClinux-dev] [PATCH 1/14] FRV: Fujitsu FR-V CPU arch implementation
       [not found] <76b4a884-2c3c-11d9-91a1-0002b3163499@redhat.com>
                   ` (14 preceding siblings ...)
       [not found] ` <200411011930.iA1JUKFH023161@warthog.cambridge.redhat.com>
@ 2004-11-03 19:46 ` David Howells
  2004-11-03 20:32   ` Christoph Hellwig
  2004-11-04 11:54 ` David Howells
  16 siblings, 1 reply; 87+ messages in thread
From: David Howells @ 2004-11-03 19:46 UTC (permalink / raw)
  To: uClinux development list; +Cc: akpm, torvalds, linux-kernel


> please don't copy the horrible boot decompressor cludges to new arches.
> Why can't your loader support vmlinux.gz files for a new port?

You're assuming I've control over the bootloader.

> Please use the generic kernel/irq/* code.

That code is not sufficient.

> I can't see this beeing called from generic code ever, why do you
> implement it?

It's a placeholder for something I'd like to implement for the FR451 CPU which
has a decrementer counter. It is actually called from entry.S.

> > +void *dma_alloc_coherent(struct device *hwdev, size_t size, dma_addr_t *dma_handle, int flag)

> the last argument is the gfp mask.

It's called "flag" in include/asm-i386/dma-mapping.h. And shouldn't it be an
"unsigned long" if it's GFP flags?

> does GFP_DMA really hae the same meaning as on i386 here?

I'm not sure whether it should put all of its memory in the DMA region, or
none of it. There's no documentation on this.

> Don't mess with per-arch fields in common procfs files.

Should I then add an arch-specific file to "/proc/<pid>/"?

David

^ permalink raw reply	[flat|nested] 87+ messages in thread

* Re: [uClinux-dev] [PATCH 1/14] FRV: Fujitsu FR-V CPU arch implementation
  2004-11-03 19:46 ` [uClinux-dev] [PATCH 1/14] FRV: Fujitsu FR-V CPU arch implementation David Howells
@ 2004-11-03 20:32   ` Christoph Hellwig
  0 siblings, 0 replies; 87+ messages in thread
From: Christoph Hellwig @ 2004-11-03 20:32 UTC (permalink / raw)
  To: David Howells
  Cc: uClinux development list, akpm, torvalds, linux-kernel, mingo

[any reason you drop me from the cc list?]

> > Please use the generic kernel/irq/* code.
> 
> That code is not sufficient.

Why?  And what makes it impossible to extend the code to handle your
hardware. 

> > I can't see this beeing called from generic code ever, why do you
> > implement it?
> 
> It's a placeholder for something I'd like to implement for the FR451 CPU which
> has a decrementer counter. It is actually called from entry.S.

So add it when you implement that code.

> > > +void *dma_alloc_coherent(struct device *hwdev, size_t size, dma_addr_t *dma_handle, int flag)
> 
> > the last argument is the gfp mask.
> 
> It's called "flag" in include/asm-i386/dma-mapping.h. And shouldn't it be an
> "unsigned long" if it's GFP flags?

If you look at the callers it's use as gfp mask.  Feel free to send patches
to change the types to what you think makes sense.

> > does GFP_DMA really hae the same meaning as on i386 here?
> 
> I'm not sure whether it should put all of its memory in the DMA region, or
> none of it. There's no documentation on this.

There's no rules on how to do it anyway.  But it looks like you don't
have any arbitrary dma limits, so conditionally setting doesn't make
much sense.

> > Don't mess with per-arch fields in common procfs files.
> 
> Should I then add an arch-specific file to "/proc/<pid>/"?

That's not that bad at least.  But you'd need to convience us why
your port is the first that absolutely needs something like that.


^ permalink raw reply	[flat|nested] 87+ messages in thread

* Re: [PATCH 12/14] FRV: Generate more useful debug info
  2004-11-03  1:52       ` Linus Torvalds
@ 2004-11-03 20:40         ` Florian Weimer
  2004-11-03 20:42           ` Linus Torvalds
  0 siblings, 1 reply; 87+ messages in thread
From: Florian Weimer @ 2004-11-03 20:40 UTC (permalink / raw)
  To: Linus Torvalds
  Cc: David Howells, Andrew Morton, davidm, linux-kernel, uclinux-dev

* Linus Torvalds:

>> That may not be true today, but what is true is that -O1 is not a light 
>> thing to just do.
>
> And btw, in some cases the inlining used to be a correcness issue, so no,
> just making it be "static inline" doesn't necessarily fix the basic issue. 

But the always_inline attribute hopefully does.

^ permalink raw reply	[flat|nested] 87+ messages in thread

* Re: [PATCH 12/14] FRV: Generate more useful debug info
  2004-11-03 20:40         ` Florian Weimer
@ 2004-11-03 20:42           ` Linus Torvalds
  0 siblings, 0 replies; 87+ messages in thread
From: Linus Torvalds @ 2004-11-03 20:42 UTC (permalink / raw)
  To: Florian Weimer
  Cc: David Howells, Andrew Morton, davidm, linux-kernel, uclinux-dev



On Wed, 3 Nov 2004, Florian Weimer wrote:

> * Linus Torvalds:
> 
> >> That may not be true today, but what is true is that -O1 is not a light 
> >> thing to just do.
> >
> > And btw, in some cases the inlining used to be a correcness issue, so no,
> > just making it be "static inline" doesn't necessarily fix the basic issue. 
> 
> But the always_inline attribute hopefully does.

Not with older compilers. 

		Linus

^ permalink raw reply	[flat|nested] 87+ messages in thread

* Re: [PATCH 1/14] FRV: Fujitsu FR-V CPU arch implementation
       [not found] <76b4a884-2c3c-11d9-91a1-0002b3163499@redhat.com>
                   ` (15 preceding siblings ...)
  2004-11-03 19:46 ` [uClinux-dev] [PATCH 1/14] FRV: Fujitsu FR-V CPU arch implementation David Howells
@ 2004-11-04 11:54 ` David Howells
  16 siblings, 0 replies; 87+ messages in thread
From: David Howells @ 2004-11-04 11:54 UTC (permalink / raw)
  To: Andrew Morton; +Cc: torvalds, davidm, linux-kernel


> > The attached patch provides an architecture implementation for the Fujitsu
> > FR-V CPU series, configurably as Linux or uClinux.
> 
> Who developed this?

Red Hat was originally contracted to do an 2.4-uclinux arch port by Fujitsu;
this has been extended since. I did most of the work and various RH engineers
did the rest.

> I didn't notice a MAINTAINERS record.  Was there one?

No. I'll add one.

> Who is maintaining it, and via what mailing list?

I'll be maintaining it for the time being. This may pass to some combination
of RH and Fujitsu engineers later.

The mailing list and website have yet to be sorted out. I'll amend the
MAINTAINERS record when they have been.

> How widespread is the usage of this architecture?

Given that it's a relatively new port, use of it isn't very widespread yet;
however, I'm given to believe that the processors themselves are very widely
used, and Fujitsu is obviously interested in anything that promotes their own
CPUs.

David

^ permalink raw reply	[flat|nested] 87+ messages in thread

* [PATCH 2/20] FRV: Fujitsu FR-V arch documentation
  2004-11-08 14:34 [PATCH 1/20] FRV: Fujitsu FR-V CPU arch maintainer record dhowells
@ 2004-11-08 14:34 ` dhowells
  2004-11-08 14:34 ` [PATCH 6/20] FRV: Fujitsu FR-V CPU arch implementation part 4 dhowells
                   ` (15 subsequent siblings)
  16 siblings, 0 replies; 87+ messages in thread
From: dhowells @ 2004-11-08 14:34 UTC (permalink / raw)
  To: torvalds, akpm, davidm; +Cc: linux-kernel, uclinux-dev

The attached patch provides the arch-specific documentation for the Fujitsu
FR-V CPU arch.

Signed-Off-By: dhowells@redhat.com
---
diffstat frv-docs-2610rc1mm3.diff
 README.txt      |   51 +++++++++
 atomic-ops.txt  |  134 ++++++++++++++++++++++++
 booting.txt     |  181 ++++++++++++++++++++++++++++++++
 clock.txt       |   65 +++++++++++
 configuring.txt |  125 ++++++++++++++++++++++
 features.txt    |  310 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 gdbinit         |  102 ++++++++++++++++++
 gdbstub.txt     |  130 +++++++++++++++++++++++
 mmu-layout.txt  |  306 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 9 files changed, 1404 insertions(+)

diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/Documentation/fujitsu/frv/atomic-ops.txt linux-2.6.10-rc1-mm3-frv/Documentation/fujitsu/frv/atomic-ops.txt
--- /warthog/kernels/linux-2.6.10-rc1-mm3/Documentation/fujitsu/frv/atomic-ops.txt	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/Documentation/fujitsu/frv/atomic-ops.txt	2004-11-05 14:13:03.000000000 +0000
@@ -0,0 +1,134 @@
+			       =====================================
+			       FUJITSU FR-V KERNEL ATOMIC OPERATIONS
+			       =====================================
+
+On the FR-V CPUs, there is only one atomic Read-Modify-Write operation: the SWAP/SWAPI
+instruction. Unfortunately, this alone can't be used to implement the following operations:
+
+ (*) Atomic add to memory
+
+ (*) Atomic subtract from memory
+
+ (*) Atomic bit modification (set, clear or invert)
+
+ (*) Atomic compare and exchange
+
+On such CPUs, the standard way of emulating such operations in uniprocessor mode is to disable
+interrupts, but on the FR-V CPUs, modifying the PSR takes a lot of clock cycles, and it has to be
+done twice. This means the CPU runs for a relatively long time with interrupts disabled,
+potentially having a great effect on interrupt latency.
+
+
+=============
+NEW ALGORITHM
+=============
+
+To get around this, the following algorithm has been implemented. It operates in a way similar to
+the LL/SC instruction pairs supported on a number of platforms.
+
+ (*) The CCCR.CC3 register is reserved within the kernel to act as an atomic modify abort flag.
+
+ (*) In the exception prologues run on kernel->kernel entry, CCCR.CC3 is set to 0 (Undefined
+     state).
+
+ (*) All atomic operations can then be broken down into the following algorithm:
+
+     (1) Set ICC3.Z to true and set CC3 to True (ORCC/CKEQ/ORCR).
+
+     (2) Load the value currently in the memory to be modified into a register.
+
+     (3) Make changes to the value.
+
+     (4) If CC3 is still True, simultaneously and atomically (by VLIW packing):
+
+	 (a) Store the modified value back to memory.
+
+	 (b) Set ICC3.Z to false (CORCC on GR29 is sufficient for this - GR29 holds the current
+	     task pointer in the kernel, and so is guaranteed to be non-zero).
+
+     (5) If ICC3.Z is still true, go back to step (1).
+
+This works in a non-SMP environment because any interrupt or other exception that happens between
+steps (1) and (4) will set CC3 to the Undefined, thus aborting the store in (4a), and causing the
+condition in ICC3 to remain with the Z flag set, thus causing step (5) to loop back to step (1).
+
+
+This algorithm suffers from two problems:
+
+ (1) The condition CCCR.CC3 is cleared unconditionally by an exception, irrespective of whether or
+     not any changes were made to the target memory location during that exception.
+
+ (2) The branch from step (5) back to step (1) may have to happen more than once until the store
+     manages to take place. In theory, this loop could cycle forever because there are too many
+     interrupts coming in, but it's unlikely.
+
+
+=======
+EXAMPLE
+=======
+
+Taking an example from include/asm-frv/atomic.h:
+
+	static inline int atomic_add_return(int i, atomic_t *v)
+	{
+		unsigned long val;
+
+		asm("0:						\n"
+
+It starts by setting ICC3.Z to true for later use, and also transforming that into CC3 being in the
+True state.
+
+		    "	orcc		gr0,gr0,gr0,icc3	\n"	<-- (1)
+		    "	ckeq		icc3,cc7		\n"	<-- (1)
+
+Then it does the load. Note that the final phase of step (1) is done at the same time as the
+load. The VLIW packing ensures they are done simultaneously. The ".p" on the load must not be
+removed without swapping the order of these two instructions.
+
+		    "	ld.p		%M0,%1			\n"	<-- (2)
+		    "	orcr		cc7,cc7,cc3		\n"	<-- (1)
+
+Then the proposed modification is generated. Note that the old value can be retained if required
+(such as in test_and_set_bit()).
+
+		    "	add%I2		%1,%2,%1		\n"	<-- (3)
+
+Then it attempts to store the value back, contingent on no exception having cleared CC3 since it
+was set to True.
+
+		    "	cst.p		%1,%M0		,cc3,#1	\n"	<-- (4a)
+
+It simultaneously records the success or failure of the store in ICC3.Z.
+
+		    "	corcc		gr29,gr29,gr0	,cc3,#1	\n"	<-- (4b)
+
+Such that the branch can then be taken if the operation was aborted.
+
+		    "	beq		icc3,#0,0b		\n"	<-- (5)
+		    : "+U"(v->counter), "=&r"(val)
+		    : "NPr"(i)
+		    : "memory", "cc7", "cc3", "icc3"
+		    );
+
+		return val;
+	}
+
+
+=============
+CONFIGURATION
+=============
+
+The atomic ops implementation can be made inline or out-of-line by changing the
+CONFIG_FRV_OUTOFLINE_ATOMIC_OPS configuration variable. Making it out-of-line has a number of
+advantages:
+
+ - The resulting kernel image may be smaller
+ - Debugging is easier as atomic ops can just be stepped over and they can be breakpointed
+
+Keeping it inline also has a number of advantages:
+
+ - The resulting kernel may be Faster
+   - no out-of-line function calls need to be made
+   - the compiler doesn't have half its registers clobbered by making a call
+
+The out-of-line implementations live in arch/frv/lib/atomic-ops.S.
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/Documentation/fujitsu/frv/booting.txt linux-2.6.10-rc1-mm3-frv/Documentation/fujitsu/frv/booting.txt
--- /warthog/kernels/linux-2.6.10-rc1-mm3/Documentation/fujitsu/frv/booting.txt	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/Documentation/fujitsu/frv/booting.txt	2004-11-05 14:13:03.000000000 +0000
@@ -0,0 +1,181 @@
+			  =========================
+			  BOOTING FR-V LINUX KERNEL
+			  =========================
+
+======================
+PROVIDING A FILESYSTEM
+======================
+
+First of all, a root filesystem must be made available. This can be done in
+one of two ways:
+
+  (1) NFS Export
+
+      A filesystem should be constructed in a directory on an NFS server that
+      the target board can reach. This directory should then be NFS exported
+      such that the target board can read and write into it as root.
+
+  (2) Flash Filesystem (JFFS2 Recommended)
+
+      In this case, the image must be stored or built up on flash before it
+      can be used. A complete image can be built using the mkfs.jffs2 or
+      similar program and then downloaded and stored into flash by RedBoot.
+
+
+========================
+LOADING THE KERNEL IMAGE
+========================
+
+The kernel will need to be loaded into RAM by RedBoot (or by some alternative
+boot loader) before it can be run. The kernel image (arch/frv/boot/Image) may
+be loaded in one of three ways:
+
+  (1) Load from Flash
+
+      This is the simplest. RedBoot can store an image in the flash (see the
+      RedBoot documentation) and then load it back into RAM. RedBoot keeps
+      track of the load address, entry point and size, so the command to do
+      this is simply:
+
+	fis load linux
+
+      The image is then ready to be executed.
+
+  (2) Load by TFTP
+
+      The following command will download a raw binary kernel image from the
+      default server (as negotiated by BOOTP) and store it into RAM:
+      
+	load -b 0x00100000 -r /tftpboot/image.bin
+
+      The image is then ready to be executed.
+
+  (3) Load by Y-Modem
+
+      The following command will download a raw binary kernel image across the
+      serial port that RedBoot is currently using:
+      
+	load -m ymodem -b 0x00100000 -r zImage
+
+      The serial client (such as minicom) must then be told to transmit the
+      program by Y-Modem.
+
+      When finished, the image will then be ready to be executed.
+
+
+==================
+BOOTING THE KERNEL
+==================
+
+Boot the image with the following RedBoot command:
+
+	exec -c "<CMDLINE>" 0x00100000
+
+For example:
+
+	exec -c "console=ttySM0,115200 ip=:::::dhcp root=/dev/mtdblock2 rw"
+
+This will start the kernel running. Note that if the GDB-stub is compiled in,
+then the kernel will immediately wait for GDB to connect over serial before
+doing anything else. See the section on kernel debugging with GDB.
+
+The kernel command line <CMDLINE> tells the kernel where its console is and
+how to find its root filesystem. This is made up of the following components,
+separated by spaces:
+
+  (*) console=ttyS<x>[,<baud>[<parity>[<bits>[<flow>]]]]
+
+      This specifies that the system console should output through on-chip
+      serial port <x> (which can be "0" or "1").
+
+      <baud> is a standard baud rate between 1200 and 115200 (default 9600).
+
+      <parity> is a parity setting of "N", "O", "E", "M" or "S" for None, Odd,
+      Even, Mark or Space. "None" is the default.
+
+      <stop> is "7" or "8" for the number of bits per character. "8" is the
+      default.
+
+      <flow> is "r" to use flow control (XCTS on serial port 2 only). The
+      default is to not use flow control.
+
+      For example:
+
+	console=ttyS0,115200
+
+      To use the first on-chip serial port at baud rate 115200, no parity, 8
+      bits, and no flow control.
+
+  (*) root=/dev/<xxxx>
+
+      This specifies the device upon which the root filesystem resides. For
+      example:
+
+	/dev/nfs	NFS root filesystem
+	/dev/mtdblock3	Fourth RedBoot partition on the System Flash
+
+  (*) rw
+
+      Start with the root filesystem mounted Read/Write.
+
+  The remaining components are all optional:
+
+  (*) ip=<ip>::::<host>:<iface>:<cfg>
+
+      Configure the network interface. If <cfg> is "off" then <ip> should
+      specify the IP address for the network device <iface>. <host> provide
+      the hostname for the device.
+
+      If <cfg> is "bootp" or "dhcp", then all of these parameters will be
+      discovered by consulting a BOOTP or DHCP server.
+
+      For example, the following might be used:
+
+	ip=192.168.73.12::::frv:eth0:off
+
+      This sets the IP address on the VDK motherboard RTL8029 ethernet chipset
+      (eth0) to be 192.168.73.12, and sets the board's hostname to be "frv".
+
+  (*) nfsroot=<server>:<dir>[,v<vers>]
+
+      This is mandatory if "root=/dev/nfs" is given as an option. It tells the
+      kernel the IP address of the NFS server providing its root filesystem,
+      and the pathname on that server of the filesystem.
+
+      The NFS version to use can also be specified. v2 and v3 are supported by
+      Linux.
+
+      For example:
+
+	nfsroot=192.168.73.1:/nfsroot-frv
+
+  (*) profile=1
+
+      Turns on the kernel profiler (accessible through /proc/profile).
+
+  (*) console=gdb0
+
+      This can be used as an alternative to the "console=ttyS..." listed
+      above. I tells the kernel to pass the console output to GDB if the
+      gdbstub is compiled in to the kernel.
+
+      If this is used, then the gdbstub passes the text to GDB, which then
+      simply dumps it to its standard output.
+
+  (*) mem=<xxx>M
+
+      Normally the kernel will work out how much SDRAM it has by reading the
+      SDRAM controller registers. That can be overridden with this
+      option. This allows the kernel to be told that it has <xxx> megabytes of
+      memory available.
+
+  (*) init=<prog> [<arg> [<arg> [<arg> ...]]]
+
+      This tells the kernel what program to run initially. By default this is
+      /sbin/init, but /sbin/sash or /bin/sh are common alternatives.
+
+  (*) vdc=...
+
+      This option configures the MB93493 companion chip visual display
+      driver. Please see Documentation/fujitsu/mb93493/vdc.txt for more
+      information.
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/Documentation/fujitsu/frv/clock.txt linux-2.6.10-rc1-mm3-frv/Documentation/fujitsu/frv/clock.txt
--- /warthog/kernels/linux-2.6.10-rc1-mm3/Documentation/fujitsu/frv/clock.txt	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/Documentation/fujitsu/frv/clock.txt	2004-11-05 14:13:03.000000000 +0000
@@ -0,0 +1,65 @@
+Clock scaling
+-------------
+
+The kernel supports scaling of CLCK.CMODE, CLCK.CM and CLKC.P0 clock
+registers. If built with CONFIG_PM and CONFIG_SYSCTL options enabled, four
+extra files will appear in the directory /proc/sys/pm/. Reading these files
+will show:
+
+      p0		-- current value of the P0 bit in CLKC register.
+      cm		-- current value of the CM bits in CLKC register.
+      cmode		-- current value of the CMODE bits in CLKC register.
+
+On all boards, the 'p0' file should also be writable, and either '1' or '0'
+can be rewritten, to set or clear the CLKC_P0 bit respectively, hence
+controlling whether the resource bus rate clock is halved.
+
+The 'cm' file should also be available on all boards. '0' can be written to it
+to shift the board into High-Speed mode (normal), and '1' can be written to
+shift the board into Medium-Speed mode. Selecting Low-Speed mode is not
+supported by this interface, even though some CPUs do support it.
+
+On the boards with FR405 CPU (i.e. CB60 and CB70), the 'cmode' file is also
+writable, allowing the CPU core speed (and other clock speeds) to be
+controlled from userspace.
+
+
+Determining current and possible settings
+-----------------------------------------
+
+The current state and the available masks can be found in /proc/cpuinfo. For
+example, on the CB70:
+
+	# cat /proc/cpuinfo
+	CPU-Series:     fr400
+	CPU-Core:       fr405, gr0-31, BE, CCCR
+	CPU:            mb93405
+	MMU:            Prot
+	FP-Media:       fr0-31, Media
+	System:         mb93091-cb70, mb93090-mb00
+	PM-Controls:    cmode=0xd31f, cm=0x3, p0=0x3, suspend=0x9
+	PM-Status:      cmode=3, cm=0, p0=0
+	Clock-In:       50.00 MHz
+	Clock-Core:     300.00 MHz
+	Clock-SDRAM:    100.00 MHz
+	Clock-CBus:     100.00 MHz
+	Clock-Res:      50.00 MHz
+	Clock-Ext:      50.00 MHz
+	Clock-DSU:      25.00 MHz
+	BogoMips:       300.00
+
+And on the PDK, the PM lines look like the following:
+
+	PM-Controls:    cm=0x3, p0=0x3, suspend=0x9
+	PM-Status:      cmode=9, cm=0, p0=0
+
+The PM-Controls line, if present, will indicate which /proc/sys/pm files can
+be set to what values. The specification values are bitmasks; so, for example,
+"suspend=0x9" indicates that 0 and 3 can be written validly to
+/proc/sys/pm/suspend.
+
+The PM-Controls line will only be present if CONFIG_PM is configured to Y.
+
+The PM-Status line indicates which clock controls are set to which value. If
+the file can be read, then the suspend value must be 0, and so that's not
+included.
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/Documentation/fujitsu/frv/configuring.txt linux-2.6.10-rc1-mm3-frv/Documentation/fujitsu/frv/configuring.txt
--- /warthog/kernels/linux-2.6.10-rc1-mm3/Documentation/fujitsu/frv/configuring.txt	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/Documentation/fujitsu/frv/configuring.txt	2004-11-05 14:13:03.000000000 +0000
@@ -0,0 +1,125 @@
+		   =======================================
+		   FUJITSU FR-V LINUX KERNEL CONFIGURATION
+		   =======================================
+
+=====================
+CONFIGURATION OPTIONS
+=====================
+
+The most important setting is in the "MMU support options" tab (the first
+presented in the configuration tools available):
+
+ (*) "Kernel Type"
+
+     This options allows selection of normal, MMU-requiring linux, and uClinux
+     (which doesn't require an MMU and doesn't have inter-process protection).
+
+There are a number of settings in the "Processor type and features" section of
+the kernel configuration that need to be considered.
+
+ (*) "CPU"
+
+     The register and instruction sets at the core of the processor. This can
+     only be set to "FR40x/45x/55x" at the moment - but this permits usage of
+     the kernel with MB93091 CB10, CB11, CB30, CB41, CB60, CB70 and CB451
+     CPU boards, and with the MB93093 PDK board.
+
+ (*) "System"
+
+     This option allows a choice of basic system. This governs the peripherals
+     that are expected to be available.
+
+ (*) "Motherboard"
+
+     This specifies the type of motherboard being used, and the peripherals
+     upon it. Currently only "MB93090-MB00" can be set here.
+
+ (*) "Default cache-write mode"
+
+     This controls the initial data cache write management mode. By default
+     Write-Through is selected, but Write-Back (Copy-Back) can also be
+     selected. This can be changed dynamically once the kernel is running (see
+     features.txt).
+
+There are some architecture specific configuration options in the "General
+Setup" section of the kernel configuration too:
+
+ (*) "Reserve memory uncached for (PCI) DMA"
+
+     This requests that a uClinux kernel set aside some memory in an uncached
+     window for the use as consistent DMA memory (mainly for PCI). At least a
+     megabyte will be allocated in this way, possibly more. Any memory so
+     reserved will not be available for normal allocations.
+
+ (*) "Kernel support for ELF-FDPIC binaries"
+
+     This enables the binary-format driver for the new FDPIC ELF binaries that
+     this platform normally uses. These binaries are totally relocatable -
+     their separate sections can relocated independently, allowing them to be
+     shared on uClinux where possible. This should normally be enabled.
+
+ (*) "Kernel image protection"
+
+     This makes the protection register governing access to the core kernel
+     image prohibit access by userspace programs. This option is available on
+     uClinux only.
+
+There are also a number of settings in the "Kernel Hacking" section of the
+kernel configuration especially for debugging a kernel on this
+architecture. See the "gdbstub.txt" file for information about those.
+
+
+======================
+DEFAULT CONFIGURATIONS
+======================
+
+The kernel sources include a number of example default configurations:
+
+ (*) defconfig-mb93091
+
+     Default configuration for the MB93091-VDK with both CPU board and
+     MB93090-MB00 motherboard running uClinux.
+
+
+ (*) defconfig-mb93091-fb
+
+     Default configuration for the MB93091-VDK with CPU board,
+     MB93090-MB00 motherboard, and DAV board running uClinux.
+     Includes framebuffer driver.
+
+
+ (*) defconfig-mb93093
+
+     Default configuration for the MB93093-PDK board running uClinux.
+
+
+ (*) defconfig-cb70-standalone
+
+     Default configuration for the MB93091-VDK with only CB70 CPU board
+     running uClinux. This will use the CB70's DM9000 for network access.
+
+
+ (*) defconfig-mmu
+
+     Default configuration for the MB93091-VDK with both CB451 CPU board and
+     MB93090-MB00 motherboard running MMU linux.
+
+ (*) defconfig-mmu-audio
+
+     Default configuration for the MB93091-VDK with CB451 CPU board, DAV
+     board, and MB93090-MB00 motherboard running MMU linux. Includes
+     audio driver.
+
+ (*) defconfig-mmu-fb
+
+     Default configuration for the MB93091-VDK with CB451 CPU board, DAV
+     board, and MB93090-MB00 motherboard running MMU linux. Includes
+     framebuffer driver.
+
+ (*) defconfig-mmu-standalone
+
+     Default configuration for the MB93091-VDK with only CB451 CPU board
+     running MMU linux.
+
+
+
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/Documentation/fujitsu/frv/features.txt linux-2.6.10-rc1-mm3-frv/Documentation/fujitsu/frv/features.txt
--- /warthog/kernels/linux-2.6.10-rc1-mm3/Documentation/fujitsu/frv/features.txt	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/Documentation/fujitsu/frv/features.txt	2004-11-05 14:13:03.000000000 +0000
@@ -0,0 +1,310 @@
+			 ===========================
+			 FUJITSU FR-V LINUX FEATURES
+			 ===========================
+
+This kernel port has a number of features of which the user should be aware:
+
+ (*) Linux and uClinux
+
+     The FR-V architecture port supports both normal MMU linux and uClinux out
+     of the same sources.
+
+
+ (*) CPU support
+
+     Support for the FR401, FR403, FR405, FR451 and FR555 CPUs should work with
+     the same uClinux kernel configuration.
+
+     In normal (MMU) Linux mode, only the FR451 CPU will work as that is the
+     only one with a suitably featured CPU.
+
+     The kernel is written and compiled with the assumption that only the
+     bottom 32 GR registers and no FR registers will be used by the kernel
+     itself, however all extra userspace registers will be saved on context
+     switch. Note that since most CPUs can't support lazy switching, no attempt
+     is made to do lazy register saving where that would be possible (FR555
+     only currently).
+
+
+ (*) Board support
+
+     The board on which the kernel will run can be configured on the "Processor
+     type and features" configuration tab.
+
+     Set the System to "MB93093-PDK" to boot from the MB93093 (FR403) PDK.
+
+     Set the System to "MB93091-VDK" to boot from the CB11, CB30, CB41, CB60,
+     CB70 or CB451 VDK boards. Set the Motherboard setting to "MB93090-MB00" to
+     boot with the standard ATA90590B VDK motherboard, and set it to "None" to
+     boot without any motherboard.
+
+
+ (*) Binary Formats
+
+     The only userspace binary format supported is FDPIC ELF. Normal ELF, FLAT
+     and AOUT binaries are not supported for this architecture.
+
+     FDPIC ELF supports shared library and program interpreter facilities.
+
+
+ (*) Scheduler Speed
+
+     The kernel scheduler runs at 100Hz irrespective of the clock speed on this
+     architecture. This value is set in asm/param.h (see the HZ macro defined
+     there).
+
+
+ (*) Normal (MMU) Linux Memory Layout.
+
+     See mmu-layout.txt in this directory for a description of the normal linux
+     memory layout
+
+     See include/asm-frv/mem-layout.h for constants pertaining to the memory
+     layout.
+
+     See include/asm-frv/mb-regs.h for the constants pertaining to the I/O bus
+     controller configuration.
+
+
+ (*) uClinux Memory Layout
+
+     The memory layout used by the uClinux kernel is as follows:
+
+	0x00000000 - 0x00000FFF		Null pointer catch page
+	0x20000000 - 0x200FFFFF CS2#    [PDK] FPGA
+	0xC0000000 - 0xCFFFFFFF		SDRAM
+	0xC0000000			Base of Linux kernel image
+	0xE0000000 - 0xEFFFFFFF	CS2#	[VDK] SLBUS/PCI window
+	0xF0000000 - 0xF0FFFFFF	CS5#	MB93493 CSC area (DAV daughter board)
+	0xF1000000 - 0xF1FFFFFF	CS7#	[CB70/CB451] CPU-card PCMCIA port space
+	0xFC000000 - 0xFC0FFFFF	CS1#	[VDK] MB86943 config space
+	0xFC100000 - 0xFC1FFFFF	CS6#	[CB70/CB451] CPU-card DM9000 NIC space
+	0xFC100000 - 0xFC1FFFFF	CS6#	[PDK] AX88796 NIC space
+	0xFC200000 - 0xFC2FFFFF	CS3#	MB93493 CSR area (DAV daughter board)
+	0xFD000000 - 0xFDFFFFFF	CS4#	[CB70/CB451] CPU-card extra flash space
+	0xFE000000 - 0xFEFFFFFF		Internal CPU peripherals
+	0xFF000000 - 0xFF1FFFFF	CS0#	Flash 1
+	0xFF200000 - 0xFF3FFFFF	CS0#	Flash 2
+	0xFFC00000 - 0xFFC0001F	CS0#	[VDK] FPGA
+
+     The kernel reads the size of the SDRAM from the memory bus controller
+     registers by default.
+
+     The kernel initialisation code (1) adjusts the SDRAM base addresses to
+     move the SDRAM to desired address, (2) moves the kernel image down to the
+     bottom of SDRAM, (3) adjusts the bus controller registers to move I/O
+     windows, and (4) rearranges the protection registers to protect all of
+     this.
+
+     The reasons for doing this are: (1) the page at address 0 should be
+     inaccessible so that NULL pointer errors can be caught; and (2) the bottom
+     three quarters are left unoccupied so that an FR-V CPU with an MMU can use
+     it for virtual userspace mappings.
+
+     See include/asm-frv/mem-layout.h for constants pertaining to the memory
+     layout.
+
+     See include/asm-frv/mb-regs.h for the constants pertaining to the I/O bus
+     controller configuration.
+
+
+ (*) uClinux Memory Protection
+
+     A DAMPR register is used to cover the entire region used for I/O
+     (0xE0000000 - 0xFFFFFFFF). This permits the kernel to make uncached
+     accesses to this region. Userspace is not permitted to access it.
+
+     The DAMPR/IAMPR protection registers not in use for any other purpose are
+     tiled over the top of the SDRAM such that:
+
+	(1) The core kernel image is covered by as small a tile as possible
+            granting only the kernel access to the underlying data, whilst
+            making sure no SDRAM is actually made unavailable by this approach.
+
+	(2) All other tiles are arranged to permit userspace access to the rest
+            of the SDRAM.
+
+     Barring point (1), there is nothing to protect kernel data against
+     userspace damage - but this is uClinux.
+
+
+ (*) Exceptions and Fixups
+
+     Since the FR40x and FR55x CPUs that do not have full MMUs generate
+     imprecise data error exceptions, there are currently no automatic fixup
+     services available in uClinux. This includes misaligned memory access
+     fixups.
+
+     Userspace EFAULT errors can be trapped by issuing a MEMBAR instruction and
+     forcing the fault to happen there.
+
+     On the FR451, however, data exceptions are mostly precise, and so
+     exception fixup handling is implemented as normal.
+
+
+ (*) Userspace Breakpoints
+
+     The ptrace() system call supports the following userspace debugging
+     features:
+
+	(1) Hardware assisted single step.
+
+	(2) Breakpoint via the FR-V "BREAK" instruction.
+
+	(3) Breakpoint via the FR-V "TIRA GR0, #1" instruction.
+
+	(4) Syscall entry/exit trap.
+
+     Each of the above generates a SIGTRAP.
+
+
+ (*) On-Chip Serial Ports
+
+     The FR-V on-chip serial ports are made available as ttyS0 and ttyS1. Note
+     that if the GDB stub is compiled in, ttyS1 will not actually be available
+     as it will be being used for the GDB stub.
+
+     These ports can be made by:
+
+	mknod /dev/ttyS0 c 4 64
+	mknod /dev/ttyS1 c 4 65
+
+
+ (*) Maskable Interrupts
+
+     Level 15 (Non-maskable) interrupts are dealt with by the GDB stub if
+     present, and cause a panic if not. If the GDB stub is present, ttyS1's
+     interrupts are rated at level 15.
+
+     All other interrupts are distributed over the set of available priorities
+     so that no IRQs are shared where possible. The arch interrupt handling
+     routines attempt to disentangle the various sources available through the
+     CPU's own multiplexor, and those on off-CPU peripherals.
+
+
+ (*) Accessing PCI Devices
+
+     Where PCI is available, care must be taken when dealing with drivers that
+     access PCI devices. PCI devices present their data in little-endian form,
+     but the CPU sees it in big-endian form. The macros in asm/io.h try to get
+     this right, but may not under all circumstances...
+
+
+ (*) Ax88796 Ethernet Driver
+
+     The MB93093 PDK board has an Ax88796 ethernet chipset (an NE2000 clone). A
+     driver has been written to deal specifically with this. The driver
+     provides MII services for the card.
+
+     The driver can be configured by running make xconfig, and going to:
+
+	(*) Network device support
+	    - turn on "Network device support"
+	    (*) Ethernet (10 or 100Mbit)
+		- turn on "Ethernet (10 or 100Mbit)"
+		- turn on "AX88796 NE2000 compatible chipset"
+
+     The driver can be found in:
+
+	drivers/net/ax88796.c
+	include/asm/ax88796.h
+
+
+ (*) WorkRAM Driver
+
+     This driver provides a character device that permits access to the WorkRAM
+     that can be found on the FR451 CPU. Each page is accessible through a
+     separate minor number, thereby permitting each page to have its own
+     filesystem permissions set on the device file.
+
+     The device files should be:
+
+	mknod /dev/frv/workram0 c 240 0
+	mknod /dev/frv/workram1 c 240 1
+	mknod /dev/frv/workram2 c 240 2
+	...
+
+     The driver will not permit the opening of any device file that does not
+     correspond to at least a partial page of WorkRAM. So the first device file
+     is the only one available on the FR451. If any other CPU is detected, none
+     of the devices will be openable.
+
+     The devices can be accessed with read, write and llseek, and can also be
+     mmapped. If they're mmapped, they will only map at the appropriate
+     0x7e8nnnnn address on linux and at the 0xfe8nnnnn address on uClinux. If
+     MAP_FIXED is not specified, the appropriate address will be chosen anyway.
+
+     The mappings must be MAP_SHARED not MAP_PRIVATE, and must not be
+     PROT_EXEC. They must also start at file offset 0, and must not be longer
+     than one page in size.
+
+     This driver can be configured by running make xconfig, and going to:
+
+	(*) Character devices
+	    - turn on "Fujitsu FR-V CPU WorkRAM support"
+
+
+ (*) Dynamic data cache write mode changing
+
+     It is possible to view and to change the data cache's write mode through
+     the /proc/sys/frv/cache-mode file while the kernel is running. There are
+     two modes available:
+
+	NAME	MEANING
+	=====	==========================================
+	wthru	Data cache is in Write-Through mode
+	wback	Data cache is in Write-Back/Copy-Back mode
+
+     To read the cache mode:
+
+	# cat /proc/sys/frv/cache-mode
+	wthru
+
+     To change the cache mode:
+
+	# echo wback >/proc/sys/frv/cache-mode
+	# cat /proc/sys/frv/cache-mode
+	wback
+
+
+ (*) MMU Context IDs and Pinning
+
+     On MMU Linux the CPU supports the concept of a context ID in its MMU to
+     make it more efficient (TLB entries are labelled with a context ID to link
+     them to specific tasks).
+
+     Normally once a context ID is allocated, it will remain affixed to a task
+     or CLONE_VM'd group of tasks for as long as it exists. However, since the
+     kernel is capable of supporting more tasks than there are possible ID
+     numbers, the kernel will pass context IDs from one task to another if
+     there are insufficient available.
+
+     The context ID currently in use by a task can be viewed in /proc:
+
+	# grep CXNR /proc/1/status
+	CXNR: 1
+
+     Note that kernel threads do not have a userspace context, and so will not
+     show a CXNR entry in that file.
+
+     Under some circumstances, however, it is desirable to pin a context ID on
+     a process such that the kernel won't pass it on. This can be done by
+     writing the process ID of the target process to a special file:
+
+	# echo 17 >/proc/sys/frv/pin-cxnr
+
+     Reading from the file will then show the context ID pinned.
+
+	# cat /proc/sys/frv/pin-cxnr
+	4
+
+     The context ID will remain pinned as long as any process is using that
+     context, i.e.: when the all the subscribing processes have exited or
+     exec'd; or when an unpinning request happens:
+
+	# echo 0 >/proc/sys/frv/pin-cxnr
+
+     When there isn't a pinned context, the file shows -1:
+
+	# cat /proc/sys/frv/pin-cxnr
+	-1
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/Documentation/fujitsu/frv/gdbinit linux-2.6.10-rc1-mm3-frv/Documentation/fujitsu/frv/gdbinit
--- /warthog/kernels/linux-2.6.10-rc1-mm3/Documentation/fujitsu/frv/gdbinit	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/Documentation/fujitsu/frv/gdbinit	2004-11-05 14:13:03.000000000 +0000
@@ -0,0 +1,102 @@
+set remotebreak 1
+
+define _amr
+
+printf "AMRx           DAMR                    IAMR         \n"
+printf "====   =====================   =====================\n"
+printf "amr0 : L:%08lx P:%08lx : L:%08lx P:%08lx\n",__debug_mmu.damr[0x0].L,__debug_mmu.damr[0x0].P,__debug_mmu.iamr[0x0].L,__debug_mmu.iamr[0x0].P
+printf "amr1 : L:%08lx P:%08lx : L:%08lx P:%08lx\n",__debug_mmu.damr[0x1].L,__debug_mmu.damr[0x1].P,__debug_mmu.iamr[0x1].L,__debug_mmu.iamr[0x1].P
+printf "amr2 : L:%08lx P:%08lx : L:%08lx P:%08lx\n",__debug_mmu.damr[0x2].L,__debug_mmu.damr[0x2].P,__debug_mmu.iamr[0x2].L,__debug_mmu.iamr[0x2].P
+printf "amr3 : L:%08lx P:%08lx : L:%08lx P:%08lx\n",__debug_mmu.damr[0x3].L,__debug_mmu.damr[0x3].P,__debug_mmu.iamr[0x3].L,__debug_mmu.iamr[0x3].P
+printf "amr4 : L:%08lx P:%08lx : L:%08lx P:%08lx\n",__debug_mmu.damr[0x4].L,__debug_mmu.damr[0x4].P,__debug_mmu.iamr[0x4].L,__debug_mmu.iamr[0x4].P
+printf "amr5 : L:%08lx P:%08lx : L:%08lx P:%08lx\n",__debug_mmu.damr[0x5].L,__debug_mmu.damr[0x5].P,__debug_mmu.iamr[0x5].L,__debug_mmu.iamr[0x5].P
+printf "amr6 : L:%08lx P:%08lx : L:%08lx P:%08lx\n",__debug_mmu.damr[0x6].L,__debug_mmu.damr[0x6].P,__debug_mmu.iamr[0x6].L,__debug_mmu.iamr[0x6].P
+printf "amr7 : L:%08lx P:%08lx : L:%08lx P:%08lx\n",__debug_mmu.damr[0x7].L,__debug_mmu.damr[0x7].P,__debug_mmu.iamr[0x7].L,__debug_mmu.iamr[0x7].P
+
+printf "amr8 : L:%08lx P:%08lx\n",__debug_mmu.damr[0x8].L,__debug_mmu.damr[0x8].P
+printf "amr9 : L:%08lx P:%08lx\n",__debug_mmu.damr[0x9].L,__debug_mmu.damr[0x9].P
+printf "amr10: L:%08lx P:%08lx\n",__debug_mmu.damr[0xa].L,__debug_mmu.damr[0xa].P
+printf "amr11: L:%08lx P:%08lx\n",__debug_mmu.damr[0xb].L,__debug_mmu.damr[0xb].P
+
+end
+
+
+define _tlb
+printf "tlb[0x00]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x0].L,__debug_mmu.tlb[0x0].P,__debug_mmu.tlb[0x40+0x0].L,__debug_mmu.tlb[0x40+0x0].P
+printf "tlb[0x01]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x1].L,__debug_mmu.tlb[0x1].P,__debug_mmu.tlb[0x40+0x1].L,__debug_mmu.tlb[0x40+0x1].P
+printf "tlb[0x02]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x2].L,__debug_mmu.tlb[0x2].P,__debug_mmu.tlb[0x40+0x2].L,__debug_mmu.tlb[0x40+0x2].P
+printf "tlb[0x03]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x3].L,__debug_mmu.tlb[0x3].P,__debug_mmu.tlb[0x40+0x3].L,__debug_mmu.tlb[0x40+0x3].P
+printf "tlb[0x04]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x4].L,__debug_mmu.tlb[0x4].P,__debug_mmu.tlb[0x40+0x4].L,__debug_mmu.tlb[0x40+0x4].P
+printf "tlb[0x05]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x5].L,__debug_mmu.tlb[0x5].P,__debug_mmu.tlb[0x40+0x5].L,__debug_mmu.tlb[0x40+0x5].P
+printf "tlb[0x06]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x6].L,__debug_mmu.tlb[0x6].P,__debug_mmu.tlb[0x40+0x6].L,__debug_mmu.tlb[0x40+0x6].P
+printf "tlb[0x07]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x7].L,__debug_mmu.tlb[0x7].P,__debug_mmu.tlb[0x40+0x7].L,__debug_mmu.tlb[0x40+0x7].P
+printf "tlb[0x08]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x8].L,__debug_mmu.tlb[0x8].P,__debug_mmu.tlb[0x40+0x8].L,__debug_mmu.tlb[0x40+0x8].P
+printf "tlb[0x09]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x9].L,__debug_mmu.tlb[0x9].P,__debug_mmu.tlb[0x40+0x9].L,__debug_mmu.tlb[0x40+0x9].P
+printf "tlb[0x0a]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0xa].L,__debug_mmu.tlb[0xa].P,__debug_mmu.tlb[0x40+0xa].L,__debug_mmu.tlb[0x40+0xa].P
+printf "tlb[0x0b]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0xb].L,__debug_mmu.tlb[0xb].P,__debug_mmu.tlb[0x40+0xb].L,__debug_mmu.tlb[0x40+0xb].P
+printf "tlb[0x0c]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0xc].L,__debug_mmu.tlb[0xc].P,__debug_mmu.tlb[0x40+0xc].L,__debug_mmu.tlb[0x40+0xc].P
+printf "tlb[0x0d]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0xd].L,__debug_mmu.tlb[0xd].P,__debug_mmu.tlb[0x40+0xd].L,__debug_mmu.tlb[0x40+0xd].P
+printf "tlb[0x0e]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0xe].L,__debug_mmu.tlb[0xe].P,__debug_mmu.tlb[0x40+0xe].L,__debug_mmu.tlb[0x40+0xe].P
+printf "tlb[0x0f]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0xf].L,__debug_mmu.tlb[0xf].P,__debug_mmu.tlb[0x40+0xf].L,__debug_mmu.tlb[0x40+0xf].P
+printf "tlb[0x10]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x10].L,__debug_mmu.tlb[0x10].P,__debug_mmu.tlb[0x40+0x10].L,__debug_mmu.tlb[0x40+0x10].P
+printf "tlb[0x11]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x11].L,__debug_mmu.tlb[0x11].P,__debug_mmu.tlb[0x40+0x11].L,__debug_mmu.tlb[0x40+0x11].P
+printf "tlb[0x12]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x12].L,__debug_mmu.tlb[0x12].P,__debug_mmu.tlb[0x40+0x12].L,__debug_mmu.tlb[0x40+0x12].P
+printf "tlb[0x13]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x13].L,__debug_mmu.tlb[0x13].P,__debug_mmu.tlb[0x40+0x13].L,__debug_mmu.tlb[0x40+0x13].P
+printf "tlb[0x14]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x14].L,__debug_mmu.tlb[0x14].P,__debug_mmu.tlb[0x40+0x14].L,__debug_mmu.tlb[0x40+0x14].P
+printf "tlb[0x15]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x15].L,__debug_mmu.tlb[0x15].P,__debug_mmu.tlb[0x40+0x15].L,__debug_mmu.tlb[0x40+0x15].P
+printf "tlb[0x16]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x16].L,__debug_mmu.tlb[0x16].P,__debug_mmu.tlb[0x40+0x16].L,__debug_mmu.tlb[0x40+0x16].P
+printf "tlb[0x17]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x17].L,__debug_mmu.tlb[0x17].P,__debug_mmu.tlb[0x40+0x17].L,__debug_mmu.tlb[0x40+0x17].P
+printf "tlb[0x18]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x18].L,__debug_mmu.tlb[0x18].P,__debug_mmu.tlb[0x40+0x18].L,__debug_mmu.tlb[0x40+0x18].P
+printf "tlb[0x19]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x19].L,__debug_mmu.tlb[0x19].P,__debug_mmu.tlb[0x40+0x19].L,__debug_mmu.tlb[0x40+0x19].P
+printf "tlb[0x1a]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x1a].L,__debug_mmu.tlb[0x1a].P,__debug_mmu.tlb[0x40+0x1a].L,__debug_mmu.tlb[0x40+0x1a].P
+printf "tlb[0x1b]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x1b].L,__debug_mmu.tlb[0x1b].P,__debug_mmu.tlb[0x40+0x1b].L,__debug_mmu.tlb[0x40+0x1b].P
+printf "tlb[0x1c]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x1c].L,__debug_mmu.tlb[0x1c].P,__debug_mmu.tlb[0x40+0x1c].L,__debug_mmu.tlb[0x40+0x1c].P
+printf "tlb[0x1d]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x1d].L,__debug_mmu.tlb[0x1d].P,__debug_mmu.tlb[0x40+0x1d].L,__debug_mmu.tlb[0x40+0x1d].P
+printf "tlb[0x1e]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x1e].L,__debug_mmu.tlb[0x1e].P,__debug_mmu.tlb[0x40+0x1e].L,__debug_mmu.tlb[0x40+0x1e].P
+printf "tlb[0x1f]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x1f].L,__debug_mmu.tlb[0x1f].P,__debug_mmu.tlb[0x40+0x1f].L,__debug_mmu.tlb[0x40+0x1f].P
+printf "tlb[0x20]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x20].L,__debug_mmu.tlb[0x20].P,__debug_mmu.tlb[0x40+0x20].L,__debug_mmu.tlb[0x40+0x20].P
+printf "tlb[0x21]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x21].L,__debug_mmu.tlb[0x21].P,__debug_mmu.tlb[0x40+0x21].L,__debug_mmu.tlb[0x40+0x21].P
+printf "tlb[0x22]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x22].L,__debug_mmu.tlb[0x22].P,__debug_mmu.tlb[0x40+0x22].L,__debug_mmu.tlb[0x40+0x22].P
+printf "tlb[0x23]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x23].L,__debug_mmu.tlb[0x23].P,__debug_mmu.tlb[0x40+0x23].L,__debug_mmu.tlb[0x40+0x23].P
+printf "tlb[0x24]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x24].L,__debug_mmu.tlb[0x24].P,__debug_mmu.tlb[0x40+0x24].L,__debug_mmu.tlb[0x40+0x24].P
+printf "tlb[0x25]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x25].L,__debug_mmu.tlb[0x25].P,__debug_mmu.tlb[0x40+0x25].L,__debug_mmu.tlb[0x40+0x25].P
+printf "tlb[0x26]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x26].L,__debug_mmu.tlb[0x26].P,__debug_mmu.tlb[0x40+0x26].L,__debug_mmu.tlb[0x40+0x26].P
+printf "tlb[0x27]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x27].L,__debug_mmu.tlb[0x27].P,__debug_mmu.tlb[0x40+0x27].L,__debug_mmu.tlb[0x40+0x27].P
+printf "tlb[0x28]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x28].L,__debug_mmu.tlb[0x28].P,__debug_mmu.tlb[0x40+0x28].L,__debug_mmu.tlb[0x40+0x28].P
+printf "tlb[0x29]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x29].L,__debug_mmu.tlb[0x29].P,__debug_mmu.tlb[0x40+0x29].L,__debug_mmu.tlb[0x40+0x29].P
+printf "tlb[0x2a]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x2a].L,__debug_mmu.tlb[0x2a].P,__debug_mmu.tlb[0x40+0x2a].L,__debug_mmu.tlb[0x40+0x2a].P
+printf "tlb[0x2b]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x2b].L,__debug_mmu.tlb[0x2b].P,__debug_mmu.tlb[0x40+0x2b].L,__debug_mmu.tlb[0x40+0x2b].P
+printf "tlb[0x2c]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x2c].L,__debug_mmu.tlb[0x2c].P,__debug_mmu.tlb[0x40+0x2c].L,__debug_mmu.tlb[0x40+0x2c].P
+printf "tlb[0x2d]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x2d].L,__debug_mmu.tlb[0x2d].P,__debug_mmu.tlb[0x40+0x2d].L,__debug_mmu.tlb[0x40+0x2d].P
+printf "tlb[0x2e]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x2e].L,__debug_mmu.tlb[0x2e].P,__debug_mmu.tlb[0x40+0x2e].L,__debug_mmu.tlb[0x40+0x2e].P
+printf "tlb[0x2f]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x2f].L,__debug_mmu.tlb[0x2f].P,__debug_mmu.tlb[0x40+0x2f].L,__debug_mmu.tlb[0x40+0x2f].P
+printf "tlb[0x30]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x30].L,__debug_mmu.tlb[0x30].P,__debug_mmu.tlb[0x40+0x30].L,__debug_mmu.tlb[0x40+0x30].P
+printf "tlb[0x31]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x31].L,__debug_mmu.tlb[0x31].P,__debug_mmu.tlb[0x40+0x31].L,__debug_mmu.tlb[0x40+0x31].P
+printf "tlb[0x32]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x32].L,__debug_mmu.tlb[0x32].P,__debug_mmu.tlb[0x40+0x32].L,__debug_mmu.tlb[0x40+0x32].P
+printf "tlb[0x33]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x33].L,__debug_mmu.tlb[0x33].P,__debug_mmu.tlb[0x40+0x33].L,__debug_mmu.tlb[0x40+0x33].P
+printf "tlb[0x34]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x34].L,__debug_mmu.tlb[0x34].P,__debug_mmu.tlb[0x40+0x34].L,__debug_mmu.tlb[0x40+0x34].P
+printf "tlb[0x35]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x35].L,__debug_mmu.tlb[0x35].P,__debug_mmu.tlb[0x40+0x35].L,__debug_mmu.tlb[0x40+0x35].P
+printf "tlb[0x36]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x36].L,__debug_mmu.tlb[0x36].P,__debug_mmu.tlb[0x40+0x36].L,__debug_mmu.tlb[0x40+0x36].P
+printf "tlb[0x37]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x37].L,__debug_mmu.tlb[0x37].P,__debug_mmu.tlb[0x40+0x37].L,__debug_mmu.tlb[0x40+0x37].P
+printf "tlb[0x38]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x38].L,__debug_mmu.tlb[0x38].P,__debug_mmu.tlb[0x40+0x38].L,__debug_mmu.tlb[0x40+0x38].P
+printf "tlb[0x39]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x39].L,__debug_mmu.tlb[0x39].P,__debug_mmu.tlb[0x40+0x39].L,__debug_mmu.tlb[0x40+0x39].P
+printf "tlb[0x3a]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x3a].L,__debug_mmu.tlb[0x3a].P,__debug_mmu.tlb[0x40+0x3a].L,__debug_mmu.tlb[0x40+0x3a].P
+printf "tlb[0x3b]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x3b].L,__debug_mmu.tlb[0x3b].P,__debug_mmu.tlb[0x40+0x3b].L,__debug_mmu.tlb[0x40+0x3b].P
+printf "tlb[0x3c]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x3c].L,__debug_mmu.tlb[0x3c].P,__debug_mmu.tlb[0x40+0x3c].L,__debug_mmu.tlb[0x40+0x3c].P
+printf "tlb[0x3d]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x3d].L,__debug_mmu.tlb[0x3d].P,__debug_mmu.tlb[0x40+0x3d].L,__debug_mmu.tlb[0x40+0x3d].P
+printf "tlb[0x3e]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x3e].L,__debug_mmu.tlb[0x3e].P,__debug_mmu.tlb[0x40+0x3e].L,__debug_mmu.tlb[0x40+0x3e].P
+printf "tlb[0x3f]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x3f].L,__debug_mmu.tlb[0x3f].P,__debug_mmu.tlb[0x40+0x3f].L,__debug_mmu.tlb[0x40+0x3f].P
+end
+
+
+define _pgd
+p (pgd_t[0x40])*(pgd_t*)(__debug_mmu.damr[0x3].L)
+end
+
+define _ptd_i
+p (pte_t[0x1000])*(pte_t*)(__debug_mmu.damr[0x4].L)
+end
+
+define _ptd_d
+p (pte_t[0x1000])*(pte_t*)(__debug_mmu.damr[0x5].L)
+end
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/Documentation/fujitsu/frv/gdbstub.txt linux-2.6.10-rc1-mm3-frv/Documentation/fujitsu/frv/gdbstub.txt
--- /warthog/kernels/linux-2.6.10-rc1-mm3/Documentation/fujitsu/frv/gdbstub.txt	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/Documentation/fujitsu/frv/gdbstub.txt	2004-11-05 14:13:03.000000000 +0000
@@ -0,0 +1,130 @@
+			     ====================
+			     DEBUGGING FR-V LINUX
+			     ====================
+
+
+The kernel contains a GDB stub that talks GDB remote protocol across a serial
+port. This permits GDB to single step through the kernel, set breakpoints and
+trap exceptions that happen in kernel space and interrupt execution. It also
+permits the NMI interrupt button or serial port events to jump the kernel into
+the debugger.
+
+On the CPUs that have on-chip UARTs (FR400, FR403, FR405, FR555), the
+GDB stub hijacks a serial port for its own purposes, and makes it
+generate level 15 interrupts (NMI). The kernel proper cannot see the serial
+port in question under these conditions.
+
+On the MB93091-VDK CPU boards, the GDB stub uses UART1, which would otherwise
+be /dev/ttyS1. On the MB93093-PDK, the GDB stub uses UART0. Therefore, on the
+PDK there is no externally accessible serial port and the serial port to
+which the touch screen is attached becomes /dev/ttyS0.
+
+Note that the GDB stub runs entirely within CPU debug mode, and so should not
+incur any exceptions or interrupts whilst it is active. In particular, note
+that the clock will lose time since it is implemented in software.
+
+
+==================
+KERNEL PREPARATION
+==================
+
+Firstly, a debuggable kernel must be built. To do this, unpack the kernel tree
+and copy the configuration that you wish to use to .config. Then reconfigure
+the following things on the "Kernel Hacking" tab:
+
+  (*) "Include debugging information"
+
+      Set this to "Y". This causes all C and Assembly files to be compiled
+      to include debugging information.
+
+  (*) "In-kernel GDB stub"
+
+      Set this to "Y". This causes the GDB stub to be compiled into the
+      kernel.
+
+  (*) "Immediate activation"
+
+      Set this to "Y" if you want the GDB stub to activate as soon as possible
+      and wait for GDB to connect. This allows you to start tracing right from
+      the beginning of start_kernel() in init/main.c.
+
+  (*) "Console through GDB stub"
+
+      Set this to "Y" if you wish to be able to use "console=gdb0" on the
+      command line. That tells the kernel to pass system console messages to
+      GDB (which then prints them on its standard output). This is useful when
+      debugging the serial drivers that'd otherwise be used to pass console
+      messages to the outside world.
+
+Then build as usual, download to the board and execute. Note that if
+"Immediate activation" was selected, then the kernel will wait for GDB to
+attach. If not, then the kernel will boot immediately and GDB will have to
+interupt it or wait for an exception to occur if before doing anything with
+the kernel.
+
+
+=========================
+KERNEL DEBUGGING WITH GDB
+=========================
+
+Set the serial port on the computer that's going to run GDB to the appropriate
+baud rate. Assuming the board's debug port is connected to ttyS0/COM1 on the
+computer doing the debugging:
+
+	stty -F /dev/ttyS0 115200
+
+Then start GDB in the base of the kernel tree:
+
+	frv-uclinux-gdb linux		[uClinux]
+
+Or:
+
+	frv-uclinux-gdb vmlinux		[MMU linux]
+
+When the prompt appears:
+
+	GNU gdb frv-031024
+	Copyright 2003 Free Software Foundation, Inc.
+	GDB is free software, covered by the GNU General Public License, and you are
+	welcome to change it and/or distribute copies of it under certain conditions.
+	Type "show copying" to see the conditions.
+	There is absolutely no warranty for GDB.  Type "show warranty" for details.
+	This GDB was configured as "--host=i686-pc-linux-gnu --target=frv-uclinux"...
+	(gdb) 
+
+Attach to the board like this:
+
+        (gdb) target remote /dev/ttyS0
+	Remote debugging using /dev/ttyS0
+	start_kernel () at init/main.c:395
+	(gdb) 
+
+This should show the appropriate lines from the source too. The kernel can
+then be debugged almost as if it's any other program.
+
+
+===============================
+INTERRUPTING THE RUNNING KERNEL
+===============================
+
+The kernel can be interrupted whilst it is running, causing a jump back to the
+GDB stub and the debugger:
+
+  (*) Pressing Ctrl-C in GDB. This will cause GDB to try and interrupt the
+      kernel by sending an RS232 BREAK over the serial line to the GDB
+      stub. This will (mostly) immediately interrupt the kernel and return it
+      to the debugger.
+
+  (*) Pressing the NMI button on the board will also cause a jump into the
+      debugger.
+
+  (*) Setting a software breakpoint. This sets a break instruction at the
+      desired location which the GDB stub then traps the exception for.
+
+  (*) Setting a hardware breakpoint. The GDB stub is capable of using the IBAR
+      and DBAR registers to assist debugging.
+
+Furthermore, the GDB stub will intercept a number of exceptions automatically
+if they are caused by kernel execution. It will also intercept BUG() macro
+invokation.
+
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/Documentation/fujitsu/frv/mmu-layout.txt linux-2.6.10-rc1-mm3-frv/Documentation/fujitsu/frv/mmu-layout.txt
--- /warthog/kernels/linux-2.6.10-rc1-mm3/Documentation/fujitsu/frv/mmu-layout.txt	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/Documentation/fujitsu/frv/mmu-layout.txt	2004-11-05 14:13:03.000000000 +0000
@@ -0,0 +1,306 @@
+				 =================================
+				 FR451 MMU LINUX MEMORY MANAGEMENT
+				 =================================
+
+============
+MMU HARDWARE
+============
+
+FR451 MMU Linux puts the MMU into EDAT mode whilst running. This means that it uses both the SAT
+registers and the DAT TLB to perform address translation.
+
+There are 8 IAMLR/IAMPR register pairs and 16 DAMLR/DAMPR register pairs for SAT mode.
+
+In DAT mode, there is also a TLB organised in cache format as 64 lines x 2 ways. Each line spans a
+16KB range of addresses, but can match a larger region.
+
+
+===========================
+MEMORY MANAGEMENT REGISTERS
+===========================
+
+Certain control registers are used by the kernel memory management routines:
+
+	REGISTERS		USAGE
+	======================	==================================================
+	IAMR0, DAMR0		Kernel image and data mappings
+	IAMR1, DAMR1		First-chance TLB lookup mapping
+	DAMR2			Page attachment for cache flush by page
+	DAMR3			Current PGD mapping
+	SCR0, DAMR4		Instruction TLB PGE/PTD cache
+	SCR1, DAMR5		Data TLB PGE/PTD cache
+	DAMR6-10		kmap_atomic() mappings
+	DAMR11			I/O mapping
+	CXNR			mm_struct context ID
+	TTBR			Page directory (PGD) pointer (physical address)
+
+
+=====================
+GENERAL MEMORY LAYOUT
+=====================
+
+The physical memory layout is as follows:
+
+  PHYSICAL ADDRESS	CONTROLLER	DEVICE
+  ===================	==============	=======================================
+  00000000 - BFFFFFFF	SDRAM		SDRAM area
+  E0000000 - EFFFFFFF	L-BUS CS2#	VDK SLBUS/PCI window
+  F0000000 - F0FFFFFF	L-BUS CS5#	MB93493 CSC area (DAV daughter board)
+  F1000000 - F1FFFFFF	L-BUS CS7#	(CB70 CPU-card PCMCIA port I/O space)
+  FC000000 - FC0FFFFF	L-BUS CS1#	VDK MB86943 config space
+  FC100000 - FC1FFFFF	L-BUS CS6#	DM9000 NIC I/O space
+  FC200000 - FC2FFFFF	L-BUS CS3#	MB93493 CSR area (DAV daughter board)
+  FD000000 - FDFFFFFF	L-BUS CS4#	(CB70 CPU-card extra flash space)
+  FE000000 - FEFFFFFF			Internal CPU peripherals
+  FF000000 - FF1FFFFF	L-BUS CS0#	Flash 1
+  FF200000 - FF3FFFFF	L-BUS CS0#	Flash 2
+  FFC00000 - FFC0001F	L-BUS CS0#	FPGA
+
+The virtual memory layout is:
+
+  VIRTUAL ADDRESS    PHYSICAL	TRANSLATOR	FLAGS	SIZE	OCCUPATION
+  =================  ========	==============	=======	=======	===================================
+  00004000-BFFFFFFF  various	TLB,xAMR1	D-N-??V	3GB	Userspace
+  C0000000-CFFFFFFF  00000000	xAMPR0		-L-S--V	256MB	Kernel image and data
+  D0000000-D7FFFFFF  various	TLB,xAMR1	D-NS??V	128MB	vmalloc area
+  D8000000-DBFFFFFF  various	TLB,xAMR1	D-NS??V	64MB	kmap() area
+  DC000000-DCFFFFFF  various	TLB			1MB	Secondary kmap_atomic() frame
+  DD000000-DD27FFFF  various	DAMR			160KB	Primary kmap_atomic() frame
+  DD040000			DAMR2/IAMR2	-L-S--V	page	Page cache flush attachment point
+  DD080000			DAMR3		-L-SC-V	page	Page Directory (PGD)
+  DD0C0000			DAMR4		-L-SC-V	page	Cached insn TLB Page Table lookup
+  DD100000			DAMR5		-L-SC-V	page	Cached data TLB Page Table lookup
+  DD140000			DAMR6		-L-S--V	page	kmap_atomic(KM_BOUNCE_READ)
+  DD180000			DAMR7		-L-S--V	page	kmap_atomic(KM_SKB_SUNRPC_DATA)
+  DD1C0000			DAMR8		-L-S--V	page	kmap_atomic(KM_SKB_DATA_SOFTIRQ)
+  DD200000			DAMR9		-L-S--V	page	kmap_atomic(KM_USER0)
+  DD240000			DAMR10		-L-S--V	page	kmap_atomic(KM_USER1)
+  E0000000-FFFFFFFF  E0000000	DAMR11		-L-SC-V	512MB	I/O region
+
+IAMPR1 and DAMPR1 are used as an extension to the TLB.
+
+
+====================
+KMAP AND KMAP_ATOMIC
+====================
+
+To access pages in the page cache (which may not be directly accessible if highmem is available),
+the kernel calls kmap(), does the access and then calls kunmap(); or it calls kmap_atomic(), does
+the access and then calls kunmap_atomic().
+
+kmap() creates an attachment between an arbitrary inaccessible page and a range of virtual
+addresses by installing a PTE in a special page table. The kernel can then access this page as it
+wills. When it's finished, the kernel calls kunmap() to clear the PTE.
+
+kmap_atomic() does something slightly different. In the interests of speed, it chooses one of two
+strategies:
+
+ (1) If possible, kmap_atomic() attaches the requested page to one of DAMPR5 through DAMPR10
+     register pairs; and the matching kunmap_atomic() clears the DAMPR. This makes high memory
+     support really fast as there's no need to flush the TLB or modify the page tables. The DAMLR
+     registers being used for this are preset during boot and don't change over the lifetime of the
+     process. There's a direct mapping between the first few kmap_atomic() types, DAMR number and
+     virtual address slot.
+
+     However, there are more kmap_atomic() types defined than there are DAMR registers available,
+     so we fall back to:
+
+ (2) kmap_atomic() uses a slot in the secondary frame (determined by the type parameter), and then
+     locks an entry in the TLB to translate that slot to the specified page. The number of slots is
+     obviously limited, and their positions are controlled such that each slot is matched by a
+     different line in the TLB. kunmap() ejects the entry from the TLB.
+
+Note that the first three kmap atomic types are really just declared as placeholders. The DAMPR
+registers involved are actually modified directly.
+
+Also note that kmap() itself may sleep, kmap_atomic() may never sleep and both always succeed;
+furthermore, a driver using kmap() may sleep before calling kunmap(), but may not sleep before
+calling kunmap_atomic() if it had previously called kmap_atomic().
+
+
+===============================
+USING MORE THAN 256MB OF MEMORY
+===============================
+
+The kernel cannot access more than 256MB of memory directly. The physical layout, however, permits
+up to 3GB of SDRAM (possibly 3.25GB) to be made available. By using CONFIG_HIGHMEM, the kernel can
+allow userspace (by way of page tables) and itself (by way of kmap) to deal with the memory
+allocation.
+
+External devices can, of course, still DMA to and from all of the SDRAM, even if the kernel can't
+see it directly. The kernel translates page references into real addresses for communicating to the
+devices.
+
+
+===================
+PAGE TABLE TOPOLOGY
+===================
+
+The page tables are arranged in 2-layer format. There is a middle layer (PMD) that would be used in
+3-layer format tables but that is folded into the top layer (PGD) and so consumes no extra memory
+or processing power.
+
+  +------+     PGD    PMD
+  | TTBR |--->+-------------------+
+  +------+    |      |      : STE |
+              | PGE0 | PME0 : STE |
+              |      |      : STE |
+              +-------------------+              Page Table
+              |      |      : STE -------------->+--------+ +0x0000
+              | PGE1 | PME0 : STE -----------+   | PTE0   |
+              |      |      : STE -------+   |   +--------+
+              +-------------------+      |   |   | PTE63  |
+              |      |      : STE |      |   +-->+--------+ +0x0100
+              | PGE2 | PME0 : STE |      |       | PTE64  |
+              |      |      : STE |      |       +--------+
+              +-------------------+      |       | PTE127 |
+              |      |      : STE |      +------>+--------+ +0x0200
+              | PGE3 | PME0 : STE |              | PTE128 |
+              |      |      : STE |              +--------+
+              +-------------------+              | PTE191 |
+                                                 +--------+ +0x0300
+
+Each Page Directory (PGD) is 16KB (page size) in size and is divided into 64 entries (PGEs). Each
+PGE contains one Page Mid Directory (PMD).
+
+Each PMD is 256 bytes in size and contains a single entry (PME). Each PME holds 64 FR451 MMU
+segment table entries of 4 bytes apiece. Each PME "points to" a page table. In practice, each STE
+points to a subset of the page table, the first to PT+0x0000, the second to PT+0x0100, the third to
+PT+0x200, and so on.
+
+Each PGE and PME covers 64MB of the total virtual address space.
+
+Each Page Table (PTD) is 16KB (page size) in size, and is divided into 4096 entries (PTEs). Each
+entry can point to one 16KB page. In practice, each Linux page table is subdivided into 64 FR451
+MMU page tables. But they are all grouped together to make management easier, in particular rmap
+support is then trivial.
+
+Grouping page tables in this fashion makes PGE caching in SCR0/SCR1 more efficient because the
+coverage of the cached item is greater.
+
+Page tables for the vmalloc area are allocated at boot time and shared between all mm_structs.
+
+
+=================
+USER SPACE LAYOUT
+=================
+
+For MMU capable Linux, the regions userspace code are allowed to access are kept entirely separate
+from those dedicated to the kernel:
+
+	VIRTUAL ADDRESS    SIZE   PURPOSE
+	=================  =====  ===================================
+	00000000-00003fff  4KB    NULL pointer access trap
+	00004000-01ffffff  ~32MB  lower mmap space (grows up)
+	02000000-021fffff  2MB    Stack space (grows down from top)
+	02200000-nnnnnnnn         Executable mapping
+        nnnnnnnn-                 brk space (grows up)
+	        -bfffffff         upper mmap space (grows down)
+
+This is so arranged so as to make best use of the 16KB page tables and the way in which PGEs/PMEs
+are cached by the TLB handler. The lower mmap space is filled first, and then the upper mmap space
+is filled.
+
+
+===============================
+GDB-STUB MMU DEBUGGING SERVICES
+===============================
+
+The gdb-stub included in this kernel provides a number of services to aid in the debugging of MMU
+related kernel services:
+
+ (*) Every time the kernel stops, certain state information is dumped into __debug_mmu. This
+     variable is defined in arch/frv/kernel/gdb-stub.c. Note that the gdbinit file in this
+     directory has some useful macros for dealing with this.
+
+     (*) __debug_mmu.tlb[]
+
+	 This receives the current TLB contents. This can be viewed with the _tlb GDB macro:
+
+		(gdb) _tlb
+		tlb[0x00]: 01000005 00718203  01000002 00718203
+		tlb[0x01]: 01004002 006d4201  01004005 006d4203
+		tlb[0x02]: 01008002 006d0201  01008006 00004200
+		tlb[0x03]: 0100c006 007f4202  0100c002 0064c202
+		tlb[0x04]: 01110005 00774201  01110002 00774201
+		tlb[0x05]: 01114005 00770201  01114002 00770201
+		tlb[0x06]: 01118002 0076c201  01118005 0076c201
+		...
+		tlb[0x3d]: 010f4002 00790200  001f4002 0054ca02
+		tlb[0x3e]: 010f8005 0078c201  010f8002 0078c201
+		tlb[0x3f]: 001fc002 0056ca01  001fc005 00538a01
+
+     (*) __debug_mmu.iamr[]
+     (*) __debug_mmu.damr[]
+
+	 These receive the current IAMR and DAMR contents. These can be viewed with with the _amr
+	 GDB macro:
+
+		(gdb) _amr
+		AMRx           DAMR                    IAMR         
+		====   =====================   =====================
+		amr0 : L:c0000000 P:00000cb9 : L:c0000000 P:000004b9
+		amr1 : L:01070005 P:006f9203 : L:0102c005 P:006a1201
+		amr2 : L:d8d00000 P:00000000 : L:d8d00000 P:00000000
+		amr3 : L:d8d04000 P:00534c0d : L:00000000 P:00000000
+		amr4 : L:d8d08000 P:00554c0d : L:00000000 P:00000000
+		amr5 : L:d8d0c000 P:00554c0d : L:00000000 P:00000000
+		amr6 : L:d8d10000 P:00000000 : L:00000000 P:00000000
+		amr7 : L:d8d14000 P:00000000 : L:00000000 P:00000000
+		amr8 : L:d8d18000 P:00000000
+		amr9 : L:d8d1c000 P:00000000
+		amr10: L:d8d20000 P:00000000
+		amr11: L:e0000000 P:e0000ccd
+
+ (*) The current task's page directory is bound to DAMR3.
+
+     This can be viewed with the _pgd GDB macro:
+	
+	(gdb) _pgd
+	$3 = {{pge = {{ste = {0x554001, 0x554101, 0x554201, 0x554301, 0x554401, 
+		  0x554501, 0x554601, 0x554701, 0x554801, 0x554901, 0x554a01, 
+		  0x554b01, 0x554c01, 0x554d01, 0x554e01, 0x554f01, 0x555001, 
+		  0x555101, 0x555201, 0x555301, 0x555401, 0x555501, 0x555601, 
+		  0x555701, 0x555801, 0x555901, 0x555a01, 0x555b01, 0x555c01, 
+		  0x555d01, 0x555e01, 0x555f01, 0x556001, 0x556101, 0x556201, 
+		  0x556301, 0x556401, 0x556501, 0x556601, 0x556701, 0x556801, 
+		  0x556901, 0x556a01, 0x556b01, 0x556c01, 0x556d01, 0x556e01, 
+		  0x556f01, 0x557001, 0x557101, 0x557201, 0x557301, 0x557401, 
+		  0x557501, 0x557601, 0x557701, 0x557801, 0x557901, 0x557a01, 
+		  0x557b01, 0x557c01, 0x557d01, 0x557e01, 0x557f01}}}}, {pge = {{
+		ste = {0x0 <repeats 64 times>}}}} <repeats 51 times>, {pge = {{ste = {
+		  0x248001, 0x248101, 0x248201, 0x248301, 0x248401, 0x248501, 
+		  0x248601, 0x248701, 0x248801, 0x248901, 0x248a01, 0x248b01, 
+		  0x248c01, 0x248d01, 0x248e01, 0x248f01, 0x249001, 0x249101, 
+		  0x249201, 0x249301, 0x249401, 0x249501, 0x249601, 0x249701, 
+		  0x249801, 0x249901, 0x249a01, 0x249b01, 0x249c01, 0x249d01, 
+		  0x249e01, 0x249f01, 0x24a001, 0x24a101, 0x24a201, 0x24a301, 
+		  0x24a401, 0x24a501, 0x24a601, 0x24a701, 0x24a801, 0x24a901, 
+		  0x24aa01, 0x24ab01, 0x24ac01, 0x24ad01, 0x24ae01, 0x24af01, 
+		  0x24b001, 0x24b101, 0x24b201, 0x24b301, 0x24b401, 0x24b501, 
+		  0x24b601, 0x24b701, 0x24b801, 0x24b901, 0x24ba01, 0x24bb01, 
+		  0x24bc01, 0x24bd01, 0x24be01, 0x24bf01}}}}, {pge = {{ste = {
+		  0x0 <repeats 64 times>}}}} <repeats 11 times>}
+
+ (*) The PTD last used by the instruction TLB miss handler is attached to DAMR4.
+ (*) The PTD last used by the data TLB miss handler is attached to DAMR5.
+
+     These can be viewed with the _ptd_i and _ptd_d GDB macros:
+
+	(gdb) _ptd_d
+	$5 = {{pte = 0x0} <repeats 127 times>, {pte = 0x539b01}, {
+	    pte = 0x0} <repeats 896 times>, {pte = 0x719303}, {pte = 0x6d5303}, {
+	    pte = 0x0}, {pte = 0x0}, {pte = 0x0}, {pte = 0x0}, {pte = 0x0}, {
+	    pte = 0x0}, {pte = 0x0}, {pte = 0x0}, {pte = 0x0}, {pte = 0x6a1303}, {
+	    pte = 0x0} <repeats 12 times>, {pte = 0x709303}, {pte = 0x0}, {pte = 0x0}, 
+	  {pte = 0x6fd303}, {pte = 0x6f9303}, {pte = 0x6f5303}, {pte = 0x0}, {
+	    pte = 0x6ed303}, {pte = 0x531b01}, {pte = 0x50db01}, {
+	    pte = 0x0} <repeats 13 times>, {pte = 0x5303}, {pte = 0x7f5303}, {
+	    pte = 0x509b01}, {pte = 0x505b01}, {pte = 0x7c9303}, {pte = 0x7b9303}, {
+	    pte = 0x7b5303}, {pte = 0x7b1303}, {pte = 0x7ad303}, {pte = 0x0}, {
+	    pte = 0x0}, {pte = 0x7a1303}, {pte = 0x0}, {pte = 0x795303}, {pte = 0x0}, {
+	    pte = 0x78d303}, {pte = 0x0}, {pte = 0x0}, {pte = 0x0}, {pte = 0x0}, {
+	    pte = 0x0}, {pte = 0x775303}, {pte = 0x771303}, {pte = 0x76d303}, {
+	    pte = 0x0}, {pte = 0x765303}, {pte = 0x7c5303}, {pte = 0x501b01}, {
+	    pte = 0x4f1b01}, {pte = 0x4edb01}, {pte = 0x0}, {pte = 0x4f9b01}, {
+	    pte = 0x4fdb01}, {pte = 0x0} <repeats 2992 times>}
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/Documentation/fujitsu/frv/README.txt linux-2.6.10-rc1-mm3-frv/Documentation/fujitsu/frv/README.txt
--- /warthog/kernels/linux-2.6.10-rc1-mm3/Documentation/fujitsu/frv/README.txt	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/Documentation/fujitsu/frv/README.txt	2004-11-05 14:13:03.000000000 +0000
@@ -0,0 +1,51 @@
+		       ================================
+		       Fujitsu FR-V LINUX DOCUMENTATION
+		       ================================
+
+This directory contains documentation for the Fujitsu FR-V CPU architecture
+port of Linux.
+
+The following documents are available:
+
+ (*) features.txt
+
+     A description of the basic features inherent in this architecture port.
+
+
+ (*) configuring.txt
+
+     A summary of the configuration options particular to this architecture.
+
+
+ (*) booting.txt
+
+     A description of how to boot the kernel image and a summary of the kernel
+     command line options.
+
+
+ (*) gdbstub.txt
+
+     A description of how to debug the kernel using GDB attached by serial
+     port, and a summary of the services available.
+
+
+ (*) mmu-layout.txt
+
+     A description of the virtual and physical memory layout used in the
+     MMU linux kernel, and the registers used to support it.
+
+
+ (*) gdbinit
+
+     An example .gdbinit file for use with GDB. It includes macros for viewing
+     MMU state on the FR451. See mmu-layout.txt for more information.
+
+
+ (*) clock.txt
+
+     A description of the CPU clock scaling interface.
+
+
+ (*) atomic-ops.txt
+
+     A description of how the FR-V kernel's atomic operations work.

^ permalink raw reply	[flat|nested] 87+ messages in thread

* [PATCH 1/20] FRV: Fujitsu FR-V CPU arch maintainer record
@ 2004-11-08 14:34 dhowells
  2004-11-08 14:34 ` [PATCH 2/20] FRV: Fujitsu FR-V arch documentation dhowells
                   ` (16 more replies)
  0 siblings, 17 replies; 87+ messages in thread
From: dhowells @ 2004-11-08 14:34 UTC (permalink / raw)
  To: torvalds, akpm, davidm; +Cc: linux-kernel, uclinux-dev

The attached patch supplies the maintainer record for an architecture
implementation for the Fujistu FR-V CPU series.

Signed-Off-By: dhowells@redhat.com
---
diffstat frv-maintainer-2610rc1mm3.diff
 MAINTAINERS |    5 +++++
 1 files changed, 5 insertions(+)

diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/MAINTAINERS linux-2.6.10-rc1-mm3-frv/MAINTAINERS
--- /warthog/kernels/linux-2.6.10-rc1-mm3/MAINTAINERS	2004-11-05 13:15:52.000000000 +0000
+++ linux-2.6.10-rc1-mm3-frv/MAINTAINERS	2004-11-05 14:13:04.000000000 +0000
@@ -856,6 +856,11 @@ M:	hch@infradead.org
 W:	ftp://ftp.openlinux.org/pub/people/hch/vxfs
 S:	Maintained
 
+FUJITSU FR-V PORT
+P:	David Howells
+M:	dhowells@redhat.com
+S:	Maintained
+
 FTAPE/QIC-117
 L:	linux-tape@vger.kernel.org
 W:	http://sourceforge.net/projects/ftape

^ permalink raw reply	[flat|nested] 87+ messages in thread

* [PATCH 7/20] FRV: Fujitsu FR-V CPU arch implementation part 5
  2004-11-08 14:34 [PATCH 1/20] FRV: Fujitsu FR-V CPU arch maintainer record dhowells
                   ` (3 preceding siblings ...)
  2004-11-08 14:34 ` [PATCH 5/20] FRV: Fujitsu FR-V CPU arch implementation part 3 dhowells
@ 2004-11-08 14:34 ` dhowells
  2004-11-09 15:09   ` Geert Uytterhoeven
  2004-11-08 14:34 ` [PATCH 3/20] FRV: Fujitsu FR-V CPU arch implementation part 1 dhowells
                   ` (11 subsequent siblings)
  16 siblings, 1 reply; 87+ messages in thread
From: dhowells @ 2004-11-08 14:34 UTC (permalink / raw)
  To: torvalds, akpm, davidm; +Cc: linux-kernel, uclinux-dev

The attached patches provides part 5 of an architecture implementation
for the Fujitsu FR-V CPU series, configurably as Linux or uClinux.

Signed-Off-By: dhowells@redhat.com
---
diffstat frv-arch_5-2610rc1mm3.diff
 ptrace.c    |  771 ++++++++++++++++++++++++++++++++++++++
 semaphore.c |  142 +++++++
 setup.c     | 1202 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 signal.c    |  595 +++++++++++++++++++++++++++++
 sleep.S     |  356 +++++++++++++++++
 switch_to.S |  486 ++++++++++++++++++++++++
 6 files changed, 3552 insertions(+)

diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/kernel/ptrace.c linux-2.6.10-rc1-mm3-frv/arch/frv/kernel/ptrace.c
--- /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/kernel/ptrace.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/arch/frv/kernel/ptrace.c	2004-11-05 14:13:03.199555230 +0000
@@ -0,0 +1,771 @@
+/*
+ *  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/smp_lock.h>
+#include <linux/errno.h>
+#include <linux/ptrace.h>
+#include <linux/user.h>
+#include <linux/config.h>
+#include <linux/security.h>
+
+#include <asm/uaccess.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/system.h>
+#include <asm/processor.h>
+#include <asm/unistd.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 0x8000
+
+/*
+ * Get contents of register REGNO in task TASK.
+ */
+static inline long get_reg(struct task_struct *task, int regno)
+{
+	struct user_context *user = task->thread.user;
+
+	if (regno < 0 || regno >= PT__END)
+		return 0;
+
+	return ((unsigned long *) user)[regno];
+}
+
+/*
+ * Write contents of register REGNO in task TASK.
+ */
+static inline int put_reg(struct task_struct *task, int regno,
+			  unsigned long data)
+{
+	struct user_context *user = task->thread.user;
+
+	if (regno < 0 || regno >= PT__END)
+		return -EIO;
+
+	switch (regno) {
+	case PT_GR(0):
+		return 0;
+	case PT_PSR:
+	case PT__STATUS:
+		return -EIO;
+	default:
+		((unsigned long *) user)[regno] = data;
+		return 0;
+	}
+}
+
+/*
+ * check that an address falls within the bounds of the target process's memory mappings
+ */
+static inline int is_user_addr_valid(struct task_struct *child,
+				     unsigned long start, unsigned long len)
+{
+#ifdef CONFIG_MMU
+	if (start >= PAGE_OFFSET || len > PAGE_OFFSET - start)
+		return -EIO;
+	return 0;
+#else
+	struct mm_tblock_struct *tblock;
+
+	for (tblock = child->mm->context.tblock; tblock; tblock = tblock->next)
+		if (start >= tblock->vma->vm_start && start + len <= tblock->vma->vm_end)
+			return 0;
+
+	return -EIO;
+#endif
+}
+
+/*
+ * Called by kernel/ptrace.c when detaching..
+ *
+ * Control h/w single stepping
+ */
+void ptrace_disable(struct task_struct *child)
+{
+	child->thread.frame0->__status &= ~REG__STATUS_STEP;
+}
+
+void ptrace_enable(struct task_struct *child)
+{
+	child->thread.frame0->__status |= REG__STATUS_STEP;
+}
+
+asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
+{
+	struct task_struct *child;
+	unsigned long tmp;
+	int ret;
+
+	lock_kernel();
+	ret = -EPERM;
+	if (request == PTRACE_TRACEME) {
+		/* are we already being traced? */
+		if (current->ptrace & PT_PTRACED)
+			goto out;
+		ret = security_ptrace(current->parent, current);
+		if (ret)
+			goto out;
+		/* set the ptrace bit in the process flags. */
+		current->ptrace |= PT_PTRACED;
+		ret = 0;
+		goto out;
+	}
+	ret = -ESRCH;
+	read_lock(&tasklist_lock);
+	child = find_task_by_pid(pid);
+	if (child)
+		get_task_struct(child);
+	read_unlock(&tasklist_lock);
+	if (!child)
+		goto out;
+
+	ret = -EPERM;
+	if (pid == 1)		/* you may not mess with init */
+		goto out_tsk;
+
+	if (request == PTRACE_ATTACH) {
+		ret = ptrace_attach(child);
+		goto out_tsk;
+	}
+
+	ret = ptrace_check_attach(child, request == PTRACE_KILL);
+	if (ret < 0)
+		goto out_tsk;
+
+	switch (request) {
+		/* when I and D space are separate, these will need to be fixed. */
+	case PTRACE_PEEKTEXT: /* read word at location addr. */
+	case PTRACE_PEEKDATA: {
+		int copied;
+
+		ret = -EIO;
+		if (is_user_addr_valid(child, addr, sizeof(tmp)) < 0)
+			break;
+
+		copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0);
+		if (copied != sizeof(tmp))
+			break;
+
+		ret = put_user(tmp,(unsigned long *) data);
+		break;
+	}
+
+		/* read the word at location addr in the USER area. */
+	case PTRACE_PEEKUSR: {
+		tmp = 0;
+		ret = -EIO;
+		if ((addr & 3) || addr < 0)
+			break;
+
+		ret = 0;
+		switch (addr >> 2) {
+		case 0 ... PT__END - 1:
+			tmp = get_reg(child, addr >> 2);
+			break;
+
+		case PT__END + 0:
+			tmp = child->mm->end_code - child->mm->start_code;
+			break;
+
+		case PT__END + 1:
+			tmp = child->mm->end_data - child->mm->start_data;
+			break;
+
+		case PT__END + 2:
+			tmp = child->mm->start_stack - child->mm->start_brk;
+			break;
+
+		case PT__END + 3:
+			tmp = child->mm->start_code;
+			break;
+
+		case PT__END + 4:
+			tmp = child->mm->start_stack;
+			break;
+
+		default:
+			ret = -EIO;
+			break;
+		}
+
+		if (ret == 0)
+			ret = put_user(tmp, (unsigned long *) data);
+		break;
+	}
+
+		/* when I and D space are separate, this will have to be fixed. */
+	case PTRACE_POKETEXT: /* write the word at location addr. */
+	case PTRACE_POKEDATA:
+		ret = -EIO;
+		if (is_user_addr_valid(child, addr, sizeof(tmp)) < 0)
+			break;
+		if (access_process_vm(child, addr, &data, sizeof(data), 1) != sizeof(data))
+			break;
+		ret = 0;
+		break;
+
+	case PTRACE_POKEUSR: /* write the word at location addr in the USER area */
+		ret = -EIO;
+		if ((addr & 3) || addr < 0)
+			break;
+
+		ret = 0;
+		switch (addr >> 2) {
+		case 0 ... PT__END-1:
+			ret = put_reg(child, addr >> 2, data);
+			break;
+
+		default:
+			ret = -EIO;
+			break;
+		}
+		break;
+
+	case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */
+	case PTRACE_CONT: /* restart after signal. */
+		ret = -EIO;
+		if ((unsigned long) data > _NSIG)
+			break;
+		if (request == PTRACE_SYSCALL)
+			set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
+		else
+			clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
+		child->exit_code = data;
+		ptrace_disable(child);
+		wake_up_process(child);
+		ret = 0;
+		break;
+
+		/* make the child exit.  Best I can do is send it a sigkill.
+		 * perhaps it should be put in the status that it wants to
+		 * exit.
+		 */
+	case PTRACE_KILL:
+		ret = 0;
+		if (child->exit_state == EXIT_ZOMBIE)	/* already dead */
+			break;
+		child->exit_code = SIGKILL;
+		clear_tsk_thread_flag(child, TIF_SINGLESTEP);
+		ptrace_disable(child);
+		wake_up_process(child);
+		break;
+
+	case PTRACE_SINGLESTEP:  /* set the trap flag. */
+		ret = -EIO;
+		if ((unsigned long) data > _NSIG)
+			break;
+		clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
+		ptrace_enable(child);
+		child->exit_code = data;
+		wake_up_process(child);
+		ret = 0;
+		break;
+
+	case PTRACE_DETACH:	/* detach a process that was attached. */
+		ret = ptrace_detach(child, data);
+		break;
+
+	case PTRACE_GETREGS: { /* Get all integer regs from the child. */
+		int i;
+		for (i = 0; i < PT__GPEND; i++) {
+			tmp = get_reg(child, i);
+			if (put_user(tmp, (unsigned long *) data)) {
+				ret = -EFAULT;
+				break;
+			}
+			data += sizeof(long);
+		}
+		ret = 0;
+		break;
+	}
+
+	case PTRACE_SETREGS: { /* Set all integer regs in the child. */
+		int i;
+		for (i = 0; i < PT__GPEND; i++) {
+			if (get_user(tmp, (unsigned long *) data)) {
+				ret = -EFAULT;
+				break;
+			}
+			put_reg(child, i, tmp);
+			data += sizeof(long);
+		}
+		ret = 0;
+		break;
+	}
+
+	case PTRACE_GETFPREGS: { /* Get the child FP/Media state. */
+		ret = 0;
+		if (copy_to_user((void *) data,
+				 &child->thread.user->f,
+				 sizeof(child->thread.user->f)))
+			ret = -EFAULT;
+		break;
+	}
+
+	case PTRACE_SETFPREGS: { /* Set the child FP/Media state. */
+		ret = 0;
+		if (copy_from_user(&child->thread.user->f,
+				   (void *) data,
+				   sizeof(child->thread.user->f)))
+			ret = -EFAULT;
+		break;
+	}
+
+	case PTRACE_GETFDPIC:
+		tmp = 0;
+		switch (addr) {
+		case PTRACE_GETFDPIC_EXEC:
+			tmp = child->mm->context.exec_fdpic_loadmap;
+			break;
+		case PTRACE_GETFDPIC_INTERP:
+			tmp = child->mm->context.interp_fdpic_loadmap;
+			break;
+		default:
+			break;
+		}
+
+		ret = 0;
+		if (put_user(tmp, (unsigned long *) data)) {
+			ret = -EFAULT;
+			break;
+		}
+		break;
+
+	default:
+		ret = -EIO;
+		break;
+	}
+out_tsk:
+	free_task_struct(child);
+out:
+	unlock_kernel();
+	return ret;
+}
+
+int __nongprelbss kstrace;
+
+static const struct {
+	const char	*name;
+	unsigned	argmask;
+} __syscall_name_table[NR_syscalls] = {
+	[0]	= { "restart_syscall"			},
+	[1]	= { "exit",		0x000001	},
+	[2]	= { "fork",		0xffffff	},
+	[3]	= { "read",		0x000141	},
+	[4]	= { "write",		0x000141	},
+	[5]	= { "open",		0x000235	},
+	[6]	= { "close",		0x000001	},
+	[7]	= { "waitpid",		0x000141	},
+	[8]	= { "creat",		0x000025	},
+	[9]	= { "link",		0x000055	},
+	[10]	= { "unlink",		0x000005	},
+	[11]	= { "execve",		0x000445	},
+	[12]	= { "chdir",		0x000005	},
+	[13]	= { "time",		0x000004	},
+	[14]	= { "mknod",		0x000325	},
+	[15]	= { "chmod",		0x000025	},
+	[16]	= { "lchown",		0x000025	},
+	[17]	= { "break" },
+	[18]	= { "oldstat",		0x000045	},
+	[19]	= { "lseek",		0x000131	},
+	[20]	= { "getpid",		0xffffff	},
+	[21]	= { "mount",		0x043555	},
+	[22]	= { "umount",		0x000005	},
+	[23]	= { "setuid",		0x000001	},
+	[24]	= { "getuid",		0xffffff	},
+	[25]	= { "stime",		0x000004	},
+	[26]	= { "ptrace",		0x004413	},
+	[27]	= { "alarm",		0x000001	},
+	[28]	= { "oldfstat",		0x000041	},
+	[29]	= { "pause",		0xffffff	},
+	[30]	= { "utime",		0x000045	},
+	[31]	= { "stty" },
+	[32]	= { "gtty" },
+	[33]	= { "access",		0x000025	},
+	[34]	= { "nice",		0x000001	},
+	[35]	= { "ftime" },
+	[36]	= { "sync",		0xffffff	},
+	[37]	= { "kill",		0x000011	},
+	[38]	= { "rename",		0x000055	},
+	[39]	= { "mkdir",		0x000025	},
+	[40]	= { "rmdir",		0x000005	},
+	[41]	= { "dup",		0x000001	},
+	[42]	= { "pipe",		0x000004	},
+	[43]	= { "times",		0x000004	},
+	[44]	= { "prof" },
+	[45]	= { "brk",		0x000004	},
+	[46]	= { "setgid",		0x000001	},
+	[47]	= { "getgid",		0xffffff	},
+	[48]	= { "signal",		0x000041	},
+	[49]	= { "geteuid",		0xffffff	},
+	[50]	= { "getegid",		0xffffff	},
+	[51]	= { "acct",		0x000005	},
+	[52]	= { "umount2",		0x000035	},
+	[53]	= { "lock" },
+	[54]	= { "ioctl",		0x000331	},
+	[55]	= { "fcntl",		0x000331	},
+	[56]	= { "mpx" },
+	[57]	= { "setpgid",		0x000011	},
+	[58]	= { "ulimit" },
+	[60]	= { "umask",		0x000002	},
+	[61]	= { "chroot",		0x000005	},
+	[62]	= { "ustat",		0x000043	},
+	[63]	= { "dup2",		0x000011	},
+	[64]	= { "getppid",		0xffffff	},
+	[65]	= { "getpgrp",		0xffffff	},
+	[66]	= { "setsid",		0xffffff	},
+	[67]	= { "sigaction" },
+	[68]	= { "sgetmask" },
+	[69]	= { "ssetmask" },
+	[70]	= { "setreuid" },
+	[71]	= { "setregid" },
+	[72]	= { "sigsuspend" },
+	[73]	= { "sigpending" },
+	[74]	= { "sethostname" },
+	[75]	= { "setrlimit" },
+	[76]	= { "getrlimit" },
+	[77]	= { "getrusage" },
+	[78]	= { "gettimeofday" },
+	[79]	= { "settimeofday" },
+	[80]	= { "getgroups" },
+	[81]	= { "setgroups" },
+	[82]	= { "select" },
+	[83]	= { "symlink" },
+	[84]	= { "oldlstat" },
+	[85]	= { "readlink" },
+	[86]	= { "uselib" },
+	[87]	= { "swapon" },
+	[88]	= { "reboot" },
+	[89]	= { "readdir" },
+	[91]	= { "munmap",		0x000034	},
+	[92]	= { "truncate" },
+	[93]	= { "ftruncate" },
+	[94]	= { "fchmod" },
+	[95]	= { "fchown" },
+	[96]	= { "getpriority" },
+	[97]	= { "setpriority" },
+	[99]	= { "statfs" },
+	[100]	= { "fstatfs" },
+	[102]	= { "socketcall" },
+	[103]	= { "syslog" },
+	[104]	= { "setitimer" },
+	[105]	= { "getitimer" },
+	[106]	= { "stat" },
+	[107]	= { "lstat" },
+	[108]	= { "fstat" },
+	[111]	= { "vhangup" },
+	[114]	= { "wait4" },
+	[115]	= { "swapoff" },
+	[116]	= { "sysinfo" },
+	[117]	= { "ipc" },
+	[118]	= { "fsync" },
+	[119]	= { "sigreturn" },
+	[120]	= { "clone" },
+	[121]	= { "setdomainname" },
+	[122]	= { "uname" },
+	[123]	= { "modify_ldt" },
+	[123]	= { "cacheflush" },
+	[124]	= { "adjtimex" },
+	[125]	= { "mprotect" },
+	[126]	= { "sigprocmask" },
+	[127]	= { "create_module" },
+	[128]	= { "init_module" },
+	[129]	= { "delete_module" },
+	[130]	= { "get_kernel_syms" },
+	[131]	= { "quotactl" },
+	[132]	= { "getpgid" },
+	[133]	= { "fchdir" },
+	[134]	= { "bdflush" },
+	[135]	= { "sysfs" },
+	[136]	= { "personality" },
+	[137]	= { "afs_syscall" },
+	[138]	= { "setfsuid" },
+	[139]	= { "setfsgid" },
+	[140]	= { "_llseek",			0x014331	},
+	[141]	= { "getdents" },
+	[142]	= { "_newselect",		0x000141	},
+	[143]	= { "flock" },
+	[144]	= { "msync" },
+	[145]	= { "readv" },
+	[146]	= { "writev" },
+	[147]	= { "getsid",			0x000001	},
+	[148]	= { "fdatasync",		0x000001	},
+	[149]	= { "_sysctl",			0x000004	},
+	[150]	= { "mlock" },
+	[151]	= { "munlock" },
+	[152]	= { "mlockall" },
+	[153]	= { "munlockall" },
+	[154]	= { "sched_setparam" },
+	[155]	= { "sched_getparam" },
+	[156]	= { "sched_setscheduler" },
+	[157]	= { "sched_getscheduler" },
+	[158]	= { "sched_yield" },
+	[159]	= { "sched_get_priority_max" },
+	[160]	= { "sched_get_priority_min" },
+	[161]	= { "sched_rr_get_interval" },
+	[162]	= { "nanosleep",		0x000044	},
+	[163]	= { "mremap" },
+	[164]	= { "setresuid" },
+	[165]	= { "getresuid" },
+	[166]	= { "vm86" },
+	[167]	= { "query_module" },
+	[168]	= { "poll" },
+	[169]	= { "nfsservctl" },
+	[170]	= { "setresgid" },
+	[171]	= { "getresgid" },
+	[172]	= { "prctl",			0x333331	},
+	[173]	= { "rt_sigreturn",		0xffffff	},
+	[174]	= { "rt_sigaction",		0x001441	},
+	[175]	= { "rt_sigprocmask",		0x001441	},
+	[176]	= { "rt_sigpending",		0x000014	},
+	[177]	= { "rt_sigtimedwait",		0x001444	},
+	[178]	= { "rt_sigqueueinfo",		0x000411	},
+	[179]	= { "rt_sigsuspend",		0x000014	},
+	[180]	= { "pread",			0x003341	},
+	[181]	= { "pwrite",			0x003341	},
+	[182]	= { "chown",			0x000115	},
+	[183]	= { "getcwd" },
+	[184]	= { "capget" },
+	[185]	= { "capset" },
+	[186]	= { "sigaltstack" },
+	[187]	= { "sendfile" },
+	[188]	= { "getpmsg" },
+	[189]	= { "putpmsg" },
+	[190]	= { "vfork",			0xffffff	},
+	[191]	= { "ugetrlimit" },
+	[192]	= { "mmap2",			0x313314	},
+	[193]	= { "truncate64" },
+	[194]	= { "ftruncate64" },
+	[195]	= { "stat64",			0x000045	},
+	[196]	= { "lstat64",			0x000045	},
+	[197]	= { "fstat64",			0x000041	},
+	[198]	= { "lchown32" },
+	[199]	= { "getuid32",			0xffffff	},
+	[200]	= { "getgid32",			0xffffff	},
+	[201]	= { "geteuid32",		0xffffff	},
+	[202]	= { "getegid32",		0xffffff	},
+	[203]	= { "setreuid32" },
+	[204]	= { "setregid32" },
+	[205]	= { "getgroups32" },
+	[206]	= { "setgroups32" },
+	[207]	= { "fchown32" },
+	[208]	= { "setresuid32" },
+	[209]	= { "getresuid32" },
+	[210]	= { "setresgid32" },
+	[211]	= { "getresgid32" },
+	[212]	= { "chown32" },
+	[213]	= { "setuid32" },
+	[214]	= { "setgid32" },
+	[215]	= { "setfsuid32" },
+	[216]	= { "setfsgid32" },
+	[217]	= { "pivot_root" },
+	[218]	= { "mincore" },
+	[219]	= { "madvise" },
+	[220]	= { "getdents64" },
+	[221]	= { "fcntl64" },
+	[223]	= { "security" },
+	[224]	= { "gettid" },
+	[225]	= { "readahead" },
+	[226]	= { "setxattr" },
+	[227]	= { "lsetxattr" },
+	[228]	= { "fsetxattr" },
+	[229]	= { "getxattr" },
+	[230]	= { "lgetxattr" },
+	[231]	= { "fgetxattr" },
+	[232]	= { "listxattr" },
+	[233]	= { "llistxattr" },
+	[234]	= { "flistxattr" },
+	[235]	= { "removexattr" },
+	[236]	= { "lremovexattr" },
+	[237]	= { "fremovexattr" },
+	[238]	= { "tkill" },
+	[239]	= { "sendfile64" },
+	[240]	= { "futex" },
+	[241]	= { "sched_setaffinity" },
+	[242]	= { "sched_getaffinity" },
+	[243]	= { "set_thread_area" },
+	[244]	= { "get_thread_area" },
+	[245]	= { "io_setup" },
+	[246]	= { "io_destroy" },
+	[247]	= { "io_getevents" },
+	[248]	= { "io_submit" },
+	[249]	= { "io_cancel" },
+	[250]	= { "fadvise64" },
+	[252]	= { "exit_group",		0x000001	},
+	[253]	= { "lookup_dcookie" },
+	[254]	= { "epoll_create" },
+	[255]	= { "epoll_ctl" },
+	[256]	= { "epoll_wait" },
+	[257]	= { "remap_file_pages" },
+	[258]	= { "set_tid_address" },
+	[259]	= { "timer_create" },
+	[260]	= { "timer_settime" },
+	[261]	= { "timer_gettime" },
+	[262]	= { "timer_getoverrun" },
+	[263]	= { "timer_delete" },
+	[264]	= { "clock_settime" },
+	[265]	= { "clock_gettime" },
+	[266]	= { "clock_getres" },
+	[267]	= { "clock_nanosleep" },
+	[268]	= { "statfs64" },
+	[269]	= { "fstatfs64" },
+	[270]	= { "tgkill" },
+	[271]	= { "utimes" },
+	[272]	= { "fadvise64_64" },
+	[273]	= { "vserver" },
+	[274]	= { "mbind" },
+	[275]	= { "get_mempolicy" },
+	[276]	= { "set_mempolicy" },
+	[277]	= { "mq_open" },
+	[278]	= { "mq_unlink" },
+	[279]	= { "mq_timedsend" },
+	[280]	= { "mq_timedreceive" },
+	[281]	= { "mq_notify" },
+	[282]	= { "mq_getsetattr" },
+	[283]	= { "sys_kexec_load" },
+};
+
+asmlinkage void do_syscall_trace(int leaving)
+{
+#if 0
+	unsigned long *argp;
+	const char *name;
+	unsigned argmask;
+	char buffer[16];
+
+	if (!kstrace)
+		return;
+
+	if (!current->mm)
+		return;
+
+	if (__frame->gr7 == __NR_close)
+		return;
+
+#if 0
+	if (__frame->gr7 != __NR_mmap2 &&
+	    __frame->gr7 != __NR_vfork &&
+	    __frame->gr7 != __NR_execve &&
+	    __frame->gr7 != __NR_exit)
+		return;
+#endif
+
+	argmask = 0;
+	name = NULL;
+	if (__frame->gr7 < NR_syscalls) {
+		name = __syscall_name_table[__frame->gr7].name;
+		argmask = __syscall_name_table[__frame->gr7].argmask;
+	}
+	if (!name) {
+		sprintf(buffer, "sys_%lx", __frame->gr7);
+		name = buffer;
+	}
+
+	if (!leaving) {
+		if (!argmask) {
+			printk(KERN_CRIT "[%d] %s(%lx,%lx,%lx,%lx,%lx,%lx)\n",
+			       current->pid,
+			       name,
+			       __frame->gr8,
+			       __frame->gr9,
+			       __frame->gr10,
+			       __frame->gr11,
+			       __frame->gr12,
+			       __frame->gr13);
+		}
+		else if (argmask == 0xffffff) {
+			printk(KERN_CRIT "[%d] %s()\n",
+			       current->pid,
+			       name);
+		}
+		else {
+			printk(KERN_CRIT "[%d] %s(",
+			       current->pid,
+			       name);
+
+			argp = &__frame->gr8;
+
+			do {
+				switch (argmask & 0xf) {
+				case 1:
+					printk("%ld", (long) *argp);
+					break;
+				case 2:
+					printk("%lo", *argp);
+					break;
+				case 3:
+					printk("%lx", *argp);
+					break;
+				case 4:
+					printk("%p", (void *) *argp);
+					break;
+				case 5:
+					printk("\"%s\"", (char *) *argp);
+					break;
+				}
+
+				argp++;
+				argmask >>= 4;
+				if (argmask)
+					printk(",");
+
+			} while (argmask);
+
+			printk(")\n");
+		}
+	}
+	else {
+		if ((int)__frame->gr8 > -4096 && (int)__frame->gr8 < 4096)
+			printk(KERN_CRIT "[%d] %s() = %ld\n", current->pid, name, __frame->gr8);
+		else
+			printk(KERN_CRIT "[%d] %s() = %lx\n", current->pid, name, __frame->gr8);
+	}
+	return;
+#endif
+
+	if (!test_thread_flag(TIF_SYSCALL_TRACE))
+		return;
+
+	if (!(current->ptrace & PT_PTRACED))
+		return;
+
+	/* we need to indicate entry or exit to strace */
+	if (leaving)
+		__frame->__status |= REG__STATUS_SYSC_EXIT;
+	else
+		__frame->__status |= REG__STATUS_SYSC_ENTRY;
+
+	ptrace_notify(SIGTRAP);
+
+	/*
+	 * 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;
+	}
+}
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/kernel/semaphore.c linux-2.6.10-rc1-mm3-frv/arch/frv/kernel/semaphore.c
--- /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/kernel/semaphore.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/arch/frv/kernel/semaphore.c	2004-11-05 14:13:03.207554554 +0000
@@ -0,0 +1,142 @@
+/* semaphore.c: FR-V semaphores
+ *
+ * Copyright (C) 2003 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ * - Derived from lib/rwsem-spinlock.c
+ *
+ * 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.
+ */
+
+#include <linux/config.h>
+#include <linux/sched.h>
+#include <linux/module.h>
+#include <asm/semaphore.h>
+
+struct sem_waiter {
+	struct list_head	list;
+	struct task_struct	*task;
+};
+
+#if SEM_DEBUG
+void semtrace(struct semaphore *sem, const char *str)
+{
+	if (sem->debug)
+		printk("[%d] %s({%d,%d})\n",
+		       current->pid,
+		       str,
+		       sem->counter,
+		       list_empty(&sem->wait_list) ? 0 : 1);
+}
+#else
+#define semtrace(SEM,STR) do { } while(0)
+#endif
+
+/*
+ * wait for a token to be granted from a semaphore
+ * - entered with lock held and interrupts disabled
+ */
+void __down(struct semaphore *sem, unsigned long flags)
+{
+	struct task_struct *tsk = current;
+	struct sem_waiter waiter;
+
+	semtrace(sem,"Entering __down");
+
+	/* set up my own style of waitqueue */
+	waiter.task	= tsk;
+
+	list_add_tail(&waiter.list, &sem->wait_list);
+
+	/* we don't need to touch the semaphore struct anymore */
+	spin_unlock_irqrestore(&sem->wait_lock, flags);
+
+	/* wait to be given the lock */
+	set_task_state(tsk, TASK_UNINTERRUPTIBLE);
+
+	for (;;) {
+		if (list_empty(&waiter.list))
+			break;
+		schedule();
+		set_task_state(tsk, TASK_UNINTERRUPTIBLE);
+	}
+
+	tsk->state = TASK_RUNNING;
+	semtrace(sem,"Leaving __down");
+}
+
+EXPORT_SYMBOL(__down);
+
+/*
+ * interruptibly wait for a token to be granted from a semaphore
+ * - entered with lock held and interrupts disabled
+ */
+int __down_interruptible(struct semaphore *sem, unsigned long flags)
+{
+	struct task_struct *tsk = current;
+	struct sem_waiter waiter;
+	int ret;
+
+	semtrace(sem,"Entering __down_interruptible");
+
+	/* set up my own style of waitqueue */
+	waiter.task = tsk;
+
+	list_add_tail(&waiter.list, &sem->wait_list);
+
+	/* we don't need to touch the semaphore struct anymore */
+	set_task_state(tsk, TASK_INTERRUPTIBLE);
+
+	spin_unlock_irqrestore(&sem->wait_lock, flags);
+
+	/* wait to be given the lock */
+	ret = 0;
+	for (;;) {
+		if (list_empty(&waiter.list))
+			break;
+		if (unlikely(signal_pending(current)))
+			goto interrupted;
+		schedule();
+		set_task_state(tsk, TASK_INTERRUPTIBLE);
+	}
+
+ out:
+	tsk->state = TASK_RUNNING;
+	semtrace(sem, "Leaving __down_interruptible");
+	return ret;
+
+ interrupted:
+	spin_lock_irqsave(&sem->wait_lock, flags);
+
+	if (!list_empty(&waiter.list)) {
+		list_del(&waiter.list);
+		ret = -EINTR;
+	}
+
+	spin_unlock_irqrestore(&sem->wait_lock, flags);
+	goto out;
+}
+
+EXPORT_SYMBOL(__down_interruptible);
+
+/*
+ * release a single token back to a semaphore
+ * - entered with lock held and interrupts disabled
+ */
+void __up(struct semaphore *sem)
+{
+	struct sem_waiter *waiter;
+
+	semtrace(sem,"Entering __up");
+
+	/* grant the token to the process at the front of the queue */
+	waiter = list_entry(sem->wait_list.next, struct sem_waiter, list);
+	list_del_init(&waiter->list);
+	wake_up_process(waiter->task);
+
+	semtrace(sem,"Leaving __up");
+}
+
+EXPORT_SYMBOL(__up);
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/kernel/setup.c linux-2.6.10-rc1-mm3-frv/arch/frv/kernel/setup.c
--- /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/kernel/setup.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/arch/frv/kernel/setup.c	2004-11-05 14:13:03.213554048 +0000
@@ -0,0 +1,1202 @@
+/*
+ *  linux/arch/frvnommu/kernel/setup.c
+ *
+ *  Copyleft  ()) 2000       James D. Schettine {james@telos-systems.com}
+ *  Copyright (C) 1999-2003  Greg Ungerer (gerg@snapgear.com)
+ *  Copyright (C) 1998,1999  D. Jeff Dionne <jeff@lineo.ca>
+ *  Copyright (C) 1998       Kenneth Albanowski <kjahds@kjahds.com>
+ *  Copyright (C) 1995       Hamish Macdonald
+ *  Copyright (C) 2000       Lineo Inc. (www.lineo.com)
+ *  Copyright (C) 2001 	     Lineo, Inc. <www.lineo.com>
+ *  Copyright (C) 2003 	     David Howells <dhowells@redhat.com>, Red Hat, Inc.
+ */
+
+/*
+ * This file handles the architecture-dependent parts of system setup
+ */
+
+#include <linux/config.h>
+#include <linux/version.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/fs.h>
+#include <linux/mm.h>
+#include <linux/fb.h>
+#include <linux/console.h>
+#include <linux/genhd.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/major.h>
+#include <linux/bootmem.h>
+#include <linux/highmem.h>
+#include <linux/seq_file.h>
+#include <linux/serial.h>
+#include <linux/serial_core.h>
+#include <linux/serial_reg.h>
+
+#include <asm/setup.h>
+#include <asm/serial.h>
+#include <asm/irq.h>
+#include <asm/sections.h>
+#include <asm/pgalloc.h>
+#include <asm/busctl-regs.h>
+#include <asm/serial-regs.h>
+#include <asm/timer-regs.h>
+#include <asm/irc-regs.h>
+#include <asm/spr-regs.h>
+#include <asm/mb-regs.h>
+#include <asm/mb93493-regs.h>
+#include <asm/gdb-stub.h>
+#include <asm/irq-routing.h>
+#include <asm/io.h>
+
+#ifdef CONFIG_BLK_DEV_INITRD
+#include <linux/blk.h>
+#include <asm/pgtable.h>
+#endif
+
+#include "local.h"
+
+#ifdef CONFIG_MB93090_MB00
+static void __init mb93090_display(void);
+#endif
+#ifdef CONFIG_MMU
+static void __init setup_linux_memory(void);
+#else
+static void __init setup_uclinux_memory(void);
+#endif
+
+#ifdef CONFIG_CONSOLE
+extern struct consw *conswitchp;
+#ifdef CONFIG_FRAMEBUFFER
+extern struct consw fb_con;
+#endif
+#endif
+
+#ifdef CONFIG_MB93090_MB00
+static char __initdata mb93090_banner[] = "FJ/RH FR-V Linux";
+static char __initdata mb93090_version[] = UTS_RELEASE;
+
+int __nongprelbss mb93090_mb00_detected;
+#endif
+
+const char __frv_unknown_system[] = "unknown";
+const char __frv_mb93091_cb10[] = "mb93091-cb10";
+const char __frv_mb93091_cb11[] = "mb93091-cb11";
+const char __frv_mb93091_cb30[] = "mb93091-cb30";
+const char __frv_mb93091_cb41[] = "mb93091-cb41";
+const char __frv_mb93091_cb60[] = "mb93091-cb60";
+const char __frv_mb93091_cb70[] = "mb93091-cb70";
+const char __frv_mb93091_cb451[] = "mb93091-cb451";
+const char __frv_mb93090_mb00[] = "mb93090-mb00";
+
+const char __frv_mb93493[] = "mb93493";
+
+const char __frv_mb93093[] = "mb93093";
+
+static const char *__nongprelbss cpu_series;
+static const char *__nongprelbss cpu_core;
+static const char *__nongprelbss cpu_silicon;
+static const char *__nongprelbss cpu_mmu;
+static const char *__nongprelbss cpu_system;
+static const char *__nongprelbss cpu_board1;
+static const char *__nongprelbss cpu_board2;
+
+static unsigned long __nongprelbss cpu_psr_all;
+static unsigned long __nongprelbss cpu_hsr0_all;
+
+unsigned long __nongprelbss pdm_suspend_mode;
+
+unsigned long __nongprelbss rom_length;
+unsigned long __nongprelbss memory_start;
+unsigned long __nongprelbss memory_end;
+
+unsigned long __nongprelbss dma_coherent_mem_start;
+unsigned long __nongprelbss dma_coherent_mem_end;
+
+unsigned long __initdata __sdram_old_base;
+unsigned long __initdata num_mappedpages;
+
+struct cpuinfo_frv __nongprelbss boot_cpu_data;
+
+char command_line[COMMAND_LINE_SIZE];
+char __initdata redboot_command_line[COMMAND_LINE_SIZE];
+
+#ifdef CONFIG_PM
+#define __pminit
+#define __pminitdata
+#else
+#define __pminit __init
+#define __pminitdata __initdata
+#endif
+
+struct clock_cmode {
+	uint8_t	xbus, sdram, corebus, core, dsu;
+};
+
+#define _frac(N,D) ((N)<<4 | (D))
+#define _x0_16	_frac(1,6)
+#define _x0_25	_frac(1,4)
+#define _x0_33	_frac(1,3)
+#define _x0_375	_frac(3,8)
+#define _x0_5	_frac(1,2)
+#define _x0_66	_frac(2,3)
+#define _x0_75	_frac(3,4)
+#define _x1	_frac(1,1)
+#define _x1_5	_frac(3,2)
+#define _x2	_frac(2,1)
+#define _x3	_frac(3,1)
+#define _x4	_frac(4,1)
+#define _x4_5	_frac(9,2)
+#define _x6	_frac(6,1)
+#define _x8	_frac(8,1)
+#define _x9	_frac(9,1)
+
+int __nongprelbss clock_p0_current;
+int __nongprelbss clock_cm_current;
+int __nongprelbss clock_cmode_current;
+#ifdef CONFIG_PM
+int __nongprelbss clock_cmodes_permitted;
+unsigned long __nongprelbss clock_bits_settable;
+#endif
+
+static struct clock_cmode __pminitdata undef_clock_cmode = { _x1, _x1, _x1, _x1, _x1 };
+
+static struct clock_cmode __pminitdata clock_cmodes_fr401_fr403[16] = {
+	[4]	= {	_x1,	_x1,	_x2,	_x2,	_x0_25	},
+	[5]	= { 	_x1,	_x2,	_x4,	_x4,	_x0_5	},
+	[8]	= { 	_x1,	_x1,	_x1,	_x2,	_x0_25	},
+	[9]	= { 	_x1,	_x2,	_x2,	_x4,	_x0_5	},
+	[11]	= { 	_x1,	_x4,	_x4,	_x8,	_x1	},
+	[12]	= { 	_x1,	_x1,	_x2,	_x4,	_x0_5	},
+	[13]	= { 	_x1,	_x2,	_x4,	_x8,	_x1	},
+};
+
+static struct clock_cmode __pminitdata clock_cmodes_fr405[16] = {
+	[0]	= {	_x1,	_x1,	_x1,	_x1,	_x0_5	},
+	[1]	= {	_x1,	_x1,	_x1,	_x3,	_x0_25	},
+	[2]	= {	_x1,	_x1,	_x2,	_x6,	_x0_5	},
+	[3]	= {	_x1,	_x2,	_x2,	_x6,	_x0_5	},
+	[4]	= {	_x1,	_x1,	_x2,	_x2,	_x0_16	},
+	[8]	= { 	_x1,	_x1,	_x1,	_x2,	_x0_16	},
+	[9]	= { 	_x1,	_x2,	_x2,	_x4,	_x0_33	},
+	[12]	= { 	_x1,	_x1,	_x2,	_x4,	_x0_33	},
+	[14]	= { 	_x1,	_x3,	_x3,	_x9,	_x0_75	},
+	[15]	= { 	_x1,	_x1_5,	_x1_5,	_x4_5,	_x0_375	},
+
+#define CLOCK_CMODES_PERMITTED_FR405 0xd31f
+};
+
+static struct clock_cmode __pminitdata clock_cmodes_fr555[16] = {
+	[0]	= {	_x1,	_x2,	_x2,	_x4,	_x0_33	},
+	[1]	= {	_x1,	_x3,	_x3,	_x6,	_x0_5	},
+	[2]	= {	_x1,	_x2,	_x4,	_x8,	_x0_66	},
+	[3]	= {	_x1,	_x1_5,	_x3,	_x6,	_x0_5	},
+	[4]	= {	_x1,	_x3,	_x3,	_x9,	_x0_75	},
+	[5]	= {	_x1,	_x2,	_x2,	_x6,	_x0_5	},
+	[6]	= {	_x1,	_x1_5,	_x1_5,	_x4_5,	_x0_375	},
+};
+
+static const struct clock_cmode __pminitdata *clock_cmodes;
+static int __pminitdata clock_doubled;
+
+static struct uart_port __initdata __frv_uart0 = {
+	.uartclk		= 0,
+	.membase		= (char *) UART0_BASE,
+	.irq			= IRQ_CPU_UART0,
+	.regshift		= 3,
+	.iotype			= UPIO_MEM,
+	.flags			= UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
+};
+
+static struct uart_port __initdata __frv_uart1 = {
+	.uartclk		= 0,
+	.membase		= (char *) UART1_BASE,
+	.irq			= IRQ_CPU_UART1,
+	.regshift		= 3,
+	.iotype			= UPIO_MEM,
+	.flags			= UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
+};
+
+#if 0
+static void __init printk_xampr(unsigned long ampr, unsigned long amlr, char i_d, int n)
+{
+	unsigned long phys, virt, cxn, size;
+
+#ifdef CONFIG_MMU
+	virt = amlr & 0xffffc000;
+	cxn = amlr & 0x3fff;
+#else
+	virt = ampr & 0xffffc000;
+	cxn = 0;
+#endif
+	phys = ampr & xAMPRx_PPFN;
+	size = 1 << (((ampr & xAMPRx_SS) >> 4) + 17);
+
+	printk("%cAMPR%d: va %08lx-%08lx [pa %08lx] %c%c%c%c [cxn:%04lx]\n",
+	       i_d, n,
+	       virt, virt + size - 1,
+	       phys,
+	       ampr & xAMPRx_S  ? 'S' : '-',
+	       ampr & xAMPRx_C  ? 'C' : '-',
+	       ampr & DAMPRx_WP ? 'W' : '-',
+	       ampr & xAMPRx_V  ? 'V' : '-',
+	       cxn
+	       );
+}
+#endif
+
+/*****************************************************************************/
+/*
+ * dump the memory map
+ */
+static void __init dump_memory_map(void)
+{
+
+#if 0
+	/* dump the protection map */
+	printk_xampr(__get_IAMPR(0),  __get_IAMLR(0),  'I', 0);
+	printk_xampr(__get_IAMPR(1),  __get_IAMLR(1),  'I', 1);
+	printk_xampr(__get_IAMPR(2),  __get_IAMLR(2),  'I', 2);
+	printk_xampr(__get_IAMPR(3),  __get_IAMLR(3),  'I', 3);
+	printk_xampr(__get_IAMPR(4),  __get_IAMLR(4),  'I', 4);
+	printk_xampr(__get_IAMPR(5),  __get_IAMLR(5),  'I', 5);
+	printk_xampr(__get_IAMPR(6),  __get_IAMLR(6),  'I', 6);
+	printk_xampr(__get_IAMPR(7),  __get_IAMLR(7),  'I', 7);
+	printk_xampr(__get_IAMPR(8),  __get_IAMLR(8),  'I', 8);
+	printk_xampr(__get_IAMPR(9),  __get_IAMLR(9),  'i', 9);
+	printk_xampr(__get_IAMPR(10), __get_IAMLR(10), 'I', 10);
+	printk_xampr(__get_IAMPR(11), __get_IAMLR(11), 'I', 11);
+	printk_xampr(__get_IAMPR(12), __get_IAMLR(12), 'I', 12);
+	printk_xampr(__get_IAMPR(13), __get_IAMLR(13), 'I', 13);
+	printk_xampr(__get_IAMPR(14), __get_IAMLR(14), 'I', 14);
+	printk_xampr(__get_IAMPR(15), __get_IAMLR(15), 'I', 15);
+
+	printk_xampr(__get_DAMPR(0),  __get_DAMLR(0),  'D', 0);
+	printk_xampr(__get_DAMPR(1),  __get_DAMLR(1),  'D', 1);
+	printk_xampr(__get_DAMPR(2),  __get_DAMLR(2),  'D', 2);
+	printk_xampr(__get_DAMPR(3),  __get_DAMLR(3),  'D', 3);
+	printk_xampr(__get_DAMPR(4),  __get_DAMLR(4),  'D', 4);
+	printk_xampr(__get_DAMPR(5),  __get_DAMLR(5),  'D', 5);
+	printk_xampr(__get_DAMPR(6),  __get_DAMLR(6),  'D', 6);
+	printk_xampr(__get_DAMPR(7),  __get_DAMLR(7),  'D', 7);
+	printk_xampr(__get_DAMPR(8),  __get_DAMLR(8),  'D', 8);
+	printk_xampr(__get_DAMPR(9),  __get_DAMLR(9),  'D', 9);
+	printk_xampr(__get_DAMPR(10), __get_DAMLR(10), 'D', 10);
+	printk_xampr(__get_DAMPR(11), __get_DAMLR(11), 'D', 11);
+	printk_xampr(__get_DAMPR(12), __get_DAMLR(12), 'D', 12);
+	printk_xampr(__get_DAMPR(13), __get_DAMLR(13), 'D', 13);
+	printk_xampr(__get_DAMPR(14), __get_DAMLR(14), 'D', 14);
+	printk_xampr(__get_DAMPR(15), __get_DAMLR(15), 'D', 15);
+#endif
+
+#if 0
+	/* dump the bus controller registers */
+	printk("LGCR: %08lx\n", __get_LGCR());
+	printk("Master: %08lx-%08lx CR=%08lx\n",
+	       __get_LEMBR(), __get_LEMBR() + __get_LEMAM(),
+	       __get_LMAICR());
+
+	int loop;
+	for (loop = 1; loop <= 7; loop++) {
+		unsigned long lcr = __get_LCR(loop), lsbr = __get_LSBR(loop);
+		printk("CS#%d: %08lx-%08lx %c%c%c%c%c%c%c%c%c\n",
+		       loop,
+		       lsbr, lsbr + __get_LSAM(loop),
+		       lcr & 0x80000000 ? 'r' : '-',
+		       lcr & 0x40000000 ? 'w' : '-',
+		       lcr & 0x08000000 ? 'b' : '-',
+		       lcr & 0x04000000 ? 'B' : '-',
+		       lcr & 0x02000000 ? 'C' : '-',
+		       lcr & 0x01000000 ? 'D' : '-',
+		       lcr & 0x00800000 ? 'W' : '-',
+		       lcr & 0x00400000 ? 'R' : '-',
+		       (lcr & 0x00030000) == 0x00000000 ? '4' :
+		       (lcr & 0x00030000) == 0x00010000 ? '2' :
+		       (lcr & 0x00030000) == 0x00020000 ? '1' :
+		       '-'
+		       );
+	}
+#endif
+
+#if 0
+	printk("\n");
+#endif
+} /* end dump_memory_map() */
+
+/*****************************************************************************/
+/*
+ * attempt to detect a VDK motherboard and DAV daughter board on an MB93091 system
+ */
+#ifdef CONFIG_MB93091_VDK
+static void __init detect_mb93091(void)
+{
+#ifdef CONFIG_MB93090_MB00
+	/* Detect CB70 without motherboard */
+	if (!(cpu_system == __frv_mb93091_cb70 && ((*(unsigned short *)0xffc00030) & 0x100))) {
+		cpu_board1 = __frv_mb93090_mb00;
+		mb93090_mb00_detected = 1;
+	}
+#endif
+
+#ifdef CONFIG_FUJITSU_MB93493
+	cpu_board2 = __frv_mb93493;
+#endif
+
+} /* end detect_mb93091() */
+#endif
+
+/*****************************************************************************/
+/*
+ * determine the CPU type and set appropriate parameters
+ *
+ * Family     Series      CPU Core    Silicon    Imple  Vers
+ * ----------------------------------------------------------
+ * FR-V --+-> FR400 --+-> FR401 --+-> MB93401     02     00 [1]
+ *        |           |           |
+ *        |           |           +-> MB93401/A   02     01
+ *        |           |           |
+ *        |           |           +-> MB93403     02     02
+ *        |           |
+ *        |           +-> FR405 ----> MB93405     04     00
+ *        |
+ *        +-> FR450 ----> FR451 ----> MB93451     05     00
+ *        |
+ *        +-> FR500 ----> FR501 --+-> MB93501     01     01 [2]
+ *        |                       |
+ *        |                       +-> MB93501/A   01     02
+ *        |
+ *        +-> FR550 --+-> FR551 ----> MB93555     03     01
+ *
+ *  [1] The MB93401 is an obsolete CPU replaced by the MB93401A
+ *  [2] The MB93501 is an obsolete CPU replaced by the MB93501A
+ *
+ * Imple is PSR(Processor Status Register)[31:28].
+ * Vers is PSR(Processor Status Register)[27:24].
+ *
+ * A "Silicon" consists of CPU core and some on-chip peripherals.
+ */
+static void __init determine_cpu(void)
+{
+	unsigned long hsr0 = __get_HSR(0);
+	unsigned long psr = __get_PSR();
+
+	/* work out what selectable services the CPU supports */
+	__set_PSR(psr | PSR_EM | PSR_EF | PSR_CM | PSR_NEM);
+	cpu_psr_all = __get_PSR();
+	__set_PSR(psr);
+
+	__set_HSR(0, hsr0 | HSR0_GRLE | HSR0_GRHE | HSR0_FRLE | HSR0_FRHE);
+	cpu_hsr0_all = __get_HSR(0);
+	__set_HSR(0, hsr0);
+
+	/* derive other service specs from the CPU type */
+	cpu_series		= "unknown";
+	cpu_core		= "unknown";
+	cpu_silicon		= "unknown";
+	cpu_mmu			= "Prot";
+	cpu_system		= __frv_unknown_system;
+	clock_cmodes		= NULL;
+	clock_doubled		= 0;
+#ifdef CONFIG_PM
+	clock_bits_settable	= CLOCK_BIT_CM_H | CLOCK_BIT_CM_M | CLOCK_BIT_P0;
+#endif
+
+	switch (PSR_IMPLE(psr)) {
+	case PSR_IMPLE_FR401:
+		cpu_series	= "fr400";
+		cpu_core	= "fr401";
+		pdm_suspend_mode = HSR0_PDM_PLL_RUN;
+
+		switch (PSR_VERSION(psr)) {
+		case PSR_VERSION_FR401_MB93401:
+			cpu_silicon	= "mb93401";
+			cpu_system	= __frv_mb93091_cb10;
+			clock_cmodes	= clock_cmodes_fr401_fr403;
+			clock_doubled	= 1;
+			break;
+		case PSR_VERSION_FR401_MB93401A:
+			cpu_silicon	= "mb93401/A";
+			cpu_system	= __frv_mb93091_cb11;
+			clock_cmodes	= clock_cmodes_fr401_fr403;
+			break;
+		case PSR_VERSION_FR401_MB93403:
+			cpu_silicon	= "mb93403";
+#ifndef CONFIG_MB93093_PDK
+			cpu_system	= __frv_mb93091_cb30;
+#else
+			cpu_system	= __frv_mb93093;
+#endif
+			clock_cmodes	= clock_cmodes_fr401_fr403;
+			break;
+		default:
+			break;
+		}
+		break;
+
+	case PSR_IMPLE_FR405:
+		cpu_series	= "fr400";
+		cpu_core	= "fr405";
+		pdm_suspend_mode = HSR0_PDM_PLL_STOP;
+
+		switch (PSR_VERSION(psr)) {
+		case PSR_VERSION_FR405_MB93405:
+			cpu_silicon	= "mb93405";
+			cpu_system	= __frv_mb93091_cb60;
+			clock_cmodes	= clock_cmodes_fr405;
+#ifdef CONFIG_PM
+			clock_bits_settable |= CLOCK_BIT_CMODE;
+			clock_cmodes_permitted = CLOCK_CMODES_PERMITTED_FR405;
+#endif
+
+			/* the FPGA on the CB70 has extra registers
+			 * - it has 0x0046 in the VDK_ID FPGA register at 0x1a0, which is
+			 *   how we tell the difference between it and a CB60
+			 */
+			if (*(volatile unsigned short *) 0xffc001a0 == 0x0046)
+				cpu_system = __frv_mb93091_cb70;
+			break;
+		default:
+			break;
+		}
+		break;
+
+	case PSR_IMPLE_FR451:
+		cpu_series	= "fr450";
+		cpu_core	= "fr451";
+		pdm_suspend_mode = HSR0_PDM_PLL_STOP;
+#ifdef CONFIG_PM
+		clock_bits_settable |= CLOCK_BIT_CMODE;
+		clock_cmodes_permitted = CLOCK_CMODES_PERMITTED_FR405;
+#endif
+		switch (PSR_VERSION(psr)) {
+		case PSR_VERSION_FR451_MB93451:
+			cpu_silicon	= "mb93451";
+			cpu_mmu		= "Prot, SAT, xSAT, DAT";
+			cpu_system	= __frv_mb93091_cb451;
+			clock_cmodes	= clock_cmodes_fr405;
+			break;
+		default:
+			break;
+		}
+		break;
+
+	case PSR_IMPLE_FR501:
+		cpu_series	= "fr500";
+		cpu_core	= "fr501";
+		pdm_suspend_mode = HSR0_PDM_PLL_STOP;
+
+		switch (PSR_VERSION(psr)) {
+		case PSR_VERSION_FR501_MB93501:  cpu_silicon = "mb93501";   break;
+		case PSR_VERSION_FR501_MB93501A: cpu_silicon = "mb93501/A"; break;
+		default:
+			break;
+		}
+		break;
+
+	case PSR_IMPLE_FR551:
+		cpu_series	= "fr550";
+		cpu_core	= "fr551";
+		pdm_suspend_mode = HSR0_PDM_PLL_STOP;
+
+		switch (PSR_VERSION(psr)) {
+		case PSR_VERSION_FR551_MB93555:
+			cpu_silicon	= "mb93555";
+			cpu_mmu		= "Prot, SAT";
+			cpu_system	= __frv_mb93091_cb41;
+			clock_cmodes	= clock_cmodes_fr555;
+			clock_doubled	= 1;
+			break;
+		default:
+			break;
+		}
+		break;
+
+	default:
+		break;
+	}
+
+	printk("- Series:%s CPU:%s Silicon:%s\n",
+	       cpu_series, cpu_core, cpu_silicon);
+
+#ifdef CONFIG_MB93091_VDK
+	detect_mb93091();
+#endif
+
+#if defined(CONFIG_MB93093_PDK) && defined(CONFIG_FUJITSU_MB93493)
+	cpu_board2 = __frv_mb93493;
+#endif
+
+} /* end determine_cpu() */
+
+/*****************************************************************************/
+/*
+ * calculate the bus clock speed
+ */
+void __pminit determine_clocks(int verbose)
+{
+	const struct clock_cmode *mode, *tmode;
+	unsigned long clkc, psr, quot;
+
+	clkc = __get_CLKC();
+	psr = __get_PSR();
+
+	clock_p0_current = !!(clkc & CLKC_P0);
+	clock_cm_current = clkc & CLKC_CM;
+	clock_cmode_current = (clkc & CLKC_CMODE) >> CLKC_CMODE_s;
+
+	if (verbose)
+		printk("psr=%08lx hsr0=%08lx clkc=%08lx\n", psr, __get_HSR(0), clkc);
+
+	/* the CB70 has some alternative ways of setting the clock speed through switches accessed
+	 * through the FPGA.  */
+	if (cpu_system == __frv_mb93091_cb70) {
+		unsigned short clkswr = *(volatile unsigned short *) 0xffc00104UL & 0x1fffUL;
+
+		if (clkswr & 0x1000)
+			__clkin_clock_speed_HZ = 60000000UL;
+		else
+			__clkin_clock_speed_HZ =
+				((clkswr >> 8) & 0xf) * 10000000 +
+				((clkswr >> 4) & 0xf) * 1000000 +
+				((clkswr     ) & 0xf) * 100000;
+	}
+	/* the FR451 is currently fixed at 24MHz */
+	else if (cpu_system == __frv_mb93091_cb451) {
+		//__clkin_clock_speed_HZ = 24000000UL; // CB451-FPGA
+		unsigned short clkswr = *(volatile unsigned short *) 0xffc00104UL & 0x1fffUL;
+
+		if (clkswr & 0x1000)
+			__clkin_clock_speed_HZ = 60000000UL;
+		else
+			__clkin_clock_speed_HZ =
+				((clkswr >> 8) & 0xf) * 10000000 +
+				((clkswr >> 4) & 0xf) * 1000000 +
+				((clkswr     ) & 0xf) * 100000;
+	}
+	/* otherwise determine the clockspeed from VDK or other registers */
+	else {
+		__clkin_clock_speed_HZ = __get_CLKIN();
+	}
+
+	/* look up the appropriate clock relationships table entry */
+	mode = &undef_clock_cmode;
+	if (clock_cmodes) {
+		tmode = &clock_cmodes[(clkc & CLKC_CMODE) >> CLKC_CMODE_s];
+		if (tmode->xbus)
+			mode = tmode;
+	}
+
+#define CLOCK(SRC,RATIO) ((SRC) * (((RATIO) >> 4) & 0x0f) / ((RATIO) & 0x0f))
+
+	if (clock_doubled)
+		__clkin_clock_speed_HZ <<= 1;
+
+	__ext_bus_clock_speed_HZ	= CLOCK(__clkin_clock_speed_HZ, mode->xbus);
+	__sdram_clock_speed_HZ		= CLOCK(__clkin_clock_speed_HZ, mode->sdram);
+	__dsu_clock_speed_HZ		= CLOCK(__clkin_clock_speed_HZ, mode->dsu);
+
+	switch (clkc & CLKC_CM) {
+	case 0: /* High */
+		__core_bus_clock_speed_HZ	= CLOCK(__clkin_clock_speed_HZ, mode->corebus);
+		__core_clock_speed_HZ		= CLOCK(__clkin_clock_speed_HZ, mode->core);
+		break;
+	case 1: /* Medium */
+		__core_bus_clock_speed_HZ	= CLOCK(__clkin_clock_speed_HZ, mode->sdram);
+		__core_clock_speed_HZ		= CLOCK(__clkin_clock_speed_HZ, mode->sdram);
+		break;
+	case 2: /* Low; not supported */
+	case 3: /* UNDEF */
+		printk("Unsupported CLKC CM %ld\n", clkc & CLKC_CM);
+		panic("Bye");
+	}
+
+	__res_bus_clock_speed_HZ = __ext_bus_clock_speed_HZ;
+	if (clkc & CLKC_P0)
+		__res_bus_clock_speed_HZ >>= 1;
+
+	if (verbose) {
+		printk("CLKIN: %lu.%3.3luMHz\n",
+		       __clkin_clock_speed_HZ / 1000000,
+		       (__clkin_clock_speed_HZ / 1000) % 1000);
+
+		printk("CLKS:"
+		       " ext=%luMHz res=%luMHz sdram=%luMHz cbus=%luMHz core=%luMHz dsu=%luMHz\n",
+		       __ext_bus_clock_speed_HZ / 1000000,
+		       __res_bus_clock_speed_HZ / 1000000,
+		       __sdram_clock_speed_HZ / 1000000,
+		       __core_bus_clock_speed_HZ / 1000000,
+		       __core_clock_speed_HZ / 1000000,
+		       __dsu_clock_speed_HZ / 1000000
+		       );
+	}
+
+	/* calculate the number of __delay() loop iterations per sec (2 insn loop) */
+	__delay_loops_MHz = __core_clock_speed_HZ / (1000000 * 2);
+
+	/* set the serial prescaler */
+	__serial_clock_speed_HZ = __res_bus_clock_speed_HZ;
+	quot = 1;
+	while (__serial_clock_speed_HZ / quot / 16 / 65536 > 3000)
+		quot += 1;
+
+	/* double the divisor if P0 is clear, so that if/when P0 is set, it's still achievable
+	 * - we have to be careful - dividing too much can mean we can't get 115200 baud
+	 */
+	if (__serial_clock_speed_HZ > 32000000 && !(clkc & CLKC_P0))
+		quot <<= 1;
+
+	__serial_clock_speed_HZ /= quot;
+	__frv_uart0.uartclk = __serial_clock_speed_HZ;
+	__frv_uart1.uartclk = __serial_clock_speed_HZ;
+
+	if (verbose)
+		printk("      uart=%luMHz\n", __serial_clock_speed_HZ / 1000000 * quot);
+
+	while (!(__get_UART0_LSR() & UART_LSR_TEMT))
+		continue;
+
+	while (!(__get_UART1_LSR() & UART_LSR_TEMT))
+		continue;
+
+	__set_UCPVR(quot);
+	__set_UCPSR(0);
+} /* end determine_clocks() */
+
+/*****************************************************************************/
+/*
+ * reserve some DMA consistent memory
+ */
+#ifdef CONFIG_RESERVE_DMA_COHERENT
+static void __init reserve_dma_coherent(void)
+{
+	unsigned long ampr;
+
+	/* find the first non-kernel memory tile and steal it */
+#define __steal_AMPR(r)						\
+	if (__get_DAMPR(r) & xAMPRx_V) {			\
+		ampr = __get_DAMPR(r);				\
+		__set_DAMPR(r, ampr | xAMPRx_S | xAMPRx_C);	\
+		__set_IAMPR(r, 0);				\
+		goto found;					\
+	}
+
+	__steal_AMPR(1);
+	__steal_AMPR(2);
+	__steal_AMPR(3);
+	__steal_AMPR(4);
+	__steal_AMPR(5);
+	__steal_AMPR(6);
+
+	if (PSR_IMPLE(__get_PSR()) == PSR_IMPLE_FR551) {
+		__steal_AMPR(7);
+		__steal_AMPR(8);
+		__steal_AMPR(9);
+		__steal_AMPR(10);
+		__steal_AMPR(11);
+		__steal_AMPR(12);
+		__steal_AMPR(13);
+		__steal_AMPR(14);
+	}
+
+	/* unable to grant any DMA consistent memory */
+	printk("No DMA consistent memory reserved\n");
+	return;
+
+ found:
+	dma_coherent_mem_start = ampr & xAMPRx_PPFN;
+	ampr &= xAMPRx_SS;
+	ampr >>= 4;
+	ampr = 1 << (ampr - 3 + 20);
+	dma_coherent_mem_end = dma_coherent_mem_start + ampr;
+
+	printk("DMA consistent memory reserved %lx-%lx\n",
+	       dma_coherent_mem_start, dma_coherent_mem_end);
+
+} /* end reserve_dma_coherent() */
+#endif
+
+/*****************************************************************************/
+/*
+ * calibrate the delay loop
+ */
+void __init calibrate_delay(void)
+{
+	loops_per_jiffy = __delay_loops_MHz * (1000000 / HZ);
+
+	printk("Calibrating delay loop... %lu.%02lu BogoMIPS\n",
+	       loops_per_jiffy / (500000 / HZ),
+	       (loops_per_jiffy / (5000 / HZ)) % 100);
+
+} /* end calibrate_delay() */
+
+/*****************************************************************************/
+/*
+ * look through the command line for some things we need to know immediately
+ */
+static void __init parse_cmdline_early(char *cmdline)
+{
+	if (!cmdline)
+		return;
+
+	while (*cmdline) {
+		if (*cmdline == ' ')
+			cmdline++;
+
+		/* "mem=XXX[kKmM]" sets SDRAM size to <mem>, overriding the value we worked
+		 * out from the SDRAM controller mask register
+		 */
+		if (!memcmp(cmdline, "mem=", 4)) {
+			unsigned long long mem_size;
+
+			mem_size = memparse(cmdline + 4, &cmdline);
+			memory_end = memory_start + mem_size;
+		}
+
+		while (*cmdline && *cmdline != ' ')
+			cmdline++;
+	}
+
+} /* end parse_cmdline_early() */
+
+/*****************************************************************************/
+/*
+ *
+ */
+void __init setup_arch(char **cmdline_p)
+{
+#ifdef CONFIG_MMU
+	printk("Linux FR-V port done by Red Hat Inc <dhowells@redhat.com>\n");
+#else
+	printk("uClinux FR-V port done by Red Hat Inc <dhowells@redhat.com>\n");
+#endif
+
+	memcpy(saved_command_line, redboot_command_line, COMMAND_LINE_SIZE);
+
+	determine_cpu();
+	determine_clocks(1);
+
+	/* For printk-directly-beats-on-serial-hardware hack */
+	console_set_baud(115200);
+#ifdef CONFIG_GDBSTUB
+	gdbstub_set_baud(115200);
+#endif
+
+#ifdef CONFIG_RESERVE_DMA_COHERENT
+	reserve_dma_coherent();
+#endif
+	dump_memory_map();
+
+#ifdef CONFIG_MB93090_MB00
+	if (mb93090_mb00_detected)
+		mb93090_display();
+#endif
+
+	/* register those serial ports that are available */
+#ifndef CONFIG_GDBSTUB_UART0
+	__reg(UART0_BASE + UART_IER * 8) = 0;
+	early_serial_setup(&__frv_uart0);
+//	register_serial(&__frv_uart0);
+#endif
+#ifndef CONFIG_GDBSTUB_UART1
+	__reg(UART1_BASE + UART_IER * 8) = 0;
+	early_serial_setup(&__frv_uart1);
+//	register_serial(&__frv_uart1);
+#endif
+
+#if defined(CONFIG_CHR_DEV_FLASH) || defined(CONFIG_BLK_DEV_FLASH)
+	/* we need to initialize the Flashrom device here since we might
+	 * do things with flash early on in the boot
+	 */
+	flash_probe();
+#endif
+
+	/* deal with the command line - RedBoot may have passed one to the kernel */
+	memcpy(command_line, saved_command_line, sizeof(command_line));
+	*cmdline_p = &command_line[0];
+	parse_cmdline_early(command_line);
+
+	/* set up the memory description
+	 * - by now the stack is part of the init task */
+	printk("Memory %08lx-%08lx\n", memory_start, memory_end);
+
+	if (memory_start == memory_end) BUG();
+
+	init_mm.start_code = (unsigned long) &_stext;
+	init_mm.end_code = (unsigned long) &_etext;
+	init_mm.end_data = (unsigned long) &_edata;
+#if 0 /* DAVIDM - don't set brk just incase someone decides to use it */
+	init_mm.brk = (unsigned long) &_end;
+#else
+	init_mm.brk = (unsigned long) 0;
+#endif
+
+#ifdef DEBUG
+	printk("KERNEL -> TEXT=0x%06x-0x%06x DATA=0x%06x-0x%06x BSS=0x%06x-0x%06x\n",
+	       (int) &_stext, (int) &_etext,
+	       (int) &_sdata, (int) &_edata,
+	       (int) &_sbss, (int) &_ebss);
+#endif
+
+#ifdef CONFIG_VT
+#if defined(CONFIG_VGA_CONSOLE)
+        conswitchp = &vga_con;
+#elif defined(CONFIG_DUMMY_CONSOLE)
+        conswitchp = &dummy_con;
+#endif
+#endif
+
+#ifdef CONFIG_BLK_DEV_BLKMEM
+	ROOT_DEV = MKDEV(BLKMEM_MAJOR,0);
+#endif
+	/*rom_length = (unsigned long)&_flashend - (unsigned long)&_romvec;*/
+
+#ifdef CONFIG_MMU
+	setup_linux_memory();
+#else
+	setup_uclinux_memory();
+#endif
+
+	/* get kmalloc into gear */
+	paging_init();
+
+	/* init DMA */
+	frv_dma_init();
+#ifdef DEBUG
+	printk("Done setup_arch\n");
+#endif
+
+	/* start the decrement timer running */
+//	asm volatile("movgs %0,timerd" :: "r"(10000000));
+//	__set_HSR(0, __get_HSR(0) | HSR0_ETMD);
+
+} /* end setup_arch() */
+
+#if 0
+/*****************************************************************************/
+/*
+ * 
+ */
+static int __devinit setup_arch_serial(void)
+{
+	/* register those serial ports that are available */
+#ifndef CONFIG_GDBSTUB_UART0
+	early_serial_setup(&__frv_uart0);
+#endif
+#ifndef CONFIG_GDBSTUB_UART1
+	early_serial_setup(&__frv_uart1);
+#endif
+
+	return 0;
+} /* end setup_arch_serial() */
+
+late_initcall(setup_arch_serial);
+#endif
+
+/*****************************************************************************/
+/*
+ * set up the memory map for normal MMU linux
+ */
+#ifdef CONFIG_MMU
+static void __init setup_linux_memory(void)
+{
+	unsigned long bootmap_size, low_top_pfn, kstart, kend, high_mem;
+
+	kstart	= (unsigned long) &__kernel_image_start - PAGE_OFFSET;
+	kend	= (unsigned long) &__kernel_image_end - PAGE_OFFSET;
+
+	kstart = kstart & PAGE_MASK;
+	kend = (kend + PAGE_SIZE - 1) & PAGE_MASK;
+
+	/* give all the memory to the bootmap allocator,  tell it to put the
+	 * boot mem_map immediately following the kernel image
+	 */
+	bootmap_size = init_bootmem_node(NODE_DATA(0),
+					 kend >> PAGE_SHIFT,		/* map addr */
+					 memory_start >> PAGE_SHIFT,	/* start of RAM */
+					 memory_end >> PAGE_SHIFT	/* end of RAM */
+					 );
+
+	/* pass the memory that the kernel can immediately use over to the bootmem allocator */
+	max_mapnr = num_physpages = (memory_end - memory_start) >> PAGE_SHIFT;
+	low_top_pfn = (KERNEL_LOWMEM_END - KERNEL_LOWMEM_START) >> PAGE_SHIFT;
+	high_mem = 0;
+
+	if (num_physpages > low_top_pfn) {
+#ifdef CONFIG_HIGHMEM
+		high_mem = num_physpages - low_top_pfn;
+#else
+		max_mapnr = num_physpages = low_top_pfn;
+#endif
+	}
+	else {
+		low_top_pfn = num_physpages;
+	}
+
+	min_low_pfn = memory_start >> PAGE_SHIFT;
+	max_low_pfn = low_top_pfn;
+	max_pfn = memory_end >> PAGE_SHIFT;
+
+	num_mappedpages = low_top_pfn;
+
+	printk(KERN_NOTICE "%ldMB LOWMEM available.\n", low_top_pfn >> (20 - PAGE_SHIFT));
+
+	free_bootmem(memory_start, low_top_pfn << PAGE_SHIFT);
+
+#ifdef CONFIG_HIGHMEM
+	if (high_mem)
+		printk(KERN_NOTICE "%ldMB HIGHMEM available.\n", high_mem >> (20 - PAGE_SHIFT));
+#endif
+
+	/* take back the memory occupied by the kernel image and the bootmem alloc map */
+	reserve_bootmem(kstart, kend - kstart + bootmap_size);
+
+	/* reserve the memory occupied by the initial ramdisk */
+#ifdef CONFIG_BLK_DEV_INITRD
+	if (LOADER_TYPE && INITRD_START) {
+		if (INITRD_START + INITRD_SIZE <= (low_top_pfn << PAGE_SHIFT)) {
+			reserve_bootmem(INITRD_START, INITRD_SIZE);
+			initrd_start = INITRD_START ? INITRD_START + PAGE_OFFSET : 0;
+			initrd_end = initrd_start + INITRD_SIZE;
+		}
+		else {
+			printk(KERN_ERR
+			       "initrd extends beyond end of memory (0x%08lx > 0x%08lx)\n"
+			       "disabling initrd\n",
+			       INITRD_START + INITRD_SIZE,
+			       low_top_pfn << PAGE_SHIFT);
+			initrd_start = 0;
+		}
+	}
+#endif
+
+} /* end setup_linux_memory() */
+#endif
+
+/*****************************************************************************/
+/*
+ * set up the memory map for uClinux
+ */
+#ifndef CONFIG_MMU
+static void __init setup_uclinux_memory(void)
+{
+#ifdef CONFIG_PROTECT_KERNEL
+	unsigned long dampr;
+#endif
+	unsigned long kend;
+	int bootmap_size;
+
+	kend = (unsigned long) &__kernel_image_end;
+	kend = (kend + PAGE_SIZE - 1) & PAGE_MASK;
+
+	/* give all the memory to the bootmap allocator,  tell it to put the
+	 * boot mem_map immediately following the kernel image
+	 */
+	bootmap_size = init_bootmem_node(NODE_DATA(0),
+					 kend >> PAGE_SHIFT,		/* map addr */
+					 memory_start >> PAGE_SHIFT,	/* start of RAM */
+					 memory_end >> PAGE_SHIFT	/* end of RAM */
+					 );
+
+	/* free all the usable memory */
+	free_bootmem(memory_start, memory_end - memory_start);
+
+	high_memory = (void *) (memory_end & PAGE_MASK);
+	max_mapnr = num_physpages = ((unsigned long) high_memory - PAGE_OFFSET) >> PAGE_SHIFT;
+
+	min_low_pfn = memory_start >> PAGE_SHIFT;
+	max_low_pfn = memory_end >> PAGE_SHIFT;
+	max_pfn = max_low_pfn;
+
+	/* now take back the bits the core kernel is occupying */
+#ifndef CONFIG_PROTECT_KERNEL
+	reserve_bootmem(kend, bootmap_size);
+	reserve_bootmem((unsigned long) &__kernel_image_start,
+			kend - (unsigned long) &__kernel_image_start);
+
+#else
+	dampr = __get_DAMPR(0);
+	dampr &= xAMPRx_SS;
+	dampr = (dampr >> 4) + 17;
+	dampr = 1 << dampr;
+
+	reserve_bootmem(__get_DAMPR(0) & xAMPRx_PPFN, dampr);
+#endif
+
+	/* reserve some memory to do uncached DMA through if requested */
+#ifdef CONFIG_RESERVE_DMA_COHERENT
+	if (dma_coherent_mem_start)
+		reserve_bootmem(dma_coherent_mem_start,
+				dma_coherent_mem_end - dma_coherent_mem_start);
+#endif
+
+} /* end setup_uclinux_memory() */
+#endif
+
+/*****************************************************************************/
+/*
+ * get CPU information for use by procfs
+ */
+static int show_cpuinfo(struct seq_file *m, void *v)
+{
+	const char *gr, *fr, *fm, *fp, *cm, *nem, *ble;
+#ifdef CONFIG_PM
+	const char *sep;
+#endif
+
+	gr  = cpu_hsr0_all & HSR0_GRHE	? "gr0-63"	: "gr0-31";
+	fr  = cpu_hsr0_all & HSR0_FRHE	? "fr0-63"	: "fr0-31";
+	fm  = cpu_psr_all  & PSR_EM	? ", Media"	: "";
+	fp  = cpu_psr_all  & PSR_EF	? ", FPU"	: "";
+	cm  = cpu_psr_all  & PSR_CM	? ", CCCR"	: "";
+	nem = cpu_psr_all  & PSR_NEM	? ", NE"	: "";
+	ble = cpu_psr_all  & PSR_BE	? "BE"		: "LE";
+
+	seq_printf(m,
+		   "CPU-Series:\t%s\n"
+		   "CPU-Core:\t%s, %s, %s%s%s\n"
+		   "CPU:\t\t%s\n"
+		   "MMU:\t\t%s\n"
+		   "FP-Media:\t%s%s%s\n"
+		   "System:\t\t%s",
+		   cpu_series,
+		   cpu_core, gr, ble, cm, nem,
+		   cpu_silicon,
+		   cpu_mmu,
+		   fr, fm, fp,
+		   cpu_system);
+
+	if (cpu_board1)
+		seq_printf(m, ", %s", cpu_board1);
+
+	if (cpu_board2)
+		seq_printf(m, ", %s", cpu_board2);
+
+	seq_printf(m, "\n");
+
+#ifdef CONFIG_PM
+	seq_printf(m, "PM-Controls:");
+	sep = "\t";
+
+	if (clock_bits_settable & CLOCK_BIT_CMODE) {
+		seq_printf(m, "%scmode=0x%04hx", sep, clock_cmodes_permitted);
+		sep = ", ";
+	}
+
+	if (clock_bits_settable & CLOCK_BIT_CM) {
+		seq_printf(m, "%scm=0x%lx", sep, clock_bits_settable & CLOCK_BIT_CM);
+		sep = ", ";
+	}
+
+	if (clock_bits_settable & CLOCK_BIT_P0) {
+		seq_printf(m, "%sp0=0x3", sep);
+		sep = ", ";
+	}
+
+	seq_printf(m, "%ssuspend=0x22\n", sep);
+#endif
+
+	seq_printf(m,
+		   "PM-Status:\tcmode=%d, cm=%d, p0=%d\n",
+		   clock_cmode_current, clock_cm_current, clock_p0_current);
+
+#define print_clk(TAG, VAR) \
+	seq_printf(m, "Clock-" TAG ":\t%lu.%2.2lu MHz\n", VAR / 1000000, (VAR / 10000) % 100)
+
+	print_clk("In",    __clkin_clock_speed_HZ);
+	print_clk("Core",  __core_clock_speed_HZ);
+	print_clk("SDRAM", __sdram_clock_speed_HZ);
+	print_clk("CBus",  __core_bus_clock_speed_HZ);
+	print_clk("Res",   __res_bus_clock_speed_HZ);
+	print_clk("Ext",   __ext_bus_clock_speed_HZ);
+	print_clk("DSU",   __dsu_clock_speed_HZ);
+
+	seq_printf(m,
+		   "BogoMips:\t%lu.%02lu\n",
+		   (loops_per_jiffy * HZ) / 500000, ((loops_per_jiffy * HZ) / 5000) % 100);
+
+	return 0;
+} /* end show_cpuinfo() */
+
+static void *c_start(struct seq_file *m, loff_t *pos)
+{
+	return *pos < NR_CPUS ? (void *) 0x12345678 : NULL;
+}
+
+static void *c_next(struct seq_file *m, void *v, loff_t *pos)
+{
+	++*pos;
+	return c_start(m, pos);
+}
+
+static void c_stop(struct seq_file *m, void *v)
+{
+}
+
+struct seq_operations cpuinfo_op = {
+	.start	= c_start,
+	.next	= c_next,
+	.stop	= c_stop,
+	.show	= show_cpuinfo,
+};
+
+void arch_gettod(int *year, int *mon, int *day, int *hour,
+		 int *min, int *sec)
+{
+	*year = *mon = *day = *hour = *min = *sec = 0;
+}
+
+/*****************************************************************************/
+/*
+ *
+ */
+#ifdef CONFIG_MB93090_MB00
+static void __init mb93090_sendlcdcmd(uint32_t cmd)
+{
+	unsigned long base = __addr_LCD();
+	int loop;
+
+	/* request reading of the busy flag */
+	__set_LCD(base, LCD_CMD_READ_BUSY);
+	__set_LCD(base, LCD_CMD_READ_BUSY & ~LCD_E);
+
+	/* wait for the busy flag to become clear */
+	for (loop = 10000; loop > 0; loop--)
+		if (!(__get_LCD(base) & 0x80))
+			break;
+
+	/* send the command */
+	__set_LCD(base, cmd);
+	__set_LCD(base, cmd & ~LCD_E);
+
+} /* end mb93090_sendlcdcmd() */
+
+/*****************************************************************************/
+/*
+ * write to the MB93090 LEDs and LCD
+ */
+static void __init mb93090_display(void)
+{
+	const char *p;
+
+	__set_LEDS(0);
+
+	/* set up the LCD */
+	mb93090_sendlcdcmd(LCD_CMD_CLEAR);
+	mb93090_sendlcdcmd(LCD_CMD_FUNCSET(1,1,0));
+	mb93090_sendlcdcmd(LCD_CMD_ON(0,0));
+	mb93090_sendlcdcmd(LCD_CMD_HOME);
+
+	mb93090_sendlcdcmd(LCD_CMD_SET_DD_ADDR(0));
+	for (p = mb93090_banner; *p; p++)
+		mb93090_sendlcdcmd(LCD_DATA_WRITE(*p));
+
+	mb93090_sendlcdcmd(LCD_CMD_SET_DD_ADDR(64));
+	for (p = mb93090_version; *p; p++)
+		mb93090_sendlcdcmd(LCD_DATA_WRITE(*p));
+
+} /* end mb93090_display() */
+
+#endif // CONFIG_MB93090_MB00
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/kernel/signal.c linux-2.6.10-rc1-mm3-frv/arch/frv/kernel/signal.c
--- /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/kernel/signal.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/arch/frv/kernel/signal.c	2004-11-05 14:13:03.219553541 +0000
@@ -0,0 +1,595 @@
+/*
+ *  linux/arch/frvnommu/kernel/signal.c
+ *
+ *  Copyright (C) 1991, 1992  Linus Torvalds
+ *
+ *  1997-11-28  Modified for POSIX.1b signals by Richard Henderson
+ *  2000-06-20  Pentium III FXSR, SSE support by Gareth Hughes
+ */
+
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/kernel.h>
+#include <linux/signal.h>
+#include <linux/errno.h>
+#include <linux/wait.h>
+#include <linux/ptrace.h>
+#include <linux/unistd.h>
+#include <linux/personality.h>
+#include <linux/suspend.h>
+#include <asm/ucontext.h>
+#include <asm/uaccess.h>
+#include <asm/cacheflush.h>
+
+#define DEBUG_SIG 0
+
+#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
+
+struct fdpic_func_descriptor {
+	unsigned long	text;
+	unsigned long	GOT;
+};
+
+asmlinkage int do_signal(struct pt_regs *regs, sigset_t *oldset);
+
+/*
+ * Atomically swap in the new signal mask, and wait for a signal.
+ */
+asmlinkage int sys_sigsuspend(int history0, int history1, old_sigset_t mask)
+{
+	sigset_t saveset;
+
+	mask &= _BLOCKABLE;
+	spin_lock_irq(&current->sighand->siglock);
+	saveset = current->blocked;
+	siginitset(&current->blocked, mask);
+	recalc_sigpending();
+	spin_unlock_irq(&current->sighand->siglock);
+
+	__frame->gr8 = -EINTR;
+	while (1) {
+		current->state = TASK_INTERRUPTIBLE;
+		schedule();
+		if (do_signal(__frame, &saveset))
+			/* return the signal number as the return value of this function
+			 * - this is an utterly evil hack. syscalls should not invoke do_signal()
+			 *   as entry.S sets regs->gr8 to the return value of the system call
+			 * - we can't just use sigpending() as we'd have to discard SIG_IGN signals
+			 *   and call waitpid() if SIGCHLD needed discarding
+			 * - this only works on the i386 because it passes arguments to the signal
+			 *   handler on the stack, and the return value in EAX is effectively
+			 *   discarded
+			 */
+			return __frame->gr8;
+	}
+}
+
+asmlinkage int sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize)
+{
+	sigset_t saveset, newset;
+
+	/* XXX: Don't preclude handling different sized sigset_t's.  */
+	if (sigsetsize != sizeof(sigset_t))
+		return -EINVAL;
+
+	if (copy_from_user(&newset, unewset, sizeof(newset)))
+		return -EFAULT;
+	sigdelsetmask(&newset, ~_BLOCKABLE);
+
+	spin_lock_irq(&current->sighand->siglock);
+	saveset = current->blocked;
+	current->blocked = newset;
+	recalc_sigpending();
+	spin_unlock_irq(&current->sighand->siglock);
+
+	__frame->gr8 = -EINTR;
+	while (1) {
+		current->state = TASK_INTERRUPTIBLE;
+		schedule();
+		if (do_signal(__frame, &saveset))
+			/* return the signal number as the return value of this function
+			 * - this is an utterly evil hack. syscalls should not invoke do_signal()
+			 *   as entry.S sets regs->gr8 to the return value of the system call
+			 * - we can't just use sigpending() as we'd have to discard SIG_IGN signals
+			 *   and call waitpid() if SIGCHLD needed discarding
+			 * - this only works on the i386 because it passes arguments to the signal
+			 *   handler on the stack, and the return value in EAX is effectively
+			 *   discarded
+			 */
+			return __frame->gr8;
+	}
+}
+
+asmlinkage int sys_sigaction(int sig,
+			     const struct old_sigaction __user *act,
+			     struct old_sigaction __user *oact)
+{
+	struct k_sigaction new_ka, old_ka;
+	int ret;
+
+	if (act) {
+		old_sigset_t mask;
+		if (verify_area(VERIFY_READ, act, sizeof(*act)) ||
+		    __get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
+		    __get_user(new_ka.sa.sa_restorer, &act->sa_restorer))
+			return -EFAULT;
+		__get_user(new_ka.sa.sa_flags, &act->sa_flags);
+		__get_user(mask, &act->sa_mask);
+		siginitset(&new_ka.sa.sa_mask, mask);
+	}
+
+	ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
+
+	if (!ret && oact) {
+		if (verify_area(VERIFY_WRITE, oact, sizeof(*oact)) ||
+		    __put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
+		    __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer))
+			return -EFAULT;
+		__put_user(old_ka.sa.sa_flags, &oact->sa_flags);
+		__put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
+	}
+
+	return ret;
+}
+
+asmlinkage
+int sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss)
+{
+	return do_sigaltstack(uss, uoss, __frame->sp);
+}
+
+
+/*
+ * Do a signal return; undo the signal stack.
+ */
+
+struct sigframe
+{
+	void (*pretcode)(void);
+	int sig;
+	struct sigcontext sc;
+	unsigned long extramask[_NSIG_WORDS-1];
+	uint32_t retcode[2];
+};
+
+struct rt_sigframe
+{
+	void (*pretcode)(void);
+	int sig;
+	struct siginfo *pinfo;
+	void *puc;
+	struct siginfo info;
+	struct ucontext uc;
+	uint32_t retcode[2];
+};
+
+static int restore_sigcontext(struct sigcontext __user *sc, int *_gr8)
+{
+	struct user_context *user = current->thread.user;
+	unsigned long tbr, psr;
+
+	tbr = user->i.tbr;
+	psr = user->i.psr;
+	if (copy_from_user(user, &sc->sc_context, sizeof(sc->sc_context)))
+		goto badframe;
+	user->i.tbr = tbr;
+	user->i.psr = psr;
+
+	restore_user_regs(user);
+
+	user->i.syscallno = -1;		/* disable syscall checks */
+
+	*_gr8 = user->i.gr[8];
+	return 0;
+
+ badframe:
+	return 1;
+}
+
+asmlinkage int sys_sigreturn(void)
+{
+	struct sigframe __user *frame = (struct sigframe __user *) __frame->sp;
+	sigset_t set;
+	int gr8;
+
+	if (verify_area(VERIFY_READ, frame, sizeof(*frame)))
+		goto badframe;
+	if (__get_user(set.sig[0], &frame->sc.sc_oldmask))
+		goto badframe;
+
+	if (_NSIG_WORDS > 1 &&
+	    __copy_from_user(&set.sig[1], &frame->extramask, sizeof(frame->extramask)))
+		goto badframe;
+
+	sigdelsetmask(&set, ~_BLOCKABLE);
+	spin_lock_irq(&current->sighand->siglock);
+	current->blocked = set;
+	recalc_sigpending();
+	spin_unlock_irq(&current->sighand->siglock);
+
+	if (restore_sigcontext(&frame->sc, &gr8))
+		goto badframe;
+	return gr8;
+
+ badframe:
+	force_sig(SIGSEGV, current);
+	return 0;
+}
+
+asmlinkage int sys_rt_sigreturn(void)
+{
+	struct rt_sigframe __user *frame = (struct rt_sigframe __user *) __frame->sp;
+	sigset_t set;
+	stack_t st;
+	int gr8;
+
+	if (verify_area(VERIFY_READ, frame, sizeof(*frame)))
+		goto badframe;
+	if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
+		goto badframe;
+
+	sigdelsetmask(&set, ~_BLOCKABLE);
+	spin_lock_irq(&current->sighand->siglock);
+	current->blocked = set;
+	recalc_sigpending();
+	spin_unlock_irq(&current->sighand->siglock);
+
+	if (restore_sigcontext(&frame->uc.uc_mcontext, &gr8))
+		goto badframe;
+
+	if (__copy_from_user(&st, &frame->uc.uc_stack, sizeof(st)))
+		goto badframe;
+
+	/* It is more difficult to avoid calling this function than to
+	 * call it and ignore errors.  */
+	/*
+	 * THIS CANNOT WORK! "&st" is a kernel address, and "do_sigaltstack()"
+	 * takes a user address (and verifies that it is a user address). End
+	 * result: it does exactly _nothing_.
+	 */
+	do_sigaltstack(&st, NULL, __frame->sp);
+
+	return gr8;
+
+badframe:
+	force_sig(SIGSEGV, current);
+	return 0;
+}
+
+/*
+ * Set up a signal frame
+ */
+static int setup_sigcontext(struct sigcontext __user *sc, unsigned long mask)
+{
+	save_user_regs(current->thread.user);
+
+	if (copy_to_user(&sc->sc_context, current->thread.user, sizeof(sc->sc_context)) != 0)
+		goto badframe;
+
+	/* non-iBCS2 extensions.. */
+	if (__put_user(mask, &sc->sc_oldmask) < 0)
+		goto badframe;
+
+	return 0;
+
+ badframe:
+	return 1;
+}
+
+/*****************************************************************************/
+/*
+ * Determine which stack to use..
+ */
+static inline void __user *get_sigframe(struct k_sigaction *ka,
+					struct pt_regs *regs,
+					size_t frame_size)
+{
+	unsigned long sp;
+
+	/* Default to using normal stack */
+	sp = regs->sp;
+
+	/* This is the X/Open sanctioned signal stack switching.  */
+	if (ka->sa.sa_flags & SA_ONSTACK) {
+		if (! on_sig_stack(sp))
+			sp = current->sas_ss_sp + current->sas_ss_size;
+	}
+
+	return (void __user *) ((sp - frame_size) & ~7UL);
+} /* end get_sigframe() */
+
+/*****************************************************************************/
+/*
+ *
+ */
+static void setup_frame(int sig, struct k_sigaction *ka, sigset_t *set, struct pt_regs * regs)
+{
+	struct sigframe __user *frame;
+	int rsig;
+
+	frame = get_sigframe(ka, regs, sizeof(*frame));
+
+	if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
+		goto give_sigsegv;
+
+	rsig = sig;
+	if (sig < 32 &&
+	    __current_thread_info->exec_domain &&
+	    __current_thread_info->exec_domain->signal_invmap)
+		rsig = __current_thread_info->exec_domain->signal_invmap[sig];
+
+	if (__put_user(rsig, &frame->sig) < 0)
+		goto give_sigsegv;
+
+	if (setup_sigcontext(&frame->sc, set->sig[0]))
+		goto give_sigsegv;
+
+	if (_NSIG_WORDS > 1) {
+		if (__copy_to_user(frame->extramask, &set->sig[1],
+				   sizeof(frame->extramask)))
+			goto give_sigsegv;
+	}
+
+	/* Set up to return from userspace.  If provided, use a stub
+	 * already in userspace.  */
+	if (ka->sa.sa_flags & SA_RESTORER) {
+		if (__put_user(ka->sa.sa_restorer, &frame->pretcode) < 0)
+			goto give_sigsegv;
+	}
+	else {
+		/* Set up the following code on the stack:
+		 *	setlos	#__NR_sigreturn,gr7
+		 *	tira	gr0,0
+		 */
+		if (__put_user((void (*)(void))frame->retcode, &frame->pretcode) ||
+		    __put_user(0x8efc0000|__NR_sigreturn, &frame->retcode[0]) ||
+		    __put_user(0xc0700000, &frame->retcode[1]))
+			goto give_sigsegv;
+
+		flush_icache_range((unsigned long) frame->retcode,
+				   (unsigned long) (frame->retcode + 2));
+	}
+
+	/* set up registers for signal handler */
+	regs->sp   = (unsigned long) frame;
+	regs->lr   = (unsigned long) &frame->retcode;
+	regs->gr8  = sig;
+
+	if (get_personality & FDPIC_FUNCPTRS) {
+		struct fdpic_func_descriptor __user *funcptr =
+			(struct fdpic_func_descriptor *) ka->sa.sa_handler;
+		__get_user(regs->pc, &funcptr->text);
+		__get_user(regs->gr15, &funcptr->GOT);
+	} else {
+		regs->pc   = (unsigned long) ka->sa.sa_handler;
+		regs->gr15 = 0;
+	}
+
+	set_fs(USER_DS);
+
+#if DEBUG_SIG
+	printk("SIG deliver %d (%s:%d): sp=%p pc=%lx ra=%p\n",
+		sig, current->comm, current->pid, frame, regs->pc, frame->pretcode);
+#endif
+
+	return;
+
+give_sigsegv:
+	if (sig == SIGSEGV)
+		ka->sa.sa_handler = SIG_DFL;
+
+	force_sig(SIGSEGV, current);
+} /* end setup_frame() */
+
+/*****************************************************************************/
+/*
+ *
+ */
+static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
+			   sigset_t *set, struct pt_regs * regs)
+{
+	struct rt_sigframe __user *frame;
+	int rsig;
+
+	frame = get_sigframe(ka, regs, sizeof(*frame));
+
+	if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
+		goto give_sigsegv;
+
+	rsig = sig;
+	if (sig < 32 &&
+	    __current_thread_info->exec_domain &&
+	    __current_thread_info->exec_domain->signal_invmap)
+		rsig = __current_thread_info->exec_domain->signal_invmap[sig];
+
+	if (__put_user(rsig,		&frame->sig) ||
+	    __put_user(&frame->info,	&frame->pinfo) ||
+	    __put_user(&frame->uc,	&frame->puc))
+		goto give_sigsegv;
+
+	if (copy_siginfo_to_user(&frame->info, info))
+		goto give_sigsegv;
+
+	/* Create the ucontext.  */
+	if (__put_user(0, &frame->uc.uc_flags) ||
+	    __put_user(0, &frame->uc.uc_link) ||
+	    __put_user((void*)current->sas_ss_sp, &frame->uc.uc_stack.ss_sp) ||
+	    __put_user(sas_ss_flags(regs->sp), &frame->uc.uc_stack.ss_flags) ||
+	    __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size))
+		goto give_sigsegv;
+
+	if (setup_sigcontext(&frame->uc.uc_mcontext, set->sig[0]))
+		goto give_sigsegv;
+
+	if (__copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)))
+		goto give_sigsegv;
+
+	/* Set up to return from userspace.  If provided, use a stub
+	 * already in userspace.  */
+	if (ka->sa.sa_flags & SA_RESTORER) {
+		if (__put_user(ka->sa.sa_restorer, &frame->pretcode))
+			goto give_sigsegv;
+	}
+	else {
+		/* Set up the following code on the stack:
+		 *	setlos	#__NR_sigreturn,gr7
+		 *	tira	gr0,0
+		 */
+		if (__put_user((void (*)(void))frame->retcode, &frame->pretcode) ||
+		    __put_user(0x8efc0000|__NR_rt_sigreturn, &frame->retcode[0]) ||
+		    __put_user(0xc0700000, &frame->retcode[1]))
+			goto give_sigsegv;
+
+		flush_icache_range((unsigned long) frame->retcode,
+				   (unsigned long) (frame->retcode + 2));
+	}
+
+	/* Set up registers for signal handler */
+	regs->sp  = (unsigned long) frame;
+	regs->lr   = (unsigned long) &frame->retcode;
+	regs->gr8 = sig;
+	regs->gr9 = (unsigned long) &frame->info;
+
+	if (get_personality & FDPIC_FUNCPTRS) {
+		struct fdpic_func_descriptor *funcptr =
+			(struct fdpic_func_descriptor __user *) ka->sa.sa_handler;
+		__get_user(regs->pc, &funcptr->text);
+		__get_user(regs->gr15, &funcptr->GOT);
+	} else {
+		regs->pc   = (unsigned long) ka->sa.sa_handler;
+		regs->gr15 = 0;
+	}
+
+	set_fs(USER_DS);
+
+#if DEBUG_SIG
+	printk("SIG deliver %d (%s:%d): sp=%p pc=%lx ra=%p\n",
+		sig, current->comm, current->pid, frame, regs->pc, frame->pretcode);
+#endif
+
+	return;
+
+give_sigsegv:
+	if (sig == SIGSEGV)
+		ka->sa.sa_handler = SIG_DFL;
+	force_sig(SIGSEGV, current);
+
+} /* end setup_rt_frame() */
+
+/*****************************************************************************/
+/*
+ * OK, we're invoking a handler
+ */
+static void handle_signal(unsigned long sig, siginfo_t *info,
+			  struct k_sigaction *ka, sigset_t *oldset,
+			  struct pt_regs *regs)
+{
+	/* Are we from a system call? */
+	if (in_syscall(regs)) {
+		/* If so, check system call restarting.. */
+		switch (regs->gr8) {
+		case -ERESTART_RESTARTBLOCK:
+		case -ERESTARTNOHAND:
+			regs->gr8 = -EINTR;
+			break;
+
+		case -ERESTARTSYS:
+			if (!(ka->sa.sa_flags & SA_RESTART)) {
+				regs->gr8 = -EINTR;
+				break;
+			}
+			/* fallthrough */
+		case -ERESTARTNOINTR:
+			regs->gr8 = regs->orig_gr8;
+			regs->pc -= 4;
+		}
+	}
+
+	/* Set up the stack frame */
+	if (ka->sa.sa_flags & SA_SIGINFO)
+		setup_rt_frame(sig, ka, info, oldset, regs);
+	else
+		setup_frame(sig, ka, oldset, regs);
+
+	if (!(ka->sa.sa_flags & SA_NODEFER)) {
+		spin_lock_irq(&current->sighand->siglock);
+		sigorsets(&current->blocked, &current->blocked, &ka->sa.sa_mask);
+		sigaddset(&current->blocked, sig);
+		recalc_sigpending();
+		spin_unlock_irq(&current->sighand->siglock);
+	}
+} /* end handle_signal() */
+
+/*****************************************************************************/
+/*
+ * Note that 'init' is a special process: it doesn't get signals it doesn't
+ * want to handle. Thus you cannot kill init even with a SIGKILL even by
+ * mistake.
+ */
+int do_signal(struct pt_regs *regs, sigset_t *oldset)
+{
+	struct k_sigaction ka;
+	siginfo_t info;
+	int signr;
+
+	/*
+	 * We want the common case to go fast, which
+	 * is why we may in certain cases get here from
+	 * kernel mode. Just return without doing anything
+	 * if so.
+	 */
+	if (!user_mode(regs))
+		return 1;
+
+	if (current->flags & PF_FREEZE) {
+		refrigerator(0);
+		goto no_signal;
+	}
+
+	if (!oldset)
+		oldset = &current->blocked;
+
+	signr = get_signal_to_deliver(&info, &ka, regs, NULL);
+	if (signr > 0) {
+		handle_signal(signr, &info, &ka, oldset, regs);
+		return 1;
+	}
+
+ no_signal:
+	/* Did we come from a system call? */
+	if (regs->syscallno >= 0) {
+		/* Restart the system call - no handlers present */
+		if (regs->gr8 == -ERESTARTNOHAND ||
+		    regs->gr8 == -ERESTARTSYS ||
+		    regs->gr8 == -ERESTARTNOINTR) {
+			regs->gr8 = regs->orig_gr8;
+			regs->pc -= 4;
+		}
+
+		if (regs->gr8 == -ERESTART_RESTARTBLOCK){
+			regs->gr8 = __NR_restart_syscall;
+			regs->pc -= 4;
+		}
+	}
+
+	return 0;
+} /* end do_signal() */
+
+/*****************************************************************************/
+/*
+ * notification of userspace execution resumption
+ * - triggered by current->work.notify_resume
+ */
+asmlinkage void do_notify_resume(__u32 thread_info_flags)
+{
+	/* pending single-step? */
+	if (thread_info_flags & _TIF_SINGLESTEP)
+		clear_thread_flag(TIF_SINGLESTEP);
+
+	/* deal with pending signal delivery */
+	if (thread_info_flags & _TIF_SIGPENDING)
+		do_signal(__frame, NULL);
+	
+} /* end do_notify_resume() */
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/kernel/sleep.S linux-2.6.10-rc1-mm3-frv/arch/frv/kernel/sleep.S
--- /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/kernel/sleep.S	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/arch/frv/kernel/sleep.S	2004-11-05 14:13:03.223553203 +0000
@@ -0,0 +1,356 @@
+/* sleep.S: power saving mode entry
+ *
+ * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
+ * Written by David Woodhouse (dwmw2@redhat.com)
+ *
+ * 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.
+ *
+ */
+
+#include <linux/sys.h>
+#include <linux/config.h>
+#include <linux/linkage.h>
+#include <asm/setup.h>
+#include <asm/segment.h>
+#include <asm/page.h>
+#include <asm/ptrace.h>
+#include <asm/errno.h>
+#include <asm/cache.h>
+#include <asm/spr-regs.h>
+
+#define __addr_MASK	0xfeff9820	/* interrupt controller mask */
+
+#define __addr_SDRAMC	0xfe000400	/* SDRAM controller regs */
+#define SDRAMC_DSTS	0x28		/* SDRAM status */
+#define SDRAMC_DSTS_SSI	0x00000001	/* indicates that the SDRAM is in self-refresh mode */
+#define SDRAMC_DRCN	0x30		/* SDRAM refresh control */
+#define SDRAMC_DRCN_SR	0x00000001	/* transition SDRAM into self-refresh mode */
+
+	.section	.bss
+	.balign		8
+	.globl		__sleep_save_area
+__sleep_save_area:
+	.space		16
+
+
+	.text
+	.balign		4
+
+.macro li v r
+	sethi.p		%hi(\v),\r
+	setlo		%lo(\v),\r
+.endm
+
+#ifdef CONFIG_PM
+###############################################################################
+#
+# CPU suspension routine
+# - void frv_cpu_suspend(unsigned long pdm_mode)
+#
+###############################################################################
+	.globl		frv_cpu_suspend
+        .type		frv_cpu_suspend,@function
+frv_cpu_suspend:
+
+	#----------------------------------------------------
+	# save hsr0, psr, isr, and lr for resume code
+	#----------------------------------------------------
+	li		__sleep_save_area,gr11
+
+	movsg		hsr0,gr4
+	movsg		psr,gr5
+	movsg		isr,gr6
+	movsg		lr,gr7
+	stdi		gr4,@(gr11,#0)
+	stdi		gr6,@(gr11,#8)
+
+	# store the return address from sleep in GR14, and its complement in GR13 as a check
+	li		__ramboot_resume,gr14
+#ifdef CONFIG_MMU
+	# Resume via RAMBOOT# will turn MMU off, so bootloader needs a physical address.
+	sethi.p		%hi(__page_offset),gr13
+	setlo		%lo(__page_offset),gr13
+	sub		gr14,gr13,gr14
+#endif
+	not		gr14,gr13
+
+	#----------------------------------------------------
+	# preload and lock into icache that code which may have to run
+	# when dram is in self-refresh state.
+	#----------------------------------------------------
+	movsg		hsr0, gr3
+	li		HSR0_ICE,gr4
+	or		gr3,gr4,gr3
+	movgs		gr3,hsr0
+	or		gr3,gr8,gr7	// add the sleep bits for later
+	
+	li		#__icache_lock_start,gr3
+	li		#__icache_lock_end,gr4
+1:	icpl		gr3,gr0,#1
+	addi		gr3,#L1_CACHE_BYTES,gr3
+	cmp		gr4,gr3,icc0
+	bhi		icc0,#0,1b
+
+	# disable exceptions
+	movsg		psr,gr8
+	andi.p		gr8,#~PSR_PIL,gr8
+	andi		gr8,~PSR_ET,gr8
+	movgs		gr8,psr
+	ori		gr8,#PSR_ET,gr8
+
+	bra		__icache_lock_start
+
+	.size		frv_cpu_suspend, .-frv_cpu_suspend
+
+#
+# the final part of the sleep sequence...
+# - we want it to be be cacheline aligned so we can lock it into the icache easily
+#  On entry:	gr7 holds desired hsr0 sleep value
+#               gr8 holds desired psr sleep value
+#
+	.balign		L1_CACHE_BYTES
+        .type		__icache_lock_start,@function
+__icache_lock_start:
+
+	#----------------------------------------------------
+	# put SDRAM in self-refresh mode
+	#----------------------------------------------------
+	li		__sleep_save_area,gr4
+	
+	# Flush all data in the cache using the DCEF instruction.
+	dcef		@(gr0,gr0),#1
+
+	# Stop DMAC transfer
+
+	# Execute dummy load from SDRAM
+	ldi.p		@(gr4,#0),gr4
+
+	# put the SDRAM into self-refresh mode
+	setlos		SDRAMC_DRCN_SR,gr3
+	li		__addr_SDRAMC,gr4
+	sti		gr3,@(gr4,#SDRAMC_DRCN)
+	membar
+
+	# wait for SDRAM to reach self-refresh mode
+1:	ldi		@(gr4,#SDRAMC_DSTS),gr3
+	andicc		gr3,#SDRAMC_DSTS_SSI,gr3,icc0
+	beq		icc0,#0,1b
+
+	#  Set the GPIO register so that the IRQ[3:0] pins become valid, as required.
+	#  Set the clock mode (CLKC register) as required.
+	#     - At this time, also set the CLKC register P0 bit.
+	
+	# Set the HSR0 register PDM field.
+	movgs		gr7,hsr0
+
+	# Execute NOP 32 times.
+	.rept		32
+	nop
+	.endr
+
+#if 0 // Fujitsu recommend to skip this and will update docs.
+	#      Release the interrupt mask setting of the MASK register of the 
+	#      interrupt controller if necessary.
+	sti		gr10,@(gr9,#0)
+	membar
+#endif
+		
+	# Set the PSR register ET bit to 1 to enable interrupts.
+	movgs		gr8,psr
+
+	###################################################
+	# this is only reached if waking up via interrupt
+	###################################################
+
+	# Execute NOP 32 times.
+	.rept		32
+	nop
+	.endr
+
+	#----------------------------------------------------
+	# wake SDRAM from self-refresh mode
+	#----------------------------------------------------
+	li		__addr_SDRAMC,gr4
+	sti		gr0,@(gr4,#SDRAMC_DRCN) // Turn off self-refresh.
+2:	
+	ldi		@(gr4,#SDRAMC_DSTS),gr3	// Wait for it to come back...
+	andicc		gr3,#SDRAMC_DSTS_SSI,gr0,icc0
+	bne		icc0,0,2b
+	
+	# wait for the SDRAM to stabilise
+	li		0x0100000,gr3
+3:	subicc		gr3,#1,gr3,icc0
+	bne		icc0,#0,3b
+
+	# now that DRAM is back, this is the end of the code which gets
+	# locked in icache.
+__icache_lock_end:
+	.size		__icache_lock_start, .-__icache_lock_start
+
+	# Fall-through to the RAMBOOT# wakeup path
+	
+###############################################################################
+#
+#  resume from suspend re-entry point reached via RAMBOOT# and bootloader
+#
+###############################################################################
+__ramboot_resume:
+	
+	#----------------------------------------------------
+	# restore hsr0, psr, isr, and leave saved lr in gr7
+	#----------------------------------------------------
+	li		__sleep_save_area,gr11
+#ifdef CONFIG_MMU
+	movsg		hsr0,gr4
+	sethi.p		%hi(HSR0_EXMMU),gr3
+	setlo		%lo(HSR0_EXMMU),gr3
+	andcc		gr3,gr4,gr0,icc0
+	bne		icc0,#0,2f
+	
+	# need to use physical address
+	sethi.p		%hi(__page_offset),gr3
+	setlo		%lo(__page_offset),gr3
+	sub		gr11,gr3,gr11
+	
+	# flush all tlb entries
+	setlos		#64,gr4
+	setlos.p	#PAGE_SIZE,gr5
+	setlos		#0,gr6
+1:
+	tlbpr		gr6,gr0,#6,#0
+	subicc.p	gr4,#1,gr4,icc0
+	add		gr6,gr5,gr6
+	bne		icc0,#2,1b
+
+	# need a temporary mapping for the current physical address we are
+	# using between time MMU is enabled and jump to virtual address is
+	# made.
+	sethi.p		%hi(0x00000000),gr4
+	setlo		%lo(0x00000000),gr4		; physical address
+	setlos		#xAMPRx_L|xAMPRx_M|xAMPRx_SS_256Mb|xAMPRx_S_KERNEL|xAMPRx_V,gr5
+	or		gr4,gr5,gr5
+
+	movsg		cxnr,gr13
+	or		gr4,gr13,gr4	
+
+	movgs		gr4,iamlr1			; mapped from real address 0
+	movgs		gr5,iampr1			; cached kernel memory at 0x00000000
+2:
+#endif
+
+	lddi		@(gr11,#0),gr4 ; hsr0, psr 
+	lddi		@(gr11,#8),gr6 ; isr, lr
+	movgs		gr4,hsr0
+	bar
+	
+#ifdef CONFIG_MMU
+	sethi.p		%hi(1f),gr11
+	setlo		%lo(1f),gr11
+	jmpl		@(gr11,gr0)
+1:
+	movgs		gr0,iampr1 	; get rid of temporary mapping
+#endif
+	movgs		gr5,psr
+	movgs		gr6,isr
+	
+	#----------------------------------------------------
+	# unlock the icache which was locked before going to sleep
+	#----------------------------------------------------
+	li		__icache_lock_start,gr3
+	li		__icache_lock_end,gr4
+1:	icul		gr3
+	addi		gr3,#L1_CACHE_BYTES,gr3
+	cmp		gr4,gr3,icc0
+	bhi		icc0,#0,1b
+
+	#----------------------------------------------------
+	# back to business as usual
+	#----------------------------------------------------
+	jmpl		@(gr7,gr0)		;
+
+#endif /* CONFIG_PM */
+
+###############################################################################
+#
+# CPU core sleep mode routine
+#
+###############################################################################
+	.globl		frv_cpu_core_sleep
+        .type		frv_cpu_core_sleep,@function
+frv_cpu_core_sleep:
+
+	# Preload into icache.
+	li		#__core_sleep_icache_lock_start,gr3
+	li		#__core_sleep_icache_lock_end,gr4
+
+1:	icpl		gr3,gr0,#1
+	addi		gr3,#L1_CACHE_BYTES,gr3
+	cmp		gr4,gr3,icc0
+	bhi		icc0,#0,1b
+
+	bra	__core_sleep_icache_lock_start
+
+	.balign L1_CACHE_BYTES
+__core_sleep_icache_lock_start:
+	
+	# (1) Set the PSR register ET bit to 0 to disable interrupts.
+	movsg		psr,gr8
+	andi.p		gr8,#~(PSR_PIL),gr8
+	andi		gr8,#~(PSR_ET),gr4
+	movgs		gr4,psr
+
+#if 0 // Fujitsu recommend to skip this and will update docs.
+	# (2) Set '1' to all bits in the MASK register of the interrupt 
+	#     controller and mask interrupts.
+	sethi.p		%hi(__addr_MASK),gr9
+	setlo		%lo(__addr_MASK),gr9
+	sethi.p		%hi(0xffff0000),gr4
+	setlo		%lo(0xffff0000),gr4
+	ldi		@(gr9,#0),gr10
+	sti		gr4,@(gr9,#0)
+#endif
+	# (3) Flush all data in the cache using the DCEF instruction.
+	dcef		@(gr0,gr0),#1
+
+	# (4) Execute the memory barrier instruction
+	membar
+
+	# (5) Set the GPIO register so that the IRQ[3:0] pins become valid, as required.
+	# (6) Set the clock mode (CLKC register) as required.
+	#     - At this time, also set the CLKC register P0 bit.
+	# (7) Set the HSR0 register PDM field to  001 .
+	movsg		hsr0,gr4
+	ori		gr4,HSR0_PDM_CORE_SLEEP,gr4
+	movgs		gr4,hsr0
+
+	# (8) Execute NOP 32 times.
+	.rept		32
+	nop
+	.endr
+
+#if 0 // Fujitsu recommend to skip this and will update docs.
+	# (9) Release the interrupt mask setting of the MASK register of the 
+	#     interrupt controller if necessary.
+	sti		gr10,@(gr9,#0)
+	membar
+#endif
+		
+	# (10) Set the PSR register ET bit to 1 to enable interrupts.
+	movgs		gr8,psr
+
+__core_sleep_icache_lock_end:
+
+	# Unlock from icache
+	li	__core_sleep_icache_lock_start,gr3
+	li	__core_sleep_icache_lock_end,gr4
+1:	icul		gr3
+	addi		gr3,#L1_CACHE_BYTES,gr3
+	cmp		gr4,gr3,icc0
+	bhi		icc0,#0,1b
+
+	bralr
+		
+	.size		frv_cpu_core_sleep, .-frv_cpu_core_sleep
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/kernel/switch_to.S linux-2.6.10-rc1-mm3-frv/arch/frv/kernel/switch_to.S
--- /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/kernel/switch_to.S	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/arch/frv/kernel/switch_to.S	2004-11-05 14:13:03.229552696 +0000
@@ -0,0 +1,486 @@
+###############################################################################
+#
+# switch_to.S: context switch operation
+#
+# Copyright (C) 2003 Red Hat, Inc. All Rights Reserved.
+# Written by David Howells (dhowells@redhat.com)
+#
+# 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.
+#
+###############################################################################
+#include <linux/config.h>
+#include <linux/linkage.h>
+#include <asm/thread_info.h>
+#include <asm/processor.h>
+#include <asm/registers.h>
+#include <asm/spr-regs.h>
+
+.macro LEDS val
+	setlos		#~\val,gr27
+	st		gr27,@(gr30,gr0)
+	membar
+	dcf		@(gr30,gr0)
+.endm
+
+	.section	.sdata
+	.balign		8
+
+	# address of frame 0 (userspace) on current kernel stack
+	.globl		__kernel_frame0_ptr
+__kernel_frame0_ptr:
+	.long		init_thread_union + THREAD_SIZE - USER_CONTEXT_SIZE
+
+	# address of current task
+	.globl		__kernel_current_task
+__kernel_current_task:
+	.long		init_task
+
+	.section	.text
+	.balign		4
+
+###############################################################################
+#
+# struct task_struct *__switch_to(struct thread_struct *prev, struct thread_struct *next)
+#
+###############################################################################
+	.globl		__switch_to
+__switch_to:
+	# save outgoing process's context
+	sethi.p		%hi(__switch_back),gr11
+	setlo		%lo(__switch_back),gr11
+	movsg		lr,gr10
+
+	stdi		gr28,@(gr8,#__THREAD_FRAME)
+	sti		sp  ,@(gr8,#__THREAD_SP)
+	sti		fp  ,@(gr8,#__THREAD_FP)
+	stdi		gr10,@(gr8,#__THREAD_LR)
+	stdi		gr16,@(gr8,#__THREAD_GR(16))
+	stdi		gr18,@(gr8,#__THREAD_GR(18))
+	stdi		gr20,@(gr8,#__THREAD_GR(20))
+	stdi		gr22,@(gr8,#__THREAD_GR(22))
+	stdi		gr24,@(gr8,#__THREAD_GR(24))
+	stdi.p		gr26,@(gr8,#__THREAD_GR(26))
+
+	or		gr8,gr8,gr22
+	ldi.p		@(gr8,#__THREAD_USER),gr8
+	call		save_user_regs
+	or		gr22,gr22,gr8
+
+	# retrieve the new context
+	sethi.p		%hi(__kernel_frame0_ptr),gr6
+	setlo		%lo(__kernel_frame0_ptr),gr6
+	movsg		psr,gr4
+
+	lddi.p		@(gr9,#__THREAD_FRAME),gr10
+	or		gr29,gr29,gr27		; ret_from_fork needs to know old current
+
+	ldi		@(gr11,#4),gr19		; get new_current->thread_info
+
+	lddi		@(gr9,#__THREAD_SP),gr12
+	ldi		@(gr9,#__THREAD_LR),gr14
+	ldi		@(gr9,#__THREAD_PC),gr18
+	ldi.p		@(gr9,#__THREAD_FRAME0),gr7
+
+	# actually switch kernel contexts with ordinary exceptions disabled
+	andi		gr4,#~PSR_ET,gr5
+	movgs		gr5,psr
+
+	or.p		gr10,gr0,gr28
+	or		gr11,gr0,gr29
+	or.p		gr12,gr0,sp
+	or		gr13,gr0,fp
+	or		gr19,gr0,gr15		; set __current_thread_info
+
+	sti		gr7,@(gr6,#0)		; set __kernel_frame0_ptr
+	sti		gr29,@(gr6,#4)		; set __kernel_current_task
+
+	movgs		gr14,lr
+	bar
+
+	srli		gr15,#28,gr5
+	subicc		gr5,#0xc,gr0,icc0
+	beq		icc0,#0,111f
+	break
+	nop
+111:
+	
+	# jump to __switch_back or ret_from_fork as appropriate
+	movgs		gr4,psr
+	jmpl		@(gr18,gr0)
+
+###############################################################################
+#
+# restore incoming process's context
+# - on entry:
+#   - SP, FP, LR, GR15, GR28 and GR29 will have been set up appropriately
+#   - GR9 will point to the incoming thread_struct
+#
+###############################################################################
+__switch_back:
+	lddi		@(gr9,#__THREAD_GR(16)),gr16
+	lddi		@(gr9,#__THREAD_GR(18)),gr18
+	lddi		@(gr9,#__THREAD_GR(20)),gr20
+	lddi		@(gr9,#__THREAD_GR(22)),gr22
+	lddi		@(gr9,#__THREAD_GR(24)),gr24
+	lddi		@(gr9,#__THREAD_GR(26)),gr26
+
+	# fall through into restore_user_regs()
+	ldi		@(gr9,#__THREAD_USER),gr8
+
+###############################################################################
+#
+# restore extra general regs and FP/Media regs
+# - void restore_user_regs(const struct user_context *target)
+#
+###############################################################################
+	.globl		restore_user_regs
+restore_user_regs:
+	movsg		hsr0,gr6
+	ori		gr6,#HSR0_GRHE|HSR0_FRLE|HSR0_FRHE,gr6
+	movgs		gr6,hsr0
+	movsg		hsr0,gr6
+
+	movsg		psr,gr7
+	ori		gr7,#PSR_EF|PSR_EM,gr7
+	movgs		gr7,psr
+	movsg		psr,gr7
+	srli		gr7,#24,gr7
+	bar
+
+	lddi		@(gr8,#__FPMEDIA_MSR(0)),gr4
+
+	movgs		gr4,msr0
+	movgs		gr5,msr1
+
+	lddfi		@(gr8,#__FPMEDIA_ACC(0)),fr16
+	lddfi		@(gr8,#__FPMEDIA_ACC(2)),fr18
+	ldbfi		@(gr8,#__FPMEDIA_ACCG(0)),fr20
+	ldbfi		@(gr8,#__FPMEDIA_ACCG(1)),fr21
+	ldbfi		@(gr8,#__FPMEDIA_ACCG(2)),fr22
+	ldbfi		@(gr8,#__FPMEDIA_ACCG(3)),fr23
+
+	mwtacc		fr16,acc0
+	mwtacc		fr17,acc1
+	mwtacc		fr18,acc2
+	mwtacc		fr19,acc3
+	mwtaccg		fr20,accg0
+	mwtaccg		fr21,accg1
+	mwtaccg		fr22,accg2
+	mwtaccg		fr23,accg3
+
+	# some CPUs have extra ACCx and ACCGx regs and maybe FSRx regs
+	subicc.p	gr7,#0x50,gr0,icc0
+	subicc		gr7,#0x31,gr0,icc1
+	beq		icc0,#0,__restore_acc_fr451
+	beq		icc1,#0,__restore_acc_fr555
+__restore_acc_cont:
+
+	# some CPU's have GR32-GR63
+	setlos		#HSR0_FRHE,gr4
+	andcc		gr6,gr4,gr0,icc0
+	beq		icc0,#1,__restore_skip_gr32_gr63
+
+	lddi		@(gr8,#__INT_GR(32)),gr32
+	lddi		@(gr8,#__INT_GR(34)),gr34
+	lddi		@(gr8,#__INT_GR(36)),gr36
+	lddi		@(gr8,#__INT_GR(38)),gr38
+	lddi		@(gr8,#__INT_GR(40)),gr40
+	lddi		@(gr8,#__INT_GR(42)),gr42
+	lddi		@(gr8,#__INT_GR(44)),gr44
+	lddi		@(gr8,#__INT_GR(46)),gr46
+	lddi		@(gr8,#__INT_GR(48)),gr48
+	lddi		@(gr8,#__INT_GR(50)),gr50
+	lddi		@(gr8,#__INT_GR(52)),gr52
+	lddi		@(gr8,#__INT_GR(54)),gr54
+	lddi		@(gr8,#__INT_GR(56)),gr56
+	lddi		@(gr8,#__INT_GR(58)),gr58
+	lddi		@(gr8,#__INT_GR(60)),gr60
+	lddi		@(gr8,#__INT_GR(62)),gr62
+__restore_skip_gr32_gr63:
+
+	# all CPU's have FR0-FR31
+	lddfi		@(gr8,#__FPMEDIA_FR( 0)),fr0
+	lddfi		@(gr8,#__FPMEDIA_FR( 2)),fr2
+	lddfi		@(gr8,#__FPMEDIA_FR( 4)),fr4
+	lddfi		@(gr8,#__FPMEDIA_FR( 6)),fr6
+	lddfi		@(gr8,#__FPMEDIA_FR( 8)),fr8
+	lddfi		@(gr8,#__FPMEDIA_FR(10)),fr10
+	lddfi		@(gr8,#__FPMEDIA_FR(12)),fr12
+	lddfi		@(gr8,#__FPMEDIA_FR(14)),fr14
+	lddfi		@(gr8,#__FPMEDIA_FR(16)),fr16
+	lddfi		@(gr8,#__FPMEDIA_FR(18)),fr18
+	lddfi		@(gr8,#__FPMEDIA_FR(20)),fr20
+	lddfi		@(gr8,#__FPMEDIA_FR(22)),fr22
+	lddfi		@(gr8,#__FPMEDIA_FR(24)),fr24
+	lddfi		@(gr8,#__FPMEDIA_FR(26)),fr26
+	lddfi		@(gr8,#__FPMEDIA_FR(28)),fr28
+	lddfi.p		@(gr8,#__FPMEDIA_FR(30)),fr30
+
+	# some CPU's have FR32-FR63
+	setlos		#HSR0_FRHE,gr4
+	andcc		gr6,gr4,gr0,icc0
+	beq		icc0,#1,__restore_skip_fr32_fr63
+
+	lddfi		@(gr8,#__FPMEDIA_FR(32)),fr32
+	lddfi		@(gr8,#__FPMEDIA_FR(34)),fr34
+	lddfi		@(gr8,#__FPMEDIA_FR(36)),fr36
+	lddfi		@(gr8,#__FPMEDIA_FR(38)),fr38
+	lddfi		@(gr8,#__FPMEDIA_FR(40)),fr40
+	lddfi		@(gr8,#__FPMEDIA_FR(42)),fr42
+	lddfi		@(gr8,#__FPMEDIA_FR(44)),fr44
+	lddfi		@(gr8,#__FPMEDIA_FR(46)),fr46
+	lddfi		@(gr8,#__FPMEDIA_FR(48)),fr48
+	lddfi		@(gr8,#__FPMEDIA_FR(50)),fr50
+	lddfi		@(gr8,#__FPMEDIA_FR(52)),fr52
+	lddfi		@(gr8,#__FPMEDIA_FR(54)),fr54
+	lddfi		@(gr8,#__FPMEDIA_FR(56)),fr56
+	lddfi		@(gr8,#__FPMEDIA_FR(58)),fr58
+	lddfi		@(gr8,#__FPMEDIA_FR(60)),fr60
+	lddfi		@(gr8,#__FPMEDIA_FR(62)),fr62
+__restore_skip_fr32_fr63:
+
+	lddi		@(gr8,#__FPMEDIA_FNER(0)),gr4
+	movsg		fner0,gr4
+	movsg		fner1,gr5
+	bralr
+
+	# the FR451 also has ACC8-11/ACCG8-11 regs (but not 4-7...)
+__restore_acc_fr451:
+	lddfi		@(gr8,#__FPMEDIA_ACC(4)),fr16
+	lddfi		@(gr8,#__FPMEDIA_ACC(6)),fr18
+	ldbfi		@(gr8,#__FPMEDIA_ACCG(4)),fr20
+	ldbfi		@(gr8,#__FPMEDIA_ACCG(5)),fr21
+	ldbfi		@(gr8,#__FPMEDIA_ACCG(6)),fr22
+	ldbfi		@(gr8,#__FPMEDIA_ACCG(7)),fr23
+
+	mwtacc		fr16,acc8
+	mwtacc		fr17,acc9
+	mwtacc		fr18,acc10
+	mwtacc		fr19,acc11
+	mwtaccg		fr20,accg8
+	mwtaccg		fr21,accg9
+	mwtaccg		fr22,accg10
+	mwtaccg		fr23,accg11
+	bra		__restore_acc_cont
+
+	# the FR555 also has ACC4-7/ACCG4-7 regs and an FSR0 reg
+__restore_acc_fr555:
+	lddfi		@(gr8,#__FPMEDIA_ACC(4)),fr16
+	lddfi		@(gr8,#__FPMEDIA_ACC(6)),fr18
+	ldbfi		@(gr8,#__FPMEDIA_ACCG(4)),fr20
+	ldbfi		@(gr8,#__FPMEDIA_ACCG(5)),fr21
+	ldbfi		@(gr8,#__FPMEDIA_ACCG(6)),fr22
+	ldbfi		@(gr8,#__FPMEDIA_ACCG(7)),fr23
+
+	mnop.p
+	mwtacc		fr16,acc4
+	mnop.p
+	mwtacc		fr17,acc5
+	mnop.p
+	mwtacc		fr18,acc6
+	mnop.p
+	mwtacc		fr19,acc7
+	mnop.p
+	mwtaccg		fr20,accg4
+	mnop.p
+	mwtaccg		fr21,accg5
+	mnop.p
+	mwtaccg		fr22,accg6
+	mnop.p
+	mwtaccg		fr23,accg7
+
+	ldi		@(gr8,#__FPMEDIA_FSR(0)),gr4
+	movgs		gr4,fsr0
+
+	bra		__restore_acc_cont
+
+
+###############################################################################
+#
+# save extra general regs and FP/Media regs
+# - void save_user_regs(struct user_context *target)
+#
+###############################################################################
+	.globl		save_user_regs
+save_user_regs:
+	movsg		hsr0,gr6
+	ori		gr6,#HSR0_GRHE|HSR0_FRLE|HSR0_FRHE,gr6
+	movgs		gr6,hsr0
+	movsg		hsr0,gr6
+
+	movsg		psr,gr7
+	ori		gr7,#PSR_EF|PSR_EM,gr7
+	movgs		gr7,psr
+	movsg		psr,gr7
+	srli		gr7,#24,gr7
+	bar
+
+	movsg		fner0,gr4
+	movsg		fner1,gr5
+	stdi.p		gr4,@(gr8,#__FPMEDIA_FNER(0))
+	
+	# some CPU's have GR32-GR63
+	setlos		#HSR0_GRHE,gr4
+	andcc		gr6,gr4,gr0,icc0
+	beq		icc0,#1,__save_skip_gr32_gr63
+
+	stdi		gr32,@(gr8,#__INT_GR(32))
+	stdi		gr34,@(gr8,#__INT_GR(34))
+	stdi		gr36,@(gr8,#__INT_GR(36))
+	stdi		gr38,@(gr8,#__INT_GR(38))
+	stdi		gr40,@(gr8,#__INT_GR(40))
+	stdi		gr42,@(gr8,#__INT_GR(42))
+	stdi		gr44,@(gr8,#__INT_GR(44))
+	stdi		gr46,@(gr8,#__INT_GR(46))
+	stdi		gr48,@(gr8,#__INT_GR(48))
+	stdi		gr50,@(gr8,#__INT_GR(50))
+	stdi		gr52,@(gr8,#__INT_GR(52))
+	stdi		gr54,@(gr8,#__INT_GR(54))
+	stdi		gr56,@(gr8,#__INT_GR(56))
+	stdi		gr58,@(gr8,#__INT_GR(58))
+	stdi		gr60,@(gr8,#__INT_GR(60))
+	stdi		gr62,@(gr8,#__INT_GR(62))
+__save_skip_gr32_gr63:
+	
+	# all CPU's have FR0-FR31
+	stdfi		fr0 ,@(gr8,#__FPMEDIA_FR( 0))
+	stdfi		fr2 ,@(gr8,#__FPMEDIA_FR( 2))
+	stdfi		fr4 ,@(gr8,#__FPMEDIA_FR( 4))
+	stdfi		fr6 ,@(gr8,#__FPMEDIA_FR( 6))
+	stdfi		fr8 ,@(gr8,#__FPMEDIA_FR( 8))
+	stdfi		fr10,@(gr8,#__FPMEDIA_FR(10))
+	stdfi		fr12,@(gr8,#__FPMEDIA_FR(12))
+	stdfi		fr14,@(gr8,#__FPMEDIA_FR(14))
+	stdfi		fr16,@(gr8,#__FPMEDIA_FR(16))
+	stdfi		fr18,@(gr8,#__FPMEDIA_FR(18))
+	stdfi		fr20,@(gr8,#__FPMEDIA_FR(20))
+	stdfi		fr22,@(gr8,#__FPMEDIA_FR(22))
+	stdfi		fr24,@(gr8,#__FPMEDIA_FR(24))
+	stdfi		fr26,@(gr8,#__FPMEDIA_FR(26))
+	stdfi		fr28,@(gr8,#__FPMEDIA_FR(28))
+	stdfi.p		fr30,@(gr8,#__FPMEDIA_FR(30))
+
+	# some CPU's have FR32-FR63
+	setlos		#HSR0_FRHE,gr4
+	andcc		gr6,gr4,gr0,icc0
+	beq		icc0,#1,__save_skip_fr32_fr63
+
+	stdfi		fr32,@(gr8,#__FPMEDIA_FR(32))
+	stdfi		fr34,@(gr8,#__FPMEDIA_FR(34))
+	stdfi		fr36,@(gr8,#__FPMEDIA_FR(36))
+	stdfi		fr38,@(gr8,#__FPMEDIA_FR(38))
+	stdfi		fr40,@(gr8,#__FPMEDIA_FR(40))
+	stdfi		fr42,@(gr8,#__FPMEDIA_FR(42))
+	stdfi		fr44,@(gr8,#__FPMEDIA_FR(44))
+	stdfi		fr46,@(gr8,#__FPMEDIA_FR(46))
+	stdfi		fr48,@(gr8,#__FPMEDIA_FR(48))
+	stdfi		fr50,@(gr8,#__FPMEDIA_FR(50))
+	stdfi		fr52,@(gr8,#__FPMEDIA_FR(52))
+	stdfi		fr54,@(gr8,#__FPMEDIA_FR(54))
+	stdfi		fr56,@(gr8,#__FPMEDIA_FR(56))
+	stdfi		fr58,@(gr8,#__FPMEDIA_FR(58))
+	stdfi		fr60,@(gr8,#__FPMEDIA_FR(60))
+	stdfi		fr62,@(gr8,#__FPMEDIA_FR(62))
+__save_skip_fr32_fr63:
+
+	mrdacc		acc0 ,fr4
+	mrdacc		acc1 ,fr5
+
+	stdfi.p		fr4 ,@(gr8,#__FPMEDIA_ACC(0))
+
+	mrdacc		acc2 ,fr6
+	mrdacc		acc3 ,fr7
+
+	stdfi.p		fr6 ,@(gr8,#__FPMEDIA_ACC(2))
+
+	mrdaccg		accg0,fr4
+	stbfi.p		fr4 ,@(gr8,#__FPMEDIA_ACCG(0))
+
+	mrdaccg		accg1,fr5
+	stbfi.p		fr5 ,@(gr8,#__FPMEDIA_ACCG(1))
+
+	mrdaccg		accg2,fr6
+	stbfi.p		fr6 ,@(gr8,#__FPMEDIA_ACCG(2))
+
+	mrdaccg		accg3,fr7
+	stbfi		fr7 ,@(gr8,#__FPMEDIA_ACCG(3))
+
+	movsg		msr0 ,gr4
+	movsg		msr1 ,gr5
+
+	stdi		gr4 ,@(gr8,#__FPMEDIA_MSR(0))
+
+	# some CPUs have extra ACCx and ACCGx regs and maybe FSRx regs
+	subicc.p	gr7,#0x50,gr0,icc0
+	subicc		gr7,#0x31,gr0,icc1
+	beq		icc0,#0,__save_acc_fr451
+	beq		icc1,#0,__save_acc_fr555
+__save_acc_cont:
+
+	lddfi		@(gr8,#__FPMEDIA_FR(4)),fr4
+	lddfi.p		@(gr8,#__FPMEDIA_FR(6)),fr6
+	bralr
+
+	# the FR451 also has ACC8-11/ACCG8-11 regs (but not 4-7...)
+__save_acc_fr451:
+	mrdacc		acc8 ,fr4
+	mrdacc		acc9 ,fr5
+
+	stdfi.p		fr4 ,@(gr8,#__FPMEDIA_ACC(4))
+
+	mrdacc		acc10,fr6
+	mrdacc		acc11,fr7
+
+	stdfi.p		fr6 ,@(gr8,#__FPMEDIA_ACC(6))
+
+	mrdaccg		accg8,fr4
+	stbfi.p		fr4 ,@(gr8,#__FPMEDIA_ACCG(4))
+
+	mrdaccg		accg9,fr5
+	stbfi.p		fr5 ,@(gr8,#__FPMEDIA_ACCG(5))
+
+	mrdaccg		accg10,fr6
+	stbfi.p		fr6 ,@(gr8,#__FPMEDIA_ACCG(6))
+
+	mrdaccg		accg11,fr7
+	stbfi		fr7 ,@(gr8,#__FPMEDIA_ACCG(7))
+	bra		__save_acc_cont
+
+	# the FR555 also has ACC4-7/ACCG4-7 regs and an FSR0 reg
+__save_acc_fr555:
+	mnop.p
+	mrdacc		acc4 ,fr4
+	mnop.p
+	mrdacc		acc5 ,fr5
+
+	stdfi		fr4 ,@(gr8,#__FPMEDIA_ACC(4))
+
+	mnop.p
+	mrdacc		acc6 ,fr6
+	mnop.p
+	mrdacc		acc7 ,fr7
+
+	stdfi		fr6 ,@(gr8,#__FPMEDIA_ACC(6))
+
+	mnop.p
+	mrdaccg		accg4,fr4
+	stbfi		fr4 ,@(gr8,#__FPMEDIA_ACCG(4))
+
+	mnop.p
+	mrdaccg		accg5,fr5
+	stbfi		fr5 ,@(gr8,#__FPMEDIA_ACCG(5))
+
+	mnop.p
+	mrdaccg		accg6,fr6
+	stbfi		fr6 ,@(gr8,#__FPMEDIA_ACCG(6))
+
+	mnop.p
+	mrdaccg		accg7,fr7
+	stbfi		fr7 ,@(gr8,#__FPMEDIA_ACCG(7))
+
+	movsg		fsr0 ,gr4
+	sti		gr4 ,@(gr8,#__FPMEDIA_FSR(0))
+	bra		__save_acc_cont

^ permalink raw reply	[flat|nested] 87+ messages in thread

* [PATCH 4/20] FRV: Fujitsu FR-V CPU arch implementation part 2
  2004-11-08 14:34 [PATCH 1/20] FRV: Fujitsu FR-V CPU arch maintainer record dhowells
  2004-11-08 14:34 ` [PATCH 2/20] FRV: Fujitsu FR-V arch documentation dhowells
  2004-11-08 14:34 ` [PATCH 6/20] FRV: Fujitsu FR-V CPU arch implementation part 4 dhowells
@ 2004-11-08 14:34 ` dhowells
  2004-11-08 14:34 ` [PATCH 5/20] FRV: Fujitsu FR-V CPU arch implementation part 3 dhowells
                   ` (13 subsequent siblings)
  16 siblings, 0 replies; 87+ messages in thread
From: dhowells @ 2004-11-08 14:34 UTC (permalink / raw)
  To: torvalds, akpm, davidm; +Cc: linux-kernel, uclinux-dev

The attached patches provides part 2 of an architecture implementation
for the Fujitsu FR-V CPU series, configurably as Linux or uClinux.

Signed-Off-By: dhowells@redhat.com
---
diffstat frv-arch_2-2610rc1mm3.diff
 break.S       |  713 +++++++++++++++++++++++++++++
 cmode.S       |  190 +++++++
 debug-stub.c  |  259 ++++++++++
 dma.c         |  464 ++++++++++++++++++
 entry-table.S |  277 +++++++++++
 entry.S       | 1420 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 6 files changed, 3323 insertions(+)

diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/kernel/break.S linux-2.6.10-rc1-mm3-frv/arch/frv/kernel/break.S
--- /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/kernel/break.S	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/arch/frv/kernel/break.S	2004-11-05 14:44:36.000000000 +0000
@@ -0,0 +1,713 @@
+/* break.S: Break interrupt handling (kept separate from entry.S)
+ *
+ * Copyright (C) 2003 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * 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.
+ */
+
+#include <linux/sys.h>
+#include <linux/config.h>
+#include <linux/linkage.h>
+#include <asm/setup.h>
+#include <asm/segment.h>
+#include <asm/ptrace.h>
+#include <asm/spr-regs.h>
+
+#include <asm/errno.h>
+
+#
+# the break handler has its own stack
+#
+	.section	.bss.stack
+	.globl		__break_user_context
+	.balign		8192
+__break_stack:
+	.space		(8192 - (USER_CONTEXT_SIZE + REG__DEBUG_XTRA)) & ~7
+__break_stack_tos:
+	.space		REG__DEBUG_XTRA
+__break_user_context:
+	.space		USER_CONTEXT_SIZE
+
+#
+# miscellaneous variables
+#
+	.section	.bss
+#ifdef CONFIG_MMU
+	.globl		__break_tlb_miss_real_return_info
+__break_tlb_miss_real_return_info:
+	.balign		8
+	.space		2*4			/* saved PCSR, PSR for TLB-miss handler fixup */
+#endif
+
+__break_trace_through_exceptions:
+	.space		4
+
+#define CS2_ECS1	0xe1200000
+#define CS2_USERLED	0x4
+
+.macro LEDS val,reg
+#	sethi.p		%hi(CS2_ECS1+CS2_USERLED),gr30
+#	setlo		%lo(CS2_ECS1+CS2_USERLED),gr30
+#	setlos		#~\val,\reg
+#	st		\reg,@(gr30,gr0)
+#	setlos		#0x5555,\reg
+#	sethi.p		%hi(0xffc00100),gr30
+#	setlo		%lo(0xffc00100),gr30
+#	sth		\reg,@(gr30,gr0)
+#	membar
+.endm
+
+###############################################################################
+#
+# entry point for Break Exceptions/Interrupts
+#
+###############################################################################
+	.text
+	.balign		4
+	.globl		__entry_break
+__entry_break:
+#ifdef CONFIG_MMU
+	movgs		gr31,scr3
+#endif
+	LEDS		0x1001,gr31
+
+	sethi.p		%hi(__break_user_context),gr31
+	setlo		%lo(__break_user_context),gr31
+
+	stdi		gr2,@(gr31,#REG_GR(2))
+	movsg		ccr,gr3
+	sti		gr3,@(gr31,#REG_CCR)
+
+	# catch the return from a TLB-miss handler that had single-step disabled
+	# traps will be enabled, so we have to do this now
+#ifdef CONFIG_MMU
+	movsg		bpcsr,gr3
+	sethi.p		%hi(__break_tlb_miss_return_breaks_here),gr2
+	setlo		%lo(__break_tlb_miss_return_breaks_here),gr2
+	subcc		gr2,gr3,gr0,icc0
+	beq		icc0,#2,__break_return_singlestep_tlbmiss
+#endif
+
+	# determine whether we have stepped through into an exception
+	# - we need to take special action to suspend h/w single stepping if we've done
+	#   that, so that the gdbstub doesn't get bogged down endlessly stepping through
+	#   external interrupt handling
+	movsg		bpsr,gr3
+	andicc		gr3,#BPSR_BET,gr0,icc0
+	bne		icc0,#2,__break_maybe_userspace	/* jump if PSR.ET was 1 */
+
+	LEDS		0x1003,gr2
+
+	movsg		brr,gr3
+	andicc		gr3,#BRR_ST,gr0,icc0
+	andicc.p	gr3,#BRR_SB,gr0,icc1
+	bne		icc0,#2,__break_step		/* jump if single-step caused break */
+	beq		icc1,#2,__break_continue	/* jump if BREAK didn't cause break */
+
+	LEDS		0x1007,gr2
+
+	# handle special breaks
+	movsg		bpcsr,gr3
+
+	sethi.p		%hi(__entry_return_singlestep_breaks_here),gr2
+	setlo		%lo(__entry_return_singlestep_breaks_here),gr2
+	subcc		gr2,gr3,gr0,icc0
+	beq		icc0,#2,__break_return_singlestep
+
+	bra		__break_continue
+
+
+###############################################################################
+#
+# handle BREAK instruction in kernel-mode exception epilogue
+#
+###############################################################################
+__break_return_singlestep:
+	LEDS		0x100f,gr2
+
+	# special break insn requests single-stepping to be turned back on
+	#		HERE		RETT
+	# PSR.ET	0		0
+	# PSR.PS	old PSR.S	?
+	# PSR.S		1		1
+	# BPSR.ET	0		1 (can't have caused orig excep otherwise)
+	# BPSR.BS	1		old PSR.S
+	movsg		dcr,gr2
+	sethi.p		%hi(DCR_SE),gr3
+	setlo		%lo(DCR_SE),gr3
+	or		gr2,gr3,gr2
+	movgs		gr2,dcr
+
+	movsg		psr,gr2
+	andi		gr2,#PSR_PS,gr2
+	slli		gr2,#11,gr2			/* PSR.PS -> BPSR.BS */
+	ori		gr2,#BPSR_BET,gr2		/* 1 -> BPSR.BET */
+	movgs		gr2,bpsr
+
+	# return to the invoker of the original kernel exception
+	movsg		pcsr,gr2
+	movgs		gr2,bpcsr
+
+	LEDS		0x101f,gr2
+
+	ldi		@(gr31,#REG_CCR),gr3
+	movgs		gr3,ccr
+	lddi.p		@(gr31,#REG_GR(2)),gr2
+	xor		gr31,gr31,gr31
+	movgs		gr0,brr
+#ifdef CONFIG_MMU
+	movsg		scr3,gr31
+#endif
+	rett		#1
+
+###############################################################################
+#
+# handle BREAK instruction in TLB-miss handler return path
+#
+###############################################################################
+#ifdef CONFIG_MMU
+__break_return_singlestep_tlbmiss:
+	LEDS		0x1100,gr2
+	
+	sethi.p		%hi(__break_tlb_miss_real_return_info),gr3
+	setlo		%lo(__break_tlb_miss_real_return_info),gr3
+	lddi		@(gr3,#0),gr2
+	movgs		gr2,pcsr
+	movgs		gr3,psr
+
+	bra		__break_return_singlestep
+#endif
+
+
+###############################################################################
+#
+# handle single stepping into an exception prologue from kernel mode
+# - we try and catch it whilst it is still in the main vector table
+# - if we catch it there, we have to jump to the fixup handler
+#   - there is a fixup table that has a pointer for every 16b slot in the trap
+#     table
+#
+###############################################################################
+__break_step:
+	LEDS		0x2003,gr2
+
+	# external interrupts seem to escape from the trap table before single
+	# step catches up with them
+	movsg		bpcsr,gr2
+	sethi.p		%hi(__entry_kernel_external_interrupt),gr3
+	setlo		%lo(__entry_kernel_external_interrupt),gr3
+	subcc		gr2,gr3,gr0,icc0
+	beq		icc0,#2,__break_step_kernel_external_interrupt
+
+	LEDS		0x2007,gr2
+
+	# the two main vector tables are adjacent on one 8Kb slab
+	movsg		bpcsr,gr2
+	setlos		#0xffffe000,gr3
+	and		gr2,gr3,gr2
+	sethi.p		%hi(__trap_tables),gr3
+	setlo		%lo(__trap_tables),gr3
+	subcc		gr2,gr3,gr0,icc0
+	bne		icc0,#2,__break_continue
+
+	LEDS		0x200f,gr2
+
+	# skip workaround if so requested by GDB
+	sethi.p		%hi(__break_trace_through_exceptions),gr3
+	setlo		%lo(__break_trace_through_exceptions),gr3
+	ld		@(gr3,gr0),gr3
+	subcc		gr3,gr0,gr0,icc0
+	bne		icc0,#0,__break_continue
+
+	LEDS		0x201f,gr2
+
+	# access the fixup table - there's a 1:1 mapping between the slots in the trap tables and
+	# the slots in the trap fixup tables allowing us to simply divide the offset into the
+	# former by 4 to access the latter
+	sethi.p		%hi(__trap_tables),gr3
+	setlo		%lo(__trap_tables),gr3
+	movsg		bpcsr,gr2
+	sub		gr2,gr3,gr2
+	srli.p		gr2,#2,gr2
+
+	sethi		%hi(__trap_fixup_tables),gr3
+	setlo.p		%lo(__trap_fixup_tables),gr3
+	andi		gr2,#~3,gr2
+	ld		@(gr2,gr3),gr2
+	jmpil		@(gr2,#0)
+
+# step through an internal exception from kernel mode
+	.globl		__break_step_kernel_softprog_interrupt
+__break_step_kernel_softprog_interrupt:
+	sethi.p		%hi(__entry_kernel_softprog_interrupt_reentry),gr3
+	setlo		%lo(__entry_kernel_softprog_interrupt_reentry),gr3
+	bra		__break_return_as_kernel_prologue
+
+# step through an external interrupt from kernel mode
+	.globl		__break_step_kernel_external_interrupt
+__break_step_kernel_external_interrupt:
+	sethi.p		%hi(__entry_kernel_external_interrupt_reentry),gr3
+	setlo		%lo(__entry_kernel_external_interrupt_reentry),gr3
+
+__break_return_as_kernel_prologue:
+	LEDS		0x203f,gr2
+
+	movgs		gr3,bpcsr
+
+	# do the bit we had to skip
+#ifdef CONFIG_MMU
+	movsg		ear0,gr2		/* EAR0 can get clobbered by gdb-stub (ICI/ICEI) */
+	movgs		gr2,scr2
+#endif
+
+	or.p		sp,gr0,gr2		/* set up the stack pointer */
+	subi		sp,#REG__END,sp
+	sti.p		gr2,@(sp,#REG_SP)
+
+	setlos		#REG__STATUS_STEP,gr2
+	sti		gr2,@(sp,#REG__STATUS)		/* record single step status */
+
+	# cancel single-stepping mode
+	movsg		dcr,gr2
+	sethi.p		%hi(~DCR_SE),gr3
+	setlo		%lo(~DCR_SE),gr3
+	and		gr2,gr3,gr2
+	movgs		gr2,dcr
+
+	LEDS		0x207f,gr2
+
+	ldi		@(gr31,#REG_CCR),gr3
+	movgs		gr3,ccr
+	lddi.p		@(gr31,#REG_GR(2)),gr2
+	xor		gr31,gr31,gr31
+	movgs		gr0,brr
+#ifdef CONFIG_MMU
+	movsg		scr3,gr31
+#endif
+	rett		#1
+
+# step through an internal exception from uspace mode
+	.globl		__break_step_uspace_softprog_interrupt
+__break_step_uspace_softprog_interrupt:
+	sethi.p		%hi(__entry_uspace_softprog_interrupt_reentry),gr3
+	setlo		%lo(__entry_uspace_softprog_interrupt_reentry),gr3
+	bra		__break_return_as_uspace_prologue
+
+# step through an external interrupt from kernel mode
+	.globl		__break_step_uspace_external_interrupt
+__break_step_uspace_external_interrupt:
+	sethi.p		%hi(__entry_uspace_external_interrupt_reentry),gr3
+	setlo		%lo(__entry_uspace_external_interrupt_reentry),gr3
+
+__break_return_as_uspace_prologue:
+	LEDS		0x20ff,gr2
+
+	movgs		gr3,bpcsr
+
+	# do the bit we had to skip
+	sethi.p		%hi(__kernel_frame0_ptr),gr28
+	setlo		%lo(__kernel_frame0_ptr),gr28
+	ldi.p		@(gr28,#0),gr28
+
+	setlos		#REG__STATUS_STEP,gr2
+	sti		gr2,@(gr28,#REG__STATUS)	/* record single step status */
+
+	# cancel single-stepping mode
+	movsg		dcr,gr2
+	sethi.p		%hi(~DCR_SE),gr3
+	setlo		%lo(~DCR_SE),gr3
+	and		gr2,gr3,gr2
+	movgs		gr2,dcr
+
+	LEDS		0x20fe,gr2
+
+	ldi		@(gr31,#REG_CCR),gr3
+	movgs		gr3,ccr
+	lddi.p		@(gr31,#REG_GR(2)),gr2
+	xor		gr31,gr31,gr31
+	movgs		gr0,brr
+#ifdef CONFIG_MMU
+	movsg		scr3,gr31
+#endif
+	rett		#1
+
+#ifdef CONFIG_MMU
+# step through an ITLB-miss handler from user mode
+	.globl		__break_user_insn_tlb_miss
+__break_user_insn_tlb_miss:
+	# we'll want to try the trap stub again
+	sethi.p		%hi(__trap_user_insn_tlb_miss),gr2
+	setlo		%lo(__trap_user_insn_tlb_miss),gr2
+	movgs		gr2,bpcsr
+
+__break_tlb_miss_common:
+	LEDS		0x2101,gr2
+	
+	# cancel single-stepping mode
+	movsg		dcr,gr2
+	sethi.p		%hi(~DCR_SE),gr3
+	setlo		%lo(~DCR_SE),gr3
+	and		gr2,gr3,gr2
+	movgs		gr2,dcr
+
+	# we'll swap the real return address for one with a BREAK insn so that we can re-enable
+	# single stepping on return
+	movsg		pcsr,gr2
+	sethi.p		%hi(__break_tlb_miss_real_return_info),gr3
+	setlo		%lo(__break_tlb_miss_real_return_info),gr3
+	sti		gr2,@(gr3,#0)
+
+	sethi.p		%hi(__break_tlb_miss_return_break),gr2
+	setlo		%lo(__break_tlb_miss_return_break),gr2
+	movgs		gr2,pcsr
+
+	# we also have to fudge PSR because the return BREAK is in kernel space and we want
+	# to get a BREAK fault not an access violation should the return be to userspace
+	movsg		psr,gr2
+	sti.p		gr2,@(gr3,#4)
+	ori		gr2,#PSR_PS,gr2
+	movgs		gr2,psr
+
+	LEDS		0x2102,gr2
+	
+	ldi		@(gr31,#REG_CCR),gr3
+	movgs		gr3,ccr
+	lddi		@(gr31,#REG_GR(2)),gr2
+	movsg		scr3,gr31
+	movgs		gr0,brr
+	rett		#1
+
+# step through a DTLB-miss handler from user mode
+	.globl		__break_user_data_tlb_miss
+__break_user_data_tlb_miss:
+	# we'll want to try the trap stub again
+	sethi.p		%hi(__trap_user_data_tlb_miss),gr2
+	setlo		%lo(__trap_user_data_tlb_miss),gr2
+	movgs		gr2,bpcsr
+	bra		__break_tlb_miss_common
+
+# step through an ITLB-miss handler from kernel mode
+	.globl		__break_kernel_insn_tlb_miss
+__break_kernel_insn_tlb_miss:
+	# we'll want to try the trap stub again
+	sethi.p		%hi(__trap_kernel_insn_tlb_miss),gr2
+	setlo		%lo(__trap_kernel_insn_tlb_miss),gr2
+	movgs		gr2,bpcsr
+	bra		__break_tlb_miss_common
+
+# step through a DTLB-miss handler from kernel mode
+	.globl		__break_kernel_data_tlb_miss
+__break_kernel_data_tlb_miss:
+	# we'll want to try the trap stub again
+	sethi.p		%hi(__trap_kernel_data_tlb_miss),gr2
+	setlo		%lo(__trap_kernel_data_tlb_miss),gr2
+	movgs		gr2,bpcsr
+	bra		__break_tlb_miss_common
+#endif
+
+###############################################################################
+#
+# handle debug events originating with userspace
+#
+###############################################################################
+__break_maybe_userspace:
+	LEDS		0x3003,gr2
+
+	setlos		#BPSR_BS,gr2
+	andcc		gr3,gr2,gr0,icc0
+	bne		icc0,#0,__break_continue	/* skip if PSR.S was 1 */
+
+	movsg		brr,gr2
+	andicc		gr2,#BRR_ST|BRR_SB,gr0,icc0
+	beq		icc0,#0,__break_continue	/* jump if not BREAK or single-step */
+
+	LEDS		0x3007,gr2
+
+	# do the first part of the exception prologue here
+	sethi.p		%hi(__kernel_frame0_ptr),gr28
+	setlo		%lo(__kernel_frame0_ptr),gr28
+	ldi		@(gr28,#0),gr28
+	andi		gr28,#~7,gr28
+
+	# set up the kernel stack pointer
+	sti		sp  ,@(gr28,#REG_SP)
+	ori		gr28,0,sp
+	sti		gr0 ,@(gr28,#REG_GR(28))
+
+	stdi		gr20,@(gr28,#REG_GR(20))
+	stdi		gr22,@(gr28,#REG_GR(22))
+
+	movsg		tbr,gr20
+	movsg		bpcsr,gr21
+	movsg		psr,gr22
+
+	# determine the exception type and cancel single-stepping mode
+	or		gr0,gr0,gr23
+
+	movsg		dcr,gr2
+	sethi.p		%hi(DCR_SE),gr3
+	setlo		%lo(DCR_SE),gr3
+	andcc		gr2,gr3,gr0,icc0
+	beq		icc0,#0,__break_no_user_sstep	/* must have been a BREAK insn */
+
+	not		gr3,gr3
+	and		gr2,gr3,gr2
+	movgs		gr2,dcr
+	ori		gr23,#REG__STATUS_STEP,gr23
+
+__break_no_user_sstep:
+	LEDS		0x300f,gr2
+
+	movsg		brr,gr2
+	andi		gr2,#BRR_ST|BRR_SB,gr2
+	slli		gr2,#1,gr2
+	or		gr23,gr2,gr23
+	sti.p		gr23,@(gr28,#REG__STATUS)	/* record single step status */
+
+	# adjust the value acquired from TBR - this indicates the exception
+	setlos		#~TBR_TT,gr2
+	and.p		gr20,gr2,gr20
+	setlos		#TBR_TT_BREAK,gr2
+	or.p		gr20,gr2,gr20
+
+	# fudge PSR.PS and BPSR.BS to return to kernel mode through the trap
+	# table as trap 126
+	andi		gr22,#~PSR_PS,gr22		/* PSR.PS should be 0 */
+	movgs		gr22,psr
+
+	setlos		#BPSR_BS,gr2			/* BPSR.BS should be 1 and BPSR.BET 0 */
+	movgs		gr2,bpsr
+
+	# return through remainder of the exception prologue
+	sethi.p		%hi(__entry_common),gr3
+	setlo		%lo(__entry_common),gr3
+	movgs		gr3,bpcsr
+
+	LEDS		0x301f,gr2
+
+	ldi		@(gr31,#REG_CCR),gr3
+	movgs		gr3,ccr
+	lddi.p		@(gr31,#REG_GR(2)),gr2
+	xor		gr31,gr31,gr31
+	movgs		gr0,brr
+#ifdef CONFIG_MMU
+	movsg		scr3,gr31
+#endif
+	rett		#1
+
+###############################################################################
+#
+# resume normal debug-mode entry
+#
+###############################################################################
+__break_continue:
+	LEDS		0x4003,gr2
+
+	# set up the kernel stack pointer
+	sti		sp,@(gr31,#REG_SP)
+
+	sethi.p		%hi(__break_stack_tos),sp
+	setlo		%lo(__break_stack_tos),sp
+
+	# finish building the exception frame
+	stdi		gr4 ,@(gr31,#REG_GR(4))
+	stdi		gr6 ,@(gr31,#REG_GR(6))
+	stdi		gr8 ,@(gr31,#REG_GR(8))
+	stdi		gr10,@(gr31,#REG_GR(10))
+	stdi		gr12,@(gr31,#REG_GR(12))
+	stdi		gr14,@(gr31,#REG_GR(14))
+	stdi		gr16,@(gr31,#REG_GR(16))
+	stdi		gr18,@(gr31,#REG_GR(18))
+	stdi		gr20,@(gr31,#REG_GR(20))
+	stdi		gr22,@(gr31,#REG_GR(22))
+	stdi		gr24,@(gr31,#REG_GR(24))
+	stdi		gr26,@(gr31,#REG_GR(26))
+	sti		gr0 ,@(gr31,#REG_GR(28))	/* NULL frame pointer */
+	sti		gr29,@(gr31,#REG_GR(29))
+	sti		gr30,@(gr31,#REG_GR(30))
+	sti		gr8 ,@(gr31,#REG_ORIG_GR8)
+
+#ifdef CONFIG_MMU
+	movsg		scr3,gr19
+	sti		gr19,@(gr31,#REG_GR(31))
+#endif
+
+	movsg		bpsr ,gr19
+	movsg		tbr  ,gr20
+	movsg		bpcsr,gr21
+	movsg		psr  ,gr22
+	movsg		isr  ,gr23
+	movsg		cccr ,gr25
+	movsg		lr   ,gr26
+	movsg		lcr  ,gr27
+
+	andi.p		gr22,#~(PSR_S|PSR_ET),gr5	/* rebuild PSR */
+	andi		gr19,#PSR_ET,gr4
+	or.p		gr4,gr5,gr5
+	srli		gr19,#10,gr4
+	andi		gr4,#PSR_S,gr4
+	or.p		gr4,gr5,gr5
+
+	setlos		#-1,gr6
+	sti		gr20,@(gr31,#REG_TBR)
+	sti		gr21,@(gr31,#REG_PC)
+	sti		gr5 ,@(gr31,#REG_PSR)
+	sti		gr23,@(gr31,#REG_ISR)
+	sti		gr25,@(gr31,#REG_CCCR)
+	stdi		gr26,@(gr31,#REG_LR)
+	sti		gr6 ,@(gr31,#REG_SYSCALLNO)
+
+	# store CPU-specific regs
+	movsg		iacc0h,gr4
+	movsg		iacc0l,gr5
+	stdi		gr4,@(gr31,#REG_IACC0)
+
+	movsg		gner0,gr4
+	movsg		gner1,gr5
+	stdi		gr4,@(gr31,#REG_GNER0)
+
+	# build the debug register frame
+	movsg		brr,gr4
+	movgs		gr0,brr
+	movsg		nmar,gr5
+	movsg		dcr,gr6
+
+	stdi		gr4 ,@(gr31,#REG_BRR)
+	sti		gr19,@(gr31,#REG_BPSR)
+	sti.p		gr6 ,@(gr31,#REG_DCR)
+
+	# trap exceptions during break handling and disable h/w breakpoints/watchpoints
+	sethi		%hi(DCR_EBE),gr5
+	setlo.p		%lo(DCR_EBE),gr5
+	sethi		%hi(__entry_breaktrap_table),gr4
+	setlo		%lo(__entry_breaktrap_table),gr4
+	movgs		gr5,dcr
+	movgs		gr4,tbr
+
+	# set up kernel global registers
+	sethi.p		%hi(__kernel_current_task),gr5
+	setlo		%lo(__kernel_current_task),gr5
+	ld		@(gr5,gr0),gr29
+	ldi.p		@(gr29,#4),gr15		; __current_thread_info = current->thread_info
+
+	sethi		%hi(_gp),gr16
+	setlo.p		%lo(_gp),gr16
+
+	# make sure we (the kernel) get div-zero and misalignment exceptions
+	setlos		#ISR_EDE|ISR_DTT_DIVBYZERO|ISR_EMAM_EXCEPTION,gr5
+	movgs		gr5,isr
+
+	# enter the GDB stub
+	LEDS		0x4007,gr2
+
+	or.p		gr0,gr0,fp
+	call		debug_stub
+
+	LEDS		0x403f,gr2
+
+	# return from break
+	lddi		@(gr31,#REG_IACC0),gr4
+	movgs		gr4,iacc0h
+	movgs		gr5,iacc0l
+
+	lddi		@(gr31,#REG_GNER0),gr4
+	movgs		gr4,gner0
+	movgs		gr5,gner1
+
+	lddi		@(gr31,#REG_LR)  ,gr26
+	lddi		@(gr31,#REG_CCR) ,gr24
+	lddi		@(gr31,#REG_PSR) ,gr22
+	ldi		@(gr31,#REG_PC)  ,gr21
+	ldi		@(gr31,#REG_TBR) ,gr20
+	ldi.p		@(gr31,#REG_DCR) ,gr6
+
+	andi		gr22,#PSR_S,gr19		/* rebuild BPSR */
+	andi.p		gr22,#PSR_ET,gr5
+	slli		gr19,#10,gr19
+	or		gr5,gr19,gr19
+
+	movgs		gr6 ,dcr
+	movgs		gr19,bpsr
+	movgs		gr20,tbr
+	movgs		gr21,bpcsr
+	movgs		gr23,isr
+	movgs		gr24,ccr
+	movgs		gr25,cccr
+	movgs		gr26,lr
+	movgs		gr27,lcr
+
+	LEDS		0x407f,gr2
+
+#ifdef CONFIG_MMU
+	ldi		@(gr31,#REG_GR(31)),gr2
+	movgs		gr2,scr3
+#endif
+
+	ldi		@(gr31,#REG_GR(30)),gr30
+	ldi		@(gr31,#REG_GR(29)),gr29
+	lddi		@(gr31,#REG_GR(26)),gr26
+	lddi		@(gr31,#REG_GR(24)),gr24
+	lddi		@(gr31,#REG_GR(22)),gr22
+	lddi		@(gr31,#REG_GR(20)),gr20
+	lddi		@(gr31,#REG_GR(18)),gr18
+	lddi		@(gr31,#REG_GR(16)),gr16
+	lddi		@(gr31,#REG_GR(14)),gr14
+	lddi		@(gr31,#REG_GR(12)),gr12
+	lddi		@(gr31,#REG_GR(10)),gr10
+	lddi		@(gr31,#REG_GR(8)) ,gr8
+	lddi		@(gr31,#REG_GR(6)) ,gr6
+	lddi		@(gr31,#REG_GR(4)) ,gr4
+	lddi		@(gr31,#REG_GR(2)) ,gr2
+	ldi.p		@(gr31,#REG_SP)    ,sp
+
+	xor		gr31,gr31,gr31
+	movgs		gr0,brr
+#ifdef CONFIG_MMU
+	movsg		scr3,gr31
+#endif
+	rett		#1
+
+###################################################################################################
+#
+# GDB stub "system calls"
+#
+###################################################################################################
+
+#ifdef CONFIG_GDBSTUB
+	# void gdbstub_console_write(struct console *con, const char *p, unsigned n)
+	.globl		gdbstub_console_write
+gdbstub_console_write:
+	break
+	bralr
+#endif
+
+	# GDB stub BUG() trap
+	# GR8 is the proposed signal number
+	.globl		__debug_bug_trap
+__debug_bug_trap:
+	break
+	bralr
+
+	# transfer kernel exeception to GDB for handling
+	.globl		__break_hijack_kernel_event
+__break_hijack_kernel_event:
+	break
+	.globl		__break_hijack_kernel_event_breaks_here
+__break_hijack_kernel_event_breaks_here:
+	nop
+
+#ifdef CONFIG_MMU
+	# handle a return from TLB-miss that requires single-step reactivation
+	.globl		__break_tlb_miss_return_break
+__break_tlb_miss_return_break:
+	break
+__break_tlb_miss_return_breaks_here:
+	nop
+#endif
+
+	# guard the first .text label in the next file from confusion
+	nop
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/kernel/cmode.S linux-2.6.10-rc1-mm3-frv/arch/frv/kernel/cmode.S
--- /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/kernel/cmode.S	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/arch/frv/kernel/cmode.S	2004-11-05 14:13:03.070566125 +0000
@@ -0,0 +1,190 @@
+/* cmode.S: clock mode management
+ *
+ * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
+ * Written by David Woodhouse (dwmw2@redhat.com)
+ *
+ * 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.
+ *
+ */
+
+#include <linux/sys.h>
+#include <linux/config.h>
+#include <linux/linkage.h>
+#include <asm/setup.h>
+#include <asm/segment.h>
+#include <asm/ptrace.h>
+#include <asm/errno.h>
+#include <asm/cache.h>
+#include <asm/spr-regs.h>
+	
+#define __addr_MASK	0xfeff9820	/* interrupt controller mask */
+
+#define __addr_SDRAMC	0xfe000400	/* SDRAM controller regs */
+#define SDRAMC_DSTS	0x28		/* SDRAM status */
+#define SDRAMC_DSTS_SSI	0x00000001	/* indicates that the SDRAM is in self-refresh mode */
+#define SDRAMC_DRCN	0x30		/* SDRAM refresh control */
+#define SDRAMC_DRCN_SR	0x00000001	/* transition SDRAM into self-refresh mode */
+#define __addr_CLKC	0xfeff9a00
+#define CLKC_SWCMODE	0x00000008
+#define __addr_LEDS	0xe1200004	
+
+.macro li v r
+	sethi.p		%hi(\v),\r
+	setlo		%lo(\v),\r
+.endm
+
+	.text
+	.balign		4
+
+	
+###############################################################################
+#
+# Change CMODE
+# - void frv_change_cmode(int cmode)
+#
+###############################################################################
+	.globl		frv_change_cmode
+        .type		frv_change_cmode,@function
+
+.macro	LEDS v
+#ifdef DEBUG_CMODE
+	setlos	#~\v,gr10
+	sti	gr10,@(gr11,#0)
+	membar
+#endif
+.endm
+		
+frv_change_cmode:	
+	movsg		lr,gr9
+#ifdef DEBUG_CMODE
+	li		__addr_LEDS,gr11
+#endif
+	dcef		@(gr0,gr0),#1
+
+	# Shift argument left by 24 bits to fit in SWCMODE register later.
+	slli		gr8,#24,gr8
+
+	# (1) Set '0' in the PSR.ET bit, and prohibit interrupts. 
+	movsg		psr,gr14
+	andi		gr14,#~PSR_ET,gr3
+	movgs		gr3,psr
+
+#if 0 // Fujitsu recommend to skip this and will update docs.
+	# (2) Set '0' to all bits of the MASK register of the interrupt 
+	#     controller, and mask interrupts. 
+	li		__addr_MASK,gr12
+	ldi		@(gr12,#0),gr13
+	li		0xffff0000,gr4
+	sti		gr4,@(gr12,#0)
+#endif
+	
+	# (3) Stop the transfer function of DMAC. Stop all the bus masters 
+	#     to access SDRAM and the internal resources.
+
+	# (already done by caller)
+	
+	# (4) Preload a series of following instructions to the instruction
+	#     cache. 
+	li		#__cmode_icache_lock_start,gr3
+	li		#__cmode_icache_lock_end,gr4
+
+1:	icpl		gr3,gr0,#1
+	addi		gr3,#L1_CACHE_BYTES,gr3
+	cmp		gr4,gr3,icc0
+	bhi		icc0,#0,1b
+
+	# Set up addresses in regs for later steps.
+	setlos		SDRAMC_DRCN_SR,gr3
+	li		__addr_SDRAMC,gr4
+	li		__addr_CLKC,gr5
+	ldi		@(gr5,#0),gr6
+	li		#0x80000000,gr7
+	or		gr6,gr7,gr6
+	
+	bra		__cmode_icache_lock_start
+
+	.balign	L1_CACHE_BYTES
+__cmode_icache_lock_start:		
+
+	# (5) Flush the content of all caches by the DCEF instruction. 
+	dcef		@(gr0,gr0),#1
+
+	# (6) Execute loading the dummy for SDRAM.
+	ldi		@(gr9,#0),gr0
+
+	# (7) Set '1' to the DRCN.SR bit, and change SDRAM to the 
+	#     self-refresh mode. Execute the dummy load to all memory
+	#     devices set to cacheable on the external bus side in parallel
+	#     with this.
+	sti		gr3,@(gr4,#SDRAMC_DRCN)
+
+	# (8) Execute memory barrier instruction (MEMBAR).
+	membar
+	
+	# (9) Read the DSTS register repeatedly until '1' stands in the 
+	#     DSTS.SSI field.
+1:	ldi		@(gr4,#SDRAMC_DSTS),gr3
+	andicc		gr3,#SDRAMC_DSTS_SSI,gr3,icc0
+	beq		icc0,#0,1b
+
+	# (10) Execute memory barrier instruction (MEMBAR).
+	membar
+	
+#if 1
+	# (11) Set the value of CMODE that you want to change to 
+	#      SWCMODE.SWCM[3:0].
+	sti		gr8,@(gr5,#CLKC_SWCMODE)
+
+	# (12) Set '1' to the CLKC.SWEN bit. In that case, do not change 
+	#      fields other than SWEN of the CLKC register.
+	sti		gr6,@(gr5,#0)
+#endif
+	# (13) Execute the instruction just after the memory barrier 
+	# instruction that executes the self-loop 256 times. (Meanwhile,
+	# the CMODE switch is done.) 
+	membar
+	setlos		#256,gr7
+2:	subicc		gr7,#1,gr7,icc0
+	bne		icc0,#2,2b
+
+	LEDS	0x36	
+
+	# (14) Release the self-refresh of SDRAM.
+	sti		gr0,@(gr4,#SDRAMC_DRCN)
+
+	# Wait for it...
+3:	ldi		@(gr4,#SDRAMC_DSTS),gr3
+	andicc		gr3,#SDRAMC_DSTS_SSI,gr3,icc0
+	bne		icc0,#2,3b
+
+#if 0
+	li		0x0100000,gr10
+4:	subicc		gr10,#1,gr10,icc0
+
+	bne		icc0,#0,4b
+#endif
+
+__cmode_icache_lock_end:		
+
+	li		#__cmode_icache_lock_start,gr3
+	li		#__cmode_icache_lock_end,gr4
+
+4:	icul		gr3
+	addi		gr3,#L1_CACHE_BYTES,gr3
+	cmp		gr4,gr3,icc0
+	bhi		icc0,#0,4b
+
+#if 0 // Fujitsu recommend to skip this and will update docs.
+	# (15) Release the interrupt mask setting of the MASK register of 
+	# the interrupt controller if necessary.
+	sti		gr13,@(gr12,#0)
+#endif	
+	# (16) Set  1' in the PSR.ET bit, and permit interrupt.
+	movgs		gr14,psr
+
+	bralr
+	
+	.size		frv_change_cmode, .-frv_change_cmode
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/kernel/debug-stub.c linux-2.6.10-rc1-mm3-frv/arch/frv/kernel/debug-stub.c
--- /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/kernel/debug-stub.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/arch/frv/kernel/debug-stub.c	2004-11-05 16:28:59.087204150 +0000
@@ -0,0 +1,259 @@
+/* debug-stub.c: debug-mode stub
+ *
+ * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * 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.
+ */
+
+#include <linux/string.h>
+#include <linux/kernel.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+#include <linux/serial_reg.h>
+
+#include <asm/system.h>
+#include <asm/serial-regs.h>
+#include <asm/timer-regs.h>
+#include <asm/irc-regs.h>
+#include <asm/gdb-stub.h>
+#include "gdb-io.h"
+
+/* CPU board CON5 */
+#define __UART0(X) (*(volatile uint8_t *)(UART0_BASE + (UART_##X)))
+
+#define LSR_WAIT_FOR0(STATE)			\
+do {						\
+} while (!(__UART0(LSR) & UART_LSR_##STATE))
+
+#define FLOWCTL_QUERY0(LINE)	({ __UART0(MSR) & UART_MSR_##LINE; })
+#define FLOWCTL_CLEAR0(LINE)	do { __UART0(MCR) &= ~UART_MCR_##LINE; } while (0)
+#define FLOWCTL_SET0(LINE)	do { __UART0(MCR) |= UART_MCR_##LINE; } while (0)
+
+#define FLOWCTL_WAIT_FOR0(LINE)			\
+do {						\
+	gdbstub_do_rx();			\
+} while(!FLOWCTL_QUERY(LINE))
+
+static void __init debug_stub_init(void);
+
+extern asmlinkage void __break_hijack_kernel_event(void);
+extern asmlinkage void __break_hijack_kernel_event_breaks_here(void);
+
+/*****************************************************************************/
+/*
+ * debug mode handler stub
+ * - we come here with the CPU in debug mode and with exceptions disabled
+ * - handle debugging services for userspace
+ */
+asmlinkage void debug_stub(void)
+{
+	unsigned long hsr0;
+	int type = 0;
+
+	static u8 inited = 0;
+	if (!inited) {
+		debug_stub_init();
+		type = -1;
+		inited = 1;
+	}
+
+	hsr0 = __get_HSR(0);
+	if (hsr0 & HSR0_ETMD)
+		__set_HSR(0, hsr0 & ~HSR0_ETMD);
+
+	/* disable single stepping */
+	__debug_regs->dcr &= ~DCR_SE;
+
+	/* kernel mode can propose an exception be handled in debug mode by jumping to a special
+	 * location */
+	if (__debug_frame->pc == (unsigned long) __break_hijack_kernel_event_breaks_here) {
+		/* replace the debug frame with the kernel frame and discard
+		 * the top kernel context */
+		*__debug_frame = *__frame;
+		__frame = __debug_frame->next_frame;
+		__debug_regs->brr = (__debug_frame->tbr & TBR_TT) << 12;
+		__debug_regs->brr |= BRR_EB;
+	}
+
+	if (__debug_frame->pc == (unsigned long) __debug_bug_trap + 4) {
+		__debug_frame->pc = __debug_frame->lr;
+		type = __debug_frame->gr8;
+	}
+
+#ifdef CONFIG_GDBSTUB
+	gdbstub(type);
+#endif
+
+	if (hsr0 & HSR0_ETMD)
+		__set_HSR(0, __get_HSR(0) | HSR0_ETMD);
+
+} /* end debug_stub() */
+
+/*****************************************************************************/
+/*
+ * debug stub initialisation
+ */
+static void __init debug_stub_init(void)
+{
+	__set_IRR(6, 0xff000000);	/* map ERRs to NMI */
+	__set_IITMR(1, 0x20000000);	/* ERR0/1, UART0/1 IRQ detect levels */
+
+	asm volatile("	movgs	gr0,ibar0	\n"
+		     "	movgs	gr0,ibar1	\n"
+		     "	movgs	gr0,ibar2	\n"
+		     "	movgs	gr0,ibar3	\n"
+		     "	movgs	gr0,dbar0	\n"
+		     "	movgs	gr0,dbmr00	\n"
+		     "	movgs	gr0,dbmr01	\n"
+		     "	movgs	gr0,dbdr00	\n"
+		     "	movgs	gr0,dbdr01	\n"
+		     "	movgs	gr0,dbar1	\n"
+		     "	movgs	gr0,dbmr10	\n"
+		     "	movgs	gr0,dbmr11	\n"
+		     "	movgs	gr0,dbdr10	\n"
+		     "	movgs	gr0,dbdr11	\n"
+		     );
+
+	/* deal with debugging stub initialisation and initial pause */
+	if (__debug_frame->pc == (unsigned long) __debug_stub_init_break)
+		__debug_frame->pc = (unsigned long) start_kernel;
+
+	/* enable the debug events we want to trap */
+	__debug_regs->dcr = DCR_EBE;
+
+#ifdef CONFIG_GDBSTUB
+	gdbstub_init();
+#endif
+
+	__clr_MASK_all();
+	__clr_MASK(15);
+	__clr_RC(15);
+
+} /* end debug_stub_init() */
+
+/*****************************************************************************/
+/*
+ * kernel "exit" trap for gdb stub
+ */
+void debug_stub_exit(int status)
+{
+
+#ifdef CONFIG_GDBSTUB
+	gdbstub_exit(status);
+#endif
+
+} /* end debug_stub_exit() */
+
+/*****************************************************************************/
+/*
+ * send string to serial port
+ */
+void debug_to_serial(const char *p, int n)
+{
+	char ch;
+
+	for (; n > 0; n--) {
+		ch = *p++;
+		FLOWCTL_SET0(DTR);
+		LSR_WAIT_FOR0(THRE);
+		// FLOWCTL_WAIT_FOR(CTS);
+
+		if (ch == 0x0a) {
+			__UART0(TX) = 0x0d;
+			mb();
+			LSR_WAIT_FOR0(THRE);
+			// FLOWCTL_WAIT_FOR(CTS);
+		}
+		__UART0(TX) = ch;
+		mb();
+
+		FLOWCTL_CLEAR0(DTR);
+	}
+
+} /* end debug_to_serial() */
+
+/*****************************************************************************/
+/*
+ * send string to serial port
+ */
+void debug_to_serial2(const char *fmt, ...)
+{
+	va_list va;
+	char buf[64];
+	int n;
+
+	va_start(va, fmt);
+	n = vsprintf(buf, fmt, va);
+	va_end(va);
+
+	debug_to_serial(buf, n);
+
+} /* end debug_to_serial2() */
+
+/*****************************************************************************/
+/*
+ * set up the ttyS0 serial port baud rate timers
+ */
+void __init console_set_baud(unsigned baud)
+{
+	unsigned value, high, low;
+	u8 lcr;
+
+	/* work out the divisor to give us the nearest higher baud rate */
+	value = __serial_clock_speed_HZ / 16 / baud;
+
+	/* determine the baud rate range */
+	high = __serial_clock_speed_HZ / 16 / value;
+	low = __serial_clock_speed_HZ / 16 / (value + 1);
+
+	/* pick the nearest bound */
+	if (low + (high - low) / 2 > baud)
+		value++;
+
+	lcr = __UART0(LCR);
+	__UART0(LCR) |= UART_LCR_DLAB;
+	mb();
+	__UART0(DLL) = value & 0xff;
+	__UART0(DLM) = (value >> 8) & 0xff;
+	mb();
+	__UART0(LCR) = lcr;
+	mb();
+
+} /* end console_set_baud() */
+
+/*****************************************************************************/
+/*
+ *
+ */
+int __init console_get_baud(void)
+{
+	unsigned value;
+	u8 lcr;
+
+	lcr = __UART0(LCR);
+	__UART0(LCR) |= UART_LCR_DLAB;
+	mb();
+	value =  __UART0(DLM) << 8;
+	value |= __UART0(DLL);
+	__UART0(LCR) = lcr;
+	mb();
+
+	return value;
+} /* end console_get_baud() */
+
+/*****************************************************************************/
+/*
+ * display BUG() info
+ */
+#ifndef CONFIG_NO_KERNEL_MSG
+void __debug_bug_printk(const char *file, unsigned line)
+{
+	printk("kernel BUG at %s:%d!\n", file, line);
+
+} /* end __debug_bug_printk() */
+#endif
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/kernel/dma.c linux-2.6.10-rc1-mm3-frv/arch/frv/kernel/dma.c
--- /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/kernel/dma.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/arch/frv/kernel/dma.c	2004-11-05 14:13:03.073565872 +0000
@@ -0,0 +1,464 @@
+/* dma.c: DMA controller management on FR401 and the like
+ *
+ * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * 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.
+ */
+
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/spinlock.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <asm/dma.h>
+#include <asm/gpio-regs.h>
+#include <asm/irc-regs.h>
+#include <asm/cpu-irqs.h>
+
+struct frv_dma_channel {
+	uint8_t			flags;
+#define FRV_DMA_FLAGS_RESERVED	0x01
+#define FRV_DMA_FLAGS_INUSE	0x02
+#define FRV_DMA_FLAGS_PAUSED	0x04
+	uint8_t			cap;		/* capabilities available */
+	int			irq;		/* completion IRQ */
+	uint32_t		dreqbit;
+	uint32_t		dackbit;
+	uint32_t		donebit;
+	const unsigned long	ioaddr;		/* DMA controller regs addr */
+	const char		*devname;
+	dma_irq_handler_t	handler;
+	void			*data;
+};
+
+
+#define __get_DMAC(IO,X)	({ *(volatile unsigned long *)((IO) + DMAC_##X##x); })
+
+#define __set_DMAC(IO,X,V)					\
+do {								\
+	*(volatile unsigned long *)((IO) + DMAC_##X##x) = (V);	\
+	mb();							\
+} while(0)
+
+#define ___set_DMAC(IO,X,V)					\
+do {								\
+	*(volatile unsigned long *)((IO) + DMAC_##X##x) = (V);	\
+} while(0)
+
+
+static struct frv_dma_channel frv_dma_channels[FRV_DMA_NCHANS] = {
+	[0] = {
+		.cap		= FRV_DMA_CAP_DREQ | FRV_DMA_CAP_DACK | FRV_DMA_CAP_DONE,
+		.irq		= IRQ_CPU_DMA0,
+		.dreqbit	= SIR_DREQ0_INPUT,
+		.dackbit	= SOR_DACK0_OUTPUT,
+		.donebit	= SOR_DONE0_OUTPUT,
+		.ioaddr		= 0xfe000900,
+	},
+	[1] = {
+		.cap		= FRV_DMA_CAP_DREQ | FRV_DMA_CAP_DACK | FRV_DMA_CAP_DONE,
+		.irq		= IRQ_CPU_DMA1,
+		.dreqbit	= SIR_DREQ1_INPUT,
+		.dackbit	= SOR_DACK1_OUTPUT,
+		.donebit	= SOR_DONE1_OUTPUT,
+		.ioaddr		= 0xfe000980,
+	},
+	[2] = {
+		.cap		= FRV_DMA_CAP_DREQ | FRV_DMA_CAP_DACK,
+		.irq		= IRQ_CPU_DMA2,
+		.dreqbit	= SIR_DREQ2_INPUT,
+		.dackbit	= SOR_DACK2_OUTPUT,
+		.ioaddr		= 0xfe000a00,
+	},
+	[3] = {
+		.cap		= FRV_DMA_CAP_DREQ | FRV_DMA_CAP_DACK,
+		.irq		= IRQ_CPU_DMA3,
+		.dreqbit	= SIR_DREQ3_INPUT,
+		.dackbit	= SOR_DACK3_OUTPUT,
+		.ioaddr		= 0xfe000a80,
+	},
+	[4] = {
+		.cap		= FRV_DMA_CAP_DREQ,
+		.irq		= IRQ_CPU_DMA4,
+		.dreqbit	= SIR_DREQ4_INPUT,
+		.ioaddr		= 0xfe001000,
+	},
+	[5] = {
+		.cap		= FRV_DMA_CAP_DREQ,
+		.irq		= IRQ_CPU_DMA5,
+		.dreqbit	= SIR_DREQ5_INPUT,
+		.ioaddr		= 0xfe001080,
+	},
+	[6] = {
+		.cap		= FRV_DMA_CAP_DREQ,
+		.irq		= IRQ_CPU_DMA6,
+		.dreqbit	= SIR_DREQ6_INPUT,
+		.ioaddr		= 0xfe001100,
+	},
+	[7] = {
+		.cap		= FRV_DMA_CAP_DREQ,
+		.irq		= IRQ_CPU_DMA7,
+		.dreqbit	= SIR_DREQ7_INPUT,
+		.ioaddr		= 0xfe001180,
+	},
+};
+
+static rwlock_t frv_dma_channels_lock = RW_LOCK_UNLOCKED;
+
+unsigned long frv_dma_inprogress;
+
+#define frv_clear_dma_inprogress(channel) \
+	atomic_clear_mask(1 << (channel), &frv_dma_inprogress);
+
+#define frv_set_dma_inprogress(channel) \
+	atomic_set_mask(1 << (channel), &frv_dma_inprogress);
+
+/*****************************************************************************/
+/*
+ * DMA irq handler - determine channel involved, grab status and call real handler
+ */
+static irqreturn_t dma_irq_handler(int irq, void *_channel, struct pt_regs *regs)
+{
+	struct frv_dma_channel *channel = _channel;
+
+	frv_clear_dma_inprogress(channel - frv_dma_channels);
+	return channel->handler(channel - frv_dma_channels,
+				__get_DMAC(channel->ioaddr, CSTR),
+				channel->data,
+				regs);
+
+} /* end dma_irq_handler() */
+
+/*****************************************************************************/
+/*
+ * Determine which DMA controllers are present on this CPU
+ */
+void __init frv_dma_init(void)
+{
+	unsigned long psr = __get_PSR();
+	int num_dma, i;
+
+	/* First, determine how many DMA channels are available */
+	switch (PSR_IMPLE(psr)) {
+	case PSR_IMPLE_FR405:
+	case PSR_IMPLE_FR451:
+	case PSR_IMPLE_FR501:
+	case PSR_IMPLE_FR551:
+		num_dma = FRV_DMA_8CHANS;
+		break;
+
+	case PSR_IMPLE_FR401:
+	default:
+		num_dma = FRV_DMA_4CHANS;
+		break;
+	}
+
+	/* Now mark all of the non-existent channels as reserved */
+	for(i = num_dma; i < FRV_DMA_NCHANS; i++)
+		frv_dma_channels[i].flags = FRV_DMA_FLAGS_RESERVED;
+
+} /* end frv_dma_init() */
+
+/*****************************************************************************/
+/*
+ * allocate a DMA controller channel and the IRQ associated with it
+ */
+int frv_dma_open(const char *devname,
+		 unsigned long dmamask,
+		 int dmacap,
+		 dma_irq_handler_t handler,
+		 unsigned long irq_flags,
+		 void *data)
+{
+	struct frv_dma_channel *channel;
+	int dma, ret;
+	uint32_t val;
+
+	write_lock(&frv_dma_channels_lock);
+
+	ret = -ENOSPC;
+
+	for (dma = FRV_DMA_NCHANS - 1; dma >= 0; dma--) {
+		channel = &frv_dma_channels[dma];
+
+		if (!test_bit(dma, &dmamask))
+			continue;
+
+		if ((channel->cap & dmacap) != dmacap)
+			continue;
+
+		if (!frv_dma_channels[dma].flags)
+			goto found;
+	}
+
+	goto out;
+
+ found:
+	ret = request_irq(channel->irq, dma_irq_handler, irq_flags, devname, channel);
+	if (ret < 0)
+		goto out;
+
+	/* okay, we've allocated all the resources */
+	channel = &frv_dma_channels[dma];
+
+	channel->flags		|= FRV_DMA_FLAGS_INUSE;
+	channel->devname	= devname;
+	channel->handler	= handler;
+	channel->data		= data;
+
+	/* Now make sure we are set up for DMA and not GPIO */
+	/* SIR bit must be set for DMA to work */
+	__set_SIR(channel->dreqbit | __get_SIR());
+	/* SOR bits depend on what the caller requests */
+	val = __get_SOR();
+	if(dmacap & FRV_DMA_CAP_DACK)
+		val |= channel->dackbit;
+	else
+		val &= ~channel->dackbit;
+	if(dmacap & FRV_DMA_CAP_DONE)
+		val |= channel->donebit;
+	else
+		val &= ~channel->donebit;
+	__set_SOR(val);
+
+	ret = dma;
+ out:
+	write_unlock(&frv_dma_channels_lock);
+	return ret;
+} /* end frv_dma_open() */
+
+EXPORT_SYMBOL(frv_dma_open);
+
+/*****************************************************************************/
+/*
+ * close a DMA channel and its associated interrupt
+ */
+void frv_dma_close(int dma)
+{
+	struct frv_dma_channel *channel = &frv_dma_channels[dma];
+	unsigned long flags;
+
+	write_lock_irqsave(&frv_dma_channels_lock, flags);
+
+	free_irq(channel->irq, channel);
+	frv_dma_stop(dma);
+
+	channel->flags &= ~FRV_DMA_FLAGS_INUSE;
+
+	write_unlock_irqrestore(&frv_dma_channels_lock, flags);
+} /* end frv_dma_close() */
+
+EXPORT_SYMBOL(frv_dma_close);
+
+/*****************************************************************************/
+/*
+ * set static configuration on a DMA channel
+ */
+void frv_dma_config(int dma, unsigned long ccfr, unsigned long cctr, unsigned long apr)
+{
+	unsigned long ioaddr = frv_dma_channels[dma].ioaddr;
+
+	___set_DMAC(ioaddr, CCFR, ccfr);
+	___set_DMAC(ioaddr, CCTR, cctr);
+	___set_DMAC(ioaddr, APR,  apr);
+	mb();
+
+} /* end frv_dma_config() */
+
+EXPORT_SYMBOL(frv_dma_config);
+
+/*****************************************************************************/
+/*
+ * start a DMA channel
+ */
+void frv_dma_start(int dma,
+		   unsigned long sba, unsigned long dba,
+		   unsigned long pix, unsigned long six, unsigned long bcl)
+{
+	unsigned long ioaddr = frv_dma_channels[dma].ioaddr;
+
+	___set_DMAC(ioaddr, SBA,  sba);
+	___set_DMAC(ioaddr, DBA,  dba);
+	___set_DMAC(ioaddr, PIX,  pix);
+	___set_DMAC(ioaddr, SIX,  six);
+	___set_DMAC(ioaddr, BCL,  bcl);
+	___set_DMAC(ioaddr, CSTR, 0);
+	mb();
+
+	__set_DMAC(ioaddr, CCTR, __get_DMAC(ioaddr, CCTR) | DMAC_CCTRx_ACT);
+	frv_set_dma_inprogress(dma);
+
+} /* end frv_dma_start() */
+
+EXPORT_SYMBOL(frv_dma_start);
+
+/*****************************************************************************/
+/*
+ * restart a DMA channel that's been stopped in circular addressing mode by comparison-end
+ */
+void frv_dma_restart_circular(int dma, unsigned long six)
+{
+	unsigned long ioaddr = frv_dma_channels[dma].ioaddr;
+
+	___set_DMAC(ioaddr, SIX,  six);
+	___set_DMAC(ioaddr, CSTR, __get_DMAC(ioaddr, CSTR) & ~DMAC_CSTRx_CE);
+	mb();
+
+	__set_DMAC(ioaddr, CCTR, __get_DMAC(ioaddr, CCTR) | DMAC_CCTRx_ACT);
+	frv_set_dma_inprogress(dma);
+
+} /* end frv_dma_restart_circular() */
+
+EXPORT_SYMBOL(frv_dma_restart_circular);
+
+/*****************************************************************************/
+/*
+ * stop a DMA channel
+ */
+void frv_dma_stop(int dma)
+{
+	unsigned long ioaddr = frv_dma_channels[dma].ioaddr;
+	uint32_t cctr;
+
+	___set_DMAC(ioaddr, CSTR, 0);
+	cctr = __get_DMAC(ioaddr, CCTR);
+	cctr &= ~(DMAC_CCTRx_IE | DMAC_CCTRx_ACT);
+	cctr |= DMAC_CCTRx_FC; 	/* fifo clear */
+	__set_DMAC(ioaddr, CCTR, cctr);
+	__set_DMAC(ioaddr, BCL,  0);
+	frv_clear_dma_inprogress(dma);
+} /* end frv_dma_stop() */
+
+EXPORT_SYMBOL(frv_dma_stop);
+
+/*****************************************************************************/
+/*
+ * test interrupt status of DMA channel
+ */
+int is_frv_dma_interrupting(int dma)
+{
+	unsigned long ioaddr = frv_dma_channels[dma].ioaddr;
+
+	return __get_DMAC(ioaddr, CSTR) & (1 << 23);
+
+} /* end is_frv_dma_interrupting() */
+
+EXPORT_SYMBOL(is_frv_dma_interrupting);
+
+/*****************************************************************************/
+/*
+ * dump data about a DMA channel
+ */
+void frv_dma_dump(int dma)
+{
+	unsigned long ioaddr = frv_dma_channels[dma].ioaddr;
+	unsigned long cstr, pix, six, bcl;
+
+	cstr = __get_DMAC(ioaddr, CSTR);
+	pix  = __get_DMAC(ioaddr, PIX);
+	six  = __get_DMAC(ioaddr, SIX);
+	bcl  = __get_DMAC(ioaddr, BCL);
+
+	printk("DMA[%d] cstr=%lx pix=%lx six=%lx bcl=%lx\n", dma, cstr, pix, six, bcl);
+
+} /* end frv_dma_dump() */
+
+EXPORT_SYMBOL(frv_dma_dump);
+
+/*****************************************************************************/
+/*
+ * pause all DMA controllers
+ * - called by clock mangling routines
+ * - caller must be holding interrupts disabled
+ */
+void frv_dma_pause_all(void)
+{
+	struct frv_dma_channel *channel;
+	unsigned long ioaddr;
+	unsigned long cstr, cctr;
+	int dma;
+
+	write_lock(&frv_dma_channels_lock);
+
+	for (dma = FRV_DMA_NCHANS - 1; dma >= 0; dma--) {
+		channel = &frv_dma_channels[dma];
+
+		if (!(channel->flags & FRV_DMA_FLAGS_INUSE))
+			continue;
+
+		ioaddr = channel->ioaddr;
+		cctr = __get_DMAC(ioaddr, CCTR);
+		if (cctr & DMAC_CCTRx_ACT) {
+			cctr &= ~DMAC_CCTRx_ACT;
+			__set_DMAC(ioaddr, CCTR, cctr);
+
+			do {
+				cstr = __get_DMAC(ioaddr, CSTR);
+			} while (cstr & DMAC_CSTRx_BUSY);
+
+			if (cstr & DMAC_CSTRx_FED)
+				channel->flags |= FRV_DMA_FLAGS_PAUSED;
+			frv_clear_dma_inprogress(dma);
+		}
+	}
+
+} /* end frv_dma_pause_all() */
+
+EXPORT_SYMBOL(frv_dma_pause_all);
+
+/*****************************************************************************/
+/*
+ * resume paused DMA controllers
+ * - called by clock mangling routines
+ * - caller must be holding interrupts disabled
+ */
+void frv_dma_resume_all(void)
+{
+	struct frv_dma_channel *channel;
+	unsigned long ioaddr;
+	unsigned long cstr, cctr;
+	int dma;
+
+	for (dma = FRV_DMA_NCHANS - 1; dma >= 0; dma--) {
+		channel = &frv_dma_channels[dma];
+
+		if (!(channel->flags & FRV_DMA_FLAGS_PAUSED))
+			continue;
+
+		ioaddr = channel->ioaddr;
+		cstr = __get_DMAC(ioaddr, CSTR);
+		cstr &= ~(DMAC_CSTRx_FED | DMAC_CSTRx_INT);
+		__set_DMAC(ioaddr, CSTR, cstr);
+
+		cctr = __get_DMAC(ioaddr, CCTR);
+		cctr |= DMAC_CCTRx_ACT;
+		__set_DMAC(ioaddr, CCTR, cctr);
+
+		channel->flags &= ~FRV_DMA_FLAGS_PAUSED;
+		frv_set_dma_inprogress(dma);
+	}
+
+	write_unlock(&frv_dma_channels_lock);
+
+} /* end frv_dma_resume_all() */
+
+EXPORT_SYMBOL(frv_dma_resume_all);
+
+/*****************************************************************************/
+/*
+ * dma status clear
+ */
+void frv_dma_status_clear(int dma)
+{
+	unsigned long ioaddr = frv_dma_channels[dma].ioaddr;
+	uint32_t cctr;
+	___set_DMAC(ioaddr, CSTR, 0);
+
+	cctr = __get_DMAC(ioaddr, CCTR);
+} /* end frv_dma_status_clear() */
+
+EXPORT_SYMBOL(frv_dma_status_clear);
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/kernel/entry.S linux-2.6.10-rc1-mm3-frv/arch/frv/kernel/entry.S
--- /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/kernel/entry.S	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/arch/frv/kernel/entry.S	2004-11-05 14:13:03.077565534 +0000
@@ -0,0 +1,1420 @@
+/* entry.S: FR-V entry
+ *
+ * Copyright (C) 2003 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * 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.
+ *
+ *
+ * Entry to the kernel is "interesting":
+ *  (1) There are no stack pointers, not even for the kernel
+ *  (2) General Registers should not be clobbered
+ *  (3) There are no kernel-only data registers
+ *  (4) Since all addressing modes are wrt to a General Register, no global
+ *      variables can be reached
+ *
+ * We deal with this by declaring that we shall kill GR28 on entering the
+ * kernel from userspace
+ *
+ * However, since break interrupts can interrupt the CPU even when PSR.ET==0,
+ * they can't rely on GR28 to be anything useful, and so need to clobber a
+ * separate register (GR31). Break interrupts are managed in break.S
+ *
+ * GR29 _is_ saved, and holds the current task pointer globally
+ *
+ */
+
+#include <linux/sys.h>
+#include <linux/config.h>
+#include <linux/linkage.h>
+#include <asm/thread_info.h>
+#include <asm/setup.h>
+#include <asm/segment.h>
+#include <asm/ptrace.h>
+#include <asm/errno.h>
+#include <asm/cache.h>
+#include <asm/spr-regs.h>
+
+#define nr_syscalls ((syscall_table_size)/4)
+
+	.text
+	.balign		4
+
+.macro LEDS val
+#	sethi.p		%hi(0xe1200004),gr30
+#	setlo		%lo(0xe1200004),gr30
+#	setlos		#~\val,gr31
+#	st		gr31,@(gr30,gr0)
+#	sethi.p		%hi(0xffc00100),gr30
+#	setlo		%lo(0xffc00100),gr30
+#	sth		gr0,@(gr30,gr0)
+#	membar
+.endm
+
+.macro LEDS32
+#	not		gr31,gr31
+#	sethi.p		%hi(0xe1200004),gr30
+#	setlo		%lo(0xe1200004),gr30
+#	st.p		gr31,@(gr30,gr0)
+#	srli		gr31,#16,gr31
+#	sethi.p		%hi(0xffc00100),gr30
+#	setlo		%lo(0xffc00100),gr30
+#	sth		gr31,@(gr30,gr0)
+#	membar
+.endm
+
+###############################################################################
+#
+# entry point for External interrupts received whilst executing userspace code
+#
+###############################################################################
+	.globl		__entry_uspace_external_interrupt
+        .type		__entry_uspace_external_interrupt,@function
+__entry_uspace_external_interrupt:
+	LEDS		0x6200
+	sethi.p		%hi(__kernel_frame0_ptr),gr28
+	setlo		%lo(__kernel_frame0_ptr),gr28
+	ldi		@(gr28,#0),gr28
+
+	# handle h/w single-step through exceptions
+	sti		gr0,@(gr28,#REG__STATUS)
+
+	.globl		__entry_uspace_external_interrupt_reentry
+__entry_uspace_external_interrupt_reentry:
+	LEDS		0x6201
+
+	setlos		#REG__END,gr30
+	dcpl		gr28,gr30,#0
+
+	# finish building the exception frame
+	sti		sp,  @(gr28,#REG_SP)
+	stdi		gr2, @(gr28,#REG_GR(2))
+	stdi		gr4, @(gr28,#REG_GR(4))
+	stdi		gr6, @(gr28,#REG_GR(6))
+	stdi		gr8, @(gr28,#REG_GR(8))
+	stdi		gr10,@(gr28,#REG_GR(10))
+	stdi		gr12,@(gr28,#REG_GR(12))
+	stdi		gr14,@(gr28,#REG_GR(14))
+	stdi		gr16,@(gr28,#REG_GR(16))
+	stdi		gr18,@(gr28,#REG_GR(18))
+	stdi		gr20,@(gr28,#REG_GR(20))
+	stdi		gr22,@(gr28,#REG_GR(22))
+	stdi		gr24,@(gr28,#REG_GR(24))
+	stdi		gr26,@(gr28,#REG_GR(26))
+	sti		gr0, @(gr28,#REG_GR(28))
+	sti		gr29,@(gr28,#REG_GR(29))
+	stdi.p		gr30,@(gr28,#REG_GR(30))
+
+	# set up the kernel stack pointer
+	ori		gr28,0,sp
+
+	movsg		tbr ,gr20
+	movsg		psr ,gr22
+	movsg		pcsr,gr21
+	movsg		isr ,gr23
+	movsg		ccr ,gr24
+	movsg		cccr,gr25
+	movsg		lr  ,gr26
+	movsg		lcr ,gr27
+
+	setlos.p	#-1,gr4
+	andi		gr22,#PSR_PS,gr5		/* try to rebuild original PSR value */
+	andi.p		gr22,#~(PSR_PS|PSR_S),gr6
+	slli		gr5,#1,gr5
+	or		gr6,gr5,gr5
+	andi		gr5,#~PSR_ET,gr5
+
+	sti		gr20,@(gr28,#REG_TBR)
+	sti		gr21,@(gr28,#REG_PC)
+	sti		gr5 ,@(gr28,#REG_PSR)
+	sti		gr23,@(gr28,#REG_ISR)
+	stdi		gr24,@(gr28,#REG_CCR)
+	stdi		gr26,@(gr28,#REG_LR)
+	sti		gr4 ,@(gr28,#REG_SYSCALLNO)
+
+	movsg		iacc0h,gr4
+	movsg		iacc0l,gr5
+	stdi		gr4,@(gr28,#REG_IACC0)
+
+	movsg		gner0,gr4
+	movsg		gner1,gr5
+	stdi		gr4,@(gr28,#REG_GNER0)
+
+	# set up kernel global registers
+	sethi.p		%hi(__kernel_current_task),gr5
+	setlo		%lo(__kernel_current_task),gr5
+	sethi.p		%hi(_gp),gr16
+	setlo		%lo(_gp),gr16
+	ldi		@(gr5,#0),gr29
+	ldi.p		@(gr29,#4),gr15		; __current_thread_info = current->thread_info
+
+	# make sure we (the kernel) get div-zero and misalignment exceptions
+	setlos		#ISR_EDE|ISR_DTT_DIVBYZERO|ISR_EMAM_EXCEPTION,gr5
+	movgs		gr5,isr
+
+	# switch to the kernel trap table
+	sethi.p		%hi(__entry_kerneltrap_table),gr6
+	setlo		%lo(__entry_kerneltrap_table),gr6
+	movgs		gr6,tbr
+
+	# set the return address
+	sethi.p		%hi(__entry_return_from_user_interrupt),gr4
+	setlo		%lo(__entry_return_from_user_interrupt),gr4
+	movgs		gr4,lr
+
+	# raise the minimum interrupt priority to 15 (NMI only) and enable exceptions
+	movsg		psr,gr4
+
+	ori		gr4,#PSR_PIL_14,gr4
+	movgs		gr4,psr
+	ori		gr4,#PSR_PIL_14|PSR_ET,gr4
+	movgs		gr4,psr
+
+	LEDS		0x6202
+	bra		do_IRQ
+
+	.size		__entry_uspace_external_interrupt,.-__entry_uspace_external_interrupt
+
+###############################################################################
+#
+# entry point for External interrupts received whilst executing kernel code
+# - on arriving here, the following registers should already be set up:
+#	GR15	- current thread_info struct pointer
+#	GR16	- kernel GP-REL pointer
+#	GR29	- current task struct pointer
+#	TBR	- kernel trap vector table
+#	ISR	- kernel's preferred integer controls
+#
+###############################################################################
+	.globl		__entry_kernel_external_interrupt
+        .type		__entry_kernel_external_interrupt,@function
+__entry_kernel_external_interrupt:
+	LEDS		0x6210
+
+	sub		sp,gr15,gr31
+	LEDS32
+
+	# set up the stack pointer
+	or.p		sp,gr0,gr30
+	subi		sp,#REG__END,sp
+	sti		gr30,@(sp,#REG_SP)
+
+	# handle h/w single-step through exceptions
+	sti		gr0,@(sp,#REG__STATUS)
+
+	.globl		__entry_kernel_external_interrupt_reentry
+__entry_kernel_external_interrupt_reentry:
+	LEDS		0x6211
+
+	# set up the exception frame
+	setlos		#REG__END,gr30
+	dcpl		sp,gr30,#0
+
+	sti.p		gr28,@(sp,#REG_GR(28))
+	ori		sp,0,gr28
+
+	# finish building the exception frame
+	stdi		gr2,@(gr28,#REG_GR(2))
+	stdi		gr4,@(gr28,#REG_GR(4))
+	stdi		gr6,@(gr28,#REG_GR(6))
+	stdi		gr8,@(gr28,#REG_GR(8))
+	stdi		gr10,@(gr28,#REG_GR(10))
+	stdi		gr12,@(gr28,#REG_GR(12))
+	stdi		gr14,@(gr28,#REG_GR(14))
+	stdi		gr16,@(gr28,#REG_GR(16))
+	stdi		gr18,@(gr28,#REG_GR(18))
+	stdi		gr20,@(gr28,#REG_GR(20))
+	stdi		gr22,@(gr28,#REG_GR(22))
+	stdi		gr24,@(gr28,#REG_GR(24))
+	stdi		gr26,@(gr28,#REG_GR(26))
+	sti		gr29,@(gr28,#REG_GR(29))
+	stdi		gr30,@(gr28,#REG_GR(30))
+
+	movsg		tbr ,gr20
+	movsg		psr ,gr22
+	movsg		pcsr,gr21
+	movsg		isr ,gr23
+	movsg		ccr ,gr24
+	movsg		cccr,gr25
+	movsg		lr  ,gr26
+	movsg		lcr ,gr27
+
+	setlos.p	#-1,gr4
+	andi		gr22,#PSR_PS,gr5		/* try to rebuild original PSR value */
+	andi.p		gr22,#~(PSR_PS|PSR_S),gr6
+	slli		gr5,#1,gr5
+	or		gr6,gr5,gr5
+	andi.p		gr5,#~PSR_ET,gr5
+
+	# set CCCR.CC3 to Undefined to abort atomic-modify completion inside the kernel
+	# - for an explanation of how it works, see: Documentation/fujitsu/frv/atomic-ops.txt
+	andi		gr25,#~0xc0,gr25
+
+	sti		gr20,@(gr28,#REG_TBR)
+	sti		gr21,@(gr28,#REG_PC)
+	sti		gr5 ,@(gr28,#REG_PSR)
+	sti		gr23,@(gr28,#REG_ISR)
+	stdi		gr24,@(gr28,#REG_CCR)
+	stdi		gr26,@(gr28,#REG_LR)
+	sti		gr4 ,@(gr28,#REG_SYSCALLNO)
+
+	movsg		iacc0h,gr4
+	movsg		iacc0l,gr5
+	stdi		gr4,@(gr28,#REG_IACC0)
+
+	movsg		gner0,gr4
+	movsg		gner1,gr5
+	stdi		gr4,@(gr28,#REG_GNER0)
+
+	# set the return address
+	sethi.p		%hi(__entry_return_from_kernel_interrupt),gr4
+	setlo		%lo(__entry_return_from_kernel_interrupt),gr4
+	movgs		gr4,lr
+
+	# clear power-saving mode flags
+	movsg		hsr0,gr4
+	andi		gr4,#~HSR0_PDM,gr4
+	movgs		gr4,hsr0
+
+	# raise the minimum interrupt priority to 15 (NMI only) and enable exceptions
+	movsg		psr,gr4
+	ori		gr4,#PSR_PIL_14,gr4
+	movgs		gr4,psr
+	ori		gr4,#PSR_ET,gr4
+	movgs		gr4,psr
+
+	LEDS		0x6212
+	bra		do_IRQ
+
+	.size		__entry_kernel_external_interrupt,.-__entry_kernel_external_interrupt
+
+
+###############################################################################
+#
+# entry point for Software and Progam interrupts generated whilst executing userspace code
+#
+###############################################################################
+	.globl		__entry_uspace_softprog_interrupt
+        .type		__entry_uspace_softprog_interrupt,@function
+	.globl		__entry_uspace_handle_mmu_fault
+__entry_uspace_softprog_interrupt:
+	LEDS		0x6000
+#ifdef CONFIG_MMU
+	movsg		ear0,gr28
+__entry_uspace_handle_mmu_fault:
+	movgs		gr28,scr2
+#endif
+	sethi.p		%hi(__kernel_frame0_ptr),gr28
+	setlo		%lo(__kernel_frame0_ptr),gr28
+	ldi		@(gr28,#0),gr28
+
+	# handle h/w single-step through exceptions
+	sti		gr0,@(gr28,#REG__STATUS)
+
+	.globl		__entry_uspace_softprog_interrupt_reentry
+__entry_uspace_softprog_interrupt_reentry:
+	LEDS		0x6001
+
+	setlos		#REG__END,gr30
+	dcpl		gr28,gr30,#0
+
+	# set up the kernel stack pointer
+	sti.p		sp,@(gr28,#REG_SP)
+	ori		gr28,0,sp
+	sti		gr0,@(gr28,#REG_GR(28))
+
+	stdi		gr20,@(gr28,#REG_GR(20))
+	stdi		gr22,@(gr28,#REG_GR(22))
+
+	movsg		tbr,gr20
+	movsg		pcsr,gr21
+	movsg		psr,gr22
+
+	sethi.p		%hi(__entry_return_from_user_exception),gr23
+	setlo		%lo(__entry_return_from_user_exception),gr23
+	bra		__entry_common
+
+	.size		__entry_uspace_softprog_interrupt,.-__entry_uspace_softprog_interrupt
+
+	# single-stepping was disabled on entry to a TLB handler that then faulted
+#ifdef CONFIG_MMU
+	.globl		__entry_uspace_handle_mmu_fault_sstep
+__entry_uspace_handle_mmu_fault_sstep:
+	movgs		gr28,scr2
+	sethi.p		%hi(__kernel_frame0_ptr),gr28
+	setlo		%lo(__kernel_frame0_ptr),gr28
+	ldi		@(gr28,#0),gr28
+
+	# flag single-step re-enablement
+	sti		gr0,@(gr28,#REG__STATUS)
+	bra		__entry_uspace_softprog_interrupt_reentry
+#endif
+
+
+###############################################################################
+#
+# entry point for Software and Progam interrupts generated whilst executing kernel code
+#
+###############################################################################
+	.globl		__entry_kernel_softprog_interrupt
+        .type		__entry_kernel_softprog_interrupt,@function
+__entry_kernel_softprog_interrupt:
+	LEDS		0x6004
+
+#ifdef CONFIG_MMU
+	movsg		ear0,gr30
+	movgs		gr30,scr2
+#endif
+
+	.globl		__entry_kernel_handle_mmu_fault
+__entry_kernel_handle_mmu_fault:
+	# set up the stack pointer
+	subi		sp,#REG__END,sp
+	sti		sp,@(sp,#REG_SP)
+	sti		sp,@(sp,#REG_SP-4)
+	andi		sp,#~7,sp
+
+	# handle h/w single-step through exceptions
+	sti		gr0,@(sp,#REG__STATUS)
+
+	.globl		__entry_kernel_softprog_interrupt_reentry
+__entry_kernel_softprog_interrupt_reentry:
+	LEDS		0x6005
+
+	setlos		#REG__END,gr30
+	dcpl		sp,gr30,#0
+
+	# set up the exception frame
+	sti.p		gr28,@(sp,#REG_GR(28))
+	ori		sp,0,gr28
+
+	stdi		gr20,@(gr28,#REG_GR(20))
+	stdi		gr22,@(gr28,#REG_GR(22))
+
+	ldi		@(sp,#REG_SP),gr22		/* reconstruct the old SP */
+	addi		gr22,#REG__END,gr22
+	sti		gr22,@(sp,#REG_SP)
+
+	# set CCCR.CC3 to Undefined to abort atomic-modify completion inside the kernel
+	# - for an explanation of how it works, see: Documentation/fujitsu/frv/atomic-ops.txt
+	movsg		cccr,gr20
+	andi		gr20,#~0xc0,gr20
+	movgs		gr20,cccr
+
+	movsg		tbr,gr20
+	movsg		pcsr,gr21
+	movsg		psr,gr22
+
+	sethi.p		%hi(__entry_return_from_kernel_exception),gr23
+	setlo		%lo(__entry_return_from_kernel_exception),gr23
+	bra		__entry_common
+
+	.size		__entry_kernel_softprog_interrupt,.-__entry_kernel_softprog_interrupt
+
+	# single-stepping was disabled on entry to a TLB handler that then faulted
+#ifdef CONFIG_MMU
+	.globl		__entry_kernel_handle_mmu_fault_sstep
+__entry_kernel_handle_mmu_fault_sstep:
+	# set up the stack pointer
+	subi		sp,#REG__END,sp
+	sti		sp,@(sp,#REG_SP)
+	sti		sp,@(sp,#REG_SP-4)
+	andi		sp,#~7,sp
+
+	# flag single-step re-enablement
+	sethi		#REG__STATUS_STEP,gr30
+	sti		gr30,@(sp,#REG__STATUS)
+	bra		__entry_kernel_softprog_interrupt_reentry
+#endif
+
+
+###############################################################################
+#
+# the rest of the kernel entry point code
+# - on arriving here, the following registers should be set up:
+#	GR1	- kernel stack pointer
+#	GR7	- syscall number (trap 0 only)
+#	GR8-13	- syscall args (trap 0 only)
+#	GR20	- saved TBR
+#	GR21	- saved PC
+#	GR22	- saved PSR
+#	GR23	- return handler address
+#	GR28	- exception frame on stack
+#	SCR2	- saved EAR0 where applicable (clobbered by ICI & ICEF insns on FR451)
+#	PSR	- PSR.S 1, PSR.ET 0
+#
+###############################################################################
+	.globl		__entry_common
+        .type		__entry_common,@function
+__entry_common:
+	LEDS		0x6008
+
+	# finish building the exception frame
+	stdi		gr2,@(gr28,#REG_GR(2))
+	stdi		gr4,@(gr28,#REG_GR(4))
+	stdi		gr6,@(gr28,#REG_GR(6))
+	stdi		gr8,@(gr28,#REG_GR(8))
+	stdi		gr10,@(gr28,#REG_GR(10))
+	stdi		gr12,@(gr28,#REG_GR(12))
+	stdi		gr14,@(gr28,#REG_GR(14))
+	stdi		gr16,@(gr28,#REG_GR(16))
+	stdi		gr18,@(gr28,#REG_GR(18))
+	stdi		gr24,@(gr28,#REG_GR(24))
+	stdi		gr26,@(gr28,#REG_GR(26))
+	sti		gr29,@(gr28,#REG_GR(29))
+	stdi		gr30,@(gr28,#REG_GR(30))
+
+	movsg		lcr ,gr27
+	movsg		lr  ,gr26
+	movgs		gr23,lr
+	movsg		cccr,gr25
+	movsg		ccr ,gr24
+	movsg		isr ,gr23
+
+	setlos.p	#-1,gr4
+	andi		gr22,#PSR_PS,gr5		/* try to rebuild original PSR value */
+	andi.p		gr22,#~(PSR_PS|PSR_S),gr6
+	slli		gr5,#1,gr5
+	or		gr6,gr5,gr5
+	andi		gr5,#~PSR_ET,gr5
+
+	sti		gr20,@(gr28,#REG_TBR)
+	sti		gr21,@(gr28,#REG_PC)
+	sti		gr5 ,@(gr28,#REG_PSR)
+	sti		gr23,@(gr28,#REG_ISR)
+	stdi		gr24,@(gr28,#REG_CCR)
+	stdi		gr26,@(gr28,#REG_LR)
+	sti		gr4 ,@(gr28,#REG_SYSCALLNO)
+
+	movsg		iacc0h,gr4
+	movsg		iacc0l,gr5
+	stdi		gr4,@(gr28,#REG_IACC0)
+
+	movsg		gner0,gr4
+	movsg		gner1,gr5
+	stdi		gr4,@(gr28,#REG_GNER0)
+
+	# set up kernel global registers
+	sethi.p		%hi(__kernel_current_task),gr5
+	setlo		%lo(__kernel_current_task),gr5
+	sethi.p		%hi(_gp),gr16
+	setlo		%lo(_gp),gr16
+	ldi		@(gr5,#0),gr29
+	ldi		@(gr29,#4),gr15		; __current_thread_info = current->thread_info
+
+	# switch to the kernel trap table
+	sethi.p		%hi(__entry_kerneltrap_table),gr6
+	setlo		%lo(__entry_kerneltrap_table),gr6
+	movgs		gr6,tbr
+
+	# make sure we (the kernel) get div-zero and misalignment exceptions
+	setlos		#ISR_EDE|ISR_DTT_DIVBYZERO|ISR_EMAM_EXCEPTION,gr5
+	movgs		gr5,isr
+
+	# clear power-saving mode flags
+	movsg		hsr0,gr4
+	andi		gr4,#~HSR0_PDM,gr4
+	movgs		gr4,hsr0
+
+	# multiplex again using old TBR as a guide
+	setlos.p	#TBR_TT,gr3
+	sethi		%hi(__entry_vector_table),gr6
+	and.p		gr20,gr3,gr5
+	setlo		%lo(__entry_vector_table),gr6
+	srli		gr5,#2,gr5
+	ld		@(gr5,gr6),gr5
+
+	LEDS		0x6009
+	jmpl		@(gr5,gr0)
+
+
+	.size		__entry_common,.-__entry_common
+
+###############################################################################
+#
+# handle instruction MMU fault
+#
+###############################################################################
+#ifdef CONFIG_MMU
+	.globl		__entry_insn_mmu_fault
+__entry_insn_mmu_fault:
+	LEDS		0x6010
+	setlos		#0,gr8
+	movsg		esr0,gr9
+	movsg		scr2,gr10
+
+	# now that we've accessed the exception regs, we can enable exceptions
+	movsg		psr,gr4
+	ori		gr4,#PSR_ET,gr4
+	movgs		gr4,psr
+
+	sethi.p		%hi(do_page_fault),gr5
+	setlo		%lo(do_page_fault),gr5
+	jmpl		@(gr5,gr0)	; call do_page_fault(0,esr0,ear0)
+#endif
+
+
+###############################################################################
+#
+# handle instruction access error
+#
+###############################################################################
+	.globl		__entry_insn_access_error
+__entry_insn_access_error:
+	LEDS		0x6011
+	sethi.p		%hi(insn_access_error),gr5
+	setlo		%lo(insn_access_error),gr5
+	movsg		esfr1,gr8
+	movsg		epcr0,gr9
+	movsg		esr0,gr10
+
+	# now that we've accessed the exception regs, we can enable exceptions
+	movsg		psr,gr4
+	ori		gr4,#PSR_ET,gr4
+	movgs		gr4,psr
+	jmpl		@(gr5,gr0)	; call insn_access_error(esfr1,epcr0,esr0)
+
+###############################################################################
+#
+# handle various instructions of dubious legality
+#
+###############################################################################
+	.globl		__entry_unsupported_trap
+	.globl		__entry_illegal_instruction
+	.globl		__entry_privileged_instruction
+	.globl		__entry_debug_exception
+__entry_unsupported_trap:
+	subi		gr21,#4,gr21
+	sti		gr21,@(gr28,#REG_PC)
+__entry_illegal_instruction:
+__entry_privileged_instruction:
+__entry_debug_exception:
+	LEDS		0x6012
+	sethi.p		%hi(illegal_instruction),gr5
+	setlo		%lo(illegal_instruction),gr5
+	movsg		esfr1,gr8
+	movsg		epcr0,gr9
+	movsg		esr0,gr10
+
+	# now that we've accessed the exception regs, we can enable exceptions
+	movsg		psr,gr4
+	ori		gr4,#PSR_ET,gr4
+	movgs		gr4,psr
+	jmpl		@(gr5,gr0)	; call ill_insn(esfr1,epcr0,esr0)
+
+###############################################################################
+#
+# handle media exception
+#
+###############################################################################
+	.globl		__entry_media_exception
+__entry_media_exception:
+	LEDS		0x6013
+	sethi.p		%hi(media_exception),gr5
+	setlo		%lo(media_exception),gr5
+	movsg		msr0,gr8
+	movsg		msr1,gr9
+
+	# now that we've accessed the exception regs, we can enable exceptions
+	movsg		psr,gr4
+	ori		gr4,#PSR_ET,gr4
+	movgs		gr4,psr
+	jmpl		@(gr5,gr0)	; call media_excep(msr0,msr1)
+
+###############################################################################
+#
+# handle data MMU fault
+# handle data DAT fault (write-protect exception)
+#
+###############################################################################
+#ifdef CONFIG_MMU
+	.globl		__entry_data_mmu_fault
+__entry_data_mmu_fault:
+	.globl		__entry_data_dat_fault
+__entry_data_dat_fault:
+	LEDS		0x6014
+	setlos		#1,gr8
+	movsg		esr0,gr9
+	movsg		scr2,gr10	; saved EAR0
+
+	# now that we've accessed the exception regs, we can enable exceptions
+	movsg		psr,gr4
+	ori		gr4,#PSR_ET,gr4
+	movgs		gr4,psr
+
+	sethi.p		%hi(do_page_fault),gr5
+	setlo		%lo(do_page_fault),gr5
+	jmpl		@(gr5,gr0)	; call do_page_fault(1,esr0,ear0)
+#endif
+
+###############################################################################
+#
+# handle data and instruction access exceptions
+#
+###############################################################################
+	.globl		__entry_insn_access_exception
+	.globl		__entry_data_access_exception
+__entry_insn_access_exception:
+__entry_data_access_exception:
+	LEDS		0x6016
+	sethi.p		%hi(memory_access_exception),gr5
+	setlo		%lo(memory_access_exception),gr5
+	movsg		esr0,gr8
+	movsg		scr2,gr9	; saved EAR0
+	movsg		epcr0,gr10
+
+	# now that we've accessed the exception regs, we can enable exceptions
+	movsg		psr,gr4
+	ori		gr4,#PSR_ET,gr4
+	movgs		gr4,psr
+	jmpl		@(gr5,gr0)	; call memory_access_error(esr0,ear0,epcr0)
+
+###############################################################################
+#
+# handle data access error
+#
+###############################################################################
+	.globl		__entry_data_access_error
+__entry_data_access_error:
+	LEDS		0x6016
+	sethi.p		%hi(data_access_error),gr5
+	setlo		%lo(data_access_error),gr5
+	movsg		esfr1,gr8
+	movsg		esr15,gr9
+	movsg		ear15,gr10
+
+	# now that we've accessed the exception regs, we can enable exceptions
+	movsg		psr,gr4
+	ori		gr4,#PSR_ET,gr4
+	movgs		gr4,psr
+	jmpl		@(gr5,gr0)	; call data_access_error(esfr1,esr15,ear15)
+
+###############################################################################
+#
+# handle data store error
+#
+###############################################################################
+	.globl		__entry_data_store_error
+__entry_data_store_error:
+	LEDS		0x6017
+	sethi.p		%hi(data_store_error),gr5
+	setlo		%lo(data_store_error),gr5
+	movsg		esfr1,gr8
+	movsg		esr14,gr9
+
+	# now that we've accessed the exception regs, we can enable exceptions
+	movsg		psr,gr4
+	ori		gr4,#PSR_ET,gr4
+	movgs		gr4,psr
+	jmpl		@(gr5,gr0)	; call data_store_error(esfr1,esr14)
+
+###############################################################################
+#
+# handle division exception
+#
+###############################################################################
+	.globl		__entry_division_exception
+__entry_division_exception:
+	LEDS		0x6018
+	sethi.p		%hi(division_exception),gr5
+	setlo		%lo(division_exception),gr5
+	movsg		esfr1,gr8
+	movsg		esr0,gr9
+	movsg		isr,gr10
+
+	# now that we've accessed the exception regs, we can enable exceptions
+	movsg		psr,gr4
+	ori		gr4,#PSR_ET,gr4
+	movgs		gr4,psr
+	jmpl		@(gr5,gr0)	; call div_excep(esfr1,esr0,isr)
+
+###############################################################################
+#
+# handle compound exception
+#
+###############################################################################
+	.globl		__entry_compound_exception
+__entry_compound_exception:
+	LEDS		0x6019
+	sethi.p		%hi(compound_exception),gr5
+	setlo		%lo(compound_exception),gr5
+	movsg		esfr1,gr8
+	movsg		esr0,gr9
+	movsg		esr14,gr10
+	movsg		esr15,gr11
+	movsg		msr0,gr12
+	movsg		msr1,gr13
+
+	# now that we've accessed the exception regs, we can enable exceptions
+	movsg		psr,gr4
+	ori		gr4,#PSR_ET,gr4
+	movgs		gr4,psr
+	jmpl		@(gr5,gr0)	; call comp_excep(esfr1,esr0,esr14,esr15,msr0,msr1)
+
+###############################################################################
+#
+# handle interrupts and NMIs
+#
+###############################################################################
+	.globl		__entry_do_IRQ
+__entry_do_IRQ:
+	LEDS		0x6020
+
+	# we can enable exceptions
+	movsg		psr,gr4
+	ori		gr4,#PSR_ET,gr4
+	movgs		gr4,psr
+	bra		do_IRQ
+
+	.globl		__entry_do_NMI
+__entry_do_NMI:
+	LEDS		0x6021
+
+	# we can enable exceptions
+	movsg		psr,gr4
+	ori		gr4,#PSR_ET,gr4
+	movgs		gr4,psr
+	bra		do_NMI
+
+###############################################################################
+#
+# the return path for a newly forked child process
+# - __switch_to() saved the old current pointer in GR27 for us
+#
+###############################################################################
+	.globl		ret_from_fork
+ret_from_fork:
+	LEDS		0x6100
+	ori.p		gr27,0,gr8
+	call		schedule_tail
+
+	# fork & co. return 0 to child
+	setlos.p	#0,gr8
+	bra		__syscall_exit
+
+###################################################################################################
+#
+# Return to user mode is not as complex as all this looks,
+# but we want the default path for a system call return to
+# go as quickly as possible which is why some of this is
+# less clear than it otherwise should be.
+#
+###################################################################################################
+	.balign		L1_CACHE_BYTES
+	.globl		system_call
+system_call:
+	LEDS		0x6101
+	movsg		psr,gr4			; enable exceptions
+	ori		gr4,#PSR_ET,gr4
+	movgs		gr4,psr
+
+	sti		gr7,@(gr28,#REG_SYSCALLNO)
+	sti.p		gr8,@(gr28,#REG_ORIG_GR8)
+
+	subicc		gr7,#nr_syscalls,gr0,icc0
+	bnc		icc0,#0,__syscall_badsys
+
+	ldi		@(gr15,#TI_FLAGS),gr4
+	ori		gr4,#_TIF_SYSCALL_TRACE,gr4
+	andicc		gr4,#_TIF_SYSCALL_TRACE,gr0,icc0
+	bne		icc0,#0,__syscall_trace_entry
+	bra		__syscall_trace_entry
+
+__syscall_call:
+	slli.p		gr7,#2,gr7
+	sethi		%hi(sys_call_table),gr5
+	setlo		%lo(sys_call_table),gr5
+	ld		@(gr5,gr7),gr4
+	calll		@(gr4,gr0)
+
+
+###############################################################################
+#
+# return to interrupted process
+#
+###############################################################################
+__syscall_exit:
+	LEDS		0x6300
+
+	sti		gr8,@(gr28,#REG_GR(8))	; save return value
+
+	# rebuild saved psr - execve will change it for init/main.c
+	ldi		@(gr28,#REG_PSR),gr22
+	srli		gr22,#1,gr5
+	andi.p		gr22,#~PSR_PS,gr22
+	andi		gr5,#PSR_PS,gr5
+	or		gr5,gr22,gr22
+	ori		gr22,#PSR_S,gr22
+
+	# keep current PSR in GR23
+	movsg		psr,gr23
+
+	# make sure we don't miss an interrupt setting need_resched or sigpending between
+	# sampling and the RETT
+	ori		gr23,#PSR_PIL_14,gr23
+	movgs		gr23,psr
+
+	ldi		@(gr15,#TI_FLAGS),gr4
+//	ori		gr4,#_TIF_SYSCALL_TRACE,gr4		/////////////////////////////////
+	sethi.p		%hi(_TIF_ALLWORK_MASK),gr5
+	setlo		%lo(_TIF_ALLWORK_MASK),gr5
+	andcc		gr4,gr5,gr0,icc0
+	bne		icc0,#0,__syscall_exit_work
+
+	# restore all registers and return
+__entry_return_direct:
+	LEDS		0x6301
+
+	andi		gr22,#~PSR_ET,gr22
+	movgs		gr22,psr
+
+	ldi		@(gr28,#REG_ISR),gr23
+	lddi		@(gr28,#REG_CCR),gr24
+	lddi		@(gr28,#REG_LR) ,gr26
+	ldi		@(gr28,#REG_PC) ,gr21
+	ldi		@(gr28,#REG_TBR),gr20
+
+	movgs		gr20,tbr
+	movgs		gr21,pcsr
+	movgs		gr23,isr
+	movgs		gr24,ccr
+	movgs		gr25,cccr
+	movgs		gr26,lr
+	movgs		gr27,lcr
+
+	lddi		@(gr28,#REG_GNER0),gr4
+	movgs		gr4,gner0
+	movgs		gr5,gner1
+
+	lddi		@(gr28,#REG_IACC0),gr4
+	movgs		gr4,iacc0h
+	movgs		gr5,iacc0l
+
+	lddi		@(gr28,#REG_GR(4)) ,gr4
+	lddi		@(gr28,#REG_GR(6)) ,gr6
+	lddi		@(gr28,#REG_GR(8)) ,gr8
+	lddi		@(gr28,#REG_GR(10)),gr10
+	lddi		@(gr28,#REG_GR(12)),gr12
+	lddi		@(gr28,#REG_GR(14)),gr14
+	lddi		@(gr28,#REG_GR(16)),gr16
+	lddi		@(gr28,#REG_GR(18)),gr18
+	lddi		@(gr28,#REG_GR(20)),gr20
+	lddi		@(gr28,#REG_GR(22)),gr22
+	lddi		@(gr28,#REG_GR(24)),gr24
+	lddi		@(gr28,#REG_GR(26)),gr26
+	ldi		@(gr28,#REG_GR(29)),gr29
+	lddi		@(gr28,#REG_GR(30)),gr30
+
+	# check to see if a debugging return is required
+	LEDS		0x67f0
+	movsg		ccr,gr2
+	ldi		@(gr28,#REG__STATUS),gr3
+	andicc		gr3,#REG__STATUS_STEP,gr0,icc0
+	bne		icc0,#0,__entry_return_singlestep
+	movgs		gr2,ccr
+
+	ldi		@(gr28,#REG_SP)    ,sp
+	lddi		@(gr28,#REG_GR(2)) ,gr2
+	ldi		@(gr28,#REG_GR(28)),gr28
+
+	LEDS		0x67fe
+//	movsg		pcsr,gr31
+//	LEDS32
+
+#if 0
+	# store the current frame in the workram on the FR451
+	movgs		gr28,scr2
+	sethi.p		%hi(0xfe800000),gr28
+	setlo		%lo(0xfe800000),gr28
+
+	stdi		gr2,@(gr28,#REG_GR(2))
+	stdi		gr4,@(gr28,#REG_GR(4))
+	stdi		gr6,@(gr28,#REG_GR(6))
+	stdi		gr8,@(gr28,#REG_GR(8))
+	stdi		gr10,@(gr28,#REG_GR(10))
+	stdi		gr12,@(gr28,#REG_GR(12))
+	stdi		gr14,@(gr28,#REG_GR(14))
+	stdi		gr16,@(gr28,#REG_GR(16))
+	stdi		gr18,@(gr28,#REG_GR(18))
+	stdi		gr24,@(gr28,#REG_GR(24))
+	stdi		gr26,@(gr28,#REG_GR(26))
+	sti		gr29,@(gr28,#REG_GR(29))
+	stdi		gr30,@(gr28,#REG_GR(30))
+
+	movsg		tbr ,gr30
+	sti		gr30,@(gr28,#REG_TBR)
+	movsg		pcsr,gr30
+	sti		gr30,@(gr28,#REG_PC)
+	movsg		psr ,gr30
+	sti		gr30,@(gr28,#REG_PSR)
+	movsg		isr ,gr30
+	sti		gr30,@(gr28,#REG_ISR)
+	movsg		ccr ,gr30
+	movsg		cccr,gr31
+	stdi		gr30,@(gr28,#REG_CCR)
+	movsg		lr  ,gr30
+	movsg		lcr ,gr31
+	stdi		gr30,@(gr28,#REG_LR)
+	sti		gr0 ,@(gr28,#REG_SYSCALLNO)
+	movsg		scr2,gr28
+#endif
+
+	rett		#0
+
+	# return via break.S
+__entry_return_singlestep:
+	movgs		gr2,ccr
+	lddi		@(gr28,#REG_GR(2)) ,gr2
+	ldi		@(gr28,#REG_SP)    ,sp
+	ldi		@(gr28,#REG_GR(28)),gr28
+	LEDS		0x67ff
+	break
+	.globl		__entry_return_singlestep_breaks_here
+__entry_return_singlestep_breaks_here:
+	nop
+
+
+###############################################################################
+#
+# return to a process interrupted in kernel space
+# - we need to consider preemption if that is enabled
+#
+###############################################################################
+	.balign		L1_CACHE_BYTES
+__entry_return_from_kernel_exception:
+	LEDS		0x6302
+	movsg		psr,gr23
+	ori		gr23,#PSR_PIL_14,gr23
+	movgs		gr23,psr
+	bra		__entry_return_direct
+
+	.balign		L1_CACHE_BYTES
+__entry_return_from_kernel_interrupt:
+	LEDS		0x6303
+	movsg		psr,gr23
+	ori		gr23,#PSR_PIL_14,gr23
+	movgs		gr23,psr
+
+#ifdef CONFIG_PREEMPT
+	ldi		@(gr15,#TI_PRE_COUNT),gr5
+	subicc		gr5,#0,gr0,icc0
+	beq		icc0,#0,__entry_return_direct
+
+__entry_preempt_need_resched:
+	ldi		@(gr15,#TI_FLAGS),gr4
+	andicc		gr4,#_TIF_NEED_RESCHED,gr0,icc0
+	beq		icc0,#1,__entry_return_direct
+
+	setlos		#PREEMPT_ACTIVE,gr5
+	sti		gr5,@(gr15,#TI_FLAGS)
+
+	andi		gr23,#~PSR_PIL,gr23
+	movgs		gr23,psr
+
+	call		schedule
+	sti		gr0,@(gr15,#TI_PRE_COUNT)
+
+	movsg		psr,gr23
+	ori		gr23,#PSR_PIL_14,gr23
+	movgs		gr23,psr
+	bra		__entry_preempt_need_resched
+#else
+	bra		__entry_return_direct
+#endif
+
+
+###############################################################################
+#
+# perform work that needs to be done immediately before resumption
+#
+###############################################################################
+	.balign		L1_CACHE_BYTES
+__entry_return_from_user_exception:
+	LEDS		0x6501
+
+__entry_resume_userspace:
+	# make sure we don't miss an interrupt setting need_resched or sigpending between
+	# sampling and the RETT
+	movsg		psr,gr23
+	ori		gr23,#PSR_PIL_14,gr23
+	movgs		gr23,psr
+
+__entry_return_from_user_interrupt:
+	LEDS		0x6402
+	ldi		@(gr15,#TI_FLAGS),gr4
+	sethi.p		%hi(_TIF_WORK_MASK),gr5
+	setlo		%lo(_TIF_WORK_MASK),gr5
+	andcc		gr4,gr5,gr0,icc0
+	beq		icc0,#1,__entry_return_direct
+
+__entry_work_pending:
+	LEDS		0x6404
+	andicc		gr4,#_TIF_NEED_RESCHED,gr0,icc0
+	beq		icc0,#1,__entry_work_notifysig
+
+__entry_work_resched:
+	LEDS		0x6408
+	movsg		psr,gr23
+	andi		gr23,#~PSR_PIL,gr23
+	movgs		gr23,psr
+	call		schedule
+	movsg		psr,gr23
+	ori		gr23,#PSR_PIL_14,gr23
+	movgs		gr23,psr
+
+	LEDS		0x6401
+	ldi		@(gr15,#TI_FLAGS),gr4
+	sethi.p		%hi(_TIF_WORK_MASK),gr5
+	setlo		%lo(_TIF_WORK_MASK),gr5
+	andcc		gr4,gr5,gr0,icc0
+	beq		icc0,#1,__entry_return_direct
+	andicc		gr4,#_TIF_NEED_RESCHED,gr0,icc0
+	bne		icc0,#1,__entry_work_resched
+
+ __entry_work_notifysig:
+	LEDS		0x6410
+	ori.p		gr4,#0,gr8
+	call		do_notify_resume
+	bra		__entry_return_direct
+
+	# perform syscall entry tracing
+__syscall_trace_entry:
+	LEDS		0x6320
+	setlos.p	#0,gr8
+	call		do_syscall_trace
+
+	ldi		@(gr28,#REG_SYSCALLNO),gr7
+	lddi		@(gr28,#REG_GR(8)) ,gr8
+	lddi		@(gr28,#REG_GR(10)),gr10
+	lddi.p		@(gr28,#REG_GR(12)),gr12
+
+	subicc		gr7,#nr_syscalls,gr0,icc0
+	bnc		icc0,#0,__syscall_badsys
+	bra		__syscall_call
+
+	# perform syscall exit tracing
+__syscall_exit_work:
+	LEDS		0x6340
+	andicc		gr4,#_TIF_SYSCALL_TRACE,gr0,icc0
+	beq		icc0,#1,__entry_work_pending
+
+	movsg		psr,gr23
+	andi		gr23,#~PSR_PIL,gr23	; could let do_syscall_trace() call schedule()
+	movgs		gr23,psr
+
+	setlos.p	#1,gr8
+	call		do_syscall_trace
+	bra		__entry_resume_userspace
+
+__syscall_badsys:
+	LEDS		0x6380
+	setlos		#-ENOSYS,gr8
+	sti		gr8,@(gr28,#REG_GR(8))	; save return value
+	bra		__entry_resume_userspace
+
+
+###############################################################################
+#
+# syscall vector table
+#
+###############################################################################
+#ifdef CONFIG_MMU
+#define __MMU(X) X
+#else
+#define __MMU(X) sys_ni_syscall
+#endif
+
+	.section .rodata
+ALIGN
+	.globl		sys_call_table
+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_lchown16
+	.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_ni_syscall // 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_ni_syscall // 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			/* old old uname 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_ni_syscall // sys_sgetmask
+	.long sys_ni_syscall // sys_ssetmask
+	.long sys_setreuid16	/* 70 */
+	.long sys_setregid16
+	.long sys_sigsuspend
+	.long sys_ni_syscall // sys_sigpending
+	.long sys_sethostname
+	.long sys_setrlimit	/* 75 */
+	.long sys_ni_syscall // sys_old_getrlimit
+	.long sys_getrusage
+	.long sys_gettimeofday
+	.long sys_settimeofday
+	.long sys_getgroups16	/* 80 */
+	.long sys_setgroups16
+	.long sys_ni_syscall			/* old_select slot */
+	.long sys_symlink
+	.long sys_lstat
+	.long sys_readlink		/* 85 */
+	.long sys_uselib
+	.long sys_swapon
+	.long sys_reboot
+	.long sys_ni_syscall // old_readdir
+	.long sys_ni_syscall	/* 90 */	/* old_mmap slot */
+	.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	/* obsolete olduname( syscall */
+	.long sys_ni_syscall	/* iopl for i386 */ /* 110 */
+	.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_ni_syscall	/* old "cacheflush" */
+	.long sys_adjtimex
+	.long __MMU(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	/* 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 __MMU(sys_msync)
+	.long sys_readv		/* 145 */
+	.long sys_writev
+	.long sys_getsid
+	.long sys_fdatasync
+	.long sys_sysctl
+	.long __MMU(sys_mlock)		/* 150 */
+	.long __MMU(sys_munlock)
+	.long __MMU(sys_mlockall)
+	.long __MMU(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 __MMU(sys_mremap)
+	.long sys_setresuid16
+	.long sys_getresuid16	/* 165 */
+	.long sys_ni_syscall	/* for vm86 */
+	.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_chown16
+	.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_lchown
+	.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_chown
+	.long sys_setuid
+	.long sys_setgid
+	.long sys_setfsuid		/* 215 */
+	.long sys_setfsgid
+	.long sys_pivot_root
+	.long __MMU(sys_mincore)
+	.long __MMU(sys_madvise)
+	.long sys_getdents64	/* 220 */
+	.long sys_fcntl64
+	.long sys_ni_syscall	/* reserved for TUX */
+	.long sys_ni_syscall	/* Reserved for Security */
+	.long sys_gettid
+	.long sys_readahead	/* 225 */
+	.long sys_setxattr
+	.long sys_lsetxattr
+	.long sys_fsetxattr
+	.long sys_getxattr
+	.long sys_lgetxattr	/* 230 */
+	.long sys_fgetxattr
+	.long sys_listxattr
+	.long sys_llistxattr
+	.long sys_flistxattr
+	.long sys_removexattr	/* 235 */
+	.long sys_lremovexattr
+	.long sys_fremovexattr
+ 	.long sys_tkill
+	.long sys_sendfile64
+	.long sys_futex		/* 240 */
+	.long sys_sched_setaffinity
+	.long sys_sched_getaffinity
+	.long sys_ni_syscall	//sys_set_thread_area
+	.long sys_ni_syscall	//sys_get_thread_area
+	.long sys_io_setup	/* 245 */
+	.long sys_io_destroy
+	.long sys_io_getevents
+	.long sys_io_submit
+	.long sys_io_cancel
+	.long sys_fadvise64	/* 250 */
+	.long sys_ni_syscall
+	.long sys_exit_group
+	.long sys_lookup_dcookie
+	.long sys_epoll_create
+	.long sys_epoll_ctl	/* 255 */
+	.long sys_epoll_wait
+ 	.long __MMU(sys_remap_file_pages)
+ 	.long sys_ni_syscall	//sys_set_tid_address
+ 	.long sys_timer_create
+ 	.long sys_timer_settime		/* 260 */
+ 	.long sys_timer_gettime
+ 	.long sys_timer_getoverrun
+ 	.long sys_timer_delete
+ 	.long sys_clock_settime
+ 	.long sys_clock_gettime		/* 265 */
+ 	.long sys_clock_getres
+ 	.long sys_clock_nanosleep
+	.long sys_statfs64
+	.long sys_fstatfs64
+	.long sys_tgkill	/* 270 */
+	.long sys_utimes
+ 	.long sys_fadvise64_64
+	.long sys_ni_syscall	/* sys_vserver */
+	.long sys_mbind
+	.long sys_get_mempolicy
+	.long sys_set_mempolicy
+	.long sys_mq_open
+	.long sys_mq_unlink
+	.long sys_mq_timedsend
+	.long sys_mq_timedreceive	/* 280 */
+	.long sys_mq_notify
+	.long sys_mq_getsetattr
+	.long sys_ni_syscall		/* reserved for kexec */
+
+
+syscall_table_size = (. - sys_call_table)
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/kernel/entry-table.S linux-2.6.10-rc1-mm3-frv/arch/frv/kernel/entry-table.S
--- /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/kernel/entry-table.S	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/arch/frv/kernel/entry-table.S	2004-11-05 14:13:03.079565365 +0000
@@ -0,0 +1,277 @@
+/* entry-table.S: main trap vector tables and exception jump table
+ *
+ * Copyright (C) 2003 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * 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.
+ *
+ */
+
+#include <linux/sys.h>
+#include <linux/config.h>
+#include <linux/linkage.h>
+#include <asm/spr-regs.h>
+
+###############################################################################
+#
+# declare the main trap and vector tables
+#
+# - the first instruction in each slot is a branch to the appropriate
+#   kernel-mode handler routine
+#
+# - the second instruction in each slot is a branch to the debug-mode hardware
+#   single-step bypass handler - this is called from break.S to deal with the
+#   CPU stepping in to exception handlers (particular where external interrupts
+#   are concerned)
+#
+# - the linker script places the user mode and kernel mode trap tables on to
+#   the same 8Kb page, so that break.S can be more efficient when performing
+#   single-step bypass management
+#
+###############################################################################
+
+	# trap table for entry from debug mode
+	.section	.trap.break,"ax"
+	.balign		256*16
+	.globl		__entry_breaktrap_table
+__entry_breaktrap_table:
+
+	# trap table for entry from user mode
+	.section	.trap.user,"ax"
+	.balign		256*16
+	.globl		__entry_usertrap_table
+__entry_usertrap_table:
+
+	# trap table for entry from kernel mode
+	.section	.trap.kernel,"ax"
+	.balign		256*16
+	.globl		__entry_kerneltrap_table
+__entry_kerneltrap_table:
+
+	# exception handler jump table
+	.section	.trap.vector,"ax"
+	.balign		256*4
+	.globl		__entry_vector_table
+__entry_vector_table:
+
+	# trap fixup table for single-stepping in user mode
+	.section	.trap.fixup.user,"a"
+	.balign		256*4
+	.globl		__break_usertrap_fixup_table
+__break_usertrap_fixup_table:
+
+	# trap fixup table for single-stepping in user mode
+	.section	.trap.fixup.kernel,"a"
+	.balign		256*4
+	.globl		__break_kerneltrap_fixup_table
+__break_kerneltrap_fixup_table:
+
+	# handler declaration for a sofware or program interrupt
+.macro VECTOR_SOFTPROG tbr_tt, vec
+	.section .trap.user
+	.org		\tbr_tt
+	bra		__entry_uspace_softprog_interrupt
+	.section .trap.fixup.user
+	.org		\tbr_tt >> 2
+	.long		__break_step_uspace_softprog_interrupt
+	.section .trap.kernel
+	.org		\tbr_tt
+	bra		__entry_kernel_softprog_interrupt
+	.section .trap.fixup.kernel
+	.org		\tbr_tt >> 2
+	.long		__break_step_kernel_softprog_interrupt
+	.section .trap.vector
+	.org		\tbr_tt >> 2
+	.long		\vec
+.endm
+
+	# handler declaration for a maskable external interrupt
+.macro VECTOR_IRQ tbr_tt, vec
+	.section .trap.user
+	.org		\tbr_tt
+	bra		__entry_uspace_external_interrupt
+	.section .trap.fixup.user
+	.org		\tbr_tt >> 2
+	.long		__break_step_uspace_external_interrupt
+	.section .trap.kernel
+	.org		\tbr_tt
+	bra		__entry_kernel_external_interrupt
+	.section .trap.fixup.kernel
+	.org		\tbr_tt >> 2
+	.long		__break_step_kernel_external_interrupt
+	.section .trap.vector
+	.org		\tbr_tt >> 2
+	.long		\vec
+.endm
+
+	# handler declaration for an NMI external interrupt
+.macro VECTOR_NMI tbr_tt, vec
+	.section .trap.user
+	.org		\tbr_tt
+	break
+	break
+	break
+	break
+	.section .trap.kernel
+	.org		\tbr_tt
+	break
+	break
+	break
+	break
+	.section .trap.vector
+	.org		\tbr_tt >> 2
+	.long		\vec
+.endm
+
+	# handler declaration for an MMU only sofware or program interrupt
+.macro VECTOR_SP_MMU tbr_tt, vec
+#ifdef CONFIG_MMU
+ 	VECTOR_SOFTPROG	\tbr_tt, \vec
+#else
+	VECTOR_NMI	\tbr_tt, 0
+#endif
+.endm
+
+
+###############################################################################
+#
+# specification of the vectors
+# - note: each macro inserts code into multiple sections
+#
+###############################################################################
+	VECTOR_SP_MMU	TBR_TT_INSTR_MMU_MISS,	__entry_insn_mmu_miss
+	VECTOR_SOFTPROG	TBR_TT_INSTR_ACC_ERROR,	__entry_insn_access_error
+	VECTOR_SOFTPROG	TBR_TT_INSTR_ACC_EXCEP,	__entry_insn_access_exception
+	VECTOR_SOFTPROG	TBR_TT_PRIV_INSTR,	__entry_privileged_instruction
+	VECTOR_SOFTPROG	TBR_TT_ILLEGAL_INSTR,	__entry_illegal_instruction
+	VECTOR_SOFTPROG	TBR_TT_FP_EXCEPTION,	__entry_media_exception
+	VECTOR_SOFTPROG	TBR_TT_MP_EXCEPTION,	__entry_media_exception
+	VECTOR_SOFTPROG	TBR_TT_DATA_ACC_ERROR,	__entry_data_access_error
+	VECTOR_SP_MMU	TBR_TT_DATA_MMU_MISS,	__entry_data_mmu_miss
+	VECTOR_SOFTPROG	TBR_TT_DATA_ACC_EXCEP,	__entry_data_access_exception
+	VECTOR_SOFTPROG	TBR_TT_DATA_STR_ERROR,	__entry_data_store_error
+	VECTOR_SOFTPROG	TBR_TT_DIVISION_EXCEP,	__entry_division_exception
+
+#ifdef CONFIG_MMU
+	.section .trap.user
+	.org		TBR_TT_INSTR_TLB_MISS
+	.globl		__trap_user_insn_tlb_miss
+__trap_user_insn_tlb_miss:
+	movsg		ear0,gr28			/* faulting address */
+	movsg		scr0,gr31			/* get mapped PTD coverage start address */
+	xor.p		gr28,gr31,gr31			/* compare addresses */
+	bra		__entry_user_insn_tlb_miss
+
+	.org		TBR_TT_DATA_TLB_MISS
+	.globl		__trap_user_data_tlb_miss
+__trap_user_data_tlb_miss:
+	movsg		ear0,gr28			/* faulting address */
+	movsg		scr1,gr31			/* get mapped PTD coverage start address */
+	xor.p		gr28,gr31,gr31			/* compare addresses */
+	bra		__entry_user_data_tlb_miss
+
+	.section .trap.kernel
+	.org		TBR_TT_INSTR_TLB_MISS
+	.globl		__trap_kernel_insn_tlb_miss
+__trap_kernel_insn_tlb_miss:
+	movsg		ear0,gr29			/* faulting address */
+	movsg		scr0,gr31			/* get mapped PTD coverage start address */
+	xor.p		gr29,gr31,gr31			/* compare addresses */
+	bra		__entry_kernel_insn_tlb_miss
+
+	.org		TBR_TT_DATA_TLB_MISS
+	.globl		__trap_kernel_data_tlb_miss
+__trap_kernel_data_tlb_miss:
+	movsg		ear0,gr29			/* faulting address */
+	movsg		scr1,gr31			/* get mapped PTD coverage start address */
+	xor.p		gr29,gr31,gr31			/* compare addresses */
+	bra		__entry_kernel_data_tlb_miss
+
+	.section .trap.fixup.user
+	.org		TBR_TT_INSTR_TLB_MISS >> 2
+	.globl		__trap_fixup_user_insn_tlb_miss
+__trap_fixup_user_insn_tlb_miss:
+	.long		__break_user_insn_tlb_miss
+	.org		TBR_TT_DATA_TLB_MISS >> 2
+	.globl		__trap_fixup_user_data_tlb_miss
+__trap_fixup_user_data_tlb_miss:
+	.long		__break_user_data_tlb_miss
+
+	.section .trap.fixup.kernel
+	.org		TBR_TT_INSTR_TLB_MISS >> 2
+	.globl		__trap_fixup_kernel_insn_tlb_miss
+__trap_fixup_kernel_insn_tlb_miss:
+	.long		__break_kernel_insn_tlb_miss
+	.org		TBR_TT_DATA_TLB_MISS >> 2
+	.globl		__trap_fixup_kernel_data_tlb_miss
+__trap_fixup_kernel_data_tlb_miss:
+	.long		__break_kernel_data_tlb_miss
+	
+	.section .trap.vector
+	.org		TBR_TT_INSTR_TLB_MISS >> 2
+	.long		__entry_insn_mmu_fault
+	.org		TBR_TT_DATA_TLB_MISS >> 2
+	.long		__entry_data_mmu_fault
+#endif
+
+	VECTOR_SP_MMU	TBR_TT_DATA_DAT_EXCEP,	__entry_data_dat_fault
+	VECTOR_NMI	TBR_TT_DECREMENT_TIMER,	__entry_do_NMI
+	VECTOR_SOFTPROG	TBR_TT_COMPOUND_EXCEP,	__entry_compound_exception
+	VECTOR_IRQ	TBR_TT_INTERRUPT_1,	__entry_do_IRQ
+	VECTOR_IRQ	TBR_TT_INTERRUPT_2,	__entry_do_IRQ
+	VECTOR_IRQ	TBR_TT_INTERRUPT_3,	__entry_do_IRQ
+	VECTOR_IRQ	TBR_TT_INTERRUPT_4,	__entry_do_IRQ
+	VECTOR_IRQ	TBR_TT_INTERRUPT_5,	__entry_do_IRQ
+	VECTOR_IRQ	TBR_TT_INTERRUPT_6,	__entry_do_IRQ
+	VECTOR_IRQ	TBR_TT_INTERRUPT_7,	__entry_do_IRQ
+	VECTOR_IRQ	TBR_TT_INTERRUPT_8,	__entry_do_IRQ
+	VECTOR_IRQ	TBR_TT_INTERRUPT_9,	__entry_do_IRQ
+	VECTOR_IRQ	TBR_TT_INTERRUPT_10,	__entry_do_IRQ
+	VECTOR_IRQ	TBR_TT_INTERRUPT_11,	__entry_do_IRQ
+	VECTOR_IRQ	TBR_TT_INTERRUPT_12,	__entry_do_IRQ
+	VECTOR_IRQ	TBR_TT_INTERRUPT_13,	__entry_do_IRQ
+	VECTOR_IRQ	TBR_TT_INTERRUPT_14,	__entry_do_IRQ
+	VECTOR_NMI	TBR_TT_INTERRUPT_15,	__entry_do_NMI
+
+	# miscellaneous user mode entry points
+	.section	.trap.user
+	.org		TBR_TT_TRAP0
+	.rept		127
+	bra		__entry_uspace_softprog_interrupt
+	bra		__break_step_uspace_softprog_interrupt
+	.long		0,0
+	.endr
+	.org		TBR_TT_BREAK
+	bra		__entry_break
+	.long		0,0,0
+
+	# miscellaneous kernel mode entry points
+	.section	.trap.kernel
+	.org		TBR_TT_TRAP0
+	.rept		127
+	bra		__entry_kernel_softprog_interrupt
+	bra		__break_step_kernel_softprog_interrupt
+	.long		0,0
+	.endr
+	.org		TBR_TT_BREAK
+	bra		__entry_break
+	.long		0,0,0
+
+	# miscellaneous debug mode entry points
+	.section	.trap.break
+	.org		TBR_TT_BREAK
+	movsg		bpcsr,gr30
+	jmpl		@(gr30,gr0)
+
+	# miscellaneous vectors
+	.section	.trap.vector
+	.org		TBR_TT_TRAP0 >> 2
+	.long		system_call
+	.rept		126
+	.long		__entry_unsupported_trap
+	.endr
+	.org		TBR_TT_BREAK >> 2
+	.long		__entry_debug_exception

^ permalink raw reply	[flat|nested] 87+ messages in thread

* [PATCH 6/20] FRV: Fujitsu FR-V CPU arch implementation part 4
  2004-11-08 14:34 [PATCH 1/20] FRV: Fujitsu FR-V CPU arch maintainer record dhowells
  2004-11-08 14:34 ` [PATCH 2/20] FRV: Fujitsu FR-V arch documentation dhowells
@ 2004-11-08 14:34 ` dhowells
  2004-11-08 14:34 ` [PATCH 4/20] FRV: Fujitsu FR-V CPU arch implementation part 2 dhowells
                   ` (14 subsequent siblings)
  16 siblings, 0 replies; 87+ messages in thread
From: dhowells @ 2004-11-08 14:34 UTC (permalink / raw)
  To: torvalds, akpm, davidm; +Cc: linux-kernel, uclinux-dev

The attached patches provides part 4 of an architecture implementation
for the Fujitsu FR-V CPU series, configurably as Linux or uClinux.

Signed-Off-By: dhowells@redhat.com
---
diffstat frv-arch_4-2610rc1mm3.diff
 Makefile        |   22 +
 head-uc-fr401.S |  311 ++++++++++++++++++++++
 head-uc-fr451.S |  174 ++++++++++++
 head-uc-fr555.S |  347 +++++++++++++++++++++++++
 init_task.c     |   39 ++
 irq-mb93091.c   |  116 ++++++++
 irq-mb93093.c   |   99 +++++++
 irq-mb93493.c   |  108 +++++++
 irq-routing.c   |  291 +++++++++++++++++++++
 irq.c           |  764 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 kernel_thread.S |   77 +++++
 local.h         |   56 ++++
 pm-mb93093.c    |   66 ++++
 pm.c            |  432 +++++++++++++++++++++++++++++++
 process.c       |  384 ++++++++++++++++++++++++++++
 15 files changed, 3286 insertions(+)

diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/kernel/head-uc-fr401.S linux-2.6.10-rc1-mm3-frv/arch/frv/kernel/head-uc-fr401.S
--- /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/kernel/head-uc-fr401.S	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/arch/frv/kernel/head-uc-fr401.S	2004-11-05 14:13:03.000000000 +0000
@@ -0,0 +1,311 @@
+/* head-uc-fr401.S: FR401/3/5 uc-linux specific bits of initialisation
+ *
+ * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * 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.
+ */
+
+#include <linux/config.h>
+#include <linux/threads.h>
+#include <linux/linkage.h>
+#include <asm/ptrace.h>
+#include <asm/page.h>
+#include <asm/spr-regs.h>
+#include <asm/mb86943a.h>
+#include "head.inc"
+
+
+#define __400_DBR0	0xfe000e00
+#define __400_DBR1	0xfe000e08
+#define __400_DBR2	0xfe000e10	/* not on FR401 */
+#define __400_DBR3	0xfe000e18	/* not on FR401 */
+#define __400_DAM0	0xfe000f00
+#define __400_DAM1	0xfe000f08
+#define __400_DAM2	0xfe000f10	/* not on FR401 */
+#define __400_DAM3	0xfe000f18	/* not on FR401 */
+#define __400_LGCR	0xfe000010
+#define __400_LCR	0xfe000100
+#define __400_LSBR	0xfe000c00
+
+	.section	.text.init,"ax"
+	.balign		4
+
+###############################################################################
+#
+# describe the position and layout of the SDRAM controller registers
+#
+#	ENTRY:			EXIT:
+# GR5	-			cacheline size
+# GR11	-			displacement of 2nd SDRAM addr reg from GR14
+# GR12	-			displacement of 3rd SDRAM addr reg from GR14
+# GR13	-			displacement of 4th SDRAM addr reg from GR14
+# GR14	-			address of 1st SDRAM addr reg
+# GR15	-			amount to shift address by to match SDRAM addr reg
+# GR26	&__head_reference	[saved]
+# GR30	LED address		[saved]
+# CC0	-			T if DBR0 is present
+# CC1	-			T if DBR1 is present
+# CC2	-			T if DBR2 is present (not FR401/FR401A)
+# CC3	-			T if DBR3 is present (not FR401/FR401A)
+#
+###############################################################################
+	.globl		__head_fr401_describe_sdram
+__head_fr401_describe_sdram:
+	sethi.p		%hi(__400_DBR0),gr14
+	setlo		%lo(__400_DBR0),gr14
+	setlos.p	#__400_DBR1-__400_DBR0,gr11
+	setlos		#__400_DBR2-__400_DBR0,gr12
+	setlos.p	#__400_DBR3-__400_DBR0,gr13
+	setlos		#32,gr5			; cacheline size
+	setlos.p	#0,gr15			; amount to shift addr reg by
+
+	# specify which DBR regs are present
+	setlos		#0x00ff,gr4
+	movgs		gr4,cccr
+	movsg		psr,gr3			; check for FR401/FR401A
+	srli		gr3,#25,gr3
+	subicc		gr3,#0x20>>1,gr0,icc0
+	bnelr		icc0,#1
+	setlos		#0x000f,gr4
+	movgs		gr4,cccr
+	bralr
+
+###############################################################################
+#
+# rearrange the bus controller registers
+#
+#	ENTRY:			EXIT:
+# GR26	&__head_reference	[saved]
+# GR30	LED address		revised LED address
+#
+###############################################################################
+	.globl		__head_fr401_set_busctl
+__head_fr401_set_busctl:
+	sethi.p		%hi(__400_LGCR),gr4
+	setlo		%lo(__400_LGCR),gr4
+	sethi.p		%hi(__400_LSBR),gr10
+	setlo		%lo(__400_LSBR),gr10
+	sethi.p		%hi(__400_LCR),gr11
+	setlo		%lo(__400_LCR),gr11
+
+	# set the bus controller
+	ldi		@(gr4,#0),gr5
+	ori		gr5,#0xff,gr5		; make sure all chip-selects are enabled
+	sti		gr5,@(gr4,#0)
+
+	sethi.p		%hi(__region_CS1),gr4
+	setlo		%lo(__region_CS1),gr4
+	sethi.p		%hi(__region_CS1_M),gr5
+	setlo		%lo(__region_CS1_M),gr5
+	sethi.p		%hi(__region_CS1_C),gr6
+	setlo		%lo(__region_CS1_C),gr6
+	sti		gr4,@(gr10,#1*0x08)
+	sti		gr5,@(gr10,#1*0x08+0x100)
+	sti		gr6,@(gr11,#1*0x08)
+	sethi.p		%hi(__region_CS2),gr4
+	setlo		%lo(__region_CS2),gr4
+	sethi.p		%hi(__region_CS2_M),gr5
+	setlo		%lo(__region_CS2_M),gr5
+	sethi.p		%hi(__region_CS2_C),gr6
+	setlo		%lo(__region_CS2_C),gr6
+	sti		gr4,@(gr10,#2*0x08)
+	sti		gr5,@(gr10,#2*0x08+0x100)
+	sti		gr6,@(gr11,#2*0x08)
+	sethi.p		%hi(__region_CS3),gr4
+	setlo		%lo(__region_CS3),gr4
+	sethi.p		%hi(__region_CS3_M),gr5
+	setlo		%lo(__region_CS3_M),gr5
+	sethi.p		%hi(__region_CS3_C),gr6
+	setlo		%lo(__region_CS3_C),gr6
+	sti		gr4,@(gr10,#3*0x08)
+	sti		gr5,@(gr10,#3*0x08+0x100)
+	sti		gr6,@(gr11,#3*0x08)
+	sethi.p		%hi(__region_CS4),gr4
+	setlo		%lo(__region_CS4),gr4
+	sethi.p		%hi(__region_CS4_M),gr5
+	setlo		%lo(__region_CS4_M),gr5
+	sethi.p		%hi(__region_CS4_C),gr6
+	setlo		%lo(__region_CS4_C),gr6
+	sti		gr4,@(gr10,#4*0x08)
+	sti		gr5,@(gr10,#4*0x08+0x100)
+	sti		gr6,@(gr11,#4*0x08)
+	sethi.p		%hi(__region_CS5),gr4
+	setlo		%lo(__region_CS5),gr4
+	sethi.p		%hi(__region_CS5_M),gr5
+	setlo		%lo(__region_CS5_M),gr5
+	sethi.p		%hi(__region_CS5_C),gr6
+	setlo		%lo(__region_CS5_C),gr6
+	sti		gr4,@(gr10,#5*0x08)
+	sti		gr5,@(gr10,#5*0x08+0x100)
+	sti		gr6,@(gr11,#5*0x08)
+	sethi.p		%hi(__region_CS6),gr4
+	setlo		%lo(__region_CS6),gr4
+	sethi.p		%hi(__region_CS6_M),gr5
+	setlo		%lo(__region_CS6_M),gr5
+	sethi.p		%hi(__region_CS6_C),gr6
+	setlo		%lo(__region_CS6_C),gr6
+	sti		gr4,@(gr10,#6*0x08)
+	sti		gr5,@(gr10,#6*0x08+0x100)
+	sti		gr6,@(gr11,#6*0x08)
+	sethi.p		%hi(__region_CS7),gr4
+	setlo		%lo(__region_CS7),gr4
+	sethi.p		%hi(__region_CS7_M),gr5
+	setlo		%lo(__region_CS7_M),gr5
+	sethi.p		%hi(__region_CS7_C),gr6
+	setlo		%lo(__region_CS7_C),gr6
+	sti		gr4,@(gr10,#7*0x08)
+	sti		gr5,@(gr10,#7*0x08+0x100)
+	sti		gr6,@(gr11,#7*0x08)
+	membar
+	bar
+
+	# adjust LED bank address
+	sethi.p		%hi(LED_ADDR - 0x20000000 +__region_CS2),gr30
+	setlo		%lo(LED_ADDR - 0x20000000 +__region_CS2),gr30
+	bralr
+
+###############################################################################
+#
+# determine the total SDRAM size
+#
+#	ENTRY:			EXIT:
+# GR25	-			SDRAM size
+# GR26	&__head_reference	[saved]
+# GR30	LED address		[saved]
+#
+###############################################################################
+	.globl		__head_fr401_survey_sdram
+__head_fr401_survey_sdram:
+	sethi.p		%hi(__400_DAM0),gr11
+	setlo		%lo(__400_DAM0),gr11
+	sethi.p		%hi(__400_DBR0),gr12
+	setlo		%lo(__400_DBR0),gr12
+
+	sethi.p		%hi(0xfe000000),gr17		; unused SDRAM DBR value
+	setlo		%lo(0xfe000000),gr17
+	setlos		#0,gr25
+
+	ldi		@(gr12,#0x00),gr4		; DAR0
+	subcc		gr4,gr17,gr0,icc0
+	beq		icc0,#0,__head_no_DCS0
+	ldi		@(gr11,#0x00),gr6		; DAM0: bits 31:20 match addr 31:20
+	add		gr25,gr6,gr25
+	addi		gr25,#1,gr25
+__head_no_DCS0:
+
+	ldi		@(gr12,#0x08),gr4		; DAR1
+	subcc		gr4,gr17,gr0,icc0
+	beq		icc0,#0,__head_no_DCS1
+	ldi		@(gr11,#0x08),gr6		; DAM1: bits 31:20 match addr 31:20
+	add		gr25,gr6,gr25
+	addi		gr25,#1,gr25
+__head_no_DCS1:
+
+	# FR401/FR401A does not have DCS2/3
+	movsg		psr,gr3
+	srli		gr3,#25,gr3
+	subicc		gr3,#0x20>>1,gr0,icc0
+	beq		icc0,#0,__head_no_DCS3
+
+	ldi		@(gr12,#0x10),gr4		; DAR2
+	subcc		gr4,gr17,gr0,icc0
+	beq		icc0,#0,__head_no_DCS2
+	ldi		@(gr11,#0x10),gr6		; DAM2: bits 31:20 match addr 31:20
+	add		gr25,gr6,gr25
+	addi		gr25,#1,gr25
+__head_no_DCS2:
+
+	ldi		@(gr12,#0x18),gr4		; DAR3
+	subcc		gr4,gr17,gr0,icc0
+	beq		icc0,#0,__head_no_DCS3
+	ldi		@(gr11,#0x18),gr6		; DAM3: bits 31:20 match addr 31:20
+	add		gr25,gr6,gr25
+	addi		gr25,#1,gr25
+__head_no_DCS3:
+	bralr
+
+###############################################################################
+#
+# set the protection map with the I/DAMPR registers
+#
+#	ENTRY:			EXIT:
+# GR25	SDRAM size		[saved]
+# GR26	&__head_reference	[saved]
+# GR30	LED address		[saved]
+#
+###############################################################################
+	.globl		__head_fr401_set_protection
+__head_fr401_set_protection:
+	movsg		lr,gr27
+
+	# set the I/O region protection registers for FR401/3/5
+	sethi.p		%hi(__region_IO),gr5
+	setlo		%lo(__region_IO),gr5
+	ori		gr5,#xAMPRx_SS_512Mb|xAMPRx_S_KERNEL|xAMPRx_C|xAMPRx_V,gr5
+	movgs		gr0,iampr7
+	movgs		gr5,dampr7			; General I/O tile
+
+	# need to tile the remaining IAMPR/DAMPR registers to cover as much of the RAM as possible
+	# - start with the highest numbered registers
+	sethi.p		%hi(__kernel_image_end),gr8
+	setlo		%lo(__kernel_image_end),gr8
+	sethi.p		%hi(32768),gr4			; allow for a maximal allocator bitmap
+	setlo		%lo(32768),gr4
+	add		gr8,gr4,gr8
+	sethi.p		%hi(1024*2048-1),gr4		; round up to nearest 2MiB
+	setlo		%lo(1024*2048-1),gr4
+	add.p		gr8,gr4,gr8
+	not		gr4,gr4
+	and		gr8,gr4,gr8
+
+	sethi.p		%hi(__page_offset),gr9
+	setlo		%lo(__page_offset),gr9
+	add		gr9,gr25,gr9
+
+	# GR8 = base of uncovered RAM
+	# GR9 = top of uncovered RAM
+
+#ifdef CONFIG_MB93093_PDK
+	sethi.p		%hi(__region_CS2),gr4
+	setlo		%lo(__region_CS2),gr4
+	ori		gr4,#xAMPRx_SS_1Mb|xAMPRx_S_KERNEL|xAMPRx_C|xAMPRx_V,gr4
+	movgs		gr4,dampr6
+	movgs		gr0,iampr6	
+#else
+	call		__head_split_region
+	movgs		gr4,iampr6
+	movgs		gr5,dampr6
+#endif
+	call		__head_split_region
+	movgs		gr4,iampr5
+	movgs		gr5,dampr5
+	call		__head_split_region
+	movgs		gr4,iampr4
+	movgs		gr5,dampr4
+	call		__head_split_region
+	movgs		gr4,iampr3
+	movgs		gr5,dampr3
+	call		__head_split_region
+	movgs		gr4,iampr2
+	movgs		gr5,dampr2
+	call		__head_split_region
+	movgs		gr4,iampr1
+	movgs		gr5,dampr1
+
+	# cover kernel core image with kernel-only segment
+	sethi.p		%hi(__page_offset),gr8
+	setlo		%lo(__page_offset),gr8
+	call		__head_split_region
+
+#ifdef CONFIG_PROTECT_KERNEL
+	ori.p		gr4,#xAMPRx_S_KERNEL,gr4
+	ori		gr5,#xAMPRx_S_KERNEL,gr5
+#endif
+
+	movgs		gr4,iampr0
+	movgs		gr5,dampr0
+	jmpl		@(gr27,gr0)
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/kernel/head-uc-fr451.S linux-2.6.10-rc1-mm3-frv/arch/frv/kernel/head-uc-fr451.S
--- /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/kernel/head-uc-fr451.S	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/arch/frv/kernel/head-uc-fr451.S	2004-11-05 14:13:03.000000000 +0000
@@ -0,0 +1,174 @@
+/* head-uc-fr451.S: FR451 uc-linux specific bits of initialisation
+ *
+ * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * 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.
+ */
+
+#include <linux/config.h>
+#include <linux/threads.h>
+#include <linux/linkage.h>
+#include <asm/ptrace.h>
+#include <asm/page.h>
+#include <asm/spr-regs.h>
+#include <asm/mb86943a.h>
+#include "head.inc"
+
+
+#define __400_DBR0	0xfe000e00
+#define __400_DBR1	0xfe000e08
+#define __400_DBR2	0xfe000e10
+#define __400_DBR3	0xfe000e18
+#define __400_DAM0	0xfe000f00
+#define __400_DAM1	0xfe000f08
+#define __400_DAM2	0xfe000f10
+#define __400_DAM3	0xfe000f18
+#define __400_LGCR	0xfe000010
+#define __400_LCR	0xfe000100
+#define __400_LSBR	0xfe000c00
+
+	.section	.text.init,"ax"
+	.balign		4
+
+###############################################################################
+#
+# set the protection map with the I/DAMPR registers
+#
+#	ENTRY:			EXIT:
+# GR25	SDRAM size		[saved]
+# GR26	&__head_reference	[saved]
+# GR30	LED address		[saved]
+#
+###############################################################################
+	.globl		__head_fr451_set_protection
+__head_fr451_set_protection:
+	movsg		lr,gr27
+
+	movgs		gr0,dampr10
+	movgs		gr0,damlr10
+	movgs		gr0,dampr9
+	movgs		gr0,damlr9
+	movgs		gr0,dampr8
+	movgs		gr0,damlr8
+
+	# set the I/O region protection registers for FR401/3/5
+	sethi.p		%hi(__region_IO),gr5
+	setlo		%lo(__region_IO),gr5
+	sethi.p		%hi(0x1fffffff),gr7
+	setlo		%lo(0x1fffffff),gr7
+	ori		gr5,#xAMPRx_SS_512Mb|xAMPRx_S_KERNEL|xAMPRx_C|xAMPRx_V,gr5
+	movgs		gr5,dampr11			; General I/O tile
+	movgs		gr7,damlr11
+
+	# need to tile the remaining IAMPR/DAMPR registers to cover as much of the RAM as possible
+	# - start with the highest numbered registers
+	sethi.p		%hi(__kernel_image_end),gr8
+	setlo		%lo(__kernel_image_end),gr8
+	sethi.p		%hi(32768),gr4			; allow for a maximal allocator bitmap
+	setlo		%lo(32768),gr4
+	add		gr8,gr4,gr8
+	sethi.p		%hi(1024*2048-1),gr4		; round up to nearest 2MiB
+	setlo		%lo(1024*2048-1),gr4
+	add.p		gr8,gr4,gr8
+	not		gr4,gr4
+	and		gr8,gr4,gr8
+
+	sethi.p		%hi(__page_offset),gr9
+	setlo		%lo(__page_offset),gr9
+	add		gr9,gr25,gr9
+
+	sethi.p		%hi(0xffffc000),gr11
+	setlo		%lo(0xffffc000),gr11
+
+	# GR8 = base of uncovered RAM
+	# GR9 = top of uncovered RAM
+	# GR11 = xAMLR mask
+	LEDS		0x3317
+	call		__head_split_region
+	movgs		gr4,iampr7
+	movgs		gr6,iamlr7
+	movgs		gr5,dampr7
+	movgs		gr7,damlr7
+
+	LEDS		0x3316
+	call		__head_split_region
+	movgs		gr4,iampr6
+	movgs		gr6,iamlr6
+	movgs		gr5,dampr6
+	movgs		gr7,damlr6
+
+	LEDS		0x3315
+	call		__head_split_region
+	movgs		gr4,iampr5
+	movgs		gr6,iamlr5
+	movgs		gr5,dampr5
+	movgs		gr7,damlr5
+
+	LEDS		0x3314
+	call		__head_split_region
+	movgs		gr4,iampr4
+	movgs		gr6,iamlr4
+	movgs		gr5,dampr4
+	movgs		gr7,damlr4
+
+	LEDS		0x3313
+	call		__head_split_region
+	movgs		gr4,iampr3
+	movgs		gr6,iamlr3
+	movgs		gr5,dampr3
+	movgs		gr7,damlr3
+
+	LEDS		0x3312
+	call		__head_split_region
+	movgs		gr4,iampr2
+	movgs		gr6,iamlr2
+	movgs		gr5,dampr2
+	movgs		gr7,damlr2
+
+	LEDS		0x3311
+	call		__head_split_region
+	movgs		gr4,iampr1
+	movgs		gr6,iamlr1
+	movgs		gr5,dampr1
+	movgs		gr7,damlr1
+
+	# cover kernel core image with kernel-only segment
+	LEDS		0x3310
+	sethi.p		%hi(__page_offset),gr8
+	setlo		%lo(__page_offset),gr8
+	call		__head_split_region
+
+#ifdef CONFIG_PROTECT_KERNEL
+	ori.p		gr4,#xAMPRx_S_KERNEL,gr4
+	ori		gr5,#xAMPRx_S_KERNEL,gr5
+#endif
+
+	movgs		gr4,iampr0
+	movgs		gr6,iamlr0
+	movgs		gr5,dampr0
+	movgs		gr7,damlr0
+
+	# start in TLB context 0 with no page tables
+	movgs		gr0,cxnr
+	movgs		gr0,ttbr
+
+	# the FR451 also has an extra trap base register
+	movsg		tbr,gr4
+	movgs		gr4,btbr
+	
+	# turn on the timers as appropriate
+	movgs		gr0,timerh
+	movgs		gr0,timerl
+	movgs		gr0,timerd
+	movsg		hsr0,gr4
+	sethi.p		%hi(HSR0_ETMI),gr5
+	setlo		%lo(HSR0_ETMI),gr5
+	or		gr4,gr5,gr4
+	movgs		gr4,hsr0
+	
+	LEDS		0x3300
+	jmpl		@(gr27,gr0)
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/kernel/head-uc-fr555.S linux-2.6.10-rc1-mm3-frv/arch/frv/kernel/head-uc-fr555.S
--- /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/kernel/head-uc-fr555.S	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/arch/frv/kernel/head-uc-fr555.S	2004-11-05 14:13:03.000000000 +0000
@@ -0,0 +1,347 @@
+/* head-uc-fr555.S: FR555 uc-linux specific bits of initialisation
+ *
+ * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * 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.
+ */
+
+#include <linux/config.h>
+#include <linux/threads.h>
+#include <linux/linkage.h>
+#include <asm/ptrace.h>
+#include <asm/page.h>
+#include <asm/spr-regs.h>
+#include <asm/mb86943a.h>
+#include "head.inc"
+
+
+#define __551_DARS0	0xfeff0100
+#define __551_DARS1	0xfeff0104
+#define __551_DARS2	0xfeff0108
+#define __551_DARS3	0xfeff010c
+#define __551_DAMK0	0xfeff0110
+#define __551_DAMK1	0xfeff0114
+#define __551_DAMK2	0xfeff0118
+#define __551_DAMK3	0xfeff011c
+#define __551_LCR	0xfeff1100
+#define __551_LSBR	0xfeff1c00
+
+	.section	.text.init,"ax"
+	.balign		4
+
+###############################################################################
+#
+# describe the position and layout of the SDRAM controller registers
+#
+#	ENTRY:			EXIT:
+# GR5	-			cacheline size
+# GR11	-			displacement of 2nd SDRAM addr reg from GR14
+# GR12	-			displacement of 3rd SDRAM addr reg from GR14
+# GR13	-			displacement of 4th SDRAM addr reg from GR14
+# GR14	-			address of 1st SDRAM addr reg
+# GR15	-			amount to shift address by to match SDRAM addr reg
+# GR26	&__head_reference	[saved]
+# GR30	LED address		[saved]
+# CC0	-			T if DARS0 is present
+# CC1	-			T if DARS1 is present
+# CC2	-			T if DARS2 is present
+# CC3	-			T if DARS3 is present
+#
+###############################################################################
+	.globl		__head_fr555_describe_sdram
+__head_fr555_describe_sdram:
+	sethi.p		%hi(__551_DARS0),gr14
+	setlo		%lo(__551_DARS0),gr14
+	setlos.p	#__551_DARS1-__551_DARS0,gr11
+	setlos		#__551_DARS2-__551_DARS0,gr12
+	setlos.p	#__551_DARS3-__551_DARS0,gr13
+	setlos		#64,gr5			; cacheline size
+	setlos		#20,gr15		; amount to shift addr by
+	setlos		#0x00ff,gr4
+	movgs		gr4,cccr		; extant DARS/DAMK regs
+	bralr
+
+###############################################################################
+#
+# rearrange the bus controller registers
+#
+#	ENTRY:			EXIT:
+# GR26	&__head_reference	[saved]
+# GR30	LED address		revised LED address
+#
+###############################################################################
+	.globl		__head_fr555_set_busctl
+__head_fr555_set_busctl:
+	LEDS		0x100f
+	sethi.p		%hi(__551_LSBR),gr10
+	setlo		%lo(__551_LSBR),gr10
+	sethi.p		%hi(__551_LCR),gr11
+	setlo		%lo(__551_LCR),gr11
+
+	# set the bus controller
+	sethi.p		%hi(__region_CS1),gr4
+	setlo		%lo(__region_CS1),gr4
+	sethi.p		%hi(__region_CS1_M),gr5
+	setlo		%lo(__region_CS1_M),gr5
+	sethi.p		%hi(__region_CS1_C),gr6
+	setlo		%lo(__region_CS1_C),gr6
+	sti		gr4,@(gr10,#1*0x08)
+	sti		gr5,@(gr10,#1*0x08+0x100)
+	sti		gr6,@(gr11,#1*0x08)
+	sethi.p		%hi(__region_CS2),gr4
+	setlo		%lo(__region_CS2),gr4
+	sethi.p		%hi(__region_CS2_M),gr5
+	setlo		%lo(__region_CS2_M),gr5
+	sethi.p		%hi(__region_CS2_C),gr6
+	setlo		%lo(__region_CS2_C),gr6
+	sti		gr4,@(gr10,#2*0x08)
+	sti		gr5,@(gr10,#2*0x08+0x100)
+	sti		gr6,@(gr11,#2*0x08)
+	sethi.p		%hi(__region_CS3),gr4
+	setlo		%lo(__region_CS3),gr4
+	sethi.p		%hi(__region_CS3_M),gr5
+	setlo		%lo(__region_CS3_M),gr5
+	sethi.p		%hi(__region_CS3_C),gr6
+	setlo		%lo(__region_CS3_C),gr6
+	sti		gr4,@(gr10,#3*0x08)
+	sti		gr5,@(gr10,#3*0x08+0x100)
+	sti		gr6,@(gr11,#3*0x08)
+	sethi.p		%hi(__region_CS4),gr4
+	setlo		%lo(__region_CS4),gr4
+	sethi.p		%hi(__region_CS4_M),gr5
+	setlo		%lo(__region_CS4_M),gr5
+	sethi.p		%hi(__region_CS4_C),gr6
+	setlo		%lo(__region_CS4_C),gr6
+	sti		gr4,@(gr10,#4*0x08)
+	sti		gr5,@(gr10,#4*0x08+0x100)
+	sti		gr6,@(gr11,#4*0x08)
+	sethi.p		%hi(__region_CS5),gr4
+	setlo		%lo(__region_CS5),gr4
+	sethi.p		%hi(__region_CS5_M),gr5
+	setlo		%lo(__region_CS5_M),gr5
+	sethi.p		%hi(__region_CS5_C),gr6
+	setlo		%lo(__region_CS5_C),gr6
+	sti		gr4,@(gr10,#5*0x08)
+	sti		gr5,@(gr10,#5*0x08+0x100)
+	sti		gr6,@(gr11,#5*0x08)
+	sethi.p		%hi(__region_CS6),gr4
+	setlo		%lo(__region_CS6),gr4
+	sethi.p		%hi(__region_CS6_M),gr5
+	setlo		%lo(__region_CS6_M),gr5
+	sethi.p		%hi(__region_CS6_C),gr6
+	setlo		%lo(__region_CS6_C),gr6
+	sti		gr4,@(gr10,#6*0x08)
+	sti		gr5,@(gr10,#6*0x08+0x100)
+	sti		gr6,@(gr11,#6*0x08)
+	sethi.p		%hi(__region_CS7),gr4
+	setlo		%lo(__region_CS7),gr4
+	sethi.p		%hi(__region_CS7_M),gr5
+	setlo		%lo(__region_CS7_M),gr5
+	sethi.p		%hi(__region_CS7_C),gr6
+	setlo		%lo(__region_CS7_C),gr6
+	sti		gr4,@(gr10,#7*0x08)
+	sti		gr5,@(gr10,#7*0x08+0x100)
+	sti		gr6,@(gr11,#7*0x08)
+	membar
+	bar
+
+	# adjust LED bank address
+#ifdef CONFIG_MB93091_VDK
+	sethi.p		%hi(LED_ADDR - 0x20000000 +__region_CS2),gr30
+	setlo		%lo(LED_ADDR - 0x20000000 +__region_CS2),gr30
+#endif
+	bralr
+
+###############################################################################
+#
+# determine the total SDRAM size
+#
+#	ENTRY:			EXIT:
+# GR25	-			SDRAM size
+# GR26	&__head_reference	[saved]
+# GR30	LED address		[saved]
+#
+###############################################################################
+	.globl		__head_fr555_survey_sdram
+__head_fr555_survey_sdram:
+	sethi.p		%hi(__551_DAMK0),gr11
+	setlo		%lo(__551_DAMK0),gr11
+	sethi.p		%hi(__551_DARS0),gr12
+	setlo		%lo(__551_DARS0),gr12
+
+	sethi.p		%hi(0xfff),gr17			; unused SDRAM AMK value
+	setlo		%lo(0xfff),gr17
+	setlos		#0,gr25
+
+	ldi		@(gr11,#0x00),gr6		; DAMK0: bits 11:0 match addr 11:0
+	subcc		gr6,gr17,gr0,icc0
+	beq		icc0,#0,__head_no_DCS0
+	ldi		@(gr12,#0x00),gr4		; DARS0
+	add		gr25,gr6,gr25
+	addi		gr25,#1,gr25
+__head_no_DCS0:
+
+	ldi		@(gr11,#0x04),gr6		; DAMK1: bits 11:0 match addr 11:0
+	subcc		gr6,gr17,gr0,icc0
+	beq		icc0,#0,__head_no_DCS1
+	ldi		@(gr12,#0x04),gr4		; DARS1
+	add		gr25,gr6,gr25
+	addi		gr25,#1,gr25
+__head_no_DCS1:
+
+	ldi		@(gr11,#0x8),gr6		; DAMK2: bits 11:0 match addr 11:0
+	subcc		gr6,gr17,gr0,icc0
+	beq		icc0,#0,__head_no_DCS2
+	ldi		@(gr12,#0x8),gr4		; DARS2
+	add		gr25,gr6,gr25
+	addi		gr25,#1,gr25
+__head_no_DCS2:
+
+	ldi		@(gr11,#0xc),gr6		; DAMK3: bits 11:0 match addr 11:0
+	subcc		gr6,gr17,gr0,icc0
+	beq		icc0,#0,__head_no_DCS3
+	ldi		@(gr12,#0xc),gr4		; DARS3
+	add		gr25,gr6,gr25
+	addi		gr25,#1,gr25
+__head_no_DCS3:
+	
+	slli		gr25,#20,gr25			; shift [11:0] -> [31:20]
+	bralr
+
+###############################################################################
+#
+# set the protection map with the I/DAMPR registers
+#
+#	ENTRY:			EXIT:
+# GR25	SDRAM size		saved
+# GR30	LED address		saved
+#
+###############################################################################
+	.globl		__head_fr555_set_protection
+__head_fr555_set_protection:
+	movsg		lr,gr27
+
+	sethi.p		%hi(0xfff00000),gr11
+	setlo		%lo(0xfff00000),gr11
+		
+	# set the I/O region protection registers for FR555
+	sethi.p		%hi(__region_IO),gr7
+	setlo		%lo(__region_IO),gr7
+	ori		gr7,#xAMPRx_SS_512Mb|xAMPRx_S_KERNEL|xAMPRx_C|xAMPRx_V,gr5
+	movgs		gr0,iampr15
+	movgs		gr0,iamlr15
+	movgs		gr5,dampr15
+	movgs		gr7,damlr15
+
+	# need to tile the remaining IAMPR/DAMPR registers to cover as much of the RAM as possible
+	# - start with the highest numbered registers
+	sethi.p		%hi(__kernel_image_end),gr8
+	setlo		%lo(__kernel_image_end),gr8
+	sethi.p		%hi(32768),gr4			; allow for a maximal allocator bitmap
+	setlo		%lo(32768),gr4
+	add		gr8,gr4,gr8
+	sethi.p		%hi(1024*2048-1),gr4		; round up to nearest 2MiB
+	setlo		%lo(1024*2048-1),gr4
+	add.p		gr8,gr4,gr8
+	not		gr4,gr4
+	and		gr8,gr4,gr8
+
+	sethi.p		%hi(__page_offset),gr9
+	setlo		%lo(__page_offset),gr9
+	add		gr9,gr25,gr9
+
+	# GR8 = base of uncovered RAM
+	# GR9 = top of uncovered RAM
+	# GR11 - mask for DAMLR/IAMLR regs
+	#
+	call		__head_split_region
+	movgs		gr4,iampr14
+	movgs		gr6,iamlr14
+	movgs		gr5,dampr14
+	movgs		gr7,damlr14
+	call		__head_split_region
+	movgs		gr4,iampr13
+	movgs		gr6,iamlr13
+	movgs		gr5,dampr13
+	movgs		gr7,damlr13
+	call		__head_split_region
+	movgs		gr4,iampr12
+	movgs		gr6,iamlr12
+	movgs		gr5,dampr12
+	movgs		gr7,damlr12
+	call		__head_split_region
+	movgs		gr4,iampr11
+	movgs		gr6,iamlr11
+	movgs		gr5,dampr11
+	movgs		gr7,damlr11
+	call		__head_split_region
+	movgs		gr4,iampr10
+	movgs		gr6,iamlr10
+	movgs		gr5,dampr10
+	movgs		gr7,damlr10
+	call		__head_split_region
+	movgs		gr4,iampr9
+	movgs		gr6,iamlr9
+	movgs		gr5,dampr9
+	movgs		gr7,damlr9
+	call		__head_split_region
+	movgs		gr4,iampr8
+	movgs		gr6,iamlr8
+	movgs		gr5,dampr8
+	movgs		gr7,damlr8
+
+	call		__head_split_region
+	movgs		gr4,iampr7
+	movgs		gr6,iamlr7
+	movgs		gr5,dampr7
+	movgs		gr7,damlr7
+	call		__head_split_region
+	movgs		gr4,iampr6
+	movgs		gr6,iamlr6
+	movgs		gr5,dampr6
+	movgs		gr7,damlr6
+	call		__head_split_region
+	movgs		gr4,iampr5
+	movgs		gr6,iamlr5
+	movgs		gr5,dampr5
+	movgs		gr7,damlr5
+	call		__head_split_region
+	movgs		gr4,iampr4
+	movgs		gr6,iamlr4
+	movgs		gr5,dampr4
+	movgs		gr7,damlr4
+	call		__head_split_region
+	movgs		gr4,iampr3
+	movgs		gr6,iamlr3
+	movgs		gr5,dampr3
+	movgs		gr7,damlr3
+	call		__head_split_region
+	movgs		gr4,iampr2
+	movgs		gr6,iamlr2
+	movgs		gr5,dampr2
+	movgs		gr7,damlr2
+	call		__head_split_region
+	movgs		gr4,iampr1
+	movgs		gr6,iamlr1
+	movgs		gr5,dampr1
+	movgs		gr7,damlr1
+
+	# cover kernel core image with kernel-only segment
+	sethi.p		%hi(__page_offset),gr8
+	setlo		%lo(__page_offset),gr8
+	call		__head_split_region
+
+#ifdef CONFIG_PROTECT_KERNEL
+	ori.p		gr4,#xAMPRx_S_KERNEL,gr4
+	ori		gr5,#xAMPRx_S_KERNEL,gr5
+#endif
+
+	movgs		gr4,iampr0
+	movgs		gr6,iamlr0
+	movgs		gr5,dampr0
+	movgs		gr7,damlr0
+	jmpl		@(gr27,gr0)
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/kernel/init_task.c linux-2.6.10-rc1-mm3-frv/arch/frv/kernel/init_task.c
--- /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/kernel/init_task.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/arch/frv/kernel/init_task.c	2004-11-05 14:13:03.141560129 +0000
@@ -0,0 +1,39 @@
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+#include <linux/init_task.h>
+#include <linux/fs.h>
+#include <linux/mqueue.h>
+
+#include <asm/uaccess.h>
+#include <asm/pgtable.h>
+
+
+static struct fs_struct init_fs = INIT_FS;
+static struct files_struct init_files = INIT_FILES;
+static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
+static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
+struct mm_struct init_mm = INIT_MM(init_mm);
+
+EXPORT_SYMBOL(init_mm);
+
+/*
+ * Initial thread structure.
+ *
+ * We need to make sure that this is THREAD_SIZE aligned due to the
+ * way process stacks are handled. This is done by having a special
+ * "init_task" linker map entry..
+ */
+union thread_union init_thread_union 
+	__attribute__((__section__(".data.init_task"))) =
+		{ INIT_THREAD_INFO(init_task) };
+
+/*
+ * Initial task structure.
+ *
+ * All other task structs will be allocated on slabs in fork.c
+ */
+struct task_struct init_task = INIT_TASK(init_task);
+
+EXPORT_SYMBOL(init_task);
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/kernel/irq.c linux-2.6.10-rc1-mm3-frv/arch/frv/kernel/irq.c
--- /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/kernel/irq.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/arch/frv/kernel/irq.c	2004-11-05 14:13:03.147559622 +0000
@@ -0,0 +1,764 @@
+/* irq.c: FRV IRQ handling
+ *
+ * Copyright (C) 2003, 2004 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * 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.
+ */
+
+/*
+ * (mostly architecture independent, will move to kernel/irq.c in 2.5.)
+ *
+ * IRQs are in fact implemented a bit like signal handlers for the kernel.
+ * Naturally it's not a 1:1 relation, but there are similarities.
+ */
+
+#include <linux/config.h>
+#include <linux/ptrace.h>
+#include <linux/errno.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/ioport.h>
+#include <linux/interrupt.h>
+#include <linux/timex.h>
+#include <linux/slab.h>
+#include <linux/random.h>
+#include <linux/smp_lock.h>
+#include <linux/init.h>
+#include <linux/kernel_stat.h>
+#include <linux/irq.h>
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+
+#include <asm/atomic.h>
+#include <asm/io.h>
+#include <asm/smp.h>
+#include <asm/system.h>
+#include <asm/bitops.h>
+#include <asm/uaccess.h>
+#include <asm/pgalloc.h>
+#include <asm/delay.h>
+#include <asm/irq.h>
+#include <asm/irc-regs.h>
+#include <asm/irq-routing.h>
+#include <asm/gdb-stub.h>
+
+extern void __init fpga_init(void);
+extern void __init route_mb93493_irqs(void);
+
+static void register_irq_proc (unsigned int irq);
+
+/*
+ * Special irq handlers.
+ */
+
+irqreturn_t no_action(int cpl, void *dev_id, struct pt_regs *regs) { return IRQ_HANDLED; }
+
+atomic_t irq_err_count;
+
+/*
+ * Generic, controller-independent functions:
+ */
+int show_interrupts(struct seq_file *p, void *v)
+{
+	struct irqaction *action;
+	struct irq_group *group;
+	unsigned long flags;
+	int level, grp, ix, i, j;
+
+	i = *(loff_t *) v;
+
+	switch (i) {
+	case 0:
+		seq_printf(p, "           ");
+		for (j = 0; j < NR_CPUS; j++)
+			if (cpu_online(j))
+				seq_printf(p, "CPU%d       ",j);
+
+		seq_putc(p, '\n');
+		break;
+
+	case 1 ... NR_IRQ_GROUPS * NR_IRQ_ACTIONS_PER_GROUP:
+		local_irq_save(flags);
+
+		grp = (i - 1) / NR_IRQ_ACTIONS_PER_GROUP;
+		group = irq_groups[grp];
+		if (!group)
+			goto skip;
+
+		ix = (i - 1) % NR_IRQ_ACTIONS_PER_GROUP;
+		action = group->actions[ix];
+		if (!action)
+			goto skip;
+
+		seq_printf(p, "%3d: ", i - 1);
+
+#ifndef CONFIG_SMP
+		seq_printf(p, "%10u ", kstat_irqs(i));
+#else
+		for (j = 0; j < NR_CPUS; j++)
+			if (cpu_online(j))
+				seq_printf(p, "%10u ", kstat_cpu(j).irqs[i - 1]);
+#endif
+
+		level = group->sources[ix]->level - frv_irq_levels;
+
+		seq_printf(p, " %12s@%x", group->sources[ix]->muxname, level);
+		seq_printf(p, "  %s", action->name);
+
+		for (action = action->next; action; action = action->next)
+			seq_printf(p, ", %s", action->name);
+
+		seq_putc(p, '\n');
+skip:
+		local_irq_restore(flags);
+		break;
+
+	case NR_IRQ_GROUPS * NR_IRQ_ACTIONS_PER_GROUP + 1:
+		seq_printf(p, "ERR: %10u\n", atomic_read(&irq_err_count));
+		break;
+
+	default:
+		break;
+	}
+
+	return 0;
+}
+
+
+/*
+ * Generic enable/disable code: this just calls
+ * down into the PIC-specific version for the actual
+ * hardware disable after having gotten the irq
+ * controller lock.
+ */
+
+/**
+ *	disable_irq_nosync - disable an irq without waiting
+ *	@irq: Interrupt to disable
+ *
+ *	Disable the selected interrupt line.  Disables and Enables are
+ *	nested.
+ *	Unlike disable_irq(), this function does not ensure existing
+ *	instances of the IRQ handler have completed before returning.
+ *
+ *	This function may be called from IRQ context.
+ */
+
+void disable_irq_nosync(unsigned int irq)
+{
+	struct irq_source *source;
+	struct irq_group *group;
+	struct irq_level *level;
+	unsigned long flags;
+	int idx = irq & (NR_IRQ_ACTIONS_PER_GROUP - 1);
+
+	group = irq_groups[irq >> NR_IRQ_LOG2_ACTIONS_PER_GROUP];
+	if (!group)
+		BUG();
+
+	source = group->sources[idx];
+	if (!source)
+		BUG();
+
+	level = source->level;
+
+	spin_lock_irqsave(&level->lock, flags);
+
+	if (group->control) {
+		if (!group->disable_cnt[idx]++)
+			group->control(group, idx, 0);
+	} else if (!level->disable_count++) {
+		__set_MASK(level - frv_irq_levels);
+	}
+
+	spin_unlock_irqrestore(&level->lock, flags);
+}
+
+/**
+ *	disable_irq - disable an irq and wait for completion
+ *	@irq: Interrupt to disable
+ *
+ *	Disable the selected interrupt line.  Enables and Disables are
+ *	nested.
+ *	This function waits for any pending IRQ handlers for this interrupt
+ *	to complete before returning. If you use this function while
+ *	holding a resource the IRQ handler may need you will deadlock.
+ *
+ *	This function may be called - with care - from IRQ context.
+ */
+
+void disable_irq(unsigned int irq)
+{
+	disable_irq_nosync(irq);
+
+#ifdef CONFIG_SMP
+	if (!local_irq_count(smp_processor_id())) {
+		do {
+			barrier();
+		} while (irq_desc[irq].status & IRQ_INPROGRESS);
+	}
+#endif
+}
+
+/**
+ *	enable_irq - enable handling of an irq
+ *	@irq: Interrupt to enable
+ *
+ *	Undoes the effect of one call to disable_irq().  If this
+ *	matches the last disable, processing of interrupts on this
+ *	IRQ line is re-enabled.
+ *
+ *	This function may be called from IRQ context.
+ */
+
+void enable_irq(unsigned int irq)
+{
+	struct irq_source *source;
+	struct irq_group *group;
+	struct irq_level *level;
+	unsigned long flags;
+	int idx = irq & (NR_IRQ_ACTIONS_PER_GROUP - 1);
+	int count;
+
+	group = irq_groups[irq >> NR_IRQ_LOG2_ACTIONS_PER_GROUP];
+	if (!group)
+		BUG();
+
+	source = group->sources[idx];
+	if (!source)
+		BUG();
+
+	level = source->level;
+
+	spin_lock_irqsave(&level->lock, flags);
+
+	if (group->control)
+		count = group->disable_cnt[idx];
+	else
+		count = level->disable_count;
+
+	switch (count) {
+	case 1:
+		if (group->control) {
+			if (group->actions[idx])
+				group->control(group, idx, 1);
+		} else {
+			if (level->usage)
+				__clr_MASK(level - frv_irq_levels);
+		}
+		/* fall-through */
+
+	default:
+		count--;
+		break;
+
+	case 0:
+		printk("enable_irq(%u) unbalanced from %p\n", irq, __builtin_return_address(0));
+	}
+
+	if (group->control)
+		group->disable_cnt[idx] = count;
+	else
+		level->disable_count = count;
+
+	spin_unlock_irqrestore(&level->lock, flags);
+}
+
+/*****************************************************************************/
+/*
+ * handles all normal device IRQ's
+ * - registers are referred to by the __frame variable (GR28)
+ * - IRQ distribution is complicated in this arch because of the many PICs, the
+ *   way they work and the way they cascade
+ */
+asmlinkage void do_IRQ(void)
+{
+	struct irq_source *source;
+	int level, cpu;
+
+	level = (__frame->tbr >> 4) & 0xf;
+	cpu = smp_processor_id();
+
+#if 0
+	{
+		static u32 irqcount;
+		*(volatile u32 *) 0xe1200004 = ~((irqcount++ << 8) | level);
+		*(volatile u16 *) 0xffc00100 = (u16) ~0x9999;
+		mb();
+	}
+#endif
+
+	if ((unsigned long) __frame - (unsigned long) (current + 1) < 512)
+		BUG();
+
+	__set_MASK(level);
+	__clr_RC(level);
+	__clr_IRL();
+
+	kstat_this_cpu.irqs[level]++;
+
+	irq_enter();
+
+	for (source = frv_irq_levels[level].sources; source; source = source->next)
+		source->doirq(source);
+
+	irq_exit();
+
+	__clr_MASK(level);
+
+	/* only process softirqs if we didn't interrupt another interrupt handler */
+	if ((__frame->psr & PSR_PIL) == PSR_PIL_0)
+		if (softirq_pending(cpu))
+			do_softirq();
+
+#ifdef CONFIG_PREEMPT
+	cli();
+	while (--current->preempt_count == 0) {
+		if (!(__frame->psr & PSR_S)
+		    || (current->need_resched == 0)
+		    || in_interrupt())
+			break;
+		current->preempt_count++;
+		sti();
+		preempt_schedule();
+		cli();
+	}
+#endif
+
+#if 0
+	{
+		*(volatile u16 *) 0xffc00100 = (u16) ~0x6666;
+		mb();
+	}
+#endif
+
+} /* end do_IRQ() */
+
+/*****************************************************************************/
+/*
+ * handles all NMIs when not co-opted by the debugger
+ * - registers are referred to by the __frame variable (GR28)
+ */
+asmlinkage void do_NMI(void)
+{
+} /* end do_NMI() */
+
+/*****************************************************************************/
+/**
+ *	request_irq - allocate an interrupt line
+ *	@irq: Interrupt line to allocate
+ *	@handler: Function to be called when the IRQ occurs
+ *	@irqflags: Interrupt type flags
+ *	@devname: An ascii name for the claiming device
+ *	@dev_id: A cookie passed back to the handler function
+ *
+ *	This call allocates interrupt resources and enables the
+ *	interrupt line and IRQ handling. From the point this
+ *	call is made your handler function may be invoked. Since
+ *	your handler function must clear any interrupt the board
+ *	raises, you must take care both to initialise your hardware
+ *	and to set up the interrupt handler in the right order.
+ *
+ *	Dev_id must be globally unique. Normally the address of the
+ *	device data structure is used as the cookie. Since the handler
+ *	receives this value it makes sense to use it.
+ *
+ *	If your interrupt is shared you must pass a non NULL dev_id
+ *	as this is required when freeing the interrupt.
+ *
+ *	Flags:
+ *
+ *	SA_SHIRQ		Interrupt is shared
+ *
+ *	SA_INTERRUPT		Disable local interrupts while processing
+ *
+ *	SA_SAMPLE_RANDOM	The interrupt can be used for entropy
+ *
+ */
+
+int request_irq(unsigned int irq,
+		irqreturn_t (*handler)(int, void *, struct pt_regs *),
+		unsigned long irqflags,
+		const char * devname,
+		void *dev_id)
+{
+	int retval;
+	struct irqaction *action;
+
+#if 1
+	/*
+	 * Sanity-check: shared interrupts should REALLY pass in
+	 * a real dev-ID, otherwise we'll have trouble later trying
+	 * to figure out which interrupt is which (messes up the
+	 * interrupt freeing logic etc).
+	 */
+	if (irqflags & SA_SHIRQ) {
+		if (!dev_id)
+			printk("Bad boy: %s (at 0x%x) called us without a dev_id!\n",
+			       devname, (&irq)[-1]);
+	}
+#endif
+
+	if ((irq >> NR_IRQ_LOG2_ACTIONS_PER_GROUP) >= NR_IRQ_GROUPS)
+		return -EINVAL;
+	if (!handler)
+		return -EINVAL;
+
+	action = (struct irqaction *) kmalloc(sizeof(struct irqaction), GFP_KERNEL);
+	if (!action)
+		return -ENOMEM;
+
+	action->handler = handler;
+	action->flags = irqflags;
+	action->mask = CPU_MASK_NONE;
+	action->name = devname;
+	action->next = NULL;
+	action->dev_id = dev_id;
+
+	retval = setup_irq(irq, action);
+	if (retval)
+		kfree(action);
+	return retval;
+}
+
+/**
+ *	free_irq - free an interrupt
+ *	@irq: Interrupt line to free
+ *	@dev_id: Device identity to free
+ *
+ *	Remove an interrupt handler. The handler is removed and if the
+ *	interrupt line is no longer in use by any driver it is disabled.
+ *	On a shared IRQ the caller must ensure the interrupt is disabled
+ *	on the card it drives before calling this function. The function
+ *	does not return until any executing interrupts for this IRQ
+ *	have completed.
+ *
+ *	This function may be called from interrupt context.
+ *
+ *	Bugs: Attempting to free an irq in a handler for the same irq hangs
+ *	      the machine.
+ */
+
+void free_irq(unsigned int irq, void *dev_id)
+{
+	struct irq_source *source;
+	struct irq_group *group;
+	struct irq_level *level;
+	struct irqaction **p, **pp;
+	unsigned long flags;
+
+	if ((irq >> NR_IRQ_LOG2_ACTIONS_PER_GROUP) >= NR_IRQ_GROUPS)
+		return;
+
+	group = irq_groups[irq >> NR_IRQ_LOG2_ACTIONS_PER_GROUP];
+	if (!group)
+		BUG();
+
+	source = group->sources[irq & (NR_IRQ_ACTIONS_PER_GROUP - 1)];
+	if (!source)
+		BUG();
+
+	level = source->level;
+	p = &group->actions[irq & (NR_IRQ_ACTIONS_PER_GROUP - 1)];
+
+	spin_lock_irqsave(&level->lock, flags);
+
+	for (pp = p; *pp; pp = &(*pp)->next) {
+		struct irqaction *action = *pp;
+
+		if (action->dev_id != dev_id)
+			continue;
+
+		/* found it - remove from the list of entries */
+		*pp = action->next;
+
+		level->usage--;
+
+		if (p == pp && group->control)
+			group->control(group, irq & (NR_IRQ_ACTIONS_PER_GROUP - 1), 0);
+
+		if (level->usage == 0)
+			__set_MASK(level - frv_irq_levels);
+
+		spin_unlock_irqrestore(&level->lock,flags);
+
+#ifdef CONFIG_SMP
+		/* Wait to make sure it's not being used on another CPU */
+		while (desc->status & IRQ_INPROGRESS)
+			barrier();
+#endif
+		kfree(action);
+		return;
+	}
+}
+
+/*
+ * IRQ autodetection code..
+ *
+ * This depends on the fact that any interrupt that comes in on to an
+ * unassigned IRQ will cause GxICR_DETECT to be set
+ */
+
+static DECLARE_MUTEX(probe_sem);
+
+/**
+ *	probe_irq_on	- begin an interrupt autodetect
+ *
+ *	Commence probing for an interrupt. The interrupts are scanned
+ *	and a mask of potential interrupt lines is returned.
+ *
+ */
+
+unsigned long probe_irq_on(void)
+{
+	down(&probe_sem);
+	return 0;
+}
+
+/*
+ * Return a mask of triggered interrupts (this
+ * can handle only legacy ISA interrupts).
+ */
+
+/**
+ *	probe_irq_mask - scan a bitmap of interrupt lines
+ *	@val:	mask of interrupts to consider
+ *
+ *	Scan the ISA bus interrupt lines and return a bitmap of
+ *	active interrupts. The interrupt probe logic state is then
+ *	returned to its previous value.
+ *
+ *	Note: we need to scan all the irq's even though we will
+ *	only return ISA irq numbers - just so that we reset them
+ *	all to a known state.
+ */
+unsigned int probe_irq_mask(unsigned long xmask)
+{
+	up(&probe_sem);
+	return 0;
+}
+
+/*
+ * Return the one interrupt that triggered (this can
+ * handle any interrupt source).
+ */
+
+/**
+ *	probe_irq_off	- end an interrupt autodetect
+ *	@xmask: mask of potential interrupts (unused)
+ *
+ *	Scans the unused interrupt lines and returns the line which
+ *	appears to have triggered the interrupt. If no interrupt was
+ *	found then zero is returned. If more than one interrupt is
+ *	found then minus the first candidate is returned to indicate
+ *	their is doubt.
+ *
+ *	The interrupt probe logic state is returned to its previous
+ *	value.
+ *
+ *	BUGS: When used in a module (which arguably shouldnt happen)
+ *	nothing prevents two IRQ probe callers from overlapping. The
+ *	results of this are non-optimal.
+ */
+
+int probe_irq_off(unsigned long xmask)
+{
+	up(&probe_sem);
+	return -1;
+}
+
+/* this was setup_x86_irq but it seems pretty generic */
+int setup_irq(unsigned int irq, struct irqaction *new)
+{
+	struct irq_source *source;
+	struct irq_group *group;
+	struct irq_level *level;
+	struct irqaction **p, **pp;
+	unsigned long flags;
+
+	group = irq_groups[irq >> NR_IRQ_LOG2_ACTIONS_PER_GROUP];
+	if (!group)
+		BUG();
+
+	source = group->sources[irq & (NR_IRQ_ACTIONS_PER_GROUP - 1)];
+	if (!source)
+		BUG();
+
+	level = source->level;
+
+	p = &group->actions[irq & (NR_IRQ_ACTIONS_PER_GROUP - 1)];
+
+	/*
+	 * Some drivers like serial.c use request_irq() heavily,
+	 * so we have to be careful not to interfere with a
+	 * running system.
+	 */
+	if (new->flags & SA_SAMPLE_RANDOM) {
+		/*
+		 * This function might sleep, we want to call it first,
+		 * outside of the atomic block.
+		 * Yes, this might clear the entropy pool if the wrong
+		 * driver is attempted to be loaded, without actually
+		 * installing a new handler, but is this really a problem,
+		 * only the sysadmin is able to do this.
+		 */
+		rand_initialize_irq(irq);
+	}
+
+	/* must juggle the interrupt processing stuff with interrupts disabled */
+	spin_lock_irqsave(&level->lock, flags);
+
+	/* can't share interrupts unless all parties agree to */
+	if (level->usage != 0 && !(level->flags & new->flags & SA_SHIRQ)) {
+		spin_unlock_irqrestore(&level->lock,flags);
+		return -EBUSY;
+	}
+
+	/* add new interrupt at end of irq queue */
+	pp = p;
+	while (*pp)
+		pp = &(*pp)->next;
+
+	*pp = new;
+
+	level->usage++;
+	level->flags = new->flags;
+
+	/* turn the interrupts on */
+	if (level->usage == 1)
+		__clr_MASK(level - frv_irq_levels);
+
+	if (p == pp && group->control)
+		group->control(group, irq & (NR_IRQ_ACTIONS_PER_GROUP - 1), 1);
+
+	spin_unlock_irqrestore(&level->lock, flags);
+	register_irq_proc(irq);
+	return 0;
+}
+
+static struct proc_dir_entry * root_irq_dir;
+static struct proc_dir_entry * irq_dir [NR_IRQS];
+
+#define HEX_DIGITS 8
+
+static unsigned int parse_hex_value (const char *buffer,
+				     unsigned long count, unsigned long *ret)
+{
+	unsigned char hexnum [HEX_DIGITS];
+	unsigned long value;
+	int i;
+
+	if (!count)
+		return -EINVAL;
+	if (count > HEX_DIGITS)
+		count = HEX_DIGITS;
+	if (copy_from_user(hexnum, buffer, count))
+		return -EFAULT;
+
+	/*
+	 * Parse the first 8 characters as a hex string, any non-hex char
+	 * is end-of-string. '00e1', 'e1', '00E1', 'E1' are all the same.
+	 */
+	value = 0;
+
+	for (i = 0; i < count; i++) {
+		unsigned int c = hexnum[i];
+
+		switch (c) {
+			case '0' ... '9': c -= '0'; break;
+			case 'a' ... 'f': c -= 'a'-10; break;
+			case 'A' ... 'F': c -= 'A'-10; break;
+		default:
+			goto out;
+		}
+		value = (value << 4) | c;
+	}
+out:
+	*ret = value;
+	return 0;
+}
+
+
+static int prof_cpu_mask_read_proc (char *page, char **start, off_t off,
+			int count, int *eof, void *data)
+{
+	unsigned long *mask = (unsigned long *) data;
+	if (count < HEX_DIGITS+1)
+		return -EINVAL;
+	return sprintf (page, "%08lx\n", *mask);
+}
+
+static int prof_cpu_mask_write_proc (struct file *file, const char *buffer,
+					unsigned long count, void *data)
+{
+	unsigned long *mask = (unsigned long *) data, full_count = count, err;
+	unsigned long new_value;
+
+	show_state();
+	err = parse_hex_value(buffer, count, &new_value);
+	if (err)
+		return err;
+
+	*mask = new_value;
+	return full_count;
+}
+
+#define MAX_NAMELEN 10
+
+static void register_irq_proc (unsigned int irq)
+{
+	char name [MAX_NAMELEN];
+
+	if (!root_irq_dir || irq_dir[irq])
+		return;
+
+	memset(name, 0, MAX_NAMELEN);
+	sprintf(name, "%d", irq);
+
+	/* create /proc/irq/1234 */
+	irq_dir[irq] = proc_mkdir(name, root_irq_dir);
+}
+
+unsigned long prof_cpu_mask = -1;
+
+void init_irq_proc (void)
+{
+	struct proc_dir_entry *entry;
+	int i;
+
+	/* create /proc/irq */
+	root_irq_dir = proc_mkdir("irq", 0);
+
+	/* create /proc/irq/prof_cpu_mask */
+	entry = create_proc_entry("prof_cpu_mask", 0600, root_irq_dir);
+	if (!entry)
+	    return;
+
+	entry->nlink = 1;
+	entry->data = (void *)&prof_cpu_mask;
+	entry->read_proc = prof_cpu_mask_read_proc;
+	entry->write_proc = prof_cpu_mask_write_proc;
+
+	/*
+	 * Create entries for all existing IRQs.
+	 */
+	for (i = 0; i < NR_IRQS; i++)
+		register_irq_proc(i);
+}
+
+/*****************************************************************************/
+/*
+ * initialise the interrupt system
+ */
+void __init init_IRQ(void)
+{
+	route_cpu_irqs();
+	fpga_init();
+#ifdef CONFIG_FUJITSU_MB93493
+	route_mb93493_irqs();
+#endif
+} /* end init_IRQ() */
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/kernel/irq-mb93091.c linux-2.6.10-rc1-mm3-frv/arch/frv/kernel/irq-mb93091.c
--- /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/kernel/irq-mb93091.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/arch/frv/kernel/irq-mb93091.c	2004-11-05 14:13:03.151559284 +0000
@@ -0,0 +1,116 @@
+/* irq-mb93091.c: MB93091 FPGA interrupt handling
+ *
+ * Copyright (C) 2003 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * 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.
+ */
+
+#include <linux/config.h>
+#include <linux/ptrace.h>
+#include <linux/errno.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/ioport.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+
+#include <asm/io.h>
+#include <asm/system.h>
+#include <asm/bitops.h>
+#include <asm/delay.h>
+#include <asm/irq.h>
+#include <asm/irc-regs.h>
+#include <asm/irq-routing.h>
+
+#define __reg16(ADDR) (*(volatile unsigned short *)(ADDR))
+
+#define __get_IMR()	({ __reg16(0xffc00004); })
+#define __set_IMR(M)	do { __reg16(0xffc00004) = (M); wmb(); } while(0)
+#define __get_IFR()	({ __reg16(0xffc0000c); })
+#define __clr_IFR(M)	do { __reg16(0xffc0000c) = ~(M); wmb(); } while(0)
+
+static void frv_fpga_doirq(struct irq_source *source);
+static void frv_fpga_control(struct irq_group *group, int irq, int on);
+
+/*****************************************************************************/
+/*
+ * FPGA IRQ multiplexor
+ */
+static struct irq_source frv_fpga[4] = {
+#define __FPGA(X, M)					\
+	[X] = {						\
+		.muxname	= "fpga."#X,		\
+		.irqmask	= M,			\
+		.doirq		= frv_fpga_doirq,	\
+	}
+
+	__FPGA(0, 0x0028),
+	__FPGA(1, 0x0050),
+	__FPGA(2, 0x1c00),
+	__FPGA(3, 0x6386),
+};
+
+static struct irq_group frv_fpga_irqs = {
+	.first_irq	= IRQ_BASE_FPGA,
+	.control	= frv_fpga_control,
+	.sources = {
+		[ 1] = &frv_fpga[3],
+		[ 2] = &frv_fpga[3],
+		[ 3] = &frv_fpga[0],
+		[ 4] = &frv_fpga[1],
+		[ 5] = &frv_fpga[0],
+		[ 6] = &frv_fpga[1],
+		[ 7] = &frv_fpga[3],
+		[ 8] = &frv_fpga[3],
+		[ 9] = &frv_fpga[3],
+		[10] = &frv_fpga[2],
+		[11] = &frv_fpga[2],
+		[12] = &frv_fpga[2],
+		[13] = &frv_fpga[3],
+		[14] = &frv_fpga[3],
+	},
+};
+
+
+static void frv_fpga_control(struct irq_group *group, int index, int on)
+{
+	uint16_t imr = __get_IMR();
+
+	if (on)
+		imr &= ~(1 << index);
+	else
+		imr |= 1 << index;
+
+	__set_IMR(imr);
+}
+
+static void frv_fpga_doirq(struct irq_source *source)
+{
+	uint16_t mask, imr;
+
+	imr = __get_IMR();
+	mask = source->irqmask & ~imr & __get_IFR();
+	if (mask) {
+		__set_IMR(imr | mask);
+		__clr_IFR(mask);
+		distribute_irqs(&frv_fpga_irqs, mask);
+		__set_IMR(imr);
+	}
+}
+
+void __init fpga_init(void)
+{
+	__set_IMR(0x7ffe);
+	__clr_IFR(0x0000);
+
+	frv_irq_route_external(&frv_fpga[0], IRQ_CPU_EXTERNAL0);
+	frv_irq_route_external(&frv_fpga[1], IRQ_CPU_EXTERNAL1);
+	frv_irq_route_external(&frv_fpga[2], IRQ_CPU_EXTERNAL2);
+	frv_irq_route_external(&frv_fpga[3], IRQ_CPU_EXTERNAL3);
+	frv_irq_set_group(&frv_fpga_irqs);
+}
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/kernel/irq-mb93093.c linux-2.6.10-rc1-mm3-frv/arch/frv/kernel/irq-mb93093.c
--- /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/kernel/irq-mb93093.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/arch/frv/kernel/irq-mb93093.c	2004-11-05 14:13:03.000000000 +0000
@@ -0,0 +1,99 @@
+/* irq-mb93093.c: MB93093 FPGA interrupt handling
+ *
+ * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * 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.
+ */
+
+#include <linux/config.h>
+#include <linux/ptrace.h>
+#include <linux/errno.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/ioport.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+
+#include <asm/io.h>
+#include <asm/system.h>
+#include <asm/bitops.h>
+#include <asm/delay.h>
+#include <asm/irq.h>
+#include <asm/irc-regs.h>
+#include <asm/irq-routing.h>
+
+#define __reg16(ADDR) (*(volatile unsigned short *)(__region_CS2 + (ADDR)))
+
+#define __get_IMR()	({ __reg16(0x0a); })
+#define __set_IMR(M)	do { __reg16(0x0a) = (M);  wmb(); } while(0)
+#define __get_IFR()	({ __reg16(0x02); })
+#define __clr_IFR(M)	do { __reg16(0x02) = ~(M); wmb(); } while(0)
+
+static void frv_fpga_doirq(struct irq_source *source);
+static void frv_fpga_control(struct irq_group *group, int irq, int on);
+
+/*****************************************************************************/
+/*
+ * FPGA IRQ multiplexor
+ */
+static struct irq_source frv_fpga[4] = {
+#define __FPGA(X, M)					\
+	[X] = {						\
+		.muxname	= "fpga."#X,		\
+		.irqmask	= M,			\
+		.doirq		= frv_fpga_doirq,	\
+	}
+
+	__FPGA(0, 0x0700),
+};
+
+static struct irq_group frv_fpga_irqs = {
+	.first_irq	= IRQ_BASE_FPGA,
+	.control	= frv_fpga_control,
+	.sources = {
+		[ 8] = &frv_fpga[0],
+		[ 9] = &frv_fpga[0],
+		[10] = &frv_fpga[0],
+	},
+};
+
+
+static void frv_fpga_control(struct irq_group *group, int index, int on)
+{
+	uint16_t imr = __get_IMR();
+
+	if (on)
+		imr &= ~(1 << index);
+	else
+		imr |= 1 << index;
+
+	__set_IMR(imr);
+}
+
+static void frv_fpga_doirq(struct irq_source *source)
+{
+	uint16_t mask, imr;
+
+	imr = __get_IMR();
+	mask = source->irqmask & ~imr & __get_IFR();
+	if (mask) {
+		__set_IMR(imr | mask);
+		__clr_IFR(mask);
+		distribute_irqs(&frv_fpga_irqs, mask);
+		__set_IMR(imr);
+	}
+}
+
+void __init fpga_init(void)
+{
+	__set_IMR(0x0700);
+	__clr_IFR(0x0000);
+
+	frv_irq_route_external(&frv_fpga[0], IRQ_CPU_EXTERNAL2);
+	frv_irq_set_group(&frv_fpga_irqs);
+}
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/kernel/irq-mb93493.c linux-2.6.10-rc1-mm3-frv/arch/frv/kernel/irq-mb93493.c
--- /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/kernel/irq-mb93493.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/arch/frv/kernel/irq-mb93493.c	2004-11-05 14:13:03.000000000 +0000
@@ -0,0 +1,108 @@
+/* irq-mb93493.c: MB93493 companion chip interrupt handler
+ *
+ * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * 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.
+ */
+
+#include <linux/config.h>
+#include <linux/ptrace.h>
+#include <linux/errno.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/ioport.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+
+#include <asm/io.h>
+#include <asm/system.h>
+#include <asm/bitops.h>
+#include <asm/delay.h>
+#include <asm/irq.h>
+#include <asm/irc-regs.h>
+#include <asm/irq-routing.h>
+#include <asm/mb93493-irqs.h>
+
+static void frv_mb93493_doirq(struct irq_source *source);
+
+/*****************************************************************************/
+/*
+ * MB93493 companion chip IRQ multiplexor
+ */
+static struct irq_source frv_mb93493[2] = {
+	[0] = {
+		.muxname		= "mb93493.0",
+		.muxdata		= __region_CS3 + 0x3d0,
+		.doirq			= frv_mb93493_doirq,
+		.irqmask		= 0x0000,
+	},
+	[1] = {
+		.muxname		= "mb93493.1",
+		.muxdata		= __region_CS3 + 0x3d4,
+		.doirq			= frv_mb93493_doirq,
+		.irqmask		= 0x0000,
+	},
+};
+
+static void frv_mb93493_control(struct irq_group *group, int index, int on)
+{
+	struct irq_source *source;
+	uint32_t iqsr;
+
+	if ((frv_mb93493[0].irqmask & (1 << index)))
+		source = &frv_mb93493[0];
+	else
+		source = &frv_mb93493[1];
+
+	iqsr = readl(source->muxdata);
+	if (on)
+		iqsr |= 1 << (index + 16);
+	else
+		iqsr &= ~(1 << (index + 16));
+
+	writel(iqsr, source->muxdata);
+}
+
+static struct irq_group frv_mb93493_irqs = {
+	.first_irq	= IRQ_BASE_MB93493,
+	.control	= frv_mb93493_control,
+};
+
+static void frv_mb93493_doirq(struct irq_source *source)
+{
+	uint32_t mask = readl(source->muxdata);
+	mask = mask & (mask >> 16) & 0xffff;
+
+	if (mask)
+		distribute_irqs(&frv_mb93493_irqs, mask);
+}
+
+static void __init mb93493_irq_route(int irq, int source)
+{
+	frv_mb93493[source].irqmask |= 1 << (irq - IRQ_BASE_MB93493);
+	frv_mb93493_irqs.sources[irq - IRQ_BASE_MB93493] = &frv_mb93493[source];
+}
+
+void __init route_mb93493_irqs(void)
+{
+	frv_irq_route_external(&frv_mb93493[0], IRQ_CPU_MB93493_0);
+	frv_irq_route_external(&frv_mb93493[1], IRQ_CPU_MB93493_1);
+
+	frv_irq_set_group(&frv_mb93493_irqs);
+
+	mb93493_irq_route(IRQ_MB93493_VDC,		IRQ_MB93493_VDC_ROUTE);
+	mb93493_irq_route(IRQ_MB93493_VCC,		IRQ_MB93493_VCC_ROUTE);
+	mb93493_irq_route(IRQ_MB93493_AUDIO_IN,		IRQ_MB93493_AUDIO_IN_ROUTE);
+	mb93493_irq_route(IRQ_MB93493_I2C_0,		IRQ_MB93493_I2C_0_ROUTE);
+	mb93493_irq_route(IRQ_MB93493_I2C_1,		IRQ_MB93493_I2C_1_ROUTE);
+	mb93493_irq_route(IRQ_MB93493_USB,		IRQ_MB93493_USB_ROUTE);
+	mb93493_irq_route(IRQ_MB93493_LOCAL_BUS,	IRQ_MB93493_LOCAL_BUS_ROUTE);
+	mb93493_irq_route(IRQ_MB93493_PCMCIA,		IRQ_MB93493_PCMCIA_ROUTE);
+	mb93493_irq_route(IRQ_MB93493_GPIO,		IRQ_MB93493_GPIO_ROUTE);
+	mb93493_irq_route(IRQ_MB93493_AUDIO_OUT,	IRQ_MB93493_AUDIO_OUT_ROUTE);
+}
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/kernel/irq-routing.c linux-2.6.10-rc1-mm3-frv/arch/frv/kernel/irq-routing.c
--- /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/kernel/irq-routing.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/arch/frv/kernel/irq-routing.c	2004-11-05 14:13:03.163558271 +0000
@@ -0,0 +1,291 @@
+/* irq-routing.c: IRQ routing
+ *
+ * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * 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.
+ */
+
+#include <linux/sched.h>
+#include <linux/random.h>
+#include <linux/init.h>
+#include <linux/serial_reg.h>
+#include <asm/io.h>
+#include <asm/irq-routing.h>
+#include <asm/irc-regs.h>
+#include <asm/serial-regs.h>
+#include <asm/dma.h>
+
+struct irq_level frv_irq_levels[16] = {
+	[0 ... 15] = {
+		.lock	= SPIN_LOCK_UNLOCKED,
+	}
+};
+
+struct irq_group *irq_groups[NR_IRQ_GROUPS];
+
+extern struct irq_group frv_cpu_irqs;
+
+void __init frv_irq_route(struct irq_source *source, int irqlevel)
+{
+	source->level = &frv_irq_levels[irqlevel];
+	source->next = frv_irq_levels[irqlevel].sources;
+	frv_irq_levels[irqlevel].sources = source;
+}
+
+void __init frv_irq_route_external(struct irq_source *source, int irq)
+{
+	int irqlevel = 0;
+
+	switch (irq) {
+	case IRQ_CPU_EXTERNAL0:	irqlevel = IRQ_XIRQ0_LEVEL; break;
+	case IRQ_CPU_EXTERNAL1:	irqlevel = IRQ_XIRQ1_LEVEL; break;
+	case IRQ_CPU_EXTERNAL2:	irqlevel = IRQ_XIRQ2_LEVEL; break;
+	case IRQ_CPU_EXTERNAL3:	irqlevel = IRQ_XIRQ3_LEVEL; break;
+	case IRQ_CPU_EXTERNAL4:	irqlevel = IRQ_XIRQ4_LEVEL; break;
+	case IRQ_CPU_EXTERNAL5:	irqlevel = IRQ_XIRQ5_LEVEL; break;
+	case IRQ_CPU_EXTERNAL6:	irqlevel = IRQ_XIRQ6_LEVEL; break;
+	case IRQ_CPU_EXTERNAL7:	irqlevel = IRQ_XIRQ7_LEVEL; break;
+	default: BUG();
+	}
+
+	source->level = &frv_irq_levels[irqlevel];
+	source->next = frv_irq_levels[irqlevel].sources;
+	frv_irq_levels[irqlevel].sources = source;
+}
+
+void __init frv_irq_set_group(struct irq_group *group)
+{
+	irq_groups[group->first_irq >> NR_IRQ_LOG2_ACTIONS_PER_GROUP] = group; 
+}
+
+void distribute_irqs(struct irq_group *group, unsigned long irqmask)
+{
+	struct irqaction *action;
+	int irq;
+
+	while (irqmask) {
+		asm("scan %1,gr0,%0" : "=r"(irq) : "r"(irqmask));
+		if (irq < 0 || irq > 31)
+			asm volatile("break");
+		irq = 31 - irq;
+
+		irqmask &= ~(1 << irq);
+		action = group->actions[irq];
+
+		irq += group->first_irq;
+
+		if (action) {
+			int status = 0;
+
+//			if (!(action->flags & SA_INTERRUPT))
+//				sti();
+
+			do {
+				status |= action->flags;
+				action->handler(irq, action->dev_id, __frame);
+				action = action->next;
+			} while (action);
+
+			if (status & SA_SAMPLE_RANDOM)
+				add_interrupt_randomness(irq);
+			cli();
+		}
+	}
+}
+
+/*****************************************************************************/
+/*
+ * CPU UART interrupts
+ */
+static void frv_cpuuart_doirq(struct irq_source *source)
+{
+//	uint8_t iir = readb(source->muxdata + UART_IIR * 8);
+//	if ((iir & 0x0f) != UART_IIR_NO_INT)
+		distribute_irqs(&frv_cpu_irqs, source->irqmask);
+}
+
+struct irq_source frv_cpuuart[2] = {
+#define __CPUUART(X, A)						\
+	[X] = {							\
+		.muxname	= "uart",			\
+		.muxdata	= (volatile void __iomem *) A,	\
+		.irqmask	= 1 << IRQ_CPU_UART##X,		\
+		.doirq		= frv_cpuuart_doirq,		\
+	}
+
+	__CPUUART(0, UART0_BASE),
+	__CPUUART(1, UART1_BASE),
+};
+
+/*****************************************************************************/
+/*
+ * CPU DMA interrupts
+ */
+static void frv_cpudma_doirq(struct irq_source *source)
+{
+	uint32_t cstr = readl(source->muxdata + DMAC_CSTRx);
+	if (cstr & DMAC_CSTRx_INT)
+		distribute_irqs(&frv_cpu_irqs, source->irqmask);
+}
+
+struct irq_source frv_cpudma[8] = {
+#define __CPUDMA(X, A)						\
+	[X] = {							\
+		.muxname	= "dma",			\
+		.muxdata	= (volatile void __iomem *) A,	\
+		.irqmask	= 1 << IRQ_CPU_DMA##X,		\
+		.doirq		= frv_cpudma_doirq,		\
+	}
+
+	__CPUDMA(0, 0xfe000900),
+	__CPUDMA(1, 0xfe000980),
+	__CPUDMA(2, 0xfe000a00),
+	__CPUDMA(3, 0xfe000a80),
+	__CPUDMA(4, 0xfe001000),
+	__CPUDMA(5, 0xfe001080),
+	__CPUDMA(6, 0xfe001100),
+	__CPUDMA(7, 0xfe001180),
+};
+
+/*****************************************************************************/
+/*
+ * CPU timer interrupts - can't tell whether they've generated an interrupt or not
+ */
+static void frv_cputimer_doirq(struct irq_source *source)
+{
+	distribute_irqs(&frv_cpu_irqs, source->irqmask);
+}
+
+struct irq_source frv_cputimer[3] = {
+#define __CPUTIMER(X)						\
+	[X] = {							\
+		.muxname	= "timer",			\
+		.muxdata	= 0,				\
+		.irqmask	= 1 << IRQ_CPU_TIMER##X,	\
+		.doirq		= frv_cputimer_doirq,		\
+	}
+
+	__CPUTIMER(0),
+	__CPUTIMER(1),
+	__CPUTIMER(2),
+};
+
+/*****************************************************************************/
+/*
+ * external CPU interrupts - can't tell directly whether they've generated an interrupt or not
+ */
+static void frv_cpuexternal_doirq(struct irq_source *source)
+{
+	distribute_irqs(&frv_cpu_irqs, source->irqmask);
+}
+
+struct irq_source frv_cpuexternal[8] = {
+#define __CPUEXTERNAL(X)					\
+	[X] = {							\
+		.muxname	= "ext",			\
+		.muxdata	= 0,				\
+		.irqmask	= 1 << IRQ_CPU_EXTERNAL##X,	\
+		.doirq		= frv_cpuexternal_doirq,	\
+	}
+
+	__CPUEXTERNAL(0),
+	__CPUEXTERNAL(1),
+	__CPUEXTERNAL(2),
+	__CPUEXTERNAL(3),
+	__CPUEXTERNAL(4),
+	__CPUEXTERNAL(5),
+	__CPUEXTERNAL(6),
+	__CPUEXTERNAL(7),
+};
+
+#define set_IRR(N,A,B,C,D) __set_IRR(N, (A << 28) | (B << 24) | (C << 20) | (D << 16))
+
+struct irq_group frv_cpu_irqs = {
+	.sources = {
+		[IRQ_CPU_UART0]		= &frv_cpuuart[0],
+		[IRQ_CPU_UART1]		= &frv_cpuuart[1],
+		[IRQ_CPU_TIMER0]	= &frv_cputimer[0],
+		[IRQ_CPU_TIMER1]	= &frv_cputimer[1],
+		[IRQ_CPU_TIMER2]	= &frv_cputimer[2],
+		[IRQ_CPU_DMA0]		= &frv_cpudma[0],
+		[IRQ_CPU_DMA1]		= &frv_cpudma[1],
+		[IRQ_CPU_DMA2]		= &frv_cpudma[2],
+		[IRQ_CPU_DMA3]		= &frv_cpudma[3],
+		[IRQ_CPU_DMA4]		= &frv_cpudma[4],
+		[IRQ_CPU_DMA5]		= &frv_cpudma[5],
+		[IRQ_CPU_DMA6]		= &frv_cpudma[6],
+		[IRQ_CPU_DMA7]		= &frv_cpudma[7],
+		[IRQ_CPU_EXTERNAL0]	= &frv_cpuexternal[0],
+		[IRQ_CPU_EXTERNAL1]	= &frv_cpuexternal[1],
+		[IRQ_CPU_EXTERNAL2]	= &frv_cpuexternal[2],
+		[IRQ_CPU_EXTERNAL3]	= &frv_cpuexternal[3],
+		[IRQ_CPU_EXTERNAL4]	= &frv_cpuexternal[4],
+		[IRQ_CPU_EXTERNAL5]	= &frv_cpuexternal[5],
+		[IRQ_CPU_EXTERNAL6]	= &frv_cpuexternal[6],
+		[IRQ_CPU_EXTERNAL7]	= &frv_cpuexternal[7],
+	},
+};
+
+/*****************************************************************************/
+/*
+ * route the CPU's interrupt sources
+ */
+void __init route_cpu_irqs(void)
+{
+	frv_irq_set_group(&frv_cpu_irqs);
+
+	__set_IITMR(0, 0x003f0000);	/* DMA0-3, TIMER0-2 IRQ detect levels */
+	__set_IITMR(1, 0x20000000);	/* ERR0-1, UART0-1, DMA4-7 IRQ detect levels */
+
+	/* route UART and error interrupts */
+	frv_irq_route(&frv_cpuuart[0],	IRQ_UART0_LEVEL);
+	frv_irq_route(&frv_cpuuart[1],	IRQ_UART1_LEVEL);
+
+	set_IRR(6, IRQ_GDBSTUB_LEVEL, IRQ_GDBSTUB_LEVEL, IRQ_UART1_LEVEL, IRQ_UART0_LEVEL);
+
+	/* route DMA channel interrupts */
+	frv_irq_route(&frv_cpudma[0],	IRQ_DMA0_LEVEL);
+	frv_irq_route(&frv_cpudma[1],	IRQ_DMA1_LEVEL);
+	frv_irq_route(&frv_cpudma[2],	IRQ_DMA2_LEVEL);
+	frv_irq_route(&frv_cpudma[3],	IRQ_DMA3_LEVEL);
+	frv_irq_route(&frv_cpudma[4],	IRQ_DMA4_LEVEL);
+	frv_irq_route(&frv_cpudma[5],	IRQ_DMA5_LEVEL);
+	frv_irq_route(&frv_cpudma[6],	IRQ_DMA6_LEVEL);
+	frv_irq_route(&frv_cpudma[7],	IRQ_DMA7_LEVEL);
+
+	set_IRR(4, IRQ_DMA3_LEVEL, IRQ_DMA2_LEVEL, IRQ_DMA1_LEVEL, IRQ_DMA0_LEVEL);
+	set_IRR(7, IRQ_DMA7_LEVEL, IRQ_DMA6_LEVEL, IRQ_DMA5_LEVEL, IRQ_DMA4_LEVEL);
+
+	/* route timer interrupts */
+	frv_irq_route(&frv_cputimer[0],	IRQ_TIMER0_LEVEL);
+	frv_irq_route(&frv_cputimer[1],	IRQ_TIMER1_LEVEL);
+	frv_irq_route(&frv_cputimer[2],	IRQ_TIMER2_LEVEL);
+
+	set_IRR(5, 0, IRQ_TIMER2_LEVEL, IRQ_TIMER1_LEVEL, IRQ_TIMER0_LEVEL);
+
+	/* route external interrupts */
+	frv_irq_route(&frv_cpuexternal[0], IRQ_XIRQ0_LEVEL);
+	frv_irq_route(&frv_cpuexternal[1], IRQ_XIRQ1_LEVEL);
+	frv_irq_route(&frv_cpuexternal[2], IRQ_XIRQ2_LEVEL);
+	frv_irq_route(&frv_cpuexternal[3], IRQ_XIRQ3_LEVEL);
+	frv_irq_route(&frv_cpuexternal[4], IRQ_XIRQ4_LEVEL);
+	frv_irq_route(&frv_cpuexternal[5], IRQ_XIRQ5_LEVEL);
+	frv_irq_route(&frv_cpuexternal[6], IRQ_XIRQ6_LEVEL);
+	frv_irq_route(&frv_cpuexternal[7], IRQ_XIRQ7_LEVEL);
+
+	set_IRR(2, IRQ_XIRQ7_LEVEL, IRQ_XIRQ6_LEVEL, IRQ_XIRQ5_LEVEL, IRQ_XIRQ4_LEVEL);
+	set_IRR(3, IRQ_XIRQ3_LEVEL, IRQ_XIRQ2_LEVEL, IRQ_XIRQ1_LEVEL, IRQ_XIRQ0_LEVEL);
+
+#if defined(CONFIG_MB93091_VDK)
+	__set_TM1(0x55550000);		/* XIRQ7-0 all active low */
+#elif defined(CONFIG_MB93093_PDK)
+	__set_TM1(0x15550000);		/* XIRQ7 active high, 6-0 all active low */
+#else
+#error dont know external IRQ trigger levels for this setup
+#endif
+
+} /* end route_cpu_irqs() */
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/kernel/kernel_thread.S linux-2.6.10-rc1-mm3-frv/arch/frv/kernel/kernel_thread.S
--- /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/kernel/kernel_thread.S	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/arch/frv/kernel/kernel_thread.S	2004-11-05 14:13:03.171557595 +0000
@@ -0,0 +1,77 @@
+/* kernel_thread.S: kernel thread creation
+ *
+ * Copyright (C) 2003 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * 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.
+ */
+
+#include <linux/linkage.h>
+#include <asm/unistd.h>
+
+#define CLONE_VM	0x00000100	/* set if VM shared between processes */
+#define	KERN_ERR	"<3>"
+
+	.section .rodata
+kernel_thread_emsg:
+	.asciz	KERN_ERR "failed to create kernel thread: error=%d\n"
+
+	.text
+	.balign		4
+
+###############################################################################
+#
+# Create a kernel thread
+#
+# int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
+#
+###############################################################################
+	.globl		kernel_thread
+	.type		kernel_thread,@function
+kernel_thread:
+	or.p		gr8,gr0,gr4
+	or		gr9,gr0,gr5
+
+	# start by forking the current process, but with shared VM
+	setlos.p	#__NR_clone,gr7		; syscall number
+	ori		gr10,#CLONE_VM,gr8	; first syscall arg	[clone_flags]
+	sethi.p		#0xe4e4,gr9		; second syscall arg	[newsp]
+	setlo		#0xe4e4,gr9
+	setlos.p	#0,gr10			; third syscall arg	[parent_tidptr]
+	setlos		#0,gr11			; fourth syscall arg	[child_tidptr]
+	tira		gr0,#0
+	setlos.p	#4095,gr7
+	andcc		gr8,gr8,gr0,icc0
+	addcc.p		gr8,gr7,gr0,icc1
+	bnelr		icc0,#2
+	bc		icc1,#0,kernel_thread_error
+
+	# now invoke the work function
+	or		gr5,gr0,gr8
+	calll		@(gr4,gr0)
+
+	# and finally exit the thread
+	setlos		#__NR_exit,gr7		; syscall number
+	tira		gr0,#0
+
+kernel_thread_error:
+	subi		sp,#8,sp
+	movsg		lr,gr4
+	sti		gr8,@(sp,#0)
+	sti.p		gr4,@(sp,#4)
+
+	or		gr8,gr0,gr9
+	sethi.p		%hi(kernel_thread_emsg),gr8
+	setlo		%lo(kernel_thread_emsg),gr8
+
+	call		printk
+
+	ldi		@(sp,#4),gr4
+	ldi		@(sp,#0),gr8
+	subi		sp,#8,sp
+	jmpl		@(gr4,gr0)
+
+	.size		kernel_thread,.-kernel_thread
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/kernel/local.h linux-2.6.10-rc1-mm3-frv/arch/frv/kernel/local.h
--- /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/kernel/local.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/arch/frv/kernel/local.h	2004-11-05 14:13:03.175557257 +0000
@@ -0,0 +1,56 @@
+/* local.h: local definitions
+ *
+ * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * 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.
+ */
+
+#ifndef _FRV_LOCAL_H
+#define _FRV_LOCAL_H
+
+#include <asm/sections.h>
+
+#ifndef __ASSEMBLY__
+
+/* dma.c */
+extern unsigned long frv_dma_inprogress;
+
+extern void frv_dma_pause_all(void);
+extern void frv_dma_resume_all(void);
+
+/* sleep.S */
+extern asmlinkage void frv_cpu_suspend(unsigned long);
+extern asmlinkage void frv_cpu_core_sleep(void);
+
+/* setup.c */
+extern unsigned long __nongprelbss pdm_suspend_mode;
+extern void determine_clocks(int verbose);
+extern int __nongprelbss clock_p0_current;
+extern int __nongprelbss clock_cm_current;
+extern int __nongprelbss clock_cmode_current;
+
+#ifdef CONFIG_PM
+extern int __nongprelbss clock_cmodes_permitted;
+extern unsigned long __nongprelbss clock_bits_settable;
+#define CLOCK_BIT_CM		0x0000000f
+#define CLOCK_BIT_CM_H		0x00000001	/* CLKC.CM can be set to 0 */
+#define CLOCK_BIT_CM_M		0x00000002	/* CLKC.CM can be set to 1 */
+#define CLOCK_BIT_CM_L		0x00000004	/* CLKC.CM can be set to 2 */
+#define CLOCK_BIT_P0		0x00000010	/* CLKC.P0 can be changed */
+#define CLOCK_BIT_CMODE		0x00000020	/* CLKC.CMODE can be changed */
+
+extern void (*__power_switch_wake_setup)(void);
+extern int  (*__power_switch_wake_check)(void);
+extern void (*__power_switch_wake_cleanup)(void);
+#endif
+
+/* time.c */
+extern void time_divisor_init(void);
+
+
+#endif /* __ASSEMBLY__ */
+#endif /* _FRV_LOCAL_H */
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/kernel/Makefile linux-2.6.10-rc1-mm3-frv/arch/frv/kernel/Makefile
--- /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/kernel/Makefile	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/arch/frv/kernel/Makefile	2004-11-05 14:13:03.179556919 +0000
@@ -0,0 +1,22 @@
+#
+# Makefile for the linux kernel.
+#
+
+heads-y				:= head-uc-fr401.o head-uc-fr451.o head-uc-fr555.o
+heads-$(CONFIG_MMU)		:= head-mmu-fr451.o
+
+extra-y:= head.o init_task.o vmlinux.lds
+
+obj-y := $(heads-y) entry.o entry-table.o break.o switch_to.o kernel_thread.o \
+	 process.o traps.o ptrace.o signal.o dma.o \
+	 sys_frv.o time.o semaphore.o setup.o frv_ksyms.o \
+	 debug-stub.o irq.o irq-routing.o sleep.o uaccess.o
+
+obj-$(CONFIG_GDBSTUB)		+= gdb-stub.o gdb-io.o
+
+obj-$(CONFIG_MB93091_VDK)	+= irq-mb93091.o
+obj-$(CONFIG_MB93093_PDK)	+= irq-mb93093.o
+obj-$(CONFIG_FUJITSU_MB93493)	+= irq-mb93493.o
+obj-$(CONFIG_PM)		+= pm.o cmode.o
+obj-$(CONFIG_MB93093_PDK)	+= pm-mb93093.o
+obj-$(CONFIG_SYSCTL)		+= sysctl.o
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/kernel/pm.c linux-2.6.10-rc1-mm3-frv/arch/frv/kernel/pm.c
--- /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/kernel/pm.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/arch/frv/kernel/pm.c	2004-11-05 14:13:03.184556497 +0000
@@ -0,0 +1,432 @@
+/*
+ * FR-V Power Management Routines
+ *
+ * Copyright (c) 2004 Red Hat, Inc.
+ *
+ * Based on SA1100 version:
+ * Copyright (c) 2001 Cliff Brake <cbrake@accelent.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License.
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/pm.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/sysctl.h>
+#include <linux/errno.h>
+#include <linux/delay.h>
+#include <asm/uaccess.h>
+
+#include <asm/mb86943a.h>
+
+#include "local.h"
+
+void (*pm_power_off)(void);
+
+extern void frv_change_cmode(int);
+
+/*
+ * Debug macros
+ */
+#define DEBUG
+
+int pm_do_suspend(void)
+{
+	cli();
+
+	__set_LEDS(0xb1);
+
+	/* go zzz */
+	frv_cpu_suspend(pdm_suspend_mode);
+
+	__set_LEDS(0xb2);
+
+	sti();
+
+	return 0;
+}
+
+static unsigned long __irq_mask;
+
+/*
+ * Setup interrupt masks, etc to enable wakeup by power switch
+ */
+static void __default_power_switch_setup(void)
+{
+	/* default is to mask all interrupt sources. */
+	__irq_mask = *(unsigned long *)0xfeff9820;
+	*(unsigned long *)0xfeff9820 = 0xfffe0000;
+}
+
+/*
+ * Cleanup interrupt masks, etc after wakeup by power switch
+ */
+static void __default_power_switch_cleanup(void)
+{
+	*(unsigned long *)0xfeff9820 = __irq_mask;
+}
+
+/*
+ * Return non-zero if wakeup irq was caused by power switch
+ */
+static int __default_power_switch_check(void)
+{
+	return 1;
+}
+
+void (*__power_switch_wake_setup)(void) = __default_power_switch_setup;
+int  (*__power_switch_wake_check)(void) = __default_power_switch_check;
+void (*__power_switch_wake_cleanup)(void) = __default_power_switch_cleanup;
+
+int pm_do_bus_sleep(void)
+{
+	cli();
+
+	/*
+         * Here is where we need some platform-dependent setup
+	 * of the interrupt state so that appropriate wakeup
+	 * sources are allowed and all others are masked.
+	 */
+	__power_switch_wake_setup();
+
+	__set_LEDS(0xa1);
+
+	/* go zzz
+	 *
+	 * This is in a loop in case power switch shares an irq with other
+	 * devices. The wake_check() tells us if we need to finish waking
+	 * or go back to sleep.
+	 */
+	do {
+		frv_cpu_suspend(HSR0_PDM_BUS_SLEEP);
+	} while (__power_switch_wake_check && !__power_switch_wake_check());
+
+	__set_LEDS(0xa2);
+
+	/*
+         * Here is where we need some platform-dependent restore
+	 * of the interrupt state prior to being called.
+	 */
+	__power_switch_wake_cleanup();
+
+	sti();
+
+	return 0;
+}
+
+unsigned long sleep_phys_sp(void *sp)
+{
+	return virt_to_phys(sp);
+}
+
+#ifdef CONFIG_SYSCTL
+/*
+ * Use a temporary sysctl number. Horrid, but will be cleaned up in 2.6
+ * when all the PM interfaces exist nicely.
+ */
+#define CTL_PM 9899
+#define CTL_PM_SUSPEND 1
+#define CTL_PM_CMODE 2
+#define CTL_PM_P0 4
+#define CTL_PM_CM 5
+
+static int user_atoi(char *ubuf, int len)
+{
+	char buf[16];
+	unsigned long ret;
+
+	if (len > 15)
+		return -EINVAL;
+
+	if (copy_from_user(buf, ubuf, len))
+		return -EFAULT;
+
+	buf[len] = 0;
+	ret = simple_strtoul(buf, NULL, 0);
+	if (ret > INT_MAX)
+		return -ERANGE;
+	return ret;
+}
+
+/*
+ * Send us to sleep.
+ */
+static int sysctl_pm_do_suspend(ctl_table *ctl, int write, struct file *filp,
+				void *buffer, size_t *lenp, loff_t *fpos)
+{
+	int retval, mode;
+
+	if (*lenp <= 0)
+		return -EIO;
+
+	mode = user_atoi(buffer, *lenp);
+	if ((mode != 1) && (mode != 5))
+		return -EINVAL;
+
+	retval = pm_send_all(PM_SUSPEND, (void *)3);
+
+	if (retval == 0) {
+		if (mode == 5)
+		    retval = pm_do_bus_sleep();
+		else
+		    retval = pm_do_suspend();
+		pm_send_all(PM_RESUME, (void *)0);
+	}
+
+	return retval;
+}
+
+static int try_set_cmode(int new_cmode)
+{
+	if (new_cmode > 15)
+		return -EINVAL;
+	if (!(clock_cmodes_permitted & (1<<new_cmode)))
+		return -EINVAL;
+
+	/* tell all the drivers we're suspending */
+	pm_send_all(PM_SUSPEND, (void *)3);
+
+	/* now change cmode */
+	cli();
+	frv_dma_pause_all();
+
+	frv_change_cmode(new_cmode);
+
+	determine_clocks(0);
+	time_divisor_init();
+
+#ifdef DEBUG
+	determine_clocks(1);
+#endif
+	frv_dma_resume_all();
+	sti();
+
+	/* tell all the drivers we're resuming */
+	pm_send_all(PM_RESUME, (void *)0);
+	return 0;
+}
+
+
+static int cmode_procctl(ctl_table *ctl, int write, struct file *filp,
+			 void *buffer, size_t *lenp, loff_t *fpos)
+{
+	int new_cmode;
+
+	if (!write)
+		return proc_dointvec(ctl, write, filp, buffer, lenp, fpos);
+
+	new_cmode = user_atoi(buffer, *lenp);
+
+	return try_set_cmode(new_cmode)?:*lenp;
+}
+
+static int cmode_sysctl(ctl_table *table, int *name, int nlen,
+			void *oldval, size_t *oldlenp,
+			void *newval, size_t newlen, void **context)
+{
+	if (oldval && oldlenp) {
+		size_t oldlen;
+
+		if (get_user(oldlen, oldlenp))
+			return -EFAULT;
+
+		if (oldlen != sizeof(int))
+			return -EINVAL;
+
+		if (put_user(clock_cmode_current, (unsigned int *)oldval) ||
+		    put_user(sizeof(int), oldlenp))
+			return -EFAULT;
+	}
+	if (newval && newlen) {
+		int new_cmode;
+
+		if (newlen != sizeof(int))
+			return -EINVAL;
+
+		if (get_user(new_cmode, (int *)newval))
+			return -EFAULT;
+
+		return try_set_cmode(new_cmode)?:1;
+	}
+	return 1;
+}
+
+static int try_set_p0(int new_p0)
+{
+	unsigned long flags, clkc;
+
+	if (new_p0 < 0 || new_p0 > 1)
+		return -EINVAL;
+
+	local_irq_save(flags);
+	__set_PSR(flags & ~PSR_ET);
+
+	frv_dma_pause_all();
+
+	clkc = __get_CLKC();
+	if (new_p0)
+		clkc |= CLKC_P0;
+	else
+		clkc &= ~CLKC_P0;
+	__set_CLKC(clkc);
+
+	determine_clocks(0);
+	time_divisor_init();
+
+#ifdef DEBUG
+	determine_clocks(1);
+#endif
+	frv_dma_resume_all();
+	local_irq_restore(flags);
+	return 0;
+}
+
+static int try_set_cm(int new_cm)
+{
+	unsigned long flags, clkc;
+
+	if (new_cm < 0 || new_cm > 1)
+		return -EINVAL;
+
+	local_irq_save(flags);
+	__set_PSR(flags & ~PSR_ET);
+
+	frv_dma_pause_all();
+
+	clkc = __get_CLKC();
+	clkc &= ~CLKC_CM;
+	clkc |= new_cm;
+	__set_CLKC(clkc);
+
+	determine_clocks(0);
+	time_divisor_init();
+
+#if 1 //def DEBUG
+	determine_clocks(1);
+#endif
+
+	frv_dma_resume_all();
+	local_irq_restore(flags);
+	return 0;
+}
+
+static int p0_procctl(ctl_table *ctl, int write, struct file *filp,
+		      void *buffer, size_t *lenp, loff_t *fpos)
+{
+	int new_p0;
+
+	if (!write)
+		return proc_dointvec(ctl, write, filp, buffer, lenp, fpos);
+
+	new_p0 = user_atoi(buffer, *lenp);
+
+	return try_set_p0(new_p0)?:*lenp;
+}
+
+static int p0_sysctl(ctl_table *table, int *name, int nlen,
+		     void *oldval, size_t *oldlenp,
+		     void *newval, size_t newlen, void **context)
+{
+	if (oldval && oldlenp) {
+		size_t oldlen;
+
+		if (get_user(oldlen, oldlenp))
+			return -EFAULT;
+
+		if (oldlen != sizeof(int))
+			return -EINVAL;
+
+		if (put_user(clock_p0_current, (unsigned int *)oldval) ||
+		    put_user(sizeof(int), oldlenp))
+			return -EFAULT;
+	}
+	if (newval && newlen) {
+		int new_p0;
+
+		if (newlen != sizeof(int))
+			return -EINVAL;
+
+		if (get_user(new_p0, (int *)newval))
+			return -EFAULT;
+
+		return try_set_p0(new_p0)?:1;
+	}
+	return 1;
+}
+
+static int cm_procctl(ctl_table *ctl, int write, struct file *filp,
+		      void *buffer, size_t *lenp, loff_t *fpos)
+{
+	int new_cm;
+
+	if (!write)
+		return proc_dointvec(ctl, write, filp, buffer, lenp, fpos);
+
+	new_cm = user_atoi(buffer, *lenp);
+
+	return try_set_cm(new_cm)?:*lenp;
+}
+
+static int cm_sysctl(ctl_table *table, int *name, int nlen,
+		     void *oldval, size_t *oldlenp,
+		     void *newval, size_t newlen, void **context)
+{
+	if (oldval && oldlenp) {
+		size_t oldlen;
+
+		if (get_user(oldlen, oldlenp))
+			return -EFAULT;
+
+		if (oldlen != sizeof(int))
+			return -EINVAL;
+
+		if (put_user(clock_cm_current, (unsigned int *)oldval) ||
+		    put_user(sizeof(int), oldlenp))
+			return -EFAULT;
+	}
+	if (newval && newlen) {
+		int new_cm;
+
+		if (newlen != sizeof(int))
+			return -EINVAL;
+
+		if (get_user(new_cm, (int *)newval))
+			return -EFAULT;
+
+		return try_set_cm(new_cm)?:1;
+	}
+	return 1;
+}
+
+
+static struct ctl_table pm_table[] =
+{
+	{CTL_PM_SUSPEND, "suspend", NULL, 0, 0200, NULL, &sysctl_pm_do_suspend},
+	{CTL_PM_CMODE, "cmode", &clock_cmode_current, sizeof(int), 0644, NULL, &cmode_procctl, &cmode_sysctl, NULL},
+	{CTL_PM_P0, "p0", &clock_p0_current, sizeof(int), 0644, NULL, &p0_procctl, &p0_sysctl, NULL},
+	{CTL_PM_CM, "cm", &clock_cm_current, sizeof(int), 0644, NULL, &cm_procctl, &cm_sysctl, NULL},
+	{0}
+};
+
+static struct ctl_table pm_dir_table[] =
+{
+	{CTL_PM, "pm", NULL, 0, 0555, pm_table},
+	{0}
+};
+
+/*
+ * Initialize power interface
+ */
+static int __init pm_init(void)
+{
+	register_sysctl_table(pm_dir_table, 1);
+	return 0;
+}
+
+__initcall(pm_init);
+
+#endif
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/kernel/pm-mb93093.c linux-2.6.10-rc1-mm3-frv/arch/frv/kernel/pm-mb93093.c
--- /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/kernel/pm-mb93093.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/arch/frv/kernel/pm-mb93093.c	2004-11-05 14:13:03.000000000 +0000
@@ -0,0 +1,66 @@
+/*
+ * FR-V MB93093 Power Management Routines
+ *
+ * Copyright (c) 2004 Red Hat, Inc.
+ *
+ * Written by: msalter@redhat.com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License.
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/pm.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/sysctl.h>
+#include <linux/errno.h>
+#include <linux/delay.h>
+#include <asm/uaccess.h>
+
+#include <asm/mb86943a.h>
+
+#include "local.h"
+
+static unsigned long imask;
+/*
+ * Setup interrupt masks, etc to enable wakeup by power switch
+ */
+static void mb93093_power_switch_setup(void)
+{
+	/* mask all but FPGA interrupt sources. */
+	imask = *(volatile unsigned long *)0xfeff9820;
+	*(volatile unsigned long *)0xfeff9820 = ~(1 << (IRQ_XIRQ2_LEVEL + 16)) & 0xfffe0000;
+}
+
+/*
+ * Cleanup interrupt masks, etc after wakeup by power switch
+ */
+static void mb93093_power_switch_cleanup(void)
+{
+	*(volatile unsigned long *)0xfeff9820 = imask;
+}
+
+/*
+ * Return non-zero if wakeup irq was caused by power switch
+ */
+static int mb93093_power_switch_check(void)
+{
+	return 1;
+}
+
+/*
+ * Initialize power interface
+ */
+static int __init mb93093_pm_init(void)
+{
+	__power_switch_wake_setup = mb93093_power_switch_setup;
+	__power_switch_wake_check = mb93093_power_switch_check;
+	__power_switch_wake_cleanup = mb93093_power_switch_cleanup;
+	return 0;
+}
+
+__initcall(mb93093_pm_init);
+
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/kernel/process.c linux-2.6.10-rc1-mm3-frv/arch/frv/kernel/process.c
--- /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/kernel/process.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/arch/frv/kernel/process.c	2004-11-05 14:13:03.193555737 +0000
@@ -0,0 +1,384 @@
+/*
+ *  linux/arch/m68k/kernel/process.c
+ *
+ *  Copyright (C) 1995  Hamish Macdonald
+ *
+ *  68060 fixes by Jesper Skov
+ *
+ *  uClinux changes Copyright (C) 2000-2002, David McCullough <davidm@snapgear.com>
+ */
+
+/*
+ * This file handles the architecture-dependent parts of process handling..
+ */
+
+#include <linux/config.h>
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/stddef.h>
+#include <linux/unistd.h>
+#include <linux/ptrace.h>
+#include <linux/slab.h>
+#include <linux/user.h>
+#include <linux/elf.h>
+#include <linux/reboot.h>
+#include <linux/interrupt.h>
+
+#include <asm/uaccess.h>
+#include <asm/system.h>
+#include <asm/setup.h>
+#include <asm/pgtable.h>
+#include <asm/gdb-stub.h>
+#include <asm/mb-regs.h>
+
+#include "local.h"
+
+asmlinkage void ret_from_fork(void);
+
+#include <asm/pgalloc.h>
+
+struct task_struct *alloc_task_struct(void)
+{
+	struct task_struct *p = kmalloc(THREAD_SIZE, GFP_KERNEL);
+	if (p)
+		atomic_set((atomic_t *)(p+1), 1);
+	return p;
+}
+
+void free_task_struct(struct task_struct *p)
+{
+	if (atomic_dec_and_test((atomic_t *)(p+1)))
+		kfree(p);
+}
+
+static void core_sleep_idle(void)
+{
+#ifdef LED_DEBUG_SLEEP
+	/* Show that we're sleeping... */
+	__set_LEDS(0x55aa);
+#endif
+	frv_cpu_core_sleep();
+#ifdef LED_DEBUG_SLEEP
+	/* ... and that we woke up */
+	__set_LEDS(0);
+#endif
+	mb();
+}
+
+void (*idle)(void) = core_sleep_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()) {
+			irq_stat[smp_processor_id()].idle_timestamp = jiffies;
+
+			if (!frv_dma_inprogress && idle)
+				idle();
+		}
+
+		schedule();
+	}
+}
+
+void machine_restart(char * __unused)
+{
+#ifdef CONFIG_GDBSTUB
+	gdbstub_exit(0);
+#endif
+
+	/* Software reset. */
+	asm volatile("      dcef @(gr0,gr0),1 ! membar !"
+		     "      sti     %1,@(%0,0) !"
+		     "      nop ! nop ! nop ! nop ! nop ! "
+		     "      nop ! nop ! nop ! nop ! nop ! "
+		     "      nop ! nop ! nop ! nop ! nop ! "
+		     "      nop ! nop ! nop ! nop ! nop ! "
+		     : : "r" (0xfeff0500), "r" (1) );
+
+	for (;;)
+		;
+}
+
+void machine_halt(void)
+{
+#ifdef CONFIG_GDBSTUB
+	gdbstub_exit(0);
+#endif
+
+	for (;;);
+}
+
+void machine_power_off(void)
+{
+#ifdef CONFIG_GDBSTUB
+	gdbstub_exit(0);
+#endif
+
+	for (;;);
+}
+
+void flush_thread(void)
+{
+#if 0 //ndef NO_FPU
+	unsigned long zero = 0;
+#endif
+	set_fs(USER_DS);
+}
+
+inline unsigned long user_stack(const struct pt_regs *regs)
+{
+	while (regs->next_frame)
+		regs = regs->next_frame;
+	return user_mode(regs) ? regs->sp : 0;
+}
+
+asmlinkage int sys_fork(void)
+{
+#ifndef CONFIG_MMU
+	/* fork almost works, enough to trick you into looking elsewhere:-( */
+	return -EINVAL;
+#else
+	return do_fork(SIGCHLD, user_stack(__frame), __frame, 0, NULL, NULL);
+#endif
+}
+
+asmlinkage int sys_vfork(void)
+{
+	return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, user_stack(__frame), __frame, 0,
+		       NULL, NULL);
+}
+
+/*****************************************************************************/
+/*
+ * clone a process
+ * - tlsptr is retrieved by copy_thread()
+ */
+asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp,
+			 int __user *parent_tidptr, int __user *child_tidptr,
+			 int __user *tlsptr)
+{
+	if (!newsp)
+		newsp = user_stack(__frame);
+	return do_fork(clone_flags, newsp, __frame, 0, parent_tidptr, child_tidptr);
+} /* end sys_clone() */
+
+/*****************************************************************************/
+/*
+ * This gets called before we allocate a new thread and copy
+ * the current task into it.
+ */
+void prepare_to_copy(struct task_struct *tsk)
+{
+	//unlazy_fpu(tsk);
+} /* end prepare_to_copy() */
+
+/*****************************************************************************/
+/*
+ * set up the kernel stack and exception frames for a new process
+ */
+int copy_thread(int nr, unsigned long clone_flags,
+		unsigned long usp, unsigned long topstk,
+		struct task_struct *p, struct pt_regs *regs)
+{
+	struct pt_regs *childregs0, *childregs, *regs0;
+
+	regs0 = __kernel_frame0_ptr;
+	childregs0 = (struct pt_regs *)
+		((unsigned long) p->thread_info + THREAD_SIZE - USER_CONTEXT_SIZE);
+	childregs = childregs0;
+
+	/* set up the userspace frame (the only place that the USP is stored) */
+	*childregs0 = *regs0;
+
+	childregs0->gr8		= 0;
+	childregs0->sp		= usp;
+	childregs0->next_frame	= NULL;
+
+	/* set up the return kernel frame if called from kernel_thread() */
+	if (regs != regs0) {
+		childregs--;
+		*childregs = *regs;
+		childregs->sp = (unsigned long) childregs0;
+		childregs->next_frame = childregs0;
+		childregs->gr15 = (unsigned long) p->thread_info;
+		childregs->gr29 = (unsigned long) p;
+	}
+
+	p->set_child_tid = p->clear_child_tid = NULL;
+
+	p->thread.frame	 = childregs;
+	p->thread.curr	 = p;
+	p->thread.sp	 = (unsigned long) childregs;
+	p->thread.fp	 = 0;
+	p->thread.lr	 = 0;
+	p->thread.pc	 = (unsigned long) ret_from_fork;
+	p->thread.frame0 = childregs0;
+
+	/* the new TLS pointer is passed in as arg #5 to sys_clone() */
+	if (clone_flags & CLONE_SETTLS)
+		childregs->gr29 = childregs->gr12;
+
+	save_user_regs(p->thread.user);
+
+	return 0;
+} /* end copy_thread() */
+
+/*
+ * fill in the user structure for a core dump..
+ */
+void dump_thread(struct pt_regs *regs, struct user *dump)
+{
+#if 0
+	/* changed the size calculations - should hopefully work better. lbt */
+	dump->magic = CMAGIC;
+	dump->start_code = 0;
+	dump->start_stack = user_stack(regs) & ~(PAGE_SIZE - 1);
+	dump->u_tsize = ((unsigned long) current->mm->end_code) >> PAGE_SHIFT;
+	dump->u_dsize = ((unsigned long) (current->mm->brk + (PAGE_SIZE-1))) >> PAGE_SHIFT;
+	dump->u_dsize -= dump->u_tsize;
+	dump->u_ssize = 0;
+
+	if (dump->start_stack < TASK_SIZE)
+		dump->u_ssize = ((unsigned long) (TASK_SIZE - dump->start_stack)) >> PAGE_SHIFT;
+
+	dump->regs = *(struct user_context *) regs;
+#endif
+}
+
+/*
+ * sys_execve() executes a new program.
+ */
+asmlinkage int sys_execve(char *name, char **argv, char **envp)
+{
+	int error;
+	char * filename;
+
+	lock_kernel();
+	filename = getname(name);
+	error = PTR_ERR(filename);
+	if (IS_ERR(filename))
+		goto out;
+	error = do_execve(filename, argv, envp, __frame);
+	putname(filename);
+ out:
+	unlock_kernel();
+	return error;
+}
+
+unsigned long get_wchan(struct task_struct *p)
+{
+	struct pt_regs *regs0;
+	unsigned long fp, pc;
+	unsigned long stack_limit;
+	int count = 0;
+	if (!p || p == current || p->state == TASK_RUNNING)
+		return 0;
+
+	stack_limit = (unsigned long) (p + 1);
+	fp = p->thread.fp;
+	regs0 = p->thread.frame0;
+
+	do {
+		if (fp < stack_limit || fp >= (unsigned long) regs0 || fp & 3)
+			return 0;
+
+		pc = ((unsigned long *) fp)[2];
+
+		/* FIXME: This depends on the order of these functions. */
+		if (!in_sched_functions(pc))
+			return pc;
+
+		fp = *(unsigned long *) fp;
+	} while (count++ < 16);
+
+	return 0;
+}
+
+unsigned long thread_saved_pc(struct task_struct *tsk)
+{
+	/* Check whether the thread is blocked in resume() */
+	if (in_sched_functions(tsk->thread.pc))
+		return ((unsigned long *)tsk->thread.fp)[2];
+	else
+		return tsk->thread.pc;
+}
+
+int elf_check_arch(const struct elf32_hdr *hdr)
+{
+	unsigned long hsr0 = __get_HSR(0);
+	unsigned long psr = __get_PSR();
+
+	if (hdr->e_machine != EM_FRV)
+		return 0;
+
+	switch (hdr->e_flags & EF_FRV_GPR_MASK) {
+	case EF_FRV_GPR64:
+		if ((hsr0 & HSR0_GRN) == HSR0_GRN_32)
+			return 0;
+	case EF_FRV_GPR32:
+	case 0:
+		break;
+	default:
+		return 0;
+	}
+
+	switch (hdr->e_flags & EF_FRV_FPR_MASK) {
+	case EF_FRV_FPR64:
+		if ((hsr0 & HSR0_FRN) == HSR0_FRN_32)
+			return 0;
+	case EF_FRV_FPR32:
+	case EF_FRV_FPR_NONE:
+	case 0:
+		break;
+	default:
+		return 0;
+	}
+
+	if ((hdr->e_flags & EF_FRV_MULADD) == EF_FRV_MULADD)
+		if (PSR_IMPLE(psr) != PSR_IMPLE_FR405 &&
+		    PSR_IMPLE(psr) != PSR_IMPLE_FR451)
+			return 0;
+
+	switch (hdr->e_flags & EF_FRV_CPU_MASK) {
+	case EF_FRV_CPU_GENERIC:
+		break;
+	case EF_FRV_CPU_FR300:
+	case EF_FRV_CPU_SIMPLE:
+	case EF_FRV_CPU_TOMCAT:
+	default:
+		return 0;
+	case EF_FRV_CPU_FR400:
+		if (PSR_IMPLE(psr) != PSR_IMPLE_FR401 &&
+		    PSR_IMPLE(psr) != PSR_IMPLE_FR405 &&
+		    PSR_IMPLE(psr) != PSR_IMPLE_FR451 &&
+		    PSR_IMPLE(psr) != PSR_IMPLE_FR551)
+			return 0;
+		break;
+	case EF_FRV_CPU_FR450:
+		if (PSR_IMPLE(psr) != PSR_IMPLE_FR451)
+			return 0;
+		break;
+	case EF_FRV_CPU_FR500:
+		if (PSR_IMPLE(psr) != PSR_IMPLE_FR501)
+			return 0;
+		break;
+	case EF_FRV_CPU_FR550:
+		if (PSR_IMPLE(psr) != PSR_IMPLE_FR551)
+			return 0;
+		break;
+	}
+
+	return 1;
+}

^ permalink raw reply	[flat|nested] 87+ messages in thread

* [PATCH 5/20] FRV: Fujitsu FR-V CPU arch implementation part 3
  2004-11-08 14:34 [PATCH 1/20] FRV: Fujitsu FR-V CPU arch maintainer record dhowells
                   ` (2 preceding siblings ...)
  2004-11-08 14:34 ` [PATCH 4/20] FRV: Fujitsu FR-V CPU arch implementation part 2 dhowells
@ 2004-11-08 14:34 ` dhowells
  2004-11-08 14:34 ` [PATCH 7/20] FRV: Fujitsu FR-V CPU arch implementation part 5 dhowells
                   ` (12 subsequent siblings)
  16 siblings, 0 replies; 87+ messages in thread
From: dhowells @ 2004-11-08 14:34 UTC (permalink / raw)
  To: torvalds, akpm, davidm; +Cc: linux-kernel, uclinux-dev

The attached patches provides part 3 of an architecture implementation
for the Fujitsu FR-V CPU series, configurably as Linux or uClinux.

Signed-Off-By: dhowells@redhat.com
---
diffstat frv-arch_3-2610rc1mm3.diff
 frv_ksyms.c      |  124 +++
 gdb-io.c         |  216 +++++
 gdb-io.h         |   55 +
 gdb-stub.c       | 2082 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 head-mmu-fr451.S |  374 +++++++++
 head.S           |  638 ++++++++++++++++
 head.inc         |   50 +
 7 files changed, 3539 insertions(+)

diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/kernel/frv_ksyms.c linux-2.6.10-rc1-mm3-frv/arch/frv/kernel/frv_ksyms.c
--- /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/kernel/frv_ksyms.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/arch/frv/kernel/frv_ksyms.c	2004-11-05 14:13:03.088564605 +0000
@@ -0,0 +1,124 @@
+#include <linux/module.h>
+#include <linux/linkage.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/user.h>
+#include <linux/elfcore.h>
+#include <linux/in6.h>
+#include <linux/interrupt.h>
+#include <linux/config.h>
+
+#include <asm/setup.h>
+#include <asm/pgalloc.h>
+#include <asm/irq.h>
+#include <asm/io.h>
+#include <asm/semaphore.h>
+#include <asm/checksum.h>
+#include <asm/hardirq.h>
+#include <asm/current.h>
+
+extern void dump_thread(struct pt_regs *, struct user *);
+extern long __memcpy_user(void *dst, const void *src, size_t count);
+
+/* platform dependent support */
+
+EXPORT_SYMBOL(__ioremap);
+EXPORT_SYMBOL(iounmap);
+
+EXPORT_SYMBOL(dump_thread);
+EXPORT_SYMBOL(strnlen);
+EXPORT_SYMBOL(strrchr);
+EXPORT_SYMBOL(strstr);
+EXPORT_SYMBOL(strchr);
+EXPORT_SYMBOL(strcat);
+EXPORT_SYMBOL(strlen);
+EXPORT_SYMBOL(strcmp);
+EXPORT_SYMBOL(strncmp);
+EXPORT_SYMBOL(strncpy);
+
+EXPORT_SYMBOL(ip_fast_csum);
+
+#if 0
+EXPORT_SYMBOL(local_irq_count);
+EXPORT_SYMBOL(local_bh_count);
+#endif
+EXPORT_SYMBOL(kernel_thread);
+
+EXPORT_SYMBOL(enable_irq);
+EXPORT_SYMBOL(disable_irq);
+EXPORT_SYMBOL(__res_bus_clock_speed_HZ);
+EXPORT_SYMBOL(__page_offset);
+EXPORT_SYMBOL(__memcpy_user);
+EXPORT_SYMBOL(flush_dcache_page);
+
+#ifndef CONFIG_MMU
+EXPORT_SYMBOL(memory_start);
+EXPORT_SYMBOL(memory_end);
+#endif
+
+EXPORT_SYMBOL_NOVERS(__debug_bug_trap);
+
+/* Networking helper routines. */
+EXPORT_SYMBOL(csum_partial_copy);
+
+/* 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_NOVERS(memcpy);
+EXPORT_SYMBOL_NOVERS(memset);
+EXPORT_SYMBOL_NOVERS(memcmp);
+EXPORT_SYMBOL_NOVERS(memscan);
+EXPORT_SYMBOL_NOVERS(memmove);
+EXPORT_SYMBOL_NOVERS(strtok);
+
+EXPORT_SYMBOL(get_wchan);
+
+#ifdef CONFIG_FRV_OUTOFLINE_ATOMIC_OPS
+EXPORT_SYMBOL_NOVERS(atomic_test_and_ANDNOT_mask);
+EXPORT_SYMBOL_NOVERS(atomic_test_and_OR_mask);
+EXPORT_SYMBOL_NOVERS(atomic_test_and_XOR_mask);
+EXPORT_SYMBOL_NOVERS(atomic_add_return);
+EXPORT_SYMBOL_NOVERS(atomic_sub_return);
+EXPORT_SYMBOL_NOVERS(__xchg_8);
+EXPORT_SYMBOL_NOVERS(__xchg_16);
+EXPORT_SYMBOL_NOVERS(__xchg_32);
+EXPORT_SYMBOL_NOVERS(__cmpxchg_8);
+EXPORT_SYMBOL_NOVERS(__cmpxchg_16);
+EXPORT_SYMBOL_NOVERS(__cmpxchg_32);
+#endif
+
+/*
+ * libgcc functions - functions that are used internally by the
+ * compiler...  (prototypes are not correct though, but that
+ * doesn't really matter since they're not versioned).
+ */
+extern void __gcc_bcmp(void);
+extern void __ashldi3(void);
+extern void __ashrdi3(void);
+extern void __cmpdi2(void);
+extern void __divdi3(void);
+extern void __lshrdi3(void);
+extern void __moddi3(void);
+extern void __muldi3(void);
+extern void __negdi2(void);
+extern void __ucmpdi2(void);
+extern void __udivdi3(void);
+extern void __udivmoddi4(void);
+extern void __umoddi3(void);
+
+        /* gcc lib functions */
+//EXPORT_SYMBOL_NOVERS(__gcc_bcmp);
+EXPORT_SYMBOL_NOVERS(__ashldi3);
+EXPORT_SYMBOL_NOVERS(__ashrdi3);
+//EXPORT_SYMBOL_NOVERS(__cmpdi2);
+//EXPORT_SYMBOL_NOVERS(__divdi3);
+EXPORT_SYMBOL_NOVERS(__lshrdi3);
+//EXPORT_SYMBOL_NOVERS(__moddi3);
+EXPORT_SYMBOL_NOVERS(__muldi3);
+EXPORT_SYMBOL_NOVERS(__negdi2);
+//EXPORT_SYMBOL_NOVERS(__ucmpdi2);
+//EXPORT_SYMBOL_NOVERS(__udivdi3);
+//EXPORT_SYMBOL_NOVERS(__udivmoddi4);
+//EXPORT_SYMBOL_NOVERS(__umoddi3);
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/kernel/gdb-io.c linux-2.6.10-rc1-mm3-frv/arch/frv/kernel/gdb-io.c
--- /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/kernel/gdb-io.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/arch/frv/kernel/gdb-io.c	2004-11-05 14:13:03.093564183 +0000
@@ -0,0 +1,216 @@
+/* gdb-io.c: FR403 GDB stub I/O
+ *
+ * Copyright (C) 2003 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * 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.
+ */
+
+#include <linux/string.h>
+#include <linux/kernel.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/console.h>
+#include <linux/init.h>
+#include <linux/serial_reg.h>
+
+#include <asm/pgtable.h>
+#include <asm/system.h>
+#include <asm/irc-regs.h>
+#include <asm/timer-regs.h>
+#include <asm/gdb-stub.h>
+#include "gdb-io.h"
+
+#ifdef CONFIG_GDBSTUB_UART0
+#define __UART(X) (*(volatile uint8_t *)(UART0_BASE + (UART_##X)))
+#define __UART_IRR_NMI 0xff0f0000
+#else /* CONFIG_GDBSTUB_UART1 */
+#define __UART(X) (*(volatile uint8_t *)(UART1_BASE + (UART_##X)))
+#define __UART_IRR_NMI 0xfff00000
+#endif
+
+#define LSR_WAIT_FOR(STATE)			\
+do {						\
+	gdbstub_do_rx();			\
+} while (!(__UART(LSR) & UART_LSR_##STATE))
+
+#define FLOWCTL_QUERY(LINE)	({ __UART(MSR) & UART_MSR_##LINE; })
+#define FLOWCTL_CLEAR(LINE)	do { __UART(MCR) &= ~UART_MCR_##LINE; mb(); } while (0)
+#define FLOWCTL_SET(LINE)	do { __UART(MCR) |= UART_MCR_##LINE;  mb(); } while (0)
+
+#define FLOWCTL_WAIT_FOR(LINE)			\
+do {						\
+	gdbstub_do_rx();			\
+} while(!FLOWCTL_QUERY(LINE))
+
+/*****************************************************************************/
+/*
+ * initialise the GDB stub
+ * - called with PSR.ET==0, so can't incur external interrupts
+ */
+void gdbstub_io_init(void)
+{
+	/* set up the serial port */
+	__UART(LCR) = UART_LCR_WLEN8; /* 1N8 */
+	__UART(FCR) =
+		UART_FCR_ENABLE_FIFO |
+		UART_FCR_CLEAR_RCVR |
+		UART_FCR_CLEAR_XMIT |
+		UART_FCR_TRIGGER_1;
+
+	FLOWCTL_CLEAR(DTR);
+	FLOWCTL_SET(RTS);
+
+//	gdbstub_set_baud(115200);
+
+	/* we want to get serial receive interrupts */
+	__UART(IER) = UART_IER_RDI | UART_IER_RLSI;
+	mb();
+
+	__set_IRR(6, __UART_IRR_NMI);	/* map ERRs and UARTx to NMI */
+
+} /* end gdbstub_io_init() */
+
+/*****************************************************************************/
+/*
+ * set up the GDB stub serial port baud rate timers
+ */
+void gdbstub_set_baud(unsigned baud)
+{
+	unsigned value, high, low;
+	u8 lcr;
+
+	/* work out the divisor to give us the nearest higher baud rate */
+	value = __serial_clock_speed_HZ / 16 / baud;
+
+	/* determine the baud rate range */
+	high = __serial_clock_speed_HZ / 16 / value;
+	low = __serial_clock_speed_HZ / 16 / (value + 1);
+
+	/* pick the nearest bound */
+	if (low + (high - low) / 2 > baud)
+		value++;
+
+	lcr = __UART(LCR);
+	__UART(LCR) |= UART_LCR_DLAB;
+	mb();
+	__UART(DLL) = value & 0xff;
+	__UART(DLM) = (value >> 8) & 0xff;
+	mb();
+	__UART(LCR) = lcr;
+	mb();
+
+} /* end gdbstub_set_baud() */
+
+/*****************************************************************************/
+/*
+ * receive characters into the receive FIFO
+ */
+void gdbstub_do_rx(void)
+{
+	unsigned ix, nix;
+
+	ix = gdbstub_rx_inp;
+
+	while (__UART(LSR) & UART_LSR_DR) {
+		nix = (ix + 2) & 0xfff;
+		if (nix == gdbstub_rx_outp)
+			break;
+
+		gdbstub_rx_buffer[ix++] = __UART(LSR);
+		gdbstub_rx_buffer[ix++] = __UART(RX);
+		ix = nix;
+	}
+
+	gdbstub_rx_inp = ix;
+
+	__clr_RC(15);
+	__clr_IRL();
+
+} /* end gdbstub_do_rx() */
+
+/*****************************************************************************/
+/*
+ * wait for a character to come from the debugger
+ */
+int gdbstub_rx_char(unsigned char *_ch, int nonblock)
+{
+	unsigned ix;
+	u8 ch, st;
+
+	*_ch = 0xff;
+
+	if (gdbstub_rx_unget) {
+		*_ch = gdbstub_rx_unget;
+		gdbstub_rx_unget = 0;
+		return 0;
+	}
+
+ try_again:
+	gdbstub_do_rx();
+
+	/* pull chars out of the buffer */
+	ix = gdbstub_rx_outp;
+	if (ix == gdbstub_rx_inp) {
+		if (nonblock)
+			return -EAGAIN;
+		//watchdog_alert_counter = 0;
+		goto try_again;
+	}
+
+	st = gdbstub_rx_buffer[ix++];
+	ch = gdbstub_rx_buffer[ix++];
+	gdbstub_rx_outp = ix & 0x00000fff;
+
+	if (st & UART_LSR_BI) {
+		gdbstub_proto("### GDB Rx Break Detected ###\n");
+		return -EINTR;
+	}
+	else if (st & (UART_LSR_FE|UART_LSR_OE|UART_LSR_PE)) {
+		gdbstub_proto("### GDB Rx Error (st=%02x) ###\n",st);
+		return -EIO;
+	}
+	else {
+		gdbstub_proto("### GDB Rx %02x (st=%02x) ###\n",ch,st);
+		*_ch = ch & 0x7f;
+		return 0;
+	}
+
+} /* end gdbstub_rx_char() */
+
+/*****************************************************************************/
+/*
+ * send a character to the debugger
+ */
+void gdbstub_tx_char(unsigned char ch)
+{
+	FLOWCTL_SET(DTR);
+	LSR_WAIT_FOR(THRE);
+//	FLOWCTL_WAIT_FOR(CTS);
+
+	if (ch == 0x0a) {
+		__UART(TX) = 0x0d;
+		mb();
+		LSR_WAIT_FOR(THRE);
+//		FLOWCTL_WAIT_FOR(CTS);
+	}
+	__UART(TX) = ch;
+	mb();
+
+	FLOWCTL_CLEAR(DTR);
+} /* end gdbstub_tx_char() */
+
+/*****************************************************************************/
+/*
+ * send a character to the debugger
+ */
+void gdbstub_tx_flush(void)
+{
+	LSR_WAIT_FOR(TEMT);
+	LSR_WAIT_FOR(THRE);
+	FLOWCTL_CLEAR(DTR);
+} /* end gdbstub_tx_flush() */
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/kernel/gdb-io.h linux-2.6.10-rc1-mm3-frv/arch/frv/kernel/gdb-io.h
--- /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/kernel/gdb-io.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/arch/frv/kernel/gdb-io.h	2004-11-05 14:13:03.096563929 +0000
@@ -0,0 +1,55 @@
+/* gdb-io.h: FR403 GDB I/O port defs
+ *
+ * Copyright (C) 2003 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * 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.
+ */
+
+#ifndef _GDB_IO_H
+#define _GDB_IO_H
+
+#include <asm/serial-regs.h>
+
+#undef UART_RX
+#undef UART_TX
+#undef UART_DLL
+#undef UART_DLM
+#undef UART_IER
+#undef UART_IIR
+#undef UART_FCR
+#undef UART_LCR
+#undef UART_MCR
+#undef UART_LSR
+#undef UART_MSR
+#undef UART_SCR
+
+#define UART_RX		0*8	/* In:  Receive buffer (DLAB=0) */
+#define UART_TX		0*8	/* Out: Transmit buffer (DLAB=0) */
+#define UART_DLL	0*8	/* Out: Divisor Latch Low (DLAB=1) */
+#define UART_DLM	1*8	/* Out: Divisor Latch High (DLAB=1) */
+#define UART_IER	1*8	/* Out: Interrupt Enable Register */
+#define UART_IIR	2*8	/* In:  Interrupt ID Register */
+#define UART_FCR	2*8	/* Out: FIFO Control Register */
+#define UART_LCR	3*8	/* Out: Line Control Register */
+#define UART_MCR	4*8	/* Out: Modem Control Register */
+#define UART_LSR	5*8	/* In:  Line Status Register */
+#define UART_MSR	6*8	/* In:  Modem Status Register */
+#define UART_SCR	7*8	/* I/O: Scratch Register */
+
+#define UART_LCR_DLAB	0x80	/* Divisor latch access bit */
+#define UART_LCR_SBC	0x40	/* Set break control */
+#define UART_LCR_SPAR	0x20	/* Stick parity (?) */
+#define UART_LCR_EPAR	0x10	/* Even parity select */
+#define UART_LCR_PARITY	0x08	/* Parity Enable */
+#define UART_LCR_STOP	0x04	/* Stop bits: 0=1 stop bit, 1= 2 stop bits */
+#define UART_LCR_WLEN5  0x00	/* Wordlength: 5 bits */
+#define UART_LCR_WLEN6  0x01	/* Wordlength: 6 bits */
+#define UART_LCR_WLEN7  0x02	/* Wordlength: 7 bits */
+#define UART_LCR_WLEN8  0x03	/* Wordlength: 8 bits */
+
+
+#endif /* _GDB_IO_H */
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/kernel/gdb-stub.c linux-2.6.10-rc1-mm3-frv/arch/frv/kernel/gdb-stub.c
--- /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/kernel/gdb-stub.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/arch/frv/kernel/gdb-stub.c	2004-11-05 14:46:41.000000000 +0000
@@ -0,0 +1,2082 @@
+/* gdb-stub.c: FRV GDB stub
+ *
+ * Copyright (C) 2003,4 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ * - Derived from Linux/MIPS version, Copyright (C) 1995 Andreas Busse
+ *
+ * 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.
+ */
+
+/*
+ *  To enable debugger support, two things need to happen.  One, a
+ *  call to set_debug_traps() is necessary in order to allow any breakpoints
+ *  or error conditions to be properly intercepted and reported to gdb.
+ *  Two, a breakpoint needs to be generated to begin communication.  This
+ *  is most easily accomplished by a call to breakpoint().  Breakpoint()
+ *  simulates a breakpoint by executing a BREAK instruction.
+ *
+ *
+ *    The following gdb commands are supported:
+ *
+ * command          function                               Return value
+ *
+ *    g             return the value of the CPU registers  hex data or ENN
+ *    G             set the value of the CPU registers     OK or ENN
+ *
+ *    mAA..AA,LLLL  Read LLLL bytes at address AA..AA      hex data or ENN
+ *    MAA..AA,LLLL: Write LLLL bytes at address AA.AA      OK or ENN
+ *
+ *    c             Resume at current address              SNN   ( signal NN)
+ *    cAA..AA       Continue at address AA..AA             SNN
+ *
+ *    s             Step one instruction                   SNN
+ *    sAA..AA       Step one instruction from AA..AA       SNN
+ *
+ *    k             kill
+ *
+ *    ?             What was the last sigval ?             SNN   (signal NN)
+ *
+ *    bBB..BB	    Set baud rate to BB..BB		   OK or BNN, then sets
+ *							   baud rate
+ *
+ * All commands and responses are sent with a packet which includes a
+ * checksum.  A packet consists of
+ *
+ * $<packet info>#<checksum>.
+ *
+ * where
+ * <packet info> :: <characters representing the command or response>
+ * <checksum>    :: < two hex digits computed as modulo 256 sum of <packetinfo>>
+ *
+ * When a packet is received, it is first acknowledged with either '+' or '-'.
+ * '+' indicates a successful transfer.  '-' indicates a failed transfer.
+ *
+ * Example:
+ *
+ * Host:                  Reply:
+ * $m0,10#2a               +$00010203040506070809101112131415#42
+ *
+ *
+ *  ==============
+ *  MORE EXAMPLES:
+ *  ==============
+ *
+ *  For reference -- the following are the steps that one
+ *  company took (RidgeRun Inc) to get remote gdb debugging
+ *  going. In this scenario the host machine was a PC and the
+ *  target platform was a Galileo EVB64120A MIPS evaluation
+ *  board.
+ *
+ *  Step 1:
+ *  First download gdb-5.0.tar.gz from the internet.
+ *  and then build/install the package.
+ *
+ *  Example:
+ *    $ tar zxf gdb-5.0.tar.gz
+ *    $ cd gdb-5.0
+ *    $ ./configure --target=frv-elf-gdb
+ *    $ make
+ *    $ frv-elf-gdb
+ *
+ *  Step 2:
+ *  Configure linux for remote debugging and build it.
+ *
+ *  Example:
+ *    $ cd ~/linux
+ *    $ make menuconfig <go to "Kernel Hacking" and turn on remote debugging>
+ *    $ make dep; make vmlinux
+ *
+ *  Step 3:
+ *  Download the kernel to the remote target and start
+ *  the kernel running. It will promptly halt and wait
+ *  for the host gdb session to connect. It does this
+ *  since the "Kernel Hacking" option has defined
+ *  CONFIG_REMOTE_DEBUG which in turn enables your calls
+ *  to:
+ *     set_debug_traps();
+ *     breakpoint();
+ *
+ *  Step 4:
+ *  Start the gdb session on the host.
+ *
+ *  Example:
+ *    $ frv-elf-gdb vmlinux
+ *    (gdb) set remotebaud 115200
+ *    (gdb) target remote /dev/ttyS1
+ *    ...at this point you are connected to
+ *       the remote target and can use gdb
+ *       in the normal fasion. Setting
+ *       breakpoints, single stepping,
+ *       printing variables, etc.
+ *
+ */
+
+#include <linux/string.h>
+#include <linux/kernel.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/console.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/nmi.h>
+
+#include <asm/pgtable.h>
+#include <asm/system.h>
+#include <asm/gdb-stub.h>
+
+#define LEDS(x) do { /* *(u32*)0xe1200004 = ~(x); mb(); */ } while(0)
+
+#undef GDBSTUB_DEBUG_PROTOCOL
+
+extern void debug_to_serial(const char *p, int n);
+extern void gdbstub_console_write(struct console *co, const char *p, unsigned n);
+
+extern volatile uint32_t __break_error_detect[3]; /* ESFR1, ESR15, EAR15 */
+extern struct user_context __break_user_context;
+
+struct __debug_amr {
+	unsigned long L, P;
+} __attribute__((aligned(8)));
+
+struct __debug_mmu {
+	struct {
+		unsigned long	hsr0, pcsr, esr0, ear0, epcr0;
+#ifdef CONFIG_MMU
+		unsigned long	tplr, tppr, tpxr, cxnr;
+#endif
+	} regs;
+
+	struct __debug_amr	iamr[16];
+	struct __debug_amr	damr[16];
+
+#ifdef CONFIG_MMU
+	struct __debug_amr	tlb[64*2];
+#endif
+};
+
+static struct __debug_mmu __debug_mmu;
+
+/*
+ * BUFMAX defines the maximum number of characters in inbound/outbound buffers
+ * at least NUMREGBYTES*2 are needed for register packets
+ */
+#define BUFMAX 2048
+
+#define BREAK_INSN	0x801000c0	/* use "break" as bkpt */
+
+static const char gdbstub_banner[] = "Linux/FR-V GDB Stub (c) RedHat 2003\n";
+
+volatile u8	gdbstub_rx_buffer[PAGE_SIZE] __attribute__((aligned(PAGE_SIZE)));
+volatile u32	gdbstub_rx_inp = 0;
+volatile u32	gdbstub_rx_outp = 0;
+volatile u8	gdbstub_rx_overflow = 0;
+u8		gdbstub_rx_unget = 0;
+
+/* set with GDB whilst running to permit step through exceptions */
+extern volatile u32 __attribute__((section(".bss"))) gdbstub_trace_through_exceptions;
+
+static char	input_buffer[BUFMAX];
+static char	output_buffer[BUFMAX];
+
+static const char hexchars[] = "0123456789abcdef";
+
+static const char *regnames[] = {
+	"PSR ", "ISR ", "CCR ", "CCCR",
+	"LR  ", "LCR ", "PC  ", "_stt",
+	"sys ", "GR8*", "GNE0", "GNE1",
+	"IACH", "IACL",
+	"TBR ", "SP  ", "FP  ", "GR3 ",
+	"GR4 ", "GR5 ", "GR6 ", "GR7 ",
+	"GR8 ", "GR9 ", "GR10", "GR11",
+	"GR12", "GR13", "GR14", "GR15",
+	"GR16", "GR17", "GR18", "GR19",
+	"GR20", "GR21", "GR22", "GR23",
+	"GR24", "GR25", "GR26", "GR27",
+	"EFRM", "CURR", "GR30", "BFRM"
+};
+
+struct gdbstub_bkpt {
+	unsigned long	addr;		/* address of breakpoint */
+	unsigned	len;		/* size of breakpoint */
+	uint32_t	originsns[7];	/* original instructions */
+};
+
+static struct gdbstub_bkpt gdbstub_bkpts[256];
+
+/*
+ * local prototypes
+ */
+
+static void gdbstub_recv_packet(char *buffer);
+static int gdbstub_send_packet(char *buffer);
+static int gdbstub_compute_signal(unsigned long tbr);
+static int hex(unsigned char ch);
+static int hexToInt(char **ptr, unsigned long *intValue);
+static unsigned char *mem2hex(const void *mem, char *buf, int count, int may_fault);
+static char *hex2mem(const char *buf, void *_mem, int count);
+
+/*
+ * Convert ch from a hex digit to an int
+ */
+static int hex(unsigned char ch)
+{
+	if (ch >= 'a' && ch <= 'f')
+		return ch-'a'+10;
+	if (ch >= '0' && ch <= '9')
+		return ch-'0';
+	if (ch >= 'A' && ch <= 'F')
+		return ch-'A'+10;
+	return -1;
+}
+
+void gdbstub_printk(const char *fmt, ...)
+{
+	static char buf[1024];
+	va_list args;
+	int len;
+
+	/* Emit the output into the temporary buffer */
+	va_start(args, fmt);
+	len = vsnprintf(buf, sizeof(buf), fmt, args);
+	va_end(args);
+	debug_to_serial(buf, len);
+}
+
+static inline char *gdbstub_strcpy(char *dst, const char *src)
+{
+	int loop = 0;
+	while ((dst[loop] = src[loop]))
+	       loop++;
+	return dst;
+}
+
+static void gdbstub_purge_cache(void)
+{
+	asm volatile("	dcef	@(gr0,gr0),#1	\n"
+		     "	icei	@(gr0,gr0),#1	\n"
+		     "	membar			\n"
+		     "	bar			\n"
+		     );
+}
+
+/*****************************************************************************/
+/*
+ * scan for the sequence $<data>#<checksum>
+ */
+static void gdbstub_recv_packet(char *buffer)
+{
+	unsigned char checksum;
+	unsigned char xmitcsum;
+	unsigned char ch;
+	int count, i, ret, error;
+
+	for (;;) {
+		/* wait around for the start character, ignore all other characters */
+		do {
+			gdbstub_rx_char(&ch, 0);
+		} while (ch != '$');
+
+		checksum = 0;
+		xmitcsum = -1;
+		count = 0;
+		error = 0;
+
+		/* now, read until a # or end of buffer is found */
+		while (count < BUFMAX) {
+			ret = gdbstub_rx_char(&ch, 0);
+			if (ret < 0)
+				error = ret;
+
+			if (ch == '#')
+				break;
+			checksum += ch;
+			buffer[count] = ch;
+			count++;
+		}
+
+		if (error == -EIO) {
+			gdbstub_proto("### GDB Rx Error - Skipping packet ###\n");
+			gdbstub_proto("### GDB Tx NAK\n");
+			gdbstub_tx_char('-');
+			continue;
+		}
+
+		if (count >= BUFMAX || error)
+			continue;
+
+		buffer[count] = 0;
+
+		/* read the checksum */
+		ret = gdbstub_rx_char(&ch, 0);
+		if (ret < 0)
+			error = ret;
+		xmitcsum = hex(ch) << 4;
+
+		ret = gdbstub_rx_char(&ch, 0);
+		if (ret < 0)
+			error = ret;
+		xmitcsum |= hex(ch);
+
+		if (error) {
+			if (error == -EIO)
+				gdbstub_proto("### GDB Rx Error - Skipping packet\n");
+			gdbstub_proto("### GDB Tx NAK\n");
+			gdbstub_tx_char('-');
+			continue;
+		}
+
+		/* check the checksum */
+		if (checksum != xmitcsum) {
+			gdbstub_proto("### GDB Tx NAK\n");
+			gdbstub_tx_char('-');	/* failed checksum */
+			continue;
+		}
+
+		gdbstub_proto("### GDB Rx '$%s#%02x' ###\n", buffer, checksum);
+		gdbstub_proto("### GDB Tx ACK\n");
+		gdbstub_tx_char('+'); /* successful transfer */
+
+		/* if a sequence char is present, reply the sequence ID */
+		if (buffer[2] == ':') {
+			gdbstub_tx_char(buffer[0]);
+			gdbstub_tx_char(buffer[1]);
+
+			/* remove sequence chars from buffer */
+			count = 0;
+			while (buffer[count]) count++;
+			for (i=3; i <= count; i++)
+				buffer[i - 3] = buffer[i];
+		}
+
+		break;
+	}
+} /* end gdbstub_recv_packet() */
+
+/*****************************************************************************/
+/*
+ * send the packet in buffer.
+ * - return 0 if successfully ACK'd
+ * - return 1 if abandoned due to new incoming packet
+ */
+static int gdbstub_send_packet(char *buffer)
+{
+	unsigned char checksum;
+	int count;
+	unsigned char ch;
+
+	/* $<packet info>#<checksum> */
+	gdbstub_proto("### GDB Tx '%s' ###\n", buffer);
+
+	do {
+		gdbstub_tx_char('$');
+		checksum = 0;
+		count = 0;
+
+		while ((ch = buffer[count]) != 0) {
+			gdbstub_tx_char(ch);
+			checksum += ch;
+			count += 1;
+		}
+
+		gdbstub_tx_char('#');
+		gdbstub_tx_char(hexchars[checksum >> 4]);
+		gdbstub_tx_char(hexchars[checksum & 0xf]);
+
+	} while (gdbstub_rx_char(&ch,0),
+#ifdef GDBSTUB_DEBUG_PROTOCOL
+		 ch=='-' && (gdbstub_proto("### GDB Rx NAK\n"),0),
+		 ch!='-' && ch!='+' && (gdbstub_proto("### GDB Rx ??? %02x\n",ch),0),
+#endif
+		 ch!='+' && ch!='$');
+
+	if (ch=='+') {
+		gdbstub_proto("### GDB Rx ACK\n");
+		return 0;
+	}
+
+	gdbstub_proto("### GDB Tx Abandoned\n");
+	gdbstub_rx_unget = ch;
+	return 1;
+} /* end gdbstub_send_packet() */
+
+/*
+ * While we find nice hex chars, build an int.
+ * Return number of chars processed.
+ */
+static int hexToInt(char **ptr, unsigned long *_value)
+{
+	int count = 0, ch;
+
+	*_value = 0;
+	while (**ptr) {
+		ch = hex(**ptr);
+		if (ch < 0)
+			break;
+
+		*_value = (*_value << 4) | ((uint8_t) ch & 0xf);
+		count++;
+
+		(*ptr)++;
+	}
+
+	return count;
+}
+
+/*****************************************************************************/
+/*
+ * probe an address to see whether it maps to anything
+ */
+static inline int gdbstub_addr_probe(const void *vaddr)
+{
+#ifdef CONFIG_MMU
+	unsigned long paddr;
+
+	asm("lrad %1,%0,#1,#0,#0" : "=r"(paddr) : "r"(vaddr));
+	if (!(paddr & xAMPRx_V))
+		return 0;
+#endif
+
+	return 1;
+} /* end gdbstub_addr_probe() */
+
+#ifdef CONFIG_MMU
+static unsigned long __saved_dampr, __saved_damlr;
+
+static inline unsigned long gdbstub_virt_to_pte(unsigned long vaddr)
+{
+	pgd_t *pgd;
+	pmd_t *pmd;
+	pte_t *pte;
+	unsigned long val, dampr5;
+
+	pgd = (pgd_t *) __get_DAMLR(3) + pgd_index(vaddr);
+	pmd = pmd_offset(pgd, vaddr);
+
+	if (pmd_bad(*pmd) || !pmd_present(*pmd))
+		return 0;
+
+	/* make sure dampr5 maps to the correct pmd */
+	dampr5 = __get_DAMPR(5);
+	val = pmd_val(*pmd);
+	__set_DAMPR(5, val | xAMPRx_L | xAMPRx_SS_16Kb | xAMPRx_S | xAMPRx_C | xAMPRx_V);
+
+	/* now its safe to access pmd */
+	pte = (pte_t *)__get_DAMLR(5) + __pte_index(vaddr);
+	if (pte_present(*pte))
+		val = pte_val(*pte);
+	else
+		val = 0;
+
+	/* restore original dampr5 */
+	__set_DAMPR(5, dampr5);
+
+	return val;
+}
+#endif
+
+static inline int gdbstub_addr_map(const void *vaddr)
+{
+#ifdef CONFIG_MMU
+	unsigned long pte;
+
+	__saved_dampr = __get_DAMPR(2);
+	__saved_damlr = __get_DAMLR(2);
+#endif
+	if (gdbstub_addr_probe(vaddr))
+		return 1;
+#ifdef CONFIG_MMU
+	pte = gdbstub_virt_to_pte((unsigned long) vaddr);
+	if (pte) {
+		__set_DAMPR(2, pte);
+		__set_DAMLR(2, (unsigned long) vaddr & PAGE_MASK);
+		return 1;
+	}
+#endif
+	return 0;
+}
+
+static inline void gdbstub_addr_unmap(void)
+{
+#ifdef CONFIG_MMU
+	__set_DAMPR(2, __saved_dampr);
+	__set_DAMLR(2, __saved_damlr);
+#endif
+}
+
+/*
+ * access potentially dodgy memory through a potentially dodgy pointer
+ */
+static inline int gdbstub_read_dword(const void *addr, uint32_t *_res)
+{
+	unsigned long brr;
+	uint32_t res;
+
+	if (!gdbstub_addr_map(addr))
+		return 0;
+
+	asm volatile("	movgs	gr0,brr	\n"
+		     "	ld%I2	%M2,%0	\n"
+		     "	movsg	brr,%1	\n"
+		     : "=r"(res), "=r"(brr)
+		     : "m"(*(uint32_t *) addr));
+	*_res = res;
+	gdbstub_addr_unmap();
+	return likely(!brr);
+}
+
+static inline int gdbstub_write_dword(void *addr, uint32_t val)
+{
+	unsigned long brr;
+
+	if (!gdbstub_addr_map(addr))
+		return 0;
+
+	asm volatile("	movgs	gr0,brr	\n"
+		     "	st%I2	%1,%M2	\n"
+		     "	movsg	brr,%0	\n"
+		     : "=r"(brr)
+		     : "r"(val), "m"(*(uint32_t *) addr));
+	gdbstub_addr_unmap();
+	return likely(!brr);
+}
+
+static inline int gdbstub_read_word(const void *addr, uint16_t *_res)
+{
+	unsigned long brr;
+	uint16_t res;
+
+	if (!gdbstub_addr_map(addr))
+		return 0;
+
+	asm volatile("	movgs	gr0,brr	\n"
+		     "	lduh%I2	%M2,%0	\n"
+		     "	movsg	brr,%1	\n"
+		     : "=r"(res), "=r"(brr)
+		     : "m"(*(uint16_t *) addr));
+	*_res = res;
+	gdbstub_addr_unmap();
+	return likely(!brr);
+}
+
+static inline int gdbstub_write_word(void *addr, uint16_t val)
+{
+	unsigned long brr;
+
+	if (!gdbstub_addr_map(addr))
+		return 0;
+
+	asm volatile("	movgs	gr0,brr	\n"
+		     "	sth%I2	%1,%M2	\n"
+		     "	movsg	brr,%0	\n"
+		     : "=r"(brr)
+		     : "r"(val), "m"(*(uint16_t *) addr));
+	gdbstub_addr_unmap();
+	return likely(!brr);
+}
+
+static inline int gdbstub_read_byte(const void *addr, uint8_t *_res)
+{
+	unsigned long brr;
+	uint8_t res;
+
+	if (!gdbstub_addr_map(addr))
+		return 0;
+
+	asm volatile("	movgs	gr0,brr	\n"
+		     "	ldub%I2	%M2,%0	\n"
+		     "	movsg	brr,%1	\n"
+		     : "=r"(res), "=r"(brr)
+		     : "m"(*(uint8_t *) addr));
+	*_res = res;
+	gdbstub_addr_unmap();
+	return likely(!brr);
+}
+
+static inline int gdbstub_write_byte(void *addr, uint8_t val)
+{
+	unsigned long brr;
+
+	if (!gdbstub_addr_map(addr))
+		return 0;
+
+	asm volatile("	movgs	gr0,brr	\n"
+		     "	stb%I2	%1,%M2	\n"
+		     "	movsg	brr,%0	\n"
+		     : "=r"(brr)
+		     : "r"(val), "m"(*(uint8_t *) addr));
+	gdbstub_addr_unmap();
+	return likely(!brr);
+}
+
+static void __gdbstub_console_write(struct console *co, const char *p, unsigned n)
+{
+	char outbuf[26];
+	int qty;
+
+	outbuf[0] = 'O';
+
+	while (n > 0) {
+		qty = 1;
+
+		while (n > 0 && qty < 20) {
+			mem2hex(p, outbuf + qty, 2, 0);
+			qty += 2;
+			if (*p == 0x0a) {
+				outbuf[qty++] = '0';
+				outbuf[qty++] = 'd';
+			}
+			p++;
+			n--;
+		}
+
+		outbuf[qty] = 0;
+		gdbstub_send_packet(outbuf);
+	}
+}
+
+#if 0
+void debug_to_serial(const char *p, int n)
+{
+	gdbstub_console_write(NULL,p,n);
+}
+#endif
+
+#ifdef CONFIG_GDBSTUB_CONSOLE
+
+static kdev_t gdbstub_console_dev(struct console *con)
+{
+	return MKDEV(1,3); /* /dev/null */
+}
+
+static struct console gdbstub_console = {
+	.name	= "gdb",
+	.write	= gdbstub_console_write,	/* in break.S */
+	.device	= gdbstub_console_dev,
+	.flags	= CON_PRINTBUFFER,
+	.index	= -1,
+};
+
+#endif
+
+/*****************************************************************************/
+/*
+ * Convert the memory pointed to by mem into hex, placing result in buf.
+ * - if successful, return a pointer to the last char put in buf (NUL)
+ * - in case of mem fault, return NULL
+ * may_fault is non-zero if we are reading from arbitrary memory, but is currently
+ * not used.
+ */
+static unsigned char *mem2hex(const void *_mem, char *buf, int count, int may_fault)
+{
+	const uint8_t *mem = _mem;
+	uint8_t ch[4] __attribute__((aligned(4)));
+
+	if ((uint32_t)mem&1 && count>=1) {
+		if (!gdbstub_read_byte(mem,ch))
+			return NULL;
+		*buf++ = hexchars[ch[0] >> 4];
+		*buf++ = hexchars[ch[0] & 0xf];
+		mem++;
+		count--;
+	}
+
+	if ((uint32_t)mem&3 && count>=2) {
+		if (!gdbstub_read_word(mem,(uint16_t *)ch))
+			return NULL;
+		*buf++ = hexchars[ch[0] >> 4];
+		*buf++ = hexchars[ch[0] & 0xf];
+		*buf++ = hexchars[ch[1] >> 4];
+		*buf++ = hexchars[ch[1] & 0xf];
+		mem += 2;
+		count -= 2;
+	}
+
+	while (count>=4) {
+		if (!gdbstub_read_dword(mem,(uint32_t *)ch))
+			return NULL;
+		*buf++ = hexchars[ch[0] >> 4];
+		*buf++ = hexchars[ch[0] & 0xf];
+		*buf++ = hexchars[ch[1] >> 4];
+		*buf++ = hexchars[ch[1] & 0xf];
+		*buf++ = hexchars[ch[2] >> 4];
+		*buf++ = hexchars[ch[2] & 0xf];
+		*buf++ = hexchars[ch[3] >> 4];
+		*buf++ = hexchars[ch[3] & 0xf];
+		mem += 4;
+		count -= 4;
+	}
+
+	if (count>=2) {
+		if (!gdbstub_read_word(mem,(uint16_t *)ch))
+			return NULL;
+		*buf++ = hexchars[ch[0] >> 4];
+		*buf++ = hexchars[ch[0] & 0xf];
+		*buf++ = hexchars[ch[1] >> 4];
+		*buf++ = hexchars[ch[1] & 0xf];
+		mem += 2;
+		count -= 2;
+	}
+
+	if (count>=1) {
+		if (!gdbstub_read_byte(mem,ch))
+			return NULL;
+		*buf++ = hexchars[ch[0] >> 4];
+		*buf++ = hexchars[ch[0] & 0xf];
+	}
+
+	*buf = 0;
+
+	return buf;
+} /* end mem2hex() */
+
+/*****************************************************************************/
+/*
+ * convert the hex array pointed to by buf into binary to be placed in mem
+ * return a pointer to the character AFTER the last byte of buffer consumed
+ */
+static char *hex2mem(const char *buf, void *_mem, int count)
+{
+	uint8_t *mem = _mem;
+	union {
+		uint32_t l;
+		uint16_t w;
+		uint8_t  b[4];
+	} ch;
+
+	if ((u32)mem&1 && count>=1) {
+		ch.b[0]  = hex(*buf++) << 4;
+		ch.b[0] |= hex(*buf++);
+		if (!gdbstub_write_byte(mem,ch.b[0]))
+			return NULL;
+		mem++;
+		count--;
+	}
+
+	if ((u32)mem&3 && count>=2) {
+		ch.b[0]  = hex(*buf++) << 4;
+		ch.b[0] |= hex(*buf++);
+		ch.b[1]  = hex(*buf++) << 4;
+		ch.b[1] |= hex(*buf++);
+		if (!gdbstub_write_word(mem,ch.w))
+			return NULL;
+		mem += 2;
+		count -= 2;
+	}
+
+	while (count>=4) {
+		ch.b[0]  = hex(*buf++) << 4;
+		ch.b[0] |= hex(*buf++);
+		ch.b[1]  = hex(*buf++) << 4;
+		ch.b[1] |= hex(*buf++);
+		ch.b[2]  = hex(*buf++) << 4;
+		ch.b[2] |= hex(*buf++);
+		ch.b[3]  = hex(*buf++) << 4;
+		ch.b[3] |= hex(*buf++);
+		if (!gdbstub_write_dword(mem,ch.l))
+			return NULL;
+		mem += 4;
+		count -= 4;
+	}
+
+	if (count>=2) {
+		ch.b[0]  = hex(*buf++) << 4;
+		ch.b[0] |= hex(*buf++);
+		ch.b[1]  = hex(*buf++) << 4;
+		ch.b[1] |= hex(*buf++);
+		if (!gdbstub_write_word(mem,ch.w))
+			return NULL;
+		mem += 2;
+		count -= 2;
+	}
+
+	if (count>=1) {
+		ch.b[0]  = hex(*buf++) << 4;
+		ch.b[0] |= hex(*buf++);
+		if (!gdbstub_write_byte(mem,ch.b[0]))
+			return NULL;
+	}
+
+	return (char *) buf;
+} /* end hex2mem() */
+
+/*****************************************************************************/
+/*
+ * This table contains the mapping between FRV TBR.TT exception codes,
+ * and signals, which are primarily what GDB understands.  It also
+ * indicates which hardware traps we need to commandeer when
+ * initializing the stub.
+ */
+static const struct brr_to_sig_map {
+	unsigned long	brr_mask;	/* BRR bitmask */
+	unsigned long	tbr_tt;		/* TBR.TT code (in BRR.EBTT) */
+	unsigned int	signo;		/* Signal that we map this into */
+} brr_to_sig_map[] = {
+	{ BRR_EB,	TBR_TT_INSTR_ACC_ERROR,	SIGSEGV		},
+	{ BRR_EB,	TBR_TT_ILLEGAL_INSTR,	SIGILL		},
+	{ BRR_EB,	TBR_TT_PRIV_INSTR,	SIGILL		},
+	{ BRR_EB,	TBR_TT_MP_EXCEPTION,	SIGFPE		},
+	{ BRR_EB,	TBR_TT_DATA_ACC_ERROR,	SIGSEGV		},
+	{ BRR_EB,	TBR_TT_DATA_STR_ERROR,	SIGSEGV		},
+	{ BRR_EB,	TBR_TT_DIVISION_EXCEP,	SIGFPE		},
+	{ BRR_EB,	TBR_TT_COMPOUND_EXCEP,	SIGSEGV		},
+	{ BRR_EB,	TBR_TT_INTERRUPT_13,	SIGALRM		},	/* watchdog */
+	{ BRR_EB,	TBR_TT_INTERRUPT_14,	SIGINT		},	/* GDB serial */
+	{ BRR_EB,	TBR_TT_INTERRUPT_15,	SIGQUIT		},	/* NMI */
+	{ BRR_CB,	0,			SIGUSR1		},
+	{ BRR_TB,	0,			SIGUSR2		},
+	{ BRR_DBNEx,	0,			SIGTRAP		},
+	{ BRR_DBx,	0,			SIGTRAP		},	/* h/w watchpoint */
+	{ BRR_IBx,	0,			SIGTRAP		},	/* h/w breakpoint */
+	{ BRR_CBB,	0,			SIGTRAP		},
+	{ BRR_SB,	0,			SIGTRAP		},
+	{ BRR_ST,	0,			SIGTRAP		},	/* single step */
+	{ 0,		0,			SIGHUP		}	/* default */
+};
+
+/*****************************************************************************/
+/*
+ * convert the FRV BRR register contents into a UNIX signal number
+ */
+static inline int gdbstub_compute_signal(unsigned long brr)
+{
+	const struct brr_to_sig_map *map;
+	unsigned long tbr = (brr & BRR_EBTT) >> 12;
+
+	for (map = brr_to_sig_map; map->brr_mask; map++)
+		if (map->brr_mask & brr)
+			if (!map->tbr_tt || map->tbr_tt == tbr)
+				break;
+
+	return map->signo;
+} /* end gdbstub_compute_signal() */
+
+/*****************************************************************************/
+/*
+ * set a software breakpoint or a hardware breakpoint or watchpoint
+ */
+static int gdbstub_set_breakpoint(unsigned long type, unsigned long addr, unsigned long len)
+{
+	unsigned long tmp;
+	int bkpt, loop, xloop;
+
+	union {
+		struct {
+			unsigned long mask0, mask1;
+		};
+		uint8_t bytes[8];
+	} dbmr;
+
+	//gdbstub_printk("setbkpt(%ld,%08lx,%ld)\n", type, addr, len);
+
+	switch (type) {
+		/* set software breakpoint */
+	case 0:
+		if (addr & 3 || len > 7*4)
+			return -EINVAL;
+
+		for (bkpt = 255; bkpt >= 0; bkpt--)
+			if (!gdbstub_bkpts[bkpt].addr)
+				break;
+		if (bkpt < 0)
+			return -ENOSPC;
+
+		for (loop = 0; loop < len/4; loop++)
+			if (!gdbstub_read_dword(&((uint32_t *) addr)[loop],
+						&gdbstub_bkpts[bkpt].originsns[loop]))
+				return -EFAULT;
+
+		for (loop = 0; loop < len/4; loop++)
+			if (!gdbstub_write_dword(&((uint32_t *) addr)[loop],
+						 BREAK_INSN)
+			    ) {
+				/* need to undo the changes if possible */
+				for (xloop = 0; xloop < loop; xloop++)
+					gdbstub_write_dword(&((uint32_t *) addr)[xloop],
+							    gdbstub_bkpts[bkpt].originsns[xloop]);
+				return -EFAULT;
+			}
+
+		gdbstub_bkpts[bkpt].addr = addr;
+		gdbstub_bkpts[bkpt].len = len;
+
+#if 0
+		gdbstub_printk("Set BKPT[%02x]: %08lx #%d {%04x, %04x} -> { %04x, %04x }\n",
+			       bkpt,
+			       gdbstub_bkpts[bkpt].addr,
+			       gdbstub_bkpts[bkpt].len,
+			       gdbstub_bkpts[bkpt].originsns[0],
+			       gdbstub_bkpts[bkpt].originsns[1],
+			       ((uint32_t *) addr)[0],
+			       ((uint32_t *) addr)[1]
+			       );
+#endif
+		return 0;
+
+		/* set hardware breakpoint */
+	case 1:
+		if (addr & 3 || len != 4)
+			return -EINVAL;
+
+		if (!(__debug_regs->dcr & DCR_IBE0)) {
+			//gdbstub_printk("set h/w break 0: %08lx\n", addr);
+			__debug_regs->dcr |= DCR_IBE0;
+			asm volatile("movgs %0,ibar0" : : "r"(addr));
+			return 0;
+		}
+
+		if (!(__debug_regs->dcr & DCR_IBE1)) {
+			//gdbstub_printk("set h/w break 1: %08lx\n", addr);
+			__debug_regs->dcr |= DCR_IBE1;
+			asm volatile("movgs %0,ibar1" : : "r"(addr));
+			return 0;
+		}
+
+		if (!(__debug_regs->dcr & DCR_IBE2)) {
+			//gdbstub_printk("set h/w break 2: %08lx\n", addr);
+			__debug_regs->dcr |= DCR_IBE2;
+			asm volatile("movgs %0,ibar2" : : "r"(addr));
+			return 0;
+		}
+
+		if (!(__debug_regs->dcr & DCR_IBE3)) {
+			//gdbstub_printk("set h/w break 3: %08lx\n", addr);
+			__debug_regs->dcr |= DCR_IBE3;
+			asm volatile("movgs %0,ibar3" : : "r"(addr));
+			return 0;
+		}
+
+		return -ENOSPC;
+
+		/* set data read/write/access watchpoint */
+	case 2:
+	case 3:
+	case 4:
+		if ((addr & ~7) != ((addr + len - 1) & ~7))
+			return -EINVAL;
+
+		tmp = addr & 7;
+
+		memset(dbmr.bytes, 0xff, sizeof(dbmr.bytes));
+		for (loop = 0; loop < len; loop++)
+			dbmr.bytes[tmp + loop] = 0;
+
+		addr &= ~7;
+
+		if (!(__debug_regs->dcr & (DCR_DRBE0|DCR_DWBE0))) {
+			//gdbstub_printk("set h/w watchpoint 0 type %ld: %08lx\n", type, addr);
+			tmp = type==2 ? DCR_DWBE0 : type==3 ? DCR_DRBE0 : DCR_DRBE0|DCR_DWBE0;
+			__debug_regs->dcr |= tmp;
+			asm volatile("	movgs	%0,dbar0	\n"
+				     "	movgs	%1,dbmr00	\n"
+				     "	movgs	%2,dbmr01	\n"
+				     "	movgs	gr0,dbdr00	\n"
+				     "	movgs	gr0,dbdr01	\n"
+				     : : "r"(addr), "r"(dbmr.mask0), "r"(dbmr.mask1));
+			return 0;
+		}
+
+		if (!(__debug_regs->dcr & (DCR_DRBE1|DCR_DWBE1))) {
+			//gdbstub_printk("set h/w watchpoint 1 type %ld: %08lx\n", type, addr);
+			tmp = type==2 ? DCR_DWBE1 : type==3 ? DCR_DRBE1 : DCR_DRBE1|DCR_DWBE1;
+			__debug_regs->dcr |= tmp;
+			asm volatile("	movgs	%0,dbar1	\n"
+				     "	movgs	%1,dbmr10	\n"
+				     "	movgs	%2,dbmr11	\n"
+				     "	movgs	gr0,dbdr10	\n"
+				     "	movgs	gr0,dbdr11	\n"
+				     : : "r"(addr), "r"(dbmr.mask0), "r"(dbmr.mask1));
+			return 0;
+		}
+
+		return -ENOSPC;
+
+	default:
+		return -EINVAL;
+	}
+
+} /* end gdbstub_set_breakpoint() */
+
+/*****************************************************************************/
+/*
+ * clear a breakpoint or watchpoint
+ */
+int gdbstub_clear_breakpoint(unsigned long type, unsigned long addr, unsigned long len)
+{
+	unsigned long tmp;
+	int bkpt, loop;
+
+	union {
+		struct {
+			unsigned long mask0, mask1;
+		};
+		uint8_t bytes[8];
+	} dbmr;
+
+	//gdbstub_printk("clearbkpt(%ld,%08lx,%ld)\n", type, addr, len);
+
+	switch (type) {
+		/* clear software breakpoint */
+	case 0:
+		for (bkpt = 255; bkpt >= 0; bkpt--)
+			if (gdbstub_bkpts[bkpt].addr == addr && gdbstub_bkpts[bkpt].len == len)
+				break;
+		if (bkpt < 0)
+			return -ENOENT;
+
+		gdbstub_bkpts[bkpt].addr = 0;
+
+		for (loop = 0; loop < len/4; loop++)
+			if (!gdbstub_write_dword(&((uint32_t *) addr)[loop],
+						 gdbstub_bkpts[bkpt].originsns[loop]))
+				return -EFAULT;
+		return 0;
+
+		/* clear hardware breakpoint */
+	case 1:
+		if (addr & 3 || len != 4)
+			return -EINVAL;
+
+#define __get_ibar(X) ({ unsigned long x; asm volatile("movsg ibar"#X",%0" : "=r"(x)); x; })
+
+		if (__debug_regs->dcr & DCR_IBE0 && __get_ibar(0) == addr) {
+			//gdbstub_printk("clear h/w break 0: %08lx\n", addr);
+			__debug_regs->dcr &= ~DCR_IBE0;
+			asm volatile("movgs gr0,ibar0");
+			return 0;
+		}
+
+		if (__debug_regs->dcr & DCR_IBE1 && __get_ibar(1) == addr) {
+			//gdbstub_printk("clear h/w break 1: %08lx\n", addr);
+			__debug_regs->dcr &= ~DCR_IBE1;
+			asm volatile("movgs gr0,ibar1");
+			return 0;
+		}
+
+		if (__debug_regs->dcr & DCR_IBE2 && __get_ibar(2) == addr) {
+			//gdbstub_printk("clear h/w break 2: %08lx\n", addr);
+			__debug_regs->dcr &= ~DCR_IBE2;
+			asm volatile("movgs gr0,ibar2");
+			return 0;
+		}
+
+		if (__debug_regs->dcr & DCR_IBE3 && __get_ibar(3) == addr) {
+			//gdbstub_printk("clear h/w break 3: %08lx\n", addr);
+			__debug_regs->dcr &= ~DCR_IBE3;
+			asm volatile("movgs gr0,ibar3");
+			return 0;
+		}
+
+		return -EINVAL;
+
+		/* clear data read/write/access watchpoint */
+	case 2:
+	case 3:
+	case 4:
+		if ((addr & ~7) != ((addr + len - 1) & ~7))
+			return -EINVAL;
+
+		tmp = addr & 7;
+
+		memset(dbmr.bytes, 0xff, sizeof(dbmr.bytes));
+		for (loop = 0; loop < len; loop++)
+			dbmr.bytes[tmp + loop] = 0;
+
+		addr &= ~7;
+
+#define __get_dbar(X) ({ unsigned long x; asm volatile("movsg dbar"#X",%0" : "=r"(x)); x; })
+#define __get_dbmr0(X) ({ unsigned long x; asm volatile("movsg dbmr"#X"0,%0" : "=r"(x)); x; })
+#define __get_dbmr1(X) ({ unsigned long x; asm volatile("movsg dbmr"#X"1,%0" : "=r"(x)); x; })
+
+		/* consider DBAR 0 */
+		tmp = type==2 ? DCR_DWBE0 : type==3 ? DCR_DRBE0 : DCR_DRBE0|DCR_DWBE0;
+
+		if ((__debug_regs->dcr & (DCR_DRBE0|DCR_DWBE0)) != tmp ||
+		    __get_dbar(0) != addr ||
+		    __get_dbmr0(0) != dbmr.mask0 ||
+		    __get_dbmr1(0) != dbmr.mask1)
+			goto skip_dbar0;
+
+		//gdbstub_printk("clear h/w watchpoint 0 type %ld: %08lx\n", type, addr);
+		__debug_regs->dcr &= ~(DCR_DRBE0|DCR_DWBE0);
+		asm volatile("	movgs	gr0,dbar0	\n"
+			     "	movgs	gr0,dbmr00	\n"
+			     "	movgs	gr0,dbmr01	\n"
+			     "	movgs	gr0,dbdr00	\n"
+			     "	movgs	gr0,dbdr01	\n");
+		return 0;
+
+	skip_dbar0:
+		/* consider DBAR 0 */
+		tmp = type==2 ? DCR_DWBE1 : type==3 ? DCR_DRBE1 : DCR_DRBE1|DCR_DWBE1;
+
+		if ((__debug_regs->dcr & (DCR_DRBE1|DCR_DWBE1)) != tmp ||
+		    __get_dbar(1) != addr ||
+		    __get_dbmr0(1) != dbmr.mask0 ||
+		    __get_dbmr1(1) != dbmr.mask1)
+			goto skip_dbar1;
+
+		//gdbstub_printk("clear h/w watchpoint 1 type %ld: %08lx\n", type, addr);
+		__debug_regs->dcr &= ~(DCR_DRBE1|DCR_DWBE1);
+		asm volatile("	movgs	gr0,dbar1	\n"
+			     "	movgs	gr0,dbmr10	\n"
+			     "	movgs	gr0,dbmr11	\n"
+			     "	movgs	gr0,dbdr10	\n"
+			     "	movgs	gr0,dbdr11	\n");
+		return 0;
+
+	skip_dbar1:
+		return -ENOSPC;
+
+	default:
+		return -EINVAL;
+	}
+} /* end gdbstub_clear_breakpoint() */
+
+/*****************************************************************************/
+/*
+ * check a for an internal software breakpoint, and wind the PC back if necessary
+ */
+static void gdbstub_check_breakpoint(void)
+{
+	unsigned long addr = __debug_frame->pc - 4;
+	int bkpt;
+
+	for (bkpt = 255; bkpt >= 0; bkpt--)
+		if (gdbstub_bkpts[bkpt].addr == addr)
+			break;
+	if (bkpt >= 0)
+		__debug_frame->pc = addr;
+
+	//gdbstub_printk("alter pc [%d] %08lx\n", bkpt, __debug_frame->pc);
+
+} /* end gdbstub_check_breakpoint() */
+
+/*****************************************************************************/
+/*
+ *
+ */
+static void __attribute__((unused)) gdbstub_show_regs(void)
+{
+	uint32_t *reg;
+	int loop;
+
+	gdbstub_printk("\n");
+
+	gdbstub_printk("Frame: @%p [%s]\n",
+		       __debug_frame,
+		       __debug_frame->psr & PSR_S ? "kernel" : "user");
+
+	reg = (uint32_t *) __debug_frame;
+	for (loop = 0; loop < REG__END; loop++) {
+		printk("%s %08x", regnames[loop + 0], reg[loop + 0]);
+
+		if (loop == REG__END - 1 || loop % 5 == 4)
+			printk("\n");
+		else
+			printk(" | ");
+	}
+
+	gdbstub_printk("Process %s (pid: %d)\n", current->comm, current->pid);
+} /* end gdbstub_show_regs() */
+
+/*****************************************************************************/
+/*
+ * dump debugging regs
+ */
+static void __attribute__((unused)) gdbstub_dump_debugregs(void)
+{
+	unsigned long x;
+
+	x = __debug_regs->dcr;
+	gdbstub_printk("DCR    %08lx  ", x);
+
+	x = __debug_regs->brr;
+	gdbstub_printk("BRR %08lx\n", x);
+
+	gdbstub_printk("IBAR0  %08lx  ", __get_ibar(0));
+	gdbstub_printk("IBAR1  %08lx  ", __get_ibar(1));
+	gdbstub_printk("IBAR2  %08lx  ", __get_ibar(2));
+	gdbstub_printk("IBAR3  %08lx\n", __get_ibar(3));
+
+	gdbstub_printk("DBAR0  %08lx  ", __get_dbar(0));
+	gdbstub_printk("DBMR00 %08lx  ", __get_dbmr0(0));
+	gdbstub_printk("DBMR01 %08lx\n", __get_dbmr1(0));
+
+	gdbstub_printk("DBAR1  %08lx  ", __get_dbar(1));
+	gdbstub_printk("DBMR10 %08lx  ", __get_dbmr0(1));
+	gdbstub_printk("DBMR11 %08lx\n", __get_dbmr1(1));
+
+	gdbstub_printk("\n");
+} /* end gdbstub_dump_debugregs() */
+
+/*****************************************************************************/
+/*
+ * dump the MMU state into a structure so that it can be accessed with GDB
+ */
+void gdbstub_get_mmu_state(void)
+{
+	asm volatile("movsg hsr0,%0" : "=r"(__debug_mmu.regs.hsr0));
+	asm volatile("movsg pcsr,%0" : "=r"(__debug_mmu.regs.pcsr));
+	asm volatile("movsg esr0,%0" : "=r"(__debug_mmu.regs.esr0));
+	asm volatile("movsg ear0,%0" : "=r"(__debug_mmu.regs.ear0));
+	asm volatile("movsg epcr0,%0" : "=r"(__debug_mmu.regs.epcr0));
+
+	/* read the protection / SAT registers */
+	__debug_mmu.iamr[0].L  = __get_IAMLR(0);
+	__debug_mmu.iamr[0].P  = __get_IAMPR(0);
+	__debug_mmu.iamr[1].L  = __get_IAMLR(1);
+	__debug_mmu.iamr[1].P  = __get_IAMPR(1);
+	__debug_mmu.iamr[2].L  = __get_IAMLR(2);
+	__debug_mmu.iamr[2].P  = __get_IAMPR(2);
+	__debug_mmu.iamr[3].L  = __get_IAMLR(3);
+	__debug_mmu.iamr[3].P  = __get_IAMPR(3);
+	__debug_mmu.iamr[4].L  = __get_IAMLR(4);
+	__debug_mmu.iamr[4].P  = __get_IAMPR(4);
+	__debug_mmu.iamr[5].L  = __get_IAMLR(5);
+	__debug_mmu.iamr[5].P  = __get_IAMPR(5);
+	__debug_mmu.iamr[6].L  = __get_IAMLR(6);
+	__debug_mmu.iamr[6].P  = __get_IAMPR(6);
+	__debug_mmu.iamr[7].L  = __get_IAMLR(7);
+	__debug_mmu.iamr[7].P  = __get_IAMPR(7);
+	__debug_mmu.iamr[8].L  = __get_IAMLR(8);
+	__debug_mmu.iamr[8].P  = __get_IAMPR(8);
+	__debug_mmu.iamr[9].L  = __get_IAMLR(9);
+	__debug_mmu.iamr[9].P  = __get_IAMPR(9);
+	__debug_mmu.iamr[10].L = __get_IAMLR(10);
+	__debug_mmu.iamr[10].P = __get_IAMPR(10);
+	__debug_mmu.iamr[11].L = __get_IAMLR(11);
+	__debug_mmu.iamr[11].P = __get_IAMPR(11);
+	__debug_mmu.iamr[12].L = __get_IAMLR(12);
+	__debug_mmu.iamr[12].P = __get_IAMPR(12);
+	__debug_mmu.iamr[13].L = __get_IAMLR(13);
+	__debug_mmu.iamr[13].P = __get_IAMPR(13);
+	__debug_mmu.iamr[14].L = __get_IAMLR(14);
+	__debug_mmu.iamr[14].P = __get_IAMPR(14);
+	__debug_mmu.iamr[15].L = __get_IAMLR(15);
+	__debug_mmu.iamr[15].P = __get_IAMPR(15);
+
+	__debug_mmu.damr[0].L  = __get_DAMLR(0);
+	__debug_mmu.damr[0].P  = __get_DAMPR(0);
+	__debug_mmu.damr[1].L  = __get_DAMLR(1);
+	__debug_mmu.damr[1].P  = __get_DAMPR(1);
+	__debug_mmu.damr[2].L  = __get_DAMLR(2);
+	__debug_mmu.damr[2].P  = __get_DAMPR(2);
+	__debug_mmu.damr[3].L  = __get_DAMLR(3);
+	__debug_mmu.damr[3].P  = __get_DAMPR(3);
+	__debug_mmu.damr[4].L  = __get_DAMLR(4);
+	__debug_mmu.damr[4].P  = __get_DAMPR(4);
+	__debug_mmu.damr[5].L  = __get_DAMLR(5);
+	__debug_mmu.damr[5].P  = __get_DAMPR(5);
+	__debug_mmu.damr[6].L  = __get_DAMLR(6);
+	__debug_mmu.damr[6].P  = __get_DAMPR(6);
+	__debug_mmu.damr[7].L  = __get_DAMLR(7);
+	__debug_mmu.damr[7].P  = __get_DAMPR(7);
+	__debug_mmu.damr[8].L  = __get_DAMLR(8);
+	__debug_mmu.damr[8].P  = __get_DAMPR(8);
+	__debug_mmu.damr[9].L  = __get_DAMLR(9);
+	__debug_mmu.damr[9].P  = __get_DAMPR(9);
+	__debug_mmu.damr[10].L = __get_DAMLR(10);
+	__debug_mmu.damr[10].P = __get_DAMPR(10);
+	__debug_mmu.damr[11].L = __get_DAMLR(11);
+	__debug_mmu.damr[11].P = __get_DAMPR(11);
+	__debug_mmu.damr[12].L = __get_DAMLR(12);
+	__debug_mmu.damr[12].P = __get_DAMPR(12);
+	__debug_mmu.damr[13].L = __get_DAMLR(13);
+	__debug_mmu.damr[13].P = __get_DAMPR(13);
+	__debug_mmu.damr[14].L = __get_DAMLR(14);
+	__debug_mmu.damr[14].P = __get_DAMPR(14);
+	__debug_mmu.damr[15].L = __get_DAMLR(15);
+	__debug_mmu.damr[15].P = __get_DAMPR(15);
+
+#ifdef CONFIG_MMU
+	do {
+		/* read the DAT entries from the TLB */
+		struct __debug_amr *p;
+		int loop;
+
+		asm volatile("movsg tplr,%0" : "=r"(__debug_mmu.regs.tplr));
+		asm volatile("movsg tppr,%0" : "=r"(__debug_mmu.regs.tppr));
+		asm volatile("movsg tpxr,%0" : "=r"(__debug_mmu.regs.tpxr));
+		asm volatile("movsg cxnr,%0" : "=r"(__debug_mmu.regs.cxnr));
+
+		p = __debug_mmu.tlb;
+
+		/* way 0 */
+		asm volatile("movgs %0,tpxr" :: "r"(0 << TPXR_WAY_SHIFT));
+		for (loop = 0; loop < 64; loop++) {
+			asm volatile("tlbpr %0,gr0,#1,#0" :: "r"(loop << PAGE_SHIFT));
+			asm volatile("movsg tplr,%0" : "=r"(p->L));
+			asm volatile("movsg tppr,%0" : "=r"(p->P));
+			p++;
+		}
+
+		/* way 1 */
+		asm volatile("movgs %0,tpxr" :: "r"(1 << TPXR_WAY_SHIFT));
+		for (loop = 0; loop < 64; loop++) {
+			asm volatile("tlbpr %0,gr0,#1,#0" :: "r"(loop << PAGE_SHIFT));
+			asm volatile("movsg tplr,%0" : "=r"(p->L));
+			asm volatile("movsg tppr,%0" : "=r"(p->P));
+			p++;
+		}
+
+		asm volatile("movgs %0,tplr" :: "r"(__debug_mmu.regs.tplr));
+		asm volatile("movgs %0,tppr" :: "r"(__debug_mmu.regs.tppr));
+		asm volatile("movgs %0,tpxr" :: "r"(__debug_mmu.regs.tpxr));
+	} while(0);
+#endif
+
+} /* end gdbstub_get_mmu_state() */
+
+/*****************************************************************************/
+/*
+ * handle event interception and GDB remote protocol processing
+ * - on entry:
+ *	PSR.ET==0, PSR.S==1 and the CPU is in debug mode
+ *	__debug_frame points to the saved registers
+ *	__frame points to the kernel mode exception frame, if it was in kernel
+ *      mode when the break happened
+ */
+void gdbstub(int sigval)
+{
+	unsigned long addr, length, loop, dbar, temp, temp2, temp3;
+	uint32_t zero;
+	char *ptr;
+	int flush_cache = 0;
+
+	LEDS(0x5000);
+
+	if (sigval < 0) {
+#ifndef CONFIG_GDBSTUB_IMMEDIATE
+		/* return immediately if GDB immediate activation option not set */
+		return;
+#else
+		sigval = SIGINT;
+#endif
+	}
+
+	save_user_regs(&__break_user_context);
+
+#if 0
+	gdbstub_printk("--> gdbstub() %08x %p %08x %08x\n",
+		       __debug_frame->pc,
+		       __debug_frame,
+		       __debug_regs->brr,
+		       __debug_regs->bpsr);
+//	gdbstub_show_regs();
+#endif
+
+	LEDS(0x5001);
+
+	/* if we were interrupted by input on the serial gdbstub serial port,
+	 * restore the context prior to the interrupt so that we return to that
+	 * directly
+	 */
+	temp = (unsigned long) __entry_kerneltrap_table;
+	temp2 = (unsigned long) __entry_usertrap_table;
+	temp3 = __debug_frame->pc & ~15;
+
+	if (temp3 == temp + TBR_TT_INTERRUPT_15 ||
+	    temp3 == temp2 + TBR_TT_INTERRUPT_15
+	    ) {
+		asm volatile("movsg pcsr,%0" : "=r"(__debug_frame->pc));
+		__debug_frame->psr |= PSR_ET;
+		__debug_frame->psr &= ~PSR_S;
+		if (__debug_frame->psr & PSR_PS)
+			__debug_frame->psr |= PSR_S;
+		__debug_regs->brr = (__debug_frame->tbr & TBR_TT) << 12;
+		__debug_regs->brr |= BRR_EB;
+		sigval = SIGINT;
+	}
+
+	/* handle the decrement timer going off (FR451 only) */
+	if (temp3 == temp + TBR_TT_DECREMENT_TIMER ||
+	    temp3 == temp2 + TBR_TT_DECREMENT_TIMER
+	    ) {
+		asm volatile("movgs %0,timerd" :: "r"(10000000));
+		asm volatile("movsg pcsr,%0" : "=r"(__debug_frame->pc));
+		__debug_frame->psr |= PSR_ET;
+		__debug_frame->psr &= ~PSR_S;
+		if (__debug_frame->psr & PSR_PS)
+			__debug_frame->psr |= PSR_S;
+		__debug_regs->brr = (__debug_frame->tbr & TBR_TT) << 12;
+		__debug_regs->brr |= BRR_EB;
+		sigval = SIGXCPU;;
+	}
+
+	LEDS(0x5002);
+
+	/* after a BREAK insn, the PC lands on the far side of it */
+	if (__debug_regs->brr & BRR_SB)
+		gdbstub_check_breakpoint();
+
+	LEDS(0x5003);
+
+	/* handle attempts to write console data via GDB "O" commands */
+	if (__debug_frame->pc == (unsigned long) gdbstub_console_write + 4) {
+		__gdbstub_console_write((struct console *) __debug_frame->gr8,
+					(const char *) __debug_frame->gr9,
+					(unsigned) __debug_frame->gr10);
+		goto done;
+	}
+
+	if (gdbstub_rx_unget) {
+		sigval = SIGINT;
+		goto packet_waiting;
+	}
+
+	if (!sigval)
+		sigval = gdbstub_compute_signal(__debug_regs->brr);
+
+	LEDS(0x5004);
+
+	/* send a message to the debugger's user saying what happened if it may
+	 * not be clear cut (we can't map exceptions onto signals properly)
+	 */
+	if (sigval != SIGINT && sigval != SIGTRAP && sigval != SIGILL) {
+		static const char title[] = "Break ";
+		static const char crlf[] = "\r\n";
+		unsigned long brr = __debug_regs->brr;
+		char hx;
+
+		ptr = output_buffer;
+		*ptr++ = 'O';
+		ptr = mem2hex(title, ptr, sizeof(title) - 1,0);
+
+		hx = hexchars[(brr & 0xf0000000) >> 28];
+		*ptr++ = hexchars[hx >> 4];	*ptr++ = hexchars[hx & 0xf];
+		hx = hexchars[(brr & 0x0f000000) >> 24];
+		*ptr++ = hexchars[hx >> 4];	*ptr++ = hexchars[hx & 0xf];
+		hx = hexchars[(brr & 0x00f00000) >> 20];
+		*ptr++ = hexchars[hx >> 4];	*ptr++ = hexchars[hx & 0xf];
+		hx = hexchars[(brr & 0x000f0000) >> 16];
+		*ptr++ = hexchars[hx >> 4];	*ptr++ = hexchars[hx & 0xf];
+		hx = hexchars[(brr & 0x0000f000) >> 12];
+		*ptr++ = hexchars[hx >> 4];	*ptr++ = hexchars[hx & 0xf];
+		hx = hexchars[(brr & 0x00000f00) >> 8];
+		*ptr++ = hexchars[hx >> 4];	*ptr++ = hexchars[hx & 0xf];
+		hx = hexchars[(brr & 0x000000f0) >> 4];
+		*ptr++ = hexchars[hx >> 4];	*ptr++ = hexchars[hx & 0xf];
+		hx = hexchars[(brr & 0x0000000f)];
+		*ptr++ = hexchars[hx >> 4];	*ptr++ = hexchars[hx & 0xf];
+
+		ptr = mem2hex(crlf, ptr, sizeof(crlf) - 1, 0);
+		*ptr = 0;
+		gdbstub_send_packet(output_buffer);	/* send it off... */
+	}
+
+	LEDS(0x5005);
+
+	/* tell the debugger that an exception has occurred */
+	ptr = output_buffer;
+
+	/* Send trap type (converted to signal) */
+	*ptr++ = 'T';
+	*ptr++ = hexchars[sigval >> 4];
+	*ptr++ = hexchars[sigval & 0xf];
+
+	/* Send Error PC */
+	*ptr++ = hexchars[GDB_REG_PC >> 4];
+	*ptr++ = hexchars[GDB_REG_PC & 0xf];
+	*ptr++ = ':';
+	ptr = mem2hex(&__debug_frame->pc, ptr, 4, 0);
+	*ptr++ = ';';
+
+	/*
+	 * Send frame pointer
+	 */
+	*ptr++ = hexchars[GDB_REG_FP >> 4];
+	*ptr++ = hexchars[GDB_REG_FP & 0xf];
+	*ptr++ = ':';
+	ptr = mem2hex(&__debug_frame->fp, ptr, 4, 0);
+	*ptr++ = ';';
+
+	/*
+	 * Send stack pointer
+	 */
+	*ptr++ = hexchars[GDB_REG_SP >> 4];
+	*ptr++ = hexchars[GDB_REG_SP & 0xf];
+	*ptr++ = ':';
+	ptr = mem2hex(&__debug_frame->sp, ptr, 4, 0);
+	*ptr++ = ';';
+
+	*ptr++ = 0;
+	gdbstub_send_packet(output_buffer);	/* send it off... */
+
+	LEDS(0x5006);
+
+ packet_waiting:
+	gdbstub_get_mmu_state();
+
+	/* wait for input from remote GDB */
+	while (1) {
+		output_buffer[0] = 0;
+
+		LEDS(0x5007);
+		gdbstub_recv_packet(input_buffer);
+		LEDS(0x5600 | input_buffer[0]);
+
+		switch (input_buffer[0]) {
+			/* request repeat of last signal number */
+		case '?':
+			output_buffer[0] = 'S';
+			output_buffer[1] = hexchars[sigval >> 4];
+			output_buffer[2] = hexchars[sigval & 0xf];
+			output_buffer[3] = 0;
+			break;
+
+		case 'd':
+			/* toggle debug flag */
+			break;
+
+			/* return the value of the CPU registers
+			 * - GR0,  GR1,  GR2,  GR3,  GR4,  GR5,  GR6,  GR7,
+			 * - GR8,  GR9,  GR10, GR11, GR12, GR13, GR14, GR15,
+			 * - GR16, GR17, GR18, GR19, GR20, GR21, GR22, GR23,
+			 * - GR24, GR25, GR26, GR27, GR28, GR29, GR30, GR31,
+			 * - GR32, GR33, GR34, GR35, GR36, GR37, GR38, GR39,
+			 * - GR40, GR41, GR42, GR43, GR44, GR45, GR46, GR47,
+			 * - GR48, GR49, GR50, GR51, GR52, GR53, GR54, GR55,
+			 * - GR56, GR57, GR58, GR59, GR60, GR61, GR62, GR63,
+			 * - FP0,  FP1,  FP2,  FP3,  FP4,  FP5,  FP6,  FP7,
+			 * - FP8,  FP9,  FP10, FP11, FP12, FP13, FP14, FP15,
+			 * - FP16, FP17, FP18, FP19, FP20, FP21, FP22, FP23,
+			 * - FP24, FP25, FP26, FP27, FP28, FP29, FP30, FP31,
+			 * - FP32, FP33, FP34, FP35, FP36, FP37, FP38, FP39,
+			 * - FP40, FP41, FP42, FP43, FP44, FP45, FP46, FP47,
+			 * - FP48, FP49, FP50, FP51, FP52, FP53, FP54, FP55,
+			 * - FP56, FP57, FP58, FP59, FP60, FP61, FP62, FP63,
+			 * - PC, PSR, CCR, CCCR,
+			 * - _X132, _X133, _X134
+			 * - TBR, BRR, DBAR0, DBAR1, DBAR2, DBAR3,
+			 * - _X141, _X142, _X143, _X144,
+			 * - LR, LCR
+			 */
+		case 'g':
+			zero = 0;
+			ptr = output_buffer;
+
+			/* deal with GR0, GR1-GR27, GR28-GR31, GR32-GR63 */
+			ptr = mem2hex(&zero, ptr, 4, 0);
+
+			for (loop = 1; loop <= 27; loop++)
+				ptr = mem2hex((unsigned long *)__debug_frame + REG_GR(loop),
+					      ptr, 4, 0);
+			temp = (unsigned long) __frame;
+			ptr = mem2hex(&temp, ptr, 4, 0);
+			ptr = mem2hex((unsigned long *)__debug_frame + REG_GR(29), ptr, 4, 0);
+			ptr = mem2hex((unsigned long *)__debug_frame + REG_GR(30), ptr, 4, 0);
+#ifdef CONFIG_MMU
+			ptr = mem2hex((unsigned long *)__debug_frame + REG_GR(31), ptr, 4, 0);
+#else
+			temp = (unsigned long) __debug_frame;
+			ptr = mem2hex(&temp, ptr, 4, 0);
+#endif
+
+			for (loop = 32; loop <= 63; loop++)
+				ptr = mem2hex((unsigned long *)__debug_frame + REG_GR(loop),
+					      ptr, 4, 0);
+
+			/* deal with FR0-FR63 */
+			for (loop = 0; loop <= 63; loop++)
+				ptr = mem2hex((unsigned long *)&__break_user_context +
+					      __FPMEDIA_FR(loop),
+					      ptr, 4, 0);
+
+			/* deal with special registers */
+			ptr = mem2hex(&__debug_frame->pc,    ptr, 4, 0);
+			ptr = mem2hex(&__debug_frame->psr,   ptr, 4, 0);
+			ptr = mem2hex(&__debug_frame->ccr,   ptr, 4, 0);
+			ptr = mem2hex(&__debug_frame->cccr,  ptr, 4, 0);
+			ptr = mem2hex(&zero, ptr, 4, 0);
+			ptr = mem2hex(&zero, ptr, 4, 0);
+			ptr = mem2hex(&zero, ptr, 4, 0);
+			ptr = mem2hex(&__debug_frame->tbr,   ptr, 4, 0);
+			ptr = mem2hex(&__debug_regs->brr ,   ptr, 4, 0);
+
+			asm volatile("movsg dbar0,%0" : "=r"(dbar));
+			ptr = mem2hex(&dbar, ptr, 4, 0);
+			asm volatile("movsg dbar1,%0" : "=r"(dbar));
+			ptr = mem2hex(&dbar, ptr, 4, 0);
+			asm volatile("movsg dbar2,%0" : "=r"(dbar));
+			ptr = mem2hex(&dbar, ptr, 4, 0);
+			asm volatile("movsg dbar3,%0" : "=r"(dbar));
+			ptr = mem2hex(&dbar, ptr, 4, 0);
+
+			asm volatile("movsg scr0,%0" : "=r"(dbar));
+			ptr = mem2hex(&dbar, ptr, 4, 0);
+			asm volatile("movsg scr1,%0" : "=r"(dbar));
+			ptr = mem2hex(&dbar, ptr, 4, 0);
+			asm volatile("movsg scr2,%0" : "=r"(dbar));
+			ptr = mem2hex(&dbar, ptr, 4, 0);
+			asm volatile("movsg scr3,%0" : "=r"(dbar));
+			ptr = mem2hex(&dbar, ptr, 4, 0);
+
+			ptr = mem2hex(&__debug_frame->lr, ptr, 4, 0);
+			ptr = mem2hex(&__debug_frame->lcr, ptr, 4, 0);
+
+			ptr = mem2hex(&__debug_frame->iacc0, ptr, 8, 0);
+
+			ptr = mem2hex(&__break_user_context.f.fsr[0], ptr, 4, 0);
+
+			for (loop = 0; loop <= 7; loop++)
+				ptr = mem2hex(&__break_user_context.f.acc[loop], ptr, 4, 0);
+
+			ptr = mem2hex(&__break_user_context.f.accg, ptr, 8, 0);
+
+			for (loop = 0; loop <= 1; loop++)
+				ptr = mem2hex(&__break_user_context.f.msr[loop], ptr, 4, 0);
+
+			ptr = mem2hex(&__debug_frame->gner0, ptr, 4, 0);
+			ptr = mem2hex(&__debug_frame->gner1, ptr, 4, 0);
+
+			ptr = mem2hex(&__break_user_context.f.fner[0], ptr, 4, 0);
+			ptr = mem2hex(&__break_user_context.f.fner[1], ptr, 4, 0);
+
+			break;
+
+			/* set the values of the CPU registers */
+		case 'G':
+			ptr = &input_buffer[1];
+
+			/* deal with GR0, GR1-GR27, GR28-GR31, GR32-GR63 */
+			ptr = hex2mem(ptr, &temp, 4);
+
+			for (loop = 1; loop <= 27; loop++)
+				ptr = hex2mem(ptr, (unsigned long *)__debug_frame + REG_GR(loop),
+					      4);
+
+			ptr = hex2mem(ptr, &temp, 4);
+			__frame = (struct pt_regs *) temp;
+			ptr = hex2mem(ptr, &__debug_frame->gr29, 4);
+			ptr = hex2mem(ptr, &__debug_frame->gr30, 4);
+#ifdef CONFIG_MMU
+			ptr = hex2mem(ptr, &__debug_frame->gr31, 4);
+#else
+			ptr = hex2mem(ptr, &temp, 4);
+#endif
+
+			for (loop = 32; loop <= 63; loop++)
+				ptr = hex2mem(ptr, (unsigned long *)__debug_frame + REG_GR(loop),
+					      4);
+
+			/* deal with FR0-FR63 */
+			for (loop = 0; loop <= 63; loop++)
+				ptr = mem2hex((unsigned long *)&__break_user_context +
+					      __FPMEDIA_FR(loop),
+					      ptr, 4, 0);
+
+			/* deal with special registers */
+			ptr = hex2mem(ptr, &__debug_frame->pc,  4);
+			ptr = hex2mem(ptr, &__debug_frame->psr, 4);
+			ptr = hex2mem(ptr, &__debug_frame->ccr, 4);
+			ptr = hex2mem(ptr, &__debug_frame->cccr,4);
+
+			for (loop = 132; loop <= 140; loop++)
+				ptr = hex2mem(ptr, &temp, 4);
+
+			ptr = hex2mem(ptr, &temp, 4);
+			asm volatile("movgs %0,scr0" :: "r"(temp));
+			ptr = hex2mem(ptr, &temp, 4);
+			asm volatile("movgs %0,scr1" :: "r"(temp));
+			ptr = hex2mem(ptr, &temp, 4);
+			asm volatile("movgs %0,scr2" :: "r"(temp));
+			ptr = hex2mem(ptr, &temp, 4);
+			asm volatile("movgs %0,scr3" :: "r"(temp));
+
+			ptr = hex2mem(ptr, &__debug_frame->lr,  4);
+			ptr = hex2mem(ptr, &__debug_frame->lcr, 4);
+
+			ptr = hex2mem(ptr, &__debug_frame->iacc0, 8);
+
+			ptr = hex2mem(ptr, &__break_user_context.f.fsr[0], 4);
+
+			for (loop = 0; loop <= 7; loop++)
+				ptr = hex2mem(ptr, &__break_user_context.f.acc[loop], 4);
+
+			ptr = hex2mem(ptr, &__break_user_context.f.accg, 8);
+
+			for (loop = 0; loop <= 1; loop++)
+				ptr = hex2mem(ptr, &__break_user_context.f.msr[loop], 4);
+
+			ptr = hex2mem(ptr, &__debug_frame->gner0, 4);
+			ptr = hex2mem(ptr, &__debug_frame->gner1, 4);
+
+			ptr = hex2mem(ptr, &__break_user_context.f.fner[0], 4);
+			ptr = hex2mem(ptr, &__break_user_context.f.fner[1], 4);
+
+			gdbstub_strcpy(output_buffer,"OK");
+			break;
+
+			/* mAA..AA,LLLL  Read LLLL bytes at address AA..AA */
+		case 'm':
+			ptr = &input_buffer[1];
+
+			if (hexToInt(&ptr, &addr) &&
+			    *ptr++ == ',' &&
+			    hexToInt(&ptr, &length)
+			    ) {
+				if (mem2hex((char *)addr, output_buffer, length, 1))
+					break;
+				gdbstub_strcpy (output_buffer, "E03");
+			}
+			else {
+				gdbstub_strcpy(output_buffer,"E01");
+			}
+			break;
+
+			/* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */
+		case 'M':
+			ptr = &input_buffer[1];
+
+			if (hexToInt(&ptr, &addr) &&
+			    *ptr++ == ',' &&
+			    hexToInt(&ptr, &length) &&
+			    *ptr++ == ':'
+			    ) {
+				if (hex2mem(ptr, (char *)addr, length)) {
+					gdbstub_strcpy(output_buffer, "OK");
+				}
+				else {
+					gdbstub_strcpy(output_buffer, "E03");
+				}
+			}
+			else
+				gdbstub_strcpy(output_buffer, "E02");
+
+			flush_cache = 1;
+			break;
+
+			/* PNN,=RRRRRRRR: Write value R to reg N return OK */
+		case 'P':
+			ptr = &input_buffer[1];
+
+			if (!hexToInt(&ptr, &addr) ||
+			    *ptr++ != '=' ||
+			    !hexToInt(&ptr, &temp)
+			    ) {
+				gdbstub_strcpy(output_buffer, "E01");
+				break;
+			}
+
+			temp2 = 1;
+			switch (addr) {
+			case GDB_REG_GR(0):
+				break;
+			case GDB_REG_GR(1) ... GDB_REG_GR(63):
+				__break_user_context.i.gr[addr - GDB_REG_GR(0)] = temp;
+				break;
+			case GDB_REG_FR(0) ... GDB_REG_FR(63):
+				__break_user_context.f.fr[addr - GDB_REG_FR(0)] = temp;
+				break;
+			case GDB_REG_PC:
+				__break_user_context.i.pc = temp;
+				break;
+			case GDB_REG_PSR:
+				__break_user_context.i.psr = temp;
+				break;
+			case GDB_REG_CCR:
+				__break_user_context.i.ccr = temp;
+				break;
+			case GDB_REG_CCCR:
+				__break_user_context.i.cccr = temp;
+				break;
+			case GDB_REG_BRR:
+				__debug_regs->brr = temp;
+				break;
+			case GDB_REG_LR:
+				__break_user_context.i.lr = temp;
+				break;
+			case GDB_REG_LCR:
+				__break_user_context.i.lcr = temp;
+				break;
+			case GDB_REG_FSR0:
+				__break_user_context.f.fsr[0] = temp;
+				break;
+			case GDB_REG_ACC(0) ... GDB_REG_ACC(7):
+				__break_user_context.f.acc[addr - GDB_REG_ACC(0)] = temp;
+				break;
+			case GDB_REG_ACCG(0):
+				*(uint32_t *) &__break_user_context.f.accg[0] = temp;
+				break;
+			case GDB_REG_ACCG(4):
+				*(uint32_t *) &__break_user_context.f.accg[4] = temp;
+				break;
+			case GDB_REG_MSR(0) ... GDB_REG_MSR(1):
+				__break_user_context.f.msr[addr - GDB_REG_MSR(0)] = temp;
+				break;
+			case GDB_REG_GNER(0) ... GDB_REG_GNER(1):
+				__break_user_context.i.gner[addr - GDB_REG_GNER(0)] = temp;
+				break;
+			case GDB_REG_FNER(0) ... GDB_REG_FNER(1):
+				__break_user_context.f.fner[addr - GDB_REG_FNER(0)] = temp;
+				break;
+			default:
+				temp2 = 0;
+				break;
+			}
+
+			if (temp2) {
+				gdbstub_strcpy(output_buffer, "OK");
+			}
+			else {
+				gdbstub_strcpy(output_buffer, "E02");
+			}
+			break;
+
+			/* cAA..AA    Continue at address AA..AA(optional) */
+		case 'c':
+			/* try to read optional parameter, pc unchanged if no parm */
+			ptr = &input_buffer[1];
+			if (hexToInt(&ptr, &addr))
+				__debug_frame->pc = addr;
+			goto done;
+
+			/* kill the program */
+		case 'k' :
+			goto done;	/* just continue */
+
+
+			/* reset the whole machine (FIXME: system dependent) */
+		case 'r':
+			break;
+
+
+			/* step to next instruction */
+		case 's':
+			__debug_regs->dcr |= DCR_SE;
+			goto done;
+
+			/* set baud rate (bBB) */
+		case 'b':
+			ptr = &input_buffer[1];
+			if (!hexToInt(&ptr, &temp)) {
+				gdbstub_strcpy(output_buffer,"B01");
+				break;
+			}
+
+			if (temp) {
+				/* ack before changing speed */
+				gdbstub_send_packet("OK");
+				gdbstub_set_baud(temp);
+			}
+			break;
+
+			/* set breakpoint */
+		case 'Z':
+			ptr = &input_buffer[1];
+
+			if (!hexToInt(&ptr,&temp) || *ptr++ != ',' ||
+			    !hexToInt(&ptr,&addr) || *ptr++ != ',' ||
+			    !hexToInt(&ptr,&length)
+			    ) {
+				gdbstub_strcpy(output_buffer,"E01");
+				break;
+			}
+
+			if (temp >= 5) {
+				gdbstub_strcpy(output_buffer,"E03");
+				break;
+			}
+
+			if (gdbstub_set_breakpoint(temp, addr, length) < 0) {
+				gdbstub_strcpy(output_buffer,"E03");
+				break;
+			}
+
+			if (temp == 0)
+				flush_cache = 1; /* soft bkpt by modified memory */
+
+			gdbstub_strcpy(output_buffer,"OK");
+			break;
+
+			/* clear breakpoint */
+		case 'z':
+			ptr = &input_buffer[1];
+
+			if (!hexToInt(&ptr,&temp) || *ptr++ != ',' ||
+			    !hexToInt(&ptr,&addr) || *ptr++ != ',' ||
+			    !hexToInt(&ptr,&length)
+			    ) {
+				gdbstub_strcpy(output_buffer,"E01");
+				break;
+			}
+
+			if (temp >= 5) {
+				gdbstub_strcpy(output_buffer,"E03");
+				break;
+			}
+
+			if (gdbstub_clear_breakpoint(temp, addr, length) < 0) {
+				gdbstub_strcpy(output_buffer,"E03");
+				break;
+			}
+
+			if (temp == 0)
+				flush_cache = 1; /* soft bkpt by modified memory */
+
+			gdbstub_strcpy(output_buffer,"OK");
+			break;
+
+		default:
+			gdbstub_proto("### GDB Unsupported Cmd '%s'\n",input_buffer);
+			break;
+		}
+
+		/* reply to the request */
+		LEDS(0x5009);
+		gdbstub_send_packet(output_buffer);
+	}
+
+ done:
+	restore_user_regs(&__break_user_context);
+
+	//gdbstub_dump_debugregs();
+	//gdbstub_printk("<-- gdbstub() %08x\n", __debug_frame->pc);
+
+	/* need to flush the instruction cache before resuming, as we may have
+	 * deposited a breakpoint, and the icache probably has no way of
+	 * knowing that a data ref to some location may have changed something
+	 * that is in the instruction cache.  NB: We flush both caches, just to
+	 * be sure...
+	 */
+
+	/* note: flushing the icache will clobber EAR0 on the FR451 */
+	if (flush_cache)
+		gdbstub_purge_cache();
+
+	LEDS(0x5666);
+
+} /* end gdbstub() */
+
+/*****************************************************************************/
+/*
+ * initialise the GDB stub
+ */
+void __init gdbstub_init(void)
+{
+#ifdef CONFIG_GDBSTUB_IMMEDIATE
+	unsigned char ch;
+	int ret;
+#endif
+
+	gdbstub_printk("%s", gdbstub_banner);
+	gdbstub_printk("DCR: %x\n", __debug_regs->dcr);
+
+	gdbstub_io_init();
+
+	/* try to talk to GDB (or anyone insane enough to want to type GDB protocol by hand) */
+	gdbstub_proto("### GDB Tx ACK\n");
+	gdbstub_tx_char('+'); /* 'hello world' */
+
+#ifdef CONFIG_GDBSTUB_IMMEDIATE
+	gdbstub_printk("GDB Stub waiting for packet\n");
+
+	/*
+	 * In case GDB is started before us, ack any packets
+	 * (presumably "$?#xx") sitting there.
+	 */
+	do { gdbstub_rx_char(&ch, 0); } while (ch != '$');
+	do { gdbstub_rx_char(&ch, 0); } while (ch != '#');
+	do { ret = gdbstub_rx_char(&ch, 0); } while (ret != 0); /* eat first csum byte */
+	do { ret = gdbstub_rx_char(&ch, 0); } while (ret != 0); /* eat second csum byte */
+
+	gdbstub_proto("### GDB Tx NAK\n");
+	gdbstub_tx_char('-'); /* nak it */
+
+#else
+	gdbstub_printk("GDB Stub set\n");
+#endif
+
+#if 0
+	/* send banner */
+	ptr = output_buffer;
+	*ptr++ = 'O';
+	ptr = mem2hex(gdbstub_banner, ptr, sizeof(gdbstub_banner) - 1, 0);
+	gdbstub_send_packet(output_buffer);
+#endif
+#if defined(CONFIG_GDBSTUB_CONSOLE) && defined(CONFIG_GDBSTUB_IMMEDIATE)
+	register_console(&gdbstub_console);
+#endif
+
+} /* end gdbstub_init() */
+
+/*****************************************************************************/
+/*
+ * register the console at a more appropriate time
+ */
+#if defined (CONFIG_GDBSTUB_CONSOLE) && !defined(CONFIG_GDBSTUB_IMMEDIATE)
+static int __init gdbstub_postinit(void)
+{
+	printk("registering console\n");
+	register_console(&gdbstub_console);
+	return 0;
+} /* end gdbstub_postinit() */
+
+__initcall(gdbstub_postinit);
+#endif
+
+/*****************************************************************************/
+/*
+ * send an exit message to GDB
+ */
+void gdbstub_exit(int status)
+{
+	unsigned char checksum;
+	int count;
+	unsigned char ch;
+
+	sprintf(output_buffer,"W%02x",status&0xff);
+
+	gdbstub_tx_char('$');
+	checksum = 0;
+	count = 0;
+
+	while ((ch = output_buffer[count]) != 0) {
+		gdbstub_tx_char(ch);
+		checksum += ch;
+		count += 1;
+	}
+
+	gdbstub_tx_char('#');
+	gdbstub_tx_char(hexchars[checksum >> 4]);
+	gdbstub_tx_char(hexchars[checksum & 0xf]);
+
+	/* make sure the output is flushed, or else RedBoot might clobber it */
+	gdbstub_tx_char('-');
+	gdbstub_tx_flush();
+
+} /* end gdbstub_exit() */
+
+/*****************************************************************************/
+/*
+ * GDB wants to call malloc() and free() to allocate memory for calling kernel
+ * functions directly from its command line
+ */
+static void *malloc(size_t size) __attribute__((unused));
+static void *malloc(size_t size)
+{
+	return kmalloc(size, GFP_ATOMIC);
+}
+
+static void free(void *p) __attribute__((unused));
+static void free(void *p)
+{
+	kfree(p);
+}
+
+static uint32_t ___get_HSR0(void) __attribute__((unused));
+static uint32_t ___get_HSR0(void)
+{
+	return __get_HSR(0);
+}
+
+static uint32_t ___set_HSR0(uint32_t x) __attribute__((unused));
+static uint32_t ___set_HSR0(uint32_t x)
+{
+	__set_HSR(0, x);
+	return __get_HSR(0);
+}
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/kernel/head.inc linux-2.6.10-rc1-mm3-frv/arch/frv/kernel/head.inc
--- /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/kernel/head.inc	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/arch/frv/kernel/head.inc	2004-11-05 14:13:03.112562578 +0000
@@ -0,0 +1,50 @@
+/* head.inc: head common definitions -*- asm -*-
+ *
+ * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * 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.
+ */
+
+
+#if defined(CONFIG_MB93090_MB00)
+#define LED_ADDR (0x21200000+4)
+
+.macro LEDS val
+	sethi.p		%hi(0xFFC00030),gr3
+	setlo		%lo(0xFFC00030),gr3
+	lduh		@(gr3,gr0),gr3
+	andicc		gr3,#0x100,gr0,icc0
+	bne		icc0,0,999f
+	
+	setlos		#~\val,gr3
+	st		gr3,@(gr30,gr0)
+	membar
+	dcf		@(gr30,gr0)
+    999:
+.endm
+
+#elif defined(CONFIG_MB93093_PDK)
+#define LED_ADDR (0x20000023)
+
+.macro LEDS val
+	setlos		#\val,gr3
+	stb		gr3,@(gr30,gr0)
+	membar
+.endm
+
+#else
+#define LED_ADDR 0
+
+.macro LEDS val
+.endm
+#endif	
+
+#ifdef CONFIG_MMU
+__sdram_base = 0x00000000		/* base address to which SDRAM relocated */
+#else
+__sdram_base = 0xc0000000		/* base address to which SDRAM relocated */
+#endif
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/kernel/head-mmu-fr451.S linux-2.6.10-rc1-mm3-frv/arch/frv/kernel/head-mmu-fr451.S
--- /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/kernel/head-mmu-fr451.S	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/arch/frv/kernel/head-mmu-fr451.S	2004-11-05 14:13:03.000000000 +0000
@@ -0,0 +1,374 @@
+/* head-mmu-fr451.S: FR451 mmu-linux specific bits of initialisation
+ *
+ * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * 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.
+ */
+
+#include <linux/config.h>
+#include <linux/threads.h>
+#include <linux/linkage.h>
+#include <asm/ptrace.h>
+#include <asm/page.h>
+#include <asm/mem-layout.h>
+#include <asm/spr-regs.h>
+#include <asm/mb86943a.h>
+#include "head.inc"
+
+
+#define __400_DBR0	0xfe000e00
+#define __400_DBR1	0xfe000e08
+#define __400_DBR2	0xfe000e10
+#define __400_DBR3	0xfe000e18
+#define __400_DAM0	0xfe000f00
+#define __400_DAM1	0xfe000f08
+#define __400_DAM2	0xfe000f10
+#define __400_DAM3	0xfe000f18
+#define __400_LGCR	0xfe000010
+#define __400_LCR	0xfe000100
+#define __400_LSBR	0xfe000c00
+
+	.section	.text.init,"ax"
+	.balign		4
+
+###############################################################################
+#
+# describe the position and layout of the SDRAM controller registers
+#
+#	ENTRY:			EXIT:
+# GR5	-			cacheline size
+# GR11	-			displacement of 2nd SDRAM addr reg from GR14
+# GR12	-			displacement of 3rd SDRAM addr reg from GR14
+# GR13	-			displacement of 4th SDRAM addr reg from GR14
+# GR14	-			address of 1st SDRAM addr reg
+# GR15	-			amount to shift address by to match SDRAM addr reg
+# GR26	&__head_reference	[saved]
+# GR30	LED address		[saved]
+# CC0	-			T if DBR0 is present
+# CC1	-			T if DBR1 is present
+# CC2	-			T if DBR2 is present
+# CC3	-			T if DBR3 is present
+#
+###############################################################################
+	.globl		__head_fr451_describe_sdram
+__head_fr451_describe_sdram:
+	sethi.p		%hi(__400_DBR0),gr14
+	setlo		%lo(__400_DBR0),gr14
+	setlos.p	#__400_DBR1-__400_DBR0,gr11
+	setlos		#__400_DBR2-__400_DBR0,gr12
+	setlos.p	#__400_DBR3-__400_DBR0,gr13
+	setlos		#32,gr5			; cacheline size
+	setlos.p	#0,gr15			; amount to shift addr reg by
+	setlos		#0x00ff,gr4
+	movgs		gr4,cccr		; extant DARS/DAMK regs
+	bralr
+
+###############################################################################
+#
+# rearrange the bus controller registers
+#
+#	ENTRY:			EXIT:
+# GR26	&__head_reference	[saved]
+# GR30	LED address		revised LED address
+#
+###############################################################################
+	.globl		__head_fr451_set_busctl
+__head_fr451_set_busctl:
+	sethi.p		%hi(__400_LGCR),gr4
+	setlo		%lo(__400_LGCR),gr4
+	sethi.p		%hi(__400_LSBR),gr10
+	setlo		%lo(__400_LSBR),gr10
+	sethi.p		%hi(__400_LCR),gr11
+	setlo		%lo(__400_LCR),gr11
+
+	# set the bus controller
+	ldi		@(gr4,#0),gr5
+	ori		gr5,#0xff,gr5		; make sure all chip-selects are enabled
+	sti		gr5,@(gr4,#0)
+
+	sethi.p		%hi(__region_CS1),gr4
+	setlo		%lo(__region_CS1),gr4
+	sethi.p		%hi(__region_CS1_M),gr5
+	setlo		%lo(__region_CS1_M),gr5
+	sethi.p		%hi(__region_CS1_C),gr6
+	setlo		%lo(__region_CS1_C),gr6
+	sti		gr4,@(gr10,#1*0x08)
+	sti		gr5,@(gr10,#1*0x08+0x100)
+	sti		gr6,@(gr11,#1*0x08)
+	sethi.p		%hi(__region_CS2),gr4
+	setlo		%lo(__region_CS2),gr4
+	sethi.p		%hi(__region_CS2_M),gr5
+	setlo		%lo(__region_CS2_M),gr5
+	sethi.p		%hi(__region_CS2_C),gr6
+	setlo		%lo(__region_CS2_C),gr6
+	sti		gr4,@(gr10,#2*0x08)
+	sti		gr5,@(gr10,#2*0x08+0x100)
+	sti		gr6,@(gr11,#2*0x08)
+	sethi.p		%hi(__region_CS3),gr4
+	setlo		%lo(__region_CS3),gr4
+	sethi.p		%hi(__region_CS3_M),gr5
+	setlo		%lo(__region_CS3_M),gr5
+	sethi.p		%hi(__region_CS3_C),gr6
+	setlo		%lo(__region_CS3_C),gr6
+	sti		gr4,@(gr10,#3*0x08)
+	sti		gr5,@(gr10,#3*0x08+0x100)
+	sti		gr6,@(gr11,#3*0x08)
+	sethi.p		%hi(__region_CS4),gr4
+	setlo		%lo(__region_CS4),gr4
+	sethi.p		%hi(__region_CS4_M),gr5
+	setlo		%lo(__region_CS4_M),gr5
+	sethi.p		%hi(__region_CS4_C),gr6
+	setlo		%lo(__region_CS4_C),gr6
+	sti		gr4,@(gr10,#4*0x08)
+	sti		gr5,@(gr10,#4*0x08+0x100)
+	sti		gr6,@(gr11,#4*0x08)
+	sethi.p		%hi(__region_CS5),gr4
+	setlo		%lo(__region_CS5),gr4
+	sethi.p		%hi(__region_CS5_M),gr5
+	setlo		%lo(__region_CS5_M),gr5
+	sethi.p		%hi(__region_CS5_C),gr6
+	setlo		%lo(__region_CS5_C),gr6
+	sti		gr4,@(gr10,#5*0x08)
+	sti		gr5,@(gr10,#5*0x08+0x100)
+	sti		gr6,@(gr11,#5*0x08)
+	sethi.p		%hi(__region_CS6),gr4
+	setlo		%lo(__region_CS6),gr4
+	sethi.p		%hi(__region_CS6_M),gr5
+	setlo		%lo(__region_CS6_M),gr5
+	sethi.p		%hi(__region_CS6_C),gr6
+	setlo		%lo(__region_CS6_C),gr6
+	sti		gr4,@(gr10,#6*0x08)
+	sti		gr5,@(gr10,#6*0x08+0x100)
+	sti		gr6,@(gr11,#6*0x08)
+	sethi.p		%hi(__region_CS7),gr4
+	setlo		%lo(__region_CS7),gr4
+	sethi.p		%hi(__region_CS7_M),gr5
+	setlo		%lo(__region_CS7_M),gr5
+	sethi.p		%hi(__region_CS7_C),gr6
+	setlo		%lo(__region_CS7_C),gr6
+	sti		gr4,@(gr10,#7*0x08)
+	sti		gr5,@(gr10,#7*0x08+0x100)
+	sti		gr6,@(gr11,#7*0x08)
+	membar
+	bar
+
+	# adjust LED bank address
+#ifdef CONFIG_MB93091_VDK
+	sethi.p		%hi(__region_CS2 + 0x01200004),gr30
+	setlo		%lo(__region_CS2 + 0x01200004),gr30
+#endif
+	bralr
+
+###############################################################################
+#
+# determine the total SDRAM size
+#
+#	ENTRY:			EXIT:
+# GR25	-			SDRAM size
+# GR26	&__head_reference	[saved]
+# GR30	LED address		[saved]
+#
+###############################################################################
+	.globl		__head_fr451_survey_sdram
+__head_fr451_survey_sdram:
+	sethi.p		%hi(__400_DAM0),gr11
+	setlo		%lo(__400_DAM0),gr11
+	sethi.p		%hi(__400_DBR0),gr12
+	setlo		%lo(__400_DBR0),gr12
+
+	sethi.p		%hi(0xfe000000),gr17		; unused SDRAM DBR value
+	setlo		%lo(0xfe000000),gr17
+	setlos		#0,gr25
+
+	ldi		@(gr12,#0x00),gr4		; DAR0
+	subcc		gr4,gr17,gr0,icc0
+	beq		icc0,#0,__head_no_DCS0
+	ldi		@(gr11,#0x00),gr6		; DAM0: bits 31:20 match addr 31:20
+	add		gr25,gr6,gr25
+	addi		gr25,#1,gr25
+__head_no_DCS0:
+
+	ldi		@(gr12,#0x08),gr4		; DAR1
+	subcc		gr4,gr17,gr0,icc0
+	beq		icc0,#0,__head_no_DCS1
+	ldi		@(gr11,#0x08),gr6		; DAM1: bits 31:20 match addr 31:20
+	add		gr25,gr6,gr25
+	addi		gr25,#1,gr25
+__head_no_DCS1:
+
+	ldi		@(gr12,#0x10),gr4		; DAR2
+	subcc		gr4,gr17,gr0,icc0
+	beq		icc0,#0,__head_no_DCS2
+	ldi		@(gr11,#0x10),gr6		; DAM2: bits 31:20 match addr 31:20
+	add		gr25,gr6,gr25
+	addi		gr25,#1,gr25
+__head_no_DCS2:
+
+	ldi		@(gr12,#0x18),gr4		; DAR3
+	subcc		gr4,gr17,gr0,icc0
+	beq		icc0,#0,__head_no_DCS3
+	ldi		@(gr11,#0x18),gr6		; DAM3: bits 31:20 match addr 31:20
+	add		gr25,gr6,gr25
+	addi		gr25,#1,gr25
+__head_no_DCS3:
+	bralr
+
+###############################################################################
+#
+# set the protection map with the I/DAMPR registers
+#
+#	ENTRY:			EXIT:
+# GR25	SDRAM size		[saved]
+# GR26	&__head_reference	[saved]
+# GR30	LED address		[saved]
+#
+#
+# Using this map:
+#	REGISTERS	ADDRESS RANGE		VIEW
+#	===============	======================	===============================
+#	IAMPR0/DAMPR0	0xC0000000-0xCFFFFFFF	Cached kernel RAM Window
+#	DAMPR11		0xE0000000-0xFFFFFFFF	Uncached I/O
+#
+###############################################################################
+	.globl		__head_fr451_set_protection
+__head_fr451_set_protection:
+	movsg		lr,gr27
+
+	# set the I/O region protection registers for FR451 in MMU mode
+#define PGPROT_IO	xAMPRx_L|xAMPRx_M|xAMPRx_S_KERNEL|xAMPRx_C|xAMPRx_V
+
+	sethi.p		%hi(__region_IO),gr5
+	setlo		%lo(__region_IO),gr5
+	setlos		#PGPROT_IO|xAMPRx_SS_512Mb,gr4
+	or		gr4,gr5,gr4
+	movgs		gr5,damlr11			; General I/O tile
+	movgs		gr4,dampr11
+
+	# need to open a window onto at least part of the RAM for the kernel's use
+	sethi.p		%hi(__sdram_base),gr8
+	setlo		%lo(__sdram_base),gr8		; physical address
+	sethi.p		%hi(__page_offset),gr9
+	setlo		%lo(__page_offset),gr9		; virtual address
+
+	setlos		#xAMPRx_L|xAMPRx_M|xAMPRx_SS_256Mb|xAMPRx_S_KERNEL|xAMPRx_V,gr11
+	or		gr8,gr11,gr8
+
+	movgs		gr9,iamlr0			; mapped from real address 0
+	movgs		gr8,iampr0			; cached kernel memory at 0xC0000000
+	movgs		gr9,damlr0
+	movgs		gr8,dampr0
+
+	# set a temporary mapping for the kernel running at address 0 until we've turned on the MMU
+	sethi.p		%hi(__sdram_base),gr9
+	setlo		%lo(__sdram_base),gr9		; virtual address
+
+	and.p		gr4,gr11,gr4
+	and		gr5,gr11,gr5
+	or.p		gr4,gr11,gr4
+	or		gr5,gr11,gr5
+
+	movgs		gr9,iamlr1			; mapped from real address 0
+	movgs		gr8,iampr1			; cached kernel memory at 0x00000000
+	movgs		gr9,damlr1
+	movgs		gr8,dampr1
+
+	# we use DAMR2-10 for kmap_atomic(), cache flush and TLB management
+	# since the DAMLR regs are not going to change, we can set them now
+	# also set up IAMLR2 to the same as DAMLR5
+	sethi.p		%hi(KMAP_ATOMIC_PRIMARY_FRAME),gr4
+	setlo		%lo(KMAP_ATOMIC_PRIMARY_FRAME),gr4
+	sethi.p		%hi(PAGE_SIZE),gr5
+	setlo		%lo(PAGE_SIZE),gr5
+	
+	movgs		gr4,damlr2
+	movgs		gr4,iamlr2
+	add		gr4,gr5,gr4
+	movgs		gr4,damlr3
+	add		gr4,gr5,gr4
+	movgs		gr4,damlr4
+	add		gr4,gr5,gr4
+	movgs		gr4,damlr5
+	add		gr4,gr5,gr4
+	movgs		gr4,damlr6
+	add		gr4,gr5,gr4
+	movgs		gr4,damlr7
+	add		gr4,gr5,gr4
+	movgs		gr4,damlr8
+	add		gr4,gr5,gr4
+	movgs		gr4,damlr9
+	add		gr4,gr5,gr4
+	movgs		gr4,damlr10
+
+	movgs		gr0,dampr2
+	movgs		gr0,dampr4
+	movgs		gr0,dampr5
+	movgs		gr0,dampr6
+	movgs		gr0,dampr7
+	movgs		gr0,dampr8
+	movgs		gr0,dampr9
+	movgs		gr0,dampr10
+
+	movgs		gr0,iamlr3
+	movgs		gr0,iamlr4
+	movgs		gr0,iamlr5
+	movgs		gr0,iamlr6
+	movgs		gr0,iamlr7
+
+	movgs		gr0,iampr2
+	movgs		gr0,iampr3
+	movgs		gr0,iampr4
+	movgs		gr0,iampr5
+	movgs		gr0,iampr6
+	movgs		gr0,iampr7
+
+	# start in TLB context 0 with the swapper's page tables
+	movgs		gr0,cxnr
+
+	sethi.p		%hi(swapper_pg_dir),gr4
+	setlo		%lo(swapper_pg_dir),gr4
+	sethi.p		%hi(__page_offset),gr5
+	setlo		%lo(__page_offset),gr5
+	sub		gr4,gr5,gr4
+	movgs		gr4,ttbr
+	setlos		#xAMPRx_L|xAMPRx_M|xAMPRx_SS_16Kb|xAMPRx_S|xAMPRx_C|xAMPRx_V,gr5
+	or		gr4,gr5,gr4
+	movgs		gr4,dampr3
+
+	# the FR451 also has an extra trap base register
+	movsg		tbr,gr4
+	movgs		gr4,btbr
+
+	LEDS		0x3300
+	jmpl		@(gr27,gr0)
+
+###############################################################################
+#
+# finish setting up the protection registers
+#
+###############################################################################
+	.globl		__head_fr451_finalise_protection
+__head_fr451_finalise_protection:
+	# turn on the timers as appropriate
+	movgs		gr0,timerh
+	movgs		gr0,timerl
+	movgs		gr0,timerd
+	movsg		hsr0,gr4
+	sethi.p		%hi(HSR0_ETMI),gr5
+	setlo		%lo(HSR0_ETMI),gr5
+	or		gr4,gr5,gr4
+	movgs		gr4,hsr0
+	
+	# clear the TLB entry cache
+	movgs		gr0,iamlr1
+	movgs		gr0,iampr1
+	movgs		gr0,damlr1
+	movgs		gr0,dampr1
+
+	# clear the PGE cache
+	sethi.p		%hi(__flush_tlb_all),gr4
+	setlo		%lo(__flush_tlb_all),gr4
+	jmpl		@(gr4,gr0)
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/kernel/head.S linux-2.6.10-rc1-mm3-frv/arch/frv/kernel/head.S
--- /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/kernel/head.S	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/arch/frv/kernel/head.S	2004-11-05 14:13:03.123561649 +0000
@@ -0,0 +1,638 @@
+/* head.S: kernel entry point for FR-V kernel
+ *
+ * Copyright (C) 2003 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * 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.
+ */
+
+#include <linux/config.h>
+#include <linux/threads.h>
+#include <linux/linkage.h>
+#include <asm/ptrace.h>
+#include <asm/page.h>
+#include <asm/spr-regs.h>
+#include <asm/mb86943a.h>
+#include "head.inc"
+
+###############################################################################
+#
+# void _boot(unsigned long magic, char *command_line) __attribute__((noreturn))
+#
+# - if magic is 0xdead1eaf, then command_line is assumed to point to the kernel
+#   command line string
+#
+###############################################################################
+	.section	.text.head,"ax"
+	.balign		4
+
+	.globl		_boot, __head_reference
+        .type		_boot,@function
+_boot:
+__head_reference:
+	sethi.p		%hi(LED_ADDR),gr30
+	setlo		%lo(LED_ADDR),gr30
+
+	LEDS		0x0000
+
+	# calculate reference address for PC-relative stuff
+	call		0f
+0:	movsg		lr,gr26
+	addi		gr26,#__head_reference-0b,gr26
+
+	# invalidate and disable both of the caches and turn off the memory access checking
+	dcef		@(gr0,gr0),1
+	bar
+
+	sethi.p		%hi(~(HSR0_ICE|HSR0_DCE|HSR0_CBM|HSR0_EIMMU|HSR0_EDMMU)),gr4
+	setlo		%lo(~(HSR0_ICE|HSR0_DCE|HSR0_CBM|HSR0_EIMMU|HSR0_EDMMU)),gr4
+	movsg		hsr0,gr5
+	and		gr4,gr5,gr5
+	movgs		gr5,hsr0
+	movsg		hsr0,gr5
+
+	LEDS		0x0001
+
+	icei		@(gr0,gr0),1
+	dcei		@(gr0,gr0),1
+	bar
+
+	# turn the instruction cache back on
+	sethi.p		%hi(HSR0_ICE),gr4
+	setlo		%lo(HSR0_ICE),gr4
+	movsg		hsr0,gr5
+	or		gr4,gr5,gr5
+	movgs		gr5,hsr0
+	movsg		hsr0,gr5
+
+	bar
+
+	LEDS		0x0002
+
+	# retrieve the parameters (including command line) before we overwrite them
+	sethi.p		%hi(0xdead1eaf),gr7
+	setlo		%lo(0xdead1eaf),gr7
+	subcc		gr7,gr8,gr0,icc0
+	bne		icc0,#0,__head_no_parameters
+
+	sethi.p		%hi(redboot_command_line-1),gr6
+	setlo		%lo(redboot_command_line-1),gr6
+	sethi.p		%hi(__head_reference),gr4
+	setlo		%lo(__head_reference),gr4
+	sub		gr6,gr4,gr6
+	add.p		gr6,gr26,gr6
+	subi		gr9,#1,gr9
+	setlos.p	#511,gr4
+	setlos		#1,gr5
+
+__head_copy_cmdline:
+	ldubu.p		@(gr9,gr5),gr16
+	subicc		gr4,#1,gr4,icc0
+	stbu.p		gr16,@(gr6,gr5)
+	subicc		gr16,#0,gr0,icc1
+	bls		icc0,#0,__head_end_cmdline
+	bne		icc1,#1,__head_copy_cmdline
+__head_end_cmdline:
+	stbu		gr0,@(gr6,gr5)
+__head_no_parameters:
+
+###############################################################################
+#
+# we need to relocate the SDRAM to 0x00000000 (linux) or 0xC0000000 (uClinux)
+# - note that we're going to have to run entirely out of the icache whilst
+#   fiddling with the SDRAM controller registers
+#
+###############################################################################
+#ifdef CONFIG_MMU
+	call		__head_fr451_describe_sdram
+
+#else
+	movsg		psr,gr5
+	srli		gr5,#28,gr5
+	subicc		gr5,#3,gr0,icc0
+	beq		icc0,#0,__head_fr551_sdram
+
+	call		__head_fr401_describe_sdram
+	bra		__head_do_sdram
+
+__head_fr551_sdram:
+	call		__head_fr555_describe_sdram
+	LEDS		0x000d
+
+__head_do_sdram:
+#endif
+
+	# preload the registers with invalid values in case any DBR/DARS are marked not present
+	sethi.p		%hi(0xfe000000),gr17		; unused SDRAM DBR value
+	setlo		%lo(0xfe000000),gr17
+	or.p		gr17,gr0,gr20
+	or		gr17,gr0,gr21
+	or.p		gr17,gr0,gr22
+	or		gr17,gr0,gr23
+
+	# consult the SDRAM controller CS address registers
+	cld		@(gr14,gr0 ),gr20,	cc0,#1	; DBR0 / DARS0
+	cld		@(gr14,gr11),gr21,	cc1,#1	; DBR1 / DARS1
+	cld		@(gr14,gr12),gr22,	cc2,#1	; DBR2 / DARS2
+	cld.p		@(gr14,gr13),gr23,	cc3,#1	; DBR3 / DARS3
+
+	sll		gr20,gr15,gr20			; shift values up for FR551
+	sll		gr21,gr15,gr21
+	sll		gr22,gr15,gr22
+	sll		gr23,gr15,gr23
+
+	LEDS		0x0003
+
+	# assume the lowest valid CS line to be the SDRAM base and get its address
+	subcc		gr20,gr17,gr0,icc0
+	subcc.p		gr21,gr17,gr0,icc1
+	subcc		gr22,gr17,gr0,icc2
+	subcc.p		gr23,gr17,gr0,icc3
+	ckne		icc0,cc4			; T if DBR0 != 0xfe000000
+	ckne		icc1,cc5
+	ckne		icc2,cc6
+	ckne		icc3,cc7
+	cor		gr23,gr0,gr24,		cc7,#1	; GR24 = SDRAM base
+	cor		gr22,gr0,gr24,		cc6,#1
+	cor		gr21,gr0,gr24,		cc5,#1
+	cor		gr20,gr0,gr24,		cc4,#1
+
+	# calculate the displacement required to get the SDRAM into the right place in memory
+	sethi.p		%hi(__sdram_base),gr16
+	setlo		%lo(__sdram_base),gr16
+	sub		gr16,gr24,gr16			; delta = __sdram_base - DBRx
+
+	# calculate the new values to go in the controller regs
+	cadd.p		gr20,gr16,gr20,		cc4,#1	; DCS#0 (new) = DCS#0 (old) + delta
+	cadd		gr21,gr16,gr21,		cc5,#1
+	cadd.p		gr22,gr16,gr22,		cc6,#1
+	cadd		gr23,gr16,gr23,		cc7,#1
+
+	srl		gr20,gr15,gr20			; shift values down for FR551
+	srl		gr21,gr15,gr21
+	srl		gr22,gr15,gr22
+	srl		gr23,gr15,gr23
+
+	# work out the address at which the reg updater resides and lock it into icache
+	# also work out the address the updater will jump to when finished
+	sethi.p		%hi(__head_move_sdram-__head_reference),gr18
+	setlo		%lo(__head_move_sdram-__head_reference),gr18
+	sethi.p		%hi(__head_sdram_moved-__head_reference),gr19
+	setlo		%lo(__head_sdram_moved-__head_reference),gr19
+	add.p		gr18,gr26,gr18
+	add		gr19,gr26,gr19
+	add.p		gr19,gr16,gr19			; moved = addr + (__sdram_base - DBRx)
+	add		gr18,gr5,gr4			; two cachelines probably required
+
+	icpl		gr18,gr0,#1			; load and lock the cachelines
+	icpl		gr4,gr0,#1
+	LEDS		0x0004
+	membar
+	bar
+	jmpl		@(gr18,gr0)
+
+	.balign		32
+__head_move_sdram:
+	cst		gr20,@(gr14,gr0 ),	cc4,#1
+	cst		gr21,@(gr14,gr11),	cc5,#1
+	cst		gr22,@(gr14,gr12),	cc6,#1
+	cst		gr23,@(gr14,gr13),	cc7,#1
+	cld		@(gr14,gr0 ),gr20,	cc4,#1
+	cld		@(gr14,gr11),gr21,	cc5,#1
+	cld		@(gr14,gr12),gr22,	cc4,#1
+	cld		@(gr14,gr13),gr23,	cc7,#1
+	bar
+	membar
+	jmpl		@(gr19,gr0)
+
+	.balign		32
+__head_sdram_moved:
+	icul		gr18
+	add		gr18,gr5,gr4
+	icul		gr4
+	icei		@(gr0,gr0),1
+	dcei		@(gr0,gr0),1
+
+	LEDS		0x0005
+
+	# recalculate reference address
+	call		0f
+0:	movsg		lr,gr26
+	addi		gr26,#__head_reference-0b,gr26
+
+
+###############################################################################
+#
+# move the kernel image down to the bottom of the SDRAM
+#
+###############################################################################
+	sethi.p		%hi(__kernel_image_size_no_bss+15),gr4
+	setlo		%lo(__kernel_image_size_no_bss+15),gr4
+	srli.p		gr4,#4,gr4			; count
+	or		gr26,gr26,gr16			; source
+
+	sethi.p		%hi(__sdram_base),gr17		; destination
+	setlo		%lo(__sdram_base),gr17
+
+	setlos		#8,gr5
+	sub.p		gr16,gr5,gr16			; adjust src for LDDU
+	sub		gr17,gr5,gr17			; adjust dst for LDDU
+
+	sethi.p		%hi(__head_move_kernel-__head_reference),gr18
+	setlo		%lo(__head_move_kernel-__head_reference),gr18
+	sethi.p		%hi(__head_kernel_moved-__head_reference+__sdram_base),gr19
+	setlo		%lo(__head_kernel_moved-__head_reference+__sdram_base),gr19
+	add		gr18,gr26,gr18
+	icpl		gr18,gr0,#1
+	jmpl		@(gr18,gr0)
+
+	.balign		32
+__head_move_kernel:
+	lddu		@(gr16,gr5),gr10
+	lddu		@(gr16,gr5),gr12
+	stdu.p		gr10,@(gr17,gr5)
+	subicc		gr4,#1,gr4,icc0
+	stdu.p		gr12,@(gr17,gr5)
+	bhi		icc0,#0,__head_move_kernel
+	jmpl		@(gr19,gr0)
+
+	.balign		32
+__head_kernel_moved:
+	icul		gr18
+	icei		@(gr0,gr0),1
+	dcei		@(gr0,gr0),1
+
+	LEDS		0x0006
+
+	# recalculate reference address
+	call		0f
+0:	movsg		lr,gr26
+	addi		gr26,#__head_reference-0b,gr26
+
+
+###############################################################################
+#
+# rearrange the iomem map and set the protection registers
+#
+###############################################################################
+
+#ifdef CONFIG_MMU
+	LEDS		0x3301
+	call		__head_fr451_set_busctl
+	LEDS		0x3303
+	call		__head_fr451_survey_sdram
+	LEDS		0x3305
+	call		__head_fr451_set_protection
+
+#else
+	movsg		psr,gr5
+	srli		gr5,#PSR_IMPLE_SHIFT,gr5
+	subicc		gr5,#PSR_IMPLE_FR551,gr0,icc0
+	beq		icc0,#0,__head_fr555_memmap
+	subicc		gr5,#PSR_IMPLE_FR451,gr0,icc0
+	beq		icc0,#0,__head_fr451_memmap
+
+	LEDS		0x3101
+	call		__head_fr401_set_busctl
+	LEDS		0x3103
+	call		__head_fr401_survey_sdram
+	LEDS		0x3105
+	call		__head_fr401_set_protection
+	bra		__head_done_memmap
+
+__head_fr451_memmap:
+	LEDS		0x3301
+	call		__head_fr401_set_busctl
+	LEDS		0x3303
+	call		__head_fr401_survey_sdram
+	LEDS		0x3305
+	call		__head_fr451_set_protection
+	bra		__head_done_memmap
+
+__head_fr555_memmap:
+	LEDS		0x3501
+	call		__head_fr555_set_busctl
+	LEDS		0x3503
+	call		__head_fr555_survey_sdram
+	LEDS		0x3505
+	call		__head_fr555_set_protection
+
+__head_done_memmap:
+#endif
+	LEDS		0x0007
+
+###############################################################################
+#
+# turn the data cache and MMU on
+# - for the FR451 this'll mean that the window through which the kernel is
+#   viewed will change
+#
+###############################################################################
+
+#ifdef CONFIG_MMU
+#define MMUMODE		HSR0_EIMMU|HSR0_EDMMU|HSR0_EXMMU|HSR0_EDAT|HSR0_XEDAT
+#else
+#define MMUMODE		HSR0_EIMMU|HSR0_EDMMU
+#endif
+
+	movsg		hsr0,gr5
+
+	sethi.p		%hi(MMUMODE),gr4
+	setlo		%lo(MMUMODE),gr4
+	or		gr4,gr5,gr5
+
+#if defined(CONFIG_FRV_DEFL_CACHE_WTHRU)
+	sethi.p		%hi(HSR0_DCE|HSR0_CBM_WRITE_THRU),gr4
+	setlo		%lo(HSR0_DCE|HSR0_CBM_WRITE_THRU),gr4
+#elif defined(CONFIG_FRV_DEFL_CACHE_WBACK)
+	sethi.p		%hi(HSR0_DCE|HSR0_CBM_COPY_BACK),gr4
+	setlo		%lo(HSR0_DCE|HSR0_CBM_COPY_BACK),gr4
+#elif defined(CONFIG_FRV_DEFL_CACHE_WBEHIND)
+	sethi.p		%hi(HSR0_DCE|HSR0_CBM_COPY_BACK),gr4
+	setlo		%lo(HSR0_DCE|HSR0_CBM_COPY_BACK),gr4
+
+	movsg		psr,gr6
+	srli		gr6,#24,gr6
+	cmpi		gr6,#0x50,icc0		// FR451
+	beq		icc0,#0,0f
+	cmpi		gr6,#0x40,icc0		// FR405
+	bne		icc0,#0,1f
+0:
+	# turn off write-allocate
+	sethi.p		%hi(HSR0_NWA),gr6
+	setlo		%lo(HSR0_NWA),gr6
+	or		gr4,gr6,gr4
+1:
+
+#else
+#error No default cache configuration set
+#endif
+
+	or		gr4,gr5,gr5
+	movgs		gr5,hsr0
+	bar
+
+	LEDS		0x0008
+
+	sethi.p		%hi(__head_mmu_enabled),gr19
+	setlo		%lo(__head_mmu_enabled),gr19
+	jmpl		@(gr19,gr0)
+
+__head_mmu_enabled:
+	icei		@(gr0,gr0),#1
+	dcei		@(gr0,gr0),#1
+
+	LEDS		0x0009
+
+#ifdef CONFIG_MMU
+	call		__head_fr451_finalise_protection
+#endif
+
+	LEDS		0x000a
+
+###############################################################################
+#
+# set up the runtime environment
+#
+###############################################################################
+
+	# clear the BSS area
+	sethi.p		%hi(__bss_start),gr4
+	setlo		%lo(__bss_start),gr4
+	sethi.p		%hi(_end),gr5
+	setlo		%lo(_end),gr5
+	or.p		gr0,gr0,gr18
+	or		gr0,gr0,gr19
+
+0:
+	stdi		gr18,@(gr4,#0)
+	stdi		gr18,@(gr4,#8)
+	stdi		gr18,@(gr4,#16)
+	stdi.p		gr18,@(gr4,#24)
+	addi		gr4,#24,gr4
+	subcc		gr5,gr4,gr0,icc0
+	bhi		icc0,#2,0b
+
+	LEDS		0x000b
+
+	# save the SDRAM details
+	sethi.p		%hi(__sdram_old_base),gr4
+	setlo		%lo(__sdram_old_base),gr4
+	st		gr24,@(gr4,gr0)
+
+	sethi.p		%hi(__sdram_base),gr5
+	setlo		%lo(__sdram_base),gr5
+	sethi.p		%hi(memory_start),gr4
+	setlo		%lo(memory_start),gr4
+	st		gr5,@(gr4,gr0)
+
+	add		gr25,gr5,gr25
+	sethi.p		%hi(memory_end),gr4
+	setlo		%lo(memory_end),gr4
+	st		gr25,@(gr4,gr0)
+
+	# point the TBR at the kernel trap table
+	sethi.p		%hi(__entry_kerneltrap_table),gr4
+	setlo		%lo(__entry_kerneltrap_table),gr4
+	movgs		gr4,tbr
+
+	# set up the exception frame for init
+	sethi.p		%hi(__kernel_frame0_ptr),gr28
+	setlo		%lo(__kernel_frame0_ptr),gr28
+	sethi.p		%hi(_gp),gr16
+	setlo		%lo(_gp),gr16
+	sethi.p		%hi(__entry_usertrap_table),gr4
+	setlo		%lo(__entry_usertrap_table),gr4
+
+	lddi		@(gr28,#0),gr28		; load __frame & current
+	ldi.p		@(gr29,#4),gr15		; set current_thread
+
+	or		gr0,gr0,fp
+	or		gr28,gr0,sp
+
+	sti.p		gr4,@(gr28,REG_TBR)
+	setlos		#ISR_EDE|ISR_DTT_DIVBYZERO|ISR_EMAM_EXCEPTION,gr5
+	movgs		gr5,isr
+
+	# turn on and off various CPU services
+	movsg		psr,gr22
+	sethi.p		%hi(#PSR_EM|PSR_EF|PSR_CM|PSR_NEM),gr4
+	setlo		%lo(#PSR_EM|PSR_EF|PSR_CM|PSR_NEM),gr4
+	or		gr22,gr4,gr22
+	movgs		gr22,psr
+
+	andi		gr22,#~(PSR_PIL|PSR_PS|PSR_S),gr22
+	ori		gr22,#PSR_ET,gr22
+	sti		gr22,@(gr28,REG_PSR)
+
+
+###############################################################################
+#
+# set up the registers and jump into the kernel
+#
+###############################################################################
+
+	LEDS		0x000c
+
+	# initialise the processor and the peripherals
+	#call		SYMBOL_NAME(processor_init)
+	#call		SYMBOL_NAME(unit_init)
+	#LEDS		0x0aff
+
+	sethi.p		#0xe5e5,gr3
+	setlo		#0xe5e5,gr3
+	or.p		gr3,gr0,gr4
+	or		gr3,gr0,gr5
+	or.p		gr3,gr0,gr6
+	or		gr3,gr0,gr7
+	or.p		gr3,gr0,gr8
+	or		gr3,gr0,gr9
+	or.p		gr3,gr0,gr10
+	or		gr3,gr0,gr11
+	or.p		gr3,gr0,gr12
+	or		gr3,gr0,gr13
+	or.p		gr3,gr0,gr14
+	or		gr3,gr0,gr17
+	or.p		gr3,gr0,gr18
+	or		gr3,gr0,gr19
+	or.p		gr3,gr0,gr20
+	or		gr3,gr0,gr21
+	or.p		gr3,gr0,gr23
+	or		gr3,gr0,gr24
+	or.p		gr3,gr0,gr25
+	or		gr3,gr0,gr26
+	or.p		gr3,gr0,gr27
+#	or		gr3,gr0,gr30
+	or		gr3,gr0,gr31
+	movgs		gr0,lr
+	movgs		gr0,lcr
+	movgs		gr0,ccr
+	movgs		gr0,cccr
+
+#ifdef CONFIG_MMU
+	movgs		gr3,scr2
+	movgs		gr3,scr3
+#endif
+
+	LEDS		0x0fff
+
+	# invoke the debugging stub if present
+	# - arch/frv/kernel/debug-stub.c will shift control directly to init/main.c
+	#   (it will not return here)
+	break
+	.globl		__debug_stub_init_break
+__debug_stub_init_break:
+
+	# however, if you need to use an ICE, and don't care about using any userspace
+	# debugging tools (such as the ptrace syscall), you can just step over the break
+	# above and get to the kernel this way
+	# look at arch/frv/kernel/debug-stub.c: debug_stub_init() to see what you've missed
+	call		start_kernel
+
+	.globl		__head_end
+__head_end:
+	.size		_boot, .-_boot
+
+	# provide a point for GDB to place a break
+	.section	.text.start,"ax"
+	.globl		_start
+	.balign		4
+_start:
+	call		_boot
+
+	.previous
+###############################################################################
+#
+# split a tile off of the region defined by GR8-GR9
+#
+#	ENTRY:			EXIT:
+# GR4	-			IAMPR value representing tile
+# GR5	-			DAMPR value representing tile
+# GR6	-			IAMLR value representing tile
+# GR7	-			DAMLR value representing tile
+# GR8	region base pointer	[saved]
+# GR9	region top pointer	updated to exclude new tile
+# GR11	xAMLR mask		[saved]
+# GR25	SDRAM size		[saved]
+# GR30	LED address		[saved]
+#
+# - GR8 and GR9 should be rounded up/down to the nearest megabyte before calling
+#
+###############################################################################
+	.globl		__head_split_region
+	.type		__head_split_region,@function
+__head_split_region:
+	subcc.p		gr9,gr8,gr4,icc0
+	setlos		#31,gr5
+	scan.p		gr4,gr0,gr6
+	beq		icc0,#0,__head_region_empty
+	sub.p		gr5,gr6,gr6			; bit number of highest set bit (1MB=>20)
+	setlos		#1,gr4
+	sll.p		gr4,gr6,gr4			; size of region (1 << bitno)
+	subi		gr6,#17,gr6			; 1MB => 0x03
+	slli.p		gr6,#4,gr6			; 1MB => 0x30
+	sub		gr9,gr4,gr9			; move uncovered top down
+
+	or		gr9,gr6,gr4
+	ori		gr4,#xAMPRx_S_USER|xAMPRx_C_CACHED|xAMPRx_V,gr4
+	or.p		gr4,gr0,gr5
+
+	and		gr4,gr11,gr6
+	and.p		gr5,gr11,gr7
+	bralr
+
+__head_region_empty:
+	or.p		gr0,gr0,gr4
+	or		gr0,gr0,gr5
+	or.p		gr0,gr0,gr6
+	or		gr0,gr0,gr7
+	bralr
+	.size		__head_split_region, .-__head_split_region
+
+###############################################################################
+#
+# write the 32-bit hex number in GR8 to ttyS0
+#
+###############################################################################
+#if 0
+	.globl		__head_write_to_ttyS0
+	.type		__head_write_to_ttyS0,@function
+__head_write_to_ttyS0:
+	sethi.p		%hi(0xfeff9c00),gr31
+	setlo		%lo(0xfeff9c00),gr31
+	setlos		#8,gr20
+
+0:	ldubi		@(gr31,#5*8),gr21
+	andi		gr21,#0x60,gr21
+	subicc		gr21,#0x60,gr21,icc0
+	bne		icc0,#0,0b
+
+1:	srli		gr8,#28,gr21
+	slli		gr8,#4,gr8
+
+	addi		gr21,#'0',gr21
+	subicc		gr21,#'9',gr0,icc0
+	bls		icc0,#2,2f
+	addi		gr21,#'A'-'0'-10,gr21
+2:
+	stbi		gr21,@(gr31,#0*8)
+	subicc		gr20,#1,gr20,icc0
+	bhi		icc0,#2,1b
+
+	setlos		#'\r',gr21
+	stbi		gr21,@(gr31,#0*8)
+
+	setlos		#'\n',gr21
+	stbi		gr21,@(gr31,#0*8)
+
+3:	ldubi		@(gr31,#5*8),gr21
+	andi		gr21,#0x60,gr21
+	subicc		gr21,#0x60,gr21,icc0
+	bne		icc0,#0,3b
+	bralr
+
+	.size		__head_write_to_ttyS0, .-__head_write_to_ttyS0
+#endif

^ permalink raw reply	[flat|nested] 87+ messages in thread

* [PATCH 3/20] FRV: Fujitsu FR-V CPU arch implementation part 1
  2004-11-08 14:34 [PATCH 1/20] FRV: Fujitsu FR-V CPU arch maintainer record dhowells
                   ` (4 preceding siblings ...)
  2004-11-08 14:34 ` [PATCH 7/20] FRV: Fujitsu FR-V CPU arch implementation part 5 dhowells
@ 2004-11-08 14:34 ` dhowells
  2004-11-08 14:34 ` [PATCH 8/20] FRV: Fujitsu FR-V CPU arch implementation part 6 dhowells
                   ` (10 subsequent siblings)
  16 siblings, 0 replies; 87+ messages in thread
From: dhowells @ 2004-11-08 14:34 UTC (permalink / raw)
  To: torvalds, akpm, davidm; +Cc: linux-kernel, uclinux-dev

The attached patches provides part 1 of an architecture implementation
for the Fujitsu FR-V CPU series, configurably as Linux or uClinux.

Signed-Off-By: dhowells@redhat.com
---
diffstat frv-arch_1-2610rc1mm3.diff
 Kconfig              |  496 +++++++++++++++++++++++++++++++++++++++++++++++++++
 Makefile             |  118 ++++++++++++
 boot/Makefile        |   73 +++++++
 kernel/vmlinux.lds.S |  187 +++++++++++++++++++
 4 files changed, 874 insertions(+)

diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/Makefile linux-2.6.10-rc1-mm3-frv/arch/frv/Makefile
--- /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/Makefile	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/arch/frv/Makefile	2004-11-05 14:13:03.323544758 +0000
@@ -0,0 +1,118 @@
+#
+# frv/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) 2003, 2004 Red Hat Inc.
+# - Written by David Howells <dhowells@redhat.com>
+# - Derived from arch/m68knommu/Makefile,
+#	Copyright (c) 1999,2001  D. Jeff Dionne <jeff@lineo.ca>,
+#	Rt-Control Inc. / Lineo, Inc.
+#
+# Copyright (C) 1998,1999  D. Jeff Dionne <jeff@uclinux.org>,
+#                          Kenneth Albanowski <kjahds@kjahds.com>,
+#
+# Based on arch/m68k/Makefile:
+# Copyright (C) 1994 by Hamish Macdonald
+#
+
+CCSPECS	:= $(shell $(CC) -v 2>&1 | grep "^Reading specs from " | head -1 | cut -c20-)
+CCDIR	:= $(strip $(patsubst %/specs,%,$(CCSPECS)))
+CPUCLASS := fr400
+
+# test for cross compiling
+COMPILE_ARCH = $(shell uname -m)
+
+ifdef CONFIG_MMU
+UTS_SYSNAME = -DUTS_SYSNAME=\"Linux\"
+else
+UTS_SYSNAME = -DUTS_SYSNAME=\"uClinux\"
+endif
+
+ARCHMODFLAGS	+= -G0 -mlong-calls
+
+ifdef CONFIG_GPREL_DATA_8
+CFLAGS		+= -G8
+else
+ifdef CONFIG_GPREL_DATA_4
+CFLAGS		+= -G4
+else
+ifdef CONFIG_GPREL_DATA_NONE
+CFLAGS		+= -G0
+endif
+endif
+endif
+
+#LDFLAGS_vmlinux	:= -Map linkmap.txt
+
+ifdef CONFIG_GC_SECTIONS
+CFLAGS		+= -ffunction-sections -fdata-sections
+LINKFLAGS	+= --gc-sections
+endif
+
+ifndef CONFIG_FRAME_POINTER
+CFLAGS		+= -mno-linked-fp
+endif
+
+ifdef CONFIG_CPU_FR451_COMPILE
+CFLAGS		+= -mcpu=fr450
+AFLAGS		+= -mcpu=fr450
+ASFLAGS		+= -mcpu=fr450
+else
+ifdef CONFIG_CPU_FR551_COMPILE
+CFLAGS		+= -mcpu=fr550
+AFLAGS		+= -mcpu=fr550
+ASFLAGS		+= -mcpu=fr550
+else
+CFLAGS		+= -mcpu=fr400
+AFLAGS		+= -mcpu=fr400
+ASFLAGS		+= -mcpu=fr400
+endif
+endif
+
+# pretend the kernel is going to run on an FR400 with no media-fp unit
+# - reserve CC3 for use with atomic ops
+# - all the extra registers are dealt with only at context switch time
+CFLAGS		+= -mno-fdpic -mgpr-32 -msoft-float -mno-media
+CFLAGS		+= -ffixed-fcc3 -ffixed-cc3 -ffixed-gr15
+AFLAGS		+= -mno-fdpic
+ASFLAGS		+= -mno-fdpic
+
+# make sure the .S files get compiled with debug info
+# and disable optimisations that are unhelpful whilst debugging
+ifdef CONFIG_DEBUG_INFO
+CFLAGS		+= -O1
+AFLAGS		+= -Wa,--gdwarf2
+ASFLAGS		+= -Wa,--gdwarf2
+endif
+
+head-y		:= arch/frv/kernel/head.o arch/frv/kernel/init_task.o
+
+core-y		+= arch/frv/kernel/ arch/frv/mm/
+libs-y		+= arch/frv/lib/
+
+core-$(CONFIG_MB93090_MB00)	+= arch/frv/mb93090-mb00/
+
+all: Image
+
+Image: vmlinux
+	$(Q)$(MAKE) $(build)=arch/frv/boot $@
+
+bootstrap:
+	$(Q)$(MAKEBOOT) bootstrap
+
+archmrproper:
+	$(Q)$(MAKE) -C arch/frv/boot mrproper
+
+archclean:
+	$(Q)$(MAKE) -C arch/frv/boot clean
+
+archdep: scripts/mkdep symlinks
+	$(Q)$(MAKE) -C arch/frv/boot dep
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/boot/Makefile linux-2.6.10-rc1-mm3-frv/arch/frv/boot/Makefile
--- /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/boot/Makefile	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/arch/frv/boot/Makefile	2004-11-05 14:13:03.064566632 +0000
@@ -0,0 +1,73 @@
+#
+# arch/arm/boot/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
+# for more details.
+#
+# Copyright (C) 1995-2000 Russell King
+#
+
+SYSTEM	=$(TOPDIR)/$(LINUX)
+
+ZTEXTADDR	 = 0x02080000
+PARAMS_PHYS	 = 0x0207c000
+INITRD_PHYS	 = 0x02180000
+INITRD_VIRT	 = 0x02180000
+
+#
+# If you don't define ZRELADDR above,
+# then it defaults to ZTEXTADDR
+#
+ifeq ($(ZRELADDR),)
+ZRELADDR	= $(ZTEXTADDR)
+endif
+
+export	SYSTEM ZTEXTADDR ZBSSADDR ZRELADDR INITRD_PHYS INITRD_VIRT PARAMS_PHYS
+
+Image: $(obj)/Image
+
+targets: $(obj)/Image
+
+$(obj)/Image: vmlinux FORCE
+	$(OBJCOPY) -O binary -R .note -R .comment -S vmlinux $@
+
+#$(obj)/Image:	$(CONFIGURE) $(SYSTEM)
+#	$(OBJCOPY) -O binary -R .note -R .comment -g -S $(SYSTEM) $@
+
+bzImage: zImage
+
+zImage:	$(CONFIGURE) compressed/$(LINUX)
+	$(OBJCOPY) -O binary -R .note -R .comment -S compressed/$(LINUX) $@
+
+bootpImage: bootp/bootp
+	$(OBJCOPY) -O binary -R .note -R .comment -S bootp/bootp $@
+
+compressed/$(LINUX): $(TOPDIR)/$(LINUX) dep
+	@$(MAKE) -C compressed $(LINUX)
+
+bootp/bootp: zImage initrd
+	@$(MAKE) -C bootp bootp
+
+initrd:
+	@test "$(INITRD_VIRT)" != "" || (echo This architecture does not support INITRD; exit -1)
+	@test "$(INITRD)" != "" || (echo You must specify INITRD; exit -1)
+
+#
+# installation
+#
+install: $(CONFIGURE) Image
+	sh ./install.sh $(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION) Image $(TOPDIR)/System.map "$(INSTALL_PATH)"
+
+zinstall: $(CONFIGURE) zImage
+	sh ./install.sh $(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION) zImage $(TOPDIR)/System.map "$(INSTALL_PATH)"
+
+#
+# miscellany
+#
+mrproper clean:
+	$(RM) Image zImage bootpImage
+#	@$(MAKE) -C compressed clean
+#	@$(MAKE) -C bootp clean
+
+dep:
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/Kconfig linux-2.6.10-rc1-mm3-frv/arch/frv/Kconfig
--- /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/Kconfig	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/arch/frv/Kconfig	2004-11-05 14:13:03.065566547 +0000
@@ -0,0 +1,496 @@
+#
+# For a description of the syntax of this configuration file,
+# see Documentation/kbuild/kconfig-language.txt.
+#
+config FRV
+	bool
+	default y
+
+config UID16
+	bool
+	default y
+
+config RWSEM_GENERIC_SPINLOCK
+	bool
+	default y
+
+config RWSEM_XCHGADD_ALGORITHM
+	bool
+
+config GENERIC_FIND_NEXT_BIT
+	bool
+	default y
+
+config GENERIC_CALIBRATE_DELAY
+	bool
+	default n
+
+config GENERIC_HARDIRQS
+	bool
+	default n
+
+mainmenu "Fujitsu FR-V Kernel Configuration"
+
+source "init/Kconfig"
+
+
+menu "Fujitsu FR-V system setup"
+
+config MMU
+	bool "MMU support"
+	help
+	  This options switches on and off support for the FR-V MMU
+	  (effectively switching between vmlinux and uClinux). Not all FR-V
+	  CPUs support this. Currently only the FR451 has a sufficiently
+	  featured MMU.
+
+config FRV_OUTOFLINE_ATOMIC_OPS
+	bool "Out-of-line the FRV atomic operations"
+	default n
+	help
+	  Setting this option causes the FR-V atomic operations to be mostly
+	  implemented out-of-line.
+
+	  See Documentation/fujitsu/frv/atomic-ops.txt for more information.
+
+config HIGHMEM
+	bool "High memory support"
+	depends on MMU
+	default y
+	help
+	  If you wish to use more than 256MB of memory with your MMU based
+	  system, you will need to select this option. The kernel can only see
+	  the memory between 0xC0000000 and 0xD0000000 directly... everything
+	  else must be kmapped.
+
+	  The arch is, however, capable of supporting up to 3GB of SDRAM.
+
+config HIGHPTE
+	bool "Allocate page tables in highmem"
+	depends on HIGHMEM
+	default y
+	help
+	  The VM uses one page of memory for each page table.  For systems
+	  with a lot of RAM, this can be wasteful of precious low memory.
+	  Setting this option will put user-space page tables in high memory.
+
+choice
+	prompt "uClinux kernel load address"
+	depends on !MMU
+	default UCPAGE_OFFSET_C0000000
+	help
+	  This option sets the base address for the uClinux kernel. The kernel
+	  will rearrange the SDRAM layout to start at this address, and move
+	  itself to start there. It must be greater than 0, and it must be
+	  sufficiently less than 0xE0000000 that the SDRAM does not intersect
+	  the I/O region.
+
+	  The base address must also be aligned such that the SDRAM controller
+	  can decode it. For instance, a 512MB SDRAM bank must be 512MB aligned.
+
+config UCPAGE_OFFSET_20000000
+       bool "0x20000000"
+
+config UCPAGE_OFFSET_40000000
+       bool "0x40000000"
+
+config UCPAGE_OFFSET_60000000
+       bool "0x60000000"
+
+config UCPAGE_OFFSET_80000000
+       bool "0x80000000"
+
+config UCPAGE_OFFSET_A0000000
+       bool "0xA0000000"
+
+config UCPAGE_OFFSET_C0000000
+       bool "0xC0000000 (Recommended)"
+
+endchoice
+
+config PROTECT_KERNEL
+	bool "Protect core kernel against userspace"
+	depends on !MMU
+	default y
+	help
+	  Selecting this option causes the uClinux kernel to change the
+	  permittivity of DAMPR register covering the core kernel image to
+	  prevent userspace accessing the underlying memory directly.
+
+choice
+	prompt "CPU Caching mode"
+	default FRV_DEFL_CACHE_WBACK
+	help
+	  This option determines the default caching mode for the kernel.
+
+	  Write-Back caching mode involves the all reads and writes causing
+	  the affected cacheline to be read into the cache first before being
+	  operated upon. Memory is not then updated by a write until the cache
+	  is filled and a cacheline needs to be displaced from the cache to
+	  make room. Only at that point is it written back.
+
+	  Write-Behind caching is similar to Write-Back caching, except that a
+	  write won't fetch a cacheline into the cache if there isn't already
+	  one there; it will write directly to memory instead.
+
+	  Write-Through caching only fetches cachelines from memory on a
+	  read. Writes always get written directly to memory. If the affected
+	  cacheline is also in cache, it will be updated too.
+
+	  The final option is to turn of caching entirely.
+
+	  Note that not all CPUs support Write-Behind caching. If the CPU on
+	  which the kernel is running doesn't, it'll fall back to Write-Back
+	  caching.
+
+config FRV_DEFL_CACHE_WBACK
+	bool "Write-Back"
+
+config FRV_DEFL_CACHE_WBEHIND
+	bool "Write-Behind"
+
+config FRV_DEFL_CACHE_WTHRU
+	bool "Write-Through"
+
+config FRV_DEFL_CACHE_DISABLED
+	bool "Disabled"
+
+endchoice
+
+menu "CPU core support"
+
+config CPU_FR401
+	bool "Include FR401 core support"
+	depends on !MMU
+	default y
+	help
+	  This enables support for the FR401, FR401A and FR403 CPUs
+
+config CPU_FR405
+	bool "Include FR405 core support"
+	depends on !MMU
+	default y
+	help
+	  This enables support for the FR405 CPU
+
+config CPU_FR451
+	bool "Include FR451 core support"
+	default y
+	help
+	  This enables support for the FR451 CPU
+
+config CPU_FR451_COMPILE
+	bool "Specifically compile for FR451 core"
+	depends on CPU_FR451 && !CPU_FR401 && !CPU_FR405 && !CPU_FR551
+	default y
+	help
+	  This causes appropriate flags to be passed to the compiler to
+	  optimise for the FR451 CPU
+
+config CPU_FR551
+	bool "Include FR551 core support"
+	depends on !MMU
+	default y
+	help
+	  This enables support for the FR555 CPU
+
+config CPU_FR551_COMPILE
+	bool "Specifically compile for FR551 core"
+	depends on CPU_FR551 && !CPU_FR401 && !CPU_FR405 && !CPU_FR451
+	default y
+	help
+	  This causes appropriate flags to be passed to the compiler to
+	  optimise for the FR555 CPU
+
+endmenu
+
+choice
+	prompt "System support"
+	default MB93091_VDK
+
+config MB93091_VDK
+	bool "MB93091 CPU board with or without motherboard"
+
+config MB93093_PDK
+	bool "MB93093 PDK unit"
+
+endchoice
+
+if MB93091_VDK
+choice
+	prompt "Motherboard support"
+	default MB93090_MB00
+
+config MB93090_MB00
+	bool "Use the MB93090-MB00 motherboard"
+	help
+	  Select this option if the MB93091 CPU board is going to be used with
+	  a MB93090-MB00 VDK motherboard
+
+config MB93091_NO_MB
+	bool "Use standalone"
+	help
+	  Select this option if the MB93091 CPU board is going to be used
+	  without a motherboard
+
+endchoice
+endif
+
+choice
+	prompt "GP-Relative data support"
+	default GPREL_DATA_8
+	help
+	  This option controls what data, if any, should be placed in the GP
+	  relative data sections. Using this means that the compiler can
+	  generate accesses to the data using GR16-relative addressing which
+	  is faster than absolute instructions and saves space (2 instructions
+	  per access).
+
+	  However, the GPREL region is limited in size because the immediate
+	  value used in the load and store instructions is limited to a 12-bit
+	  signed number.
+
+	  So if the linker starts complaining that accesses to GPREL data are
+	  out of range, try changing this option from the default.
+
+	  Note that modules will always be compiled with this feature disabled
+	  as the module data will not be in range of the GP base address.
+
+config GPREL_DATA_8
+	bool "Put data objects of up to 8 bytes into GP-REL"
+
+config GPREL_DATA_4
+	bool "Put data objects of up to 4 bytes into GP-REL"
+
+config GPREL_DATA_NONE
+	bool "Don't use GP-REL"
+
+endchoice
+
+config PCI
+	bool "Use PCI"
+	depends on MB93090_MB00
+	default y
+	help
+	  Some FR-V systems (such as the MB93090-MB00 VDK) have PCI
+	  onboard. If you have one of these boards and you wish to use the PCI
+	  facilities, say Y here.
+
+	  The PCI-HOWTO, available from
+	  <http://www.tldp.org/docs.html#howto>, contains valuable
+	  information about which PCI hardware does work under Linux and which
+	  doesn't.
+
+config RESERVE_DMA_COHERENT
+	bool "Reserve DMA coherent memory"
+	depends on PCI && !MMU
+	default y
+	help
+	  Many PCI drivers require access to uncached memory for DMA device
+	  communications (such as is done with some Ethernet buffer rings). If
+	  a fully featured MMU is available, this can be done through page
+	  table settings, but if not, a region has to be set aside and marked
+	  with a special DAMPR register.
+
+	  Setting this option causes uClinux to set aside a portion of the
+	  available memory for use in this manner. The memory will then be
+	  unavailable for normal kernel use.
+
+source "drivers/pci/Kconfig"
+
+config PCMCIA
+	tristate "Use PCMCIA"
+	help
+	  Say Y here if you want to attach PCMCIA- or PC-cards to your FR-V
+	  board.  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 MATH_EMULATION
+#	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.
+
+menu "Power management options"
+source kernel/power/Kconfig
+endmenu
+
+endmenu
+
+
+menu "Executable formats"
+
+source "fs/Kconfig.binfmt"
+
+endmenu
+
+source "drivers/Kconfig"
+
+source "fs/Kconfig"
+
+menu "Kernel hacking"
+
+config DEBUG_KERNEL
+	bool "Kernel debugging"
+	help
+	  Say Y here if you are developing drivers or trying to debug and
+	  identify kernel problems.
+
+config EARLY_PRINTK
+	bool "Early printk"
+	depends on EMBEDDED && DEBUG_KERNEL
+	default n
+	help
+	  Write kernel log output directly into the VGA buffer or to a serial
+	  port.
+
+	  This is useful for kernel debugging when your machine crashes very
+	  early before the console code is initialized. For normal operation
+	  it is not recommended because it looks ugly and doesn't cooperate
+	  with klogd/syslogd or the X server. You should normally N here,
+	  unless you want to debug such a crash.
+
+config DEBUG_STACKOVERFLOW
+	bool "Check for stack overflows"
+	depends on DEBUG_KERNEL
+
+config DEBUG_SLAB
+	bool "Debug memory allocations"
+	depends on DEBUG_KERNEL
+	help
+	  Say Y here to have the kernel do limited verification on memory
+	  allocation as well as poisoning memory on free to catch use of freed
+	  memory.
+
+config MAGIC_SYSRQ
+	bool "Magic SysRq key"
+	depends on DEBUG_KERNEL
+	help
+	  If you say Y here, you will have some control over the system even
+	  if the system crashes for example during kernel debugging (e.g., you
+	  will be able to flush the buffer cache to disk, reboot the system
+	  immediately or dump some status information). This is accomplished
+	  by pressing various keys while holding SysRq (Alt+PrintScreen). It
+	  also works on a serial console (on PC hardware at least), if you
+	  send a BREAK and then within 5 seconds a command keypress. The
+	  keys are documented in <file:Documentation/sysrq.txt>. Don't say Y
+	  unless you really know what this hack does.
+
+config DEBUG_SPINLOCK
+	bool "Spinlock debugging"
+	depends on DEBUG_KERNEL
+	help
+	  Say Y here and build SMP to catch missing spinlock initialization
+	  and certain other kinds of spinlock errors commonly made.  This is
+	  best used in conjunction with the NMI watchdog so that spinlock
+	  deadlocks are also debuggable.
+	  
+config DEBUG_SPINLOCK_SLEEP
+	bool "Sleep-inside-spinlock checking"
+	depends on DEBUG_KERNEL
+	help
+	  If you say Y here, various routines which may sleep will become very
+	  noisy if they are called with a spinlock held.	
+
+config DEBUG_PAGEALLOC
+	bool "Page alloc debugging"
+	depends on DEBUG_KERNEL
+	help
+	  Unmap pages from the kernel linear mapping after free_pages().
+	  This results in a large slowdown, but helps to find certain types
+	  of memory corruptions.
+
+config DEBUG_HIGHMEM
+	bool "Highmem debugging"
+	depends on DEBUG_KERNEL && HIGHMEM
+	help
+	  This options enables addition error checking for high memory systems.
+	  Disable for production systems.
+
+config DEBUG_INFO
+	bool "Compile the kernel with debug info"
+	depends on DEBUG_KERNEL
+	help
+          If you say Y here the resulting kernel image will include
+	  debugging info resulting in a larger kernel image.
+	  Say Y here only if you plan to use gdb to debug the kernel.
+	  If you don't debug the kernel, you can say N.
+
+config DEBUG_BUGVERBOSE
+	bool "Verbose BUG() reporting"
+	depends on DEBUG_KERNEL
+
+config FRAME_POINTER
+	bool "Compile the kernel with frame pointers"
+	depends on DEBUG_KERNEL
+	help
+	  If you say Y here the resulting kernel image will be slightly larger
+	  and slower, but it will give very useful debugging information.
+	  If you don't debug the kernel, you can say N, but we may not be able
+	  to solve problems without frame pointers.
+
+config GDBSTUB
+	bool "Remote GDB kernel debugging"
+	depends on DEBUG_KERNEL
+	select DEBUG_INFO
+	select FRAME_POINTER
+	help
+	  If you say Y here, it will be possible to remotely debug the kernel
+	  using gdb. This enlarges your kernel ELF image disk size by several
+	  megabytes and requires a machine with more than 16 MB, better 32 MB
+	  RAM to avoid excessive linking time. This is only useful for kernel
+	  hackers. If unsure, say N.
+
+choice
+	prompt "GDB stub port"
+	default GDBSTUB_UART1
+	depends on GDBSTUB
+	help
+	  Select the on-CPU port used for GDB-stub
+
+config GDBSTUB_UART0
+	bool "/dev/ttyS0"
+
+config GDBSTUB_UART1
+	bool "/dev/ttyS1"
+
+endchoice
+
+config GDBSTUB_IMMEDIATE
+	bool "Break into GDB stub immediately"
+	depends on GDBSTUB
+	help
+	  If you say Y here, GDB stub will break into the program as soon as
+	  possible, leaving the program counter at the beginning of
+	  start_kernel() in init/main.c.
+
+config GDB_CONSOLE
+	bool "Console output to GDB"
+	depends on KGDB
+	help
+	  If you are using GDB for remote debugging over a serial port and
+	  would like kernel messages to be formatted into GDB $O packets so
+	  that GDB prints them as program output, say 'Y'.
+
+endmenu
+
+source "security/Kconfig"
+
+source "crypto/Kconfig"
+
+source "lib/Kconfig"
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/kernel/vmlinux.lds.S linux-2.6.10-rc1-mm3-frv/arch/frv/kernel/vmlinux.lds.S
--- /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/kernel/vmlinux.lds.S	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/arch/frv/kernel/vmlinux.lds.S	2004-11-05 14:13:03.258550247 +0000
@@ -0,0 +1,187 @@
+/* ld script to make FRV Linux kernel -*- c -*-
+ * Written by Martin Mares <mj@atrey.karlin.mff.cuni.cz>;
+ */
+OUTPUT_FORMAT("elf32-frv", "elf32-frv", "elf32-frv")
+OUTPUT_ARCH(frv)
+ENTRY(_start)
+
+#include <asm-generic/vmlinux.lds.h>
+#include <asm/processor.h>
+#include <asm/page.h>
+#include <asm/cache.h>
+#include <asm/thread_info.h>
+
+jiffies = jiffies_64 + 4;
+
+__page_offset = 0xc0000000;		/* start of area covered by struct pages */
+__kernel_image_start = __page_offset;	/* address at which kernel image resides */
+
+SECTIONS
+{
+  . = __kernel_image_start;
+
+  /* discardable initialisation code and data */
+  . = ALIGN(PAGE_SIZE);			/* Init code and data */
+  __init_begin = .;
+
+  _sinittext = .;
+  .init.text : {
+	*(.text.head)
+#ifndef CONFIG_DEBUG_INFO
+	*(.init.text)
+	*(.exit.text)
+	*(.exit.data)
+	*(.exitcall.exit)
+#endif
+  }
+  _einittext = .;
+  .init.data : { *(.init.data) }
+
+  . = ALIGN(8);
+  __setup_start = .;
+  .setup.init : { KEEP(*(.init.setup)) }
+  __setup_end = .;
+
+  __initcall_start = .;
+  .initcall.init : {
+	*(.initcall1.init) 
+	*(.initcall2.init) 
+	*(.initcall3.init) 
+	*(.initcall4.init) 
+	*(.initcall5.init) 
+	*(.initcall6.init) 
+	*(.initcall7.init)
+  }
+  __initcall_end = .;
+  __con_initcall_start = .;
+  .con_initcall.init : { *(.con_initcall.init) }
+  __con_initcall_end = .;
+  SECURITY_INIT
+  . = ALIGN(4);
+  __alt_instructions = .;
+  .altinstructions : { *(.altinstructions) } 
+  __alt_instructions_end = .; 
+ .altinstr_replacement : { *(.altinstr_replacement) } 
+
+  __per_cpu_start = .;
+  .data.percpu  : { *(.data.percpu) }
+  __per_cpu_end = .;
+
+  . = ALIGN(4096);
+  __initramfs_start = .;
+  .init.ramfs : { *(.init.ramfs) }
+  __initramfs_end = .;
+
+  . = ALIGN(THREAD_SIZE);
+  __init_end = .;
+
+  /* put sections together that have massive alignment issues */
+  . = ALIGN(THREAD_SIZE);
+  .data.init_task : {
+	  /* init task record & stack */
+	  *(.data.init_task)
+  }
+
+  .trap : {
+	/* trap table management - read entry-table.S before modifying */
+	. = ALIGN(8192);
+	__trap_tables = .;
+	*(.trap.user)	
+	*(.trap.kernel)	
+	. = ALIGN(4096);
+	*(.trap.break)	
+  }
+
+  . = ALIGN(4096);
+  .data.page_aligned : { *(.data.idt) }
+
+  . = ALIGN(L1_CACHE_BYTES);
+  .data.cacheline_aligned : { *(.data.cacheline_aligned) }
+
+  /* Text and read-only data */
+  . = ALIGN(4);
+  _text = .;
+  _stext = .;
+  .text : {
+	*(
+		.text.start .text .text.*
+#ifdef CONFIG_DEBUG_INFO
+	.init.text
+	.exit.text
+	.exitcall.exit
+#endif
+	)
+	SCHED_TEXT
+	*(.fixup)
+	*(.gnu.warning)
+	*(.exitcall.exit)
+	} = 0x9090
+
+  _etext = .;			/* End of text section */
+
+  RODATA
+
+  .rodata : {
+	*(.trap.vector)
+
+	/* this clause must not be modified - the ordering and adjacency are imperative */
+	__trap_fixup_tables = .;
+	*(.trap.fixup.user .trap.fixup.kernel)
+
+	}
+
+  . = ALIGN(8);		/* Exception table */
+  __start___ex_table = .;
+  __ex_table : { KEEP(*(__ex_table)) }
+  __stop___ex_table = .;
+
+  _sdata = .;
+  .data : {			/* Data */
+	*(.data .data.*)
+	*(.exit.data)
+	CONSTRUCTORS
+	}
+
+  _edata = .;			/* End of data section */
+
+  /* GP section */
+  . = ALIGN(L1_CACHE_BYTES);
+  _gp = . + 2048;
+  PROVIDE (gp = _gp);
+
+  .sdata : { *(.sdata .sdata.*) }
+
+  /* BSS */
+  . = ALIGN(L1_CACHE_BYTES);
+  __bss_start = .;
+
+  .sbss		: { *(.sbss .sbss.*) }
+  .bss		: { *(.bss .bss.*) }
+  .bss.stack	: { *(.bss) }
+
+  __bss_stop = .; 
+  _end = . ;
+  . = ALIGN(PAGE_SIZE);
+  __kernel_image_end = .;
+
+  /* Stabs debugging sections.  */
+  .stab 0 : { *(.stab) }
+  .stabstr 0 : { *(.stabstr) }
+  .stab.excl 0 : { *(.stab.excl) }
+  .stab.exclstr 0 : { *(.stab.exclstr) }
+  .stab.index 0 : { *(.stab.index) }
+  .stab.indexstr 0 : { *(.stab.indexstr) }
+
+  .debug_line		0 : { *(.debug_line) }
+  .debug_info		0 : { *(.debug_info) }
+  .debug_abbrev		0 : { *(.debug_abbrev) }
+  .debug_aranges	0 : { *(.debug_aranges) }
+  .debug_frame		0 : { *(.debug_frame) }
+  .debug_pubnames	0 : { *(.debug_pubnames) }
+  .debug_str		0 : { *(.debug_str) }
+  .debug_ranges		0 : { *(.debug_ranges) }
+
+  .comment 0 : { *(.comment) }
+}
+
+__kernel_image_size_no_bss = __bss_start - __kernel_image_start;

^ permalink raw reply	[flat|nested] 87+ messages in thread

* [PATCH 11/20] FRV: Fujitsu FR-V CPU arch implementation part 9
  2004-11-08 14:34 [PATCH 1/20] FRV: Fujitsu FR-V CPU arch maintainer record dhowells
                   ` (7 preceding siblings ...)
  2004-11-08 14:34 ` [PATCH 9/20] FRV: Fujitsu FR-V CPU arch implementation part 7 dhowells
@ 2004-11-08 14:34 ` dhowells
  2004-11-08 14:34 ` [PATCH 10/20] FRV: Fujitsu FR-V CPU arch implementation part 8 dhowells
                   ` (7 subsequent siblings)
  16 siblings, 0 replies; 87+ messages in thread
From: dhowells @ 2004-11-08 14:34 UTC (permalink / raw)
  To: torvalds, akpm, davidm; +Cc: linux-kernel, uclinux-dev

The attached patches provides part 9 of an architecture implementation
for the Fujitsu FR-V CPU series, configurably as Linux or uClinux.

Signed-Off-By: dhowells@redhat.com
---
diffstat frv-arch_9-2610rc1mm3.diff
 Makefile      |    9 
 cache-page.c  |   66 ++++++
 dma-alloc.c   |  186 +++++++++++++++++
 elf-fdpic.c   |  123 +++++++++++
 extable.c     |   91 ++++++++
 fault.c       |  323 +++++++++++++++++++++++++++++
 highmem.c     |   33 +++
 init.c        |  244 ++++++++++++++++++++++
 kmap.c        |   56 +++++
 mmu-context.c |  210 +++++++++++++++++++
 pgalloc.c     |  159 ++++++++++++++
 tlb-flush.S   |  185 +++++++++++++++++
 tlb-miss.S    |  631 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 unaligned.c   |  218 ++++++++++++++++++++
 14 files changed, 2534 insertions(+)

diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/mm/cache-page.c linux-2.6.10-rc1-mm3-frv/arch/frv/mm/cache-page.c
--- /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/mm/cache-page.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/arch/frv/mm/cache-page.c	2004-11-05 14:13:03.000000000 +0000
@@ -0,0 +1,66 @@
+/* cache-page.c: whole-page cache wrangling functions for MMU linux
+ *
+ * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * 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.
+ */
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/highmem.h>
+#include <asm/pgalloc.h>
+
+/*****************************************************************************/
+/*
+ * DCF takes a virtual address and the page may not currently have one
+ * - temporarily hijack a kmap_atomic() slot and attach the page to it
+ */
+void flush_dcache_page(struct page *page)
+{
+	unsigned long dampr2;
+	void *vaddr;
+
+	dampr2 = __get_DAMPR(2);
+
+	vaddr = kmap_atomic(page, __KM_CACHE);
+
+	frv_dcache_writeback((unsigned long) vaddr, (unsigned long) vaddr + PAGE_SIZE);
+
+	kunmap_atomic(vaddr, __KM_CACHE);
+
+	if (dampr2) {
+		__set_DAMPR(2, dampr2);
+		__set_IAMPR(2, dampr2);
+	}
+
+} /* end flush_dcache_page() */
+
+/*****************************************************************************/
+/*
+ * ICI takes a virtual address and the page may not currently have one
+ * - so we temporarily attach the page to a bit of virtual space so that is can be flushed
+ */
+void flush_icache_user_range(struct vm_area_struct *vma, struct page *page,
+			     unsigned long start, unsigned long len)
+{
+	unsigned long dampr2;
+	void *vaddr;
+
+	dampr2 = __get_DAMPR(2);
+
+	vaddr = kmap_atomic(page, __KM_CACHE);
+
+	start = (start & ~PAGE_MASK) | (unsigned long) vaddr;
+	frv_cache_wback_inv(start, start + len);
+
+	kunmap_atomic(vaddr, __KM_CACHE);
+
+	if (dampr2) {
+		__set_DAMPR(2, dampr2);
+		__set_IAMPR(2, dampr2);
+	}
+
+} /* end flush_icache_user_range() */
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/mm/dma-alloc.c linux-2.6.10-rc1-mm3-frv/arch/frv/mm/dma-alloc.c
--- /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/mm/dma-alloc.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/arch/frv/mm/dma-alloc.c	2004-11-05 16:57:33.000000000 +0000
@@ -0,0 +1,186 @@
+/* dma-alloc.c: consistent DMA memory allocation
+ *
+ * Derived from arch/ppc/mm/cachemap.c
+ *
+ *  PowerPC version derived from arch/arm/mm/consistent.c
+ *    Copyright (C) 2001 Dan Malek (dmalek@jlc.net)
+ *
+ *  linux/arch/arm/mm/consistent.c
+ *
+ *  Copyright (C) 2000 Russell King
+ *
+ * Consistent memory allocators.  Used for DMA devices that want to
+ * share uncached memory with the processor core.  The function return
+ * is the virtual address and 'dma_handle' is the physical address.
+ * Mostly stolen from the ARM port, with some changes for PowerPC.
+ *						-- Dan
+ * Modified for 36-bit support.  -Matt
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/types.h>
+#include <linux/ptrace.h>
+#include <linux/mman.h>
+#include <linux/mm.h>
+#include <linux/swap.h>
+#include <linux/stddef.h>
+#include <linux/vmalloc.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+
+#include <asm/pgalloc.h>
+#include <asm/io.h>
+#include <asm/hardirq.h>
+#include <asm/mmu_context.h>
+#include <asm/pgtable.h>
+#include <asm/mmu.h>
+#include <asm/uaccess.h>
+#include <asm/smp.h>
+
+static int map_page(unsigned long va, unsigned long pa, pgprot_t prot)
+{
+	pgd_t *pge;
+	pmd_t *pme;
+	pte_t *pte;
+	int err = -ENOMEM;
+
+	spin_lock(&init_mm.page_table_lock);
+
+	/* Use upper 10 bits of VA to index the first level map */
+	pge = pml4_pgd_offset_k(pml4_offset_k(va), va);
+	pme = pmd_offset(pge, va);
+
+	/* Use middle 10 bits of VA to index the second-level map */
+	pte = pte_alloc_kernel(&init_mm, pme, va);
+	if (pte != 0) {
+		err = 0;
+		set_pte(pte, mk_pte_phys(pa & PAGE_MASK, prot));
+	}
+
+	spin_unlock(&init_mm.page_table_lock);
+	return err;
+}
+
+/*
+ * This function will allocate the requested contiguous pages and
+ * map them into the kernel's vmalloc() space.  This is done so we
+ * get unique mapping for these pages, outside of the kernel's 1:1
+ * virtual:physical mapping.  This is necessary so we can cover large
+ * portions of the kernel with single large page TLB entries, and
+ * still get unique uncached pages for consistent DMA.
+ */
+void *consistent_alloc(int gfp, size_t size, dma_addr_t *dma_handle)
+{
+	struct vm_struct *area;
+	unsigned long page, va, pa;
+	void *ret;
+	int order, err, i;
+
+	if (in_interrupt())
+		BUG();
+
+	/* only allocate page size areas */
+	size = PAGE_ALIGN(size);
+	order = get_order(size);
+
+	page = __get_free_pages(gfp, order);
+	if (!page) {
+		BUG();
+		return NULL;
+	}
+
+	/* allocate some common virtual space to map the new pages */
+	area = get_vm_area(size, VM_ALLOC);
+	if (area == 0) {
+		free_pages(page, order);
+		return NULL;
+	}
+	va = VMALLOC_VMADDR(area->addr);
+	ret = (void *) va;
+
+	/* this gives us the real physical address of the first page */
+	*dma_handle = pa = virt_to_bus((void *) page);
+
+	/* set refcount=1 on all pages in an order>0 allocation so that vfree() will actually free
+	 * all pages that were allocated.
+	 */
+	if (order > 0) {
+		struct page *rpage = virt_to_page(page);
+
+		for (i = 1; i < (1 << order); i++)
+			set_page_count(rpage + i, 1);
+	}
+
+	err = 0;
+	for (i = 0; i < size && err == 0; i += PAGE_SIZE)
+		err = map_page(va + i, pa + i, PAGE_KERNEL_NOCACHE);
+
+	if (err) {
+		vfree((void *) va);
+		return NULL;
+	}
+
+	/* we need to ensure that there are no cachelines in use, or worse dirty in this area
+	 * - can't do until after virtual address mappings are created
+	 */
+	frv_cache_invalidate(va, va + size);
+
+	return ret;
+}
+
+/*
+ * free page(s) as defined by the above mapping.
+ */
+void consistent_free(void *vaddr)
+{
+	if (in_interrupt())
+		BUG();
+	vfree(vaddr);
+}
+
+/*
+ * make an area consistent.
+ */
+void consistent_sync(void *vaddr, size_t size, int direction)
+{
+	unsigned long start = (unsigned long) vaddr;
+	unsigned long end   = start + size;
+
+	switch (direction) {
+	case PCI_DMA_NONE:
+		BUG();
+	case PCI_DMA_FROMDEVICE:	/* invalidate only */
+		frv_cache_invalidate(start, end);
+		break;
+	case PCI_DMA_TODEVICE:		/* writeback only */
+		frv_dcache_writeback(start, end);
+		break;
+	case PCI_DMA_BIDIRECTIONAL:	/* writeback and invalidate */
+		frv_dcache_writeback(start, end);
+		break;
+	}
+}
+
+/*
+ * consistent_sync_page make a page are consistent. identical
+ * to consistent_sync, but takes a struct page instead of a virtual address
+ */
+
+void consistent_sync_page(struct page *page, unsigned long offset,
+			  size_t size, int direction)
+{
+	void *start;
+
+	start = page_address(page) + offset;
+	consistent_sync(start, size, direction);
+}
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/mm/elf-fdpic.c linux-2.6.10-rc1-mm3-frv/arch/frv/mm/elf-fdpic.c
--- /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/mm/elf-fdpic.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/arch/frv/mm/elf-fdpic.c	2004-11-05 14:13:03.000000000 +0000
@@ -0,0 +1,123 @@
+/* elf-fdpic.c: ELF FDPIC memory layout management
+ *
+ * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * 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.
+ */
+
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/fs.h>
+#include <linux/elf-fdpic.h>
+
+/*****************************************************************************/
+/*
+ * lay out the userspace VM according to our grand design
+ */
+#ifdef CONFIG_MMU
+void elf_fdpic_arch_lay_out_mm(struct elf_fdpic_params *exec_params,
+			       struct elf_fdpic_params *interp_params,
+			       unsigned long *start_stack,
+			       unsigned long *start_brk)
+{
+	*start_stack = 0x02200000UL;
+
+	/* if the only executable is a shared object, assume that it is an interpreter rather than
+	 * a true executable, and map it such that "ld.so --list" comes out right
+	 */
+	if (!(interp_params->flags & ELF_FDPIC_FLAG_PRESENT) &&
+	    exec_params->hdr.e_type != ET_EXEC
+	    ) {
+		exec_params->load_addr = PAGE_SIZE;
+
+		*start_brk = 0x80000000UL;
+	}
+	else {
+		exec_params->load_addr = 0x02200000UL;
+
+		if ((exec_params->flags & ELF_FDPIC_FLAG_ARRANGEMENT) ==
+		    ELF_FDPIC_FLAG_INDEPENDENT
+		    ) {
+			exec_params->flags &= ~ELF_FDPIC_FLAG_ARRANGEMENT;
+			exec_params->flags |= ELF_FDPIC_FLAG_CONSTDISP;
+		}
+	}
+
+} /* end elf_fdpic_arch_lay_out_mm() */
+#endif
+
+/*****************************************************************************/
+/*
+ * place non-fixed mmaps firstly in the bottom part of memory, working up, and then in the top part
+ * of memory, working down
+ */
+unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, unsigned long len,
+				     unsigned long pgoff, unsigned long flags)
+{
+	struct vm_area_struct *vma;
+	unsigned long limit;
+
+	if (len > TASK_SIZE)
+		return -ENOMEM;
+
+	/* only honour a hint if we're not going to clobber something doing so */
+	if (addr) {
+		addr = PAGE_ALIGN(addr);
+		vma = find_vma(current->mm, addr);
+		if (TASK_SIZE - len >= addr &&
+		    (!vma || addr + len <= vma->vm_start))
+			goto success;
+	}
+
+	/* search between the bottom of user VM and the stack grow area */
+	addr = PAGE_SIZE;
+	limit = (current->mm->start_stack - 0x00200000);
+	if (addr + len <= limit) {
+		limit -= len;
+
+		if (addr <= limit) {
+			vma = find_vma(current->mm, PAGE_SIZE);
+			for (; vma; vma = vma->vm_next) {
+				if (addr > limit)
+					break;
+				if (addr + len <= vma->vm_start)
+					goto success;
+				addr = vma->vm_end;
+			}
+		}
+	}
+
+	/* search from just above the WorkRAM area to the top of memory */
+	addr = PAGE_ALIGN(0x80000000);
+	limit = TASK_SIZE - len;
+	if (addr <= limit) {
+		vma = find_vma(current->mm, addr);
+		for (; vma; vma = vma->vm_next) {
+			if (addr > limit)
+				break;
+			if (addr + len <= vma->vm_start)
+				goto success;
+			addr = vma->vm_end;
+		}
+
+		if (!vma && addr <= limit)
+			goto success;
+	}
+
+#if 0
+	printk("[area] l=%lx (ENOMEM) f='%s'\n",
+	       len, filp ? filp->f_dentry->d_name.name : "");
+#endif
+	return -ENOMEM;
+
+ success:
+#if 0
+	printk("[area] l=%lx ad=%lx f='%s'\n",
+	       len, addr, filp ? filp->f_dentry->d_name.name : "");
+#endif
+	return addr;
+} /* end arch_get_unmapped_area() */
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/mm/extable.c linux-2.6.10-rc1-mm3-frv/arch/frv/mm/extable.c
--- /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/mm/extable.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/arch/frv/mm/extable.c	2004-11-05 14:13:03.000000000 +0000
@@ -0,0 +1,91 @@
+/*
+ * linux/arch/frv/mm/extable.c
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include <asm/uaccess.h>
+
+extern const struct exception_table_entry __attribute__((aligned(8))) __start___ex_table[];
+extern const struct exception_table_entry __attribute__((aligned(8))) __stop___ex_table[];
+extern const void __memset_end, __memset_user_error_lr, __memset_user_error_handler;
+extern const void __memcpy_end, __memcpy_user_error_lr, __memcpy_user_error_handler;
+extern spinlock_t modlist_lock;
+
+/*****************************************************************************/
+/*
+ *
+ */
+static inline unsigned long search_one_table(const struct exception_table_entry *first,
+					     const struct exception_table_entry *last,
+					     unsigned long value)
+{
+        while (first <= last) {
+		const struct exception_table_entry __attribute__((aligned(8))) *mid;
+		long diff;
+
+		mid = (last - first) / 2 + first;
+		diff = mid->insn - value;
+                if (diff == 0)
+                        return mid->fixup;
+                else if (diff < 0)
+                        first = mid + 1;
+                else
+                        last = mid - 1;
+        }
+        return 0;
+} /* end search_one_table() */
+
+/*****************************************************************************/
+/*
+ * see if there's a fixup handler available to deal with a kernel fault
+ */
+unsigned long search_exception_table(unsigned long pc)
+{
+	unsigned long ret = 0;
+
+	/* determine if the fault lay during a memcpy_user or a memset_user */
+	if (__frame->lr == (unsigned long) &__memset_user_error_lr &&
+	    (unsigned long) &memset <= pc && pc < (unsigned long) &__memset_end
+	    ) {
+		/* the fault occurred in a protected memset
+		 * - we search for the return address (in LR) instead of the program counter
+		 * - it was probably during a clear_user()
+		 */
+		return (unsigned long) &__memset_user_error_handler;
+	}
+	else if (__frame->lr == (unsigned long) &__memcpy_user_error_lr &&
+		 (unsigned long) &memcpy <= pc && pc < (unsigned long) &__memcpy_end
+		 ) {
+		/* the fault occurred in a protected memset
+		 * - we search for the return address (in LR) instead of the program counter
+		 * - it was probably during a copy_to/from_user()
+		 */
+		return (unsigned long) &__memcpy_user_error_handler;
+	}
+
+#ifndef CONFIG_MODULES
+	/* there is only the kernel to search.  */
+	ret = search_one_table(__start___ex_table, __stop___ex_table - 1, pc);
+	return ret;
+
+#else
+	/* the kernel is the last "module" -- no need to treat it special */
+	unsigned long flags;
+	struct module *mp;
+
+	spin_lock_irqsave(&modlist_lock, flags);
+
+	for (mp = module_list; mp != NULL; mp = mp->next) {
+		if (mp->ex_table_start == NULL || !(mp->flags & (MOD_RUNNING | MOD_INITIALIZING)))
+			continue;
+		ret = search_one_table(mp->ex_table_start, mp->ex_table_end - 1, pc);
+		if (ret)
+			break;
+	}
+
+	spin_unlock_irqrestore(&modlist_lock, flags);
+	return ret;
+#endif
+} /* end search_exception_table() */
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/mm/fault.c linux-2.6.10-rc1-mm3-frv/arch/frv/mm/fault.c
--- /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/mm/fault.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/arch/frv/mm/fault.c	2004-11-05 15:43:56.000000000 +0000
@@ -0,0 +1,323 @@
+/*
+ *  linux/arch/frv/mm/fault.c
+ *
+ * Copyright (C) 2003 Red Hat, Inc. All Rights Reserved.
+ * - Written by David Howells (dhowells@redhat.com)
+ * - Derived from arch/m68knommu/mm/fault.c
+ *   - Copyright (C) 1998  D. Jeff Dionne <jeff@lineo.ca>,
+ *   - Copyright (C) 2000  Lineo, Inc.  (www.lineo.com)
+ *
+ *  Based on:
+ *
+ *  linux/arch/m68k/mm/fault.c
+ *
+ *  Copyright (C) 1995  Hamish Macdonald
+ */
+
+#include <linux/mman.h>
+#include <linux/mm.h>
+#include <linux/kernel.h>
+#include <linux/ptrace.h>
+#include <linux/hardirq.h>
+
+#include <asm/system.h>
+#include <asm/pgtable.h>
+#include <asm/uaccess.h>
+#include <asm/gdb-stub.h>
+
+/*****************************************************************************/
+/*
+ * This routine handles page faults.  It determines the problem, and
+ * then passes it off to one of the appropriate routines.
+ */
+asmlinkage void do_page_fault(int datammu, unsigned long esr0, unsigned long ear0)
+{
+	struct vm_area_struct *vma, *prev_vma;
+	struct mm_struct *mm;
+	unsigned long _pme, lrai, lrad, fixup;
+	siginfo_t info;
+	pml4_t *pml4e;
+	pgd_t *pge;
+	pte_t *pte;
+	int write;
+
+#if 0
+	const char *atxc[16] = {
+		[0x0] = "mmu-miss", [0x8] = "multi-dat", [0x9] = "multi-sat",
+		[0xa] = "tlb-miss", [0xc] = "privilege", [0xd] = "write-prot",
+	};
+
+	printk("do_page_fault(%d,%lx [%s],%lx)\n",
+	       datammu, esr0, atxc[esr0 >> 20 & 0xf], ear0);
+#endif
+
+	mm = current->mm;
+
+	/*
+	 * We fault-in kernel-space virtual memory on-demand. The
+	 * 'reference' page table is init_mm.pgd.
+	 *
+	 * NOTE! We MUST NOT take any locks for this case. We may
+	 * be in an interrupt or a critical region, and should
+	 * only copy the information from the master page table,
+	 * nothing more.
+	 *
+	 * This verifies that the fault happens in kernel space
+	 * and that the fault was a page not present (invalid) error
+	 */
+	if (!user_mode(__frame) && (esr0 & ESR0_ATXC) == ESR0_ATXC_AMRTLB_MISS) {
+		if (ear0 >= VMALLOC_START && ear0 < VMALLOC_END)
+			goto kernel_pte_fault;
+		if (ear0 >= PKMAP_BASE && ear0 < PKMAP_END)
+			goto kernel_pte_fault;
+	}
+
+	info.si_code = SEGV_MAPERR;
+
+	/*
+	 * If we're in an interrupt or have no user
+	 * context, we must not take the fault..
+	 */
+	if (in_interrupt() || !mm)
+		goto no_context;
+
+	down_read(&mm->mmap_sem);
+
+	vma = find_vma(mm, ear0);
+	if (!vma)
+		goto bad_area;
+	if (vma->vm_start <= ear0)
+		goto good_area;
+	if (!(vma->vm_flags & VM_GROWSDOWN))
+		goto bad_area;
+
+	if (user_mode(__frame)) {
+		/*
+		 * accessing the stack below %esp is always a bug.
+		 * The "+ 32" is there due to some instructions (like
+		 * pusha) doing post-decrement on the stack and that
+		 * doesn't show up until later..
+		 */
+		if ((ear0 & PAGE_MASK) + 2 * PAGE_SIZE < __frame->sp) {
+#if 0
+			printk("[%d] ### Access below stack @%lx (sp=%lx)\n",
+			       current->pid, ear0, __frame->sp);
+			show_registers(__frame);
+			printk("[%d] ### Code: [%08lx] %02x %02x %02x %02x %02x %02x %02x %02x\n",
+			       current->pid,
+			       __frame->pc,
+			       ((u8*)__frame->pc)[0],
+			       ((u8*)__frame->pc)[1],
+			       ((u8*)__frame->pc)[2],
+			       ((u8*)__frame->pc)[3],
+			       ((u8*)__frame->pc)[4],
+			       ((u8*)__frame->pc)[5],
+			       ((u8*)__frame->pc)[6],
+			       ((u8*)__frame->pc)[7]
+			       );
+#endif
+			goto bad_area;
+		}
+	}
+
+	/* find_vma_prev is just a bit slower, because it cannot use
+	 * the mmap_cache, so we run it only in the growsdown slow
+	 * path and we leave find_vma in the fast path.
+	 */
+	find_vma_prev(current->mm, ear0, &prev_vma);
+	if (expand_stack(vma, ear0, prev_vma))
+		goto bad_area;
+
+/*
+ * Ok, we have a good vm_area for this memory access, so
+ * we can handle it..
+ */
+ good_area:
+	info.si_code = SEGV_ACCERR;
+	write = 0;
+	switch (esr0 & ESR0_ATXC) {
+	default:
+		/* handle write to write protected page */
+	case ESR0_ATXC_WP_EXCEP:
+#ifdef TEST_VERIFY_AREA
+		if (!(user_mode(__frame)))
+			printk("WP fault at %08lx\n", __frame->pc);
+#endif
+		if (!(vma->vm_flags & VM_WRITE))
+			goto bad_area;
+		write = 1;
+		break;
+
+		 /* handle read from protected page */
+	case ESR0_ATXC_PRIV_EXCEP:
+		goto bad_area;
+
+		 /* handle read, write or exec on absent page
+		  * - can't support write without permitting read
+		  * - don't support execute without permitting read and vice-versa
+		  */
+	case ESR0_ATXC_AMRTLB_MISS:
+		if (!(vma->vm_flags & (VM_READ | VM_WRITE | VM_EXEC)))
+			goto bad_area;
+		break;
+	}
+
+	/*
+	 * If for any reason at all we couldn't handle the fault,
+	 * make sure we exit gracefully rather than endlessly redo
+	 * the fault.
+	 */
+	switch (handle_mm_fault(mm, vma, ear0, write)) {
+	case 1:
+		current->min_flt++;
+		break;
+	case 2:
+		current->maj_flt++;
+		break;
+	case 0:
+		goto do_sigbus;
+	default:
+		goto out_of_memory;
+	}
+
+	up_read(&mm->mmap_sem);
+	return;
+
+/*
+ * Something tried to access memory that isn't in our memory map..
+ * Fix it, but check if it's kernel or user first..
+ */
+ bad_area:
+	up_read(&mm->mmap_sem);
+
+	/* User mode accesses just cause a SIGSEGV */
+	if (user_mode(__frame)) {
+		info.si_signo = SIGSEGV;
+		info.si_errno = 0;
+		/* info.si_code has been set above */
+		info.si_addr = (void *) ear0;
+		force_sig_info(SIGSEGV, &info, current);
+		return;
+	}
+
+ no_context:
+	/* are we prepared to handle this kernel fault? */
+	if ((fixup = search_exception_table(__frame->pc)) != 0) {
+		__frame->pc = fixup;
+		return;
+	}
+
+/*
+ * Oops. The kernel tried to access some bad page. We'll have to
+ * terminate things with extreme prejudice.
+ */
+
+	bust_spinlocks(1);
+
+	if (ear0 < PAGE_SIZE)
+		printk(KERN_ALERT "Unable to handle kernel NULL pointer dereference");
+	else
+		printk(KERN_ALERT "Unable to handle kernel paging request");
+	printk(" at virtual addr %08lx\n", ear0);
+	printk("  PC  : %08lx\n", __frame->pc);
+	printk("  EXC : esr0=%08lx ear0=%08lx\n", esr0, ear0);
+
+	asm("lrai %1,%0,#1,#0,#0" : "=&r"(lrai) : "r"(ear0));
+	asm("lrad %1,%0,#1,#0,#0" : "=&r"(lrad) : "r"(ear0));
+
+	printk(KERN_ALERT "  LRAI: %08lx\n", lrai);
+	printk(KERN_ALERT "  LRAD: %08lx\n", lrad);
+
+	__break_hijack_kernel_event();
+
+	pml4e = pml4_offset(current->mm, ear0);
+	pge = pml4_pgd_offset(pml4e, ear0);
+	_pme = pge->pge[0].ste[0];
+
+	printk(KERN_ALERT "  PGE : %8p { PME %08lx }\n", pge, _pme);
+
+	if (_pme & xAMPRx_V) {
+		unsigned long dampr, damlr, val;
+
+		asm volatile("movsg dampr2,%0 ! movgs %2,dampr2 ! movsg damlr2,%1"
+			     : "=&r"(dampr), "=r"(damlr)
+			     : "r" (_pme | xAMPRx_L|xAMPRx_SS_16Kb|xAMPRx_S|xAMPRx_C|xAMPRx_V)
+			     );
+
+		pte = (pte_t *) damlr + __pte_index(ear0);
+		val = pte_val(*pte);
+
+		asm volatile("movgs %0,dampr2" :: "r" (dampr));
+
+		printk(KERN_ALERT "  PTE : %8p { %08lx }\n", pte, val);
+	}
+
+	die_if_kernel("Oops\n");
+	do_exit(SIGKILL);
+
+/*
+ * We ran out of memory, or some other thing happened to us that made
+ * us unable to handle the page fault gracefully.
+ */
+ out_of_memory:
+	up_read(&mm->mmap_sem);
+	printk("VM: killing process %s\n", current->comm);
+	if (user_mode(__frame))
+		do_exit(SIGKILL);
+	goto no_context;
+
+ do_sigbus:
+	up_read(&mm->mmap_sem);
+
+	/*
+	 * Send a sigbus, regardless of whether we were in kernel
+	 * or user mode.
+	 */
+	info.si_signo = SIGBUS;
+	info.si_errno = 0;
+	info.si_code = BUS_ADRERR;
+	info.si_addr = (void *) ear0;
+	force_sig_info(SIGBUS, &info, current);
+
+	/* Kernel mode? Handle exceptions or die */
+	if (!user_mode(__frame))
+		goto no_context;
+	return;
+
+/*
+ * The fault was caused by a kernel PTE (such as installed by vmalloc or kmap)
+ */
+ kernel_pte_fault:
+	{
+		/*
+		 * Synchronize this task's top level page-table
+		 * with the 'reference' page table.
+		 *
+		 * Do _not_ use "tsk" here. We might be inside
+		 * an interrupt in the middle of a task switch..
+		 */
+		int index = pgd_index(ear0);
+		pgd_t *pgd, *pgd_k;
+		pmd_t *pmd, *pmd_k;
+		pte_t *pte_k;
+
+		pgd = (pgd_t *) __get_TTBR();
+		pgd = (pgd_t *)__va(pgd) + index;
+		pgd_k = ((pgd_t *)(init_mm.pml4)) + index;
+
+		if (!pgd_present(*pgd_k))
+			goto no_context;
+		set_pgd(pgd, *pgd_k);
+
+		pmd = pmd_offset(pgd, ear0);
+		pmd_k = pmd_offset(pgd_k, ear0);
+		if (!pmd_present(*pmd_k))
+			goto no_context;
+		set_pmd(pmd, *pmd_k);
+
+		pte_k = pte_offset(pmd_k, ear0);
+		if (!pte_present(*pte_k))
+			goto no_context;
+		return;
+	}
+} /* end do_page_fault() */
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/mm/highmem.c linux-2.6.10-rc1-mm3-frv/arch/frv/mm/highmem.c
--- /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/mm/highmem.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/arch/frv/mm/highmem.c	2004-11-05 14:13:03.000000000 +0000
@@ -0,0 +1,33 @@
+/* highmem.c: arch-specific highmem stuff
+ *
+ * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * 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.
+ */
+#include <linux/highmem.h>
+
+void *kmap(struct page *page)
+{
+	might_sleep();
+	if (page < highmem_start_page)
+		return page_address(page);
+	return kmap_high(page);
+}
+
+void kunmap(struct page *page)
+{
+	if (in_interrupt())
+		BUG();
+	if (page < highmem_start_page)
+		return;
+	kunmap_high(page);
+}
+
+struct page *kmap_atomic_to_page(void *ptr)
+{
+	return virt_to_page(ptr);
+}
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/mm/init.c linux-2.6.10-rc1-mm3-frv/arch/frv/mm/init.c
--- /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/mm/init.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/arch/frv/mm/init.c	2004-11-05 14:52:13.000000000 +0000
@@ -0,0 +1,244 @@
+/* init.c: memory initialisation for FRV
+ *
+ * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * 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.
+ *
+ * Derived from:
+ *  - linux/arch/m68knommu/mm/init.c
+ *    - Copyright (C) 1998  D. Jeff Dionne <jeff@lineo.ca>, Kenneth Albanowski <kjahds@kjahds.com>,
+ *    - Copyright (C) 2000  Lineo, Inc.  (www.lineo.com) 
+ *  - linux/arch/m68k/mm/init.c
+ *    - Copyright (C) 1995  Hamish Macdonald
+ */
+
+#include <linux/config.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/pagemap.h>
+#include <linux/swap.h>
+#include <linux/mm.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/types.h>
+#include <linux/bootmem.h>
+#include <linux/highmem.h>
+
+#include <asm/setup.h>
+#include <asm/segment.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/system.h>
+#include <asm/mmu_context.h>
+#include <asm/virtconvert.h>
+#include <asm/sections.h>
+#include <asm/tlb.h>
+
+#undef DEBUG
+
+DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
+
+/*
+ * BAD_PAGE is the page that is used for page faults when linux
+ * is out-of-memory. Older versions of linux just did a
+ * do_exit(), but using this instead means there is less risk
+ * for a process dying in kernel mode, possibly leaving a inode
+ * unused etc..
+ *
+ * BAD_PAGETABLE is the accompanying page-table: it is initialized
+ * to point to BAD_PAGE entries.
+ *
+ * ZERO_PAGE is a special page that is used for zero-initialized
+ * data and COW.
+ */
+static unsigned long empty_bad_page_table;
+static unsigned long empty_bad_page;
+unsigned long empty_zero_page;
+
+/*****************************************************************************/
+/*
+ * 
+ */
+void show_mem(void)
+{
+	unsigned long i;
+	int free = 0, total = 0, reserved = 0, shared = 0;
+
+	printk("\nMem-info:\n");
+	show_free_areas();
+	i = max_mapnr;
+	while (i-- > 0) {
+		struct page *page = &mem_map[i];
+
+		total++;
+		if (PageReserved(page))
+			reserved++;
+		else if (!page_count(page))
+			free++;
+		else
+			shared += page_count(page) - 1;
+	}
+
+	printk("%d pages of RAM\n",total);
+	printk("%d free pages\n",free);
+	printk("%d reserved pages\n",reserved);
+	printk("%d pages shared\n",shared);
+
+} /* end show_mem() */
+
+/*****************************************************************************/
+/*
+ * paging_init() continues the virtual memory environment setup which
+ * was begun by the code in arch/head.S.
+ * The parameters are pointers to where to stick the starting and ending
+ * addresses  of available kernel virtual memory.
+ */
+void __init paging_init(void)
+{
+	unsigned long zones_size[MAX_NR_ZONES] = {0, 0, 0};
+
+	/* allocate some pages for kernel housekeeping tasks */
+	empty_bad_page_table	= (unsigned long) alloc_bootmem_pages(PAGE_SIZE);
+	empty_bad_page		= (unsigned long) alloc_bootmem_pages(PAGE_SIZE);
+	empty_zero_page		= (unsigned long) alloc_bootmem_pages(PAGE_SIZE);
+
+	memset((void *) empty_zero_page, 0, PAGE_SIZE);
+
+#if CONFIG_HIGHMEM
+	if (num_physpages - num_mappedpages) {
+		pgd_t *pge;
+		pmd_t *pme;
+
+		pkmap_page_table = alloc_bootmem_pages(PAGE_SIZE);
+
+		memset(pkmap_page_table, 0, PAGE_SIZE);
+
+		pge = swapper_pg_dir + pgd_index_k(PKMAP_BASE);
+		pme = pmd_offset(pge, PKMAP_BASE);
+		__set_pmd(pme, virt_to_phys(pkmap_page_table) | _PAGE_TABLE);
+	}
+#endif
+
+	/* distribute the allocatable pages across the various zones and pass them to the allocator
+	 */
+	zones_size[ZONE_DMA]     = 0 >> PAGE_SHIFT;
+	zones_size[ZONE_NORMAL]  = max_low_pfn - min_low_pfn;
+#ifdef CONFIG_HIGHMEM
+	zones_size[ZONE_HIGHMEM] = num_physpages - num_mappedpages;
+#endif
+
+	free_area_init(zones_size);
+
+#ifdef CONFIG_MMU
+	/* high memory (if present) starts after the last mapped page
+	 * - this is used by kmap()
+	 */
+	highmem_start_page = mem_map + num_mappedpages;
+
+	/* initialise init's MMU context */
+	init_new_context(&init_task, &init_mm);
+#endif
+
+} /* end paging_init() */
+
+/*****************************************************************************/
+/*
+ * 
+ */
+void __init mem_init(void)
+{
+	unsigned long npages = (memory_end - memory_start) >> PAGE_SHIFT;
+	unsigned long tmp;
+#ifdef CONFIG_MMU
+	unsigned long loop, pfn;
+	int datapages = 0;
+#endif
+	int codek = 0, datak = 0;
+
+	/* this will put all memory onto the freelists */
+	totalram_pages = free_all_bootmem();
+
+#ifdef CONFIG_MMU
+	for (loop = 0 ; loop < npages ; loop++)
+		if (PageReserved(&mem_map[loop]))
+			datapages++;
+
+#ifdef CONFIG_HIGHMEM
+	for (pfn = num_physpages - 1; pfn >= num_mappedpages; pfn--) {
+		struct page *page = &mem_map[pfn];
+
+		ClearPageReserved(page);
+		set_bit(PG_highmem, &page->flags);
+		set_page_count(page, 1);
+		__free_page(page);
+		totalram_pages++;
+	}
+#endif
+	
+	codek = ((unsigned long) &_etext - (unsigned long) &_stext) >> 10;
+	datak = datapages << (PAGE_SHIFT - 10);
+
+#else
+	codek = (_etext - _stext) >> 10;
+	datak = 0; //(_ebss - _sdata) >> 10;
+#endif
+
+	tmp = nr_free_pages() << PAGE_SHIFT;
+	printk("Memory available: %luKiB/%luKiB RAM, %luKiB/%luKiB ROM (%dKiB kernel code, %dKiB data)\n",
+	       tmp >> 10,
+	       npages << (PAGE_SHIFT - 10),
+	       (rom_length > 0) ? ((rom_length >> 10) - codek) : 0,
+	       rom_length >> 10,
+	       codek,
+	       datak
+	       );
+
+} /* end mem_init() */
+
+/*****************************************************************************/
+/*
+ * free the memory that was only required for initialisation
+ */
+void __init free_initmem(void)
+{
+#if defined(CONFIG_RAMKERNEL) && !defined(CONFIG_PROTECT_KERNEL)
+	unsigned long start, end, addr;
+
+	start = PAGE_ALIGN((unsigned long) &__init_begin);	/* round up */
+	end   = ((unsigned long) &__init_end) & PAGE_MASK;	/* round down */
+
+	/* next to check that the page we free is not a partial page */
+	for (addr = start; addr < end; addr += PAGE_SIZE) {
+		ClearPageReserved(virt_to_page(addr));
+		set_page_count(virt_to_page(addr), 1);
+		free_page(addr);
+		totalram_pages++;
+	}
+
+	printk("Freeing unused kernel memory: %ldKiB freed (0x%lx - 0x%lx)\n",
+	       (end - start) >> 10, start, end);
+#endif
+} /* end free_initmem() */
+
+/*****************************************************************************/
+/*
+ * free the initial ramdisk memory
+ */
+#ifdef CONFIG_BLK_DEV_INITRD
+void __init free_initrd_mem(unsigned long start, unsigned long end)
+{
+	int pages = 0;
+	for (; start < end; start += PAGE_SIZE) {
+		ClearPageReserved(virt_to_page(start));
+		set_page_count(virt_to_page(start), 1);
+		free_page(start);
+		totalram_pages++;
+		pages++;
+	}
+	printk("Freeing initrd memory: %dKiB freed\n", (pages * PAGE_SIZE) >> 10);
+} /* end free_initrd_mem() */
+#endif
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/mm/kmap.c linux-2.6.10-rc1-mm3-frv/arch/frv/mm/kmap.c
--- /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/mm/kmap.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/arch/frv/mm/kmap.c	2004-11-05 14:13:03.385539521 +0000
@@ -0,0 +1,56 @@
+/*
+ *  linux/arch/m68knommu/mm/kmap.c
+ *
+ *  Copyright (C) 2000 Lineo, <davidm@lineo.com>
+ */
+
+#include <linux/config.h>
+#include <linux/mm.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/types.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
+
+/*****************************************************************************/
+/*
+ * Map some physical address range into the kernel address space.
+ */
+
+void *__ioremap(unsigned long physaddr, unsigned long size, int cacheflag)
+{
+	return (void *)physaddr;
+}
+
+/*
+ * Unmap a ioremap()ed region again
+ */
+void iounmap(void *addr)
+{
+}
+
+/*
+ * __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)
+{
+}
+
+/*
+ * 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)
+{
+}
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/mm/Makefile linux-2.6.10-rc1-mm3-frv/arch/frv/mm/Makefile
--- /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/mm/Makefile	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/arch/frv/mm/Makefile	2004-11-05 14:13:03.388539268 +0000
@@ -0,0 +1,9 @@
+#
+# Makefile for the arch-specific parts of the memory manager.
+#
+
+obj-y := init.o kmap.o
+
+obj-$(CONFIG_MMU) += \
+	pgalloc.o highmem.o fault.o extable.o cache-page.o tlb-flush.o tlb-miss.o \
+	mmu-context.o dma-alloc.o unaligned.o elf-fdpic.o
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/mm/mmu-context.c linux-2.6.10-rc1-mm3-frv/arch/frv/mm/mmu-context.c
--- /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/mm/mmu-context.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/arch/frv/mm/mmu-context.c	2004-11-05 15:59:15.000000000 +0000
@@ -0,0 +1,210 @@
+/* mmu-context.c: MMU context allocation and management
+ *
+ * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * 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.
+ */
+
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <asm/tlbflush.h>
+
+#define NR_CXN	4096
+
+static unsigned long cxn_bitmap[NR_CXN / (sizeof(unsigned long) * 8)];
+static LIST_HEAD(cxn_owners_lru);
+static spinlock_t cxn_owners_lock = SPIN_LOCK_UNLOCKED;
+
+int __nongpreldata cxn_pinned = -1;
+
+
+/*****************************************************************************/
+/*
+ * initialise a new context
+ */
+int init_new_context(struct task_struct *tsk, struct mm_struct *mm)
+{
+	memset(&mm->context, 0, sizeof(mm->context));
+	INIT_LIST_HEAD(&mm->context.id_link);
+	mm->context.itlb_cached_pge = 0xffffffffUL;
+	mm->context.dtlb_cached_pge = 0xffffffffUL;
+
+	return 0;
+} /* end init_new_context() */
+
+/*****************************************************************************/
+/*
+ * make sure a kernel MMU context has a CPU context number
+ * - call with cxn_owners_lock held
+ */
+static unsigned get_cxn(mm_context_t *ctx)
+{
+	struct list_head *_p;
+	mm_context_t *p;
+	unsigned cxn;
+
+	if (!list_empty(&ctx->id_link)) {
+		list_move_tail(&ctx->id_link, &cxn_owners_lru);
+	}
+	else {
+		/* find the first unallocated context number
+		 * - 0 is reserved for the kernel
+		 */
+		cxn = find_next_zero_bit(&cxn_bitmap, NR_CXN, 1);
+		if (cxn < NR_CXN) {
+			set_bit(cxn, &cxn_bitmap);
+		}
+		else {
+			/* none remaining - need to steal someone else's cxn */
+			p = NULL;
+			list_for_each(_p, &cxn_owners_lru) {
+				p = list_entry(_p, mm_context_t, id_link);
+				if (!p->id_busy && p->id != cxn_pinned)
+					break;
+			}
+
+			BUG_ON(_p == &cxn_owners_lru);
+
+			cxn = p->id;
+			p->id = 0;
+			list_del_init(&p->id_link);
+			__flush_tlb_mm(cxn);
+		}
+
+		ctx->id = cxn;
+		list_add_tail(&ctx->id_link, &cxn_owners_lru);
+	}
+
+	return ctx->id;
+} /* end get_cxn() */
+
+/*****************************************************************************/
+/*
+ * restore the current TLB miss handler mapped page tables into the MMU context and set up a
+ * mapping for the page directory
+ */
+void change_mm_context(mm_context_t *old, mm_context_t *ctx, pml4_t *pml4)
+{
+	unsigned long _pgd;
+	pgd_t *pgd;
+
+	pgd = pml4_pgd_offset(pml4, 0);
+	_pgd = virt_to_phys(pgd);
+
+	/* save the state of the outgoing MMU context */
+	old->id_busy = 0;
+
+	asm volatile("movsg scr0,%0"   : "=r"(old->itlb_cached_pge));
+	asm volatile("movsg dampr4,%0" : "=r"(old->itlb_ptd_mapping));
+	asm volatile("movsg scr1,%0"   : "=r"(old->dtlb_cached_pge));
+	asm volatile("movsg dampr5,%0" : "=r"(old->dtlb_ptd_mapping));
+
+	/* select an MMU context number */
+	spin_lock(&cxn_owners_lock);
+	get_cxn(ctx);
+	ctx->id_busy = 1;
+	spin_unlock(&cxn_owners_lock);
+
+	asm volatile("movgs %0,cxnr"   : : "r"(ctx->id));
+
+	/* restore the state of the incoming MMU context */
+	asm volatile("movgs %0,scr0"   : : "r"(ctx->itlb_cached_pge));
+	asm volatile("movgs %0,dampr4" : : "r"(ctx->itlb_ptd_mapping));
+	asm volatile("movgs %0,scr1"   : : "r"(ctx->dtlb_cached_pge));
+	asm volatile("movgs %0,dampr5" : : "r"(ctx->dtlb_ptd_mapping));
+
+	/* map the PGD into uncached virtual memory */
+	asm volatile("movgs %0,ttbr"   : : "r"(_pgd));
+	asm volatile("movgs %0,dampr3"
+		     :: "r"(_pgd | xAMPRx_L | xAMPRx_M | xAMPRx_SS_16Kb |
+			    xAMPRx_S | xAMPRx_C | xAMPRx_V));
+
+} /* end change_mm_context() */
+
+/*****************************************************************************/
+/*
+ * finished with an MMU context number
+ */
+void destroy_context(struct mm_struct *mm)
+{
+	mm_context_t *ctx = &mm->context;
+
+	spin_lock(&cxn_owners_lock);
+
+	if (!list_empty(&ctx->id_link)) {
+		if (ctx->id == cxn_pinned)
+			cxn_pinned = -1;
+
+		list_del_init(&ctx->id_link);
+		clear_bit(ctx->id, &cxn_bitmap);
+		__flush_tlb_mm(ctx->id);
+		ctx->id = 0;
+	}
+
+	spin_unlock(&cxn_owners_lock);
+} /* end destroy_context() */
+
+/*****************************************************************************/
+/*
+ * display the MMU context currently a process is currently using
+ */
+#ifdef CONFIG_PROC_FS
+char *proc_pid_status_frv_cxnr(struct mm_struct *mm, char *buffer)
+{
+	spin_lock(&cxn_owners_lock);
+	buffer += sprintf(buffer, "CXNR: %u\n", mm->context.id);
+	spin_unlock(&cxn_owners_lock);
+
+	return buffer;
+} /* end proc_pid_status_frv_cxnr() */
+#endif
+
+/*****************************************************************************/
+/*
+ * (un)pin a process's mm_struct's MMU context ID
+ */
+int cxn_pin_by_pid(pid_t pid)
+{
+	struct task_struct *tsk;
+	struct mm_struct *mm = NULL;
+	int ret;
+
+	/* unpin if pid is zero */
+	if (pid == 0) {
+		cxn_pinned = -1;
+		return 0;
+	}
+
+	ret = -ESRCH;
+
+	/* get a handle on the mm_struct */
+	read_lock(&tasklist_lock);
+	tsk = find_task_by_pid(pid);
+	if (tsk) {
+		ret = -EINVAL;
+
+		task_lock(tsk);
+		if (tsk->mm) {
+			mm = tsk->mm;
+			atomic_inc(&mm->mm_users);
+			ret = 0;
+		}
+		task_unlock(tsk);
+	}
+	read_unlock(&tasklist_lock);
+
+	if (ret < 0)
+		return ret;
+
+	/* make sure it has a CXN and pin it */
+	spin_lock(&cxn_owners_lock);
+	cxn_pinned = get_cxn(&mm->context);
+	spin_unlock(&cxn_owners_lock);
+
+	mmput(mm);
+	return 0;
+} /* end cxn_pin_by_pid() */
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/mm/pgalloc.c linux-2.6.10-rc1-mm3-frv/arch/frv/mm/pgalloc.c
--- /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/mm/pgalloc.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/arch/frv/mm/pgalloc.c	2004-11-05 15:28:55.000000000 +0000
@@ -0,0 +1,159 @@
+/* pgalloc.c: page directory & page table allocation
+ *
+ * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * 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.
+ */
+
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/mm.h>
+#include <linux/highmem.h>
+#include <asm/pgalloc.h>
+#include <asm/page.h>
+#include <asm/cacheflush.h>
+
+pgd_t swapper_pg_dir[PTRS_PER_PGD] __attribute__((aligned(PAGE_SIZE)));
+kmem_cache_t *pgd_cache;
+
+pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address)
+{
+	pte_t *pte = (pte_t *)__get_free_page(GFP_KERNEL|__GFP_REPEAT);
+	if (pte)
+		clear_page(pte);
+	return pte;
+}
+
+struct page *pte_alloc_one(struct mm_struct *mm, unsigned long address)
+{
+	struct page *page;
+
+#ifdef CONFIG_HIGHPTE
+	page = alloc_pages(GFP_KERNEL|__GFP_HIGHMEM|__GFP_REPEAT, 0);
+#else
+	page = alloc_pages(GFP_KERNEL|__GFP_REPEAT, 0);
+#endif
+	if (page)
+		clear_highpage(page);
+	flush_dcache_page(page);
+	return page;
+}
+
+void __set_pmd(pmd_t *pmdptr, unsigned long pmd)
+{
+	unsigned long *__ste_p = pmdptr->ste;
+	int loop;
+
+	if (!pmd) {
+		memset(__ste_p, 0, PME_SIZE);
+	}
+	else {
+		BUG_ON(pmd & xAMPRx_SS);
+
+		for (loop = PME_SIZE; loop > 0; loop -= 4) {
+			*__ste_p++ = pmd;
+			pmd += __frv_PT_SIZE;
+		}
+	}
+
+	frv_dcache_writeback((unsigned long) pmdptr, (unsigned long) (pmdptr + 1));
+}
+
+/*
+ * List of all pgd's needed for non-PAE so it can invalidate entries
+ * in both cached and uncached pgd's; not needed for PAE since the
+ * kernel pmd is shared. If PAE were not to share the pmd a similar
+ * tactic would be needed. This is essentially codepath-based locking
+ * against pageattr.c; it is the unique case in which a valid change
+ * of kernel pagetables can't be lazily synchronized by vmalloc faults.
+ * vmalloc faults work because attached pagetables are never freed.
+ * If the locking proves to be non-performant, a ticketing scheme with
+ * checks at dup_mmap(), exec(), and other mmlist addition points
+ * could be used. The locking scheme was chosen on the basis of
+ * manfred's recommendations and having no core impact whatsoever.
+ * -- wli
+ */
+spinlock_t pgd_lock = SPIN_LOCK_UNLOCKED;
+struct page *pgd_list;
+
+static inline void pgd_list_add(pgd_t *pgd)
+{
+	struct page *page = virt_to_page(pgd);
+	page->index = (unsigned long) pgd_list;
+	if (pgd_list)
+		pgd_list->private = (unsigned long) &page->index;
+	pgd_list = page;
+	page->private = (unsigned long) &pgd_list;
+}
+
+static inline void pgd_list_del(pgd_t *pgd)
+{
+	struct page *next, **pprev, *page = virt_to_page(pgd);
+	next = (struct page *) page->index;
+	pprev = (struct page **) page->private;
+	*pprev = next;
+	if (next)
+		next->private = (unsigned long) pprev;
+}
+
+void pgd_ctor(void *pgd, kmem_cache_t *cache, unsigned long unused)
+{
+	unsigned long flags;
+
+	if (PTRS_PER_PMD == 1)
+		spin_lock_irqsave(&pgd_lock, flags);
+
+	memcpy((pgd_t *) pgd + USER_PGDS_IN_LAST_PML4,
+	       swapper_pg_dir + USER_PGDS_IN_LAST_PML4,
+	       (PTRS_PER_PGD - USER_PGDS_IN_LAST_PML4) * sizeof(pgd_t));
+
+	if (PTRS_PER_PMD > 1)
+		return;
+
+	pgd_list_add(pgd);
+	spin_unlock_irqrestore(&pgd_lock, flags);
+	memset(pgd, 0, USER_PGDS_IN_LAST_PML4 * sizeof(pgd_t));
+}
+
+/* never called when PTRS_PER_PMD > 1 */
+void pgd_dtor(void *pgd, kmem_cache_t *cache, unsigned long unused)
+{
+	unsigned long flags; /* can be called from interrupt context */
+
+	spin_lock_irqsave(&pgd_lock, flags);
+	pgd_list_del(pgd);
+	spin_unlock_irqrestore(&pgd_lock, flags);
+}
+
+pgd_t *__pgd_alloc(struct mm_struct *mm, pml4_t *pml4, unsigned long address)
+{
+	pgd_t *pgd;
+
+	pgd = kmem_cache_alloc(pgd_cache, GFP_KERNEL);
+	if (!pgd)
+		return pgd;
+
+	return pgd;
+}
+
+void pgd_free(pgd_t *pgd)
+{
+	/* in the non-PAE case, clear_page_tables() clears user pgd entries */
+	kmem_cache_free(pgd_cache, pgd);
+}
+
+void __init pgtable_cache_init(void)
+{
+	pgd_cache = kmem_cache_create("pgd",
+				      PTRS_PER_PGD * sizeof(pgd_t),
+				      PTRS_PER_PGD * sizeof(pgd_t),
+				      0,
+				      pgd_ctor,
+				      pgd_dtor);
+	if (!pgd_cache)
+		panic("pgtable_cache_init(): Cannot create pgd cache");
+}
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/mm/tlb-flush.S linux-2.6.10-rc1-mm3-frv/arch/frv/mm/tlb-flush.S
--- /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/mm/tlb-flush.S	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/arch/frv/mm/tlb-flush.S	2004-11-05 14:13:03.000000000 +0000
@@ -0,0 +1,185 @@
+/* tlb-flush.S: TLB flushing routines
+ *
+ * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * 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.
+ */
+
+#include <linux/sys.h>
+#include <linux/config.h>
+#include <linux/linkage.h>
+#include <asm/page.h>
+#include <asm/ptrace.h>
+#include <asm/spr-regs.h>
+
+.macro DEBUG ch
+#	sethi.p		%hi(0xfeff9c00),gr4
+#	setlo		%lo(0xfeff9c00),gr4
+#	setlos		#\ch,gr5
+#	stbi		gr5,@(gr4,#0)
+#	membar
+.endm
+
+	.section	.rodata
+
+	# sizes corresponding to TPXR.LMAX
+	.balign		1
+__tlb_lmax_sizes:
+	.byte		0, 64, 0, 0
+	.byte		0, 0, 0, 0
+	.byte		0, 0, 0, 0
+	.byte		0, 0, 0, 0
+
+	.section	.text
+	.balign		4
+
+###############################################################################
+#
+# flush everything
+# - void __flush_tlb_all(void)
+#
+###############################################################################
+	.globl		__flush_tlb_all
+	.type		__flush_tlb_all,@function
+__flush_tlb_all:
+	DEBUG		'A'
+
+	# kill cached PGE value
+	setlos		#0xffffffff,gr4
+	movgs		gr4,scr0
+	movgs		gr4,scr1
+
+	# kill AMPR-cached TLB values
+	movgs		gr0,iamlr1
+	movgs		gr0,iampr1
+	movgs		gr0,damlr1
+	movgs		gr0,dampr1
+
+	# find out how many lines there are
+	movsg		tpxr,gr5
+	sethi.p		%hi(__tlb_lmax_sizes),gr4
+	srli		gr5,#TPXR_LMAX_SHIFT,gr5
+	setlo.p		%lo(__tlb_lmax_sizes),gr4
+	andi		gr5,#TPXR_LMAX_SMASK,gr5
+	ldub		@(gr4,gr5),gr4
+
+	# now, we assume that the TLB line step is page size in size
+	setlos.p	#PAGE_SIZE,gr5
+	setlos		#0,gr6
+1:
+	tlbpr		gr6,gr0,#6,#0
+	subicc.p	gr4,#1,gr4,icc0
+	add		gr6,gr5,gr6
+	bne		icc0,#2,1b
+
+	DEBUG		'B'
+	bralr
+
+	.size		__flush_tlb_all, .-__flush_tlb_all
+
+###############################################################################
+#
+# flush everything to do with one context
+# - void __flush_tlb_mm(unsigned long contextid [GR8])
+#
+###############################################################################
+	.globl		__flush_tlb_mm
+	.type		__flush_tlb_mm,@function
+__flush_tlb_mm:
+	DEBUG		'M'
+
+	# kill cached PGE value
+	setlos		#0xffffffff,gr4
+	movgs		gr4,scr0
+	movgs		gr4,scr1
+
+	# specify the context we want to flush
+	movgs		gr8,tplr
+
+	# find out how many lines there are
+	movsg		tpxr,gr5
+	sethi.p		%hi(__tlb_lmax_sizes),gr4
+	srli		gr5,#TPXR_LMAX_SHIFT,gr5
+	setlo.p		%lo(__tlb_lmax_sizes),gr4
+	andi		gr5,#TPXR_LMAX_SMASK,gr5
+	ldub		@(gr4,gr5),gr4
+
+	# now, we assume that the TLB line step is page size in size
+	setlos.p	#PAGE_SIZE,gr5
+	setlos		#0,gr6
+0:
+	tlbpr		gr6,gr0,#5,#0
+	subicc.p	gr4,#1,gr4,icc0
+	add		gr6,gr5,gr6
+	bne		icc0,#2,0b
+
+	DEBUG		'N'
+	bralr
+
+	.size		__flush_tlb_mm, .-__flush_tlb_mm
+
+###############################################################################
+#
+# flush a range of addresses from the TLB
+# - void __flush_tlb_page(unsigned long contextid [GR8],
+#			  unsigned long start [GR9])
+#
+###############################################################################
+	.globl		__flush_tlb_page
+	.type		__flush_tlb_page,@function
+__flush_tlb_page:
+	# kill cached PGE value
+	setlos		#0xffffffff,gr4
+	movgs		gr4,scr0
+	movgs		gr4,scr1
+
+	# specify the context we want to flush
+	movgs		gr8,tplr
+
+	# zap the matching TLB line and AMR values
+	setlos		#~(PAGE_SIZE-1),gr5
+	and		gr9,gr5,gr9
+	tlbpr		gr9,gr0,#5,#0
+
+	bralr
+
+	.size		__flush_tlb_page, .-__flush_tlb_page
+
+###############################################################################
+#
+# flush a range of addresses from the TLB
+# - void __flush_tlb_range(unsigned long contextid [GR8],
+#			   unsigned long start [GR9],
+#			   unsigned long end [GR10])
+#
+###############################################################################
+	.globl		__flush_tlb_range
+	.type		__flush_tlb_range,@function
+__flush_tlb_range:
+	# kill cached PGE value
+	setlos		#0xffffffff,gr4
+	movgs		gr4,scr0
+	movgs		gr4,scr1
+
+	# specify the context we want to flush
+	movgs		gr8,tplr
+
+	# round the start down to beginning of TLB line and end up to beginning of next TLB line
+	setlos.p	#~(PAGE_SIZE-1),gr5
+	setlos		#PAGE_SIZE,gr6
+	subi.p		gr10,#1,gr10
+	and		gr9,gr5,gr9
+	and		gr10,gr5,gr10
+2:
+	tlbpr		gr9,gr0,#5,#0
+	subcc.p		gr9,gr10,gr0,icc0
+	add		gr9,gr6,gr9
+	bne		icc0,#0,2b		; most likely a 1-page flush
+
+	bralr
+
+	.size		__flush_tlb_range, .-__flush_tlb_range
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/mm/tlb-miss.S linux-2.6.10-rc1-mm3-frv/arch/frv/mm/tlb-miss.S
--- /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/mm/tlb-miss.S	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/arch/frv/mm/tlb-miss.S	2004-11-05 14:13:03.000000000 +0000
@@ -0,0 +1,631 @@
+/* tlb-miss.S: TLB miss handlers
+ *
+ * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * 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.
+ */
+
+#include <linux/sys.h>
+#include <linux/config.h>
+#include <linux/linkage.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/highmem.h>
+#include <asm/spr-regs.h>
+
+	.section	.text
+	.balign		4
+
+	.globl		__entry_insn_mmu_miss
+__entry_insn_mmu_miss:
+	break
+	nop
+
+	.globl		__entry_insn_mmu_exception
+__entry_insn_mmu_exception:
+	break
+	nop
+
+	.globl		__entry_data_mmu_miss
+__entry_data_mmu_miss:
+	break
+	nop
+
+	.globl		__entry_data_mmu_exception
+__entry_data_mmu_exception:
+	break
+	nop
+
+###############################################################################
+#
+# handle a lookup failure of one sort or another in a kernel TLB handler
+# On entry:
+#   GR29 - faulting address
+#   SCR2 - saved CCR
+#
+###############################################################################
+	.type		__tlb_kernel_fault,@function
+__tlb_kernel_fault:
+	# see if we're supposed to re-enable single-step mode upon return
+	sethi.p		%hi(__break_tlb_miss_return_break),gr30
+	setlo		%lo(__break_tlb_miss_return_break),gr30
+	movsg		pcsr,gr31
+
+	subcc		gr31,gr30,gr0,icc0
+	beq		icc0,#0,__tlb_kernel_fault_sstep
+
+	movsg		scr2,gr30
+	movgs		gr30,ccr
+	movgs		gr29,scr2			/* save EAR0 value */
+	sethi.p		%hi(__kernel_current_task),gr29
+	setlo		%lo(__kernel_current_task),gr29
+	ldi.p		@(gr29,#0),gr29			/* restore GR29 */
+
+	bra		__entry_kernel_handle_mmu_fault
+
+	# we've got to re-enable single-stepping
+__tlb_kernel_fault_sstep:
+	sethi.p		%hi(__break_tlb_miss_real_return_info),gr30
+	setlo		%lo(__break_tlb_miss_real_return_info),gr30
+	lddi		@(gr30,0),gr30
+	movgs		gr30,pcsr
+	movgs		gr31,psr
+
+	movsg		scr2,gr30
+	movgs		gr30,ccr
+	movgs		gr29,scr2			/* save EAR0 value */
+	sethi.p		%hi(__kernel_current_task),gr29
+	setlo		%lo(__kernel_current_task),gr29
+	ldi.p		@(gr29,#0),gr29			/* restore GR29 */
+	bra		__entry_kernel_handle_mmu_fault_sstep
+	
+	.size		__tlb_kernel_fault, .-__tlb_kernel_fault
+
+###############################################################################
+#
+# handle a lookup failure of one sort or another in a user TLB handler
+# On entry:
+#   GR28 - faulting address
+#   SCR2 - saved CCR
+#
+###############################################################################
+	.type		__tlb_user_fault,@function
+__tlb_user_fault:
+	# see if we're supposed to re-enable single-step mode upon return
+	sethi.p		%hi(__break_tlb_miss_return_break),gr30
+	setlo		%lo(__break_tlb_miss_return_break),gr30
+	movsg		pcsr,gr31
+	subcc		gr31,gr30,gr0,icc0
+	beq		icc0,#0,__tlb_user_fault_sstep
+
+	movsg		scr2,gr30
+	movgs		gr30,ccr
+	bra		__entry_uspace_handle_mmu_fault
+
+	# we've got to re-enable single-stepping
+__tlb_user_fault_sstep:
+	sethi.p		%hi(__break_tlb_miss_real_return_info),gr30
+	setlo		%lo(__break_tlb_miss_real_return_info),gr30
+	lddi		@(gr30,0),gr30
+	movgs		gr30,pcsr
+	movgs		gr31,psr
+	movsg		scr2,gr30
+	movgs		gr30,ccr
+	bra		__entry_uspace_handle_mmu_fault_sstep
+
+	.size		__tlb_user_fault, .-__tlb_user_fault
+
+###############################################################################
+#
+# Kernel instruction TLB miss handler
+# On entry:
+#   GR1   - kernel stack pointer
+#   GR28  - saved exception frame pointer
+#   GR29  - faulting address
+#   GR31  - EAR0 ^ SCR0
+#   SCR0  - base of virtual range covered by cached PGE from last ITLB miss (or 0xffffffff)
+#   DAMR3 - mapped page directory
+#   DAMR4 - mapped page table as matched by SCR0
+#
+###############################################################################
+	.globl		__entry_kernel_insn_tlb_miss
+	.type		__entry_kernel_insn_tlb_miss,@function
+__entry_kernel_insn_tlb_miss:
+#if 0
+	sethi.p		%hi(0xe1200004),gr30
+	setlo		%lo(0xe1200004),gr30
+	st		gr0,@(gr30,gr0)
+	sethi.p		%hi(0xffc00100),gr30
+	setlo		%lo(0xffc00100),gr30
+	sth		gr30,@(gr30,gr0)
+	membar
+#endif
+
+	movsg		ccr,gr30			/* save CCR */
+	movgs		gr30,scr2
+
+	# see if the cached page table mapping is appropriate
+	srlicc.p	gr31,#26,gr0,icc0
+	setlos		0x3ffc,gr30
+	srli.p		gr29,#12,gr31			/* use EAR0[25:14] as PTE index */
+	bne		icc0,#0,__itlb_k_PTD_miss
+
+__itlb_k_PTD_mapped:
+	# access the PTD with EAR0[25:14]
+	# - DAMLR4 points to the virtual address of the appropriate page table
+	# - the PTD holds 4096 PTEs
+	# - the PTD must be accessed uncached
+	# - the PTE must be marked accessed if it was valid
+	#
+	and		gr31,gr30,gr31
+	movsg		damlr4,gr30
+	add		gr30,gr31,gr31
+	ldi		@(gr31,#0),gr30			/* fetch the PTE */
+	andicc		gr30,#_PAGE_PRESENT,gr0,icc0
+	ori.p		gr30,#_PAGE_ACCESSED,gr30
+	beq		icc0,#0,__tlb_kernel_fault	/* jump if PTE invalid */
+	sti.p		gr30,@(gr31,#0)			/* update the PTE */
+	andi		gr30,#~_PAGE_ACCESSED,gr30
+
+	# we're using IAMR1 as an extra TLB entry
+	# - punt the entry here (if valid) to the real TLB and then replace with the new PTE
+	# - need to check DAMR1 lest we cause an multiple-DAT-hit exception
+	# - IAMPR1 has no WP bit, and we mustn't lose WP information
+	movsg		iampr1,gr31
+	andicc		gr31,#xAMPRx_V,gr0,icc0
+	setlos.p	0xfffff000,gr31
+	beq		icc0,#0,__itlb_k_nopunt		/* punt not required */
+
+	movsg		iamlr1,gr31
+	movgs		gr31,tplr			/* set TPLR.CXN */
+	tlbpr		gr31,gr0,#4,#0			/* delete matches from TLB, IAMR1, DAMR1 */
+
+	movsg		iampr1,gr31
+	ori		gr31,#xAMPRx_V|DAMPRx_WP,gr31	/* entry was invalidated by tlbpr #4 */
+	movgs		gr31,tppr
+	movsg		iamlr1,gr31			/* set TPLR.CXN */
+	movgs		gr31,tplr
+	tlbpr		gr31,gr0,#2,#0			/* save to the TLB */
+	movsg		tpxr,gr31			/* check the TLB write error flag */
+	andicc.p	gr31,#TPXR_E,gr0,icc0
+	setlos		#0xfffff000,gr31
+	bne		icc0,#0,__tlb_kernel_fault
+
+__itlb_k_nopunt:
+
+	# assemble the new TLB entry
+	and		gr29,gr31,gr29
+	movsg		cxnr,gr31
+	or		gr29,gr31,gr29
+	movgs		gr29,iamlr1			/* xAMLR = address | context number */
+	movgs		gr30,iampr1
+	movgs		gr29,damlr1
+	movgs		gr30,dampr1
+
+	# return, restoring registers
+	movsg		scr2,gr30
+	movgs		gr30,ccr
+	sethi.p		%hi(__kernel_current_task),gr29
+	setlo		%lo(__kernel_current_task),gr29
+	ldi		@(gr29,#0),gr29
+	rett		#0
+	beq		icc0,#3,0			/* prevent icache prefetch */
+
+	# the PTE we want wasn't in the PTD we have mapped, so we need to go looking for a more
+	# appropriate page table and map that instead
+	#   - access the PGD with EAR0[31:26]
+	#   - DAMLR3 points to the virtual address of the page directory
+	#   - the PGD holds 64 PGEs and each PGE/PME points to a set of page tables
+__itlb_k_PTD_miss:
+	srli		gr29,#26,gr31			/* calculate PGE offset */
+	slli		gr31,#8,gr31			/* and clear bottom bits */
+
+	movsg		damlr3,gr30
+	ld		@(gr31,gr30),gr30		/* access the PGE */
+
+	andicc.p	gr30,#_PAGE_PRESENT,gr0,icc0
+	andicc		gr30,#xAMPRx_SS,gr0,icc1
+
+	# map this PTD instead and record coverage address
+	ori.p		gr30,#xAMPRx_L|xAMPRx_SS_16Kb|xAMPRx_S|xAMPRx_C|xAMPRx_V,gr30
+	beq		icc0,#0,__tlb_kernel_fault	/* jump if PGE not present */
+	slli.p		gr31,#18,gr31
+	bne		icc1,#0,__itlb_k_bigpage
+	movgs		gr30,dampr4
+	movgs		gr31,scr0
+
+	# we can now resume normal service
+	setlos		0x3ffc,gr30
+	srli.p		gr29,#12,gr31			/* use EAR0[25:14] as PTE index */
+	bra		__itlb_k_PTD_mapped
+
+__itlb_k_bigpage:
+	break
+	nop
+
+	.size		__entry_kernel_insn_tlb_miss, .-__entry_kernel_insn_tlb_miss
+
+###############################################################################
+#
+# Kernel data TLB miss handler
+# On entry:
+#   GR1   - kernel stack pointer
+#   GR28  - saved exception frame pointer
+#   GR29  - faulting address
+#   GR31  - EAR0 ^ SCR1
+#   SCR1  - base of virtual range covered by cached PGE from last DTLB miss (or 0xffffffff)
+#   DAMR3 - mapped page directory
+#   DAMR5 - mapped page table as matched by SCR1
+#
+###############################################################################
+	.globl		__entry_kernel_data_tlb_miss
+	.type		__entry_kernel_data_tlb_miss,@function
+__entry_kernel_data_tlb_miss:
+#if 0
+	sethi.p		%hi(0xe1200004),gr30
+	setlo		%lo(0xe1200004),gr30
+	st		gr0,@(gr30,gr0)
+	sethi.p		%hi(0xffc00100),gr30
+	setlo		%lo(0xffc00100),gr30
+	sth		gr30,@(gr30,gr0)
+	membar
+#endif
+
+	movsg		ccr,gr30			/* save CCR */
+	movgs		gr30,scr2
+
+	# see if the cached page table mapping is appropriate
+	srlicc.p	gr31,#26,gr0,icc0
+	setlos		0x3ffc,gr30
+	srli.p		gr29,#12,gr31			/* use EAR0[25:14] as PTE index */
+	bne		icc0,#0,__dtlb_k_PTD_miss
+
+__dtlb_k_PTD_mapped:
+	# access the PTD with EAR0[25:14]
+	# - DAMLR5 points to the virtual address of the appropriate page table
+	# - the PTD holds 4096 PTEs
+	# - the PTD must be accessed uncached
+	# - the PTE must be marked accessed if it was valid
+	#
+	and		gr31,gr30,gr31
+	movsg		damlr5,gr30
+	add		gr30,gr31,gr31
+	ldi		@(gr31,#0),gr30			/* fetch the PTE */
+	andicc		gr30,#_PAGE_PRESENT,gr0,icc0
+	ori.p		gr30,#_PAGE_ACCESSED,gr30
+	beq		icc0,#0,__tlb_kernel_fault	/* jump if PTE invalid */
+	sti.p		gr30,@(gr31,#0)			/* update the PTE */
+	andi		gr30,#~_PAGE_ACCESSED,gr30
+
+	# we're using DAMR1 as an extra TLB entry
+	# - punt the entry here (if valid) to the real TLB and then replace with the new PTE
+	# - need to check IAMR1 lest we cause an multiple-DAT-hit exception
+	movsg		dampr1,gr31
+	andicc		gr31,#xAMPRx_V,gr0,icc0
+	setlos.p	0xfffff000,gr31
+	beq		icc0,#0,__dtlb_k_nopunt		/* punt not required */
+
+	movsg		damlr1,gr31
+	movgs		gr31,tplr			/* set TPLR.CXN */
+	tlbpr		gr31,gr0,#4,#0			/* delete matches from TLB, IAMR1, DAMR1 */
+
+	movsg		dampr1,gr31
+	ori		gr31,#xAMPRx_V,gr31		/* entry was invalidated by tlbpr #4 */
+	movgs		gr31,tppr
+	movsg		damlr1,gr31			/* set TPLR.CXN */
+	movgs		gr31,tplr
+	tlbpr		gr31,gr0,#2,#0			/* save to the TLB */
+	movsg		tpxr,gr31			/* check the TLB write error flag */
+	andicc.p	gr31,#TPXR_E,gr0,icc0
+	setlos		#0xfffff000,gr31
+	bne		icc0,#0,__tlb_kernel_fault
+
+__dtlb_k_nopunt:
+
+	# assemble the new TLB entry
+	and		gr29,gr31,gr29
+	movsg		cxnr,gr31
+	or		gr29,gr31,gr29
+	movgs		gr29,iamlr1			/* xAMLR = address | context number */
+	movgs		gr30,iampr1
+	movgs		gr29,damlr1
+	movgs		gr30,dampr1
+
+	# return, restoring registers
+	movsg		scr2,gr30
+	movgs		gr30,ccr
+	sethi.p		%hi(__kernel_current_task),gr29
+	setlo		%lo(__kernel_current_task),gr29
+	ldi		@(gr29,#0),gr29
+	rett		#0
+	beq		icc0,#3,0			/* prevent icache prefetch */
+
+	# the PTE we want wasn't in the PTD we have mapped, so we need to go looking for a more
+	# appropriate page table and map that instead
+	#   - access the PGD with EAR0[31:26]
+	#   - DAMLR3 points to the virtual address of the page directory
+	#   - the PGD holds 64 PGEs and each PGE/PME points to a set of page tables
+__dtlb_k_PTD_miss:
+	srli		gr29,#26,gr31			/* calculate PGE offset */
+	slli		gr31,#8,gr31			/* and clear bottom bits */
+
+	movsg		damlr3,gr30
+	ld		@(gr31,gr30),gr30		/* access the PGE */
+
+	andicc.p	gr30,#_PAGE_PRESENT,gr0,icc0
+	andicc		gr30,#xAMPRx_SS,gr0,icc1
+
+	# map this PTD instead and record coverage address
+	ori.p		gr30,#xAMPRx_L|xAMPRx_SS_16Kb|xAMPRx_S|xAMPRx_C|xAMPRx_V,gr30
+	beq		icc0,#0,__tlb_kernel_fault	/* jump if PGE not present */
+	slli.p		gr31,#18,gr31
+	bne		icc1,#0,__dtlb_k_bigpage
+	movgs		gr30,dampr5
+	movgs		gr31,scr1
+
+	# we can now resume normal service
+	setlos		0x3ffc,gr30
+	srli.p		gr29,#12,gr31			/* use EAR0[25:14] as PTE index */
+	bra		__dtlb_k_PTD_mapped
+
+__dtlb_k_bigpage:
+	break
+	nop
+
+	.size		__entry_kernel_data_tlb_miss, .-__entry_kernel_data_tlb_miss
+
+###############################################################################
+#
+# Userspace instruction TLB miss handler (with PGE prediction)
+# On entry:
+#   GR28  - faulting address
+#   GR31  - EAR0 ^ SCR0
+#   SCR0  - base of virtual range covered by cached PGE from last ITLB miss (or 0xffffffff)
+#   DAMR3 - mapped page directory
+#   DAMR4 - mapped page table as matched by SCR0
+#
+###############################################################################
+	.globl		__entry_user_insn_tlb_miss
+	.type		__entry_user_insn_tlb_miss,@function
+__entry_user_insn_tlb_miss:
+#if 0
+	sethi.p		%hi(0xe1200004),gr30
+	setlo		%lo(0xe1200004),gr30
+	st		gr0,@(gr30,gr0)
+	sethi.p		%hi(0xffc00100),gr30
+	setlo		%lo(0xffc00100),gr30
+	sth		gr30,@(gr30,gr0)
+	membar
+#endif
+
+	movsg		ccr,gr30			/* save CCR */
+	movgs		gr30,scr2
+
+	# see if the cached page table mapping is appropriate
+	srlicc.p	gr31,#26,gr0,icc0
+	setlos		0x3ffc,gr30
+	srli.p		gr28,#12,gr31			/* use EAR0[25:14] as PTE index */
+	bne		icc0,#0,__itlb_u_PTD_miss
+
+__itlb_u_PTD_mapped:
+	# access the PTD with EAR0[25:14]
+	# - DAMLR4 points to the virtual address of the appropriate page table
+	# - the PTD holds 4096 PTEs
+	# - the PTD must be accessed uncached
+	# - the PTE must be marked accessed if it was valid
+	#
+	and		gr31,gr30,gr31
+	movsg		damlr4,gr30
+	add		gr30,gr31,gr31
+	ldi		@(gr31,#0),gr30			/* fetch the PTE */
+	andicc		gr30,#_PAGE_PRESENT,gr0,icc0
+	ori.p		gr30,#_PAGE_ACCESSED,gr30
+	beq		icc0,#0,__tlb_user_fault	/* jump if PTE invalid */
+	sti.p		gr30,@(gr31,#0)			/* update the PTE */
+	andi		gr30,#~_PAGE_ACCESSED,gr30
+
+	# we're using IAMR1/DAMR1 as an extra TLB entry
+	# - punt the entry here (if valid) to the real TLB and then replace with the new PTE
+	movsg		dampr1,gr31
+	andicc		gr31,#xAMPRx_V,gr0,icc0
+	setlos.p	0xfffff000,gr31
+	beq		icc0,#0,__itlb_u_nopunt		/* punt not required */
+
+	movsg		dampr1,gr31
+	movgs		gr31,tppr
+	movsg		damlr1,gr31			/* set TPLR.CXN */
+	movgs		gr31,tplr
+	tlbpr		gr31,gr0,#2,#0			/* save to the TLB */
+	movsg		tpxr,gr31			/* check the TLB write error flag */
+	andicc.p	gr31,#TPXR_E,gr0,icc0
+	setlos		#0xfffff000,gr31
+	bne		icc0,#0,__tlb_user_fault
+
+__itlb_u_nopunt:
+
+	# assemble the new TLB entry
+	and		gr28,gr31,gr28
+	movsg		cxnr,gr31
+	or		gr28,gr31,gr28
+	movgs		gr28,iamlr1			/* xAMLR = address | context number */
+	movgs		gr30,iampr1
+	movgs		gr28,damlr1
+	movgs		gr30,dampr1
+	
+	# return, restoring registers
+	movsg		scr2,gr30
+	movgs		gr30,ccr
+	rett		#0
+	beq		icc0,#3,0			/* prevent icache prefetch */
+
+	# the PTE we want wasn't in the PTD we have mapped, so we need to go looking for a more
+	# appropriate page table and map that instead
+	#   - access the PGD with EAR0[31:26]
+	#   - DAMLR3 points to the virtual address of the page directory
+	#   - the PGD holds 64 PGEs and each PGE/PME points to a set of page tables
+__itlb_u_PTD_miss:
+	srli		gr28,#26,gr31			/* calculate PGE offset */
+	slli		gr31,#8,gr31			/* and clear bottom bits */
+
+	movsg		damlr3,gr30
+	ld		@(gr31,gr30),gr30		/* access the PGE */
+
+	andicc.p	gr30,#_PAGE_PRESENT,gr0,icc0
+	andicc		gr30,#xAMPRx_SS,gr0,icc1
+
+	# map this PTD instead and record coverage address
+	ori.p		gr30,#xAMPRx_L|xAMPRx_SS_16Kb|xAMPRx_S|xAMPRx_C|xAMPRx_V,gr30
+	beq		icc0,#0,__tlb_user_fault	/* jump if PGE not present */
+	slli.p		gr31,#18,gr31
+	bne		icc1,#0,__itlb_u_bigpage
+	movgs		gr30,dampr4
+	movgs		gr31,scr0
+
+	# we can now resume normal service
+	setlos		0x3ffc,gr30
+	srli.p		gr28,#12,gr31			/* use EAR0[25:14] as PTE index */
+	bra		__itlb_u_PTD_mapped
+
+__itlb_u_bigpage:
+	break
+	nop
+
+	.size		__entry_user_insn_tlb_miss, .-__entry_user_insn_tlb_miss
+
+###############################################################################
+#
+# Userspace data TLB miss handler
+# On entry:
+#   GR28  - faulting address
+#   GR31  - EAR0 ^ SCR1
+#   SCR1  - base of virtual range covered by cached PGE from last DTLB miss (or 0xffffffff)
+#   DAMR3 - mapped page directory
+#   DAMR5 - mapped page table as matched by SCR1
+#
+###############################################################################
+	.globl		__entry_user_data_tlb_miss
+	.type		__entry_user_data_tlb_miss,@function
+__entry_user_data_tlb_miss:
+#if 0
+	sethi.p		%hi(0xe1200004),gr30
+	setlo		%lo(0xe1200004),gr30
+	st		gr0,@(gr30,gr0)
+	sethi.p		%hi(0xffc00100),gr30
+	setlo		%lo(0xffc00100),gr30
+	sth		gr30,@(gr30,gr0)
+	membar
+#endif
+
+	movsg		ccr,gr30			/* save CCR */
+	movgs		gr30,scr2
+
+	# see if the cached page table mapping is appropriate
+	srlicc.p	gr31,#26,gr0,icc0
+	setlos		0x3ffc,gr30
+	srli.p		gr28,#12,gr31			/* use EAR0[25:14] as PTE index */
+	bne		icc0,#0,__dtlb_u_PTD_miss
+
+__dtlb_u_PTD_mapped:
+	# access the PTD with EAR0[25:14]
+	# - DAMLR5 points to the virtual address of the appropriate page table
+	# - the PTD holds 4096 PTEs
+	# - the PTD must be accessed uncached
+	# - the PTE must be marked accessed if it was valid
+	#
+	and		gr31,gr30,gr31
+	movsg		damlr5,gr30
+
+__dtlb_u_using_iPTD:
+	add		gr30,gr31,gr31
+	ldi		@(gr31,#0),gr30			/* fetch the PTE */
+	andicc		gr30,#_PAGE_PRESENT,gr0,icc0
+	ori.p		gr30,#_PAGE_ACCESSED,gr30
+	beq		icc0,#0,__tlb_user_fault	/* jump if PTE invalid */
+	sti.p		gr30,@(gr31,#0)			/* update the PTE */
+	andi		gr30,#~_PAGE_ACCESSED,gr30
+
+	# we're using DAMR1 as an extra TLB entry
+	# - punt the entry here (if valid) to the real TLB and then replace with the new PTE
+	movsg		dampr1,gr31
+	andicc		gr31,#xAMPRx_V,gr0,icc0
+	setlos.p	0xfffff000,gr31
+	beq		icc0,#0,__dtlb_u_nopunt		/* punt not required */
+
+	movsg		dampr1,gr31
+	movgs		gr31,tppr
+	movsg		damlr1,gr31			/* set TPLR.CXN */
+	movgs		gr31,tplr
+	tlbpr		gr31,gr0,#2,#0			/* save to the TLB */
+	movsg		tpxr,gr31			/* check the TLB write error flag */
+	andicc.p	gr31,#TPXR_E,gr0,icc0
+	setlos		#0xfffff000,gr31
+	bne		icc0,#0,__tlb_user_fault
+
+__dtlb_u_nopunt:
+
+	# assemble the new TLB entry
+	and		gr28,gr31,gr28
+	movsg		cxnr,gr31
+	or		gr28,gr31,gr28
+	movgs		gr28,iamlr1			/* xAMLR = address | context number */
+	movgs		gr30,iampr1
+	movgs		gr28,damlr1
+	movgs		gr30,dampr1
+
+	# return, restoring registers
+	movsg		scr2,gr30
+	movgs		gr30,ccr
+	rett		#0
+	beq		icc0,#3,0			/* prevent icache prefetch */
+
+	# the PTE we want wasn't in the PTD we have mapped, so we need to go looking for a more
+	# appropriate page table and map that instead
+	#   - first of all, check the insn PGE cache - we may well get a hit there
+	#   - access the PGD with EAR0[31:26]
+	#   - DAMLR3 points to the virtual address of the page directory
+	#   - the PGD holds 64 PGEs and each PGE/PME points to a set of page tables
+__dtlb_u_PTD_miss:
+	movsg		scr0,gr31			/* consult the insn-PGE-cache key */
+	xor		gr28,gr31,gr31
+	srlicc		gr31,#26,gr0,icc0
+	srli		gr28,#12,gr31			/* use EAR0[25:14] as PTE index */
+	bne		icc0,#0,__dtlb_u_iPGE_miss
+
+	# what we're looking for is covered by the insn-PGE-cache
+	setlos		0x3ffc,gr30
+	and		gr31,gr30,gr31
+	movsg		damlr4,gr30
+	bra		__dtlb_u_using_iPTD
+
+__dtlb_u_iPGE_miss:	
+	srli		gr28,#26,gr31			/* calculate PGE offset */
+	slli		gr31,#8,gr31			/* and clear bottom bits */
+
+	movsg		damlr3,gr30
+	ld		@(gr31,gr30),gr30		/* access the PGE */
+
+	andicc.p	gr30,#_PAGE_PRESENT,gr0,icc0
+	andicc		gr30,#xAMPRx_SS,gr0,icc1
+
+	# map this PTD instead and record coverage address
+	ori.p		gr30,#xAMPRx_L|xAMPRx_SS_16Kb|xAMPRx_S|xAMPRx_C|xAMPRx_V,gr30
+	beq		icc0,#0,__tlb_user_fault	/* jump if PGE not present */
+	slli.p		gr31,#18,gr31
+	bne		icc1,#0,__dtlb_u_bigpage
+	movgs		gr30,dampr5
+	movgs		gr31,scr1
+
+	# we can now resume normal service
+	setlos		0x3ffc,gr30
+	srli.p		gr28,#12,gr31			/* use EAR0[25:14] as PTE index */
+	bra		__dtlb_u_PTD_mapped
+
+__dtlb_u_bigpage:
+	break
+	nop
+
+	.size		__entry_user_data_tlb_miss, .-__entry_user_data_tlb_miss
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/mm/unaligned.c linux-2.6.10-rc1-mm3-frv/arch/frv/mm/unaligned.c
--- /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/mm/unaligned.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/arch/frv/mm/unaligned.c	2004-11-05 14:13:03.000000000 +0000
@@ -0,0 +1,218 @@
+/* unaligned.c: unalignment fixup handler for CPUs on which it is supported (FR451 only)
+ *
+ * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * 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.
+ */
+
+#include <linux/config.h>
+#include <linux/sched.h>
+#include <linux/signal.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/types.h>
+#include <linux/user.h>
+#include <linux/string.h>
+#include <linux/linkage.h>
+#include <linux/init.h>
+
+#include <asm/setup.h>
+#include <asm/system.h>
+#include <asm/uaccess.h>
+
+#if 0
+#define kdebug(fmt, ...) printk("FDPIC "fmt"\n" ,##__VA_ARGS__ )
+#else
+#define kdebug(fmt, ...) do {} while(0)
+#endif
+
+#define _MA_SIGNED	0x01
+#define _MA_HALF	0x02
+#define _MA_WORD	0x04
+#define _MA_DWORD	0x08
+#define _MA_SZ_MASK	0x0e
+#define _MA_LOAD	0x10
+#define _MA_STORE	0x20
+#define _MA_UPDATE	0x40
+#define _MA_IMM		0x80
+
+#define _MA_LDxU	_MA_LOAD | _MA_UPDATE
+#define _MA_LDxI	_MA_LOAD | _MA_IMM
+#define _MA_STxU	_MA_STORE | _MA_UPDATE
+#define _MA_STxI	_MA_STORE | _MA_IMM
+
+static const uint8_t tbl_LDGRk_reg[0x40] = {
+	[0x02] = _MA_LOAD | _MA_HALF | _MA_SIGNED,	/* LDSH  @(GRi,GRj),GRk */
+	[0x03] = _MA_LOAD | _MA_HALF,			/* LDUH  @(GRi,GRj),GRk */
+	[0x04] = _MA_LOAD | _MA_WORD,			/* LD	 @(GRi,GRj),GRk */
+	[0x05] = _MA_LOAD | _MA_DWORD,			/* LDD	 @(GRi,GRj),GRk */
+	[0x12] = _MA_LDxU | _MA_HALF | _MA_SIGNED,	/* LDSHU @(GRi,GRj),GRk */
+	[0x13] = _MA_LDxU | _MA_HALF,			/* LDUHU @(GRi,GRj),GRk */
+	[0x14] = _MA_LDxU | _MA_WORD,			/* LDU	 @(GRi,GRj),GRk */
+	[0x15] = _MA_LDxU | _MA_DWORD,			/* LDDU	 @(GRi,GRj),GRk */
+};
+
+static const uint8_t tbl_STGRk_reg[0x40] = {
+	[0x01] = _MA_STORE | _MA_HALF,			/* STH   @(GRi,GRj),GRk */
+	[0x02] = _MA_STORE | _MA_WORD,			/* ST	 @(GRi,GRj),GRk */
+	[0x03] = _MA_STORE | _MA_DWORD,			/* STD	 @(GRi,GRj),GRk */
+	[0x11] = _MA_STxU  | _MA_HALF,			/* STHU  @(GRi,GRj),GRk */
+	[0x12] = _MA_STxU  | _MA_WORD,			/* STU	 @(GRi,GRj),GRk */
+	[0x13] = _MA_STxU  | _MA_DWORD,			/* STDU	 @(GRi,GRj),GRk */
+};
+
+static const uint8_t tbl_LDSTGRk_imm[0x80] = {
+	[0x31] = _MA_LDxI | _MA_HALF | _MA_SIGNED,	/* LDSHI @(GRi,d12),GRk */
+	[0x32] = _MA_LDxI | _MA_WORD,			/* LDI   @(GRi,d12),GRk */
+	[0x33] = _MA_LDxI | _MA_DWORD,			/* LDDI  @(GRi,d12),GRk */
+	[0x36] = _MA_LDxI | _MA_HALF,			/* LDUHI @(GRi,d12),GRk */
+	[0x51] = _MA_STxI | _MA_HALF,			/* STHI  @(GRi,d12),GRk */
+	[0x52] = _MA_STxI | _MA_WORD,			/* STI   @(GRi,d12),GRk */
+	[0x53] = _MA_STxI | _MA_DWORD,			/* STDI  @(GRi,d12),GRk */
+};
+
+
+/*****************************************************************************/
+/*
+ * see if we can handle the exception by fixing up a misaligned memory access
+ */
+int handle_misalignment(unsigned long esr0, unsigned long ear0, unsigned long epcr0)
+{
+	unsigned long insn, addr, *greg;
+	int GRi, GRj, GRk, D12, op;
+
+	union {
+		uint64_t _64;
+		uint32_t _32[2];
+		uint16_t _16;
+		uint8_t _8[8];
+	} x;
+
+	if (!(esr0 & ESR0_EAV) || !(epcr0 & EPCR0_V) || !(ear0 & 7))
+		return -EAGAIN;
+
+	epcr0 &= EPCR0_PC;
+
+	if (__frame->pc != epcr0) {
+		kdebug("MISALIGN: Execution not halted on excepting instruction\n");
+		BUG();
+	}
+
+	if (__get_user(insn, (unsigned long *) epcr0) < 0)
+		return -EFAULT;
+
+	/* determine the instruction type first */
+	switch ((insn >> 18) & 0x7f) {
+	case 0x2:
+		/* LDx @(GRi,GRj),GRk */
+		op = tbl_LDGRk_reg[(insn >> 6) & 0x3f];
+		break;
+
+	case 0x3:
+		/* STx GRk,@(GRi,GRj) */
+		op = tbl_STGRk_reg[(insn >> 6) & 0x3f];
+		break;
+
+	default:
+		op = tbl_LDSTGRk_imm[(insn >> 18) & 0x7f];
+		break;
+	}
+
+	if (!op)
+		return -EAGAIN;
+
+	kdebug("MISALIGN: pc=%08lx insn=%08lx ad=%08lx op=%02x\n", epcr0, insn, ear0, op);
+
+	memset(&x, 0xba, 8);
+
+	/* validate the instruction parameters */
+	greg = (unsigned long *) &__frame->tbr;
+
+	GRi = (insn >> 12) & 0x3f;
+	GRk = (insn >> 25) & 0x3f;
+
+	if (GRi > 31 || GRk > 31)
+		return -ENOENT;
+
+	if (op & _MA_DWORD && GRk & 1)
+		return -EINVAL;
+
+	if (op & _MA_IMM) {
+		D12 = insn & 0xfff;
+		asm ("slli %0,#20,%0 ! srai %0,#20,%0" : "=r"(D12) : "0"(D12)); /* sign extend */
+		addr = (GRi ? greg[GRi] : 0) + D12;
+	}
+	else {
+		GRj = (insn >>  0) & 0x3f;
+		if (GRj > 31)
+			return -ENOENT;
+		addr = (GRi ? greg[GRi] : 0) + (GRj ? greg[GRj] : 0);
+	}
+
+	if (addr != ear0) {
+		kdebug("MISALIGN: Calculated addr (%08lx) does not match EAR0 (%08lx)\n",
+		       addr, ear0);
+		return -EFAULT;
+	}
+
+	/* check the address is okay */
+	if (user_mode(__frame) && ___range_ok(ear0, 8) < 0)
+		return -EFAULT;
+
+	/* perform the memory op */
+	if (op & _MA_STORE) {
+		/* perform a store */
+		x._32[0] = 0;
+		if (GRk != 0) {
+			if (op & _MA_HALF) {
+				x._16 = greg[GRk];
+			}
+			else {
+				x._32[0] = greg[GRk];
+			}
+		}
+		if (op & _MA_DWORD)
+			x._32[1] = greg[GRk + 1];
+
+		kdebug("MISALIGN: Store GR%d { %08x:%08x } -> %08lx (%dB)\n",
+		       GRk, x._32[1], x._32[0], addr, op & _MA_SZ_MASK);
+
+		if (__memcpy_user((void *) addr, &x, op & _MA_SZ_MASK) != 0)
+			return -EFAULT;
+	}
+	else {
+		/* perform a load */
+		if (__memcpy_user(&x, (void *) addr, op & _MA_SZ_MASK) != 0)
+			return -EFAULT;
+
+		if (op & _MA_HALF) {
+			if (op & _MA_SIGNED)
+				asm ("slli %0,#16,%0 ! srai %0,#16,%0"
+				     : "=r"(x._32[0]) : "0"(x._16));
+			else
+				asm ("sethi #0,%0"
+				     : "=r"(x._32[0]) : "0"(x._16));
+		}
+
+		kdebug("MISALIGN: Load %08lx (%dB) -> GR%d, { %08x:%08x }\n",
+		       addr, op & _MA_SZ_MASK, GRk, x._32[1], x._32[0]);
+
+		if (GRk != 0)
+			greg[GRk] = x._32[0];
+		if (op & _MA_DWORD)
+			greg[GRk + 1] = x._32[1];
+	}
+
+	/* update the base pointer if required */
+	if (op & _MA_UPDATE)
+		greg[GRi] = addr;
+
+	/* well... we've done that insn */
+	__frame->pc = __frame->pc + 4;
+
+	return 0;
+} /* end handle_misalignment() */

^ permalink raw reply	[flat|nested] 87+ messages in thread

* [PATCH 9/20] FRV: Fujitsu FR-V CPU arch implementation part 7
  2004-11-08 14:34 [PATCH 1/20] FRV: Fujitsu FR-V CPU arch maintainer record dhowells
                   ` (6 preceding siblings ...)
  2004-11-08 14:34 ` [PATCH 8/20] FRV: Fujitsu FR-V CPU arch implementation part 6 dhowells
@ 2004-11-08 14:34 ` dhowells
  2004-11-08 14:34 ` [PATCH 11/20] FRV: Fujitsu FR-V CPU arch implementation part 9 dhowells
                   ` (8 subsequent siblings)
  16 siblings, 0 replies; 87+ messages in thread
From: dhowells @ 2004-11-08 14:34 UTC (permalink / raw)
  To: torvalds, akpm, davidm; +Cc: linux-kernel, uclinux-dev

The attached patches provides part 7 of an architecture implementation
for the Fujitsu FR-V CPU series, configurably as Linux or uClinux.

Signed-Off-By: dhowells@redhat.com
---
diffstat frv-arch_7-2610rc1mm3.diff
 Makefile     |    8 +
 __ashldi3.S  |   40 ++++++++
 __ashrdi3.S  |   41 +++++++++
 __lshrdi3.S  |   40 ++++++++
 __muldi3.S   |   32 +++++++
 __negdi2.S   |   28 ++++++
 atomic-ops.S |  265 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 cache.S      |   98 +++++++++++++++++++++
 checksum.c   |  148 ++++++++++++++++++++++++++++++++
 insl_ns.S    |   52 +++++++++++
 insl_sw.S    |   40 ++++++++
 memcpy.S     |  135 ++++++++++++++++++++++++++++++
 memset.S     |  182 ++++++++++++++++++++++++++++++++++++++++
 outsl_ns.S   |   59 +++++++++++++
 outsl_sw.S   |   45 ++++++++++
 15 files changed, 1213 insertions(+)

diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/lib/__ashldi3.S linux-2.6.10-rc1-mm3-frv/arch/frv/lib/__ashldi3.S
--- /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/lib/__ashldi3.S	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/arch/frv/lib/__ashldi3.S	2004-11-05 14:13:03.262549909 +0000
@@ -0,0 +1,40 @@
+/* __ashldi3.S:	64-bit arithmetic shift left
+ *
+ * Copyright (C) 2003 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * 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.
+ */
+
+        .text
+        .p2align	4
+
+###############################################################################
+#
+# unsigned long long __ashldi3(unsigned long long value [GR8:GR9], unsigned by [GR10])
+#
+###############################################################################
+        .globl		__ashldi3
+        .type		__ashldi3,@function
+__ashldi3:
+	andicc.p	gr10,#63,gr10,icc0
+	setlos		#32,gr5
+	andicc.p	gr10,#32,gr0,icc1
+	beqlr		icc0,#0
+	ckeq		icc1,cc4			; cc4 is true if 0<N<32
+
+	# deal with a shift in the range 1<=N<=31
+	csll.p		gr8,gr10,gr8	,cc4,#1		; MSW <<= N
+	csub		gr5,gr10,gr5	,cc4,#1		; M = 32 - N
+	csrl.p		gr9,gr5,gr4	,cc4,#1
+	csll		gr9,gr10,gr9	,cc4,#1		; LSW <<= N
+	cor.p		gr4,gr8,gr8	,cc4,#1		; MSW |= LSW >> M
+
+	# deal with a shift in the range 32<=N<=63
+	csll		gr9,gr10,gr8	,cc4,#0		; MSW = LSW << (N & 31 [implicit AND])
+	cor.p		gr0,gr0,gr9	,cc4,#0		; LSW = 0
+	bralr
+	.size		__ashldi3, .-__ashldi3
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/lib/__ashrdi3.S linux-2.6.10-rc1-mm3-frv/arch/frv/lib/__ashrdi3.S
--- /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/lib/__ashrdi3.S	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/arch/frv/lib/__ashrdi3.S	2004-11-05 14:13:03.266549572 +0000
@@ -0,0 +1,41 @@
+/* __ashrdi3.S:	64-bit arithmetic shift right
+ *
+ * Copyright (C) 2003 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * 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.
+ */
+
+        .text
+        .p2align	4
+
+###############################################################################
+#
+# signed long long __ashrdi3(signed long long value [GR8:GR9], unsigned by [GR10])
+#
+###############################################################################
+        .globl		__ashrdi3
+        .type		__ashrdi3,@function
+__ashrdi3:
+	andicc.p	gr10,#63,gr10,icc0
+	setlos		#32,gr5
+	andicc.p	gr10,#32,gr0,icc1
+	beqlr		icc0,#0
+	setlos.p	#31,gr6
+	ckeq		icc1,cc4			; cc4 is true if 0<N<32
+
+	# deal with a shift in the range 1<=N<=31
+	csrl.p		gr9,gr10,gr9	,cc4,#1		; LSW >>= N
+	csub		gr5,gr10,gr5	,cc4,#1		; M = 32 - N
+	csll.p		gr8,gr5,gr4	,cc4,#1
+	csra		gr8,gr10,gr8	,cc4,#1		; MSW >>= N
+	cor.p		gr4,gr9,gr9	,cc4,#1		; LSW |= MSW << M
+
+	# deal with a shift in the range 32<=N<=63
+	csra		gr8,gr10,gr9	,cc4,#0		; LSW = MSW >> (N & 31 [implicit AND])
+	csra.p		gr8,gr6,gr8	,cc4,#0		; MSW >>= 31
+	bralr
+	.size		__ashrdi3, .-__ashrdi3
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/lib/atomic-ops.S linux-2.6.10-rc1-mm3-frv/arch/frv/lib/atomic-ops.S
--- /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/lib/atomic-ops.S	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/arch/frv/lib/atomic-ops.S	2004-11-05 14:13:03.270549234 +0000
@@ -0,0 +1,265 @@
+/* atomic-ops.S: kernel atomic operations
+ *
+ * For an explanation of how atomic ops work in this arch, see:
+ *   Documentation/fujitsu/frv/atomic-ops.txt
+ *
+ * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * 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.
+ */
+
+#include <asm/spr-regs.h>
+
+	.text
+	.balign 4
+
+###############################################################################
+#
+# unsigned long atomic_test_and_ANDNOT_mask(unsigned long mask, volatile unsigned long *v);
+#
+###############################################################################
+	.globl		atomic_test_and_ANDNOT_mask
+        .type		atomic_test_and_ANDNOT_mask,@function
+atomic_test_and_ANDNOT_mask:
+	not.p		gr8,gr10
+0:
+	orcc		gr0,gr0,gr0,icc3		/* set ICC3.Z */
+	ckeq		icc3,cc7
+	ld.p		@(gr9,gr0),gr8			/* LD.P/ORCR must be atomic */
+	orcr		cc7,cc7,cc3			/* set CC3 to true */
+	and		gr8,gr10,gr11
+	cst.p		gr11,@(gr9,gr0)		,cc3,#1
+	corcc		gr29,gr29,gr0		,cc3,#1	/* clear ICC3.Z if store happens */
+	beq		icc3,#0,0b
+	bralr
+
+	.size		atomic_test_and_ANDNOT_mask, .-atomic_test_and_ANDNOT_mask
+
+###############################################################################
+#
+# unsigned long atomic_test_and_OR_mask(unsigned long mask, volatile unsigned long *v);
+#
+###############################################################################
+	.globl		atomic_test_and_OR_mask
+        .type		atomic_test_and_OR_mask,@function
+atomic_test_and_OR_mask:
+	or.p		gr8,gr8,gr10
+0:
+	orcc		gr0,gr0,gr0,icc3		/* set ICC3.Z */
+	ckeq		icc3,cc7
+	ld.p		@(gr9,gr0),gr8			/* LD.P/ORCR must be atomic */
+	orcr		cc7,cc7,cc3			/* set CC3 to true */
+	or		gr8,gr10,gr11
+	cst.p		gr11,@(gr9,gr0)		,cc3,#1
+	corcc		gr29,gr29,gr0		,cc3,#1	/* clear ICC3.Z if store happens */
+	beq		icc3,#0,0b
+	bralr
+
+	.size		atomic_test_and_OR_mask, .-atomic_test_and_OR_mask
+
+###############################################################################
+#
+# unsigned long atomic_test_and_XOR_mask(unsigned long mask, volatile unsigned long *v);
+#
+###############################################################################
+	.globl		atomic_test_and_XOR_mask
+        .type		atomic_test_and_XOR_mask,@function
+atomic_test_and_XOR_mask:
+	or.p		gr8,gr8,gr10
+0:
+	orcc		gr0,gr0,gr0,icc3		/* set ICC3.Z */
+	ckeq		icc3,cc7
+	ld.p		@(gr9,gr0),gr8			/* LD.P/ORCR must be atomic */
+	orcr		cc7,cc7,cc3			/* set CC3 to true */
+	xor		gr8,gr10,gr11
+	cst.p		gr11,@(gr9,gr0)		,cc3,#1
+	corcc		gr29,gr29,gr0		,cc3,#1	/* clear ICC3.Z if store happens */
+	beq		icc3,#0,0b
+	bralr
+
+	.size		atomic_test_and_XOR_mask, .-atomic_test_and_XOR_mask
+
+###############################################################################
+#
+# int atomic_add_return(int i, atomic_t *v)
+#
+###############################################################################
+	.globl		atomic_add_return
+        .type		atomic_add_return,@function
+atomic_add_return:
+	or.p		gr8,gr8,gr10
+0:
+	orcc		gr0,gr0,gr0,icc3		/* set ICC3.Z */
+	ckeq		icc3,cc7
+	ld.p		@(gr9,gr0),gr8			/* LD.P/ORCR must be atomic */
+	orcr		cc7,cc7,cc3			/* set CC3 to true */
+	add		gr8,gr10,gr8
+	cst.p		gr8,@(gr9,gr0)		,cc3,#1
+	corcc		gr29,gr29,gr0		,cc3,#1	/* clear ICC3.Z if store happens */
+	beq		icc3,#0,0b
+	bralr
+
+	.size		atomic_add_return, .-atomic_add_return
+
+###############################################################################
+#
+# int atomic_sub_return(int i, atomic_t *v)
+#
+###############################################################################
+	.globl		atomic_sub_return
+        .type		atomic_sub_return,@function
+atomic_sub_return:
+	or.p		gr8,gr8,gr10
+0:
+	orcc		gr0,gr0,gr0,icc3		/* set ICC3.Z */
+	ckeq		icc3,cc7
+	ld.p		@(gr9,gr0),gr8			/* LD.P/ORCR must be atomic */
+	orcr		cc7,cc7,cc3			/* set CC3 to true */
+	sub		gr8,gr10,gr8
+	cst.p		gr8,@(gr9,gr0)		,cc3,#1
+	corcc		gr29,gr29,gr0		,cc3,#1	/* clear ICC3.Z if store happens */
+	beq		icc3,#0,0b
+	bralr
+
+	.size		atomic_sub_return, .-atomic_sub_return
+
+###############################################################################
+#
+# uint8_t __xchg_8(uint8_t i, uint8_t *v)
+#
+###############################################################################
+	.globl		__xchg_8
+        .type		__xchg_8,@function
+__xchg_8:
+	or.p		gr8,gr8,gr10
+0:
+	orcc		gr0,gr0,gr0,icc3		/* set ICC3.Z */
+	ckeq		icc3,cc7
+	ldub.p		@(gr9,gr0),gr8			/* LD.P/ORCR must be atomic */
+	orcr		cc7,cc7,cc3			/* set CC3 to true */
+	cstb.p		gr10,@(gr9,gr0)		,cc3,#1
+	corcc		gr29,gr29,gr0		,cc3,#1	/* clear ICC3.Z if store happens */
+	beq		icc3,#0,0b
+	bralr
+
+	.size		__xchg_8, .-__xchg_8
+
+###############################################################################
+#
+# uint16_t __xchg_16(uint16_t i, uint16_t *v)
+#
+###############################################################################
+	.globl		__xchg_16
+        .type		__xchg_16,@function
+__xchg_16:
+	or.p		gr8,gr8,gr10
+0:
+	orcc		gr0,gr0,gr0,icc3		/* set ICC3.Z */
+	ckeq		icc3,cc7
+	lduh.p		@(gr9,gr0),gr8			/* LD.P/ORCR must be atomic */
+	orcr		cc7,cc7,cc3			/* set CC3 to true */
+	csth.p		gr10,@(gr9,gr0)		,cc3,#1
+	corcc		gr29,gr29,gr0		,cc3,#1	/* clear ICC3.Z if store happens */
+	beq		icc3,#0,0b
+	bralr
+
+	.size		__xchg_16, .-__xchg_16
+
+###############################################################################
+#
+# uint32_t __xchg_32(uint32_t i, uint32_t *v)
+#
+###############################################################################
+	.globl		__xchg_32
+        .type		__xchg_32,@function
+__xchg_32:
+	or.p		gr8,gr8,gr10
+0:
+	orcc		gr0,gr0,gr0,icc3		/* set ICC3.Z */
+	ckeq		icc3,cc7
+	ld.p		@(gr9,gr0),gr8			/* LD.P/ORCR must be atomic */
+	orcr		cc7,cc7,cc3			/* set CC3 to true */
+	cst.p		gr10,@(gr9,gr0)		,cc3,#1
+	corcc		gr29,gr29,gr0		,cc3,#1	/* clear ICC3.Z if store happens */
+	beq		icc3,#0,0b
+	bralr
+
+	.size		__xchg_32, .-__xchg_32
+
+###############################################################################
+#
+# uint8_t __cmpxchg_8(uint8_t *v, uint8_t test, uint8_t new)
+#
+###############################################################################
+	.globl		__cmpxchg_8
+        .type		__cmpxchg_8,@function
+__cmpxchg_8:
+	or.p		gr8,gr8,gr11
+0:
+	orcc		gr0,gr0,gr0,icc3
+	ckeq		icc3,cc7
+	ldub.p		@(gr11,gr0),gr8
+	orcr		cc7,cc7,cc3
+	sub		gr8,gr9,gr7
+	sllicc		gr7,#24,gr0,icc0
+	bne		icc0,#0,1f
+	cstb.p		gr10,@(gr11,gr0)	,cc3,#1
+	corcc		gr29,gr29,gr0		,cc3,#1
+	beq		icc3,#0,0b
+1:
+	bralr
+
+	.size		__cmpxchg_8, .-__cmpxchg_8
+
+###############################################################################
+#
+# uint16_t __cmpxchg_16(uint16_t *v, uint16_t test, uint16_t new)
+#
+###############################################################################
+	.globl		__cmpxchg_16
+        .type		__cmpxchg_16,@function
+__cmpxchg_16:
+	or.p		gr8,gr8,gr11
+0:
+	orcc		gr0,gr0,gr0,icc3
+	ckeq		icc3,cc7
+	lduh.p		@(gr11,gr0),gr8
+	orcr		cc7,cc7,cc3
+	sub		gr8,gr9,gr7
+	sllicc		gr7,#16,gr0,icc0
+	bne		icc0,#0,1f
+	csth.p		gr10,@(gr11,gr0)	,cc3,#1
+	corcc		gr29,gr29,gr0		,cc3,#1
+	beq		icc3,#0,0b
+1:
+	bralr
+
+	.size		__cmpxchg_16, .-__cmpxchg_16
+
+###############################################################################
+#
+# uint32_t __cmpxchg_32(uint32_t *v, uint32_t test, uint32_t new)
+#
+###############################################################################
+	.globl		__cmpxchg_32
+        .type		__cmpxchg_32,@function
+__cmpxchg_32:
+	or.p		gr8,gr8,gr11
+0:
+	orcc		gr0,gr0,gr0,icc3
+	ckeq		icc3,cc7
+	ld.p		@(gr11,gr0),gr8
+	orcr		cc7,cc7,cc3
+	subcc		gr8,gr9,gr7,icc0
+	bne		icc0,#0,1f
+	cst.p		gr10,@(gr11,gr0)	,cc3,#1
+	corcc		gr29,gr29,gr0		,cc3,#1
+	beq		icc3,#0,0b
+1:
+	bralr
+
+	.size		__cmpxchg_32, .-__cmpxchg_32
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/lib/cache.S linux-2.6.10-rc1-mm3-frv/arch/frv/lib/cache.S
--- /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/lib/cache.S	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/arch/frv/lib/cache.S	2004-11-05 14:13:03.274548896 +0000
@@ -0,0 +1,98 @@
+/* cache.S: cache managment routines
+ *
+ * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * 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.
+ */
+
+#include <asm/spr-regs.h>
+#include <asm/cache.h>
+
+        .text
+        .p2align	4
+
+###############################################################################
+#
+# Write back a range of dcache
+# - void frv_dcache_writeback(unsigned long start [GR8], unsigned long size [GR9])
+#
+###############################################################################
+        .globl		frv_dcache_writeback
+        .type		frv_dcache_writeback,@function
+frv_dcache_writeback:	
+	andi		gr8,~(L1_CACHE_BYTES-1),gr8
+
+2:	dcf		@(gr8,gr0)
+	addi		gr8,#L1_CACHE_BYTES,gr8
+	cmp		gr9,gr8,icc0
+	bhi		icc0,#2,2b
+
+	membar
+	bralr
+	.size		frv_dcache_writeback, .-frv_dcache_writeback
+
+##############################################################################
+#
+# Invalidate a range of dcache and icache
+# - void frv_cache_invalidate(unsigned long start [GR8], unsigned long end [GR9]);
+#
+###############################################################################
+        .globl		frv_cache_invalidate
+        .type		frv_cache_invalidate,@function
+frv_cache_invalidate:
+	andi		gr8,~(L1_CACHE_BYTES-1),gr8
+
+2:	dci		@(gr8,gr0)
+	ici		@(gr8,gr0)
+	addi		gr8,#L1_CACHE_BYTES,gr8
+	cmp		gr9,gr8,icc0
+	bhi		icc0,#2,2b
+
+	membar
+	bralr
+	.size		frv_cache_invalidate, .-frv_cache_invalidate
+
+##############################################################################
+#
+# Invalidate a range of icache
+# - void frv_icache_invalidate(unsigned long start [GR8], unsigned long end [GR9]);
+#
+###############################################################################
+        .globl		frv_icache_invalidate
+        .type		frv_icache_invalidate,@function
+frv_icache_invalidate:
+	andi		gr8,~(L1_CACHE_BYTES-1),gr8
+
+2:	ici		@(gr8,gr0)
+	addi		gr8,#L1_CACHE_BYTES,gr8
+	cmp		gr9,gr8,icc0
+	bhi		icc0,#2,2b
+
+	membar
+	bralr
+	.size		frv_icache_invalidate, .-frv_icache_invalidate
+
+###############################################################################
+#
+# Write back and invalidate a range of dcache and icache
+# - void frv_cache_wback_inv(unsigned long start [GR8], unsigned long end [GR9])
+#
+###############################################################################
+        .globl		frv_cache_wback_inv
+        .type		frv_cache_wback_inv,@function
+frv_cache_wback_inv:	
+	andi		gr8,~(L1_CACHE_BYTES-1),gr8
+
+2:	dcf		@(gr8,gr0)
+	ici		@(gr8,gr0)
+	addi		gr8,#L1_CACHE_BYTES,gr8
+	cmp		gr9,gr8,icc0
+	bhi		icc0,#2,2b
+
+	membar
+	bralr
+	.size		frv_cache_wback_inv, .-frv_cache_wback_inv
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/lib/checksum.c linux-2.6.10-rc1-mm3-frv/arch/frv/lib/checksum.c
--- /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/lib/checksum.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/arch/frv/lib/checksum.c	2004-11-05 14:13:03.278548558 +0000
@@ -0,0 +1,148 @@
+/*
+ * 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.
+ */
+ 
+/* Revised by Kenneth Albanowski for m68knommu. Basic problem: unaligned access kills, so most
+   of the assembly has to go. */
+
+#include <net/checksum.h>
+#include <asm/checksum.h>
+
+static inline unsigned short from32to16(unsigned long x)
+{
+	/* add up 16-bit and 16-bit for 16+c bit */
+	x = (x & 0xffff) + (x >> 16);
+	/* add up carry.. */
+	x = (x & 0xffff) + (x >> 16);
+	return x;
+}
+
+static unsigned long do_csum(const unsigned char * buff, int len)
+{
+	int odd, count;
+	unsigned long result = 0;
+
+	if (len <= 0)
+		goto out;
+	odd = 1 & (unsigned long) buff;
+	if (odd) {
+		result = *buff;
+		len--;
+		buff++;
+	}
+	count = len >> 1;		/* nr of 16-bit words.. */
+	if (count) {
+		if (2 & (unsigned long) buff) {
+			result += *(unsigned short *) buff;
+			count--;
+			len -= 2;
+			buff += 2;
+		}
+		count >>= 1;		/* nr of 32-bit words.. */
+		if (count) {
+		        unsigned long carry = 0;
+			do {
+				unsigned long w = *(unsigned long *) buff;
+				count--;
+				buff += 4;
+				result += carry;
+				result += w;
+				carry = (w > result);
+			} while (count);
+			result += carry;
+			result = (result & 0xffff) + (result >> 16);
+		}
+		if (len & 2) {
+			result += *(unsigned short *) buff;
+			buff += 2;
+		}
+	}
+	if (len & 1)
+		result += (*buff << 8);
+	result = from32to16(result);
+	if (odd)
+		result = ((result >> 8) & 0xff) | ((result & 0xff) << 8);
+out:
+	return result;
+}
+
+/*
+ * computes the checksum of a memory block at buff, length len,
+ * and adds in "sum" (32-bit)
+ *
+ * returns a 32-bit number suitable for feeding into itself
+ * or csum_tcpudp_magic
+ *
+ * this function must be called with even lengths, except
+ * for the last fragment, which may be odd
+ *
+ * it's best to have buff aligned on a 32-bit boundary
+ */
+unsigned int csum_partial(const unsigned char * buff, int len, unsigned int sum)
+{
+	unsigned int result = do_csum(buff, len);
+
+	/* add in old sum, and carry.. */
+	result += sum;
+	if (sum > result)
+		result += 1;
+	return result;
+}
+
+/*
+ * this routine is used for miscellaneous IP-like checksums, mainly
+ * in icmp.c
+ */
+unsigned short ip_compute_csum(const unsigned char * buff, int len)
+{
+	return ~do_csum(buff,len);
+}
+
+/*
+ * copy from fs while checksumming, otherwise like csum_partial
+ */
+
+unsigned int
+csum_partial_copy_from_user(const char *src, char *dst, int len, int sum, int *csum_err)
+{
+	if (csum_err) *csum_err = 0;
+	memcpy(dst, src, len);
+	return csum_partial(dst, len, sum);
+}
+
+/*
+ * copy from ds while checksumming, otherwise like csum_partial
+ */
+
+unsigned int
+csum_partial_copy(const char *src, char *dst, int len, int sum)
+{
+	memcpy(dst, src, len);
+	return csum_partial(dst, len, sum);
+}
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/lib/insl_ns.S linux-2.6.10-rc1-mm3-frv/arch/frv/lib/insl_ns.S
--- /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/lib/insl_ns.S	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/arch/frv/lib/insl_ns.S	2004-11-05 14:13:03.282548220 +0000
@@ -0,0 +1,52 @@
+/* insl_ns.S: input array of 4b words from device port without byte swapping
+ *
+ * Copyright (C) 2003 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * 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.
+ */
+
+
+        .text
+        .p2align	4
+
+###############################################################################
+#
+# void __insl_ns(unsigned int port, void *buf, int n)
+#
+###############################################################################
+        .globl		__insl_ns
+        .type		__insl_ns,@function
+__insl_ns:
+	andicc.p	gr9,#3,gr0,icc0
+	setlos		#4,gr4
+	bne		icc0,#0,__insl_ns_misaligned
+	subi		gr9,#4,gr9
+0:
+	ldi.p		@(gr8,#0),gr5
+	subicc		gr10,#1,gr10,icc0
+	stu.p		gr5,@(gr9,gr4)
+	bhi		icc0,#2,0b
+	bralr
+
+__insl_ns_misaligned:
+	subi.p		gr9,#1,gr9
+	setlos		#1,gr4
+0:
+	ldi		@(gr8,#0),gr5
+
+	srli		gr5,#24,gr6
+	stbu.p		gr6,@(gr9,gr4)
+	srli		gr5,#16,gr6
+	stbu.p		gr6,@(gr9,gr4)
+	srli		gr5,#8,gr6
+	stbu.p		gr6,@(gr9,gr4)
+	subicc		gr10,#1,gr10,icc0
+	stbu.p		gr5,@(gr9,gr4)
+	bhi		icc0,#2,0b
+	bralr
+
+	.size		__insl_ns, .-__insl_ns
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/lib/insl_sw.S linux-2.6.10-rc1-mm3-frv/arch/frv/lib/insl_sw.S
--- /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/lib/insl_sw.S	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/arch/frv/lib/insl_sw.S	2004-11-05 14:13:03.286547882 +0000
@@ -0,0 +1,40 @@
+/* insl_sw.S: input array of 4b words from device port with byte swapping
+ *
+ * Copyright (C) 2003 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * 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.
+ */
+
+
+        .text
+        .p2align	4
+
+###############################################################################
+#
+# void __insl_sw(unsigned int port, void *buf, int n)
+#
+###############################################################################
+        .globl		__insl_sw
+        .type		__insl_sw,@function
+__insl_sw:
+	subi.p		gr9,#1,gr9
+	setlos		#1,gr4
+0:
+	ldi.p		@(gr8,#0),gr5		; get 0xAABBCCDD
+	subicc		gr10,#1,gr10,icc0
+
+	stbu.p		gr5,@(gr9,gr4)		; write 0xDD
+	srli		gr5,#8,gr5
+	stbu.p		gr5,@(gr9,gr4)		; write 0xCC
+	srli		gr5,#8,gr5
+	stbu.p		gr5,@(gr9,gr4)		; write 0xBB
+	srli		gr5,#8,gr5
+	stbu.p		gr5,@(gr9,gr4)		; write 0xAA
+	bhi		icc0,#2,0b
+	bralr
+
+	.size		__insl_sw, .-__insl_sw
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/lib/__lshrdi3.S linux-2.6.10-rc1-mm3-frv/arch/frv/lib/__lshrdi3.S
--- /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/lib/__lshrdi3.S	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/arch/frv/lib/__lshrdi3.S	2004-11-05 14:13:03.289547629 +0000
@@ -0,0 +1,40 @@
+/* __lshrdi3.S:	64-bit logical shift right
+ *
+ * Copyright (C) 2003 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * 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.
+ */
+
+        .text
+        .p2align	4
+
+###############################################################################
+#
+# unsigned long long __lshrdi3(unsigned long long value [GR8:GR9], unsigned by [GR10])
+#
+###############################################################################
+        .globl		__lshrdi3
+        .type		__lshrdi3,@function
+__lshrdi3:
+	andicc.p	gr10,#63,gr10,icc0
+	setlos		#32,gr5
+	andicc.p	gr10,#32,gr0,icc1
+	beqlr		icc0,#0
+	ckeq		icc1,cc4			; cc4 is true if 0<N<32
+
+	# deal with a shift in the range 1<=N<=31
+	csrl.p		gr9,gr10,gr9	,cc4,#1		; LSW >>= N
+	csub		gr5,gr10,gr5	,cc4,#1		; M = 32 - N
+	csll.p		gr8,gr5,gr4	,cc4,#1
+	csrl		gr8,gr10,gr8	,cc4,#1		; MSW >>= N
+	cor.p		gr4,gr9,gr9	,cc4,#1		; LSW |= MSW << M
+
+	# deal with a shift in the range 32<=N<=63
+	csrl		gr8,gr10,gr9	,cc4,#0		; LSW = MSW >> (N & 31 [implicit AND])
+	cor.p		gr0,gr0,gr8	,cc4,#0		; MSW = 0
+	bralr
+	.size		__lshrdi3, .-__lshrdi3
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/lib/Makefile linux-2.6.10-rc1-mm3-frv/arch/frv/lib/Makefile
--- /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/lib/Makefile	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/arch/frv/lib/Makefile	2004-11-05 14:13:03.293547291 +0000
@@ -0,0 +1,8 @@
+#
+# Makefile for FRV-specific library files..
+#
+
+lib-y := \
+	__ashldi3.o __lshrdi3.o __muldi3.o __ashrdi3.o __negdi2.o \
+	checksum.o memcpy.o memset.o atomic-ops.o \
+	outsl_ns.o outsl_sw.o insl_ns.o insl_sw.o cache.o
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/lib/memcpy.S linux-2.6.10-rc1-mm3-frv/arch/frv/lib/memcpy.S
--- /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/lib/memcpy.S	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/arch/frv/lib/memcpy.S	2004-11-05 14:13:03.300546700 +0000
@@ -0,0 +1,135 @@
+/* memcpy.S: optimised assembly memcpy
+ *
+ * Copyright (C) 2003 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * 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.
+ */
+
+
+        .text
+        .p2align	4
+
+###############################################################################
+#
+# void *memcpy(void *to, const char *from, size_t count)
+#
+# - NOTE: must not use any stack. exception detection performs function return
+#         to caller's fixup routine, aborting the remainder of the copy
+#
+###############################################################################
+        .globl		memcpy,__memcpy_end
+        .type		memcpy,@function
+memcpy:
+	or.p		gr8,gr9,gr4
+	orcc		gr10,gr0,gr0,icc3
+	or.p		gr10,gr4,gr4
+	beqlr		icc3,#0
+
+	# optimise based on best common alignment for to, from & count
+	andicc.p	gr4,#0x0f,gr0,icc0
+	setlos		#8,gr11
+	andicc.p	gr4,#0x07,gr0,icc1
+	beq		icc0,#0,memcpy_16
+	andicc.p	gr4,#0x03,gr0,icc0
+	beq		icc1,#0,memcpy_8
+	andicc.p	gr4,#0x01,gr0,icc1
+	beq		icc0,#0,memcpy_4
+	setlos.p	#1,gr11
+	beq		icc1,#0,memcpy_2
+
+	# do byte by byte copy
+	sub.p		gr8,gr11,gr3
+	sub		gr9,gr11,gr9
+0:	ldubu.p		@(gr9,gr11),gr4
+	subicc		gr10,#1,gr10,icc0
+	stbu.p		gr4,@(gr3,gr11)
+	bne		icc0,#2,0b
+	bralr
+
+	# do halfword by halfword copy
+memcpy_2:
+	setlos		#2,gr11
+	sub.p		gr8,gr11,gr3
+	sub		gr9,gr11,gr9
+0:	lduhu.p		@(gr9,gr11),gr4
+	subicc		gr10,#2,gr10,icc0
+	sthu.p		gr4,@(gr3,gr11)
+	bne		icc0,#2,0b
+	bralr
+
+	# do word by word copy
+memcpy_4:
+	setlos		#4,gr11
+	sub.p		gr8,gr11,gr3
+	sub		gr9,gr11,gr9
+0:	ldu.p		@(gr9,gr11),gr4
+	subicc		gr10,#4,gr10,icc0
+	stu.p		gr4,@(gr3,gr11)
+	bne		icc0,#2,0b
+	bralr
+
+	# do double-word by double-word copy
+memcpy_8:
+	sub.p		gr8,gr11,gr3
+	sub		gr9,gr11,gr9
+0:	lddu.p		@(gr9,gr11),gr4
+	subicc		gr10,#8,gr10,icc0
+	stdu.p		gr4,@(gr3,gr11)
+	bne		icc0,#2,0b
+	bralr
+
+	# do quad-word by quad-word copy
+memcpy_16:
+	sub.p		gr8,gr11,gr3
+	sub		gr9,gr11,gr9
+0:	lddu		@(gr9,gr11),gr4
+	lddu.p		@(gr9,gr11),gr6
+	subicc		gr10,#16,gr10,icc0
+	stdu		gr4,@(gr3,gr11)
+	stdu.p		gr6,@(gr3,gr11)
+	bne		icc0,#2,0b
+	bralr
+__memcpy_end:
+
+	.size		memcpy, __memcpy_end-memcpy
+
+###############################################################################
+#
+# copy to/from userspace
+# - return the number of bytes that could not be copied (0 on complete success)
+#
+# long __memcpy_user(void *dst, const void *src, size_t count)
+#
+###############################################################################
+        .globl		__memcpy_user, __memcpy_user_error_lr, __memcpy_user_error_handler
+        .type		__memcpy_user,@function
+__memcpy_user:
+	movsg		lr,gr7
+	subi.p		sp,#8,sp
+	add		gr8,gr10,gr6		; calculate expected end address
+	stdi		gr6,@(sp,#0)
+
+	# abuse memcpy to do the dirty work
+	call		memcpy
+__memcpy_user_error_lr:
+	ldi.p		@(sp,#4),gr7
+	setlos		#0,gr8
+	jmpl.p		@(gr7,gr0)
+	addi		sp,#8,sp
+
+	# deal any exception generated by memcpy
+	# GR8 - memcpy's current dest address
+	# GR11 - memset's step value (index register for store insns)
+__memcpy_user_error_handler:
+	lddi.p		@(sp,#0),gr4		; load GR4 with dst+count, GR5 with ret addr
+	add		gr11,gr3,gr7
+	sub.p		gr4,gr7,gr8
+
+	addi		sp,#8,sp
+	jmpl		@(gr5,gr0)
+
+	.size		__memcpy_user, .-__memcpy_user
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/lib/memset.S linux-2.6.10-rc1-mm3-frv/arch/frv/lib/memset.S
--- /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/lib/memset.S	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/arch/frv/lib/memset.S	2004-11-05 14:13:03.304546362 +0000
@@ -0,0 +1,182 @@
+/* memset.S: optimised assembly memset
+ *
+ * Copyright (C) 2003 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * 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.
+ */
+
+
+        .text
+        .p2align	4
+
+###############################################################################
+#
+# void *memset(void *p, char ch, size_t count)
+#
+# - NOTE: must not use any stack. exception detection performs function return
+#         to caller's fixup routine, aborting the remainder of the set
+#         GR4, GR7, GR8, and GR11 must be managed
+#
+###############################################################################
+        .globl		memset,__memset_end
+        .type		memset,@function
+memset:
+	orcc.p		gr10,gr0,gr5,icc3		; GR5 = count
+	andi		gr9,#0xff,gr9
+	or.p		gr8,gr0,gr4			; GR4 = address
+	beqlr		icc3,#0
+
+	# conditionally write a byte to 2b-align the address
+	setlos.p	#1,gr6
+	andicc		gr4,#1,gr0,icc0
+	ckne		icc0,cc7
+	cstb.p		gr9,@(gr4,gr0)		,cc7,#1
+	csubcc		gr5,gr6,gr5		,cc7,#1	; also set ICC3
+	cadd.p		gr4,gr6,gr4		,cc7,#1
+	beqlr		icc3,#0
+
+	# conditionally write a word to 4b-align the address
+	andicc.p	gr4,#2,gr0,icc0
+	subicc		gr5,#2,gr0,icc1
+	setlos.p	#2,gr6
+	ckne		icc0,cc7
+	slli.p		gr9,#8,gr12			; need to double up the pattern
+	cknc		icc1,cc5
+	or.p		gr9,gr12,gr12
+	andcr		cc7,cc5,cc7
+
+	csth.p		gr12,@(gr4,gr0)		,cc7,#1
+	csubcc		gr5,gr6,gr5		,cc7,#1	; also set ICC3
+	cadd.p		gr4,gr6,gr4		,cc7,#1
+	beqlr		icc3,#0
+
+	# conditionally write a dword to 8b-align the address
+	andicc.p	gr4,#4,gr0,icc0
+	subicc		gr5,#4,gr0,icc1
+	setlos.p	#4,gr6
+	ckne		icc0,cc7
+	slli.p		gr12,#16,gr13			; need to quadruple-up the pattern
+	cknc		icc1,cc5
+	or.p		gr13,gr12,gr12
+	andcr		cc7,cc5,cc7
+
+	cst.p		gr12,@(gr4,gr0)		,cc7,#1
+	csubcc		gr5,gr6,gr5		,cc7,#1	; also set ICC3
+	cadd.p		gr4,gr6,gr4		,cc7,#1
+	beqlr		icc3,#0
+
+	or.p		gr12,gr12,gr13			; need to octuple-up the pattern
+
+	# the address is now 8b-aligned - loop around writing 64b chunks
+	setlos		#8,gr7
+	subi.p		gr4,#8,gr4			; store with update index does weird stuff
+	setlos		#64,gr6
+
+	subicc		gr5,#64,gr0,icc0
+0:	cknc		icc0,cc7
+	cstdu		gr12,@(gr4,gr7)		,cc7,#1
+	cstdu		gr12,@(gr4,gr7)		,cc7,#1
+	cstdu		gr12,@(gr4,gr7)		,cc7,#1
+	cstdu		gr12,@(gr4,gr7)		,cc7,#1
+	cstdu		gr12,@(gr4,gr7)		,cc7,#1
+	cstdu.p		gr12,@(gr4,gr7)		,cc7,#1
+	csubcc		gr5,gr6,gr5		,cc7,#1	; also set ICC3
+	cstdu.p		gr12,@(gr4,gr7)		,cc7,#1
+	subicc		gr5,#64,gr0,icc0
+	cstdu.p		gr12,@(gr4,gr7)		,cc7,#1
+	beqlr		icc3,#0
+	bnc		icc0,#2,0b
+
+	# now do 32-byte remnant
+	subicc.p	gr5,#32,gr0,icc0
+	setlos		#32,gr6
+	cknc		icc0,cc7
+	cstdu.p		gr12,@(gr4,gr7)		,cc7,#1
+	csubcc		gr5,gr6,gr5		,cc7,#1	; also set ICC3
+	cstdu.p		gr12,@(gr4,gr7)		,cc7,#1
+	setlos		#16,gr6
+	cstdu.p		gr12,@(gr4,gr7)		,cc7,#1
+	subicc		gr5,#16,gr0,icc0
+	cstdu.p		gr12,@(gr4,gr7)		,cc7,#1
+	beqlr		icc3,#0
+
+	# now do 16-byte remnant
+	cknc		icc0,cc7
+	cstdu.p		gr12,@(gr4,gr7)		,cc7,#1
+	csubcc		gr5,gr6,gr5		,cc7,#1	; also set ICC3
+	cstdu.p		gr12,@(gr4,gr7)		,cc7,#1
+	beqlr		icc3,#0
+
+	# now do 8-byte remnant
+	subicc		gr5,#8,gr0,icc1
+	cknc		icc1,cc7
+	cstdu.p		gr12,@(gr4,gr7)		,cc7,#1
+	csubcc		gr5,gr7,gr5		,cc7,#1	; also set ICC3
+	setlos.p	#4,gr7
+	beqlr		icc3,#0
+
+	# now do 4-byte remnant
+	subicc		gr5,#4,gr0,icc0
+	addi.p		gr4,#4,gr4
+	cknc		icc0,cc7
+	cstu.p		gr12,@(gr4,gr7)		,cc7,#1
+	csubcc		gr5,gr7,gr5		,cc7,#1	; also set ICC3
+	subicc.p	gr5,#2,gr0,icc1
+	beqlr		icc3,#0
+
+	# now do 2-byte remnant
+	setlos		#2,gr7
+	addi.p		gr4,#2,gr4
+	cknc		icc1,cc7
+	csthu.p		gr12,@(gr4,gr7)		,cc7,#1
+	csubcc		gr5,gr7,gr5		,cc7,#1	; also set ICC3
+	subicc.p	gr5,#1,gr0,icc0
+	beqlr		icc3,#0
+
+	# now do 1-byte remnant
+	setlos		#0,gr7
+	addi.p		gr4,#2,gr4
+	cknc		icc0,cc7
+	cstb.p		gr12,@(gr4,gr0)		,cc7,#1
+	bralr
+__memset_end:
+
+	.size		memset, __memset_end-memset
+
+###############################################################################
+#
+# clear memory in userspace
+# - return the number of bytes that could not be cleared (0 on complete success)
+#
+# long __memset_user(void *p, size_t count)
+#
+###############################################################################
+        .globl		__memset_user, __memset_user_error_lr, __memset_user_error_handler
+        .type		__memset_user,@function
+__memset_user:
+	movsg		lr,gr11
+
+	# abuse memset to do the dirty work
+	or.p		gr9,gr9,gr10
+	setlos		#0,gr9
+	call		memset
+__memset_user_error_lr:
+	jmpl.p		@(gr11,gr0)
+	setlos		#0,gr8
+
+	# deal any exception generated by memset
+	# GR4  - memset's address tracking pointer
+	# GR7  - memset's step value (index register for store insns)
+	# GR8  - memset's original start address
+	# GR10 - memset's original count
+__memset_user_error_handler:
+	add.p		gr4,gr7,gr4
+	add		gr8,gr10,gr8
+	jmpl.p		@(gr11,gr0)
+	sub		gr8,gr4,gr8		; we return the amount left uncleared
+
+	.size		__memset_user, .-__memset_user
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/lib/__muldi3.S linux-2.6.10-rc1-mm3-frv/arch/frv/lib/__muldi3.S
--- /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/lib/__muldi3.S	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/arch/frv/lib/__muldi3.S	2004-11-05 14:13:03.308546024 +0000
@@ -0,0 +1,32 @@
+/* __muldi3.S:	64-bit multiply
+ *
+ * Copyright (C) 2003 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * 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.
+ */
+
+        .text
+        .p2align	4
+
+###############################################################################
+#
+# unsigned long long __muldi3(unsigned long long x [GR8:GR9],
+#                             unsigned long long y [GR10:GR11])
+#
+###############################################################################
+        .globl		__muldi3, __mulll, __umulll
+        .type		__muldi3,@function
+__muldi3:
+__mulll:
+__umulll:
+	umul		gr8,gr11,gr4		; GR4:GR5 = x.MSW * y.LSW
+	umul		gr9,gr10,gr6		; GR6:GR7 = x.LSW * y.MSW
+	umul.p		gr9,gr11,gr8		; GR8:GR9 = x.LSW * y.LSW
+	add		gr5,gr7,gr5
+	add.p		gr8,gr5,gr8		; GR8 += GR5 + GR7
+	bralr
+	.size		__muldi3, .-__muldi3
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/lib/__negdi2.S linux-2.6.10-rc1-mm3-frv/arch/frv/lib/__negdi2.S
--- /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/lib/__negdi2.S	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/arch/frv/lib/__negdi2.S	2004-11-05 14:13:03.312545687 +0000
@@ -0,0 +1,28 @@
+/* __negdi2.S: 64-bit negate
+ *
+ * Copyright (C) 2003 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * 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.
+ */
+
+
+        .text
+        .p2align	4
+
+###############################################################################
+#
+# unsigned long long __negdi2(unsigned long long value [GR8:GR9])
+#
+###############################################################################
+        .globl		__negdi2
+        .type		__negdi2,@function
+__negdi2:
+	subcc		gr0,gr9,gr9,icc0
+	subx		gr0,gr8,gr8,icc0
+	bralr
+	.size		__negdi2, .-__negdi2
+
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/lib/outsl_ns.S linux-2.6.10-rc1-mm3-frv/arch/frv/lib/outsl_ns.S
--- /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/lib/outsl_ns.S	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/arch/frv/lib/outsl_ns.S	2004-11-05 14:13:03.315545433 +0000
@@ -0,0 +1,59 @@
+/* outsl_ns.S: output array of 4b words to device without byte swapping
+ *
+ * Copyright (C) 2003 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * 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.
+ */
+
+
+        .text
+        .p2align	4
+
+###############################################################################
+#
+# void __outsl_ns(unsigned int port, const void *buf, int n)
+#
+###############################################################################
+        .globl		__outsl_ns
+        .type		__outsl_ns,@function
+__outsl_ns:
+	andicc.p	gr9,#3,gr0,icc0
+	setlos		#4,gr4
+	bne		icc0,#0,__outsl_ns_misaligned
+	subi		gr9,#4,gr9
+0:
+	ldu.p		@(gr9,gr4),gr5
+	subicc		gr10,#1,gr10,icc0
+	sti.p		gr5,@(gr8,#0)
+	bhi		icc0,#2,0b
+
+	membar
+	bralr
+
+__outsl_ns_misaligned:
+	subi.p		gr9,#1,gr9
+	setlos		#1,gr4
+0:
+	ldubu		@(gr9,gr4),gr5
+	ldubu.p		@(gr9,gr4),gr6
+	slli		gr5,#8,gr5
+	ldubu.p		@(gr9,gr4),gr7
+	or		gr5,gr6,gr5
+	ldubu.p		@(gr9,gr4),gr6
+	slli		gr5,#16,gr5
+	slli.p		gr7,#8,gr7
+	or		gr5,gr6,gr5
+	subicc.p	gr10,#1,gr10,icc0
+	or		gr5,gr7,gr5
+
+	sti.p		gr5,@(gr8,#0)
+	bhi		icc0,#2,0b
+
+	membar
+	bralr
+
+	.size		__outsl_ns, .-__outsl_ns
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/lib/outsl_sw.S linux-2.6.10-rc1-mm3-frv/arch/frv/lib/outsl_sw.S
--- /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/lib/outsl_sw.S	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/arch/frv/lib/outsl_sw.S	2004-11-05 14:13:03.319545095 +0000
@@ -0,0 +1,45 @@
+/* outsl_ns.S: output array of 4b words to device with byte swapping
+ *
+ * Copyright (C) 2003 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * 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.
+ */
+
+
+        .text
+        .p2align	4
+
+###############################################################################
+#
+# void __outsl_sw(unsigned int port, const void *buf, int n)
+#
+###############################################################################
+        .globl		__outsl_sw
+        .type		__outsl_sw,@function
+__outsl_sw:
+	subi.p		gr9,#1,gr9
+	setlos		#1,gr4
+0:
+	ldubu		@(gr9,gr4),gr5
+	ldubu		@(gr9,gr4),gr6
+	slli		gr6,#8,gr6
+	ldubu.p		@(gr9,gr4),gr7
+	or		gr5,gr6,gr5
+	ldubu.p		@(gr9,gr4),gr6
+	slli		gr7,#16,gr7
+	slli.p		gr6,#24,gr6
+	or		gr5,gr7,gr5
+	subicc.p	gr10,#1,gr10,icc0
+	or		gr5,gr6,gr5
+
+	sti.p		gr5,@(gr8,#0)
+	bhi		icc0,#2,0b
+
+	membar
+	bralr
+
+	.size		__outsl_sw, .-__outsl_sw

^ permalink raw reply	[flat|nested] 87+ messages in thread

* [PATCH 10/20] FRV: Fujitsu FR-V CPU arch implementation part 8
  2004-11-08 14:34 [PATCH 1/20] FRV: Fujitsu FR-V CPU arch maintainer record dhowells
                   ` (8 preceding siblings ...)
  2004-11-08 14:34 ` [PATCH 11/20] FRV: Fujitsu FR-V CPU arch implementation part 9 dhowells
@ 2004-11-08 14:34 ` dhowells
  2004-11-08 14:34 ` [PATCH 15/20] FRV: Fujitsu FR-V arch include files dhowells
                   ` (6 subsequent siblings)
  16 siblings, 0 replies; 87+ messages in thread
From: dhowells @ 2004-11-08 14:34 UTC (permalink / raw)
  To: torvalds, akpm, davidm; +Cc: linux-kernel, uclinux-dev

The attached patches provides part 8 of an architecture implementation
for the Fujitsu FR-V CPU series, configurably as Linux or uClinux.

Signed-Off-By: dhowells@redhat.com
---
diffstat frv-arch_8-2610rc1mm3.diff
 Makefile  |    5 
 pci-dma.c |  124 ++++++++++++++++
 pci-frv.c |  363 ++++++++++++++++++++++++++++++++++++++++++++++++
 pci-frv.h |   47 ++++++
 pci-irq.c |   70 +++++++++
 pci-vdk.c |  462 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 6 files changed, 1071 insertions(+)

diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/mb93090-mb00/Makefile linux-2.6.10-rc1-mm3-frv/arch/frv/mb93090-mb00/Makefile
--- /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/mb93090-mb00/Makefile	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/arch/frv/mb93090-mb00/Makefile	2004-11-05 14:13:03.327544420 +0000
@@ -0,0 +1,5 @@
+#
+# Makefile for the MB93090-MB00 motherboard stuff
+#
+
+obj-$(CONFIG_PCI) := pci-frv.o pci-dma.o pci-irq.o pci-vdk.o
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/mb93090-mb00/pci-dma.c linux-2.6.10-rc1-mm3-frv/arch/frv/mb93090-mb00/pci-dma.c
--- /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/mb93090-mb00/pci-dma.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/arch/frv/mb93090-mb00/pci-dma.c	2004-11-05 14:13:03.331544082 +0000
@@ -0,0 +1,124 @@
+/*
+ * Dynamic DMA mapping support.
+ *
+ * On i386 there is no hardware dynamic DMA address translation,
+ * so consistent alloc/free are merely page allocation/freeing.
+ * The rest of the dynamic DMA mapping interface is implemented
+ * in asm/pci.h.
+ */
+
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/dma-mapping.h>
+#include <linux/list.h>
+#include <linux/pci.h>
+#include <asm/io.h>
+
+#ifdef CONFIG_MMU
+
+void *dma_alloc_coherent(struct device *hwdev, size_t size, dma_addr_t *dma_handle, int gfp)
+{
+	void *ret;
+
+	ret = consistent_alloc(gfp, size, dma_handle);
+	if (ret)
+		memset(ret, 0, size);
+
+	return ret;
+}
+
+void dma_free_coherent(struct device *hwdev, size_t size, void *vaddr, dma_addr_t dma_handle)
+{
+	consistent_free(vaddr);
+}
+
+
+#else /* CONFIG_MMU */
+
+#if 1
+#define DMA_SRAM_START	dma_coherent_mem_start
+#define DMA_SRAM_END	dma_coherent_mem_end
+#else // Use video RAM on Matrox
+#define DMA_SRAM_START	0xe8900000
+#define DMA_SRAM_END	0xe8a00000
+#endif
+
+struct dma_alloc_record {
+	struct list_head	list;
+	unsigned long		ofs;
+	unsigned long		len;
+};
+
+static spinlock_t dma_alloc_lock = SPIN_LOCK_UNLOCKED;
+static LIST_HEAD(dma_alloc_list);
+
+void *dma_alloc_coherent(struct device *hwdev, size_t size, dma_addr_t *dma_handle, int gfp)
+{
+	struct dma_alloc_record *new;
+	struct list_head *this = &dma_alloc_list;
+	unsigned long flags;
+	unsigned long start = DMA_SRAM_START;
+	unsigned long end;
+
+	if (!DMA_SRAM_START) {
+		printk("%s called without any DMA area reserved!\n", __func__);
+		return NULL;
+	}
+
+	new = kmalloc(sizeof (*new), GFP_ATOMIC);
+	if (!new)
+		return NULL;
+
+	/* Round up to a reasonable alignment */
+	new->len = (size + 31) & ~31;
+
+	spin_lock_irqsave(&dma_alloc_lock, flags);
+	
+	list_for_each (this, &dma_alloc_list) {
+		struct dma_alloc_record *this_r = list_entry(this, struct dma_alloc_record, list);
+		end = this_r->ofs;
+
+		if (end - start >= size)
+			goto gotone;
+
+		start = this_r->ofs + this_r->len;
+	}
+	/* Reached end of list. */
+	end = DMA_SRAM_END;
+	this = &dma_alloc_list;
+
+	if (end - start >= size) {
+	gotone:
+		new->ofs = start;
+		list_add_tail(&new->list, this);
+		spin_unlock_irqrestore(&dma_alloc_lock, flags);
+
+		*dma_handle = start;
+		return (void *)start;
+	}
+
+	kfree(new);
+	spin_unlock_irqrestore(&dma_alloc_lock, flags);
+	return NULL;
+}
+
+void dma_free_coherent(struct device *hwdev, size_t size, void *vaddr, dma_addr_t dma_handle)
+{
+	struct dma_alloc_record *rec;
+	unsigned long flags;
+
+	spin_lock_irqsave(&dma_alloc_lock, flags);
+
+	list_for_each_entry(rec, &dma_alloc_list, list) {
+		if (rec->ofs == dma_handle) {
+			list_del(&rec->list);
+			kfree(rec);
+			spin_unlock_irqrestore(&dma_alloc_lock, flags);
+			return;
+		}
+	}
+	spin_unlock_irqrestore(&dma_alloc_lock, flags);
+	BUG();
+}
+
+#endif /* CONFIG_MMU */
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/mb93090-mb00/pci-frv.c linux-2.6.10-rc1-mm3-frv/arch/frv/mb93090-mb00/pci-frv.c
--- /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/mb93090-mb00/pci-frv.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/arch/frv/mb93090-mb00/pci-frv.c	2004-11-05 14:13:03.337543575 +0000
@@ -0,0 +1,363 @@
+/*
+ *	Low-Level PCI Access for FRV machines
+ *
+ * Copyright 1993, 1994 Drew Eckhardt
+ *      Visionary Computing
+ *      (Unix and Linux consulting and custom programming)
+ *      Drew@Colorado.EDU
+ *      +1 (303) 786-7975
+ *
+ * Drew's work was sponsored by:
+ *	iX Multiuser Multitasking Magazine
+ *	Hannover, Germany
+ *	hm@ix.de
+ *
+ * Copyright 1997--2000 Martin Mares <mj@ucw.cz>
+ *
+ * For more information, please consult the following manuals (look at
+ * http://www.pcisig.com/ for how to get them):
+ *
+ * PCI BIOS Specification
+ * PCI Local Bus Specification
+ * PCI to PCI Bridge Specification
+ * PCI System Design Guide
+ *
+ *
+ * CHANGELOG :
+ * Jun 17, 1994 : Modified to accommodate the broken pre-PCI BIOS SPECIFICATION
+ *	Revision 2.0 present on <thys@dennis.ee.up.ac.za>'s ASUS mainboard.
+ *
+ * Jan 5,  1995 : Modified to probe PCI hardware at boot time by Frederic
+ *     Potter, potter@cao-vlsi.ibp.fr
+ *
+ * Jan 10, 1995 : Modified to store the information about configured pci
+ *      devices into a list, which can be accessed via /proc/pci by
+ *      Curtis Varner, cvarner@cs.ucr.edu
+ *
+ * Jan 12, 1995 : CPU-PCI bridge optimization support by Frederic Potter.
+ *	Alpha version. Intel & UMC chipset support only.
+ *
+ * Apr 16, 1995 : Source merge with the DEC Alpha PCI support. Most of the code
+ *	moved to drivers/pci/pci.c.
+ *
+ * Dec 7, 1996  : Added support for direct configuration access of boards
+ *      with Intel compatible access schemes (tsbogend@alpha.franken.de)
+ *
+ * Feb 3, 1997  : Set internal functions to static, save/restore flags
+ *	avoid dead locks reading broken PCI BIOS, werner@suse.de 
+ *
+ * Apr 26, 1997 : Fixed case when there is BIOS32, but not PCI BIOS
+ *	(mj@atrey.karlin.mff.cuni.cz)
+ *
+ * May 7,  1997 : Added some missing cli()'s. [mj]
+ * 
+ * Jun 20, 1997 : Corrected problems in "conf1" type accesses.
+ *      (paubert@iram.es)
+ *
+ * Aug 2,  1997 : Split to PCI BIOS handling and direct PCI access parts
+ *	and cleaned it up...     Martin Mares <mj@atrey.karlin.mff.cuni.cz>
+ *
+ * Feb 6,  1998 : No longer using BIOS to find devices and device classes. [mj]
+ *
+ * May 1,  1998 : Support for peer host bridges. [mj]
+ *
+ * Jun 19, 1998 : Changed to use spinlocks, so that PCI configuration space
+ *	can be accessed from interrupts even on SMP systems. [mj]
+ *
+ * August  1998 : Better support for peer host bridges and more paranoid
+ *	checks for direct hardware access. Ugh, this file starts to look as
+ *	a large gallery of common hardware bug workarounds (watch the comments)
+ *	-- the PCI specs themselves are sane, but most implementors should be
+ *	hit hard with \hammer scaled \magstep5. [mj]
+ *
+ * Jan 23, 1999 : More improvements to peer host bridge logic. i450NX fixup. [mj]
+ *
+ * Feb 8,  1999 : Added UM8886BF I/O address fixup. [mj]
+ *
+ * August  1999 : New resource management and configuration access stuff. [mj]
+ *
+ * Sep 19, 1999 : Use PCI IRQ routing tables for detection of peer host bridges.
+ *		  Based on ideas by Chris Frantz and David Hinds. [mj]
+ *
+ * Sep 28, 1999 : Handle unreported/unassigned IRQs. Thanks to Shuu Yamaguchi
+ *		  for a lot of patience during testing. [mj]
+ *
+ * Oct  8, 1999 : Split to pci-i386.c, pci-pc.c and pci-visws.c. [mj]
+ */
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/errno.h>
+
+#include "pci-frv.h"
+
+#if 0
+void
+pcibios_update_resource(struct pci_dev *dev, struct resource *root,
+			struct resource *res, int resource)
+{
+	u32 new, check;
+	int reg;
+
+	new = res->start | (res->flags & PCI_REGION_FLAG_MASK);
+	if (resource < 6) {
+		reg = PCI_BASE_ADDRESS_0 + 4*resource;
+	} else if (resource == PCI_ROM_RESOURCE) {
+		res->flags |= PCI_ROM_ADDRESS_ENABLE;
+		new |= PCI_ROM_ADDRESS_ENABLE;
+		reg = dev->rom_base_reg;
+	} else {
+		/* Somebody might have asked allocation of a non-standard resource */
+		return;
+	}
+	
+	pci_write_config_dword(dev, reg, new);
+	pci_read_config_dword(dev, reg, &check);
+	if ((new ^ check) & ((new & PCI_BASE_ADDRESS_SPACE_IO) ? PCI_BASE_ADDRESS_IO_MASK : PCI_BASE_ADDRESS_MEM_MASK)) {
+		printk(KERN_ERR "PCI: Error while updating region "
+		       "%s/%d (%08x != %08x)\n", dev->slot_name, resource,
+		       new, check);
+	}
+}
+#endif
+
+/*
+ * We need to avoid collisions with `mirrored' VGA ports
+ * and other strange ISA hardware, so we always want the
+ * addresses to be allocated in the 0x000-0x0ff region
+ * modulo 0x400.
+ *
+ * Why? Because some silly external IO cards only decode
+ * the low 10 bits of the IO address. The 0x00-0xff region
+ * is reserved for motherboard devices that decode all 16
+ * bits, so it's ok to allocate at, say, 0x2800-0x28ff,
+ * but we want to try to avoid allocating at 0x2900-0x2bff
+ * which might have be mirrored at 0x0100-0x03ff..
+ */
+void
+pcibios_align_resource(void *data, struct resource *res,
+		       unsigned long size, unsigned long align)
+{
+	if (res->flags & IORESOURCE_IO) {
+		unsigned long start = res->start;
+
+		if (start & 0x300) {
+			start = (start + 0x3ff) & ~0x3ff;
+			res->start = start;
+		}
+	}
+}
+
+
+/*
+ *  Handle resources of PCI devices.  If the world were perfect, we could
+ *  just allocate all the resource regions and do nothing more.  It isn't.
+ *  On the other hand, we cannot just re-allocate all devices, as it would
+ *  require us to know lots of host bridge internals.  So we attempt to
+ *  keep as much of the original configuration as possible, but tweak it
+ *  when it's found to be wrong.
+ *
+ *  Known BIOS problems we have to work around:
+ *	- I/O or memory regions not configured
+ *	- regions configured, but not enabled in the command register
+ *	- bogus I/O addresses above 64K used
+ *	- expansion ROMs left enabled (this may sound harmless, but given
+ *	  the fact the PCI specs explicitly allow address decoders to be
+ *	  shared between expansion ROMs and other resource regions, it's
+ *	  at least dangerous)
+ *
+ *  Our solution:
+ *	(1) Allocate resources for all buses behind PCI-to-PCI bridges.
+ *	    This gives us fixed barriers on where we can allocate.
+ *	(2) Allocate resources for all enabled devices.  If there is
+ *	    a collision, just mark the resource as unallocated. Also
+ *	    disable expansion ROMs during this step.
+ *	(3) Try to allocate resources for disabled devices.  If the
+ *	    resources were assigned correctly, everything goes well,
+ *	    if they weren't, they won't disturb allocation of other
+ *	    resources.
+ *	(4) Assign new addresses to resources which were either
+ *	    not configured at all or misconfigured.  If explicitly
+ *	    requested by the user, configure expansion ROM address
+ *	    as well.
+ */
+
+static void __init pcibios_allocate_bus_resources(struct list_head *bus_list)
+{
+	struct list_head *ln;
+	struct pci_bus *bus;
+	struct pci_dev *dev;
+	int idx;
+	struct resource *r, *pr;
+
+	/* Depth-First Search on bus tree */
+	for (ln=bus_list->next; ln != bus_list; ln=ln->next) {
+		bus = pci_bus_b(ln);
+		if ((dev = bus->self)) {
+			for (idx = PCI_BRIDGE_RESOURCES; idx < PCI_NUM_RESOURCES; idx++) {
+				r = &dev->resource[idx];
+				if (!r->start)
+					continue;
+				pr = pci_find_parent_resource(dev, r);
+				if (!pr || request_resource(pr, r) < 0)
+					printk(KERN_ERR "PCI: Cannot allocate resource region %d of bridge %s\n", idx, dev->slot_name);
+			}
+		}
+		pcibios_allocate_bus_resources(&bus->children);
+	}
+}
+
+static void __init pcibios_allocate_resources(int pass)
+{
+	struct pci_dev *dev = NULL;
+	int idx, disabled;
+	u16 command;
+	struct resource *r, *pr;
+
+	while (dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev),
+	       dev != NULL
+	       ) {
+		pci_read_config_word(dev, PCI_COMMAND, &command);
+		for(idx = 0; idx < 6; idx++) {
+			r = &dev->resource[idx];
+			if (r->parent)		/* Already allocated */
+				continue;
+			if (!r->start)		/* Address not assigned at all */
+				continue;
+			if (r->flags & IORESOURCE_IO)
+				disabled = !(command & PCI_COMMAND_IO);
+			else
+				disabled = !(command & PCI_COMMAND_MEMORY);
+			if (pass == disabled) {
+				DBG("PCI: Resource %08lx-%08lx (f=%lx, d=%d, p=%d)\n",
+				    r->start, r->end, r->flags, disabled, pass);
+				pr = pci_find_parent_resource(dev, r);
+				if (!pr || request_resource(pr, r) < 0) {
+					printk(KERN_ERR "PCI: Cannot allocate resource region %d of device %s\n", idx, pci_name(dev));
+					/* We'll assign a new address later */
+					r->end -= r->start;
+					r->start = 0;
+				}
+			}
+		}
+		if (!pass) {
+			r = &dev->resource[PCI_ROM_RESOURCE];
+			if (r->flags & PCI_ROM_ADDRESS_ENABLE) {
+				/* Turn the ROM off, leave the resource region, but keep it unregistered. */
+				u32 reg;
+				DBG("PCI: Switching off ROM of %s\n", pci_name(dev));
+				r->flags &= ~PCI_ROM_ADDRESS_ENABLE;
+				pci_read_config_dword(dev, dev->rom_base_reg, &reg);
+				pci_write_config_dword(dev, dev->rom_base_reg, reg & ~PCI_ROM_ADDRESS_ENABLE);
+			}
+		}
+	}
+}
+
+static void __init pcibios_assign_resources(void)
+{
+	struct pci_dev *dev = NULL;
+	int idx;
+	struct resource *r;
+
+	while (dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev),
+	       dev != NULL
+	       ) {
+		int class = dev->class >> 8;
+
+		/* Don't touch classless devices and host bridges */
+		if (!class || class == PCI_CLASS_BRIDGE_HOST)
+			continue;
+
+		for(idx=0; idx<6; idx++) {
+			r = &dev->resource[idx];
+
+			/*
+			 *  Don't touch IDE controllers and I/O ports of video cards!
+			 */
+			if ((class == PCI_CLASS_STORAGE_IDE && idx < 4) ||
+			    (class == PCI_CLASS_DISPLAY_VGA && (r->flags & IORESOURCE_IO)))
+				continue;
+
+			/*
+			 *  We shall assign a new address to this resource, either because
+			 *  the BIOS forgot to do so or because we have decided the old
+			 *  address was unusable for some reason.
+			 */
+			if (!r->start && r->end)
+				pci_assign_resource(dev, idx);
+		}
+
+		if (pci_probe & PCI_ASSIGN_ROMS) {
+			r = &dev->resource[PCI_ROM_RESOURCE];
+			r->end -= r->start;
+			r->start = 0;
+			if (r->end)
+				pci_assign_resource(dev, PCI_ROM_RESOURCE);
+		}
+	}
+}
+
+void __init pcibios_resource_survey(void)
+{
+	DBG("PCI: Allocating resources\n");
+	pcibios_allocate_bus_resources(&pci_root_buses);
+	pcibios_allocate_resources(0);
+	pcibios_allocate_resources(1);
+	pcibios_assign_resources();
+}
+
+int pcibios_enable_resources(struct pci_dev *dev, int mask)
+{
+	u16 cmd, old_cmd;
+	int idx;
+	struct resource *r;
+
+	pci_read_config_word(dev, PCI_COMMAND, &cmd);
+	old_cmd = cmd;
+	for(idx=0; idx<6; idx++) {
+		/* Only set up the requested stuff */
+		if (!(mask & (1<<idx)))
+			continue;
+			
+		r = &dev->resource[idx];
+		if (!r->start && r->end) {
+			printk(KERN_ERR "PCI: Device %s not available because of resource collisions\n", pci_name(dev));
+			return -EINVAL;
+		}
+		if (r->flags & IORESOURCE_IO)
+			cmd |= PCI_COMMAND_IO;
+		if (r->flags & IORESOURCE_MEM)
+			cmd |= PCI_COMMAND_MEMORY;
+	}
+	if (dev->resource[PCI_ROM_RESOURCE].start)
+		cmd |= PCI_COMMAND_MEMORY;
+	if (cmd != old_cmd) {
+		printk("PCI: Enabling device %s (%04x -> %04x)\n", pci_name(dev), old_cmd, cmd);
+		pci_write_config_word(dev, PCI_COMMAND, cmd);
+	}
+	return 0;
+}
+
+/*
+ *  If we set up a device for bus mastering, we need to check the latency
+ *  timer as certain crappy BIOSes forget to set it properly.
+ */
+unsigned int pcibios_max_latency = 255;
+
+void pcibios_set_master(struct pci_dev *dev)
+{
+	u8 lat;
+	pci_read_config_byte(dev, PCI_LATENCY_TIMER, &lat);
+	if (lat < 16)
+		lat = (64 <= pcibios_max_latency) ? 64 : pcibios_max_latency;
+	else if (lat > pcibios_max_latency)
+		lat = pcibios_max_latency;
+	else
+		return;
+	printk(KERN_DEBUG "PCI: Setting latency timer of device %s to %d\n", pci_name(dev), lat);
+	pci_write_config_byte(dev, PCI_LATENCY_TIMER, lat);
+}
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/mb93090-mb00/pci-frv.h linux-2.6.10-rc1-mm3-frv/arch/frv/mb93090-mb00/pci-frv.h
--- /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/mb93090-mb00/pci-frv.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/arch/frv/mb93090-mb00/pci-frv.h	2004-11-05 14:13:03.340543322 +0000
@@ -0,0 +1,47 @@
+/*
+ *	Low-Level PCI Access for FRV machines.
+ *
+ *	(c) 1999 Martin Mares <mj@ucw.cz>
+ */
+
+#include <asm/sections.h>
+
+#undef DEBUG
+
+#ifdef DEBUG
+#define DBG(x...) printk(x)
+#else
+#define DBG(x...)
+#endif
+
+#define PCI_PROBE_BIOS		0x0001
+#define PCI_PROBE_CONF1		0x0002
+#define PCI_PROBE_CONF2		0x0004
+#define PCI_NO_SORT		0x0100
+#define PCI_BIOS_SORT		0x0200
+#define PCI_NO_CHECKS		0x0400
+#define PCI_ASSIGN_ROMS		0x1000
+#define PCI_BIOS_IRQ_SCAN	0x2000
+#define PCI_ASSIGN_ALL_BUSSES	0x4000
+
+extern unsigned int __nongpreldata pci_probe;
+
+/* pci-frv.c */
+
+extern unsigned int pcibios_max_latency;
+
+void pcibios_resource_survey(void);
+int pcibios_enable_resources(struct pci_dev *, int);
+
+/* pci-vdk.c */
+
+extern int __nongpreldata pcibios_last_bus;
+extern struct pci_bus *__nongpreldata pci_root_bus;
+extern struct pci_ops *__nongpreldata pci_root_ops;
+
+/* pci-irq.c */
+extern unsigned int pcibios_irq_mask;
+
+void pcibios_irq_init(void);
+void pcibios_fixup_irqs(void);
+void pcibios_enable_irq(struct pci_dev *dev);
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/mb93090-mb00/pci-irq.c linux-2.6.10-rc1-mm3-frv/arch/frv/mb93090-mb00/pci-irq.c
--- /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/mb93090-mb00/pci-irq.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/arch/frv/mb93090-mb00/pci-irq.c	2004-11-05 14:13:03.344542984 +0000
@@ -0,0 +1,70 @@
+/* pci-irq.c: PCI IRQ routing on the FRV motherboard
+ *
+ * Copyright (C) 2003 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ * derived from: arch/i386/kernel/pci-irq.c: (c) 1999--2000 Martin Mares <mj@suse.cz>
+ */
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+
+#include <asm/io.h>
+#include <asm/smp.h>
+#include <asm/irq-routing.h>
+
+#include "pci-frv.h"
+
+/*
+ *	DEVICE	DEVNO	INT#A	INT#B	INT#C	INT#D
+ *	=======	=======	=======	=======	=======	=======
+ *	MB86943	0	fpga.10	-	-	-
+ *	RTL8029	16	fpga.12	-	-	-
+ *	SLOT 1	19	fpga.6	fpga.5	fpga.4	fpga.3
+ *	SLOT 2	18	fpga.5	fpga.4	fpga.3	fpga.6
+ *	SLOT 3	17	fpga.4	fpga.3	fpga.6	fpga.5
+ *
+ */
+
+static const uint8_t __initdata pci_bus0_irq_routing[32][4] = {
+	[0 ] {	IRQ_FPGA_MB86943_PCI_INTA },
+	[16] {	IRQ_FPGA_RTL8029_INTA },
+	[17] {	IRQ_FPGA_PCI_INTC, IRQ_FPGA_PCI_INTD, IRQ_FPGA_PCI_INTA, IRQ_FPGA_PCI_INTB },
+	[18] {	IRQ_FPGA_PCI_INTB, IRQ_FPGA_PCI_INTC, IRQ_FPGA_PCI_INTD, IRQ_FPGA_PCI_INTA },
+	[19] {	IRQ_FPGA_PCI_INTA, IRQ_FPGA_PCI_INTB, IRQ_FPGA_PCI_INTC, IRQ_FPGA_PCI_INTD },
+};
+
+void __init pcibios_irq_init(void)
+{
+}
+
+void __init pcibios_fixup_irqs(void)
+{
+	struct pci_dev *dev = NULL;
+	uint8_t line, pin;
+
+	while (dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev),
+	       dev != NULL
+	       ) {
+		pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
+		if (pin) {
+			dev->irq = pci_bus0_irq_routing[PCI_SLOT(dev->devfn)][pin - 1];
+			pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
+		}
+		pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &line);
+	}
+}
+
+void __init pcibios_penalize_isa_irq(int irq)
+{
+}
+
+void pcibios_enable_irq(struct pci_dev *dev)
+{
+	pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
+}
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/mb93090-mb00/pci-vdk.c linux-2.6.10-rc1-mm3-frv/arch/frv/mb93090-mb00/pci-vdk.c
--- /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/mb93090-mb00/pci-vdk.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/arch/frv/mb93090-mb00/pci-vdk.c	2004-11-05 14:13:03.352542308 +0000
@@ -0,0 +1,462 @@
+/* pci-vdk.c: MB93090-MB00 (VDK) PCI support
+ *
+ * Copyright (C) 2003, 2004 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * 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.
+ */
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+
+#include <asm/segment.h>
+#include <asm/io.h>
+#include <asm/mb-regs.h>
+#include <asm/mb86943a.h>
+#include "pci-frv.h"
+
+unsigned int __nongpreldata pci_probe = 1;
+
+int  __nongpreldata pcibios_last_bus = -1;
+struct pci_bus *__nongpreldata pci_root_bus;
+struct pci_ops *__nongpreldata pci_root_ops;
+
+/*
+ * Functions for accessing PCI configuration space
+ */
+
+#define CONFIG_CMD(bus, dev, where) \
+	(0x80000000 | (bus->number << 16) | (devfn << 8) | (where & ~3))
+
+#define __set_PciCfgAddr(A) writel((A), (volatile void __iomem *) __region_CS1 + 0x80)
+
+#define __get_PciCfgDataB(A) readb((volatile void __iomem *) __region_CS1 + 0x88 + ((A) & 3))
+#define __get_PciCfgDataW(A) readw((volatile void __iomem *) __region_CS1 + 0x88 + ((A) & 2))
+#define __get_PciCfgDataL(A) readl((volatile void __iomem *) __region_CS1 + 0x88)
+
+#define __set_PciCfgDataB(A,V) writeb((V), (volatile void __iomem *) __region_CS1 + 0x88 + ((A) & 3))
+#define __set_PciCfgDataW(A,V) writew((V), (volatile void __iomem *) __region_CS1 + 0x88 + ((A) & 2))
+#define __set_PciCfgDataL(A,V) writel((V), (volatile void __iomem *) __region_CS1 + 0x88)
+
+#define __get_PciBridgeDataB(A) readb((volatile void __iomem *) __region_CS1 + 0x800 + (A))
+#define __get_PciBridgeDataW(A) readw((volatile void __iomem *) __region_CS1 + 0x800 + (A))
+#define __get_PciBridgeDataL(A) readl((volatile void __iomem *) __region_CS1 + 0x800 + (A))
+
+#define __set_PciBridgeDataB(A,V) writeb((V), (volatile void __iomem *) __region_CS1 + 0x800 + (A))
+#define __set_PciBridgeDataW(A,V) writew((V), (volatile void __iomem *) __region_CS1 + 0x800 + (A))
+#define __set_PciBridgeDataL(A,V) writel((V), (volatile void __iomem *) __region_CS1 + 0x800 + (A))
+
+static inline int __query(const struct pci_dev *dev)
+{
+//	return dev->bus->number==0 && (dev->devfn==PCI_DEVFN(0,0));
+//	return dev->bus->number==1;
+//	return dev->bus->number==0 &&
+//		(dev->devfn==PCI_DEVFN(2,0) || dev->devfn==PCI_DEVFN(3,0));
+	return 0;
+}
+
+/*****************************************************************************/
+/*
+ *
+ */
+static int pci_frv_read_config(struct pci_bus *bus, unsigned int devfn, int where, int size,
+			       u32 *val)
+{
+	u32 _value;
+
+	if (bus->number == 0 && devfn == PCI_DEVFN(0, 0)) {
+		_value = __get_PciBridgeDataL(where & ~3);
+	}
+	else {
+		__set_PciCfgAddr(CONFIG_CMD(bus, devfn, where));
+		_value = __get_PciCfgDataL(where & ~3);
+	}
+
+	switch (size) {
+	case 1:
+		_value = _value >> ((where & 3) * 8);
+		break;
+
+	case 2:
+		_value = _value >> ((where & 2) * 8);
+		break;
+
+	case 4:
+		break;
+
+	default:
+		BUG();
+	}
+
+	*val = _value;
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static int pci_frv_write_config(struct pci_bus *bus, unsigned int devfn, int where, int size,
+				u32 value)
+{
+	switch (size) {
+	case 1:
+		if (bus->number == 0 && devfn == PCI_DEVFN(0, 0)) {
+			__set_PciBridgeDataB(where, value);
+		}
+		else {
+			__set_PciCfgAddr(CONFIG_CMD(bus, devfn, where));
+			__set_PciCfgDataB(where, value);
+		}
+		break;
+
+	case 2:
+		if (bus->number == 0 && devfn == PCI_DEVFN(0, 0)) {
+			__set_PciBridgeDataW(where, value);
+		}
+		else {
+			__set_PciCfgAddr(CONFIG_CMD(bus, devfn, where));
+			__set_PciCfgDataW(where, value);
+		}
+		break;
+
+	case 4:
+		if (bus->number == 0 && devfn == PCI_DEVFN(0, 0)) {
+			__set_PciBridgeDataL(where, value);
+		}
+		else {
+			__set_PciCfgAddr(CONFIG_CMD(bus, devfn, where));
+			__set_PciCfgDataL(where, value);
+		}
+		break;
+
+	default:
+		BUG();
+	}
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static struct pci_ops pci_direct_frv = {
+	pci_frv_read_config,
+	pci_frv_write_config,
+};
+
+/*
+ * Before we decide to use direct hardware access mechanisms, we try to do some
+ * trivial checks to ensure it at least _seems_ to be working -- we just test
+ * whether bus 00 contains a host bridge (this is similar to checking
+ * techniques used in XFree86, but ours should be more reliable since we
+ * attempt to make use of direct access hints provided by the PCI BIOS).
+ *
+ * This should be close to trivial, but it isn't, because there are buggy
+ * chipsets (yes, you guessed it, by Intel and Compaq) that have no class ID.
+ */
+static int __init pci_sanity_check(struct pci_ops *o)
+{
+	struct pci_bus bus;		/* Fake bus and device */
+	u32 id;
+
+	bus.number	= 0;
+
+	if (o->read(&bus, 0, PCI_VENDOR_ID, 4, &id) == PCIBIOS_SUCCESSFUL) {
+		printk("PCI: VDK Bridge device:vendor: %08x\n", id);
+		if (id == 0x200e10cf)
+			return 1;
+	}
+
+	printk("PCI: VDK Bridge: Sanity check failed\n");
+	return 0;
+}
+
+static struct pci_ops * __init pci_check_direct(void)
+{
+	unsigned long flags;
+
+	local_irq_save(flags);
+
+	/* check if access works */
+	if (pci_sanity_check(&pci_direct_frv)) {
+		local_irq_restore(flags);
+		printk("PCI: Using configuration frv\n");
+//		request_mem_region(0xBE040000, 256, "FRV bridge");
+//		request_mem_region(0xBFFFFFF4, 12, "PCI frv");
+		return &pci_direct_frv;
+	}
+
+	local_irq_restore(flags);
+	return NULL;
+}
+
+/*
+ * Several buggy motherboards address only 16 devices and mirror
+ * them to next 16 IDs. We try to detect this `feature' on all
+ * primary buses (those containing host bridges as they are
+ * expected to be unique) and remove the ghost devices.
+ */
+
+static void __init pcibios_fixup_ghosts(struct pci_bus *b)
+{
+	struct list_head *ln, *mn;
+	struct pci_dev *d, *e;
+	int mirror = PCI_DEVFN(16,0);
+	int seen_host_bridge = 0;
+	int i;
+
+	for (ln=b->devices.next; ln != &b->devices; ln=ln->next) {
+		d = pci_dev_b(ln);
+		if ((d->class >> 8) == PCI_CLASS_BRIDGE_HOST)
+			seen_host_bridge++;
+		for (mn=ln->next; mn != &b->devices; mn=mn->next) {
+			e = pci_dev_b(mn);
+			if (e->devfn != d->devfn + mirror ||
+			    e->vendor != d->vendor ||
+			    e->device != d->device ||
+			    e->class != d->class)
+				continue;
+			for(i=0; i<PCI_NUM_RESOURCES; i++)
+				if (e->resource[i].start != d->resource[i].start ||
+				    e->resource[i].end != d->resource[i].end ||
+				    e->resource[i].flags != d->resource[i].flags)
+					continue;
+			break;
+		}
+		if (mn == &b->devices)
+			return;
+	}
+	if (!seen_host_bridge)
+		return;
+	printk("PCI: Ignoring ghost devices on bus %02x\n", b->number);
+
+	ln = &b->devices;
+	while (ln->next != &b->devices) {
+		d = pci_dev_b(ln->next);
+		if (d->devfn >= mirror) {
+			list_del(&d->global_list);
+			list_del(&d->bus_list);
+			kfree(d);
+		} else
+			ln = ln->next;
+	}
+}
+
+/*
+ * Discover remaining PCI buses in case there are peer host bridges.
+ * We use the number of last PCI bus provided by the PCI BIOS.
+ */
+static void __init pcibios_fixup_peer_bridges(void)
+{
+	struct pci_bus bus;
+	struct pci_dev dev;
+	int n;
+	u16 l;
+
+	if (pcibios_last_bus <= 0 || pcibios_last_bus >= 0xff)
+		return;
+	printk("PCI: Peer bridge fixup\n");
+	for (n=0; n <= pcibios_last_bus; n++) {
+		if (pci_find_bus(0, n))
+			continue;
+		bus.number = n;
+		bus.ops = pci_root_ops;
+		dev.bus = &bus;
+		for(dev.devfn=0; dev.devfn<256; dev.devfn += 8)
+			if (!pci_read_config_word(&dev, PCI_VENDOR_ID, &l) &&
+			    l != 0x0000 && l != 0xffff) {
+				printk("Found device at %02x:%02x [%04x]\n", n, dev.devfn, l);
+				printk("PCI: Discovered peer bus %02x\n", n);
+				pci_scan_bus(n, pci_root_ops, NULL);
+				break;
+			}
+	}
+}
+
+/*
+ * Exceptions for specific devices. Usually work-arounds for fatal design flaws.
+ */
+
+static void __init pci_fixup_umc_ide(struct pci_dev *d)
+{
+	/*
+	 * UM8886BF IDE controller sets region type bits incorrectly,
+	 * therefore they look like memory despite of them being I/O.
+	 */
+	int i;
+
+	printk("PCI: Fixing base address flags for device %s\n", d->slot_name);
+	for(i=0; i<4; i++)
+		d->resource[i].flags |= PCI_BASE_ADDRESS_SPACE_IO;
+}
+
+static void __init pci_fixup_ide_bases(struct pci_dev *d)
+{
+	int i;
+
+	/*
+	 * PCI IDE controllers use non-standard I/O port decoding, respect it.
+	 */
+	if ((d->class >> 8) != PCI_CLASS_STORAGE_IDE)
+		return;
+	printk("PCI: IDE base address fixup for %s\n", d->slot_name);
+	for(i=0; i<4; i++) {
+		struct resource *r = &d->resource[i];
+		if ((r->start & ~0x80) == 0x374) {
+			r->start |= 2;
+			r->end = r->start;
+		}
+	}
+}
+
+static void __init pci_fixup_ide_trash(struct pci_dev *d)
+{
+	int i;
+
+	/*
+	 * There exist PCI IDE controllers which have utter garbage
+	 * in first four base registers. Ignore that.
+	 */
+	printk("PCI: IDE base address trash cleared for %s\n", d->slot_name);
+	for(i=0; i<4; i++)
+		d->resource[i].start = d->resource[i].end = d->resource[i].flags = 0;
+}
+
+static void __devinit  pci_fixup_latency(struct pci_dev *d)
+{
+	/*
+	 *  SiS 5597 and 5598 chipsets require latency timer set to
+	 *  at most 32 to avoid lockups.
+	 */
+	DBG("PCI: Setting max latency to 32\n");
+	pcibios_max_latency = 32;
+}
+
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_UMC, PCI_DEVICE_ID_UMC_UM8886BF, pci_fixup_umc_ide);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_5513, pci_fixup_ide_trash);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_5597, pci_fixup_latency);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_5598, pci_fixup_latency);
+DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pci_fixup_ide_bases);
+
+/*
+ *  Called after each bus is probed, but before its children
+ *  are examined.
+ */
+
+void __init pcibios_fixup_bus(struct pci_bus *bus)
+{
+#if 0
+	printk("### PCIBIOS_FIXUP_BUS(%d)\n",bus->number);
+#endif
+	pcibios_fixup_ghosts(bus);
+	pci_read_bridge_bases(bus);
+
+	if (bus->number == 0) {
+		struct list_head *ln;
+		struct pci_dev *dev;
+		for (ln=bus->devices.next; ln != &bus->devices; ln=ln->next) {
+			dev = pci_dev_b(ln);
+			if (dev->devfn == 0) {
+				dev->resource[0].start = 0;
+				dev->resource[0].end = 0;
+			}
+		}
+	}
+}
+
+/*
+ * Initialization. Try all known PCI access methods. Note that we support
+ * using both PCI BIOS and direct access: in such cases, we use I/O ports
+ * to access config space, but we still keep BIOS order of cards to be
+ * compatible with 2.0.X. This should go away some day.
+ */
+
+int __init pcibios_init(void)
+{
+	struct pci_ops *dir = NULL;
+
+	if (!mb93090_mb00_detected)
+		return -ENXIO;
+
+	__reg_MB86943_sl_ctl |= MB86943_SL_CTL_DRCT_MASTER_SWAP | MB86943_SL_CTL_DRCT_SLAVE_SWAP;
+
+	__reg_MB86943_ecs_base(1)	= ((__region_CS2 + 0x01000000) >> 9) | 0x08000000;
+	__reg_MB86943_ecs_base(2)	= ((__region_CS2 + 0x00000000) >> 9) | 0x08000000;
+
+	*(volatile uint32_t *) (__region_CS1 + 0x848) = 0xe0000000;
+	*(volatile uint32_t *) (__region_CS1 + 0x8b8) = 0x00000000;
+
+	__reg_MB86943_sl_pci_io_base	= (__region_CS2 + 0x04000000) >> 9;
+	__reg_MB86943_sl_pci_mem_base	= (__region_CS2 + 0x08000000) >> 9;
+	__reg_MB86943_pci_sl_io_base	= __region_CS2 + 0x04000000;
+	__reg_MB86943_pci_sl_mem_base	= __region_CS2 + 0x08000000;
+	mb();
+
+	*(volatile unsigned long *)(__region_CS2+0x01300014) == 1;
+
+	ioport_resource.start	= (__reg_MB86943_sl_pci_io_base << 9) & 0xfffffc00;
+	ioport_resource.end	= (__reg_MB86943_sl_pci_io_range << 9) | 0x3ff;
+	ioport_resource.end	+= ioport_resource.start;
+
+	printk("PCI IO window:  %08lx-%08lx\n", ioport_resource.start, ioport_resource.end);
+
+	iomem_resource.start	= (__reg_MB86943_sl_pci_mem_base << 9) & 0xfffffc00;
+
+	/* Reserve somewhere to write to flush posted writes. */
+	iomem_resource.start += 0x400;
+
+	iomem_resource.end	= (__reg_MB86943_sl_pci_mem_range << 9) | 0x3ff;
+	iomem_resource.end	+= iomem_resource.start;
+
+	printk("PCI MEM window: %08lx-%08lx\n", iomem_resource.start, iomem_resource.end);
+	printk("PCI DMA memory: %08lx-%08lx\n", dma_coherent_mem_start, dma_coherent_mem_end);
+
+	if (!pci_probe)
+		return -ENXIO;
+
+	dir = pci_check_direct();
+	if (dir)
+		pci_root_ops = dir;
+	else {
+		printk("PCI: No PCI bus detected\n");
+		return -ENXIO;
+	}
+
+	printk("PCI: Probing PCI hardware\n");
+	pci_root_bus = pci_scan_bus(0, pci_root_ops, NULL);
+
+	pcibios_irq_init();
+	pcibios_fixup_peer_bridges();
+	pcibios_fixup_irqs();
+	pcibios_resource_survey();
+
+	return 0;
+}
+
+arch_initcall(pcibios_init);
+
+char * __init pcibios_setup(char *str)
+{
+	if (!strcmp(str, "off")) {
+		pci_probe = 0;
+		return NULL;
+	} else if (!strncmp(str, "lastbus=", 8)) {
+		pcibios_last_bus = simple_strtol(str+8, NULL, 0);
+		return NULL;
+	}
+	return str;
+}
+
+int pcibios_enable_device(struct pci_dev *dev, int mask)
+{
+	int err;
+
+	if ((err = pcibios_enable_resources(dev, mask)) < 0)
+		return err;
+	pcibios_enable_irq(dev);
+	return 0;
+}

^ permalink raw reply	[flat|nested] 87+ messages in thread

* [PATCH 8/20] FRV: Fujitsu FR-V CPU arch implementation part 6
  2004-11-08 14:34 [PATCH 1/20] FRV: Fujitsu FR-V CPU arch maintainer record dhowells
                   ` (5 preceding siblings ...)
  2004-11-08 14:34 ` [PATCH 3/20] FRV: Fujitsu FR-V CPU arch implementation part 1 dhowells
@ 2004-11-08 14:34 ` dhowells
  2004-11-08 14:34 ` [PATCH 9/20] FRV: Fujitsu FR-V CPU arch implementation part 7 dhowells
                   ` (9 subsequent siblings)
  16 siblings, 0 replies; 87+ messages in thread
From: dhowells @ 2004-11-08 14:34 UTC (permalink / raw)
  To: torvalds, akpm, davidm; +Cc: linux-kernel, uclinux-dev

The attached patches provides part 6 of an architecture implementation
for the Fujitsu FR-V CPU series, configurably as Linux or uClinux.

Signed-Off-By: dhowells@redhat.com
---
diffstat frv-arch_6-2610rc1mm3.diff
 sys_frv.c |  210 ++++++++++++++++++++++++++++++
 sysctl.c  |  206 +++++++++++++++++++++++++++++
 time.c    |  234 +++++++++++++++++++++++++++++++++
 traps.c   |  431 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 uaccess.c |   95 +++++++++++++
 5 files changed, 1176 insertions(+)

diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/kernel/sysctl.c linux-2.6.10-rc1-mm3-frv/arch/frv/kernel/sysctl.c
--- /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/kernel/sysctl.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/arch/frv/kernel/sysctl.c	2004-11-05 14:13:03.233552359 +0000
@@ -0,0 +1,206 @@
+/* sysctl.c: implementation of /proc/sys files relating to FRV specifically
+ *
+ * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * 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.
+ */
+
+#include <linux/config.h>
+#include <linux/slab.h>
+#include <linux/sysctl.h>
+#include <linux/proc_fs.h>
+#include <linux/init.h>
+#include <asm/uaccess.h>
+
+static const char frv_cache_wback[] = "wback";
+static const char frv_cache_wthru[] = "wthru";
+
+static void frv_change_dcache_mode(unsigned long newmode)
+{
+	unsigned long flags, hsr0;
+
+	local_irq_save(flags);
+
+	hsr0 = __get_HSR(0);
+	hsr0 &= ~HSR0_DCE;
+	__set_HSR(0, hsr0);
+
+	asm volatile("	dcef	@(gr0,gr0),#1	\n"
+		     "	membar			\n"
+		     : : : "memory"
+		     );
+
+	hsr0 = (hsr0 & ~HSR0_CBM) | newmode;
+	__set_HSR(0, hsr0);
+	hsr0 |= HSR0_DCE;
+	__set_HSR(0, hsr0);
+
+	local_irq_restore(flags);
+
+	//printk("HSR0 now %08lx\n", hsr0);
+}
+
+/*****************************************************************************/
+/*
+ * handle requests to dynamically switch the write caching mode delivered by /proc
+ */
+static int procctl_frv_cachemode(ctl_table *table, int write, struct file *filp,
+				 void *buffer, size_t *lenp, loff_t *ppos)
+{
+	unsigned long hsr0;
+	char buff[8];
+	int len;
+
+	len = *lenp;
+
+	if (write) {
+		/* potential state change */
+		if (len <= 1 || len > sizeof(buff) - 1)
+			return -EINVAL;
+
+		if (copy_from_user(buff, buffer, len) != 0)
+			return -EFAULT;
+
+		if (buff[len - 1] == '\n')
+			buff[len - 1] = '\0';
+		else
+			buff[len] = '\0';
+
+		if (strcmp(buff, frv_cache_wback) == 0) {
+			/* switch dcache into write-back mode */
+			frv_change_dcache_mode(HSR0_CBM_COPY_BACK);
+			return 0;
+		}
+
+		if (strcmp(buff, frv_cache_wthru) == 0) {
+			/* switch dcache into write-through mode */
+			frv_change_dcache_mode(HSR0_CBM_WRITE_THRU);
+			return 0;
+		}
+
+		return -EINVAL;
+	}
+
+	/* read the state */
+	if (filp->f_pos > 0) {
+		*lenp = 0;
+		return 0;
+	}
+
+	hsr0 = __get_HSR(0);
+	switch (hsr0 & HSR0_CBM) {
+	case HSR0_CBM_WRITE_THRU:
+		memcpy(buff, frv_cache_wthru, sizeof(frv_cache_wthru) - 1);
+		buff[sizeof(frv_cache_wthru) - 1] = '\n';
+		len = sizeof(frv_cache_wthru);
+		break;
+	default:
+		memcpy(buff, frv_cache_wback, sizeof(frv_cache_wback) - 1);
+		buff[sizeof(frv_cache_wback) - 1] = '\n';
+		len = sizeof(frv_cache_wback);
+		break;
+	}
+
+	if (len > *lenp)
+		len = *lenp;
+
+	if (copy_to_user(buffer, buff, len) != 0)
+		return -EFAULT;
+
+	*lenp = len;
+	filp->f_pos = len;
+	return 0;
+
+} /* end procctl_frv_cachemode() */
+
+/*****************************************************************************/
+/*
+ * permit the mm_struct the nominated process is using have its MMU context ID pinned
+ */
+#ifdef CONFIG_MMU
+static int procctl_frv_pin_cxnr(ctl_table *table, int write, struct file *filp,
+				void *buffer, size_t *lenp, loff_t *ppos)
+{
+	pid_t pid;
+	char buff[16], *p;
+	int len;
+
+	len = *lenp;
+
+	if (write) {
+		/* potential state change */
+		if (len <= 1 || len > sizeof(buff) - 1)
+			return -EINVAL;
+
+		if (copy_from_user(buff, buffer, len) != 0)
+			return -EFAULT;
+
+		if (buff[len - 1] == '\n')
+			buff[len - 1] = '\0';
+		else
+			buff[len] = '\0';
+
+		pid = simple_strtoul(buff, &p, 10);
+		if (*p)
+			return -EINVAL;
+
+		return cxn_pin_by_pid(pid);
+	}
+
+	/* read the currently pinned CXN */
+	if (filp->f_pos > 0) {
+		*lenp = 0;
+		return 0;
+	}
+
+	len = snprintf(buff, sizeof(buff), "%d\n", cxn_pinned);
+	if (len > *lenp)
+		len = *lenp;
+
+	if (copy_to_user(buffer, buff, len) != 0)
+		return -EFAULT;
+
+	*lenp = len;
+	filp->f_pos = len;
+	return 0;
+
+} /* end procctl_frv_pin_cxnr() */
+#endif
+
+/*
+ * FR-V specific sysctls
+ */
+static struct ctl_table frv_table[] =
+{
+	{ 1, "cache-mode",	NULL, 0, 0644, NULL, &procctl_frv_cachemode },
+#ifdef CONFIG_MMU
+	{ 2, "pin-cxnr",	NULL, 0, 0644, NULL, &procctl_frv_pin_cxnr },
+#endif
+	{ 0 }
+};
+
+/*
+ * Use a temporary sysctl number. Horrid, but will be cleaned up in 2.6
+ * when all the PM interfaces exist nicely.
+ */
+#define CTL_FRV 9898
+static struct ctl_table frv_dir_table[] =
+{
+	{CTL_FRV, "frv", NULL, 0, 0555, frv_table},
+	{0}
+};
+
+/*
+ * Initialize power interface
+ */
+static int __init frv_sysctl_init(void)
+{
+	register_sysctl_table(frv_dir_table, 1);
+	return 0;
+}
+
+__initcall(frv_sysctl_init);
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/kernel/sys_frv.c linux-2.6.10-rc1-mm3-frv/arch/frv/kernel/sys_frv.c
--- /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/kernel/sys_frv.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/arch/frv/kernel/sys_frv.c	2004-11-05 14:13:03.237552021 +0000
@@ -0,0 +1,210 @@
+/*
+ * linux/arch/frvnommu/kernel/sys_frv.c
+ *
+ * This file contains various random system calls that
+ * have a non-standard calling sequence on the Linux/FRV
+ * platform.
+ */
+
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/sem.h>
+#include <linux/msg.h>
+#include <linux/shm.h>
+#include <linux/stat.h>
+#include <linux/mman.h>
+#include <linux/file.h>
+#include <linux/utsname.h>
+#include <linux/syscalls.h>
+
+#include <asm/setup.h>
+#include <asm/uaccess.h>
+#include <asm/ipc.h>
+
+/*
+ * sys_pipe() is the normal C calling standard for creating
+ * a pipe. It's not the way unix traditionally does this, though.
+ */
+asmlinkage long sys_pipe(unsigned long * fildes)
+{
+	int fd[2];
+	int error;
+
+	error = do_pipe(fd);
+	if (!error) {
+		if (copy_to_user(fildes, fd, 2*sizeof(int)))
+			error = -EFAULT;
+	}
+	return error;
+}
+
+asmlinkage long sys_mmap2(unsigned long addr, unsigned long len,
+			  unsigned long prot, unsigned long flags,
+			  unsigned long fd, unsigned long pgoff)
+{
+	int error = -EBADF;
+	struct file * file = NULL;
+
+	flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
+	if (!(flags & MAP_ANONYMOUS)) {
+		file = fget(fd);
+		if (!file)
+			goto out;
+	}
+
+	/* As with sparc32, make sure the shift for mmap2 is constant
+	   (12), no matter what PAGE_SIZE we have.... */
+
+	/* But unlike sparc32, don't just silently break if we're
+	   trying to map something we can't */
+	if (pgoff & ((1<<(PAGE_SHIFT-12))-1))
+		return -EINVAL;
+
+	pgoff >>= (PAGE_SHIFT - 12);
+
+	down_write(&current->mm->mmap_sem);
+	error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
+	up_write(&current->mm->mmap_sem);
+
+	if (file)
+		fput(file);
+out:
+	return error;
+}
+
+#if 0 /* DAVIDM - do we want this */
+struct mmap_arg_struct64 {
+	__u32 addr;
+	__u32 len;
+	__u32 prot;
+	__u32 flags;
+	__u64 offset; /* 64 bits */
+	__u32 fd;
+};
+
+asmlinkage long sys_mmap64(struct mmap_arg_struct64 *arg)
+{
+	int error = -EFAULT;
+	struct file * file = NULL;
+	struct mmap_arg_struct64 a;
+	unsigned long pgoff;
+
+	if (copy_from_user(&a, arg, sizeof(a)))
+		return -EFAULT;
+
+	if ((long)a.offset & ~PAGE_MASK)
+		return -EINVAL;
+
+	pgoff = a.offset >> PAGE_SHIFT;
+	if ((a.offset >> PAGE_SHIFT) != pgoff)
+		return -EINVAL;
+
+	if (!(a.flags & MAP_ANONYMOUS)) {
+		error = -EBADF;
+		file = fget(a.fd);
+		if (!file)
+			goto out;
+	}
+	a.flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
+
+	down_write(&current->mm->mmap_sem);
+	error = do_mmap_pgoff(file, a.addr, a.len, a.prot, a.flags, pgoff);
+	up_write(&current->mm->mmap_sem);
+	if (file)
+		fput(file);
+out:
+	return error;
+}
+#endif
+
+/*
+ * sys_ipc() is the de-multiplexer for the SysV IPC calls..
+ *
+ * This is really horribly ugly.
+ */
+asmlinkage long sys_ipc(unsigned long call,
+			unsigned long first,
+			unsigned long second,
+			unsigned long third,
+			void __user *ptr,
+			unsigned long fifth)
+{
+	int version, ret;
+
+	version = call >> 16; /* hack for backward compatibility */
+	call &= 0xffff;
+
+	switch (call) {
+	case SEMOP:
+		return sys_semtimedop(first, (struct sembuf __user *)ptr, second, NULL);
+	case SEMTIMEDOP:
+		return sys_semtimedop(first, (struct sembuf __user *)ptr, second,
+				      (const struct timespec __user *)fifth);
+
+	case SEMGET:
+		return sys_semget (first, second, third);
+	case SEMCTL: {
+		union semun fourth;
+		if (!ptr)
+			return -EINVAL;
+		if (get_user(fourth.__pad, (void * __user *) ptr))
+			return -EFAULT;
+		return sys_semctl (first, second, third, fourth);
+	}
+
+	case MSGSND:
+		return sys_msgsnd (first, (struct msgbuf __user *) ptr, 
+				   second, third);
+	case MSGRCV:
+		switch (version) {
+		case 0: {
+			struct ipc_kludge tmp;
+			if (!ptr)
+				return -EINVAL;
+			
+			if (copy_from_user(&tmp,
+					   (struct ipc_kludge __user *) ptr, 
+					   sizeof (tmp)))
+				return -EFAULT;
+			return sys_msgrcv (first, tmp.msgp, second,
+					   tmp.msgtyp, third);
+		}
+		default:
+			return sys_msgrcv (first,
+					   (struct msgbuf __user *) ptr,
+					   second, fifth, third);
+		}
+	case MSGGET:
+		return sys_msgget ((key_t) first, second);
+	case MSGCTL:
+		return sys_msgctl (first, second, (struct msqid_ds __user *) ptr);
+
+	case SHMAT:
+		switch (version) {
+		default: {
+			ulong raddr;
+			ret = do_shmat (first, (char __user *) ptr, second, &raddr);
+			if (ret)
+				return ret;
+			return put_user (raddr, (ulong __user *) third);
+		}
+		case 1:	/* iBCS2 emulator entry point */
+			if (!segment_eq(get_fs(), get_ds()))
+				return -EINVAL;
+			/* The "(ulong *) third" is valid _only_ because of the kernel segment thing */
+			return do_shmat (first, (char __user *) ptr, second, (ulong *) third);
+		}
+	case SHMDT: 
+		return sys_shmdt ((char __user *)ptr);
+	case SHMGET:
+		return sys_shmget (first, second, third);
+	case SHMCTL:
+		return sys_shmctl (first, second,
+				   (struct shmid_ds __user *) ptr);
+	default:
+		return -ENOSYS;
+	}
+}
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/kernel/time.c linux-2.6.10-rc1-mm3-frv/arch/frv/kernel/time.c
--- /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/kernel/time.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/arch/frv/kernel/time.c	2004-11-05 14:13:03.242551599 +0000
@@ -0,0 +1,234 @@
+/*
+ *  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/config.h> /* CONFIG_HEARTBEAT */
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/param.h>
+#include <linux/string.h>
+#include <linux/interrupt.h>
+#include <linux/profile.h>
+#include <linux/irq.h>
+#include <linux/mm.h>
+
+#include <asm/io.h>
+#include <asm/timer-regs.h>
+#include <asm/mb-regs.h>
+#include <asm/mb86943a.h>
+#include <asm/irq-routing.h>
+
+#include <linux/timex.h>
+
+#define TICK_SIZE (tick_nsec / 1000)
+
+extern unsigned long wall_jiffies;
+
+u64 jiffies_64 = INITIAL_JIFFIES;
+EXPORT_SYMBOL(jiffies_64);
+
+unsigned long __nongprelbss __clkin_clock_speed_HZ;
+unsigned long __nongprelbss __ext_bus_clock_speed_HZ;
+unsigned long __nongprelbss __res_bus_clock_speed_HZ;
+unsigned long __nongprelbss __sdram_clock_speed_HZ;
+unsigned long __nongprelbss __core_bus_clock_speed_HZ;
+unsigned long __nongprelbss __core_clock_speed_HZ;
+unsigned long __nongprelbss __dsu_clock_speed_HZ;
+unsigned long __nongprelbss __serial_clock_speed_HZ;
+unsigned long __delay_loops_MHz;
+
+static irqreturn_t timer_interrupt(int irq, void *dummy, struct pt_regs *regs);
+
+static struct irqaction timer_irq  = {
+	timer_interrupt, SA_INTERRUPT, CPU_MASK_NONE, "timer", NULL, NULL
+};
+
+static inline int set_rtc_mmss(unsigned long nowtime)
+{
+	return -1;
+}
+
+/*
+ * timer_interrupt() needs to keep up the real-time clock,
+ * as well as call the "do_timer()" routine every clocktick
+ */
+static irqreturn_t timer_interrupt(int irq, void *dummy, struct pt_regs * regs)
+{
+	/* last time the cmos clock got updated */
+	static long last_rtc_update = 0;
+
+	/*
+	 * Here we are in the timer irq handler. We just have irqs locally
+	 * disabled but we don't know if the timer_bh is running on the other
+	 * CPU. We need to avoid to SMP race with it. NOTE: we don' t need
+	 * the irq version of write_lock because as just said we have irq
+	 * locally disabled. -arca
+	 */
+	write_seqlock(&xtime_lock);
+
+	do_timer(regs);
+	update_process_times(user_mode(regs));
+	profile_tick(CPU_PROFILING, regs);
+
+	/*
+	 * If we have an externally synchronized Linux clock, then update
+	 * CMOS clock accordingly every ~11 minutes. Set_rtc_mmss() has to be
+	 * called as close as possible to 500 ms before the new second starts.
+	 */
+	if ((time_status & STA_UNSYNC) == 0 &&
+	    xtime.tv_sec > last_rtc_update + 660 &&
+	    (xtime.tv_nsec / 1000) >= 500000 - ((unsigned) TICK_SIZE) / 2 &&
+	    (xtime.tv_nsec / 1000) <= 500000 + ((unsigned) TICK_SIZE) / 2
+	    ) {
+		if (set_rtc_mmss(xtime.tv_sec) == 0)
+			last_rtc_update = xtime.tv_sec;
+		else
+			last_rtc_update = xtime.tv_sec - 600; /* do it again in 60 s */
+	}
+
+#ifdef CONFIG_HEARTBEAT
+	static unsigned short n;
+	n++;
+	__set_LEDS(n);
+#endif /* CONFIG_HEARTBEAT */
+
+	write_sequnlock(&xtime_lock);
+	return IRQ_HANDLED;
+}
+
+void time_divisor_init(void)
+{
+	unsigned short base, pre, prediv;
+
+	/* set the scheduling timer going */
+	pre = 1;
+	prediv = 4;
+	base = __res_bus_clock_speed_HZ / pre / HZ / (1 << prediv);
+
+	__set_TPRV(pre);
+	__set_TxCKSL_DATA(0, prediv);
+	__set_TCTR(TCTR_SC_CTR0 | TCTR_RL_RW_LH8 | TCTR_MODE_2);
+	__set_TCSR_DATA(0, base & 0xff);
+	__set_TCSR_DATA(0, base >> 8);
+}
+
+void time_init(void)
+{
+	unsigned int year, mon, day, hour, min, sec;
+
+	extern void arch_gettod(int *year, int *mon, int *day, int *hour, int *min, int *sec);
+
+	/* FIX by dqg : Set to zero for platforms that don't have tod */
+	/* without this time is undefined and can overflow time_t, causing  */
+	/* very stange errors */
+	year = 1980;
+	mon = day = 1;
+	hour = min = sec = 0;
+	arch_gettod (&year, &mon, &day, &hour, &min, &sec);
+
+	if ((year += 1900) < 1970)
+		year += 100;
+	xtime.tv_sec = mktime(year, mon, day, hour, min, sec);
+	xtime.tv_nsec = 0;
+
+	/* install scheduling interrupt handler */
+	setup_irq(IRQ_CPU_TIMER0, &timer_irq);
+
+	time_divisor_init();
+}
+
+/*
+ * This version of gettimeofday has near microsecond resolution.
+ */
+void do_gettimeofday(struct timeval *tv)
+{
+	unsigned long seq;
+	unsigned long usec, sec;
+	unsigned long max_ntp_tick;
+
+	do {
+		unsigned long lost;
+
+		seq = read_seqbegin(&xtime_lock);
+
+		usec = 0;
+		lost = jiffies - wall_jiffies;
+
+		/*
+		 * If time_adjust is negative then NTP is slowing the clock
+		 * so make sure not to go into next possible interval.
+		 * Better to lose some accuracy than have time go backwards..
+		 */
+		if (unlikely(time_adjust < 0)) {
+			max_ntp_tick = (USEC_PER_SEC / HZ) - tickadj;
+			usec = min(usec, max_ntp_tick);
+
+			if (lost)
+				usec += lost * max_ntp_tick;
+		}
+		else if (unlikely(lost))
+			usec += lost * (USEC_PER_SEC / HZ);
+
+		sec = xtime.tv_sec;
+		usec += (xtime.tv_nsec / 1000);
+	} while (read_seqretry(&xtime_lock, seq));
+
+	while (usec >= 1000000) {
+		usec -= 1000000;
+		sec++;
+	}
+
+	tv->tv_sec = sec;
+	tv->tv_usec = usec;
+}
+
+int do_settimeofday(struct timespec *tv)
+{
+	time_t wtm_sec, sec = tv->tv_sec;
+	long wtm_nsec, nsec = tv->tv_nsec;
+
+	if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC)
+		return -EINVAL;
+
+	write_seqlock_irq(&xtime_lock);
+	/*
+	 * This is revolting. We need to set "xtime" correctly. However, the
+	 * value in this location is the value at the most recent update of
+	 * wall time.  Discover what correction gettimeofday() would have
+	 * made, and then undo it!
+	 */
+	nsec -= 0 * NSEC_PER_USEC;
+	nsec -= (jiffies - wall_jiffies) * TICK_NSEC;
+
+	wtm_sec  = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec);
+	wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec);
+
+	set_normalized_timespec(&xtime, sec, nsec);
+	set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
+
+	time_adjust = 0;		/* stop active adjtime() */
+	time_status |= STA_UNSYNC;
+	time_maxerror = NTP_PHASE_LIMIT;
+	time_esterror = NTP_PHASE_LIMIT;
+	write_sequnlock_irq(&xtime_lock);
+	clock_was_set();
+	return 0;
+}
+
+/*
+ * Scheduler clock - returns current time in nanosec units.
+ */
+unsigned long long sched_clock(void)
+{
+	return jiffies_64 * (1000000000 / HZ);
+}
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/kernel/traps.c linux-2.6.10-rc1-mm3-frv/arch/frv/kernel/traps.c
--- /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/kernel/traps.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/arch/frv/kernel/traps.c	2004-11-05 14:13:03.247551176 +0000
@@ -0,0 +1,431 @@
+/* traps.c: high-level exception handler for FR-V
+ *
+ * Copyright (C) 2003 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * 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.
+ */
+
+#include <linux/config.h>
+#include <linux/sched.h>
+#include <linux/signal.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/types.h>
+#include <linux/user.h>
+#include <linux/string.h>
+#include <linux/linkage.h>
+#include <linux/init.h>
+
+#include <asm/setup.h>
+#include <asm/fpu.h>
+#include <asm/system.h>
+#include <asm/uaccess.h>
+#include <asm/pgtable.h>
+#include <asm/siginfo.h>
+#include <asm/unaligned.h>
+
+void show_backtrace(struct pt_regs *, unsigned long);
+
+extern asmlinkage void __break_hijack_kernel_event(void);
+
+/*****************************************************************************/
+/*
+ * instruction access error
+ */
+asmlinkage void insn_access_error(unsigned long esfr1, unsigned long epcr0, unsigned long esr0)
+{
+	siginfo_t info;
+
+	die_if_kernel("-- Insn Access Error --\n"
+		      "EPCR0 : %08lx\n"
+		      "ESR0  : %08lx\n",
+		      epcr0, esr0);
+
+	info.si_signo	= SIGSEGV;
+	info.si_code	= SEGV_ACCERR;
+	info.si_errno	= 0;
+	info.si_addr	= (void *) ((epcr0 & EPCR0_V) ? (epcr0 & EPCR0_PC) : __frame->pc);
+
+	force_sig_info(info.si_signo, &info, current);
+} /* end insn_access_error() */
+
+/*****************************************************************************/
+/*
+ * handler for:
+ * - illegal instruction
+ * - privileged instruction
+ * - unsupported trap
+ * - debug exceptions
+ */
+asmlinkage void illegal_instruction(unsigned long esfr1, unsigned long epcr0, unsigned long esr0)
+{
+	siginfo_t info;
+
+	die_if_kernel("-- Illegal Instruction --\n"
+		      "EPCR0 : %08lx\n"
+		      "ESR0  : %08lx\n"
+		      "ESFR1 : %08lx\n",
+		      epcr0, esr0, esfr1);
+
+	info.si_errno	= 0;
+	info.si_addr	= (void *) ((epcr0 & EPCR0_PC) ? (epcr0 & EPCR0_PC) : __frame->pc);
+
+	switch (__frame->tbr & TBR_TT) {
+	case TBR_TT_ILLEGAL_INSTR:
+		info.si_signo	= SIGILL;
+		info.si_code	= ILL_ILLOPC;
+		break;
+	case TBR_TT_PRIV_INSTR:
+		info.si_signo	= SIGILL;
+		info.si_code	= ILL_PRVOPC;
+		break;
+	case TBR_TT_TRAP2 ... TBR_TT_TRAP126:
+		info.si_signo	= SIGILL;
+		info.si_code	= ILL_ILLTRP;
+		break;
+	/* GDB uses "tira gr0, #1" as a breakpoint instruction.  */
+	case TBR_TT_TRAP1:
+	case TBR_TT_BREAK:
+		info.si_signo	= SIGTRAP;
+		info.si_code	=
+			(__frame->__status & REG__STATUS_STEPPED) ? TRAP_TRACE : TRAP_BRKPT;
+		break;
+	}
+
+	force_sig_info(info.si_signo, &info, current);
+} /* end illegal_instruction() */
+
+/*****************************************************************************/
+/*
+ * 
+ */
+asmlinkage void media_exception(unsigned long msr0, unsigned long msr1)
+{
+	siginfo_t info;
+
+	die_if_kernel("-- Media Exception --\n"
+		      "MSR0 : %08lx\n"
+		      "MSR1 : %08lx\n",
+		      msr0, msr1);
+
+	info.si_signo	= SIGFPE;
+	info.si_code	= FPE_MDAOVF;
+	info.si_errno	= 0;
+	info.si_addr	= (void *) __frame->pc;
+
+	force_sig_info(info.si_signo, &info, current);
+} /* end media_exception() */
+
+/*****************************************************************************/
+/*
+ * instruction or data access exception
+ */
+asmlinkage void memory_access_exception(unsigned long esr0,
+					unsigned long ear0,
+					unsigned long epcr0)
+{
+	siginfo_t info;
+
+#ifdef CONFIG_MMU
+	unsigned long fixup;
+
+	if ((esr0 & ESRx_EC) == ESRx_EC_DATA_ACCESS)
+		if (handle_misalignment(esr0, ear0, epcr0) == 0)
+			return;
+
+	if ((fixup = search_exception_table(__frame->pc)) != 0) {
+		__frame->pc = fixup;
+		return;
+	}
+#endif
+
+	die_if_kernel("-- Memory Access Exception --\n"
+		      "ESR0  : %08lx\n"
+		      "EAR0  : %08lx\n"
+		      "EPCR0 : %08lx\n",
+		      esr0, ear0, epcr0);
+
+	info.si_signo	= SIGSEGV;
+	info.si_code	= SEGV_ACCERR;
+	info.si_errno	= 0;
+	info.si_addr	= NULL;
+
+	if ((esr0 & (ESRx_VALID | ESR0_EAV)) == (ESRx_VALID | ESR0_EAV))
+		info.si_addr = (void *) ear0;
+
+	force_sig_info(info.si_signo, &info, current);
+
+} /* end memory_access_exception() */
+
+/*****************************************************************************/
+/*
+ * data access error
+ * - double-word data load from CPU control area (0xFExxxxxx)
+ * - read performed on inactive or self-refreshing SDRAM
+ * - error notification from slave device
+ * - misaligned address
+ * - access to out of bounds memory region
+ * - user mode accessing privileged memory region
+ * - write to R/O memory region
+ */
+asmlinkage void data_access_error(unsigned long esfr1, unsigned long esr15, unsigned long ear15)
+{
+	siginfo_t info;
+
+	die_if_kernel("-- Data Access Error --\n"
+		      "ESR15 : %08lx\n"
+		      "EAR15 : %08lx\n",
+		      esr15, ear15);
+
+	info.si_signo	= SIGSEGV;
+	info.si_code	= SEGV_ACCERR;
+	info.si_errno	= 0;
+	info.si_addr	= (void *)
+		(((esr15 & (ESRx_VALID|ESR15_EAV)) == (ESRx_VALID|ESR15_EAV)) ? ear15 : 0);
+
+	force_sig_info(info.si_signo, &info, current);
+} /* end data_access_error() */
+
+/*****************************************************************************/
+/*
+ * data store error - should only happen if accessing inactive or self-refreshing SDRAM
+ */
+asmlinkage void data_store_error(unsigned long esfr1, unsigned long esr15)
+{
+	die_if_kernel("-- Data Store Error --\n"
+		      "ESR15 : %08lx\n",
+		      esr15);
+	BUG();
+} /* end data_store_error() */
+
+/*****************************************************************************/
+/*
+ * 
+ */
+asmlinkage void division_exception(unsigned long esfr1, unsigned long esr0, unsigned long isr)
+{
+	siginfo_t info;
+
+	die_if_kernel("-- Division Exception --\n"
+		      "ESR0 : %08lx\n"
+		      "ISR  : %08lx\n",
+		      esr0, isr);
+
+	info.si_signo	= SIGFPE;
+	info.si_code	= FPE_INTDIV;
+	info.si_errno	= 0;
+	info.si_addr	= (void *) __frame->pc;
+
+	force_sig_info(info.si_signo, &info, current);
+} /* end division_exception() */
+
+/*****************************************************************************/
+/*
+ * 
+ */
+asmlinkage void compound_exception(unsigned long esfr1,
+				   unsigned long esr0, unsigned long esr14, unsigned long esr15,
+				   unsigned long msr0, unsigned long msr1)
+{
+	die_if_kernel("-- Compound Exception --\n"
+		      "ESR0  : %08lx\n"
+		      "ESR15 : %08lx\n"
+		      "ESR15 : %08lx\n"
+		      "MSR0  : %08lx\n"
+		      "MSR1  : %08lx\n",
+		      esr0, esr14, esr15, msr0, msr1);
+	BUG();
+} /* end compound_exception() */
+
+/*****************************************************************************/
+/*
+ * The architecture-independent backtrace generator
+ */
+void dump_stack(void)
+{
+	show_stack(NULL, NULL);
+}
+
+void show_stack(struct task_struct *task, unsigned long *sp)
+{
+}
+
+void show_trace_task(struct task_struct *tsk)
+{
+	printk("CONTEXT: stack=0x%lx frame=0x%p LR=0x%lx RET=0x%lx\n",
+	       tsk->thread.sp, tsk->thread.frame, tsk->thread.lr, tsk->thread.sched_lr);
+}
+
+static const char *regnames[] = {
+	"PSR ", "ISR ", "CCR ", "CCCR",
+	"LR  ", "LCR ", "PC  ", "_stt",
+	"sys ", "GR8*", "GNE0", "GNE1",
+	"IACH", "IACL",
+	"TBR ", "SP  ", "FP  ", "GR3 ",
+	"GR4 ", "GR5 ", "GR6 ", "GR7 ",
+	"GR8 ", "GR9 ", "GR10", "GR11",
+	"GR12", "GR13", "GR14", "GR15",
+	"GR16", "GR17", "GR18", "GR19",
+	"GR20", "GR21", "GR22", "GR23",
+	"GR24", "GR25", "GR26", "GR27",
+	"EFRM", "CURR", "GR30", "BFRM"
+};
+
+void show_regs(struct pt_regs *regs)
+{
+	uint32_t *reg;
+	int loop;
+
+	printk("\n");
+
+	printk("Frame: @%08x [%s]\n",
+	       (uint32_t) regs,
+	       regs->psr & PSR_S ? "kernel" : "user");
+
+	reg = (uint32_t *) regs;
+	for (loop = 0; loop < REG__END; loop++) {
+		printk("%s %08x", regnames[loop + 0], reg[loop + 0]);
+
+		if (loop == REG__END - 1 || loop % 5 == 4)
+			printk("\n");
+		else
+			printk(" | ");
+	}
+
+	printk("Process %s (pid: %d)\n", current->comm, current->pid);
+}
+
+void die_if_kernel(const char *str, ...)
+{
+	char buffer[256];
+	va_list va;
+
+	if (user_mode(__frame))
+		return;
+
+	va_start(va, str);
+	vsprintf(buffer, str, va);
+	va_end(va);
+
+	console_verbose();
+	printk("\n===================================\n");
+	printk("%s\n", buffer);
+	show_backtrace(__frame, 0);
+
+	__break_hijack_kernel_event();
+	do_exit(SIGSEGV);
+}
+
+/*****************************************************************************/
+/*
+ * dump the contents of an exception frame
+ */
+static void show_backtrace_regs(struct pt_regs *frame)
+{
+	uint32_t *reg;
+	int loop;
+
+	/* print the registers for this frame */
+	printk("<-- %s Frame: @%p -->\n",
+	       frame->psr & PSR_S ? "Kernel Mode" : "User Mode",
+	       frame);
+
+	reg = (uint32_t *) frame;
+	for (loop = 0; loop < REG__END; loop++) {
+		printk("%s %08x", regnames[loop + 0], reg[loop + 0]);
+
+		if (loop == REG__END - 1 || loop % 5 == 4)
+			printk("\n");
+		else
+			printk(" | ");
+	}
+
+	printk("--------\n");
+} /* end show_backtrace_regs() */
+
+/*****************************************************************************/
+/*
+ * generate a backtrace of the kernel stack
+ */
+void show_backtrace(struct pt_regs *frame, unsigned long sp)
+{
+	struct pt_regs *frame0;
+	unsigned long tos = 0, stop = 0, base;
+	int format;
+
+	base = ((((unsigned long) frame) + 8191) & ~8191) - sizeof(struct user_context);
+	frame0 = (struct pt_regs *) base;
+
+	if (sp) {
+		tos = sp;
+		stop = (unsigned long) frame;
+	}
+
+	printk("\nProcess %s (pid: %d)\n\n", current->comm, current->pid);
+
+	for (;;) {
+		/* dump stack segment between frames */
+		//printk("%08lx -> %08lx\n", tos, stop);
+		format = 0;
+		while (tos < stop) {
+			if (format == 0)
+				printk(" %04lx :", tos & 0xffff);
+
+			printk(" %08lx", *(unsigned long *) tos);
+
+			tos += 4;
+			format++;
+			if (format == 8) {
+				printk("\n");
+				format = 0;
+			}
+		}
+
+		if (format > 0)
+			printk("\n");
+
+		/* dump frame 0 outside of the loop */
+		if (frame == frame0)
+			break;
+
+		tos = frame->sp;
+		if (((unsigned long) frame) + sizeof(*frame) != tos) {
+			printk("-- TOS %08lx does not follow frame %p --\n",
+			       tos, frame);
+			break;
+		}
+
+		show_backtrace_regs(frame);
+
+		/* dump the stack between this frame and the next */
+		stop = (unsigned long) frame->next_frame;
+		if (stop != base &&
+		    (stop < tos ||
+		     stop > base ||
+		     (stop < base && stop + sizeof(*frame) > base) ||
+		     stop & 3)) {
+			printk("-- next_frame %08lx is invalid (range %08lx-%08lx) --\n",
+			       stop, tos, base);
+			break;
+		}
+
+		/* move to next frame */
+		frame = frame->next_frame;
+	}
+
+	/* we can always dump frame 0, even if the rest of the stack is corrupt */
+	show_backtrace_regs(frame0);
+
+} /* end show_backtrace() */
+
+/*****************************************************************************/
+/*
+ * initialise traps 
+ */
+void __init trap_init (void)
+{
+} /* end trap_init() */
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/kernel/uaccess.c linux-2.6.10-rc1-mm3-frv/arch/frv/kernel/uaccess.c
--- /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/kernel/uaccess.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/arch/frv/kernel/uaccess.c	2004-11-05 14:13:03.254550585 +0000
@@ -0,0 +1,95 @@
+/* uaccess.c: userspace access functions
+ *
+ * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * 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.
+ */
+
+#include <linux/mm.h>
+#include <asm/uaccess.h>
+
+/*****************************************************************************/
+/*
+ * copy a null terminated string from userspace
+ */
+long strncpy_from_user(char *dst, const char *src, long count)
+{
+	unsigned long max;
+	char *p, ch;
+	long err = -EFAULT;
+
+	if (count < 0)
+		BUG();
+
+	p = dst;
+
+#ifndef CONFIG_MMU
+	if ((unsigned long) src < memory_start)
+		goto error;
+#endif
+
+	if ((unsigned long) src >= get_addr_limit())
+		goto error;
+
+	max = get_addr_limit() - (unsigned long) src;
+	if ((unsigned long) count > max) {
+		memset(dst + max, 0, count - max);
+		count = max;
+	}
+	
+	err = 0;
+	for (; count > 0; count--, p++, src++) {
+		__get_user_asm(err, ch, src, "ub", "=r");
+		if (err < 0)
+			goto error;
+		if (!ch)
+			break;
+		*p = ch;
+	}
+
+	err = p - dst; /* return length excluding NUL */
+
+ error:
+	if (count > 0)
+		memset(p, 0, count); /* clear remainder of buffer [security] */
+
+	return err;
+} /* end strncpy_from_user() */
+
+/*****************************************************************************/
+/*
+ * Return the size of a string (including the ending 0)
+ *
+ * Return 0 on exception, a value greater than N if too long
+ */
+long strnlen_user(const char *src, long count)
+{
+	const char *p;
+	long err = 0;
+	char ch;
+
+	if (count < 0)
+		BUG();
+
+#ifndef CONFIG_MMU
+	if ((unsigned long) src < memory_start)
+		return 0;
+#endif
+
+	if ((unsigned long) src >= get_addr_limit())
+		return 0;
+
+	for (p = src; count > 0; count--, p++) {
+		__get_user_asm(err, ch, p, "ub", "=r");
+		if (err < 0)
+			return 0;
+		if (!ch)
+			break;
+	}
+
+	return p - src + 1; /* return length including NUL */
+} /* end strnlen_user() */

^ permalink raw reply	[flat|nested] 87+ messages in thread

* [PATCH 13/20] FRV: Fujitsu FR-V arch include files
  2004-11-08 14:34 [PATCH 1/20] FRV: Fujitsu FR-V CPU arch maintainer record dhowells
                   ` (12 preceding siblings ...)
  2004-11-08 14:34 ` [PATCH 14/20] FRV: Fujitsu FR-V arch include files dhowells
@ 2004-11-08 14:34 ` dhowells
  2004-11-08 14:34 ` [PATCH 18/20] FRV: procfs changes for nommu changes dhowells
                   ` (2 subsequent siblings)
  16 siblings, 0 replies; 87+ messages in thread
From: dhowells @ 2004-11-08 14:34 UTC (permalink / raw)
  To: torvalds, akpm, davidm; +Cc: linux-kernel, uclinux-dev

The attached patch provides the arch-specific include files for the Fujitsu
FR-V CPU arch.

Signed-Off-By: dhowells@redhat.com
---
diffstat frv-include_2-2610rc1mm3.diff
 ipc.h               |   33 +++
 ipcbuf.h            |   30 +++
 irc-regs.h          |   53 +++++
 irq-routing.h       |   70 +++++++
 irq.h               |   44 ++++
 kmap_types.h        |   29 +++
 linkage.h           |    7 
 local.h             |    6 
 math-emu.h          |  301 +++++++++++++++++++++++++++++++
 mb-regs.h           |  185 +++++++++++++++++++
 mb86943a.h          |   39 ++++
 mb93091-fpga-irqs.h |   44 ++++
 mb93093-fpga-irqs.h |   31 +++
 mb93493-irqs.h      |   52 +++++
 mb93493-regs.h      |  279 +++++++++++++++++++++++++++++
 mem-layout.h        |   78 ++++++++
 mman.h              |   44 ++++
 mmu.h               |   42 ++++
 mmu_context.h       |   50 +++++
 module.h            |   20 ++
 msgbuf.h            |   32 +++
 namei.h             |   18 +
 page.h              |  104 +++++++++++
 param.h             |   23 ++
 pci.h               |  108 +++++++++++
 percpu.h            |    6 
 pgalloc.h           |   66 ++++++
 pgtable.h           |  491 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 poll.h              |   23 ++
 posix_types.h       |   66 ++++++
 processor.h         |  153 ++++++++++++++++
 ptrace.h            |   86 +++++++++
 32 files changed, 2613 insertions(+)

diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/include/asm-frv/ipcbuf.h linux-2.6.10-rc1-mm3-frv/include/asm-frv/ipcbuf.h
--- /warthog/kernels/linux-2.6.10-rc1-mm3/include/asm-frv/ipcbuf.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/include/asm-frv/ipcbuf.h	2004-11-05 14:13:04.023485638 +0000
@@ -0,0 +1,30 @@
+#ifndef __ASM_IPCBUF_H__
+#define __ASM_IPCBUF_H__
+
+/*
+ * The user_ipc_perm structure for FR-V architecture.
+ * Note extra padding because this structure is passed back and forth
+ * between kernel and user space.
+ *
+ * Pad space is left for:
+ * - 32-bit mode_t and seq
+ * - 2 miscellaneous 32-bit values
+ */
+
+struct ipc64_perm
+{
+	__kernel_key_t		key;
+	__kernel_uid32_t	uid;
+	__kernel_gid32_t	gid;
+	__kernel_uid32_t	cuid;
+	__kernel_gid32_t	cgid;
+	__kernel_mode_t		mode;
+	unsigned short		__pad1;
+	unsigned short		seq;
+	unsigned short		__pad2;
+	unsigned long		__unused1;
+	unsigned long		__unused2;
+};
+
+#endif /* __ASM_IPCBUF_H__ */
+
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/include/asm-frv/ipc.h linux-2.6.10-rc1-mm3-frv/include/asm-frv/ipc.h
--- /warthog/kernels/linux-2.6.10-rc1-mm3/include/asm-frv/ipc.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/include/asm-frv/ipc.h	2004-11-05 14:13:04.027485300 +0000
@@ -0,0 +1,33 @@
+#ifndef __ASM_IPC_H__
+#define __ASM_IPC_H__
+
+/* 
+ * These are used to wrap system calls on FR-V
+ *
+ * See arch/frv/kernel/sys_frv.c for ugly details..
+ */
+struct ipc_kludge {
+	struct msgbuf __user *msgp;
+	long msgtyp;
+};
+
+#define SEMOP		 1
+#define SEMGET		 2
+#define SEMCTL		 3
+#define SEMTIMEDOP	 4
+#define MSGSND		11
+#define MSGRCV		12
+#define MSGGET		13
+#define MSGCTL		14
+#define SHMAT		21
+#define SHMDT		22
+#define SHMGET		23
+#define SHMCTL		24
+
+/* Used by the DIPC package, try and avoid reusing it */
+#define DIPC		25
+
+#define IPCCALL(version,op)	((version)<<16 | (op))
+
+#endif
+
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/include/asm-frv/irc-regs.h linux-2.6.10-rc1-mm3-frv/include/asm-frv/irc-regs.h
--- /warthog/kernels/linux-2.6.10-rc1-mm3/include/asm-frv/irc-regs.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/include/asm-frv/irc-regs.h	2004-11-05 14:13:04.031484963 +0000
@@ -0,0 +1,53 @@
+/* irc-regs.h: on-chip interrupt controller registers
+ *
+ * Copyright (C) 2003 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * 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.
+ */
+
+#ifndef _ASM_IRC_REGS
+#define _ASM_IRC_REGS
+
+#define __reg(ADDR) (*(volatile unsigned long *)(ADDR))
+
+#define __get_TM0()	({ __reg(0xfeff9800); })
+#define __get_TM1()	({ __reg(0xfeff9808); })
+#define __set_TM1(V)	do { __reg(0xfeff9808) = (V); mb(); } while(0)
+
+#define __set_TM1x(XI,V)			\
+do {						\
+	int shift = (XI) * 2 + 16;		\
+	unsigned long tm1 = __reg(0xfeff9808);	\
+	tm1 &= ~(0x3 << shift);			\
+	tm1 |= (V) << shift;			\
+	__reg(0xfeff9808) = tm1;		\
+	mb();					\
+} while(0)
+
+#define __get_RS(C)	({ (__reg(0xfeff9810) >> ((C)+16)) & 1; })
+
+#define __clr_RC(C)	do { __reg(0xfeff9818) = 1 << ((C)+16); mb(); } while(0)
+
+#define __get_MASK(C)	({ (__reg(0xfeff9820) >> ((C)+16)) & 1; })
+#define __set_MASK(C)	do { __reg(0xfeff9820) |=  1 << ((C)+16); mb(); } while(0)
+#define __clr_MASK(C)	do { __reg(0xfeff9820) &=  ~(1 << ((C)+16)); mb(); } while(0)
+
+#define __get_MASK_all() __get_MASK(0)
+#define __set_MASK_all() __set_MASK(0)
+#define __clr_MASK_all() __clr_MASK(0)
+
+#define __get_IRL()	({ (__reg(0xfeff9828) >> 16) & 0xf; })
+#define __clr_IRL()	do { __reg(0xfeff9828) = 0x100000; mb(); } while(0)
+
+#define __get_IRR(N)	({ __reg(0xfeff9840 + (N) * 8); })
+#define __set_IRR(N,V)	do { __reg(0xfeff9840 + (N) * 8) = (V); } while(0)
+
+#define __get_IITMR(N)	({ __reg(0xfeff9880 + (N) * 8); })
+#define __set_IITMR(N,V) do { __reg(0xfeff9880 + (N) * 8) = (V); } while(0)
+
+
+#endif /* _ASM_IRC_REGS */
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/include/asm-frv/irq.h linux-2.6.10-rc1-mm3-frv/include/asm-frv/irq.h
--- /warthog/kernels/linux-2.6.10-rc1-mm3/include/asm-frv/irq.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/include/asm-frv/irq.h	2004-11-05 14:13:04.034484709 +0000
@@ -0,0 +1,44 @@
+/* irq.h: FRV IRQ definitions
+ *
+ * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * 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.
+ */
+
+#ifndef _ASM_IRQ_H_
+#define _ASM_IRQ_H_
+
+#include <linux/config.h>
+
+/*
+ * the system has an on-CPU PIC and another PIC on the FPGA and other PICs on other peripherals,
+ * so we do some routing in irq-routing.[ch] to reduce the number of false-positives seen by
+ * drivers
+ */
+
+/* this number is used when no interrupt has been assigned */
+#define NO_IRQ				(-1)
+
+#define NR_IRQ_LOG2_ACTIONS_PER_GROUP	5
+#define NR_IRQ_ACTIONS_PER_GROUP	(1 << NR_IRQ_LOG2_ACTIONS_PER_GROUP)
+#define NR_IRQ_GROUPS			4
+#define NR_IRQS				(NR_IRQ_ACTIONS_PER_GROUP * NR_IRQ_GROUPS)
+
+/* probe returns a 32-bit IRQ mask:-/ */
+#define MIN_PROBE_IRQ	(NR_IRQS - 32)
+
+static inline int irq_canonicalize(int irq)
+{
+	return irq;
+}
+
+extern void disable_irq_nosync(unsigned int irq);
+extern void disable_irq(unsigned int irq);
+extern void enable_irq(unsigned int irq);
+
+
+#endif /* _ASM_IRQ_H_ */
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/include/asm-frv/irq-routing.h linux-2.6.10-rc1-mm3-frv/include/asm-frv/irq-routing.h
--- /warthog/kernels/linux-2.6.10-rc1-mm3/include/asm-frv/irq-routing.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/include/asm-frv/irq-routing.h	2004-11-05 14:13:04.039484287 +0000
@@ -0,0 +1,70 @@
+/* irq-routing.h: multiplexed IRQ routing
+ *
+ * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * 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.
+ */
+
+#ifndef _ASM_IRQ_ROUTING_H
+#define _ASM_IRQ_ROUTING_H
+
+#ifndef __ASSEMBLY__
+
+#include <linux/spinlock.h>
+#include <asm/irq.h>
+
+struct irq_source;
+struct irq_level;
+
+/*
+ * IRQ action distribution sets
+ */
+struct irq_group {
+	int			first_irq;	/* first IRQ distributed here */
+	void (*control)(struct irq_group *group, int index, int on);
+
+	struct irqaction	*actions[NR_IRQ_ACTIONS_PER_GROUP];	/* IRQ action chains */
+	struct irq_source	*sources[NR_IRQ_ACTIONS_PER_GROUP];	/* IRQ sources */
+	int			disable_cnt[NR_IRQ_ACTIONS_PER_GROUP];	/* disable counts */
+};
+
+/*
+ * IRQ source manager
+ */
+struct irq_source {
+	struct irq_source	*next;
+	struct irq_level	*level;
+	const char		*muxname;
+	volatile void __iomem	*muxdata;
+	unsigned long		irqmask;
+
+	void (*doirq)(struct irq_source *source);
+};
+
+/*
+ * IRQ level management (per CPU IRQ priority / entry vector)
+ */
+struct irq_level {
+	int			usage;
+	int			disable_count;
+	unsigned long		flags;		/* current SA_INTERRUPT and SA_SHIRQ settings */
+	spinlock_t		lock;
+	struct irq_source	*sources;
+};
+
+extern struct irq_level frv_irq_levels[16];
+extern struct irq_group *irq_groups[NR_IRQ_GROUPS];
+
+extern void frv_irq_route(struct irq_source *source, int irqlevel);
+extern void frv_irq_route_external(struct irq_source *source, int irq);
+extern void frv_irq_set_group(struct irq_group *group);
+extern void distribute_irqs(struct irq_group *group, unsigned long irqmask);
+extern void route_cpu_irqs(void);
+
+#endif /* !__ASSEMBLY__ */
+
+#endif /* _ASM_IRQ_ROUTING_H */
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/include/asm-frv/kmap_types.h linux-2.6.10-rc1-mm3-frv/include/asm-frv/kmap_types.h
--- /warthog/kernels/linux-2.6.10-rc1-mm3/include/asm-frv/kmap_types.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/include/asm-frv/kmap_types.h	2004-11-05 14:13:04.042484033 +0000
@@ -0,0 +1,29 @@
+                                                                                
+#ifndef _ASM_KMAP_TYPES_H
+#define _ASM_KMAP_TYPES_H
+ 
+enum km_type {
+	/* arch specific kmaps - change the numbers attached to these at your peril */
+	__KM_CACHE,		/* cache flush page attachment point */
+	__KM_PGD,		/* current page directory */
+	__KM_ITLB_PTD,		/* current instruction TLB miss page table lookup */
+	__KM_DTLB_PTD,		/* current data TLB miss page table lookup */
+
+	/* general kmaps */
+        KM_BOUNCE_READ,
+        KM_SKB_SUNRPC_DATA,
+        KM_SKB_DATA_SOFTIRQ,
+        KM_USER0,
+        KM_USER1,
+	KM_BIO_SRC_IRQ,
+	KM_BIO_DST_IRQ,
+	KM_PTE0,
+	KM_PTE1,
+	KM_IRQ0,
+	KM_IRQ1,
+	KM_SOFTIRQ0,
+	KM_SOFTIRQ1,
+	KM_TYPE_NR
+};
+ 
+#endif
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/include/asm-frv/linkage.h linux-2.6.10-rc1-mm3-frv/include/asm-frv/linkage.h
--- /warthog/kernels/linux-2.6.10-rc1-mm3/include/asm-frv/linkage.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/include/asm-frv/linkage.h	2004-11-05 14:13:04.046483696 +0000
@@ -0,0 +1,7 @@
+#ifndef __ASM_LINKAGE_H
+#define __ASM_LINKAGE_H
+
+#define __ALIGN		.align 4
+#define __ALIGN_STR	".align 4"
+
+#endif
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/include/asm-frv/local.h linux-2.6.10-rc1-mm3-frv/include/asm-frv/local.h
--- /warthog/kernels/linux-2.6.10-rc1-mm3/include/asm-frv/local.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/include/asm-frv/local.h	2004-11-05 14:13:04.051483273 +0000
@@ -0,0 +1,6 @@
+#ifndef _ASM_LOCAL_H
+#define _ASM_LOCAL_H
+
+#include <asm-generic/local.h>
+
+#endif /* _ASM_LOCAL_H */
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/include/asm-frv/math-emu.h linux-2.6.10-rc1-mm3-frv/include/asm-frv/math-emu.h
--- /warthog/kernels/linux-2.6.10-rc1-mm3/include/asm-frv/math-emu.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/include/asm-frv/math-emu.h	2004-11-05 14:13:04.000000000 +0000
@@ -0,0 +1,301 @@
+#ifndef _ASM_MATH_EMU_H
+#define _ASM_MATH_EMU_H
+
+#include <asm/setup.h>
+#include <linux/linkage.h>
+
+/* Status Register bits */
+
+/* accrued exception bits */
+#define FPSR_AEXC_INEX	3
+#define FPSR_AEXC_DZ	4
+#define FPSR_AEXC_UNFL	5
+#define FPSR_AEXC_OVFL	6
+#define FPSR_AEXC_IOP	7
+
+/* exception status bits */
+#define FPSR_EXC_INEX1	8
+#define FPSR_EXC_INEX2	9
+#define FPSR_EXC_DZ	10
+#define FPSR_EXC_UNFL	11
+#define FPSR_EXC_OVFL	12
+#define FPSR_EXC_OPERR	13
+#define FPSR_EXC_SNAN	14
+#define FPSR_EXC_BSUN	15
+
+/* quotient byte, assumes big-endian, of course */
+#define FPSR_QUOTIENT(fpsr) (*((signed char *) &(fpsr) + 1))
+
+/* condition code bits */
+#define FPSR_CC_NAN	24
+#define FPSR_CC_INF	25
+#define FPSR_CC_Z	26
+#define FPSR_CC_NEG	27
+
+
+/* Control register bits */
+
+/* rounding mode */
+#define	FPCR_ROUND_RN	0		/* round to nearest/even */
+#define FPCR_ROUND_RZ	1		/* round to zero */
+#define FPCR_ROUND_RM	2		/* minus infinity */
+#define FPCR_ROUND_RP	3		/* plus infinity */
+
+/* rounding precision */
+#define FPCR_PRECISION_X	0	/* long double */
+#define FPCR_PRECISION_S	1	/* double */
+#define FPCR_PRECISION_D	2	/* float */
+
+
+/* Flags to select the debugging output */
+#define PDECODE		0
+#define PEXECUTE	1
+#define PCONV		2
+#define PNORM		3
+#define PREGISTER	4
+#define PINSTR		5
+#define PUNIMPL		6
+#define PMOVEM		7
+
+#define PMDECODE	(1<<PDECODE)
+#define PMEXECUTE	(1<<PEXECUTE)
+#define PMCONV		(1<<PCONV)
+#define PMNORM		(1<<PNORM)
+#define PMREGISTER	(1<<PREGISTER)
+#define PMINSTR		(1<<PINSTR)
+#define PMUNIMPL	(1<<PUNIMPL)
+#define PMMOVEM		(1<<PMOVEM)
+
+#ifndef __ASSEMBLY__
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+
+union fp_mant64 {
+	unsigned long long m64;
+	unsigned long m32[2];
+};
+
+union fp_mant128 {
+	unsigned long long m64[2];
+	unsigned long m32[4];
+};
+
+/* internal representation of extended fp numbers */
+struct fp_ext {
+	unsigned char lowmant;
+	unsigned char sign;
+	unsigned short exp;
+	union fp_mant64 mant;
+};
+
+/* C representation of FPU registers */
+/* NOTE: if you change this, you have to change the assembler offsets
+   below and the size in <asm/fpu.h>, too */
+struct fp_data {
+	struct fp_ext fpreg[8];
+	unsigned int fpcr;
+	unsigned int fpsr;
+	unsigned int fpiar;
+	unsigned short prec;
+	unsigned short rnd;
+	struct fp_ext temp[2];
+};
+
+#if FPU_EMU_DEBUG
+extern unsigned int fp_debugprint;
+
+#define dprint(bit, fmt, args...) ({			\
+	if (fp_debugprint & (1 << (bit)))		\
+		printk(fmt, ## args);			\
+})
+#else
+#define dprint(bit, fmt, args...)
+#endif
+
+#define uprint(str) ({					\
+	static int __count = 3;				\
+							\
+	if (__count > 0) {				\
+		printk("You just hit an unimplemented "	\
+		       "fpu instruction (%s)\n", str);	\
+		printk("Please report this to ....\n");	\
+		__count--;				\
+	}						\
+})
+
+#define FPDATA		((struct fp_data *)current->thread.fp)
+
+#else	/* __ASSEMBLY__ */
+
+#define FPDATA		%a2
+
+/* offsets from the base register to the floating point data in the task struct */
+#define FPD_FPREG	(TASK_THREAD+THREAD_FPREG+0)
+#define FPD_FPCR	(TASK_THREAD+THREAD_FPREG+96)
+#define FPD_FPSR	(TASK_THREAD+THREAD_FPREG+100)
+#define FPD_FPIAR	(TASK_THREAD+THREAD_FPREG+104)
+#define FPD_PREC	(TASK_THREAD+THREAD_FPREG+108)
+#define FPD_RND		(TASK_THREAD+THREAD_FPREG+110)
+#define FPD_TEMPFP1	(TASK_THREAD+THREAD_FPREG+112)
+#define FPD_TEMPFP2	(TASK_THREAD+THREAD_FPREG+124)
+#define FPD_SIZEOF	(TASK_THREAD+THREAD_FPREG+136)
+
+/* offsets on the stack to access saved registers,
+ * these are only used during instruction decoding
+ * where we always know how deep we're on the stack.
+ */
+#define FPS_DO		(PT_D0)
+#define FPS_D1		(PT_D1)
+#define FPS_D2		(PT_D2)
+#define FPS_A0		(PT_A0)
+#define FPS_A1		(PT_A1)
+#define FPS_A2		(PT_A2)
+#define FPS_SR		(PT_SR)
+#define FPS_PC		(PT_PC)
+#define FPS_EA		(PT_PC+6)
+#define FPS_PC2		(PT_PC+10)
+
+.macro	fp_get_fp_reg
+	lea	(FPD_FPREG,FPDATA,%d0.w*4),%a0
+	lea	(%a0,%d0.w*8),%a0
+.endm
+
+/* Macros used to get/put the current program counter.
+ * 020/030 use a different stack frame then 040/060, for the
+ * 040/060 the return pc points already to the next location,
+ * so this only needs to be modified for jump instructions.
+ */
+.macro	fp_get_pc dest
+	move.l	(FPS_PC+4,%sp),\dest
+.endm
+
+.macro	fp_put_pc src,jump=0
+	move.l	\src,(FPS_PC+4,%sp)
+.endm
+
+.macro	fp_get_instr_data	f,s,dest,label
+	getuser	\f,%sp@(FPS_PC+4)@(0),\dest,\label,%sp@(FPS_PC+4)
+	addq.l	#\s,%sp@(FPS_PC+4)
+.endm
+
+.macro	fp_get_instr_word	dest,label,addr
+	fp_get_instr_data	w,2,\dest,\label,\addr
+.endm
+
+.macro	fp_get_instr_long	dest,label,addr
+	fp_get_instr_data	l,4,\dest,\label,\addr
+.endm
+
+/* These macros are used to read from/write to user space
+ * on error we jump to the fixup section, load the fault
+ * address into %a0 and jump to the exit.
+ * (derived from <asm/uaccess.h>)
+ */
+.macro	getuser	size,src,dest,label,addr
+|	printf	,"[\size<%08x]",1,\addr
+.Lu1\@:	moves\size	\src,\dest
+
+	.section .fixup,"ax"
+	.even
+.Lu2\@:	move.l	\addr,%a0
+	jra	\label
+	.previous
+
+	.section __ex_table,"a"
+	.align	4
+	.long	.Lu1\@,.Lu2\@
+	.previous
+.endm
+
+.macro	putuser	size,src,dest,label,addr
+|	printf	,"[\size>%08x]",1,\addr
+.Lu1\@:	moves\size	\src,\dest
+.Lu2\@:
+
+	.section .fixup,"ax"
+	.even
+.Lu3\@:	move.l	\addr,%a0
+	jra	\label
+	.previous
+
+	.section __ex_table,"a"
+	.align	4
+	.long	.Lu1\@,.Lu3\@
+	.long	.Lu2\@,.Lu3\@
+	.previous
+.endm
+
+
+.macro	movestack	nr,arg1,arg2,arg3,arg4,arg5
+	.if	\nr
+	movestack	(\nr-1),\arg2,\arg3,\arg4,\arg5
+	move.l	\arg1,-(%sp)
+	.endif
+.endm
+
+.macro	printf	bit=-1,string,nr=0,arg1,arg2,arg3,arg4,arg5
+#ifdef FPU_EMU_DEBUG
+	.data
+.Lpdata\@:
+	.string	"\string"
+	.previous
+
+	movem.l	%d0/%d1/%a0/%a1,-(%sp)
+	.if	\bit+1
+#if 0
+	moveq	#\bit,%d0
+	andw	#7,%d0
+	btst	%d0,fp_debugprint+((31-\bit)/8)
+#else
+	btst	#\bit,fp_debugprint+((31-\bit)/8)
+#endif
+	jeq	.Lpskip\@
+	.endif
+	movestack	\nr,\arg1,\arg2,\arg3,\arg4,\arg5
+	pea	.Lpdata\@
+	jsr	printk
+	lea	((\nr+1)*4,%sp),%sp
+.Lpskip\@:
+	movem.l	(%sp)+,%d0/%d1/%a0/%a1
+#endif
+.endm
+
+.macro	printx	bit,fp
+#ifdef FPU_EMU_DEBUG
+	movem.l	%d0/%a0,-(%sp)
+	lea	\fp,%a0
+#if 0
+	moveq	#'+',%d0
+	tst.w	(%a0)
+	jeq	.Lx1\@
+	moveq	#'-',%d0
+.Lx1\@:	printf	\bit," %c",1,%d0
+	move.l	(4,%a0),%d0
+	bclr	#31,%d0
+	jne	.Lx2\@
+	printf	\bit,"0."
+	jra	.Lx3\@
+.Lx2\@:	printf	\bit,"1."
+.Lx3\@:	printf	\bit,"%08x%08x",2,%d0,%a0@(8)
+	move.w	(2,%a0),%d0
+	ext.l	%d0
+	printf	\bit,"E%04x",1,%d0
+#else
+	printf	\bit," %08x%08x%08x",3,%a0@,%a0@(4),%a0@(8)
+#endif
+	movem.l	(%sp)+,%d0/%a0
+#endif
+.endm
+
+.macro	debug	instr,args
+#ifdef FPU_EMU_DEBUG
+	\instr	\args
+#endif
+.endm
+
+
+#endif	/* __ASSEMBLY__ */
+
+#endif	/* _ASM_FRV_MATH_EMU_H */
+
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/include/asm-frv/mb86943a.h linux-2.6.10-rc1-mm3-frv/include/asm-frv/mb86943a.h
--- /warthog/kernels/linux-2.6.10-rc1-mm3/include/asm-frv/mb86943a.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/include/asm-frv/mb86943a.h	2004-11-05 14:13:04.060482513 +0000
@@ -0,0 +1,39 @@
+/* mb86943a.h: MB86943 SPARClite <-> PCI bridge registers
+ *
+ * Copyright (C) 2003 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * 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.
+ */
+
+#ifndef _ASM_MB86943A_H
+#define _ASM_MB86943A_H
+
+#include <asm/mb-regs.h>
+
+#define __reg_MB86943_sl_ctl		*(volatile uint32_t *) (__region_CS1 + 0x00)
+
+#define MB86943_SL_CTL_BUS_WIDTH_64	0x00000001
+#define MB86943_SL_CTL_AS_HOST		0x00000002
+#define MB86943_SL_CTL_DRCT_MASTER_SWAP	0x00000004
+#define MB86943_SL_CTL_DRCT_SLAVE_SWAP	0x00000008
+#define MB86943_SL_CTL_PCI_CONFIG_SWAP	0x00000010
+#define MB86943_SL_CTL_ECS0_ENABLE	0x00000020
+#define MB86943_SL_CTL_ECS1_ENABLE	0x00000040
+#define MB86943_SL_CTL_ECS2_ENABLE	0x00000080
+
+#define __reg_MB86943_ecs_ctl(N)	*(volatile uint32_t *) (__region_CS1 + 0x08 + (0x08*(N)))
+#define __reg_MB86943_ecs_range(N)	*(volatile uint32_t *) (__region_CS1 + 0x20 + (0x10*(N)))
+#define __reg_MB86943_ecs_base(N)	*(volatile uint32_t *) (__region_CS1 + 0x28 + (0x10*(N)))
+
+#define __reg_MB86943_sl_pci_io_range	*(volatile uint32_t *) (__region_CS1 + 0x50)
+#define __reg_MB86943_sl_pci_io_base	*(volatile uint32_t *) (__region_CS1 + 0x58)
+#define __reg_MB86943_sl_pci_mem_range	*(volatile uint32_t *) (__region_CS1 + 0x60)
+#define __reg_MB86943_sl_pci_mem_base	*(volatile uint32_t *) (__region_CS1 + 0x68)
+#define __reg_MB86943_pci_sl_io_base	*(volatile uint32_t *) (__region_CS1 + 0x70)
+#define __reg_MB86943_pci_sl_mem_base	*(volatile uint32_t *) (__region_CS1 + 0x78)
+
+#endif /* _ASM_MB86943A_H */
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/include/asm-frv/mb93091-fpga-irqs.h linux-2.6.10-rc1-mm3-frv/include/asm-frv/mb93091-fpga-irqs.h
--- /warthog/kernels/linux-2.6.10-rc1-mm3/include/asm-frv/mb93091-fpga-irqs.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/include/asm-frv/mb93091-fpga-irqs.h	2004-11-05 14:13:04.065482091 +0000
@@ -0,0 +1,44 @@
+/* mb93091-fpga-irqs.h: MB93091 CPU board FPGA IRQs
+ *
+ * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * 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.
+ */
+
+#ifndef _ASM_MB93091_FPGA_IRQS_H
+#define _ASM_MB93091_FPGA_IRQS_H
+
+#ifndef __ASSEMBLY__
+
+#include <asm/irq-routing.h>
+
+#define IRQ_BASE_FPGA		(NR_IRQ_ACTIONS_PER_GROUP * 1)
+
+/* IRQ IDs presented to drivers */
+enum {
+	IRQ_FPGA__UNUSED			= IRQ_BASE_FPGA,
+	IRQ_FPGA_SYSINT_BUS_EXPANSION_1,
+	IRQ_FPGA_SL_BUS_EXPANSION_2,
+	IRQ_FPGA_PCI_INTD,
+	IRQ_FPGA_PCI_INTC,
+	IRQ_FPGA_PCI_INTB,
+	IRQ_FPGA_PCI_INTA,
+	IRQ_FPGA_SL_BUS_EXPANSION_7,
+	IRQ_FPGA_SYSINT_BUS_EXPANSION_8,
+	IRQ_FPGA_SL_BUS_EXPANSION_9,
+	IRQ_FPGA_MB86943_PCI_INTA,
+	IRQ_FPGA_MB86943_SLBUS_SIDE,
+	IRQ_FPGA_RTL8029_INTA,
+	IRQ_FPGA_SYSINT_BUS_EXPANSION_13,
+	IRQ_FPGA_SL_BUS_EXPANSION_14,
+	IRQ_FPGA_NMI,
+};
+
+
+#endif /* !__ASSEMBLY__ */
+
+#endif /* _ASM_MB93091_FPGA_IRQS_H */
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/include/asm-frv/mb93093-fpga-irqs.h linux-2.6.10-rc1-mm3-frv/include/asm-frv/mb93093-fpga-irqs.h
--- /warthog/kernels/linux-2.6.10-rc1-mm3/include/asm-frv/mb93093-fpga-irqs.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/include/asm-frv/mb93093-fpga-irqs.h	2004-11-05 14:13:04.000000000 +0000
@@ -0,0 +1,31 @@
+/* mb93093-fpga-irqs.h: MB93093 CPU board FPGA IRQs
+ *
+ * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * 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.
+ */
+
+#ifndef _ASM_MB93093_FPGA_IRQS_H
+#define _ASM_MB93093_FPGA_IRQS_H
+
+#ifndef __ASSEMBLY__
+
+#include <asm/irq-routing.h>
+
+#define IRQ_BASE_FPGA		(NR_IRQ_ACTIONS_PER_GROUP * 1)
+
+/* IRQ IDs presented to drivers */
+enum {
+	IRQ_FPGA_PUSH_BUTTON_SW1_5		= IRQ_BASE_FPGA + 8,
+	IRQ_FPGA_ROCKER_C_SW8			= IRQ_BASE_FPGA + 9,
+	IRQ_FPGA_ROCKER_C_SW9			= IRQ_BASE_FPGA + 10,
+};
+
+
+#endif /* !__ASSEMBLY__ */
+
+#endif /* _ASM_MB93093_FPGA_IRQS_H */
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/include/asm-frv/mb93493-irqs.h linux-2.6.10-rc1-mm3-frv/include/asm-frv/mb93493-irqs.h
--- /warthog/kernels/linux-2.6.10-rc1-mm3/include/asm-frv/mb93493-irqs.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/include/asm-frv/mb93493-irqs.h	2004-11-05 14:13:04.072481500 +0000
@@ -0,0 +1,52 @@
+/* mb93493-irqs.h: MB93493 companion chip IRQs
+ *
+ * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * 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.
+ */
+
+#ifndef _ASM_MB93493_IRQS_H
+#define _ASM_MB93493_IRQS_H
+
+#ifndef __ASSEMBLY__
+
+#include <asm/irq-routing.h>
+
+#define IRQ_BASE_MB93493	(NR_IRQ_ACTIONS_PER_GROUP * 2)
+
+/* IRQ IDs presented to drivers */
+enum {
+	IRQ_MB93493_VDC			= IRQ_BASE_MB93493 + 0,
+	IRQ_MB93493_VCC			= IRQ_BASE_MB93493 + 1,
+	IRQ_MB93493_AUDIO_OUT		= IRQ_BASE_MB93493 + 2,
+	IRQ_MB93493_I2C_0		= IRQ_BASE_MB93493 + 3,
+	IRQ_MB93493_I2C_1		= IRQ_BASE_MB93493 + 4,
+	IRQ_MB93493_USB			= IRQ_BASE_MB93493 + 5,
+	IRQ_MB93493_LOCAL_BUS		= IRQ_BASE_MB93493 + 7,
+	IRQ_MB93493_PCMCIA		= IRQ_BASE_MB93493 + 8,
+	IRQ_MB93493_GPIO		= IRQ_BASE_MB93493 + 9,
+	IRQ_MB93493_AUDIO_IN		= IRQ_BASE_MB93493 + 10,
+};
+
+/* IRQ multiplexor mappings */
+#define ROUTE_VIA_IRQ0	0	/* route IRQ by way of CPU external IRQ 0 */
+#define ROUTE_VIA_IRQ1	1	/* route IRQ by way of CPU external IRQ 1 */
+
+#define IRQ_MB93493_VDC_ROUTE		ROUTE_VIA_IRQ0
+#define IRQ_MB93493_VCC_ROUTE		ROUTE_VIA_IRQ1
+#define IRQ_MB93493_AUDIO_OUT_ROUTE	ROUTE_VIA_IRQ1
+#define IRQ_MB93493_I2C_0_ROUTE		ROUTE_VIA_IRQ1
+#define IRQ_MB93493_I2C_1_ROUTE		ROUTE_VIA_IRQ1
+#define IRQ_MB93493_USB_ROUTE		ROUTE_VIA_IRQ1
+#define IRQ_MB93493_LOCAL_BUS_ROUTE	ROUTE_VIA_IRQ1
+#define IRQ_MB93493_PCMCIA_ROUTE	ROUTE_VIA_IRQ1
+#define IRQ_MB93493_GPIO_ROUTE		ROUTE_VIA_IRQ1
+#define IRQ_MB93493_AUDIO_IN_ROUTE	ROUTE_VIA_IRQ1
+
+#endif /* !__ASSEMBLY__ */
+
+#endif /* _ASM_MB93493_IRQS_H */
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/include/asm-frv/mb93493-regs.h linux-2.6.10-rc1-mm3-frv/include/asm-frv/mb93493-regs.h
--- /warthog/kernels/linux-2.6.10-rc1-mm3/include/asm-frv/mb93493-regs.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/include/asm-frv/mb93493-regs.h	2004-11-05 14:13:04.077481078 +0000
@@ -0,0 +1,279 @@
+/* mb93493-regs.h: MB93493 companion chip registers
+ *
+ * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * 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.
+ */
+
+#ifndef _ASM_MB93493_REGS_H
+#define _ASM_MB93493_REGS_H
+
+#include <asm/mb-regs.h>
+#include <asm/mb93493-irqs.h>
+
+#define __get_MB93493(X)	({ *(volatile unsigned long *)(__region_CS3 + (X)); })
+
+#define __set_MB93493(X,V)						\
+do {									\
+	*(volatile unsigned long *)(__region_CS3 + (X)) = (V); mb();	\
+} while(0)
+
+#define __get_MB93493_STSR(X)	__get_MB93493(0x3c0 + (X) * 4)
+#define __set_MB93493_STSR(X,V)	__set_MB93493(0x3c0 + (X) * 4, (V))
+#define MB93493_STSR_EN
+
+#define __get_MB93493_IQSR(X)	__get_MB93493(0x3d0 + (X) * 4)
+#define __set_MB93493_IQSR(X,V)	__set_MB93493(0x3d0 + (X) * 4, (V))
+
+#define __get_MB93493_DQSR(X)	__get_MB93493(0x3e0 + (X) * 4)
+#define __set_MB93493_DQSR(X,V)	__set_MB93493(0x3e0 + (X) * 4, (V))
+
+#define __get_MB93493_LBSER()	__get_MB93493(0x3f0)
+#define __set_MB93493_LBSER(V)	__set_MB93493(0x3f0, (V))
+
+#define MB93493_LBSER_VDC	0x00010000
+#define MB93493_LBSER_VCC	0x00020000
+#define MB93493_LBSER_AUDIO	0x00040000
+#define MB93493_LBSER_I2C_0	0x00080000
+#define MB93493_LBSER_I2C_1	0x00100000
+#define MB93493_LBSER_USB	0x00200000
+#define MB93493_LBSER_GPIO	0x00800000
+#define MB93493_LBSER_PCMCIA	0x01000000
+
+#define __get_MB93493_LBSR()	__get_MB93493(0x3fc)
+#define __set_MB93493_LBSR(V)	__set_MB93493(0x3fc, (V))
+
+/*
+ * video display controller
+ */
+#define __get_MB93493_VDC(X)	__get_MB93493(MB93493_VDC_##X)
+#define __set_MB93493_VDC(X,V)	__set_MB93493(MB93493_VDC_##X, (V))
+
+#define MB93493_VDC_RCURSOR	0x140	/* cursor position */
+#define MB93493_VDC_RCT1	0x144	/* cursor colour 1 */
+#define MB93493_VDC_RCT2	0x148	/* cursor colour 2 */
+#define MB93493_VDC_RHDC	0x150	/* horizontal display period */
+#define MB93493_VDC_RH_MARGINS	0x154	/* horizontal margin sizes */
+#define MB93493_VDC_RVDC	0x158	/* vertical display period */
+#define MB93493_VDC_RV_MARGINS	0x15c	/* vertical margin sizes */
+#define MB93493_VDC_RC		0x170	/* VDC control */
+#define MB93493_VDC_RCLOCK	0x174	/* clock divider, DMA req delay */
+#define MB93493_VDC_RBLACK	0x178	/* black insert sizes */
+#define MB93493_VDC_RS		0x17c	/* VDC status */
+
+#define __addr_MB93493_VDC_BCI(X)  ({ (volatile unsigned long *)(__region_CS3 + 0x000 + (X)); })
+#define __addr_MB93493_VDC_TPO(X)  (__region_CS3 + 0x1c0 + (X))
+
+#define VDC_TPO_WIDTH		32
+
+#define VDC_RC_DSR		0x00000080	/* VDC master reset */
+
+#define VDC_RS_IT		0x00060000	/* interrupt indicators */
+#define VDC_RS_IT_UNDERFLOW	0x00040000	/* - underflow event */
+#define VDC_RS_IT_VSYNC		0x00020000	/* - VSYNC event */
+#define VDC_RS_DFI		0x00010000	/* current interlace field number */
+#define VDC_RS_DFI_TOP		0x00000000	/* - top field */
+#define VDC_RS_DFI_BOTTOM	0x00010000	/* - bottom field */
+#define VDC_RS_DCSR		0x00000010	/* cursor state */
+#define VDC_RS_DCM		0x00000003	/* display mode */
+#define VDC_RS_DCM_DISABLED	0x00000000	/* - display disabled */
+#define VDC_RS_DCM_STOPPED	0x00000001	/* - VDC stopped */
+#define VDC_RS_DCM_FREERUNNING	0x00000002	/* - VDC free-running */
+#define VDC_RS_DCM_TRANSFERRING	0x00000003	/* - data being transferred to VDC */
+
+/*
+ * video capture controller
+ */
+#define __get_MB93493_VCC(X)	__get_MB93493(MB93493_VCC_##X)
+#define __set_MB93493_VCC(X,V)	__set_MB93493(MB93493_VCC_##X, (V))
+
+#define MB93493_VCC_RREDUCT	0x104	/* reduction rate */
+#define MB93493_VCC_RHY		0x108	/* horizontal brightness filter coefficients */
+#define MB93493_VCC_RHC		0x10c	/* horizontal colour-difference filter coefficients */
+#define MB93493_VCC_RHSIZE	0x110	/* horizontal cycle sizes */
+#define MB93493_VCC_RHBC	0x114	/* horizontal back porch size */
+#define MB93493_VCC_RVCC	0x118	/* vertical capture period */
+#define MB93493_VCC_RVBC	0x11c	/* vertical back porch period */
+#define MB93493_VCC_RV		0x120	/* vertical filter coefficients */
+#define MB93493_VCC_RDTS	0x128	/* DMA transfer size */
+#define MB93493_VCC_RDTS_4B	0x01000000	/* 4-byte transfer */
+#define MB93493_VCC_RDTS_32B	0x03000000	/* 32-byte transfer */
+#define MB93493_VCC_RDTS_SHIFT	24
+#define MB93493_VCC_RCC		0x130	/* VCC control */
+#define MB93493_VCC_RIS		0x134	/* VCC interrupt status */
+
+#define __addr_MB93493_VCC_TPI(X)  (__region_CS3 + 0x180 + (X))
+
+#define VCC_RHSIZE_RHCC		0x000007ff
+#define VCC_RHSIZE_RHCC_SHIFT	0
+#define VCC_RHSIZE_RHTCC	0x0fff0000
+#define VCC_RHSIZE_RHTCC_SHIFT	16
+
+#define VCC_RVBC_RVBC		0x00003f00
+#define VCC_RVBC_RVBC_SHIFT	8
+
+#define VCC_RREDUCT_RHR		0x07ff0000
+#define VCC_RREDUCT_RHR_SHIFT	16
+#define VCC_RREDUCT_RVR		0x000007ff
+#define VCC_RREDUCT_RVR_SHIFT	0
+
+#define VCC_RCC_CE		0x00000001	/* VCC enable */
+#define VCC_RCC_CS		0x00000002	/* request video capture start */
+#define VCC_RCC_CPF		0x0000000c	/* pixel format */
+#define VCC_RCC_CPF_YCBCR_16	0x00000000	/* - YCbCr 4:2:2 16-bit format */
+#define VCC_RCC_CPF_RGB		0x00000004	/* - RGB 4:4:4 format */
+#define VCC_RCC_CPF_YCBCR_24	0x00000008	/* - YCbCr 4:2:2 24-bit format */
+#define VCC_RCC_CPF_BT656	0x0000000c	/* - ITU R-BT.656 format */
+#define VCC_RCC_CPF_SHIFT	2
+#define VCC_RCC_CSR		0x00000080	/* request reset */
+#define VCC_RCC_HSIP		0x00000100	/* HSYNC polarity */
+#define VCC_RCC_HSIP_LOACT	0x00000000	/* - low active */
+#define VCC_RCC_HSIP_HIACT	0x00000100	/* - high active */
+#define VCC_RCC_VSIP		0x00000200	/* VSYNC polarity */
+#define VCC_RCC_VSIP_LOACT	0x00000000	/* - low active */
+#define VCC_RCC_VSIP_HIACT	0x00000200	/* - high active */
+#define VCC_RCC_CIE		0x00000800	/* interrupt enable */
+#define VCC_RCC_CFP		0x00001000	/* RGB pixel packing */
+#define VCC_RCC_CFP_4TO3	0x00000000	/* - pack 4 pixels into 3 words */
+#define VCC_RCC_CFP_1TO1	0x00001000	/* - pack 1 pixel into 1 words */
+#define VCC_RCC_CSM		0x00006000	/* interlace specification */
+#define VCC_RCC_CSM_ONEPASS	0x00002000	/* - non-interlaced */
+#define VCC_RCC_CSM_INTERLACE	0x00004000	/* - interlaced */
+#define VCC_RCC_CSM_SHIFT	13
+#define VCC_RCC_ES		0x00008000	/* capture start polarity */
+#define VCC_RCC_ES_NEG		0x00000000	/* - negative edge */
+#define VCC_RCC_ES_POS		0x00008000	/* - positive edge */
+#define VCC_RCC_IFI		0x00080000	/* inferlace field evaluation reverse */
+#define VCC_RCC_FDTS		0x00300000	/* interlace field start */
+#define VCC_RCC_FDTS_3_8	0x00000000	/* - 3/8 of horizontal entire cycle */
+#define VCC_RCC_FDTS_1_4	0x00100000	/* - 1/4 of horizontal entire cycle */
+#define VCC_RCC_FDTS_7_16	0x00200000	/* - 7/16 of horizontal entire cycle */
+#define VCC_RCC_FDTS_SHIFT	20
+#define VCC_RCC_MOV		0x00400000	/* test bit - always set to 1 */
+#define VCC_RCC_STP		0x00800000	/* request video capture stop */
+#define VCC_RCC_TO		0x01000000	/* input during top-field only */
+
+#define VCC_RIS_VSYNC		0x01000000	/* VSYNC interrupt */
+#define VCC_RIS_OV		0x02000000	/* overflow interrupt */
+#define VCC_RIS_BOTTOM		0x08000000	/* interlace bottom field */
+#define VCC_RIS_STARTED		0x10000000	/* capture started */
+
+/*
+ * I2C
+ */
+#define MB93493_I2C_BSR 	0x340		/* bus status */
+#define MB93493_I2C_BCR		0x344		/* bus control */
+#define MB93493_I2C_CCR		0x348		/* clock control */
+#define MB93493_I2C_ADR		0x34c		/* address */
+#define MB93493_I2C_DTR		0x350		/* data */
+#define MB93493_I2C_BC2R	0x35c		/* bus control 2 */
+
+#define __addr_MB93493_I2C(port,X)   (__region_CS3 + MB93493_I2C_##X + ((port)*0x20))
+#define __get_MB93493_I2C(port,X)    __get_MB93493(MB93493_I2C_##X + ((port)*0x20))
+#define __set_MB93493_I2C(port,X,V)  __set_MB93493(MB93493_I2C_##X + ((port)*0x20), (V))
+
+#define I2C_BSR_BB	(1 << 7)
+
+/*
+ * audio controller (I2S) registers
+ */
+#define __get_MB93493_I2S(X)	__get_MB93493(MB93493_I2S_##X)
+#define __set_MB93493_I2S(X,V)	__set_MB93493(MB93493_I2S_##X, (V))
+
+#define MB93493_I2S_ALDR	0x300		/* L-channel data */
+#define MB93493_I2S_ARDR	0x304		/* R-channel data */
+#define MB93493_I2S_APDR	0x308		/* 16-bit packed data */
+#define MB93493_I2S_AISTR	0x310		/* status */
+#define MB93493_I2S_AICR	0x314		/* control */
+
+#define __addr_MB93493_I2S_ALDR(X)	(__region_CS3 + MB93493_I2S_ALDR + (X))
+#define __addr_MB93493_I2S_ARDR(X)	(__region_CS3 + MB93493_I2S_ARDR + (X))
+#define __addr_MB93493_I2S_APDR(X)	(__region_CS3 + MB93493_I2S_APDR + (X))
+#define __addr_MB93493_I2S_ADR(X)	(__region_CS3 + 0x320 + (X))
+
+#define I2S_AISTR_OTST		0x00000003	/* status of output data transfer */
+#define I2S_AISTR_OTR		0x00000010	/* output transfer request pending */
+#define I2S_AISTR_OUR		0x00000020	/* output FIFO underrun detected */
+#define I2S_AISTR_OOR		0x00000040	/* output FIFO overrun detected */
+#define I2S_AISTR_ODS		0x00000100	/* output DMA transfer size */
+#define I2S_AISTR_ODE		0x00000400	/* output DMA transfer request enable */
+#define I2S_AISTR_OTRIE		0x00001000	/* output transfer request interrupt enable */
+#define I2S_AISTR_OURIE		0x00002000	/* output FIFO underrun interrupt enable */
+#define I2S_AISTR_OORIE		0x00004000	/* output FIFO overrun interrupt enable */
+#define I2S_AISTR__OUT_MASK	0x00007570
+#define I2S_AISTR_ITST		0x00030000	/* status of input data transfer */
+#define I2S_AISTR_ITST_SHIFT	16
+#define I2S_AISTR_ITR		0x00100000	/* input transfer request pending */
+#define I2S_AISTR_IUR		0x00200000	/* input FIFO underrun detected */
+#define I2S_AISTR_IOR		0x00400000	/* input FIFO overrun detected */
+#define I2S_AISTR_IDS		0x01000000	/* input DMA transfer size */
+#define I2S_AISTR_IDE		0x04000000	/* input DMA transfer request enable */
+#define I2S_AISTR_ITRIE		0x10000000	/* input transfer request interrupt enable */
+#define I2S_AISTR_IURIE		0x20000000	/* input FIFO underrun interrupt enable */
+#define I2S_AISTR_IORIE		0x40000000	/* input FIFO overrun interrupt enable */
+#define I2S_AISTR__IN_MASK	0x75700000
+
+#define I2S_AICR_MI		0x00000001	/* mono input requested */
+#define I2S_AICR_AMI		0x00000002	/* relation between LRCKI/FS1 and SDI */
+#define I2S_AICR_LRI		0x00000004	/* function of LRCKI pin */
+#define I2S_AICR_SDMI		0x00000070	/* format of input audio data */
+#define I2S_AICR_SDMI_SHIFT	4
+#define I2S_AICR_CLI		0x00000080	/* input FIFO clearing control */
+#define I2S_AICR_IM		0x00000300	/* input state control */
+#define I2S_AICR_IM_SHIFT	8
+#define I2S_AICR__IN_MASK	0x000003f7
+#define I2S_AICR_MO		0x00001000	/* mono output requested */
+#define I2S_AICR_AMO		0x00002000	/* relation between LRCKO/FS0 and SDO */
+#define I2S_AICR_AMO_SHIFT	13
+#define I2S_AICR_LRO		0x00004000	/* function of LRCKO pin */
+#define I2S_AICR_SDMO		0x00070000	/* format of output audio data */
+#define I2S_AICR_SDMO_SHIFT	16
+#define I2S_AICR_CLO		0x00080000	/* output FIFO clearing control */
+#define I2S_AICR_OM		0x00100000	/* output state control */
+#define I2S_AICR__OUT_MASK	0x001f7000
+#define I2S_AICR_DIV		0x03000000	/* frequency division rate */
+#define I2S_AICR_DIV_SHIFT	24
+#define I2S_AICR_FL		0x20000000	/* frame length */
+#define I2S_AICR_FS		0x40000000	/* frame sync method */
+#define I2S_AICR_ME		0x80000000	/* master enable */
+
+/*
+ * PCMCIA
+ */
+#define __addr_MB93493_PCMCIA(X)  ((volatile unsigned long *)(__region_CS5 + (X)))
+
+/*
+ * GPIO
+ */
+#define __get_MB93493_GPIO_PDR(X)	__get_MB93493(0x380 + (X) * 0xc0)
+#define __set_MB93493_GPIO_PDR(X,V)	__set_MB93493(0x380 + (X) * 0xc0, (V))
+
+#define __get_MB93493_GPIO_GPDR(X)	__get_MB93493(0x384 + (X) * 0xc0)
+#define __set_MB93493_GPIO_GPDR(X,V)	__set_MB93493(0x384 + (X) * 0xc0, (V))
+
+#define __get_MB93493_GPIO_SIR(X)	__get_MB93493(0x388 + (X) * 0xc0)
+#define __set_MB93493_GPIO_SIR(X,V)	__set_MB93493(0x388 + (X) * 0xc0, (V))
+
+#define __get_MB93493_GPIO_SOR(X)	__get_MB93493(0x38c + (X) * 0xc0)
+#define __set_MB93493_GPIO_SOR(X,V)	__set_MB93493(0x38c + (X) * 0xc0, (V))
+
+#define __get_MB93493_GPIO_PDSR(X)	__get_MB93493(0x390 + (X) * 0xc0)
+#define __set_MB93493_GPIO_PDSR(X,V)	__set_MB93493(0x390 + (X) * 0xc0, (V))
+
+#define __get_MB93493_GPIO_PDCR(X)	__get_MB93493(0x394 + (X) * 0xc0)
+#define __set_MB93493_GPIO_PDCR(X,V)	__set_MB93493(0x394 + (X) * 0xc0, (V))
+
+#define __get_MB93493_GPIO_INTST(X)	__get_MB93493(0x398 + (X) * 0xc0)
+#define __set_MB93493_GPIO_INTST(X,V)	__set_MB93493(0x398 + (X) * 0xc0, (V))
+
+#define __get_MB93493_GPIO_IEHL(X)	__get_MB93493(0x39c + (X) * 0xc0)
+#define __set_MB93493_GPIO_IEHL(X,V)	__set_MB93493(0x39c + (X) * 0xc0, (V))
+
+#define __get_MB93493_GPIO_IELH(X)	__get_MB93493(0x3a0 + (X) * 0xc0)
+#define __set_MB93493_GPIO_IELH(X,V)	__set_MB93493(0x3a0 + (X) * 0xc0, (V))
+
+#endif /* _ASM_MB93493_REGS_H */
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/include/asm-frv/mb-regs.h linux-2.6.10-rc1-mm3-frv/include/asm-frv/mb-regs.h
--- /warthog/kernels/linux-2.6.10-rc1-mm3/include/asm-frv/mb-regs.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/include/asm-frv/mb-regs.h	2004-11-05 14:13:04.081480740 +0000
@@ -0,0 +1,185 @@
+/* mb-regs.h: motherboard registers
+ *
+ * Copyright (C) 2003, 2004 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * 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.
+ */
+
+#ifndef _ASM_MB_REGS_H
+#define _ASM_MB_REGS_H
+
+#include <asm/cpu-irqs.h>
+#include <asm/sections.h>
+#include <asm/mem-layout.h>
+
+#define __region_IO	KERNEL_IO_START	/* the region from 0xe0000000 to 0xffffffff has suitable
+					 * protection laid over the top for use in memory-mapped
+					 * I/O
+					 */
+
+#define __region_CS0	0xff000000	/* Boot ROMs area */
+
+#ifdef CONFIG_MB93091_VDK
+/*
+ * VDK motherboard and CPU card specific stuff
+ */
+
+#include <asm/mb93091-fpga-irqs.h>
+
+#define IRQ_CPU_MB93493_0	IRQ_CPU_EXTERNAL0
+#define IRQ_CPU_MB93493_1	IRQ_CPU_EXTERNAL1
+
+#define __region_CS2	0xe0000000	/* SLBUS/PCI I/O space */
+#define __region_CS2_M		0x0fffffff /* mask */
+#define __region_CS2_C		0x00000000 /* control */
+#define __region_CS5	0xf0000000	/* MB93493 CSC area (DAV daughter board) */
+#define __region_CS5_M		0x00ffffff
+#define __region_CS5_C		0x00010000
+#define __region_CS7	0xf1000000	/* CB70 CPU-card PCMCIA port I/O space */
+#define __region_CS7_M		0x00ffffff
+#define __region_CS7_C		0x00410701
+#define __region_CS1	0xfc000000	/* SLBUS/PCI bridge control registers */
+#define __region_CS1_M		0x000fffff
+#define __region_CS1_C		0x00000000
+#define __region_CS6	0xfc100000	/* CB70 CPU-card DM9000 LAN I/O space */
+#define __region_CS6_M		0x000fffff
+#define __region_CS6_C		0x00400707
+#define __region_CS3	0xfc200000	/* MB93493 CSR area (DAV daughter board) */
+#define __region_CS3_M		0x000fffff
+#define __region_CS3_C		0xc8100000
+#define __region_CS4	0xfd000000	/* CB70 CPU-card extra flash space */
+#define __region_CS4_M		0x00ffffff
+#define __region_CS4_C		0x00000f07
+
+#define __region_PCI_IO		(__region_CS2 + 0x04000000UL)
+#define __region_PCI_MEM	(__region_CS2 + 0x08000000UL)
+#define __flush_PCI_writes()						\
+do {									\
+	__builtin_write8((volatile void *) __region_PCI_MEM, 0);	\
+} while(0)
+
+#define __is_PCI_IO(addr) \
+	(((unsigned long)(addr) >> 24) - (__region_PCI_IO >> 24)  < (0x04000000UL >> 24))
+
+#define __is_PCI_MEM(addr) \
+	((unsigned long)(addr) - __region_PCI_MEM < 0x08000000UL)
+
+#define __get_CLKSW()	({ *(volatile unsigned long *)(__region_CS2 + 0x0130000cUL) & 0xffUL; })
+#define __get_CLKIN()	(__get_CLKSW() * 125U * 100000U / 24U)
+
+#ifndef __ASSEMBLY__
+extern int __nongprelbss mb93090_mb00_detected;
+#endif
+
+#define __addr_LEDS()		(__region_CS2 + 0x01200004UL)
+#ifdef CONFIG_MB93090_MB00
+#define __set_LEDS(X)							\
+do {									\
+	if (mb93090_mb00_detected)					\
+		__builtin_write32((void *) __addr_LEDS(), ~(X));	\
+} while (0)
+#else
+#define __set_LEDS(X)
+#endif
+
+#define __addr_LCD()		(__region_CS2 + 0x01200008UL)
+#define __get_LCD(B)		__builtin_read32((volatile void *) (B))
+#define __set_LCD(B,X)		__builtin_write32((volatile void *) (B), (X))
+
+#define LCD_D			0x000000ff		/* LCD data bus */
+#define LCD_RW			0x00000100		/* LCD R/W signal */
+#define LCD_RS			0x00000200		/* LCD Register Select */
+#define LCD_E			0x00000400		/* LCD Start Enable Signal */
+
+#define LCD_CMD_CLEAR		(LCD_E|0x001)
+#define LCD_CMD_HOME		(LCD_E|0x002)
+#define LCD_CMD_CURSOR_INC	(LCD_E|0x004)
+#define LCD_CMD_SCROLL_INC	(LCD_E|0x005)
+#define LCD_CMD_CURSOR_DEC	(LCD_E|0x006)
+#define LCD_CMD_SCROLL_DEC	(LCD_E|0x007)
+#define LCD_CMD_OFF		(LCD_E|0x008)
+#define LCD_CMD_ON(CRSR,BLINK)	(LCD_E|0x00c|(CRSR<<1)|BLINK)
+#define LCD_CMD_CURSOR_MOVE_L	(LCD_E|0x010)
+#define LCD_CMD_CURSOR_MOVE_R	(LCD_E|0x014)
+#define LCD_CMD_DISPLAY_SHIFT_L	(LCD_E|0x018)
+#define LCD_CMD_DISPLAY_SHIFT_R	(LCD_E|0x01c)
+#define LCD_CMD_FUNCSET(DL,N,F)	(LCD_E|0x020|(DL<<4)|(N<<3)|(F<<2))
+#define LCD_CMD_SET_CG_ADDR(X)	(LCD_E|0x040|X)
+#define LCD_CMD_SET_DD_ADDR(X)	(LCD_E|0x080|X)
+#define LCD_CMD_READ_BUSY	(LCD_E|LCD_RW)
+#define LCD_DATA_WRITE(X)	(LCD_E|LCD_RS|(X))
+#define LCD_DATA_READ		(LCD_E|LCD_RS|LCD_RW)
+
+#else
+/*
+ * PDK unit specific stuff
+ */
+
+#include <asm/mb93093-fpga-irqs.h>
+
+#define IRQ_CPU_MB93493_0	IRQ_CPU_EXTERNAL0
+#define IRQ_CPU_MB93493_1	IRQ_CPU_EXTERNAL1
+
+#define __region_CS5	0xf0000000	/* MB93493 CSC area (DAV daughter board) */
+#define __region_CS5_M		0x00ffffff /* mask */
+#define __region_CS5_C		0x00010000 /* control */
+#define __region_CS2	0x20000000	/* FPGA registers */
+#define __region_CS2_M		0x000fffff
+#define __region_CS2_C		0x00000000
+#define __region_CS1	0xfc100000	/* LAN registers */
+#define __region_CS1_M		0x000fffff
+#define __region_CS1_C		0x00010404
+#define __region_CS3	0xfc200000	/* MB93493 CSR area (DAV daughter board) */
+#define __region_CS3_M		0x000fffff
+#define __region_CS3_C		0xc8000000
+#define __region_CS4	0xfd000000	/* extra ROMs area */
+#define __region_CS4_M		0x00ffffff
+#define __region_CS4_C		0x00000f07
+
+#define __region_CS6	0xfe000000	/* not used - hide behind CPU resource I/O regs */
+#define __region_CS6_M		0x000fffff
+#define __region_CS6_C		0x00000f07
+#define __region_CS7	0xfe000000	/* not used - hide behind CPU resource I/O regs */
+#define __region_CS7_M		0x000fffff
+#define __region_CS7_C		0x00000f07
+
+#define __is_PCI_IO(addr)	0	/* no PCI */
+#define __is_PCI_MEM(addr)	0
+#define __region_PCI_IO		0
+#define __region_PCI_MEM	0
+#define __flush_PCI_writes()	do { } while(0)
+
+#define __get_CLKSW()		0UL
+#define __get_CLKIN()		66000000UL
+
+#define __addr_LEDS()		(__region_CS2 + 0x00000023UL)
+#define __set_LEDS(X)		__builtin_write8((volatile void *) __addr_LEDS(), (X))
+
+#define __addr_FPGATR()		(__region_CS2 + 0x00000030UL)
+#define __set_FPGATR(X)		__builtin_write32((volatile void *) __addr_FPGATR(), (X))
+#define __get_FPGATR()		__builtin_read32((volatile void *) __addr_FPGATR())
+
+#define MB93093_FPGA_FPGATR_AUDIO_CLK	0x00000003
+
+#define __set_FPGATR_AUDIO_CLK(V) \
+	__set_FPGATR((__get_FPGATR() & ~MB93093_FPGA_FPGATR_AUDIO_CLK) | (V))
+
+#define MB93093_FPGA_FPGATR_AUDIO_CLK_OFF	0x0
+#define MB93093_FPGA_FPGATR_AUDIO_CLK_11MHz	0x1
+#define MB93093_FPGA_FPGATR_AUDIO_CLK_12MHz	0x2
+#define MB93093_FPGA_FPGATR_AUDIO_CLK_02MHz	0x3
+
+#define MB93093_FPGA_SWR_PUSHSWMASK	(0x1F<<26)
+#define MB93093_FPGA_SWR_PUSHSW4	(1<<29)
+
+#define __addr_FPGA_SWR		((volatile void *)(__region_CS2 + 0x28UL))
+#define __get_FPGA_PUSHSW1_5()	(__builtin_read32(__addr_FPGA_SWR) & MB93093_FPGA_SWR_PUSHSWMASK)
+
+
+#endif
+
+#endif /* _ASM_MB_REGS_H */
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/include/asm-frv/mem-layout.h linux-2.6.10-rc1-mm3-frv/include/asm-frv/mem-layout.h
--- /warthog/kernels/linux-2.6.10-rc1-mm3/include/asm-frv/mem-layout.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/include/asm-frv/mem-layout.h	2004-11-05 14:13:04.085480402 +0000
@@ -0,0 +1,78 @@
+/* mem-layout.h: memory layout
+ *
+ * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * 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.
+ */
+
+#ifndef _ASM_MEM_LAYOUT_H
+#define _ASM_MEM_LAYOUT_H
+
+#ifndef __ASSEMBLY__
+#define __UL(X)	((unsigned long) (X))
+#else
+#define __UL(X)	(X)
+#endif
+
+/*
+ * PAGE_SHIFT determines the page size
+ */
+#define PAGE_SHIFT			14
+
+#ifndef __ASSEMBLY__
+#define PAGE_SIZE			(1UL << PAGE_SHIFT)
+#else
+#define PAGE_SIZE			(1 << PAGE_SHIFT)
+#endif
+
+#define PAGE_MASK			(~(PAGE_SIZE-1))
+
+/*****************************************************************************/
+/*
+ * virtual memory layout from kernel's point of view
+ */
+#define PAGE_OFFSET			((unsigned long) &__page_offset)
+
+#ifdef CONFIG_MMU
+
+/* see Documentation/fujitsu/frv/mmu-layout.txt */
+#define KERNEL_LOWMEM_START		__UL(0xc0000000)
+#define KERNEL_LOWMEM_END		__UL(0xd0000000)
+#define VMALLOC_START			__UL(0xd0000000)
+#define VMALLOC_END			__UL(0xd8000000)
+#define PKMAP_BASE			__UL(0xd8000000)
+#define PKMAP_END			__UL(0xdc000000)
+#define KMAP_ATOMIC_SECONDARY_FRAME	__UL(0xdc000000)
+#define KMAP_ATOMIC_PRIMARY_FRAME	__UL(0xdd000000)
+
+#endif
+
+#define KERNEL_IO_START			__UL(0xe0000000)
+
+
+/*****************************************************************************/
+/*
+ * memory layout from userspace's point of view
+ */
+#define BRK_BASE			__UL(2 * 1024 * 1024 + PAGE_SIZE)
+#define STACK_TOP			__UL(2 * 1024 * 1024)
+
+/* userspace process size */
+#ifdef CONFIG_MMU
+#define TASK_SIZE			(PAGE_OFFSET)
+#else
+#define TASK_SIZE			__UL(0xFFFFFFFFUL)
+#endif
+
+/* base of area at which unspecified mmaps will start */
+#ifdef CONFIG_BINFMT_ELF_FDPIC
+#define TASK_UNMAPPED_BASE		__UL(16 * 1024 * 1024)
+#else
+#define TASK_UNMAPPED_BASE		__UL(TASK_SIZE / 3)
+#endif
+
+#endif /* _ASM_MEM_LAYOUT_H */
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/include/asm-frv/mman.h linux-2.6.10-rc1-mm3-frv/include/asm-frv/mman.h
--- /warthog/kernels/linux-2.6.10-rc1-mm3/include/asm-frv/mman.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/include/asm-frv/mman.h	2004-11-05 14:13:04.089480064 +0000
@@ -0,0 +1,44 @@
+#ifndef __ASM_MMAN_H__
+#define __ASM_MMAN_H__
+
+#define PROT_READ	0x1		/* page can be read */
+#define PROT_WRITE	0x2		/* page can be written */
+#define PROT_EXEC	0x4		/* page can be executed */
+#define PROT_SEM	0x8		/* page may be used for atomic ops */
+#define PROT_NONE	0x0		/* page can not be accessed */
+#define PROT_GROWSDOWN	0x01000000	/* mprotect flag: extend change to start of growsdown vma */
+#define PROT_GROWSUP	0x02000000	/* mprotect flag: extend change to end of growsup vma */
+
+#define MAP_SHARED	0x01		/* Share changes */
+#define MAP_PRIVATE	0x02		/* Changes are private */
+#define MAP_TYPE	0x0f		/* Mask for type of mapping */
+#define MAP_FIXED	0x10		/* Interpret addr exactly */
+#define MAP_ANONYMOUS	0x20		/* don't use a file */
+
+#define MAP_GROWSDOWN	0x0100		/* stack-like segment */
+#define MAP_DENYWRITE	0x0800		/* ETXTBSY */
+#define MAP_EXECUTABLE	0x1000		/* mark it as an executable */
+#define MAP_LOCKED	0x2000		/* pages are locked */
+#define MAP_NORESERVE	0x4000		/* don't check for reservations */
+#define MAP_POPULATE	0x8000		/* populate (prefault) pagetables */
+#define MAP_NONBLOCK	0x10000		/* do not block on IO */
+
+#define MS_ASYNC	1		/* sync memory asynchronously */
+#define MS_INVALIDATE	2		/* invalidate the caches */
+#define MS_SYNC		4		/* synchronous memory sync */
+
+#define MCL_CURRENT	1		/* lock all current mappings */
+#define MCL_FUTURE	2		/* lock all future mappings */
+
+#define MADV_NORMAL	0x0		/* default page-in behavior */
+#define MADV_RANDOM	0x1		/* page-in minimum required */
+#define MADV_SEQUENTIAL	0x2		/* read-ahead aggressively */
+#define MADV_WILLNEED	0x3		/* pre-fault pages */
+#define MADV_DONTNEED	0x4		/* discard these pages */
+
+/* compatibility flags */
+#define MAP_ANON	MAP_ANONYMOUS
+#define MAP_FILE	0
+
+#endif /* __ASM_MMAN_H__ */
+
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/include/asm-frv/mmu_context.h linux-2.6.10-rc1-mm3-frv/include/asm-frv/mmu_context.h
--- /warthog/kernels/linux-2.6.10-rc1-mm3/include/asm-frv/mmu_context.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/include/asm-frv/mmu_context.h	2004-11-05 15:56:17.064106992 +0000
@@ -0,0 +1,50 @@
+/* mmu_context.h: MMU context management routines
+ *
+ * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * 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.
+ */
+
+#ifndef _ASM_MMU_CONTEXT_H
+#define _ASM_MMU_CONTEXT_H
+
+#include <linux/config.h>
+#include <asm/setup.h>
+#include <asm/page.h>
+#include <asm/pgalloc.h>
+
+static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)
+{
+}
+
+#ifdef CONFIG_MMU
+extern int init_new_context(struct task_struct *tsk, struct mm_struct *mm);
+extern void change_mm_context(mm_context_t *old, mm_context_t *ctx, pml4_t *_pml4);
+extern void destroy_context(struct mm_struct *mm);
+
+#else
+#define init_new_context(tsk, mm)		({ 0; })
+#define change_mm_context(old, ctx, _pml4)	do {} while(0)
+#define destroy_context(mm)			do {} while(0)
+#endif
+
+#define switch_mm(prev, next, tsk)						\
+do {										\
+	if (prev != next)							\
+		change_mm_context(&prev->context, &next->context, next->pml4);	\
+} while(0)
+
+#define activate_mm(prev, next)						\
+do {									\
+	change_mm_context(&prev->context, &next->context, next->pml4);	\
+} while(0)
+
+#define deactivate_mm(tsk, mm)			\
+do {						\
+} while(0)
+
+#endif
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/include/asm-frv/mmu.h linux-2.6.10-rc1-mm3-frv/include/asm-frv/mmu.h
--- /warthog/kernels/linux-2.6.10-rc1-mm3/include/asm-frv/mmu.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/include/asm-frv/mmu.h	2004-11-05 14:13:04.097479388 +0000
@@ -0,0 +1,42 @@
+/* mmu.h: memory management context for FR-V with or without MMU support
+ *
+ * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * 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.
+ */
+#ifndef _ASM_MMU_H
+#define _ASM_MMU_H
+
+typedef struct {
+#ifdef CONFIG_MMU
+	struct list_head id_link;		/* link in list of context ID owners */
+	unsigned short	id;			/* MMU context ID */
+	unsigned short	id_busy;		/* true if ID is in CXNR */
+	unsigned long	itlb_cached_pge;	/* [SCR0] PGE cached for insn TLB handler */
+	unsigned long	itlb_ptd_mapping;	/* [DAMR4] PTD mapping for itlb cached PGE */
+	unsigned long	dtlb_cached_pge;	/* [SCR1] PGE cached for data TLB handler */
+	unsigned long	dtlb_ptd_mapping;	/* [DAMR5] PTD mapping for dtlb cached PGE */
+
+#else
+	struct mm_tblock_struct	*tblock;
+	unsigned long		end_brk;
+
+#endif
+
+#ifdef CONFIG_BINFMT_ELF_FDPIC
+	unsigned long	exec_fdpic_loadmap;
+	unsigned long	interp_fdpic_loadmap;
+#endif
+
+} mm_context_t;
+
+#ifdef CONFIG_MMU
+extern int __nongpreldata cxn_pinned;
+extern int cxn_pin_by_pid(pid_t pid);
+#endif
+
+#endif /* _ASM_MMU_H */
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/include/asm-frv/module.h linux-2.6.10-rc1-mm3-frv/include/asm-frv/module.h
--- /warthog/kernels/linux-2.6.10-rc1-mm3/include/asm-frv/module.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/include/asm-frv/module.h	2004-11-05 14:13:04.103478882 +0000
@@ -0,0 +1,20 @@
+/* module.h: FRV module stuff
+ *
+ * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * 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.
+ */
+#ifndef _ASM_MODULE_H
+#define _ASM_MODULE_H
+
+#define module_map(x)		vmalloc(x)
+#define module_unmap(x)		vfree(x)
+#define module_arch_init(x)	(0)
+#define arch_init_modules(x)	do { } while (0)
+
+#endif /* _ASM_MODULE_H */
+
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/include/asm-frv/msgbuf.h linux-2.6.10-rc1-mm3-frv/include/asm-frv/msgbuf.h
--- /warthog/kernels/linux-2.6.10-rc1-mm3/include/asm-frv/msgbuf.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/include/asm-frv/msgbuf.h	2004-11-05 14:13:04.107478544 +0000
@@ -0,0 +1,32 @@
+#ifndef _ASM_MSGBUF_H
+#define _ASM_MSGBUF_H
+
+/* 
+ * The msqid64_ds structure for FR-V architecture.
+ * Note extra padding because this structure is passed back and forth
+ * between kernel and user space.
+ *
+ * Pad space is left for:
+ * - 64-bit time_t to solve y2038 problem
+ * - 2 miscellaneous 32-bit values
+ */
+
+struct msqid64_ds {
+	struct ipc64_perm	msg_perm;
+	__kernel_time_t		msg_stime;	/* last msgsnd time */
+	unsigned long		__unused1;
+	__kernel_time_t		msg_rtime;	/* last msgrcv time */
+	unsigned long		__unused2;
+	__kernel_time_t		msg_ctime;	/* last change time */
+	unsigned long		__unused3;
+	unsigned long		msg_cbytes;	/* current number of bytes on queue */
+	unsigned long		msg_qnum;	/* number of messages in queue */
+	unsigned long		msg_qbytes;	/* max number of bytes on queue */
+	__kernel_pid_t		msg_lspid;	/* pid of last msgsnd */
+	__kernel_pid_t		msg_lrpid;	/* last receive pid */
+	unsigned long		__unused4;
+	unsigned long		__unused5;
+};
+
+#endif /* _ASM_MSGBUF_H */
+
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/include/asm-frv/namei.h linux-2.6.10-rc1-mm3-frv/include/asm-frv/namei.h
--- /warthog/kernels/linux-2.6.10-rc1-mm3/include/asm-frv/namei.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/include/asm-frv/namei.h	2004-11-05 14:13:04.111478206 +0000
@@ -0,0 +1,18 @@
+/*
+ * asm/namei.h
+ *
+ * Included from linux/fs/namei.c
+ */
+
+#ifndef __ASM_NAMEI_H
+#define __ASM_NAMEI_H
+
+/* This dummy routine maybe changed to something useful
+ * for /usr/gnemul/ emulation stuff.
+ * Look at asm-sparc/namei.h for details.
+ */
+
+#define __emul_prefix() NULL
+
+#endif
+
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/include/asm-frv/page.h linux-2.6.10-rc1-mm3-frv/include/asm-frv/page.h
--- /warthog/kernels/linux-2.6.10-rc1-mm3/include/asm-frv/page.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/include/asm-frv/page.h	2004-11-05 16:02:50.175208222 +0000
@@ -0,0 +1,104 @@
+#ifndef _ASM_PAGE_H
+#define _ASM_PAGE_H
+
+#ifdef __KERNEL__
+
+#include <linux/config.h>
+#include <asm/virtconvert.h>
+#include <asm/mem-layout.h>
+#include <asm/sections.h>
+#include <asm/setup.h>
+ 
+#ifndef __ASSEMBLY__
+ 
+#define get_user_page(vaddr)			__get_free_page(GFP_KERNEL)
+#define free_user_page(page, addr)		free_page(addr)
+
+#define clear_page(pgaddr)			memset((pgaddr), 0, PAGE_SIZE)
+#define copy_page(to,from)			memcpy((to), (from), PAGE_SIZE)
+
+#define clear_user_page(pgaddr, vaddr, page)	memset((pgaddr), 0, PAGE_SIZE)
+#define copy_user_page(vto, vfrom, vaddr, topg)	memcpy((vto), (vfrom), PAGE_SIZE)
+
+/*
+ * These are used to make use of C type-checking..
+ */
+typedef struct { unsigned long pte;	} pte_t;
+typedef struct { unsigned long ste[64];	} pmd_t;
+typedef struct { pmd_t         pge[1];	} pgd_t;
+typedef struct { unsigned long pgprot;	} pgprot_t;
+
+#define pte_val(x)	((x).pte)
+#define pmd_val(x)	((x).ste[0])
+#define pgd_val(x)	((x).pge[0])
+#define pgprot_val(x)	((x).pgprot)
+
+#define __pte(x)	((pte_t) { (x) } )
+#define __pmd(x)	((pmd_t) { (x) } )
+#define __pgd(x)	((pgd_t) { (x) } )
+#define __pgprot(x)	((pgprot_t) { (x) } )
+#define PTE_MASK	PAGE_MASK
+
+/* to align the pointer to the (next) page boundary */
+#define PAGE_ALIGN(addr)	(((addr) + PAGE_SIZE - 1) & PAGE_MASK)
+
+/* Pure 2^n version of get_order */
+static inline int get_order(unsigned long size) __attribute_const__;
+static inline int get_order(unsigned long size)
+{
+	int order;
+
+	size = (size - 1) >> (PAGE_SHIFT - 1);
+	order = -1;
+	do {
+		size >>= 1;
+		order++;
+	} while (size);
+	return order;
+}
+
+#define devmem_is_allowed(pfn)	1
+
+#define __pa(vaddr)		virt_to_phys((void *) vaddr)
+#define __va(paddr)		phys_to_virt((unsigned long) paddr)
+
+#define pfn_to_kaddr(pfn)	__va((pfn) << PAGE_SHIFT)
+
+extern unsigned long max_low_pfn;
+extern unsigned long min_low_pfn;
+extern unsigned long max_pfn;
+
+#ifdef CONFIG_MMU
+#define pfn_to_page(pfn)	(mem_map + (pfn))
+#define page_to_pfn(page)	((unsigned long) ((page) - mem_map))
+#define pfn_valid(pfn)		((pfn) < max_mapnr)
+
+#else
+#define pfn_to_page(pfn)	(&mem_map[(pfn) - (PAGE_OFFSET >> PAGE_SHIFT)])
+#define page_to_pfn(page)	((PAGE_OFFSET >> PAGE_SHIFT) + (unsigned long) ((page) - mem_map))
+#define pfn_valid(pfn)		((pfn) >= min_low_pfn && (pfn) < max_low_pfn)
+
+#endif
+
+#define virt_to_page(kaddr)	pfn_to_page(__pa(kaddr) >> PAGE_SHIFT)
+#define virt_addr_valid(kaddr)	pfn_valid(__pa(kaddr) >> PAGE_SHIFT)
+
+
+#ifdef CONFIG_MMU
+#define VM_DATA_DEFAULT_FLAGS \
+	(VM_READ | VM_WRITE | \
+	((current->personality & READ_IMPLIES_EXEC) ? VM_EXEC : 0 ) | \
+		 VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
+#endif
+
+#include <asm-generic/nopml4-page.h>
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* __KERNEL__ */
+
+#ifdef CONFIG_CONTIGUOUS_PAGE_ALLOC
+#define WANT_PAGE_VIRTUAL	1
+#endif
+
+#endif /* _ASM_PAGE_H */
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/include/asm-frv/param.h linux-2.6.10-rc1-mm3-frv/include/asm-frv/param.h
--- /warthog/kernels/linux-2.6.10-rc1-mm3/include/asm-frv/param.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/include/asm-frv/param.h	2004-11-05 14:13:04.119477530 +0000
@@ -0,0 +1,23 @@
+#ifndef _ASM_PARAM_H
+#define _ASM_PARAM_H
+
+#ifdef __KERNEL__
+#define HZ		1000		/* Internal kernel timer frequency */
+#define USER_HZ		100		/* .. some user interfaces are in "ticks" */
+#define CLOCKS_PER_SEC	(USER_HZ)	/* like times() */
+#endif
+
+#ifndef HZ
+#define HZ 100
+#endif
+
+#define EXEC_PAGESIZE	16384
+
+#ifndef NOGROUP
+#define NOGROUP		(-1)
+#endif
+
+#define MAXHOSTNAMELEN		64	/* max length of hostname */
+#define COMMAND_LINE_SIZE	512
+
+#endif /* _ASM_PARAM_H */
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/include/asm-frv/pci.h linux-2.6.10-rc1-mm3-frv/include/asm-frv/pci.h
--- /warthog/kernels/linux-2.6.10-rc1-mm3/include/asm-frv/pci.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/include/asm-frv/pci.h	2004-11-05 14:13:04.123477193 +0000
@@ -0,0 +1,108 @@
+/* pci.h: FR-V specific PCI declarations
+ *
+ * Copyright (C) 2003 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ * - Derived from include/asm-m68k/pci.h
+ *
+ * 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.
+ */
+
+#ifndef ASM_PCI_H
+#define	ASM_PCI_H
+
+#include <linux/config.h>
+#include <linux/mm.h>
+#include <asm/scatterlist.h>
+#include <asm-generic/pci-dma-compat.h>
+#include <asm-generic/pci.h>
+
+struct pci_dev;
+
+#define pcibios_assign_all_busses()	0
+
+static inline void pcibios_add_platform_entries(struct pci_dev *dev)
+{
+}
+
+extern void pcibios_set_master(struct pci_dev *dev);
+
+extern void pcibios_penalize_isa_irq(int irq);
+
+#ifdef CONFIG_MMU
+extern void *consistent_alloc(int gfp, size_t size, dma_addr_t *dma_handle);
+extern void consistent_free(void *vaddr);
+extern void consistent_sync(void *vaddr, size_t size, int direction);
+extern void consistent_sync_page(struct page *page, unsigned long offset,
+				 size_t size, int direction);
+#endif
+
+extern void *pci_alloc_consistent(struct pci_dev *hwdev, size_t size,
+				  dma_addr_t *dma_handle);
+
+extern void pci_free_consistent(struct pci_dev *hwdev, size_t size,
+				void *vaddr, dma_addr_t dma_handle);
+
+/* This is always fine. */
+#define pci_dac_dma_supported(pci_dev, mask)	(1)
+
+/* Return the index of the PCI controller for device PDEV. */
+#define pci_controller_num(PDEV)	(0)
+
+/* The PCI address space does equal the physical memory
+ * address space.  The networking and block device layers use
+ * this boolean for bounce buffer decisions.
+ */
+#define PCI_DMA_BUS_IS_PHYS	(1)
+
+/*
+ *	These are pretty much arbitary with the CoMEM implementation.
+ *	We have the whole address space to ourselves.
+ */
+#define PCIBIOS_MIN_IO		0x100
+#define PCIBIOS_MIN_MEM		0x00010000
+
+/* Make physical memory consistent for a single
+ * streaming mode DMA translation after a transfer.
+ *
+ * If you perform a pci_map_single() but wish to interrogate the
+ * buffer using the cpu, yet do not wish to teardown the PCI dma
+ * mapping, you must call this function before doing so.  At the
+ * next point you give the PCI dma address back to the card, the
+ * device again owns the buffer.
+ */
+static inline void pci_dma_sync_single(struct pci_dev *hwdev,
+				       dma_addr_t dma_handle,
+				       size_t size, int direction)
+{
+	if (direction == PCI_DMA_NONE)
+                BUG();
+
+	frv_cache_wback_inv((unsigned long)bus_to_virt(dma_handle), 
+			    (unsigned long)bus_to_virt(dma_handle) + size);
+}
+
+/* Make physical memory consistent for a set of streaming
+ * mode DMA translations after a transfer.
+ *
+ * The same as pci_dma_sync_single but for a scatter-gather list,
+ * same rules and usage.
+ */
+static inline void pci_dma_sync_sg(struct pci_dev *hwdev,
+				   struct scatterlist *sg,
+				   int nelems, int direction)
+{
+	int i;
+
+	if (direction == PCI_DMA_NONE)
+                BUG();
+
+	for (i = 0; i < nelems; i++)
+		frv_cache_wback_inv(sg_dma_address(&sg[i]),
+				    sg_dma_address(&sg[i])+sg_dma_len(&sg[i]));
+}
+
+
+#endif
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/include/asm-frv/percpu.h linux-2.6.10-rc1-mm3-frv/include/asm-frv/percpu.h
--- /warthog/kernels/linux-2.6.10-rc1-mm3/include/asm-frv/percpu.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/include/asm-frv/percpu.h	2004-11-05 14:13:04.127476855 +0000
@@ -0,0 +1,6 @@
+#ifndef __ASM_PERCPU_H
+#define __ASM_PERCPU_H
+
+#include <asm-generic/percpu.h>
+
+#endif	/* __ASM_PERCPU_H */
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/include/asm-frv/pgalloc.h linux-2.6.10-rc1-mm3-frv/include/asm-frv/pgalloc.h
--- /warthog/kernels/linux-2.6.10-rc1-mm3/include/asm-frv/pgalloc.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/include/asm-frv/pgalloc.h	2004-11-05 14:59:30.000000000 +0000
@@ -0,0 +1,66 @@
+/* pgalloc.h: Page allocation routines for FRV
+ *
+ * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * 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.
+ *
+ * Derived from:
+ *	include/asm-m68knommu/pgalloc.h
+ *	include/asm-i386/pgalloc.h
+ */
+#ifndef _ASM_PGALLOC_H
+#define _ASM_PGALLOC_H
+
+#include <linux/config.h>
+#include <asm/setup.h>
+#include <asm/virtconvert.h>
+
+#ifdef CONFIG_MMU
+
+#define pmd_populate_kernel(mm, pmd, pte) __set_pmd(pmd, __pa(pte) | _PAGE_TABLE)
+#define pmd_populate(MM, PMD, PAGE)						\
+do {										\
+	__set_pmd((PMD), page_to_pfn(PAGE) << PAGE_SHIFT | _PAGE_TABLE);	\
+} while(0)
+
+/*
+ * Allocate and free page tables.
+ */
+
+extern void pgd_free(pgd_t *);
+
+extern pte_t *pte_alloc_one_kernel(struct mm_struct *, unsigned long);
+
+extern struct page *pte_alloc_one(struct mm_struct *, unsigned long);
+
+static inline void pte_free_kernel(pte_t *pte)
+{
+	free_page((unsigned long)pte);
+}
+
+static inline void pte_free(struct page *pte)
+{
+	__free_page(pte);
+}
+
+#define __pte_free_tlb(tlb,pte)		tlb_remove_page((tlb),(pte))
+
+/*
+ * allocating and freeing a pmd is trivial: the 1-entry pmd is
+ * inside the pgd, so has no extra memory associated with it.
+ * (In the PAE case we free the pmds as part of the pgd.)
+ */
+#define pmd_alloc_one(mm, addr)		({ BUG(); ((pmd_t *) 2); })
+#define pmd_free(x)			do { } while (0)
+#define __pmd_free_tlb(tlb,x)		do { } while (0)
+#define pgd_populate(mm, pmd, pte)	BUG()
+
+#include <asm-generic/nopml4-pgalloc.h>
+
+#endif /* CONFIG_MMU */
+
+#endif /* _ASM_PGALLOC_H */
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/include/asm-frv/pgtable.h linux-2.6.10-rc1-mm3-frv/include/asm-frv/pgtable.h
--- /warthog/kernels/linux-2.6.10-rc1-mm3/include/asm-frv/pgtable.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/include/asm-frv/pgtable.h	2004-11-05 14:58:27.452086136 +0000
@@ -0,0 +1,491 @@
+/* pgtable.h: FR-V page table mangling
+ *
+ * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * 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.
+ *
+ * Derived from:
+ *	include/asm-m68knommu/pgtable.h
+ *	include/asm-i386/pgtable.h
+ */
+
+#ifndef _ASM_PGTABLE_H
+#define _ASM_PGTABLE_H
+
+#include <linux/config.h>
+#include <asm/mem-layout.h>
+#include <asm/setup.h>
+#include <asm/processor.h>
+
+#ifndef __ASSEMBLY__
+#include <linux/threads.h>
+#include <linux/slab.h>
+#include <linux/list.h>
+#include <linux/spinlock.h>
+#endif
+
+#ifndef __ASSEMBLY__
+#if defined(CONFIG_HIGHPTE)
+typedef unsigned long pte_addr_t;
+#else
+typedef pte_t *pte_addr_t;
+#endif
+#endif
+
+/*****************************************************************************/
+/*
+ * MMU-less operation case first
+ */
+#ifndef CONFIG_MMU
+
+#define pgd_present(pgd)	(1)		/* pages are always present on NO_MM */
+#define pgd_none(pgd)		(0)
+#define pgd_bad(pgd)		(0)
+#define pgd_clear(pgdp)
+#define kern_addr_valid(addr)	(1)
+#define	pmd_offset(a, b)	((void *) 0)
+
+#define PAGE_NONE		__pgprot(0)	/* these mean nothing to NO_MM */
+#define PAGE_SHARED		__pgprot(0)	/* these mean nothing to NO_MM */
+#define PAGE_COPY		__pgprot(0)	/* these mean nothing to NO_MM */
+#define PAGE_READONLY		__pgprot(0)	/* these mean nothing to NO_MM */
+#define PAGE_KERNEL		__pgprot(0)	/* these mean nothing to NO_MM */
+
+#define __swp_type(x)		(0)
+#define __swp_offset(x)		(0)
+#define __swp_entry(typ,off)	((swp_entry_t) { ((typ) | ((off) << 7)) })
+#define __pte_to_swp_entry(pte)	((swp_entry_t) { pte_val(pte) })
+#define __swp_entry_to_pte(x)	((pte_t) { (x).val })
+
+#ifndef __ASSEMBLY__
+static inline int pte_file(pte_t pte) { return 0; }
+#endif
+
+#define ZERO_PAGE(vaddr)	({ BUG(); NULL; })
+
+#define swapper_pg_dir		((pgd_t *) NULL)
+
+#define pgtable_cache_init()	do {} while(0)
+
+#else /* !CONFIG_MMU */
+/*****************************************************************************/
+/*
+ * then MMU operation
+ */
+
+/*
+ * ZERO_PAGE is a global shared page that is always zero: used
+ * for zero-mapped memory areas etc..
+ */
+#ifndef __ASSEMBLY__
+extern unsigned long empty_zero_page;
+#define ZERO_PAGE(vaddr)	virt_to_page(empty_zero_page)
+#endif
+
+/*
+ * we use 2-level page tables, folding the PMD (mid-level table) into the PGE (top-level entry)
+ * [see Documentation/fujitsu/frv/mmu-layout.txt]
+ *
+ * 4th-Level Page Directory:
+ *  - Size: 16KB
+ *  - 1 PML4Es per PML4
+ *  - Each PML4E holds 1 PGD and covers 4GB
+ *
+ * Page Directory:
+ *  - Size: 16KB
+ *  - 64 PGEs per PGD
+ *  - Each PGE holds 1 PMD and covers 64MB
+ *
+ * Page Mid-Level Directory
+ *  - 1 PME per PMD
+ *  - Each PME holds 64 STEs, all of which point to separate chunks of the same Page Table
+ *  - All STEs are instantiated at the same time
+ *  - Size: 256B
+ *
+ * Page Table
+ *  - Size: 16KB
+ *  - 4096 PTEs per PT
+ *  - Each Linux PT is subdivided into 64 FR451 PT's, each of which holds 64 entries
+ *
+ * Pages
+ *  - Size: 4KB
+ *
+ * total PTEs
+ *	= 1 PML4E * 64 PGEs * 1 PMEs * 4096 PTEs
+ *	= 1 PML4E * 64 PGEs * 64 STEs * 64 PTEs/FR451-PT
+ *	= 262144 (or 256 * 1024)
+ */
+#define PGDIR_SHIFT		26
+#define PGDIR_SIZE		(1UL << PGDIR_SHIFT)
+#define PGDIR_MASK		(~(PGDIR_SIZE - 1))
+#define PTRS_PER_PGD		64
+
+#define PMD_SHIFT		26
+#define PMD_SIZE		(1UL << PMD_SHIFT)
+#define PMD_MASK		(~(PMD_SIZE - 1))
+#define PTRS_PER_PMD		1
+#define PME_SIZE		256
+
+#define __frv_PT_SIZE		256
+
+#define PTRS_PER_PTE		4096
+
+#define USER_PGDS_IN_LAST_PML4	(TASK_SIZE / PGDIR_SIZE)
+#define FIRST_USER_PGD_NR	0
+
+#define USER_PGD_PTRS		(PAGE_OFFSET >> PGDIR_SHIFT)
+#define KERNEL_PGD_PTRS		(PTRS_PER_PGD - USER_PGD_PTRS)
+
+#define TWOLEVEL_PGDIR_SHIFT	26
+#define BOOT_USER_PGD_PTRS	(__PAGE_OFFSET >> TWOLEVEL_PGDIR_SHIFT)
+#define BOOT_KERNEL_PGD_PTRS	(PTRS_PER_PGD - BOOT_USER_PGD_PTRS)
+
+#ifndef __ASSEMBLY__
+
+extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
+
+#define pte_ERROR(e) \
+	printk("%s:%d: bad pte %08lx.\n", __FILE__, __LINE__, (e).pte)
+#define pmd_ERROR(e) \
+	printk("%s:%d: bad pmd %08lx.\n", __FILE__, __LINE__, pmd_val(e))
+#define pgd_ERROR(e) \
+	printk("%s:%d: bad pgd %08lx.\n", __FILE__, __LINE__, pmd_val(pgd_val(e)))
+
+/*
+ * The "pgd_xxx()" functions here are trivial for a folded two-level
+ * setup: the pgd is never bad, and a pmd always exists (as it's folded
+ * into the pgd entry)
+ */
+static inline int pgd_none(pgd_t pgd)		{ return 0; }
+static inline int pgd_bad(pgd_t pgd)		{ return 0; }
+static inline int pgd_present(pgd_t pgd)	{ return 1; }
+#define pgd_clear(xp)				do { } while (0)
+
+/*
+ * Certain architectures need to do special things when PTEs
+ * within a page table are directly modified.  Thus, the following
+ * hook is made available.
+ */
+#define set_pte(pteptr, pteval)				\
+do {							\
+	*(pteptr) = (pteval);				\
+	asm volatile("dcf %M0" :: "U"(*pteptr));	\
+} while(0)
+
+#define set_pte_atomic(pteptr, pteval)		set_pte((pteptr), (pteval))
+
+/*
+ * (pmds are folded into pgds so this doesn't get actually called,
+ * but the define is needed for a generic inline function.)
+ */
+#define set_pgd(pgdptr, pgdval)			(*(pgdptr) = pgdval)
+
+extern void __set_pmd(pmd_t *pmdptr, unsigned long __pmd);
+
+#define set_pmd(pmdptr, pmdval)			\
+do {						\
+	__set_pmd((pmdptr), (pmdval).ste[0]);	\
+} while(0)
+
+#define pgd_page(pgd)				((unsigned long) __va(pgd_val(pgd) & PAGE_MASK))
+
+#define __pmd_index(address)			0
+
+static inline pmd_t *pmd_offset(pgd_t *dir, unsigned long address)
+{
+	return (pmd_t *) dir + __pmd_index(address);
+}
+
+#define pte_same(a, b)		((a).pte == (b).pte)
+#define pte_page(x)		(mem_map + ((unsigned long)(((x).pte >> PAGE_SHIFT))))
+#define pte_none(x)		(!(x).pte)
+#define pte_pfn(x)		((unsigned long)(((x).pte >> PAGE_SHIFT)))
+#define pfn_pte(pfn, prot)	__pte(((pfn) << PAGE_SHIFT) | pgprot_val(prot))
+#define pfn_pmd(pfn, prot)	__pmd(((pfn) << PAGE_SHIFT) | pgprot_val(prot))
+
+#define VMALLOC_VMADDR(x)	((unsigned long) (x))
+
+#endif /* !__ASSEMBLY__ */
+
+/*
+ * control flags in AMPR registers and TLB entries
+ */
+#define _PAGE_BIT_PRESENT	xAMPRx_V_BIT
+#define _PAGE_BIT_WP		DAMPRx_WP_BIT
+#define _PAGE_BIT_NOCACHE	xAMPRx_C_BIT
+#define _PAGE_BIT_SUPER		xAMPRx_S_BIT
+#define _PAGE_BIT_ACCESSED	xAMPRx_RESERVED8_BIT
+#define _PAGE_BIT_DIRTY		xAMPRx_M_BIT
+#define _PAGE_BIT_NOTGLOBAL	xAMPRx_NG_BIT
+
+#define _PAGE_PRESENT		xAMPRx_V
+#define _PAGE_WP		DAMPRx_WP
+#define _PAGE_NOCACHE		xAMPRx_C
+#define _PAGE_SUPER		xAMPRx_S
+#define _PAGE_ACCESSED		xAMPRx_RESERVED8	/* accessed if set */
+#define _PAGE_DIRTY		xAMPRx_M
+#define _PAGE_NOTGLOBAL		xAMPRx_NG
+
+#define _PAGE_RESERVED_MASK	(xAMPRx_RESERVED8 | xAMPRx_RESERVED13)
+
+#define _PAGE_FILE		0x002	/* set:pagecache unset:swap */
+#define _PAGE_PROTNONE		0x000	/* If not present */
+
+#define _PAGE_CHG_MASK		(PTE_MASK | _PAGE_ACCESSED | _PAGE_DIRTY)
+
+#define __PGPROT_BASE \
+	(_PAGE_PRESENT | xAMPRx_SS_16Kb | xAMPRx_D | _PAGE_NOTGLOBAL | _PAGE_ACCESSED)
+
+#define PAGE_NONE	__pgprot(_PAGE_PROTNONE | _PAGE_ACCESSED)
+#define PAGE_SHARED	__pgprot(__PGPROT_BASE)
+#define PAGE_COPY	__pgprot(__PGPROT_BASE | _PAGE_WP)
+#define PAGE_READONLY	__pgprot(__PGPROT_BASE | _PAGE_WP)
+
+#define __PAGE_KERNEL		(__PGPROT_BASE | _PAGE_SUPER | _PAGE_DIRTY)
+#define __PAGE_KERNEL_NOCACHE	(__PGPROT_BASE | _PAGE_SUPER | _PAGE_DIRTY | _PAGE_NOCACHE)
+#define __PAGE_KERNEL_RO	(__PGPROT_BASE | _PAGE_SUPER | _PAGE_DIRTY | _PAGE_WP)
+
+#define MAKE_GLOBAL(x) __pgprot((x) & ~_PAGE_NOTGLOBAL)
+
+#define PAGE_KERNEL		MAKE_GLOBAL(__PAGE_KERNEL)
+#define PAGE_KERNEL_RO		MAKE_GLOBAL(__PAGE_KERNEL_RO)
+#define PAGE_KERNEL_NOCACHE	MAKE_GLOBAL(__PAGE_KERNEL_NOCACHE)
+
+#define _PAGE_TABLE		(_PAGE_PRESENT | xAMPRx_SS_16Kb | xAMPRx_D | _PAGE_ACCESSED)
+
+#ifndef __ASSEMBLY__
+
+/*
+ * The FR451 can do execute protection by virtue of having separate TLB miss handlers for
+ * instruction access and for data access. However, we don't have enough reserved bits to say
+ * "execute only", so we don't bother. If you can read it, you can execute it and vice versa.
+ */
+#define __P000	PAGE_NONE
+#define __P001	PAGE_READONLY
+#define __P010	PAGE_COPY
+#define __P011	PAGE_COPY
+#define __P100	PAGE_READONLY
+#define __P101	PAGE_READONLY
+#define __P110	PAGE_COPY
+#define __P111	PAGE_COPY
+
+#define __S000	PAGE_NONE
+#define __S001	PAGE_READONLY
+#define __S010	PAGE_SHARED
+#define __S011	PAGE_SHARED
+#define __S100	PAGE_READONLY
+#define __S101	PAGE_READONLY
+#define __S110	PAGE_SHARED
+#define __S111	PAGE_SHARED
+
+/*
+ * Define this to warn about kernel memory accesses that are
+ * done without a 'verify_area(VERIFY_WRITE,..)'
+ */
+#undef TEST_VERIFY_AREA
+
+#define pte_present(x)	(pte_val(x) & _PAGE_PRESENT)
+#define pte_clear(xp)	do { set_pte(xp, __pte(0)); } while (0)
+
+#define pmd_none(x)	(!pmd_val(x))
+#define pmd_present(x)	(pmd_val(x) & _PAGE_PRESENT)
+#define	pmd_bad(x)	(pmd_val(x) & xAMPRx_SS)
+#define pmd_clear(xp)	do { __set_pmd(xp, 0); } while(0)
+
+#define pmd_page_kernel(pmd) \
+	((unsigned long) __va(pmd_val(pmd) & PAGE_MASK))
+
+#ifndef CONFIG_DISCONTIGMEM
+#define pmd_page(pmd)	(pfn_to_page(pmd_val(pmd) >> PAGE_SHIFT))
+#endif
+
+#define pages_to_mb(x) ((x) >> (20-PAGE_SHIFT))
+
+/*
+ * The following only work if pte_present() is true.
+ * Undefined behaviour if not..
+ */
+static inline int pte_read(pte_t pte)		{ return !((pte).pte & _PAGE_SUPER); }
+static inline int pte_exec(pte_t pte)		{ return !((pte).pte & _PAGE_SUPER); }
+static inline int pte_dirty(pte_t pte)		{ return (pte).pte & _PAGE_DIRTY; }
+static inline int pte_young(pte_t pte)		{ return (pte).pte & _PAGE_ACCESSED; }
+static inline int pte_write(pte_t pte)		{ return !((pte).pte & _PAGE_WP); }
+
+static inline pte_t pte_rdprotect(pte_t pte)	{ (pte).pte |= _PAGE_SUPER; return pte; }
+static inline pte_t pte_exprotect(pte_t pte)	{ (pte).pte |= _PAGE_SUPER; return pte; }
+static inline pte_t pte_mkclean(pte_t pte)	{ (pte).pte &= ~_PAGE_DIRTY; return pte; }
+static inline pte_t pte_mkold(pte_t pte)	{ (pte).pte &= ~_PAGE_ACCESSED; return pte; }
+static inline pte_t pte_wrprotect(pte_t pte)	{ (pte).pte |= _PAGE_WP; return pte; }
+static inline pte_t pte_mkread(pte_t pte)	{ (pte).pte &= ~_PAGE_SUPER; return pte; }
+static inline pte_t pte_mkexec(pte_t pte)	{ (pte).pte &= ~_PAGE_SUPER; return pte; }
+static inline pte_t pte_mkdirty(pte_t pte)	{ (pte).pte |= _PAGE_DIRTY; return pte; }
+static inline pte_t pte_mkyoung(pte_t pte)	{ (pte).pte |= _PAGE_ACCESSED; return pte; }
+static inline pte_t pte_mkwrite(pte_t pte)	{ (pte).pte &= ~_PAGE_WP; return pte; }
+
+static inline int ptep_test_and_clear_dirty(pte_t *ptep)
+{
+	int i = test_and_clear_bit(_PAGE_BIT_DIRTY, ptep);
+	asm volatile("dcf %M0" :: "U"(*ptep));
+	return i;
+}
+
+static inline int ptep_test_and_clear_young(pte_t *ptep)
+{
+	int i = test_and_clear_bit(_PAGE_BIT_ACCESSED, ptep);
+	asm volatile("dcf %M0" :: "U"(*ptep));
+	return i;
+}
+
+static inline pte_t ptep_get_and_clear(pte_t *ptep)
+{
+	unsigned long x = xchg(&ptep->pte, 0);
+	asm volatile("dcf %M0" :: "U"(*ptep));
+	return __pte(x);
+}
+
+static inline void ptep_set_wrprotect(pte_t *ptep)
+{
+	set_bit(_PAGE_BIT_WP, ptep);
+	asm volatile("dcf %M0" :: "U"(*ptep));
+}
+
+static inline void ptep_mkdirty(pte_t *ptep)
+{
+	set_bit(_PAGE_BIT_DIRTY, ptep);
+	asm volatile("dcf %M0" :: "U"(*ptep));
+}
+
+/*
+ * Conversion functions: convert a page and protection to a page entry,
+ * and a page entry and page directory to the page they refer to.
+ */
+
+#define mk_pte(page, pgprot)	pfn_pte(page_to_pfn(page), (pgprot))
+#define mk_pte_huge(entry)	((entry).pte_low |= _PAGE_PRESENT | _PAGE_PSE)
+
+/* This takes a physical page address that is used by the remapping functions */
+#define mk_pte_phys(physpage, pgprot)	pfn_pte((physpage) >> PAGE_SHIFT, pgprot)
+
+static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
+{
+	pte.pte &= _PAGE_CHG_MASK;
+	pte.pte |= pgprot_val(newprot);
+	return pte;
+}
+
+#define page_pte(page)	page_pte_prot(page, __pgprot(0))
+
+/* to find an entry in a page-table-directory. */
+#define pgd_index(address) ((address >> PGDIR_SHIFT) & (PTRS_PER_PGD - 1))
+#define pgd_index_k(addr) pgd_index(addr)
+
+/* Find an entry in the third-level page table.. */
+#define __pte_index(address) ((address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))
+#define pte_offset(dir, address) ((pte_t *) pmd_page(*(dir)) + __pte_index(address))
+
+/*
+ * the pte page can be thought of an array like this: pte_t[PTRS_PER_PTE]
+ *
+ * this macro returns the index of the entry in the pte page which would
+ * control the given virtual address
+ */
+#define pte_index(address) \
+		(((address) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))
+#define pte_offset_kernel(dir, address) \
+	((pte_t *) pmd_page_kernel(*(dir)) +  pte_index(address))
+
+#if defined(CONFIG_HIGHPTE)
+#define pte_offset_map(dir, address) \
+	((pte_t *)kmap_atomic(pmd_page(*(dir)),KM_PTE0) + pte_index(address))
+#define pte_offset_map_nested(dir, address) \
+	((pte_t *)kmap_atomic(pmd_page(*(dir)),KM_PTE1) + pte_index(address))
+#define pte_unmap(pte) kunmap_atomic(pte, KM_PTE0)
+#define pte_unmap_nested(pte) kunmap_atomic(pte, KM_PTE1)
+#else
+#define pte_offset_map(dir, address) \
+	((pte_t *)page_address(pmd_page(*(dir))) + pte_index(address))
+#define pte_offset_map_nested(dir, address) pte_offset_map(dir, address)
+#define pte_unmap(pte) do { } while (0)
+#define pte_unmap_nested(pte) do { } while (0)
+#endif
+
+/*
+ * Handle swap and file entries
+ * - the PTE is encoded in the following format:
+ *	bit 0:		Must be 0 (!_PAGE_PRESENT)
+ *	bit 1:		Type: 0 for swap, 1 for file (_PAGE_FILE)
+ *	bits 2-7:	Swap type
+ *	bits 8-31:	Swap offset
+ *	bits 2-31:	File pgoff
+ */
+#define __swp_type(x)			(((x).val >> 2) & 0x1f)
+#define __swp_offset(x)			((x).val >> 8)
+#define __swp_entry(type, offset)	((swp_entry_t) { ((type) << 2) | ((offset) << 8) })
+#define __pte_to_swp_entry(pte)		((swp_entry_t) { (pte).pte })
+#define __swp_entry_to_pte(x)		((pte_t) { (x).val })
+
+static inline int pte_file(pte_t pte)
+{
+	return pte.pte & _PAGE_FILE;
+}
+
+#define PTE_FILE_MAX_BITS	29
+
+#define pte_to_pgoff(PTE)	((PTE).pte >> 2)
+#define pgoff_to_pte(off)	__pte((off) << 2 | _PAGE_FILE)
+
+/* Needs to be defined here and not in linux/mm.h, as it is arch dependent */
+#define PageSkip(page)		(0)
+#define kern_addr_valid(addr)	(1)
+
+#define io_remap_page_range	remap_page_range
+
+#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG
+#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_DIRTY
+#define __HAVE_ARCH_PTEP_GET_AND_CLEAR
+#define __HAVE_ARCH_PTEP_SET_WRPROTECT
+#define __HAVE_ARCH_PTEP_MKDIRTY
+#define __HAVE_ARCH_PTE_SAME
+#include <asm-generic/pgtable.h>
+#include <asm-generic/nopml4-pgtable.h>
+
+/*
+ * preload information about a newly instantiated PTE into the SCR0/SCR1 PGE cache
+ */
+static inline void update_mmu_cache(struct vm_area_struct *vma, unsigned long address, pte_t pte)
+{
+	unsigned long ampr;
+	pml4_t *pml4e = pml4_offset(current->mm, address);
+	pgd_t *pge = pml4_pgd_offset(pml4e, address);
+	pmd_t *pme = pmd_offset(pge, address);
+
+	ampr = pme->ste[0] & 0xffffff00;
+	ampr |= xAMPRx_L | xAMPRx_SS_16Kb | xAMPRx_S | xAMPRx_C | xAMPRx_V;
+
+	asm volatile("movgs %0,scr0\n"
+		     "movgs %0,scr1\n"
+		     "movgs %1,dampr4\n"
+		     "movgs %1,dampr5\n"
+		     :
+		     : "r"(address), "r"(ampr)
+		     );
+}
+
+#ifdef CONFIG_PROC_FS
+extern char *proc_pid_status_frv_cxnr(struct mm_struct *mm, char *buffer);
+#endif
+
+extern void __init pgtable_cache_init(void);
+
+#endif /* !__ASSEMBLY__ */
+#endif /* !CONFIG_MMU */
+
+#ifndef __ASSEMBLY__
+extern void __init paging_init(void);
+#endif /* !__ASSEMBLY__ */
+
+#endif /* _ASM_PGTABLE_H */
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/include/asm-frv/poll.h linux-2.6.10-rc1-mm3-frv/include/asm-frv/poll.h
--- /warthog/kernels/linux-2.6.10-rc1-mm3/include/asm-frv/poll.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/include/asm-frv/poll.h	2004-11-05 14:13:04.140475757 +0000
@@ -0,0 +1,23 @@
+#ifndef _ASM_POLL_H
+#define _ASM_POLL_H
+
+#define POLLIN		  1
+#define POLLPRI		  2
+#define POLLOUT		  4
+#define POLLERR		  8
+#define POLLHUP		 16
+#define POLLNVAL	 32
+#define POLLRDNORM	 64
+#define POLLWRNORM	POLLOUT
+#define POLLRDBAND	128
+#define POLLWRBAND	256
+#define POLLMSG		0x0400
+
+struct pollfd {
+	int fd;
+	short events;
+	short revents;
+};
+
+#endif
+
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/include/asm-frv/posix_types.h linux-2.6.10-rc1-mm3-frv/include/asm-frv/posix_types.h
--- /warthog/kernels/linux-2.6.10-rc1-mm3/include/asm-frv/posix_types.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/include/asm-frv/posix_types.h	2004-11-05 14:13:04.144475419 +0000
@@ -0,0 +1,66 @@
+#ifndef _ASM_POSIX_TYPES_H
+#define _ASM_POSIX_TYPES_H
+
+/*
+ * This file is generally used by user-level software, so you need to
+ * be a little careful about namespace pollution etc.  Also, we cannot
+ * assume GCC is being used.
+ */
+
+typedef unsigned long	__kernel_ino_t;
+typedef unsigned short	__kernel_mode_t;
+typedef unsigned short	__kernel_nlink_t;
+typedef long		__kernel_off_t;
+typedef int		__kernel_pid_t;
+typedef unsigned short	__kernel_ipc_pid_t;
+typedef unsigned short	__kernel_uid_t;
+typedef unsigned short	__kernel_gid_t;
+typedef unsigned int	__kernel_size_t;
+typedef int		__kernel_ssize_t;
+typedef int		__kernel_ptrdiff_t;
+typedef long		__kernel_time_t;
+typedef long		__kernel_suseconds_t;
+typedef long		__kernel_clock_t;
+typedef int		__kernel_timer_t;
+typedef int		__kernel_clockid_t;
+typedef int		__kernel_daddr_t;
+typedef char *		__kernel_caddr_t;
+typedef unsigned short	__kernel_uid16_t;
+typedef unsigned short	__kernel_gid16_t;
+typedef unsigned int	__kernel_uid32_t;
+typedef unsigned int	__kernel_gid32_t;
+
+typedef unsigned short	__kernel_old_uid_t;
+typedef unsigned short	__kernel_old_gid_t;
+typedef unsigned short	__kernel_old_dev_t;
+
+#ifdef __GNUC__
+typedef long long	__kernel_loff_t;
+#endif
+
+typedef struct {
+#if defined(__KERNEL__) || defined(__USE_ALL)
+	int	val[2];
+#else /* !defined(__KERNEL__) && !defined(__USE_ALL) */
+	int	__val[2];
+#endif /* !defined(__KERNEL__) && !defined(__USE_ALL) */
+} __kernel_fsid_t;
+
+#if defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2)
+
+#undef	__FD_SET
+#define	__FD_SET(d, set)	((set)->fds_bits[__FDELT(d)] |= __FDMASK(d))
+
+#undef	__FD_CLR
+#define	__FD_CLR(d, set)	((set)->fds_bits[__FDELT(d)] &= ~__FDMASK(d))
+
+#undef	__FD_ISSET
+#define	__FD_ISSET(d, set)	(!!((set)->fds_bits[__FDELT(d)] & __FDMASK(d)))
+
+#undef	__FD_ZERO
+#define __FD_ZERO(fdsetp) (memset (fdsetp, 0, sizeof(*(fd_set *)fdsetp)))
+
+#endif /* defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2) */
+
+#endif
+
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/include/asm-frv/processor.h linux-2.6.10-rc1-mm3-frv/include/asm-frv/processor.h
--- /warthog/kernels/linux-2.6.10-rc1-mm3/include/asm-frv/processor.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/include/asm-frv/processor.h	2004-11-05 14:13:04.151474828 +0000
@@ -0,0 +1,153 @@
+/* processor.h: FRV processor definitions
+ *
+ * Copyright (C) 2003 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * 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.
+ */
+
+#ifndef _ASM_PROCESSOR_H
+#define _ASM_PROCESSOR_H
+
+#include <linux/config.h>
+#include <asm/mem-layout.h>
+
+#ifndef __ASSEMBLY__
+/*
+ * Default implementation of macro that returns current
+ * instruction pointer ("program counter").
+ */
+#define current_text_addr() ({ __label__ _l; _l: &&_l;})
+
+#include <linux/linkage.h>
+#include <asm/sections.h>
+#include <asm/segment.h>
+#include <asm/fpu.h>
+#include <asm/registers.h>
+#include <asm/ptrace.h>
+#include <asm/current.h>
+#include <asm/cache.h>
+
+/* Forward declaration, a strange C thing */
+struct task_struct;
+
+/*
+ *  CPU type and hardware bug flags. Kept separately for each CPU.
+ */
+struct cpuinfo_frv {
+#ifdef CONFIG_MMU
+	unsigned long	*pgd_quick;
+	unsigned long	*pte_quick;
+	unsigned long	pgtable_cache_sz;
+#endif
+} __cacheline_aligned;
+
+extern struct cpuinfo_frv __nongprelbss boot_cpu_data;
+
+#define cpu_data		(&boot_cpu_data)
+#define current_cpu_data	boot_cpu_data
+
+/*
+ * Bus types
+ */
+#define EISA_bus 0
+#define MCA_bus 0
+
+struct thread_struct {
+	struct pt_regs		*frame;		/* [GR28] exception frame ptr for this thread */
+	struct task_struct	*curr;		/* [GR29] current pointer for this thread */
+	unsigned long		sp;		/* [GR1 ] kernel stack pointer */
+	unsigned long		fp;		/* [GR2 ] kernel frame pointer */
+	unsigned long		lr;		/* link register */
+	unsigned long		pc;		/* program counter */
+	unsigned long		gr[12];		/* [GR16-GR27] */
+	unsigned long		sched_lr;	/* LR from schedule() */
+
+	union {
+		struct pt_regs		*frame0;	/* top (user) stack frame */
+		struct user_context	*user;		/* userspace context */
+	};
+} __attribute__((aligned(8)));
+
+extern struct pt_regs *__kernel_frame0_ptr;
+extern struct task_struct *__kernel_current_task;
+
+#endif
+
+#ifndef __ASSEMBLY__
+#define INIT_THREAD_FRAME0 \
+	((struct pt_regs *) \
+	(sizeof(init_stack) + (unsigned long) init_stack - sizeof(struct user_context)))
+
+#define INIT_THREAD {				\
+	NULL,					\
+	(struct task_struct *) init_stack,	\
+	0, 0, 0, 0,				\
+	{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },	\
+	0,					\
+	{ INIT_THREAD_FRAME0 },			\
+}
+
+/*
+ * do necessary setup to start up a newly executed thread.
+ * - need to discard the frame stacked by init() invoking the execve syscall
+ */
+#define start_thread(_regs, _pc, _usp)			\
+do {							\
+	set_fs(USER_DS); /* reads from user space */	\
+	__frame = __kernel_frame0_ptr;			\
+	__frame->pc	= (_pc);			\
+	__frame->psr	&= ~PSR_S;			\
+	__frame->sp	= (_usp);			\
+} while(0)
+
+extern void prepare_to_copy(struct task_struct *tsk);
+
+/* Free all resources held by a thread. */
+static inline void release_thread(struct task_struct *dead_task)
+{
+}
+
+extern asmlinkage int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
+extern asmlinkage void save_user_regs(struct user_context *target);
+extern asmlinkage void restore_user_regs(const struct user_context *target);
+
+#define copy_segments(tsk, mm)		do { } while (0)
+#define release_segments(mm)		do { } while (0)
+#define forget_segments()		do { } while (0)
+
+/*
+ * Free current thread data structures etc..
+ */
+static inline void exit_thread(void)
+{
+}
+
+/*
+ * Return saved PC of a blocked thread.
+ */
+extern unsigned long thread_saved_pc(struct task_struct *tsk);
+
+unsigned long get_wchan(struct task_struct *p);
+
+#define	KSTK_EIP(tsk)	((tsk)->thread.frame0->pc)
+#define	KSTK_ESP(tsk)	((tsk)->thread.frame0->sp)
+
+/* Allocation and freeing of basic task resources. */
+extern struct task_struct *alloc_task_struct(void);
+extern void free_task_struct(struct task_struct *p);
+
+#define cpu_relax()    do { } while (0)
+
+/* data cache prefetch */
+#define ARCH_HAS_PREFETCH
+static inline void prefetch(const void *x)
+{
+	asm volatile("dcpl %0,gr0,#0" : : "r"(x));
+}
+
+#endif /* __ASSEMBLY__ */
+#endif /* _ASM_PROCESSOR_H */
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/include/asm-frv/ptrace.h linux-2.6.10-rc1-mm3-frv/include/asm-frv/ptrace.h
--- /warthog/kernels/linux-2.6.10-rc1-mm3/include/asm-frv/ptrace.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/include/asm-frv/ptrace.h	2004-11-05 14:13:04.154474574 +0000
@@ -0,0 +1,86 @@
+/* ptrace.h: ptrace() relevant definitions
+ *
+ * Copyright (C) 2003 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * 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.
+ */
+#ifndef _ASM_PTRACE_H
+#define _ASM_PTRACE_H
+
+#include <asm/registers.h>
+
+#define in_syscall(regs) (((regs)->tbr & TBR_TT) == TBR_TT_TRAP0)
+
+
+#define PT_PSR		0
+#define	PT_ISR		1
+#define PT_CCR		2
+#define PT_CCCR		3
+#define PT_LR		4
+#define PT_LCR		5
+#define PT_PC		6
+
+#define PT__STATUS	7	/* exception status */
+#define PT_SYSCALLNO	8	/* syscall number or -1 */
+#define PT_ORIG_GR8	9	/* saved GR8 for signal handling */
+#define PT_GNER0	10
+#define PT_GNER1	11
+#define PT_IACC0H	12
+#define PT_IACC0L	13
+
+#define PT_GR(j)	( 14 + (j))	/* GRj for 0<=j<=63 */
+#define PT_FR(j)	( 78 + (j))	/* FRj for 0<=j<=63 */
+#define PT_FNER(j)	(142 + (j))	/* FNERj for 0<=j<=1 */
+#define PT_MSR(j)	(144 + (j))	/* MSRj for 0<=j<=2 */
+#define PT_ACC(j)	(146 + (j))	/* ACCj for 0<=j<=7 */
+#define PT_ACCG(jklm)	(154 + (jklm))	/* ACCGjklm for 0<=jklm<=1 (reads four regs per slot) */
+#define PT_FSR(j)	(156 + (j))	/* FSRj for 0<=j<=0 */
+#define PT__GPEND	78
+#define PT__END		157
+
+#define PT_TBR		PT_GR(0)
+#define PT_SP		PT_GR(1)
+#define PT_FP		PT_GR(2)
+#define PT_PREV_FRAME	PT_GR(28)	/* previous exception frame pointer (old gr28 value) */
+#define PT_CURR_TASK	PT_GR(29)	/* current task */
+
+
+/* Arbitrarily choose the same ptrace numbers as used by the Sparc code. */
+#define PTRACE_GETREGS		12
+#define PTRACE_SETREGS		13
+#define PTRACE_GETFPREGS	14
+#define PTRACE_SETFPREGS	15
+#define PTRACE_GETFDPIC		31	/* get the ELF fdpic loadmap address */
+
+#define PTRACE_GETFDPIC_EXEC	0	/* [addr] request the executable loadmap */
+#define PTRACE_GETFDPIC_INTERP	1	/* [addr] request the interpreter loadmap */
+
+#ifndef __ASSEMBLY__
+
+/*
+ * dedicate GR28; to keeping the a pointer to the current exception frame
+ */
+register struct pt_regs *__frame asm("gr28");
+register struct pt_regs *__debug_frame asm("gr31");
+
+#ifndef container_of
+#define container_of(ptr, type, member) ({			\
+        const typeof( ((type *)0)->member ) *__mptr = (ptr);	\
+        (type *)( (char *)__mptr - offsetof(type,member) );})
+#endif
+
+#define __debug_regs container_of(__debug_frame, struct pt_debug_regs, normal_regs)
+
+#define user_mode(regs)			(!((regs)->psr & PSR_S))
+#define instruction_pointer(regs)	((regs)->pc)
+
+extern unsigned long user_stack(const struct pt_regs *);
+extern void show_regs(struct pt_regs *);
+#define profile_pc(regs) ((regs)->pc)
+
+#endif /* !__ASSEMBLY__ */
+#endif /* _ASM_PTRACE_H */

^ permalink raw reply	[flat|nested] 87+ messages in thread

* [PATCH 15/20] FRV: Fujitsu FR-V arch include files
  2004-11-08 14:34 [PATCH 1/20] FRV: Fujitsu FR-V CPU arch maintainer record dhowells
                   ` (9 preceding siblings ...)
  2004-11-08 14:34 ` [PATCH 10/20] FRV: Fujitsu FR-V CPU arch implementation part 8 dhowells
@ 2004-11-08 14:34 ` dhowells
  2004-11-08 14:34 ` [PATCH 16/20] FRV: Make calibrate_delay() optional dhowells
                   ` (5 subsequent siblings)
  16 siblings, 0 replies; 87+ messages in thread
From: dhowells @ 2004-11-08 14:34 UTC (permalink / raw)
  To: torvalds, akpm, davidm; +Cc: linux-kernel, uclinux-dev

The attached patch provides the arch-specific include files for the Fujitsu
FR-V CPU arch.

Signed-Off-By: dhowells@redhat.com
---
diffstat frv-include_4-2610rc1mm3.diff
 asm-frv/unaligned.h   |  203 ++++++++++++++++++++
 asm-frv/unistd.h      |  491 ++++++++++++++++++++++++++++++++++++++++++++++++++
 asm-frv/user.h        |   80 ++++++++
 asm-frv/virtconvert.h |   42 ++++
 linux/elf.h           |    7 
 linux/suspend.h       |    2 
 6 files changed, 822 insertions(+), 3 deletions(-)

diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/include/asm-frv/unaligned.h linux-2.6.10-rc1-mm3-frv/include/asm-frv/unaligned.h
--- /warthog/kernels/linux-2.6.10-rc1-mm3/include/asm-frv/unaligned.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/include/asm-frv/unaligned.h	2004-11-05 14:13:04.310461399 +0000
@@ -0,0 +1,203 @@
+/* unaligned.h: unaligned access handler
+ *
+ * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * 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.
+ */
+
+#ifndef _ASM_UNALIGNED_H
+#define _ASM_UNALIGNED_H
+
+#include <linux/config.h>
+
+/*
+ * Unaligned accesses on uClinux can't be performed in a fault handler - the
+ * CPU detects them as imprecise exceptions making this impossible.
+ *
+ * With the FR451, however, they are precise, and so we used to fix them up in
+ * the memory access fault handler.  However, instruction bundling make this
+ * impractical.  So, now we fall back to using memcpy.
+ */
+#ifdef CONFIG_MMU
+
+/*
+ * The asm statement in the macros below is a way to get GCC to copy a
+ * value from one variable to another without having any clue it's
+ * actually doing so, so that it won't have any idea that the values
+ * in the two variables are related.
+ */
+
+#define get_unaligned(ptr) ({				\
+	typeof((*(ptr))) __x;				\
+	void *__ptrcopy;				\
+	asm("" : "=r" (__ptrcopy) : "0" (ptr));		\
+	memcpy(&__x, __ptrcopy, sizeof(*(ptr)));	\
+	__x;						\
+})
+
+#define put_unaligned(val, ptr) ({			\
+	typeof((*(ptr))) __x = (val);			\
+	void *__ptrcopy;				\
+	asm("" : "=r" (__ptrcopy) : "0" (ptr));		\
+	memcpy(__ptrcopy, &__x, sizeof(*(ptr)));	\
+})
+
+extern int handle_misalignment(unsigned long esr0, unsigned long ear0, unsigned long epcr0);
+
+#else
+
+#define get_unaligned(ptr)							\
+({										\
+	typeof(*(ptr)) x;							\
+	const char *__p = (const char *) (ptr);					\
+										\
+	switch (sizeof(x)) {							\
+	case 1:									\
+		x = *(ptr);							\
+		break;								\
+	case 2:									\
+	{									\
+		uint8_t a;							\
+		asm("	ldub%I2		%M2,%0		\n"			\
+		    "	ldub%I3.p	%M3,%1		\n"			\
+		    "	slli		%0,#8,%0	\n"			\
+		    "	or		%0,%1,%0	\n"			\
+		    : "=&r"(x), "=&r"(a)					\
+		    : "m"(__p[0]),  "m"(__p[1])					\
+		    );								\
+		break;								\
+	}									\
+										\
+	case 4:									\
+	{									\
+		uint8_t a;							\
+		asm("	ldub%I2		%M2,%0		\n"			\
+		    "	ldub%I3.p	%M3,%1		\n"			\
+		    "	slli		%0,#8,%0	\n"			\
+		    "	or		%0,%1,%0	\n"			\
+		    "	ldub%I4.p	%M4,%1		\n"			\
+		    "	slli		%0,#8,%0	\n"			\
+		    "	or		%0,%1,%0	\n"			\
+		    "	ldub%I5.p	%M5,%1		\n"			\
+		    "	slli		%0,#8,%0	\n"			\
+		    "	or		%0,%1,%0	\n"			\
+		    : "=&r"(x), "=&r"(a)					\
+		    : "m"(__p[0]),  "m"(__p[1]), "m"(__p[2]), "m"(__p[3])	\
+		    );								\
+		break;								\
+	}									\
+										\
+	case 8:									\
+	{									\
+		union { uint64_t x; u32 y[2]; } z;				\
+		uint8_t a;							\
+		asm("	ldub%I3		%M3,%0		\n"			\
+		    "	ldub%I4.p	%M4,%2		\n"			\
+		    "	slli		%0,#8,%0	\n"			\
+		    "	or		%0,%2,%0	\n"			\
+		    "	ldub%I5.p	%M5,%2		\n"			\
+		    "	slli		%0,#8,%0	\n"			\
+		    "	or		%0,%2,%0	\n"			\
+		    "	ldub%I6.p	%M6,%2		\n"			\
+		    "	slli		%0,#8,%0	\n"			\
+		    "	or		%0,%2,%0	\n"			\
+		    "	ldub%I7		%M7,%1		\n"			\
+		    "	ldub%I8.p	%M8,%2		\n"			\
+		    "	slli		%1,#8,%1	\n"			\
+		    "	or		%1,%2,%1	\n"			\
+		    "	ldub%I9.p	%M9,%2		\n"			\
+		    "	slli		%1,#8,%1	\n"			\
+		    "	or		%1,%2,%1	\n"			\
+		    "	ldub%I10.p	%M10,%2		\n"			\
+		    "	slli		%1,#8,%1	\n"			\
+		    "	or		%1,%2,%1	\n"			\
+		    : "=&r"(z.y[0]), "=&r"(z.y[1]), "=&r"(a)			\
+		    : "m"(__p[0]), "m"(__p[1]), "m"(__p[2]), "m"(__p[3]),	\
+		      "m"(__p[4]), "m"(__p[5]), "m"(__p[6]), "m"(__p[7])	\
+		    );								\
+		x = z.x;							\
+		break;								\
+	}									\
+										\
+	default:								\
+		x = 0;								\
+		BUG();								\
+		break;								\
+	}									\
+										\
+	x;									\
+})
+
+#define put_unaligned(val, ptr)								\
+do {											\
+	char *__p = (char *) (ptr);							\
+	int x;										\
+											\
+	switch (sizeof(*ptr)) {								\
+	case 2:										\
+	{										\
+		asm("	stb%I1.p	%0,%M1		\n"				\
+		    "	srli		%0,#8,%0	\n"				\
+		    "	stb%I2		%0,%M2		\n"				\
+		    : "=r"(x), "=m"(__p[1]),  "=m"(__p[0])				\
+		    : "0"(val)								\
+		    );									\
+		break;									\
+	}										\
+											\
+	case 4:										\
+	{										\
+		asm("	stb%I1.p	%0,%M1		\n"				\
+		    "	srli		%0,#8,%0	\n"				\
+		    "	stb%I2.p	%0,%M2		\n"				\
+		    "	srli		%0,#8,%0	\n"				\
+		    "	stb%I3.p	%0,%M3		\n"				\
+		    "	srli		%0,#8,%0	\n"				\
+		    "	stb%I4		%0,%M4		\n"				\
+		    : "=r"(x), "=m"(__p[3]),  "=m"(__p[2]), "=m"(__p[1]), "=m"(__p[0])	\
+		    : "0"(val)								\
+		    );									\
+		break;									\
+	}										\
+											\
+	case 8:										\
+	{										\
+		uint32_t __high, __low;							\
+		__high = (uint64_t)val >> 32;						\
+		__low = val & 0xffffffff;						\
+		asm("	stb%I2.p	%0,%M2		\n"				\
+		    "	srli		%0,#8,%0	\n"				\
+		    "	stb%I3.p	%0,%M3		\n"				\
+		    "	srli		%0,#8,%0	\n"				\
+		    "	stb%I4.p	%0,%M4		\n"				\
+		    "	srli		%0,#8,%0	\n"				\
+		    "	stb%I5.p	%0,%M5		\n"				\
+		    "	srli		%0,#8,%0	\n"				\
+		    "	stb%I6.p	%1,%M6		\n"				\
+		    "	srli		%1,#8,%1	\n"				\
+		    "	stb%I7.p	%1,%M7		\n"				\
+		    "	srli		%1,#8,%1	\n"				\
+		    "	stb%I8.p	%1,%M8		\n"				\
+		    "	srli		%1,#8,%1	\n"				\
+		    "	stb%I9		%1,%M9		\n"				\
+		    : "=&r"(__low), "=&r"(__high), "=m"(__p[7]), "=m"(__p[6]), 		\
+		      "=m"(__p[5]), "=m"(__p[4]), "=m"(__p[3]), "=m"(__p[2]), 		\
+		      "=m"(__p[1]), "=m"(__p[0])					\
+		    : "0"(__low), "1"(__high)						\
+		    );									\
+		break;									\
+	}										\
+											\
+        default:									\
+		*(ptr) = (val);								\
+		break;									\
+	}										\
+} while(0)
+
+#endif
+
+#endif
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/include/asm-frv/unistd.h linux-2.6.10-rc1-mm3-frv/include/asm-frv/unistd.h
--- /warthog/kernels/linux-2.6.10-rc1-mm3/include/asm-frv/unistd.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/include/asm-frv/unistd.h	2004-11-05 14:13:04.315460977 +0000
@@ -0,0 +1,491 @@
+#ifndef _ASM_UNISTD_H_
+#define _ASM_UNISTD_H_
+
+/*
+ * This file contains the system call numbers.
+ */
+
+#define __NR_restart_syscall      0
+#define __NR_exit		  1
+#define __NR_fork		  2
+#define __NR_read		  3
+#define __NR_write		  4
+#define __NR_open		  5
+#define __NR_close		  6
+#define __NR_waitpid		  7
+#define __NR_creat		  8
+#define __NR_link		  9
+#define __NR_unlink		 10
+#define __NR_execve		 11
+#define __NR_chdir		 12
+#define __NR_time		 13
+#define __NR_mknod		 14
+#define __NR_chmod		 15
+#define __NR_lchown		 16
+#define __NR_break		 17
+#define __NR_oldstat		 18
+#define __NR_lseek		 19
+#define __NR_getpid		 20
+#define __NR_mount		 21
+#define __NR_umount		 22
+#define __NR_setuid		 23
+#define __NR_getuid		 24
+#define __NR_stime		 25
+#define __NR_ptrace		 26
+#define __NR_alarm		 27
+#define __NR_oldfstat		 28
+#define __NR_pause		 29
+#define __NR_utime		 30
+#define __NR_stty		 31
+#define __NR_gtty		 32
+#define __NR_access		 33
+#define __NR_nice		 34
+#define __NR_ftime		 35
+#define __NR_sync		 36
+#define __NR_kill		 37
+#define __NR_rename		 38
+#define __NR_mkdir		 39
+#define __NR_rmdir		 40
+#define __NR_dup		 41
+#define __NR_pipe		 42
+#define __NR_times		 43
+#define __NR_prof		 44
+#define __NR_brk		 45
+#define __NR_setgid		 46
+#define __NR_getgid		 47
+#define __NR_signal		 48
+#define __NR_geteuid		 49
+#define __NR_getegid		 50
+#define __NR_acct		 51
+#define __NR_umount2		 52
+#define __NR_lock		 53
+#define __NR_ioctl		 54
+#define __NR_fcntl		 55
+#define __NR_mpx		 56
+#define __NR_setpgid		 57
+#define __NR_ulimit		 58
+// #define __NR_oldolduname	 /* 59 */ obsolete
+#define __NR_umask		 60
+#define __NR_chroot		 61
+#define __NR_ustat		 62
+#define __NR_dup2		 63
+#define __NR_getppid		 64
+#define __NR_getpgrp		 65
+#define __NR_setsid		 66
+#define __NR_sigaction		 67
+#define __NR_sgetmask		 68
+#define __NR_ssetmask		 69
+#define __NR_setreuid		 70
+#define __NR_setregid		 71
+#define __NR_sigsuspend		 72
+#define __NR_sigpending		 73
+#define __NR_sethostname	 74
+#define __NR_setrlimit		 75
+#define __NR_getrlimit		 76	/* Back compatible 2Gig limited rlimit */
+#define __NR_getrusage		 77
+#define __NR_gettimeofday	 78
+#define __NR_settimeofday	 79
+#define __NR_getgroups		 80
+#define __NR_setgroups		 81
+#define __NR_select		 82
+#define __NR_symlink		 83
+#define __NR_oldlstat		 84
+#define __NR_readlink		 85
+#define __NR_uselib		 86
+#define __NR_swapon		 87
+#define __NR_reboot		 88
+#define __NR_readdir		 89
+// #define __NR_mmap		 90	/* obsolete - not implemented */
+#define __NR_munmap		 91
+#define __NR_truncate		 92
+#define __NR_ftruncate		 93
+#define __NR_fchmod		 94
+#define __NR_fchown		 95
+#define __NR_getpriority	 96
+#define __NR_setpriority	 97
+// #define __NR_profil		 /* 98 */ obsolete
+#define __NR_statfs		 99
+#define __NR_fstatfs		100
+// #define __NR_ioperm		/* 101 */ not supported
+#define __NR_socketcall		102
+#define __NR_syslog		103
+#define __NR_setitimer		104
+#define __NR_getitimer		105
+#define __NR_stat		106
+#define __NR_lstat		107
+#define __NR_fstat		108
+// #define __NR_olduname		/* 109 */ obsolete
+// #define __NR_iopl		/* 110 */ not supported
+#define __NR_vhangup		111
+// #define __NR_idle		/* 112 */ Obsolete
+// #define __NR_vm86old		/* 113 */ not supported
+#define __NR_wait4		114
+#define __NR_swapoff		115
+#define __NR_sysinfo		116
+#define __NR_ipc		117
+#define __NR_fsync		118
+#define __NR_sigreturn		119
+#define __NR_clone		120
+#define __NR_setdomainname	121
+#define __NR_uname		122
+// #define __NR_modify_ldt	/* 123 */ not supported
+#define __NR_cacheflush		123
+#define __NR_adjtimex		124
+#define __NR_mprotect		125
+#define __NR_sigprocmask	126
+#define __NR_create_module	127
+#define __NR_init_module	128
+#define __NR_delete_module	129
+#define __NR_get_kernel_syms	130
+#define __NR_quotactl		131
+#define __NR_getpgid		132
+#define __NR_fchdir		133
+#define __NR_bdflush		134
+#define __NR_sysfs		135
+#define __NR_personality	136
+#define __NR_afs_syscall	137 /* Syscall for Andrew File System */
+#define __NR_setfsuid		138
+#define __NR_setfsgid		139
+#define __NR__llseek		140
+#define __NR_getdents		141
+#define __NR__newselect		142
+#define __NR_flock		143
+#define __NR_msync		144
+#define __NR_readv		145
+#define __NR_writev		146
+#define __NR_getsid		147
+#define __NR_fdatasync		148
+#define __NR__sysctl		149
+#define __NR_mlock		150
+#define __NR_munlock		151
+#define __NR_mlockall		152
+#define __NR_munlockall		153
+#define __NR_sched_setparam		154
+#define __NR_sched_getparam		155
+#define __NR_sched_setscheduler		156
+#define __NR_sched_getscheduler		157
+#define __NR_sched_yield		158
+#define __NR_sched_get_priority_max	159
+#define __NR_sched_get_priority_min	160
+#define __NR_sched_rr_get_interval	161
+#define __NR_nanosleep		162
+#define __NR_mremap		163
+#define __NR_setresuid		164
+#define __NR_getresuid		165
+// #define __NR_vm86		/* 166 */ not supported
+#define __NR_query_module	167
+#define __NR_poll		168
+#define __NR_nfsservctl		169
+#define __NR_setresgid		170
+#define __NR_getresgid		171
+#define __NR_prctl		172
+#define __NR_rt_sigreturn	173
+#define __NR_rt_sigaction	174
+#define __NR_rt_sigprocmask	175
+#define __NR_rt_sigpending	176
+#define __NR_rt_sigtimedwait	177
+#define __NR_rt_sigqueueinfo	178
+#define __NR_rt_sigsuspend	179
+#define __NR_pread		180
+#define __NR_pwrite		181
+#define __NR_chown		182
+#define __NR_getcwd		183
+#define __NR_capget		184
+#define __NR_capset		185
+#define __NR_sigaltstack	186
+#define __NR_sendfile		187
+#define __NR_getpmsg		188	/* some people actually want streams */
+#define __NR_putpmsg		189	/* some people actually want streams */
+#define __NR_vfork		190
+#define __NR_ugetrlimit		191	/* SuS compliant getrlimit */
+#define __NR_mmap2		192
+#define __NR_truncate64		193
+#define __NR_ftruncate64	194
+#define __NR_stat64		195
+#define __NR_lstat64		196
+#define __NR_fstat64		197
+#define __NR_lchown32		198
+#define __NR_getuid32		199
+#define __NR_getgid32		200
+#define __NR_geteuid32		201
+#define __NR_getegid32		202
+#define __NR_setreuid32		203
+#define __NR_setregid32		204
+#define __NR_getgroups32	205
+#define __NR_setgroups32	206
+#define __NR_fchown32		207
+#define __NR_setresuid32	208
+#define __NR_getresuid32	209
+#define __NR_setresgid32	210
+#define __NR_getresgid32	211
+#define __NR_chown32		212
+#define __NR_setuid32		213
+#define __NR_setgid32		214
+#define __NR_setfsuid32		215
+#define __NR_setfsgid32		216
+#define __NR_pivot_root		217
+#define __NR_mincore		218
+#define __NR_madvise		219
+
+#define __NR_getdents64		220
+#define __NR_fcntl64		221
+#define __NR_security		223	/* syscall for security modules */
+#define __NR_gettid		224
+#define __NR_readahead		225
+#define __NR_setxattr		226
+#define __NR_lsetxattr		227
+#define __NR_fsetxattr		228
+#define __NR_getxattr		229
+#define __NR_lgetxattr		230
+#define __NR_fgetxattr		231
+#define __NR_listxattr		232
+#define __NR_llistxattr		233
+#define __NR_flistxattr		234
+#define __NR_removexattr	235
+#define __NR_lremovexattr	236
+#define __NR_fremovexattr	237
+#define __NR_tkill		238
+#define __NR_sendfile64		239
+#define __NR_futex		240
+#define __NR_sched_setaffinity	241
+#define __NR_sched_getaffinity	242
+#define __NR_set_thread_area	243
+#define __NR_get_thread_area	244
+#define __NR_io_setup		245
+#define __NR_io_destroy		246
+#define __NR_io_getevents	247
+#define __NR_io_submit		248
+#define __NR_io_cancel		249
+#define __NR_fadvise64		250
+
+#define __NR_exit_group		252
+#define __NR_lookup_dcookie	253
+#define __NR_epoll_create	254
+#define __NR_epoll_ctl		255
+#define __NR_epoll_wait		256
+#define __NR_remap_file_pages	257
+#define __NR_set_tid_address	258
+#define __NR_timer_create	259
+#define __NR_timer_settime	(__NR_timer_create+1)
+#define __NR_timer_gettime	(__NR_timer_create+2)
+#define __NR_timer_getoverrun	(__NR_timer_create+3)
+#define __NR_timer_delete	(__NR_timer_create+4)
+#define __NR_clock_settime	(__NR_timer_create+5)
+#define __NR_clock_gettime	(__NR_timer_create+6)
+#define __NR_clock_getres	(__NR_timer_create+7)
+#define __NR_clock_nanosleep	(__NR_timer_create+8)
+#define __NR_statfs64		268
+#define __NR_fstatfs64		269
+#define __NR_tgkill		270
+#define __NR_utimes		271
+#define __NR_fadvise64_64	272
+#define __NR_vserver		273
+#define __NR_mbind		274
+#define __NR_get_mempolicy	275
+#define __NR_set_mempolicy	276
+#define __NR_mq_open 		277
+#define __NR_mq_unlink		(__NR_mq_open+1)
+#define __NR_mq_timedsend	(__NR_mq_open+2)
+#define __NR_mq_timedreceive	(__NR_mq_open+3)
+#define __NR_mq_notify		(__NR_mq_open+4)
+#define __NR_mq_getsetattr	(__NR_mq_open+5)
+#define __NR_sys_kexec_load	283
+
+#define NR_syscalls 284
+
+/*
+ * process the return value of a syscall, consigning it to one of two possible fates
+ * - user-visible error numbers are in the range -1 - -4095: see <asm-frv/errno.h>
+ */
+#undef __syscall_return
+#define __syscall_return(type, res)					\
+do {									\
+        unsigned long __sr2 = (res);					\
+	if (__builtin_expect(__sr2 >= (unsigned long)(-4095), 0)) {	\
+		errno = (-__sr2);					\
+		__sr2 = ULONG_MAX;					\
+	}								\
+	return (type) __sr2;						\
+} while (0)
+
+/* XXX - _foo needs to be __foo, while __NR_bar could be _NR_bar. */
+
+#undef _syscall0
+#define _syscall0(type,name)						\
+type name(void)								\
+{									\
+	register unsigned long __scnum __asm__ ("gr7") = (__NR_##name);	\
+	register unsigned long __sc0 __asm__ ("gr8");			\
+	__asm__ __volatile__ ("tira gr0,#0"				\
+			      : "=r" (__sc0)				\
+			      : "r" (__scnum));				\
+	__syscall_return(type, __sc0);					\
+}
+
+#undef _syscall1
+#define _syscall1(type,name,type1,arg1)						\
+type name(type1 arg1)								\
+{										\
+	register unsigned long __scnum __asm__ ("gr7") = (__NR_##name);		\
+	register unsigned long __sc0 __asm__ ("gr8") = (unsigned long) arg1;	\
+	__asm__ __volatile__ ("tira gr0,#0"					\
+			      : "+r" (__sc0)					\
+			      : "r" (__scnum));					\
+	__syscall_return(type, __sc0);						\
+}
+
+#undef _syscall2
+#define _syscall2(type,name,type1,arg1,type2,arg2)				\
+type name(type1 arg1,type2 arg2)						\
+{										\
+	register unsigned long __scnum __asm__ ("gr7") = (__NR_##name);		\
+	register unsigned long __sc0 __asm__ ("gr8") = (unsigned long) arg1;	\
+	register unsigned long __sc1 __asm__ ("gr9") = (unsigned long) arg2;	\
+	__asm__ __volatile__ ("tira gr0,#0"					\
+			      : "+r" (__sc0)					\
+			      : "r" (__scnum), "r" (__sc1));			\
+	__syscall_return(type, __sc0);						\
+}
+
+#undef _syscall3
+#define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3)			\
+type name(type1 arg1,type2 arg2,type3 arg3)					\
+{										\
+	register unsigned long __scnum __asm__ ("gr7") = (__NR_##name);		\
+	register unsigned long __sc0 __asm__ ("gr8") = (unsigned long) arg1;	\
+	register unsigned long __sc1 __asm__ ("gr9") = (unsigned long) arg2;	\
+	register unsigned long __sc2 __asm__ ("gr10") = (unsigned long) arg3;	\
+	__asm__ __volatile__ ("tira gr0,#0"					\
+			      : "+r" (__sc0)					\
+			      : "r" (__scnum), "r" (__sc1), "r" (__sc2));	\
+	__syscall_return(type, __sc0);						\
+}
+
+#undef _syscall4
+#define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4)		\
+type name (type1 arg1, type2 arg2, type3 arg3, type4 arg4)				\
+{											\
+	register unsigned long __scnum __asm__ ("gr7") = (__NR_##name);			\
+	register unsigned long __sc0 __asm__ ("gr8") = (unsigned long) arg1;		\
+	register unsigned long __sc1 __asm__ ("gr9") = (unsigned long) arg2;		\
+	register unsigned long __sc2 __asm__ ("gr10") = (unsigned long) arg3;		\
+	register unsigned long __sc3 __asm__ ("gr11") = (unsigned long) arg4;		\
+	__asm__ __volatile__ ("tira gr0,#0"						\
+			      : "+r" (__sc0)						\
+			      : "r" (__scnum), "r" (__sc1), "r" (__sc2), "r" (__sc3));	\
+	__syscall_return(type, __sc0);							\
+}
+
+#undef _syscall5
+#define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,type5,arg5)	\
+type name (type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5)			\
+{											\
+	register unsigned long __scnum __asm__ ("gr7") = (__NR_##name);			\
+	register unsigned long __sc0 __asm__ ("gr8") = (unsigned long) arg1;		\
+	register unsigned long __sc1 __asm__ ("gr9") = (unsigned long) arg2;		\
+	register unsigned long __sc2 __asm__ ("gr10") = (unsigned long) arg3;		\
+	register unsigned long __sc3 __asm__ ("gr11") = (unsigned long) arg4;		\
+	register unsigned long __sc4 __asm__ ("gr12") = (unsigned long) arg5;		\
+	__asm__ __volatile__ ("tira gr0,#0"						\
+			      : "+r" (__sc0)						\
+			      : "r" (__scnum), "r" (__sc1), "r" (__sc2),		\
+			      "r" (__sc3), "r" (__sc4));				\
+	__syscall_return(type, __sc0);							\
+}
+
+#undef _syscall6
+#define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,type5,arg5, type6, arg6) \
+type name (type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6)		 \
+{												 \
+	register unsigned long __scnum __asm__ ("gr7") = (__NR_##name);				 \
+	register unsigned long __sc0 __asm__ ("gr8") = (unsigned long) arg1;			 \
+	register unsigned long __sc1 __asm__ ("gr9") = (unsigned long) arg2;			 \
+	register unsigned long __sc2 __asm__ ("gr10") = (unsigned long) arg3;			 \
+	register unsigned long __sc3 __asm__ ("gr11") = (unsigned long) arg4;			 \
+	register unsigned long __sc4 __asm__ ("gr12") = (unsigned long) arg5;			 \
+	register unsigned long __sc5 __asm__ ("gr13") = (unsigned long) arg6;			 \
+	__asm__ __volatile__ ("tira gr0,#0"							 \
+			      : "+r" (__sc0)							 \
+			      : "r" (__scnum), "r" (__sc1), "r" (__sc2),			 \
+			      "r" (__sc3), "r" (__sc4), "r" (__sc5));				 \
+	__syscall_return(type, __sc0);								 \
+}
+		
+
+#ifdef __KERNEL_SYSCALLS__
+
+#include <linux/compiler.h>
+#include <linux/types.h>
+#include <linux/linkage.h>
+#include <asm/ptrace.h>
+
+/*
+ * we need this inline - forking from kernel space will result
+ * in NO COPY ON WRITE (!!!), until an execve is executed. This
+ * is no problem, but for the stack. This is handled by not letting
+ * main() use the stack at all after fork(). Thus, no function
+ * calls - which means inline code for fork too, as otherwise we
+ * would use the stack upon exit from 'fork()'.
+ *
+ * Actually only pause and fork are needed inline, so that there
+ * won't be any messing with the stack from main(), but we define
+ * some others too.
+ */
+#define __NR__exit __NR_exit
+static inline _syscall0(int,pause)
+static inline _syscall0(int,sync)
+static inline _syscall0(pid_t,setsid)
+static inline _syscall3(int,write,int,fd,const char *,buf,off_t,count)
+static inline _syscall3(int,read,int,fd,char *,buf,off_t,count)
+static inline _syscall3(off_t,lseek,int,fd,off_t,offset,int,count)
+static inline _syscall1(int,dup,int,fd)
+static inline _syscall3(int,execve,const char *,file,char **,argv,char **,envp)
+static inline _syscall3(int,open,const char *,file,int,flag,int,mode)
+static inline _syscall1(int,close,int,fd)
+static inline _syscall1(int,_exit,int,exitcode)
+static inline _syscall3(pid_t,waitpid,pid_t,pid,int *,wait_stat,int,options)
+static inline _syscall1(int,delete_module,const char *,name)
+
+static inline pid_t wait(int * wait_stat)
+{
+	return waitpid(-1,wait_stat,0);
+}
+
+#endif
+
+#ifdef __KERNEL__
+#define __ARCH_WANT_IPC_PARSE_VERSION
+/* #define __ARCH_WANT_OLD_READDIR */
+#define __ARCH_WANT_OLD_STAT
+#define __ARCH_WANT_STAT64
+#define __ARCH_WANT_SYS_ALARM
+/* #define __ARCH_WANT_SYS_GETHOSTNAME */
+#define __ARCH_WANT_SYS_PAUSE
+/* #define __ARCH_WANT_SYS_SGETMASK */
+/* #define __ARCH_WANT_SYS_SIGNAL */
+#define __ARCH_WANT_SYS_TIME
+#define __ARCH_WANT_SYS_UTIME
+#define __ARCH_WANT_SYS_WAITPID
+#define __ARCH_WANT_SYS_SOCKETCALL
+#define __ARCH_WANT_SYS_FADVISE64
+#define __ARCH_WANT_SYS_GETPGRP
+#define __ARCH_WANT_SYS_LLSEEK
+#define __ARCH_WANT_SYS_NICE
+/* #define __ARCH_WANT_SYS_OLD_GETRLIMIT */
+#define __ARCH_WANT_SYS_OLDUMOUNT
+/* #define __ARCH_WANT_SYS_SIGPENDING */
+#define __ARCH_WANT_SYS_SIGPROCMASK
+#define __ARCH_WANT_SYS_RT_SIGACTION
+#endif
+
+/*
+ * "Conditional" syscalls
+ *
+ * What we want is __attribute__((weak,alias("sys_ni_syscall"))),
+ * but it doesn't work on all toolchains, so we just do it by hand
+ */
+#ifndef cond_syscall
+#define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall");
+#endif
+
+#endif /* _ASM_UNISTD_H_ */
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/include/asm-frv/user.h linux-2.6.10-rc1-mm3-frv/include/asm-frv/user.h
--- /warthog/kernels/linux-2.6.10-rc1-mm3/include/asm-frv/user.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/include/asm-frv/user.h	2004-11-05 14:13:04.320460555 +0000
@@ -0,0 +1,80 @@
+/* user.h: FR-V core file format stuff
+ *
+ * Copyright (C) 2003 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * 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.
+ */
+#ifndef _ASM_USER_H
+#define _ASM_USER_H
+
+#include <asm/page.h>
+#include <asm/registers.h>
+
+/* Core file format: The core file is written in such a way that gdb
+ * can understand it and provide useful information to the user (under
+ * linux we use the 'trad-core' bfd).  There are quite a number of
+ * obstacles to being able to view the contents of the floating point
+ * registers, and until these are solved you will not be able to view
+ * the contents of them.  Actually, you can read in the core file and
+ * look at the contents of the user struct to find out what the
+ * floating point registers contain.
+ * 
+ * The actual file contents are as follows:
+ * UPAGE:
+ *   1 page consisting of a user struct that tells gdb what is present
+ *   in the file.  Directly after this is a copy of the task_struct,
+ *   which is currently not used by gdb, but it may come in useful at
+ *   some point.  All of the registers are stored as part of the
+ *   upage.  The upage should always be only one page.
+ *
+ * DATA:
+ *   The data area is stored.  We use current->end_text to
+ *   current->brk to pick up all of the user variables, plus any
+ *   memory that may have been malloced.  No attempt is made to
+ *   determine if a page is demand-zero or if a page is totally
+ *   unused, we just cover the entire range.  All of the addresses are
+ *   rounded in such a way that an integral number of pages is
+ *   written.
+ *
+ * STACK:
+ *   We need the stack information in order to get a meaningful
+ *   backtrace.  We need to write the data from (esp) to
+ *   current->start_stack, so we round each of these off in order to
+ *   be able to write an integer number of pages.  The minimum core
+ *   file size is 3 pages, or 12288 bytes.
+ */
+	
+/* When the kernel dumps core, it starts by dumping the user struct -
+ * this will be used by gdb to figure out where the data and stack segments
+ *  are within the file, and what virtual addresses to use.
+ */
+struct user {
+	/* We start with the registers, to mimic the way that "memory" is returned
+	 * from the ptrace(3,...) function.  */
+	struct user_context	regs;
+
+	/* The rest of this junk is to help gdb figure out what goes where */
+	unsigned long		u_tsize;	/* Text segment size (pages). */
+	unsigned long		u_dsize;	/* Data segment size (pages). */
+	unsigned long		u_ssize;	/* Stack segment size (pages). */
+	unsigned long		start_code;     /* Starting virtual address of text. */
+	unsigned long		start_stack;	/* Starting virtual address of stack area.
+						 * This is actually the bottom of the stack,
+						 * the top of the stack is always found in the
+						 * esp register.  */
+	long int		signal;		/* Signal that caused the core dump. */
+
+	unsigned long		magic;		/* To uniquely identify a core file */
+	char			u_comm[32];	/* User command that was responsible */
+};
+
+#define NBPG			PAGE_SIZE
+#define UPAGES			1
+#define HOST_TEXT_START_ADDR	(u.start_code)
+#define HOST_STACK_END_ADDR	(u.start_stack + u.u_ssize * NBPG)
+
+#endif
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/include/asm-frv/virtconvert.h linux-2.6.10-rc1-mm3-frv/include/asm-frv/virtconvert.h
--- /warthog/kernels/linux-2.6.10-rc1-mm3/include/asm-frv/virtconvert.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/include/asm-frv/virtconvert.h	2004-11-05 14:13:04.323460301 +0000
@@ -0,0 +1,42 @@
+/* virtconvert.h: virtual/physical/page address convertion
+ *
+ * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * 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.
+ */
+#ifndef _ASM_VIRTCONVERT_H
+#define _ASM_VIRTCONVERT_H
+
+/*
+ * Macros used for converting between virtual and physical mappings.
+ */
+
+#ifdef __KERNEL__
+
+#include <linux/config.h>
+#include <asm/setup.h>
+
+#ifdef CONFIG_MMU
+
+#define phys_to_virt(vaddr)	((void *) ((unsigned long)(vaddr) + PAGE_OFFSET))
+#define virt_to_phys(vaddr)	((unsigned long) (vaddr) - PAGE_OFFSET)
+
+#else
+
+#define phys_to_virt(vaddr)	((void *) (vaddr))
+#define virt_to_phys(vaddr)	((unsigned long) (vaddr))
+
+#endif
+
+#define virt_to_bus virt_to_phys
+#define bus_to_virt phys_to_virt
+
+#define __page_address(page)	(PAGE_OFFSET + (((page) - mem_map) << PAGE_SHIFT))
+#define page_to_phys(page)	virt_to_phys((void *)__page_address(page))
+
+#endif
+#endif
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/include/linux/elf.h linux-2.6.10-rc1-mm3-frv/include/linux/elf.h
--- /warthog/kernels/linux-2.6.10-rc1-mm3/include/linux/elf.h	2004-10-19 10:42:16.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/include/linux/elf.h	2004-11-05 14:13:04.388454812 +0000
@@ -36,8 +36,9 @@ typedef __s64	Elf64_Sxword;
 #define PT_NOTE    4
 #define PT_SHLIB   5
 #define PT_PHDR    6
-#define PT_LOOS	   0x60000000
-#define PT_HIOS	   0x6fffffff
+#define PT_TLS     7               /* Thread local storage segment */
+#define PT_LOOS    0x60000000      /* OS-specific */
+#define PT_HIOS    0x6fffffff      /* OS-specific */
 #define PT_LOPROC  0x70000000
 #define PT_HIPROC  0x7fffffff
 #define PT_GNU_EH_FRAME		0x6474e550
@@ -109,6 +110,8 @@ typedef __s64	Elf64_Sxword;
  */
 #define EM_S390_OLD     0xA390
 
+#define EM_FRV		0x5441		/* Fujitsu FR-V */
+
 /* This is the info that is needed to parse the dynamic section of the file */
 #define DT_NULL		0
 #define DT_NEEDED	1
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/include/linux/suspend.h linux-2.6.10-rc1-mm3-frv/include/linux/suspend.h
--- /warthog/kernels/linux-2.6.10-rc1-mm3/include/linux/suspend.h	2004-10-19 10:42:17.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/include/linux/suspend.h	2004-11-05 14:13:04.442450251 +0000
@@ -1,7 +1,7 @@
 #ifndef _LINUX_SWSUSP_H
 #define _LINUX_SWSUSP_H
 
-#ifdef CONFIG_X86
+#if defined(CONFIG_X86) || defined(CONFIG_FRV)
 #include <asm/suspend.h>
 #endif
 #include <linux/swap.h>

^ permalink raw reply	[flat|nested] 87+ messages in thread

* [PATCH 14/20] FRV: Fujitsu FR-V arch include files
  2004-11-08 14:34 [PATCH 1/20] FRV: Fujitsu FR-V CPU arch maintainer record dhowells
                   ` (11 preceding siblings ...)
  2004-11-08 14:34 ` [PATCH 16/20] FRV: Make calibrate_delay() optional dhowells
@ 2004-11-08 14:34 ` dhowells
  2004-11-08 14:34 ` [PATCH 13/20] " dhowells
                   ` (3 subsequent siblings)
  16 siblings, 0 replies; 87+ messages in thread
From: dhowells @ 2004-11-08 14:34 UTC (permalink / raw)
  To: torvalds, akpm, davidm; +Cc: linux-kernel, uclinux-dev

The attached patch provides the arch-specific include files for the Fujitsu
FR-V CPU arch.

Signed-Off-By: dhowells@redhat.com
---
diffstat frv-include_3-2610rc1mm3.diff
 registers.h   |  255 ++++++++++++++++++++++++++++++++++++
 resource.h    |   53 +++++++
 scatterlist.h |   32 ++++
 sections.h    |   46 ++++++
 segment.h     |   46 ++++++
 semaphore.h   |  161 +++++++++++++++++++++++
 sembuf.h      |   26 +++
 serial-regs.h |   44 ++++++
 serial.h      |   19 ++
 setup.h       |   25 +++
 shmbuf.h      |   43 ++++++
 shmparam.h    |    7 +
 sigcontext.h  |   26 +++
 siginfo.h     |   12 +
 signal.h      |  187 +++++++++++++++++++++++++++
 smp.h         |   10 +
 socket.h      |   51 +++++++
 sockios.h     |   13 +
 spinlock.h    |   17 ++
 spr-regs.h    |  401 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 stat.h        |  100 ++++++++++++++
 statfs.h      |    7 +
 string.h      |   51 +++++++
 suspend.h     |   20 ++
 system.h      |  123 +++++++++++++++++
 termbits.h    |  177 +++++++++++++++++++++++++
 termios.h     |   74 ++++++++++
 thread_info.h |  158 ++++++++++++++++++++++
 timer-regs.h  |  106 +++++++++++++++
 timex.h       |   25 +++
 tlb.h         |   23 +++
 tlbflush.h    |   76 ++++++++++
 topology.h    |   14 ++
 types.h       |   74 ++++++++++
 uaccess.h     |  317 +++++++++++++++++++++++++++++++++++++++++++++
 ucontext.h    |   12 +
 36 files changed, 2831 insertions(+)

diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/include/asm-frv/registers.h linux-2.6.10-rc1-mm3-frv/include/asm-frv/registers.h
--- /warthog/kernels/linux-2.6.10-rc1-mm3/include/asm-frv/registers.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/include/asm-frv/registers.h	2004-11-05 14:13:04.159474152 +0000
@@ -0,0 +1,255 @@
+/* registers.h: register frame declarations
+ *
+ * Copyright (C) 2003 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * 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.
+ */
+
+/*
+ * notes:
+ *
+ * (1) that the members of all these structures are carefully aligned to permit
+ *     usage of STD/STDF instructions
+ *
+ * (2) if you change these structures, you must change the code in
+ *     arch/frvnommu/kernel/{break.S,entry.S,switch_to.S,gdb-stub.c}
+ *
+ *
+ * the kernel stack space block looks like this:
+ *
+ *	+0x2000	+----------------------
+ *		| union {
+ *		|	struct user_context
+ *		|	struct pt_regs [user exception]
+ *		| }
+ *		+---------------------- <-- __kernel_frame0_ptr (maybe GR28)
+ *		|
+ *		| kernel stack
+ *		|
+ *		|......................
+ *		| struct pt_regs [kernel exception]
+ *		|...................... <-- __kernel_frame0_ptr (maybe GR28)
+ *		|
+ *		| kernel stack
+ *		|
+ *		|...................... <-- stack pointer (GR1)
+ *		|
+ *		| unused stack space
+ *		|
+ *		+----------------------
+ *		| struct thread_info
+ *	+0x0000	+---------------------- <-- __current_thread_info (GR15);
+ *	
+ * note that GR28 points to the current exception frame
+ */
+
+#ifndef _ASM_REGISTERS_H
+#define _ASM_REGISTERS_H
+
+#ifndef __ASSEMBLY__
+#define __OFFSET(X)	(X)
+#define __OFFSETC(X,N)	xxxxxxxxxxxxxxxxxxxxxxxx
+#else
+#define __OFFSET(X)	((X)*4)
+#define __OFFSETC(X,N)	((X)*4+(N))
+#endif
+
+/*****************************************************************************/
+/*
+ * Exception/Interrupt frame
+ * - held on kernel stack
+ * - 8-byte aligned on stack (old SP is saved in frame)
+ * - GR0 is fixed 0, so we don't save it
+ */
+#ifndef __ASSEMBLY__
+
+struct pt_regs {
+	unsigned long		psr;		/* Processor Status Register */
+	unsigned long		isr;		/* Integer Status Register */
+	unsigned long		ccr;		/* Condition Code Register */
+	unsigned long		cccr;		/* Condition Code for Conditional Insns Register */
+	unsigned long		lr;		/* Link Register */
+	unsigned long		lcr;		/* Loop Count Register */
+	unsigned long		pc;		/* Program Counter Register */
+	unsigned long		__status;	/* exception status */
+	unsigned long		syscallno;	/* syscall number or -1 */
+	unsigned long		orig_gr8;	/* original syscall arg #1 */
+	unsigned long		gner0;
+	unsigned long		gner1;
+	unsigned long long	iacc0;
+	unsigned long		tbr;		/* GR0 is fixed zero, so we use this for TBR */
+	unsigned long		sp;		/* GR1: USP/KSP */
+	unsigned long		fp;		/* GR2: FP */
+	unsigned long		gr3;
+	unsigned long		gr4;
+	unsigned long		gr5;
+	unsigned long		gr6;
+	unsigned long		gr7;		/* syscall number */
+	unsigned long		gr8;		/* 1st syscall param; syscall return */
+	unsigned long		gr9;		/* 2nd syscall param */
+	unsigned long		gr10;		/* 3rd syscall param */
+	unsigned long		gr11;		/* 4th syscall param */
+	unsigned long		gr12;		/* 5th syscall param */
+	unsigned long		gr13;		/* 6th syscall param */
+	unsigned long		gr14;
+	unsigned long		gr15;
+	unsigned long		gr16;		/* GP pointer */
+	unsigned long		gr17;		/* small data */
+	unsigned long		gr18;		/* PIC/PID */
+	unsigned long		gr19;
+	unsigned long		gr20;
+	unsigned long		gr21;
+	unsigned long		gr22;
+	unsigned long		gr23;
+	unsigned long		gr24;
+	unsigned long		gr25;
+	unsigned long		gr26;
+	unsigned long		gr27;
+	struct pt_regs		*next_frame;	/* GR28 - next exception frame */
+	unsigned long		gr29;		/* GR29 - OS reserved */
+	unsigned long		gr30;		/* GR30 - OS reserved */
+	unsigned long		gr31;		/* GR31 - OS reserved */
+} __attribute__((aligned(8)));
+
+#endif
+
+#define REG_PSR		__OFFSET( 0)	/* Processor Status Register */
+#define REG_ISR		__OFFSET( 1)	/* Integer Status Register */
+#define REG_CCR		__OFFSET( 2)	/* Condition Code Register */
+#define REG_CCCR	__OFFSET( 3)	/* Condition Code for Conditional Insns Register */
+#define REG_LR		__OFFSET( 4)	/* Link Register */
+#define REG_LCR		__OFFSET( 5)	/* Loop Count Register */
+#define REG_PC		__OFFSET( 6)	/* Program Counter */
+
+#define REG__STATUS	__OFFSET( 7)	/* exception status */
+#define REG__STATUS_STEP	0x00000001	/* - reenable single stepping on return */
+#define REG__STATUS_STEPPED	0x00000002	/* - single step caused exception */
+#define REG__STATUS_BROKE	0x00000004	/* - BREAK insn caused exception */
+#define REG__STATUS_SYSC_ENTRY	0x40000000	/* - T on syscall entry (ptrace.c only) */
+#define REG__STATUS_SYSC_EXIT	0x80000000	/* - T on syscall exit (ptrace.c only) */
+
+#define REG_SYSCALLNO	__OFFSET( 8)	/* syscall number or -1 */
+#define REG_ORIG_GR8	__OFFSET( 9)	/* saved GR8 for signal handling */
+#define REG_GNER0	__OFFSET(10)
+#define REG_GNER1	__OFFSET(11)
+#define REG_IACC0	__OFFSET(12)
+
+#define REG_TBR		__OFFSET(14)	/* Trap Vector Register */
+#define REG_GR(R)	__OFFSET((14+(R)))
+#define REG__END	REG_GR(32)
+
+#define REG_SP		REG_GR(1)
+#define REG_FP		REG_GR(2)
+#define REG_PREV_FRAME	REG_GR(28)	/* previous exception frame pointer (old gr28 value) */
+#define REG_CURR_TASK	REG_GR(29)	/* current task */
+
+/*****************************************************************************/
+/*
+ * extension tacked in front of the exception frame in debug mode
+ */
+#ifndef __ASSEMBLY__
+
+struct pt_debug_regs
+{
+	unsigned long		bpsr;
+	unsigned long		dcr;
+	unsigned long		brr;
+	unsigned long		nmar;
+	struct pt_regs		normal_regs;
+} __attribute__((aligned(8)));
+
+#endif
+
+#define REG_NMAR		__OFFSET(-1)
+#define REG_BRR			__OFFSET(-2)
+#define REG_DCR			__OFFSET(-3)
+#define REG_BPSR		__OFFSET(-4)
+#define REG__DEBUG_XTRA		__OFFSET(4)
+
+/*****************************************************************************/
+/*
+ * userspace registers
+ */
+#ifndef __ASSEMBLY__
+
+struct user_int_regs
+{
+	/* integer registers
+	 * - up to gr[31] mirror pt_regs
+	 * - total size must be multiple of 8 bytes
+	 */
+	unsigned long		psr;		/* Processor Status Register */
+	unsigned long		isr;		/* Integer Status Register */
+	unsigned long		ccr;		/* Condition Code Register */
+	unsigned long		cccr;		/* Condition Code for Conditional Insns Register */
+	unsigned long		lr;		/* Link Register */
+	unsigned long		lcr;		/* Loop Count Register */
+	unsigned long		pc;		/* Program Counter Register */
+	unsigned long		__status;	/* exception status */
+	unsigned long		syscallno;	/* syscall number or -1 */
+	unsigned long		orig_gr8;	/* original syscall arg #1 */
+	unsigned long		gner[2];
+	unsigned long long	iacc[1];
+
+	union {
+		unsigned long	tbr;
+		unsigned long	gr[64];
+	};
+};
+
+struct user_fpmedia_regs
+{
+	/* FP/Media registers */
+	unsigned long	fr[64];
+	unsigned long	fner[2];
+	unsigned long	msr[2];
+	unsigned long	acc[8];
+	unsigned char	accg[8];
+	unsigned long	fsr[1];
+};
+
+struct user_context
+{
+	struct user_int_regs		i;
+	struct user_fpmedia_regs	f;
+
+	/* we provide a context extension so that we can save the regs for CPUs that
+	 * implement many more of Fujitsu's lavish register spec
+	 */
+	void *extension;
+} __attribute__((aligned(8)));
+
+#endif
+
+#define NR_USER_INT_REGS	(14 + 64)
+#define NR_USER_FPMEDIA_REGS	(64 + 2 + 2 + 8 + 8/4 + 1)
+#define NR_USER_CONTEXT		(NR_USER_INT_REGS + NR_USER_FPMEDIA_REGS + 1)
+
+#define USER_CONTEXT_SIZE	(((NR_USER_CONTEXT + 1) & ~1) * 4)
+
+#define __THREAD_FRAME		__OFFSET(0)
+#define __THREAD_CURR		__OFFSET(1)
+#define __THREAD_SP		__OFFSET(2)
+#define __THREAD_FP		__OFFSET(3)
+#define __THREAD_LR		__OFFSET(4)
+#define __THREAD_PC		__OFFSET(5)
+#define __THREAD_GR(R)		__OFFSET(6 + (R) - 16)
+#define __THREAD_FRAME0		__OFFSET(19)
+#define __THREAD_USER		__OFFSET(19)
+
+#define __USER_INT		__OFFSET(0)
+#define __INT_GR(R)		__OFFSET(14 + (R))
+
+#define __USER_FPMEDIA		__OFFSET(NR_USER_INT_REGS)
+#define __FPMEDIA_FR(R)		__OFFSET(NR_USER_INT_REGS + (R))
+#define __FPMEDIA_FNER(R)	__OFFSET(NR_USER_INT_REGS + 64 + (R))
+#define __FPMEDIA_MSR(R)	__OFFSET(NR_USER_INT_REGS + 66 + (R))
+#define __FPMEDIA_ACC(R)	__OFFSET(NR_USER_INT_REGS + 68 + (R))
+#define __FPMEDIA_ACCG(R)	__OFFSETC(NR_USER_INT_REGS + 76, (R))
+#define __FPMEDIA_FSR(R)	__OFFSET(NR_USER_INT_REGS + 78 + (R))
+
+#endif /* _ASM_REGISTERS_H */
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/include/asm-frv/resource.h linux-2.6.10-rc1-mm3-frv/include/asm-frv/resource.h
--- /warthog/kernels/linux-2.6.10-rc1-mm3/include/asm-frv/resource.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/include/asm-frv/resource.h	2004-11-05 14:13:04.164473730 +0000
@@ -0,0 +1,53 @@
+#ifndef _ASM_RESOURCE_H
+#define _ASM_RESOURCE_H
+
+/*
+ * Resource limits
+ */
+
+#define RLIMIT_CPU	0		/* CPU time in ms */
+#define RLIMIT_FSIZE	1		/* Maximum filesize */
+#define RLIMIT_DATA	2		/* max data size */
+#define RLIMIT_STACK	3		/* max stack size */
+#define RLIMIT_CORE	4		/* max core file size */
+#define RLIMIT_RSS	5		/* max resident set size */
+#define RLIMIT_NPROC	6		/* max number of processes */
+#define RLIMIT_NOFILE	7		/* max number of open files */
+#define RLIMIT_MEMLOCK	8		/* max locked-in-memory address space */
+#define RLIMIT_AS	9		/* address space limit */
+#define RLIMIT_LOCKS	10		/* maximum file locks held */
+#define RLIMIT_SIGPENDING 11		/* max number of pending signals */
+#define RLIMIT_MSGQUEUE 12		/* maximum bytes in POSIX mqueues */
+
+#define RLIM_NLIMITS	13
+
+
+/*
+ * SuS says limits have to be unsigned.
+ * Which makes a ton more sense anyway.
+ */
+#define RLIM_INFINITY	(~0UL)
+
+#ifdef __KERNEL__
+
+#define INIT_RLIMITS					\
+{							\
+	{ RLIM_INFINITY, RLIM_INFINITY },		\
+	{ RLIM_INFINITY, RLIM_INFINITY },		\
+	{ RLIM_INFINITY, RLIM_INFINITY },		\
+	{      _STK_LIM, RLIM_INFINITY },		\
+	{             0, RLIM_INFINITY },		\
+	{ RLIM_INFINITY, RLIM_INFINITY },		\
+	{             0,             0 },		\
+	{      INR_OPEN,     INR_OPEN  },		\
+	{   MLOCK_LIMIT,   MLOCK_LIMIT },		\
+	{ RLIM_INFINITY, RLIM_INFINITY },		\
+        { RLIM_INFINITY, RLIM_INFINITY },		\
+	{ MAX_SIGPENDING, MAX_SIGPENDING },		\
+	{ MQ_BYTES_MAX, MQ_BYTES_MAX },			\
+}
+
+#endif /* __KERNEL__ */
+
+#endif /* _ASM_RESOURCE_H */
+
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/include/asm-frv/scatterlist.h linux-2.6.10-rc1-mm3-frv/include/asm-frv/scatterlist.h
--- /warthog/kernels/linux-2.6.10-rc1-mm3/include/asm-frv/scatterlist.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/include/asm-frv/scatterlist.h	2004-11-05 14:13:04.168473392 +0000
@@ -0,0 +1,32 @@
+#ifndef _ASM_SCATTERLIST_H
+#define _ASM_SCATTERLIST_H
+
+/*
+ * Drivers must set either ->address or (preferred) ->page and ->offset
+ * to indicate where data must be transferred to/from.
+ *
+ * Using ->page is recommended since it handles highmem data as well as
+ * low mem. ->address is restricted to data which has a virtual mapping, and
+ * it will go away in the future. Updating to ->page can be automated very
+ * easily -- something like
+ *
+ * sg->address = some_ptr;
+ *
+ * can be rewritten as
+ *
+ * sg->page = virt_to_page(some_ptr);
+ * sg->offset = (unsigned long) some_ptr & ~PAGE_MASK;
+ *
+ * and that's it. There's no excuse for not highmem enabling YOUR driver. /jens
+ */
+struct scatterlist {
+	struct page	*page;		/* Location for highmem page, if any */
+	unsigned int	offset;		/* for highmem, page offset */
+
+	dma_addr_t	dma_address;
+	unsigned int	length;
+};
+
+#define ISA_DMA_THRESHOLD (0xffffffffUL)
+
+#endif /* !_ASM_SCATTERLIST_H */
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/include/asm-frv/sections.h linux-2.6.10-rc1-mm3-frv/include/asm-frv/sections.h
--- /warthog/kernels/linux-2.6.10-rc1-mm3/include/asm-frv/sections.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/include/asm-frv/sections.h	2004-11-05 14:13:04.172473054 +0000
@@ -0,0 +1,46 @@
+/* sections.h: linkage layout variables
+ *
+ * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * 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.
+ */
+
+#ifndef _ASM_SECTIONS_H
+#define _ASM_SECTIONS_H
+
+#ifndef __ASSEMBLY__
+
+#include <linux/types.h>
+#include <asm-generic/sections.h>
+
+#ifdef __KERNEL__
+
+/*
+ * we don't want to put variables in the GP-REL section if they're not used very much - that would
+ * be waste since GP-REL addressing is limited to GP16+/-2048
+ */
+#define __nongpreldata	__attribute__((section(".data")))
+#define __nongprelbss	__attribute__((section(".bss")))
+
+/*
+ * linker symbols
+ */
+extern const void __kernel_image_start, __kernel_image_end, __page_offset;
+
+extern unsigned long __nongprelbss memory_start;
+extern unsigned long __nongprelbss memory_end;
+extern unsigned long __nongprelbss rom_length;
+
+/* determine if we're running from ROM */
+static inline int is_in_rom(unsigned long addr)
+{
+	return 0; /* default case: not in ROM */
+}
+
+#endif
+#endif
+#endif /* _ASM_SECTIONS_H */
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/include/asm-frv/segment.h linux-2.6.10-rc1-mm3-frv/include/asm-frv/segment.h
--- /warthog/kernels/linux-2.6.10-rc1-mm3/include/asm-frv/segment.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/include/asm-frv/segment.h	2004-11-05 14:13:04.176472716 +0000
@@ -0,0 +1,46 @@
+/* segment.h: MMU segment settings
+ *
+ * Copyright (C) 2003 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * 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.
+ */
+
+#ifndef _ASM_SEGMENT_H
+#define _ASM_SEGMENT_H
+
+#include <linux/config.h>
+
+#ifndef __ASSEMBLY__
+
+typedef struct {
+	unsigned long seg;
+} mm_segment_t;
+
+#define MAKE_MM_SEG(s)	((mm_segment_t) { (s) })
+
+#define KERNEL_DS		MAKE_MM_SEG(0xdfffffffUL)
+
+#ifdef CONFIG_MMU
+#define USER_DS			MAKE_MM_SEG(TASK_SIZE - 1)
+#else
+#define USER_DS			KERNEL_DS
+#endif
+
+#define get_ds()		(KERNEL_DS)
+#define get_fs()		(__current_thread_info->addr_limit)
+#define segment_eq(a,b)		((a).seg == (b).seg)
+#define __kernel_ds_p()		segment_eq(get_fs(), KERNEL_DS)
+#define get_addr_limit()	(get_fs().seg)
+
+#define set_fs(_x)					\
+do {							\
+	__current_thread_info->addr_limit = (_x);	\
+} while(0)
+
+
+#endif /* __ASSEMBLY__ */
+#endif /* _ASM_SEGMENT_H */
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/include/asm-frv/semaphore.h linux-2.6.10-rc1-mm3-frv/include/asm-frv/semaphore.h
--- /warthog/kernels/linux-2.6.10-rc1-mm3/include/asm-frv/semaphore.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/include/asm-frv/semaphore.h	2004-11-05 14:13:04.179472463 +0000
@@ -0,0 +1,161 @@
+/* semaphore.h: semaphores for the FR-V
+ *
+ * Copyright (C) 2003 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * 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.
+ */
+#ifndef _ASM_SEMAPHORE_H
+#define _ASM_SEMAPHORE_H
+
+#define RW_LOCK_BIAS		 0x01000000
+
+#ifndef __ASSEMBLY__
+
+#include <linux/linkage.h>
+#include <linux/wait.h>
+#include <linux/spinlock.h>
+#include <linux/rwsem.h>
+
+#define SEMAPHORE_DEBUG		WAITQUEUE_DEBUG
+
+/*
+ * the semaphore definition
+ * - if counter is >0 then there are tokens available on the semaphore for down to collect
+ * - if counter is <=0 then there are no spare tokens, and anyone that wants one must wait
+ * - if wait_list is not empty, then there are processes waiting for the semaphore
+ */
+struct semaphore {
+	unsigned		counter;
+	spinlock_t		wait_lock;
+	struct list_head	wait_list;
+#if SEMAPHORE_DEBUG
+	unsigned		__magic;
+#endif
+};
+
+#if SEMAPHORE_DEBUG
+# define __SEM_DEBUG_INIT(name) , (long)&(name).__magic
+#else
+# define __SEM_DEBUG_INIT(name)
+#endif
+
+
+#define __SEMAPHORE_INITIALIZER(name,count) \
+{ count, SPIN_LOCK_UNLOCKED, LIST_HEAD_INIT((name).wait_list) __SEM_DEBUG_INIT(name) }
+
+#define __MUTEX_INITIALIZER(name) \
+	__SEMAPHORE_INITIALIZER(name,1)
+
+#define __DECLARE_SEMAPHORE_GENERIC(name,count) \
+	struct semaphore name = __SEMAPHORE_INITIALIZER(name,count)
+
+#define DECLARE_MUTEX(name) __DECLARE_SEMAPHORE_GENERIC(name,1)
+#define DECLARE_MUTEX_LOCKED(name) __DECLARE_SEMAPHORE_GENERIC(name,0)
+
+static inline void sema_init (struct semaphore *sem, int val)
+{
+	*sem = (struct semaphore) __SEMAPHORE_INITIALIZER(*sem, val);
+}
+
+static inline void init_MUTEX (struct semaphore *sem)
+{
+	sema_init(sem, 1);
+}
+
+static inline void init_MUTEX_LOCKED (struct semaphore *sem)
+{
+	sema_init(sem, 0);
+}
+
+extern void __down(struct semaphore *sem, unsigned long flags);
+extern int  __down_interruptible(struct semaphore *sem, unsigned long flags);
+extern void __up(struct semaphore *sem);
+
+static inline void down(struct semaphore *sem)
+{
+	unsigned long flags;
+
+#if SEMAPHORE_DEBUG
+	CHECK_MAGIC(sem->__magic);
+#endif
+
+	spin_lock_irqsave(&sem->wait_lock, flags);
+	if (likely(sem->counter > 0)) {
+		sem->counter--;
+		spin_unlock_irqrestore(&sem->wait_lock, flags);
+	}
+	else {
+		__down(sem, flags);
+	}
+}
+
+static inline int down_interruptible(struct semaphore *sem)
+{
+	unsigned long flags;
+	int ret = 0;
+
+#if SEMAPHORE_DEBUG
+	CHECK_MAGIC(sem->__magic);
+#endif
+
+	spin_lock_irqsave(&sem->wait_lock, flags);
+	if (likely(sem->counter > 0)) {
+		sem->counter--;
+		spin_unlock_irqrestore(&sem->wait_lock, flags);
+	}
+	else {
+		ret = __down_interruptible(sem, flags);
+	}
+	return ret;
+}
+
+/*
+ * non-blockingly attempt to down() a semaphore.
+ * - returns zero if we acquired it
+ */
+static inline int down_trylock(struct semaphore *sem)
+{
+	unsigned long flags;
+	int success = 0;
+
+#if SEMAPHORE_DEBUG
+	CHECK_MAGIC(sem->__magic);
+#endif
+
+	spin_lock_irqsave(&sem->wait_lock, flags);
+	if (sem->counter > 0) {
+		sem->counter--;
+		success = 1;
+	}
+	spin_unlock_irqrestore(&sem->wait_lock, flags);
+	return !success;
+}
+
+static inline void up(struct semaphore *sem)
+{
+	unsigned long flags;
+
+#if SEMAPHORE_DEBUG
+	CHECK_MAGIC(sem->__magic);
+#endif
+
+	spin_lock_irqsave(&sem->wait_lock, flags);
+	if (!list_empty(&sem->wait_list))
+		__up(sem);
+	else
+		sem->counter++;
+	spin_unlock_irqrestore(&sem->wait_lock, flags);
+}
+
+static inline int sem_getcount(struct semaphore *sem)
+{
+	return sem->counter;
+}
+
+#endif /* __ASSEMBLY__ */
+
+#endif
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/include/asm-frv/sembuf.h linux-2.6.10-rc1-mm3-frv/include/asm-frv/sembuf.h
--- /warthog/kernels/linux-2.6.10-rc1-mm3/include/asm-frv/sembuf.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/include/asm-frv/sembuf.h	2004-11-05 14:13:04.184472041 +0000
@@ -0,0 +1,26 @@
+#ifndef _ASM_SEMBUF_H
+#define _ASM_SEMBUF_H
+
+/* 
+ * The semid64_ds structure for FR-V architecture.
+ * Note extra padding because this structure is passed back and forth
+ * between kernel and user space.
+ *
+ * Pad space is left for:
+ * - 64-bit time_t to solve y2038 problem
+ * - 2 miscellaneous 32-bit values
+ */
+
+struct semid64_ds {
+	struct ipc64_perm	sem_perm;	/* permissions .. see ipc.h */
+	__kernel_time_t		sem_otime;	/* last semop time */
+	unsigned long		__unused1;
+	__kernel_time_t		sem_ctime;	/* last change time */
+	unsigned long		__unused2;
+	unsigned long		sem_nsems;	/* no. of semaphores in array */
+	unsigned long		__unused3;
+	unsigned long		__unused4;
+};
+
+#endif /* _ASM_SEMBUF_H */
+
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/include/asm-frv/serial.h linux-2.6.10-rc1-mm3-frv/include/asm-frv/serial.h
--- /warthog/kernels/linux-2.6.10-rc1-mm3/include/asm-frv/serial.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/include/asm-frv/serial.h	2004-11-05 14:13:04.187471787 +0000
@@ -0,0 +1,19 @@
+/*
+ * serial.h
+ *
+ * Copyright (C) 2003 Develer S.r.l. (http://www.develer.com/)
+ * Author: Bernardo Innocenti <bernie@codewiz.org>
+ *
+ * Based on linux/include/asm-i386/serial.h
+ */
+#include <linux/config.h>
+#include <asm/serial-regs.h>
+
+/*
+ * the base baud is derived from the clock speed and so is variable
+ */
+#define BASE_BAUD 0
+
+#define STD_COM_FLAGS		ASYNC_BOOT_AUTOCONF
+
+#define SERIAL_PORT_DFNS
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/include/asm-frv/serial-regs.h linux-2.6.10-rc1-mm3-frv/include/asm-frv/serial-regs.h
--- /warthog/kernels/linux-2.6.10-rc1-mm3/include/asm-frv/serial-regs.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/include/asm-frv/serial-regs.h	2004-11-05 14:13:04.191471450 +0000
@@ -0,0 +1,44 @@
+/* serial-regs.h: serial port registers
+ *
+ * Copyright (C) 2003 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * 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.
+ */
+
+#ifndef _ASM_SERIAL_REGS_H
+#define _ASM_SERIAL_REGS_H
+
+#include <linux/serial_reg.h>
+#include <asm/irc-regs.h>
+
+#define SERIAL_ICLK	33333333	/* the target serial input clock */
+#define UART0_BASE	0xfeff9c00
+#define UART1_BASE	0xfeff9c40
+
+#define __get_UART0(R) ({ __reg(UART0_BASE + (R) * 8) >> 24; })
+#define __get_UART1(R) ({ __reg(UART1_BASE + (R) * 8) >> 24; })
+#define __set_UART0(R,V) do { __reg(UART0_BASE + (R) * 8) = (V) << 24; } while(0)
+#define __set_UART1(R,V) do { __reg(UART1_BASE + (R) * 8) = (V) << 24; } while(0)
+
+#define __get_UART0_LSR() ({ __get_UART0(UART_LSR); })
+#define __get_UART1_LSR() ({ __get_UART1(UART_LSR); })
+
+#define __set_UART0_IER(V) __set_UART0(UART_IER,(V))
+#define __set_UART1_IER(V) __set_UART1(UART_IER,(V))
+
+/* serial prescaler select register */
+#define __get_UCPSR()	({ *(volatile unsigned long *)(0xfeff9c90); })
+#define __set_UCPSR(V)	do { *(volatile unsigned long *)(0xfeff9c90) = (V); } while(0)
+#define UCPSR_SELECT0	0x07000000
+#define UCPSR_SELECT1	0x38000000
+
+/* serial prescaler base value register */
+#define __get_UCPVR()	({ *(volatile unsigned long *)(0xfeff9c98); mb(); })
+#define __set_UCPVR(V)	do { *(volatile unsigned long *)(0xfeff9c98) = (V) << 24; mb(); } while(0)
+
+
+#endif /* _ASM_SERIAL_REGS_H */
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/include/asm-frv/setup.h linux-2.6.10-rc1-mm3-frv/include/asm-frv/setup.h
--- /warthog/kernels/linux-2.6.10-rc1-mm3/include/asm-frv/setup.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/include/asm-frv/setup.h	2004-11-05 14:13:04.195471112 +0000
@@ -0,0 +1,25 @@
+/* setup.h: setup stuff
+ *
+ * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * 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.
+ */
+
+#ifndef _ASM_SETUP_H
+#define _ASM_SETUP_H
+
+#include <linux/init.h>
+
+#ifndef __ASSEMBLY__
+
+#ifdef CONFIG_MMU
+extern unsigned long __initdata num_mappedpages;
+#endif
+
+#endif /* !__ASSEMBLY__ */
+
+#endif /* _ASM_SETUP_H */
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/include/asm-frv/shmbuf.h linux-2.6.10-rc1-mm3-frv/include/asm-frv/shmbuf.h
--- /warthog/kernels/linux-2.6.10-rc1-mm3/include/asm-frv/shmbuf.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/include/asm-frv/shmbuf.h	2004-11-05 14:13:04.199470774 +0000
@@ -0,0 +1,43 @@
+#ifndef _ASM_SHMBUF_H
+#define _ASM_SHMBUF_H
+
+/* 
+ * The shmid64_ds structure for FR-V architecture.
+ * Note extra padding because this structure is passed back and forth
+ * between kernel and user space.
+ *
+ * Pad space is left for:
+ * - 64-bit time_t to solve y2038 problem
+ * - 2 miscellaneous 32-bit values
+ */
+
+struct shmid64_ds {
+	struct ipc64_perm	shm_perm;	/* operation perms */
+	size_t			shm_segsz;	/* size of segment (bytes) */
+	__kernel_time_t		shm_atime;	/* last attach time */
+	unsigned long		__unused1;
+	__kernel_time_t		shm_dtime;	/* last detach time */
+	unsigned long		__unused2;
+	__kernel_time_t		shm_ctime;	/* last change time */
+	unsigned long		__unused3;
+	__kernel_pid_t		shm_cpid;	/* pid of creator */
+	__kernel_pid_t		shm_lpid;	/* pid of last operator */
+	unsigned long		shm_nattch;	/* no. of current attaches */
+	unsigned long		__unused4;
+	unsigned long		__unused5;
+};
+
+struct shminfo64 {
+	unsigned long	shmmax;
+	unsigned long	shmmin;
+	unsigned long	shmmni;
+	unsigned long	shmseg;
+	unsigned long	shmall;
+	unsigned long	__unused1;
+	unsigned long	__unused2;
+	unsigned long	__unused3;
+	unsigned long	__unused4;
+};
+
+#endif /* _ASM_SHMBUF_H */
+
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/include/asm-frv/shmparam.h linux-2.6.10-rc1-mm3-frv/include/asm-frv/shmparam.h
--- /warthog/kernels/linux-2.6.10-rc1-mm3/include/asm-frv/shmparam.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/include/asm-frv/shmparam.h	2004-11-05 14:13:04.203470436 +0000
@@ -0,0 +1,7 @@
+#ifndef _ASM_SHMPARAM_H
+#define _ASM_SHMPARAM_H
+
+#define	SHMLBA PAGE_SIZE		 /* attach addr a multiple of this */
+
+#endif /* _ASM_SHMPARAM_H */
+
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/include/asm-frv/sigcontext.h linux-2.6.10-rc1-mm3-frv/include/asm-frv/sigcontext.h
--- /warthog/kernels/linux-2.6.10-rc1-mm3/include/asm-frv/sigcontext.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/include/asm-frv/sigcontext.h	2004-11-05 14:13:04.207470098 +0000
@@ -0,0 +1,26 @@
+/* sigcontext.h: FRV signal context
+ *
+ * Copyright (C) 2003 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * 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.
+ */
+#ifndef _ASM_SIGCONTEXT_H
+#define _ASM_SIGCONTEXT_H
+
+#include <asm/registers.h>
+
+/*
+ * Signal context structure - contains all info to do with the state
+ * before the signal handler was invoked.  Note: only add new entries
+ * to the end of the structure.
+ */
+struct sigcontext {
+	struct user_context	sc_context;
+	unsigned long		sc_oldmask; 	/* old sigmask */
+} __attribute__((aligned(8)));
+
+#endif
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/include/asm-frv/siginfo.h linux-2.6.10-rc1-mm3-frv/include/asm-frv/siginfo.h
--- /warthog/kernels/linux-2.6.10-rc1-mm3/include/asm-frv/siginfo.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/include/asm-frv/siginfo.h	2004-11-05 14:13:04.214469507 +0000
@@ -0,0 +1,12 @@
+#ifndef _ASM_SIGINFO_H
+#define _ASM_SIGINFO_H
+
+#include <linux/types.h>
+#include <asm-generic/siginfo.h>
+
+#define FPE_MDAOVF	(__SI_FAULT|9)	/* media overflow */
+#undef NSIGFPE
+#define NSIGFPE		9
+
+#endif
+
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/include/asm-frv/signal.h linux-2.6.10-rc1-mm3-frv/include/asm-frv/signal.h
--- /warthog/kernels/linux-2.6.10-rc1-mm3/include/asm-frv/signal.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/include/asm-frv/signal.h	2004-11-05 14:13:04.218469169 +0000
@@ -0,0 +1,187 @@
+#ifndef _ASM_SIGNAL_H
+#define _ASM_SIGNAL_H
+
+#include <linux/types.h>
+
+/* Avoid too many header ordering problems.  */
+struct siginfo;
+
+#ifdef __KERNEL__
+/* Most things should be clean enough to redefine this at will, if care
+   is taken to make libc match.  */
+
+#define _NSIG		64
+#define _NSIG_BPW	32
+#define _NSIG_WORDS	(_NSIG / _NSIG_BPW)
+
+typedef unsigned long old_sigset_t;		/* at least 32 bits */
+
+typedef struct {
+	unsigned long sig[_NSIG_WORDS];
+} sigset_t;
+
+#else
+/* Here we must cater to libcs that poke about in kernel headers.  */
+
+#define NSIG		32
+typedef unsigned long sigset_t;
+
+#endif /* __KERNEL__ */
+
+#define SIGHUP		 1
+#define SIGINT		 2
+#define SIGQUIT		 3
+#define SIGILL		 4
+#define SIGTRAP		 5
+#define SIGABRT		 6
+#define SIGIOT		 6
+#define SIGBUS		 7
+#define SIGFPE		 8
+#define SIGKILL		 9
+#define SIGUSR1		10
+#define SIGSEGV		11
+#define SIGUSR2		12
+#define SIGPIPE		13
+#define SIGALRM		14
+#define SIGTERM		15
+#define SIGSTKFLT	16
+#define SIGCHLD		17
+#define SIGCONT		18
+#define SIGSTOP		19
+#define SIGTSTP		20
+#define SIGTTIN		21
+#define SIGTTOU		22
+#define SIGURG		23
+#define SIGXCPU		24
+#define SIGXFSZ		25
+#define SIGVTALRM	26
+#define SIGPROF		27
+#define SIGWINCH	28
+#define SIGIO		29
+#define SIGPOLL		SIGIO
+/*
+#define SIGLOST		29
+*/
+#define SIGPWR		30
+#define SIGSYS		31
+#define	SIGUNUSED	31
+
+/* These should not be considered constants from userland.  */
+#define SIGRTMIN	32
+#define SIGRTMAX	(_NSIG-1)
+
+/*
+ * SA_FLAGS values:
+ *
+ * SA_ONSTACK indicates that a registered stack_t will be used.
+ * SA_INTERRUPT is a no-op, but left due to historical reasons. Use the
+ * SA_RESTART flag to get restarting signals (which were the default long ago)
+ * SA_NOCLDSTOP flag to turn off SIGCHLD when children stop.
+ * SA_RESETHAND clears the handler when the signal is delivered.
+ * SA_NOCLDWAIT flag on SIGCHLD to inhibit zombies.
+ * SA_NODEFER prevents the current signal from being masked in the handler.
+ *
+ * SA_ONESHOT and SA_NOMASK are the historical Linux names for the Single
+ * Unix names RESETHAND and NODEFER respectively.
+ */
+#define SA_NOCLDSTOP	0x00000001
+#define SA_NOCLDWAIT	0x00000002 /* not supported yet */
+#define SA_SIGINFO	0x00000004
+#define SA_ONSTACK	0x08000000
+#define SA_RESTART	0x10000000
+#define SA_NODEFER	0x40000000
+#define SA_RESETHAND	0x80000000
+
+#define SA_NOMASK	SA_NODEFER
+#define SA_ONESHOT	SA_RESETHAND
+#define SA_INTERRUPT	0x20000000 /* dummy -- ignored */
+
+#define SA_RESTORER	0x04000000
+
+/* 
+ * sigaltstack controls
+ */
+#define SS_ONSTACK	1
+#define SS_DISABLE	2
+
+#define MINSIGSTKSZ	2048
+#define SIGSTKSZ	8192
+
+#ifdef __KERNEL__
+
+/*
+ * These values of sa_flags are used only by the kernel as part of the
+ * irq handling routines.
+ *
+ * SA_INTERRUPT is also used by the irq handling routines.
+ * SA_SHIRQ is for shared interrupt support on PCI and EISA.
+ */
+#define SA_PROBE		SA_ONESHOT
+#define SA_SAMPLE_RANDOM	SA_RESTART
+#define SA_SHIRQ		0x04000000
+#endif
+
+#define SIG_BLOCK          0	/* for blocking signals */
+#define SIG_UNBLOCK        1	/* for unblocking signals */
+#define SIG_SETMASK        2	/* for setting the signal mask */
+
+/* Type of a signal handler.  */
+typedef void (*__sighandler_t)(int);
+
+#define SIG_DFL	((__sighandler_t)0)	/* default signal handling */
+#define SIG_IGN	((__sighandler_t)1)	/* ignore signal */
+#define SIG_ERR	((__sighandler_t)-1)	/* error return from signal */
+
+#ifdef __KERNEL__
+struct old_sigaction {
+	__sighandler_t sa_handler;
+	old_sigset_t sa_mask;
+	unsigned long sa_flags;
+	void (*sa_restorer)(void);
+};
+
+struct sigaction {
+	__sighandler_t sa_handler;
+	unsigned long sa_flags;
+	void (*sa_restorer)(void);
+	sigset_t sa_mask;		/* mask last for extensibility */
+};
+
+struct k_sigaction {
+	struct sigaction sa;
+};
+#else
+/* Here we must cater to libcs that poke about in kernel headers.  */
+
+struct sigaction {
+	union {
+	  __sighandler_t _sa_handler;
+	  void (*_sa_sigaction)(int, struct siginfo *, void *);
+	} _u;
+	sigset_t sa_mask;
+	unsigned long sa_flags;
+	void (*sa_restorer)(void);
+};
+
+#define sa_handler	_u._sa_handler
+#define sa_sigaction	_u._sa_sigaction
+
+#endif /* __KERNEL__ */
+
+typedef struct sigaltstack {
+	void *ss_sp;
+	int ss_flags;
+	size_t ss_size;
+} stack_t;
+
+extern int do_signal(struct pt_regs *regs, sigset_t *oldset);
+#define ptrace_signal_deliver(regs, cookie) do { } while (0)
+
+#ifdef __KERNEL__
+
+#include <asm/sigcontext.h>
+#undef __HAVE_ARCH_SIG_BITOPS
+
+#endif /* __KERNEL__ */
+
+#endif /* _ASM_SIGNAL_H */
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/include/asm-frv/smp.h linux-2.6.10-rc1-mm3-frv/include/asm-frv/smp.h
--- /warthog/kernels/linux-2.6.10-rc1-mm3/include/asm-frv/smp.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/include/asm-frv/smp.h	2004-11-05 14:13:04.222468831 +0000
@@ -0,0 +1,10 @@
+#ifndef __ASM_SMP_H
+#define __ASM_SMP_H
+
+#include <linux/config.h>
+
+#ifdef CONFIG_SMP
+#error SMP not supported
+#endif
+
+#endif
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/include/asm-frv/socket.h linux-2.6.10-rc1-mm3-frv/include/asm-frv/socket.h
--- /warthog/kernels/linux-2.6.10-rc1-mm3/include/asm-frv/socket.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/include/asm-frv/socket.h	2004-11-05 14:13:04.226468494 +0000
@@ -0,0 +1,51 @@
+#ifndef _ASM_SOCKET_H
+#define _ASM_SOCKET_H
+
+#include <asm/sockios.h>
+
+/* For setsockopt(2) */
+#define SOL_SOCKET	1
+
+#define SO_DEBUG	1
+#define SO_REUSEADDR	2
+#define SO_TYPE		3
+#define SO_ERROR	4
+#define SO_DONTROUTE	5
+#define SO_BROADCAST	6
+#define SO_SNDBUF	7
+#define SO_RCVBUF	8
+#define SO_KEEPALIVE	9
+#define SO_OOBINLINE	10
+#define SO_NO_CHECK	11
+#define SO_PRIORITY	12
+#define SO_LINGER	13
+#define SO_BSDCOMPAT	14
+/* To add :#define SO_REUSEPORT 15 */
+#define SO_PASSCRED	16
+#define SO_PEERCRED	17
+#define SO_RCVLOWAT	18
+#define SO_SNDLOWAT	19
+#define SO_RCVTIMEO	20
+#define SO_SNDTIMEO	21
+
+/* Security levels - as per NRL IPv6 - don't actually do anything */
+#define SO_SECURITY_AUTHENTICATION		22
+#define SO_SECURITY_ENCRYPTION_TRANSPORT	23
+#define SO_SECURITY_ENCRYPTION_NETWORK		24
+
+#define SO_BINDTODEVICE	25
+
+/* Socket filtering */
+#define SO_ATTACH_FILTER        26
+#define SO_DETACH_FILTER        27
+
+#define SO_PEERNAME             28
+#define SO_TIMESTAMP		29
+#define SCM_TIMESTAMP		SO_TIMESTAMP
+
+#define SO_ACCEPTCONN		30
+
+#define SO_PEERSEC		31
+
+#endif /* _ASM_SOCKET_H */
+
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/include/asm-frv/sockios.h linux-2.6.10-rc1-mm3-frv/include/asm-frv/sockios.h
--- /warthog/kernels/linux-2.6.10-rc1-mm3/include/asm-frv/sockios.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/include/asm-frv/sockios.h	2004-11-05 14:13:04.230468156 +0000
@@ -0,0 +1,13 @@
+#ifndef _ASM_SOCKIOS__
+#define _ASM_SOCKIOS__
+
+/* Socket-level I/O control calls. */
+#define FIOSETOWN 	0x8901
+#define SIOCSPGRP	0x8902
+#define FIOGETOWN	0x8903
+#define SIOCGPGRP	0x8904
+#define SIOCATMARK	0x8905
+#define SIOCGSTAMP	0x8906		/* Get stamp */
+
+#endif /* _ASM_SOCKIOS__ */
+
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/include/asm-frv/spinlock.h linux-2.6.10-rc1-mm3-frv/include/asm-frv/spinlock.h
--- /warthog/kernels/linux-2.6.10-rc1-mm3/include/asm-frv/spinlock.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/include/asm-frv/spinlock.h	2004-11-05 14:13:04.000000000 +0000
@@ -0,0 +1,17 @@
+/* spinlock.h: spinlocks for FR-V
+ *
+ * Copyright (C) 2003 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * 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.
+ */
+
+#ifndef _ASM_SPINLOCK_H
+#define _ASM_SPINLOCK_H
+
+#error no spinlocks for FR-V yet
+
+#endif /* _ASM_SPINLOCK_H */
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/include/asm-frv/spr-regs.h linux-2.6.10-rc1-mm3-frv/include/asm-frv/spr-regs.h
--- /warthog/kernels/linux-2.6.10-rc1-mm3/include/asm-frv/spr-regs.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/include/asm-frv/spr-regs.h	2004-11-05 14:13:04.238467480 +0000
@@ -0,0 +1,401 @@
+/* spr-regs.h: special-purpose registers on the FRV
+ *
+ * Copyright (C) 2003, 2004 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * 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.
+ */
+
+#ifndef _ASM_SPR_REGS_H
+#define _ASM_SPR_REGS_H
+
+/*
+ * PSR - Processor Status Register
+ */
+#define PSR_ET			0x00000001	/* enable interrupts/exceptions flag */
+#define PSR_PS			0x00000002	/* previous supervisor mode flag */
+#define PSR_S			0x00000004	/* supervisor mode flag */
+#define PSR_PIL			0x00000078	/* processor external interrupt level */
+#define PSR_PIL_0		0x00000000	/* - no interrupt in progress */
+#define PSR_PIL_13		0x00000068	/* - debugging only */
+#define PSR_PIL_14		0x00000070	/* - debugging in progress */
+#define PSR_PIL_15		0x00000078	/* - NMI in progress */
+#define PSR_EM			0x00000080	/* enable media operation */
+#define PSR_EF			0x00000100	/* enable FPU operation */
+#define PSR_BE			0x00001000	/* endianness mode */
+#define PSR_BE_LE		0x00000000	/* - little endian mode */
+#define PSR_BE_BE		0x00001000	/* - big endian mode */
+#define PSR_CM			0x00002000	/* conditional mode */
+#define PSR_NEM			0x00004000	/* non-excepting mode */
+#define PSR_ICE			0x00010000	/* in-circuit emulation mode */
+#define PSR_VERSION_SHIFT	24		/* CPU silicon ID */
+#define PSR_IMPLE_SHIFT		28		/* CPU core ID */
+
+#define PSR_VERSION(psr)	(((psr) >> PSR_VERSION_SHIFT) & 0xf)
+#define PSR_IMPLE(psr)		(((psr) >> PSR_IMPLE_SHIFT) & 0xf)
+
+#define PSR_IMPLE_FR401		0x2
+#define PSR_VERSION_FR401_MB93401	0x0
+#define PSR_VERSION_FR401_MB93401A	0x1
+#define PSR_VERSION_FR401_MB93403	0x2
+
+#define PSR_IMPLE_FR405		0x4
+#define PSR_VERSION_FR405_MB93405	0x0
+
+#define PSR_IMPLE_FR451		0x5
+#define PSR_VERSION_FR451_MB93451	0x0
+
+#define PSR_IMPLE_FR501		0x1
+#define PSR_VERSION_FR501_MB93501	0x1
+#define PSR_VERSION_FR501_MB93501A	0x2
+
+#define PSR_IMPLE_FR551		0x3
+#define PSR_VERSION_FR551_MB93555	0x1
+
+#define __get_PSR()	({ unsigned long x; asm volatile("movsg psr,%0" : "=r"(x)); x; })
+#define __set_PSR(V)	do { asm volatile("movgs %0,psr" : : "r"(V)); } while(0)
+
+/*
+ * TBR - Trap Base Register
+ */
+#define TBR_TT			0x00000ff0
+#define TBR_TT_INSTR_MMU_MISS	(0x01 << 4)
+#define TBR_TT_INSTR_ACC_ERROR	(0x02 << 4)
+#define TBR_TT_INSTR_ACC_EXCEP	(0x03 << 4)
+#define TBR_TT_PRIV_INSTR	(0x06 << 4)
+#define TBR_TT_ILLEGAL_INSTR	(0x07 << 4)
+#define TBR_TT_FP_EXCEPTION	(0x0d << 4)
+#define TBR_TT_MP_EXCEPTION	(0x0e << 4)
+#define TBR_TT_DATA_ACC_ERROR	(0x11 << 4)
+#define TBR_TT_DATA_MMU_MISS	(0x12 << 4)
+#define TBR_TT_DATA_ACC_EXCEP	(0x13 << 4)
+#define TBR_TT_DATA_STR_ERROR	(0x14 << 4)
+#define TBR_TT_DIVISION_EXCEP	(0x17 << 4)
+#define TBR_TT_COMMIT_EXCEP	(0x19 << 4)
+#define TBR_TT_INSTR_TLB_MISS	(0x1a << 4)
+#define TBR_TT_DATA_TLB_MISS	(0x1b << 4)
+#define TBR_TT_DATA_DAT_EXCEP	(0x1d << 4)
+#define TBR_TT_DECREMENT_TIMER	(0x1f << 4)
+#define TBR_TT_COMPOUND_EXCEP	(0x20 << 4)
+#define TBR_TT_INTERRUPT_1	(0x21 << 4)
+#define TBR_TT_INTERRUPT_2	(0x22 << 4)
+#define TBR_TT_INTERRUPT_3	(0x23 << 4)
+#define TBR_TT_INTERRUPT_4	(0x24 << 4)
+#define TBR_TT_INTERRUPT_5	(0x25 << 4)
+#define TBR_TT_INTERRUPT_6	(0x26 << 4)
+#define TBR_TT_INTERRUPT_7	(0x27 << 4)
+#define TBR_TT_INTERRUPT_8	(0x28 << 4)
+#define TBR_TT_INTERRUPT_9	(0x29 << 4)
+#define TBR_TT_INTERRUPT_10	(0x2a << 4)
+#define TBR_TT_INTERRUPT_11	(0x2b << 4)
+#define TBR_TT_INTERRUPT_12	(0x2c << 4)
+#define TBR_TT_INTERRUPT_13	(0x2d << 4)
+#define TBR_TT_INTERRUPT_14	(0x2e << 4)
+#define TBR_TT_INTERRUPT_15	(0x2f << 4)
+#define TBR_TT_TRAP0		(0x80 << 4)
+#define TBR_TT_TRAP1		(0x81 << 4)
+#define TBR_TT_TRAP2		(0x82 << 4)
+#define TBR_TT_TRAP126		(0xfe << 4)
+#define TBR_TT_BREAK		(0xff << 4)
+
+#define __get_TBR()	({ unsigned long x; asm volatile("movsg tbr,%0" : "=r"(x)); x; })
+
+/*
+ * HSR0 - Hardware Status Register 0
+ */
+#define HSR0_PDM		0x00000007	/* power down mode */
+#define HSR0_PDM_NORMAL		0x00000000	/* - normal mode */
+#define HSR0_PDM_CORE_SLEEP	0x00000001	/* - CPU core sleep mode */
+#define HSR0_PDM_BUS_SLEEP	0x00000003	/* - bus sleep mode */
+#define HSR0_PDM_PLL_RUN	0x00000005	/* - PLL run */
+#define HSR0_PDM_PLL_STOP	0x00000007	/* - PLL stop */
+#define HSR0_GRLE		0x00000040	/* GR lower register set enable */
+#define HSR0_GRHE		0x00000080	/* GR higher register set enable */
+#define HSR0_FRLE		0x00000100	/* FR lower register set enable */
+#define HSR0_FRHE		0x00000200	/* FR higher register set enable */
+#define HSR0_GRN		0x00000400	/* GR quantity */
+#define HSR0_GRN_64		0x00000000	/* - 64 GR registers */
+#define HSR0_GRN_32		0x00000400	/* - 32 GR registers */
+#define HSR0_FRN		0x00000800	/* FR quantity */
+#define HSR0_FRN_64		0x00000000	/* - 64 FR registers */
+#define HSR0_FRN_32		0x00000800	/* - 32 FR registers */
+#define HSR0_SA			0x00001000	/* start address (RAMBOOT#) */
+#define HSR0_ETMI		0x00008000	/* enable TIMERI (64-bit up timer) */
+#define HSR0_ETMD		0x00004000	/* enable TIMERD (32-bit down timer) */
+#define HSR0_PEDAT		0x00010000	/* previous DAT mode */
+#define HSR0_XEDAT		0x00020000	/* exception DAT mode */
+#define HSR0_EDAT		0x00080000	/* enable DAT mode */
+#define HSR0_RME		0x00400000	/* enable RAM mode */
+#define HSR0_EMEM		0x00800000	/* enable MMU_Miss mask */
+#define HSR0_EXMMU		0x01000000	/* enable extended MMU mode */
+#define HSR0_EDMMU		0x02000000	/* enable data MMU */
+#define HSR0_EIMMU		0x04000000	/* enable instruction MMU */
+#define HSR0_CBM		0x08000000	/* copy back mode */
+#define HSR0_CBM_WRITE_THRU	0x00000000	/* - write through */
+#define HSR0_CBM_COPY_BACK	0x08000000	/* - copy back */
+#define HSR0_NWA		0x10000000	/* no write allocate */
+#define HSR0_DCE		0x40000000	/* data cache enable */
+#define HSR0_ICE		0x80000000	/* instruction cache enable */
+
+#define __get_HSR(R)	({ unsigned long x; asm volatile("movsg hsr"#R",%0" : "=r"(x)); x; })
+#define __set_HSR(R,V)	do { asm volatile("movgs %0,hsr"#R : : "r"(V)); } while(0)
+
+/*
+ * CCR - Condition Codes Register
+ */
+#define CCR_FCC0		0x0000000f	/* FP/Media condition 0 (fcc0 reg) */
+#define CCR_FCC1		0x000000f0	/* FP/Media condition 1 (fcc1 reg) */
+#define CCR_FCC2		0x00000f00	/* FP/Media condition 2 (fcc2 reg) */
+#define CCR_FCC3		0x0000f000	/* FP/Media condition 3 (fcc3 reg) */
+#define CCR_ICC0		0x000f0000	/* Integer condition 0 (icc0 reg) */
+#define CCR_ICC0_C		0x00010000	/* - Carry flag */
+#define CCR_ICC0_V		0x00020000	/* - Overflow flag */
+#define CCR_ICC0_Z		0x00040000	/* - Zero flag */
+#define CCR_ICC0_N		0x00080000	/* - Negative flag */
+#define CCR_ICC1		0x00f00000	/* Integer condition 1 (icc1 reg) */
+#define CCR_ICC2		0x0f000000	/* Integer condition 2 (icc2 reg) */
+#define CCR_ICC3		0xf0000000	/* Integer condition 3 (icc3 reg) */
+
+/*
+ * CCCR - Condition Codes for Conditional Instructions Register
+ */
+#define CCCR_CC0		0x00000003	/* condition 0 (cc0 reg) */
+#define CCCR_CC0_FALSE		0x00000002	/* - condition is false */
+#define CCCR_CC0_TRUE		0x00000003	/* - condition is true */
+#define CCCR_CC1		0x0000000c	/* condition 1 (cc1 reg) */
+#define CCCR_CC2		0x00000030	/* condition 2 (cc2 reg) */
+#define CCCR_CC3		0x000000c0	/* condition 3 (cc3 reg) */
+#define CCCR_CC4		0x00000300	/* condition 4 (cc4 reg) */
+#define CCCR_CC5		0x00000c00	/* condition 5 (cc5 reg) */
+#define CCCR_CC6		0x00003000	/* condition 6 (cc6 reg) */
+#define CCCR_CC7		0x0000c000	/* condition 7 (cc7 reg) */
+
+/*
+ * ISR - Integer Status Register
+ */
+#define ISR_EMAM		0x00000001	/* memory misaligned access handling */
+#define ISR_EMAM_EXCEPTION	0x00000000	/* - generate exception */
+#define ISR_EMAM_FUDGE		0x00000001	/* - mask out invalid address bits */
+#define ISR_AEXC		0x00000004	/* accrued [overflow] exception */
+#define ISR_DTT			0x00000018	/* division type trap */
+#define ISR_DTT_IGNORE		0x00000000	/* - ignore division error */
+#define ISR_DTT_DIVBYZERO	0x00000008	/* - generate exception */
+#define ISR_DTT_OVERFLOW	0x00000010	/* - record overflow */
+#define ISR_EDE			0x00000020	/* enable division exception */
+#define ISR_PLI			0x20000000	/* pre-load instruction information */
+#define ISR_QI			0x80000000	/* quad data implementation information */
+
+/*
+ * EPCR0 - Exception PC Register
+ */
+#define EPCR0_V			0x00000001	/* register content validity indicator */
+#define EPCR0_PC		0xfffffffc	/* faulting instruction address */
+
+/*
+ * ESR0/14/15 - Exception Status Register
+ */
+#define ESRx_VALID		0x00000001	/* register content validity indicator */
+#define ESRx_EC			0x0000003e	/* exception type */
+#define ESRx_EC_DATA_STORE	0x00000000	/* - data_store_error */
+#define ESRx_EC_INSN_ACCESS	0x00000006	/* - instruction_access_error */
+#define ESRx_EC_PRIV_INSN	0x00000008	/* - privileged_instruction */
+#define ESRx_EC_ILL_INSN	0x0000000a	/* - illegal_instruction */
+#define ESRx_EC_MP_EXCEP	0x0000001c	/* - mp_exception */
+#define ESRx_EC_DATA_ACCESS	0x00000024	/* - data_access_error */
+#define ESRx_EC_DIVISION	0x00000026	/* - division_exception */
+#define ESRx_EC_ITLB_MISS	0x00000034	/* - instruction_access_TLB_miss */
+#define ESRx_EC_DTLB_MISS	0x00000036	/* - data_access_TLB_miss */
+#define ESRx_EC_DATA_ACCESS_DAT	0x0000003a	/* - data_access_DAT_exception */
+
+#define ESR0_IAEC		0x00000100	/* info for instruction-access-exception */
+#define ESR0_IAEC_RESV		0x00000000	/* - reserved */
+#define ESR0_IAEC_PROT_VIOL	0x00000100	/* - protection violation */
+
+#define ESR0_ATXC		0x00f00000	/* address translation exception code */
+#define ESR0_ATXC_MMU_MISS	0x00000000	/* - MMU miss exception and more (?) */
+#define ESR0_ATXC_MULTI_DAT	0x00800000	/* - multiple DAT entry hit */
+#define ESR0_ATXC_MULTI_SAT	0x00900000	/* - multiple SAT entry hit */
+#define ESR0_ATXC_AMRTLB_MISS	0x00a00000	/* - MMU/TLB miss exception */
+#define ESR0_ATXC_PRIV_EXCEP	0x00c00000	/* - privilege protection fault */
+#define ESR0_ATXC_WP_EXCEP	0x00d00000	/* - write protection fault */
+
+#define ESR0_EAV		0x00000800	/* true if EAR0 register valid */
+#define ESR15_EAV		0x00000800	/* true if EAR15 register valid */
+
+/*
+ * ESFR1 - Exception Status Valid Flag Register
+ */
+#define ESFR1_ESR0		0x00000001	/* true if ESR0 is valid */
+#define ESFR1_ESR14		0x00004000	/* true if ESR14 is valid */
+#define ESFR1_ESR15		0x00008000	/* true if ESR15 is valid */
+
+/*
+ * MSR - Media Status Register
+ */
+#define MSR0_AOVF		0x00000001	/* overflow exception accrued */
+#define MSRx_OVF		0x00000002	/* overflow exception detected */
+#define MSRx_SIE		0x0000003c	/* last SIMD instruction exception detected */
+#define MSRx_SIE_NONE		0x00000000	/* - none detected */
+#define MSRx_SIE_FRkHI_ACCk	0x00000020	/* - exception at FRkHI or ACCk */
+#define MSRx_SIE_FRkLO_ACCk1	0x00000010	/* - exception at FRkLO or ACCk+1 */
+#define MSRx_SIE_FRk1HI_ACCk2	0x00000008	/* - exception at FRk+1HI or ACCk+2 */
+#define MSRx_SIE_FRk1LO_ACCk3	0x00000004	/* - exception at FRk+1LO or ACCk+3 */
+#define MSR0_MTT		0x00007000	/* type of last media trap detected */
+#define MSR0_MTT_NONE		0x00000000	/* - none detected */
+#define MSR0_MTT_OVERFLOW	0x00001000	/* - overflow detected */
+#define MSR0_HI			0x00c00000	/* hardware implementation */
+#define MSR0_HI_ROUNDING	0x00000000	/* - rounding mode */
+#define MSR0_HI_NONROUNDING	0x00c00000	/* - non-rounding mode */
+#define MSR0_EMCI		0x01000000	/* enable media custom instructions */
+#define MSR0_SRDAV		0x10000000	/* select rounding mode of MAVEH */
+#define MSR0_SRDAV_RDAV		0x00000000	/* - controlled by MSR.RDAV */
+#define MSR0_SRDAV_RD		0x10000000	/* - controlled by MSR.RD */
+#define MSR0_RDAV		0x20000000	/* rounding mode of MAVEH */
+#define MSR0_RDAV_NEAREST_MI	0x00000000	/* - round to nearest minus */
+#define MSR0_RDAV_NEAREST_PL	0x20000000	/* - round to nearest plus */
+#define MSR0_RD			0xc0000000	/* rounding mode */
+#define MSR0_RD_NEAREST		0x00000000	/* - nearest */
+#define MSR0_RD_ZERO		0x40000000	/* - zero */
+#define MSR0_RD_POS_INF		0x80000000	/* - postive infinity */
+#define MSR0_RD_NEG_INF		0xc0000000	/* - negative infinity */
+
+/*
+ * IAMPR0-7 - Instruction Address Mapping Register
+ * DAMPR0-7 - Data Address Mapping Register
+ */
+#define xAMPRx_V		0x00000001	/* register content validity indicator */
+#define DAMPRx_WP		0x00000002	/* write protect */
+#define DAMPRx_WP_RW		0x00000000	/* - read/write */
+#define DAMPRx_WP_RO		0x00000002	/* - read-only */
+#define xAMPRx_C		0x00000004	/* cached/uncached */
+#define xAMPRx_C_CACHED		0x00000000	/* - cached */
+#define xAMPRx_C_UNCACHED	0x00000004	/* - uncached */
+#define xAMPRx_S		0x00000008	/* supervisor only */
+#define xAMPRx_S_USER		0x00000000	/* - userspace can access */
+#define xAMPRx_S_KERNEL		0x00000008	/* - kernel only */
+#define xAMPRx_SS		0x000000f0	/* segment size */
+#define xAMPRx_SS_16Kb		0x00000000	/* - 16 kilobytes */
+#define xAMPRx_SS_64Kb		0x00000010	/* - 64 kilobytes */
+#define xAMPRx_SS_256Kb		0x00000020	/* - 256 kilobytes */
+#define xAMPRx_SS_1Mb		0x00000030	/* - 1 megabyte */
+#define xAMPRx_SS_2Mb		0x00000040	/* - 2 megabytes */
+#define xAMPRx_SS_4Mb		0x00000050	/* - 4 megabytes */
+#define xAMPRx_SS_8Mb		0x00000060	/* - 8 megabytes */
+#define xAMPRx_SS_16Mb		0x00000070	/* - 16 megabytes */
+#define xAMPRx_SS_32Mb		0x00000080	/* - 32 megabytes */
+#define xAMPRx_SS_64Mb		0x00000090	/* - 64 megabytes */
+#define xAMPRx_SS_128Mb		0x000000a0	/* - 128 megabytes */
+#define xAMPRx_SS_256Mb		0x000000b0	/* - 256 megabytes */
+#define xAMPRx_SS_512Mb		0x000000c0	/* - 512 megabytes */
+#define xAMPRx_RESERVED8	0x00000100	/* reserved bit */
+#define xAMPRx_NG		0x00000200	/* non-global */
+#define xAMPRx_L		0x00000400	/* locked */
+#define xAMPRx_M		0x00000800	/* modified */
+#define xAMPRx_D		0x00001000	/* DAT entry */
+#define xAMPRx_RESERVED13	0x00002000	/* reserved bit */
+#define xAMPRx_PPFN		0xfff00000	/* physical page frame number */
+
+#define xAMPRx_V_BIT		0
+#define DAMPRx_WP_BIT		1
+#define xAMPRx_C_BIT		2
+#define xAMPRx_S_BIT		3
+#define xAMPRx_RESERVED8_BIT	8
+#define xAMPRx_NG_BIT		9
+#define xAMPRx_L_BIT		10
+#define xAMPRx_M_BIT		11
+#define xAMPRx_D_BIT		12
+#define xAMPRx_RESERVED13_BIT	13
+
+#define __get_IAMPR(R) ({ unsigned long x; asm volatile("movsg iampr"#R",%0" : "=r"(x)); x; })
+#define __get_DAMPR(R) ({ unsigned long x; asm volatile("movsg dampr"#R",%0" : "=r"(x)); x; })
+
+#define __get_IAMLR(R) ({ unsigned long x; asm volatile("movsg iamlr"#R",%0" : "=r"(x)); x; })
+#define __get_DAMLR(R) ({ unsigned long x; asm volatile("movsg damlr"#R",%0" : "=r"(x)); x; })
+
+#define __set_IAMPR(R,V) 	do { asm volatile("movgs %0,iampr"#R : : "r"(V)); } while(0)
+#define __set_DAMPR(R,V)  	do { asm volatile("movgs %0,dampr"#R : : "r"(V)); } while(0)
+
+#define __set_IAMLR(R,V) 	do { asm volatile("movgs %0,iamlr"#R : : "r"(V)); } while(0)
+#define __set_DAMLR(R,V)  	do { asm volatile("movgs %0,damlr"#R : : "r"(V)); } while(0)
+
+#define save_dampr(R, _dampr)					\
+do {								\
+	asm volatile("movsg dampr"R",%0" : "=r"(_dampr));	\
+} while(0)
+
+#define restore_dampr(R, _dampr)			\
+do {							\
+	asm volatile("movgs %0,dampr"R :: "r"(_dampr));	\
+} while(0)
+
+/*
+ * AMCR - Address Mapping Control Register
+ */
+#define AMCR_IAMRN		0x000000ff	/* quantity of IAMPR registers */
+#define AMCR_DAMRN		0x0000ff00	/* quantity of DAMPR registers */
+
+/*
+ * TTBR - Address Translation Table Base Register
+ */
+#define __get_TTBR()		({ unsigned long x; asm volatile("movsg ttbr,%0" : "=r"(x)); x; })
+
+/*
+ * TPXR - TLB Probe Extend Register
+ */
+#define TPXR_E			0x00000001
+#define TPXR_LMAX_SHIFT		20
+#define TPXR_LMAX_SMASK		0xf
+#define TPXR_WMAX_SHIFT		24
+#define TPXR_WMAX_SMASK		0xf
+#define TPXR_WAY_SHIFT		28
+#define TPXR_WAY_SMASK		0xf
+
+/*
+ * DCR - Debug Control Register
+ */
+#define DCR_IBCE3		0x00000001	/* break on conditional insn pointed to by IBAR3 */
+#define DCR_IBE3		0x00000002	/* break on insn pointed to by IBAR3 */
+#define DCR_IBCE1		0x00000004	/* break on conditional insn pointed to by IBAR2 */
+#define DCR_IBE1		0x00000008	/* break on insn pointed to by IBAR2 */
+#define DCR_IBCE2		0x00000010	/* break on conditional insn pointed to by IBAR1 */
+#define DCR_IBE2		0x00000020	/* break on insn pointed to by IBAR1 */
+#define DCR_IBCE0		0x00000040	/* break on conditional insn pointed to by IBAR0 */
+#define DCR_IBE0		0x00000080	/* break on insn pointed to by IBAR0 */
+
+#define DCR_DDBE1		0x00004000	/* use DBDR1x when checking DBAR1 */
+#define DCR_DWBE1		0x00008000	/* break on store to address in DBAR1/DBMR1x */
+#define DCR_DRBE1		0x00010000	/* break on load from address in DBAR1/DBMR1x */
+#define DCR_DDBE0		0x00020000	/* use DBDR0x when checking DBAR0 */
+#define DCR_DWBE0		0x00040000	/* break on store to address in DBAR0/DBMR0x */
+#define DCR_DRBE0		0x00080000	/* break on load from address in DBAR0/DBMR0x */
+
+#define DCR_EIM			0x0c000000	/* external interrupt disable */
+#define DCR_IBM			0x10000000	/* instruction break disable */
+#define DCR_SE			0x20000000	/* single step enable */
+#define DCR_EBE			0x40000000	/* exception break enable */
+
+/*
+ * BRR - Break Interrupt Request Register
+ */
+#define BRR_ST			0x00000001	/* single-step detected */
+#define BRR_SB			0x00000002	/* break instruction detected */
+#define BRR_BB			0x00000004	/* branch with hint detected */
+#define BRR_CBB			0x00000008	/* branch to LR detected */
+#define BRR_IBx			0x000000f0	/* hardware breakpoint detected */
+#define BRR_DBx			0x00000f00	/* hardware watchpoint detected */
+#define BRR_DBNEx		0x0000f000	/* ? */
+#define BRR_EBTT		0x00ff0000	/* trap type of exception break */
+#define BRR_TB			0x10000000	/* external break request detected */
+#define BRR_CB			0x20000000	/* ICE break command detected */
+#define BRR_EB			0x40000000	/* exception break detected */
+
+/*
+ * BPSR - Break PSR Save Register
+ */
+#define BPSR_BET		0x00000001	/* former PSR.ET */
+#define BPSR_BS			0x00001000	/* former PSR.S */
+
+#endif /* _ASM_SPR_REGS_H */
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/include/asm-frv/statfs.h linux-2.6.10-rc1-mm3-frv/include/asm-frv/statfs.h
--- /warthog/kernels/linux-2.6.10-rc1-mm3/include/asm-frv/statfs.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/include/asm-frv/statfs.h	2004-11-05 14:13:04.242467142 +0000
@@ -0,0 +1,7 @@
+#ifndef _ASM_STATFS_H
+#define _ASM_STATFS_H
+
+#include <asm-generic/statfs.h>
+
+#endif /* _ASM_STATFS_H */
+
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/include/asm-frv/stat.h linux-2.6.10-rc1-mm3-frv/include/asm-frv/stat.h
--- /warthog/kernels/linux-2.6.10-rc1-mm3/include/asm-frv/stat.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/include/asm-frv/stat.h	2004-11-05 14:13:04.246466805 +0000
@@ -0,0 +1,100 @@
+#ifndef _ASM_STAT_H
+#define _ASM_STAT_H
+
+struct __old_kernel_stat {
+	unsigned short st_dev;
+	unsigned short st_ino;
+	unsigned short st_mode;
+	unsigned short st_nlink;
+	unsigned short st_uid;
+	unsigned short st_gid;
+	unsigned short st_rdev;
+	unsigned long  st_size;
+	unsigned long  st_atime;
+	unsigned long  st_mtime;
+	unsigned long  st_ctime;
+};
+
+/* This matches struct stat in uClibc/glibc.  */
+struct stat {
+	unsigned char __pad1[6];
+	unsigned short st_dev;
+
+	unsigned long __pad2;
+	unsigned long st_ino;
+
+	unsigned short __pad3;
+	unsigned short st_mode;
+	unsigned short __pad4;
+	unsigned short st_nlink;
+
+	unsigned short __pad5;
+	unsigned short st_uid;
+	unsigned short __pad6;
+	unsigned short st_gid;
+
+	unsigned char __pad7[6];
+	unsigned short st_rdev;
+
+	unsigned long __pad8;
+	unsigned long st_size;
+
+	unsigned long __pad9;		/* align 64-bit st_blocks to 2-word */
+	unsigned long st_blksize;
+
+	unsigned long __pad10;	/* future possible st_blocks high bits */
+	unsigned long st_blocks;	/* Number 512-byte blocks allocated. */
+
+	unsigned long __unused1;
+	unsigned long st_atime;
+
+	unsigned long __unused2;
+	unsigned long st_mtime;
+
+	unsigned long __unused3;
+	unsigned long st_ctime;
+
+	unsigned long long __unused4;
+};
+
+/* This matches struct stat64 in uClibc/glibc.  The layout is exactly
+   the same as that of struct stat above, with 64-bit types taking up
+   space that was formerly used by padding.  stat syscalls are still
+   different from stat64, though, in that the former tests for
+   overflow.  */
+struct stat64 {
+	unsigned char __pad1[6];
+	unsigned short st_dev;
+
+	unsigned long long st_ino;
+
+	unsigned int st_mode;
+	unsigned int st_nlink;
+
+	unsigned long st_uid;
+	unsigned long st_gid;
+
+	unsigned char __pad2[6];
+	unsigned short st_rdev;
+
+	long long st_size;
+
+	unsigned long __pad3;		/* align 64-bit st_blocks to 2-word */
+	unsigned long st_blksize;
+
+	unsigned long __pad4;		/* future possible st_blocks high bits */
+	unsigned long st_blocks;	/* Number 512-byte blocks allocated. */
+
+	unsigned long st_atime_nsec;
+	unsigned long st_atime;
+
+	unsigned int st_mtime_nsec;
+	unsigned long st_mtime;
+
+	unsigned long st_ctime_nsec;
+	unsigned long st_ctime;
+
+	unsigned long long __unused4;
+};
+
+#endif /* _ASM_STAT_H */
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/include/asm-frv/string.h linux-2.6.10-rc1-mm3-frv/include/asm-frv/string.h
--- /warthog/kernels/linux-2.6.10-rc1-mm3/include/asm-frv/string.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/include/asm-frv/string.h	2004-11-05 14:13:04.250466467 +0000
@@ -0,0 +1,51 @@
+/* string.h: FRV string handling
+ *
+ * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * 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.
+ */
+
+#ifndef _ASM_STRING_H_
+#define _ASM_STRING_H_
+
+#ifdef __KERNEL__ /* only set these up for kernel code */
+
+#define __HAVE_ARCH_MEMSET 1
+#define __HAVE_ARCH_MEMCPY 1
+
+extern void *memset(void *, int, __kernel_size_t);
+extern void *memcpy(void *, const void *, __kernel_size_t);
+
+#else /* KERNEL */
+
+/*
+ *	let user libraries deal with these,
+ *	IMHO the kernel has no place defining these functions for user apps
+ */
+
+#define __HAVE_ARCH_STRCPY 1
+#define __HAVE_ARCH_STRNCPY 1
+#define __HAVE_ARCH_STRCAT 1
+#define __HAVE_ARCH_STRNCAT 1
+#define __HAVE_ARCH_STRCMP 1
+#define __HAVE_ARCH_STRNCMP 1
+#define __HAVE_ARCH_STRNICMP 1
+#define __HAVE_ARCH_STRCHR 1
+#define __HAVE_ARCH_STRRCHR 1
+#define __HAVE_ARCH_STRSTR 1
+#define __HAVE_ARCH_STRLEN 1
+#define __HAVE_ARCH_STRNLEN 1
+#define __HAVE_ARCH_MEMSET 1
+#define __HAVE_ARCH_MEMCPY 1
+#define __HAVE_ARCH_MEMMOVE 1
+#define __HAVE_ARCH_MEMSCAN 1
+#define __HAVE_ARCH_MEMCMP 1
+#define __HAVE_ARCH_MEMCHR 1
+#define __HAVE_ARCH_STRTOK 1
+
+#endif /* KERNEL */
+#endif /* _ASM_STRING_H_ */
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/include/asm-frv/suspend.h linux-2.6.10-rc1-mm3-frv/include/asm-frv/suspend.h
--- /warthog/kernels/linux-2.6.10-rc1-mm3/include/asm-frv/suspend.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/include/asm-frv/suspend.h	2004-11-05 14:13:04.254466129 +0000
@@ -0,0 +1,20 @@
+/* suspend.h: suspension stuff
+ *
+ * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * 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.
+ */
+
+#ifndef _ASM_SUSPEND_H
+#define _ASM_SUSPEND_H
+
+static inline int arch_prepare_suspend(void)
+{
+	return 0;
+}
+
+#endif /* _ASM_SUSPEND_H */
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/include/asm-frv/system.h linux-2.6.10-rc1-mm3-frv/include/asm-frv/system.h
--- /warthog/kernels/linux-2.6.10-rc1-mm3/include/asm-frv/system.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/include/asm-frv/system.h	2004-11-05 14:13:04.259465707 +0000
@@ -0,0 +1,123 @@
+/* system.h: FR-V CPU control definitions
+ *
+ * Copyright (C) 2003 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * 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.
+ */
+
+#ifndef _ASM_SYSTEM_H
+#define _ASM_SYSTEM_H
+
+#include <linux/config.h> /* get configuration macros */
+#include <linux/linkage.h>
+#include <asm/atomic.h>
+
+struct thread_struct;
+
+#define prepare_to_switch()    do { } while(0)
+
+/*
+ * switch_to(prev, next) should switch from task `prev' to `next'
+ * `prev' will never be the same as `next'.
+ * The `mb' is to tell GCC not to cache `current' across this call.
+ */
+extern asmlinkage
+void __switch_to(struct thread_struct *prev, struct thread_struct *next);
+
+#define switch_to(prev, next, last)						\
+do {										\
+	prev->thread.sched_lr = (unsigned long) __builtin_return_address(0);	\
+	__switch_to(&prev->thread, &next->thread);				\
+	mb();									\
+} while(0)
+
+/*
+ * interrupt flag manipulation
+ */
+#define local_irq_disable()				\
+do {							\
+	unsigned long psr;				\
+	asm volatile("	movsg	psr,%0		\n"	\
+		     "	andi	%0,%2,%0	\n"	\
+		     "	ori	%0,%1,%0	\n"	\
+		     "	movgs	%0,psr		\n"	\
+		     : "=r"(psr)			\
+		     : "i" (PSR_PIL_14), "i" (~PSR_PIL)	\
+		     : "memory");			\
+} while(0)
+
+#define local_irq_enable()				\
+do {							\
+	unsigned long psr;				\
+	asm volatile("	movsg	psr,%0		\n"	\
+		     "	andi	%0,%1,%0	\n"	\
+		     "	movgs	%0,psr		\n"	\
+		     : "=r"(psr)			\
+		     : "i" (~PSR_PIL)			\
+		     : "memory");			\
+} while(0)
+
+#define local_save_flags(flags)			\
+do {						\
+	typecheck(unsigned long, flags);	\
+	asm("movsg psr,%0"			\
+	    : "=r"(flags)			\
+	    :					\
+	    : "memory");			\
+} while(0)
+
+#define	local_irq_save(flags)				\
+do {							\
+	unsigned long npsr;				\
+	typecheck(unsigned long, flags);		\
+	asm volatile("	movsg	psr,%0		\n"	\
+		     "	andi	%0,%3,%1	\n"	\
+		     "	ori	%1,%2,%1	\n"	\
+		     "	movgs	%1,psr		\n"	\
+		     : "=r"(flags), "=r"(npsr)		\
+		     : "i" (PSR_PIL_14), "i" (~PSR_PIL)	\
+		     : "memory");			\
+} while(0)
+
+#define	local_irq_restore(flags)			\
+do {							\
+	typecheck(unsigned long, flags);		\
+	asm volatile("	movgs	%0,psr		\n"	\
+		     :					\
+		     : "r" (flags)			\
+		     : "memory");			\
+} while(0)
+
+#define irqs_disabled() \
+	((__get_PSR() & PSR_PIL) >= PSR_PIL_14)
+
+/*
+ * Force strict CPU ordering.
+ */
+#define nop()			asm volatile ("nop"::)
+#define mb()			asm volatile ("membar" : : :"memory")
+#define rmb()			asm volatile ("membar" : : :"memory")
+#define wmb()			asm volatile ("membar" : : :"memory")
+#define set_mb(var, value)	do { var = value; mb(); } while (0)
+#define set_wmb(var, value)	do { var = value; wmb(); } while (0)
+
+#define smp_mb()		mb()
+#define smp_rmb()		rmb()
+#define smp_wmb()		wmb()
+
+#define read_barrier_depends()		do {} while(0)
+#define smp_read_barrier_depends()	read_barrier_depends()
+
+#define HARD_RESET_NOW()			\
+do {						\
+	cli();					\
+} while(1)
+
+extern void die_if_kernel(const char *, ...) __attribute__((format(printf, 1, 2)));
+extern void free_initmem(void);
+
+#endif /* _ASM_SYSTEM_H */
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/include/asm-frv/termbits.h linux-2.6.10-rc1-mm3-frv/include/asm-frv/termbits.h
--- /warthog/kernels/linux-2.6.10-rc1-mm3/include/asm-frv/termbits.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/include/asm-frv/termbits.h	2004-11-05 16:11:21.023484003 +0000
@@ -0,0 +1,177 @@
+#ifndef _ASM_TERMBITS_H__
+#define _ASM_TERMBITS_H__
+
+#include <linux/posix_types.h>
+
+typedef unsigned char	cc_t;
+typedef unsigned int	speed_t;
+typedef unsigned int	tcflag_t;
+
+#define NCCS 19
+struct termios {
+	tcflag_t c_iflag;		/* input mode flags */
+	tcflag_t c_oflag;		/* output mode flags */
+	tcflag_t c_cflag;		/* control mode flags */
+	tcflag_t c_lflag;		/* local mode flags */
+	cc_t c_line;			/* line discipline */
+	cc_t c_cc[NCCS];		/* control characters */
+};
+
+/* c_cc characters */
+#define VINTR 0
+#define VQUIT 1
+#define VERASE 2
+#define VKILL 3
+#define VEOF 4
+#define VTIME 5
+#define VMIN 6
+#define VSWTC 7
+#define VSTART 8
+#define VSTOP 9
+#define VSUSP 10
+#define VEOL 11
+#define VREPRINT 12
+#define VDISCARD 13
+#define VWERASE 14
+#define VLNEXT 15
+#define VEOL2 16
+
+
+/* c_iflag bits */
+#define IGNBRK	0000001
+#define BRKINT	0000002
+#define IGNPAR	0000004
+#define PARMRK	0000010
+#define INPCK	0000020
+#define ISTRIP	0000040
+#define INLCR	0000100
+#define IGNCR	0000200
+#define ICRNL	0000400
+#define IUCLC	0001000
+#define IXON	0002000
+#define IXANY	0004000
+#define IXOFF	0010000
+#define IMAXBEL	0020000
+#define IUTF8	0040000
+
+/* c_oflag bits */
+#define OPOST	0000001
+#define OLCUC	0000002
+#define ONLCR	0000004
+#define OCRNL	0000010
+#define ONOCR	0000020
+#define ONLRET	0000040
+#define OFILL	0000100
+#define OFDEL	0000200
+#define NLDLY	0000400
+#define   NL0	0000000
+#define   NL1	0000400
+#define CRDLY	0003000
+#define   CR0	0000000
+#define   CR1	0001000
+#define   CR2	0002000
+#define   CR3	0003000
+#define TABDLY	0014000
+#define   TAB0	0000000
+#define   TAB1	0004000
+#define   TAB2	0010000
+#define   TAB3	0014000
+#define   XTABS	0014000
+#define BSDLY	0020000
+#define   BS0	0000000
+#define   BS1	0020000
+#define VTDLY	0040000
+#define   VT0	0000000
+#define   VT1	0040000
+#define FFDLY	0100000
+#define   FF0	0000000
+#define   FF1	0100000
+
+/* c_cflag bit meaning */
+#define CBAUD	0010017
+#define  B0	0000000		/* hang up */
+#define  B50	0000001
+#define  B75	0000002
+#define  B110	0000003
+#define  B134	0000004
+#define  B150	0000005
+#define  B200	0000006
+#define  B300	0000007
+#define  B600	0000010
+#define  B1200	0000011
+#define  B1800	0000012
+#define  B2400	0000013
+#define  B4800	0000014
+#define  B9600	0000015
+#define  B19200	0000016
+#define  B38400	0000017
+#define EXTA B19200
+#define EXTB B38400
+#define CSIZE	0000060
+#define   CS5	0000000
+#define   CS6	0000020
+#define   CS7	0000040
+#define   CS8	0000060
+#define CSTOPB	0000100
+#define CREAD	0000200
+#define PARENB	0000400
+#define PARODD	0001000
+#define HUPCL	0002000
+#define CLOCAL	0004000
+#define CBAUDEX 0010000
+#define    B57600 0010001
+#define   B115200 0010002
+#define   B230400 0010003
+#define   B460800 0010004
+#define   B500000 0010005
+#define   B576000 0010006
+#define   B921600 0010007
+#define  B1000000 0010010
+#define  B1152000 0010011
+#define  B1500000 0010012
+#define  B2000000 0010013
+#define  B2500000 0010014
+#define  B3000000 0010015
+#define  B3500000 0010016
+#define  B4000000 0010017
+#define CIBAUD	  002003600000	/* input baud rate (not used) */
+#define CTVB	  004000000000		/* VisioBraille Terminal flow control */
+#define CMSPAR	  010000000000		/* mark or space (stick) parity */
+#define CRTSCTS	  020000000000		/* flow control */
+
+/* c_lflag bits */
+#define ISIG	0000001
+#define ICANON	0000002
+#define XCASE	0000004
+#define ECHO	0000010
+#define ECHOE	0000020
+#define ECHOK	0000040
+#define ECHONL	0000100
+#define NOFLSH	0000200
+#define TOSTOP	0000400
+#define ECHOCTL	0001000
+#define ECHOPRT	0002000
+#define ECHOKE	0004000
+#define FLUSHO	0010000
+#define PENDIN	0040000
+#define IEXTEN	0100000
+
+
+/* tcflow() and TCXONC use these */
+#define	TCOOFF		0
+#define	TCOON		1
+#define	TCIOFF		2
+#define	TCION		3
+
+/* tcflush() and TCFLSH use these */
+#define	TCIFLUSH	0
+#define	TCOFLUSH	1
+#define	TCIOFLUSH	2
+
+/* tcsetattr uses these */
+#define	TCSANOW		0
+#define	TCSADRAIN	1
+#define	TCSAFLUSH	2
+
+#endif /* _ASM_TERMBITS_H__ */
+
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/include/asm-frv/termios.h linux-2.6.10-rc1-mm3-frv/include/asm-frv/termios.h
--- /warthog/kernels/linux-2.6.10-rc1-mm3/include/asm-frv/termios.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/include/asm-frv/termios.h	2004-11-05 14:13:04.267465031 +0000
@@ -0,0 +1,74 @@
+#ifndef _ASM_TERMIOS_H
+#define _ASM_TERMIOS_H
+
+#include <asm/termbits.h>
+#include <asm/ioctls.h>
+
+struct winsize {
+	unsigned short ws_row;
+	unsigned short ws_col;
+	unsigned short ws_xpixel;
+	unsigned short ws_ypixel;
+};
+
+#define NCC 8
+struct termio {
+	unsigned short c_iflag;		/* input mode flags */
+	unsigned short c_oflag;		/* output mode flags */
+	unsigned short c_cflag;		/* control mode flags */
+	unsigned short c_lflag;		/* local mode flags */
+	unsigned char c_line;		/* line discipline */
+	unsigned char c_cc[NCC];	/* control characters */
+};
+
+#ifdef __KERNEL__
+/*	intr=^C		quit=^|		erase=del	kill=^U
+	eof=^D		vtime=\0	vmin=\1		sxtc=\0
+	start=^Q	stop=^S		susp=^Z		eol=\0
+	reprint=^R	discard=^U	werase=^W	lnext=^V
+	eol2=\0
+*/
+#define INIT_C_CC "\003\034\177\025\004\0\1\0\021\023\032\0\022\017\027\026\0"
+#endif
+
+/* modem lines */
+#define TIOCM_LE	0x001
+#define TIOCM_DTR	0x002
+#define TIOCM_RTS	0x004
+#define TIOCM_ST	0x008
+#define TIOCM_SR	0x010
+#define TIOCM_CTS	0x020
+#define TIOCM_CAR	0x040
+#define TIOCM_RNG	0x080
+#define TIOCM_DSR	0x100
+#define TIOCM_CD	TIOCM_CAR
+#define TIOCM_RI	TIOCM_RNG
+#define TIOCM_OUT1	0x2000
+#define TIOCM_OUT2	0x4000
+#define TIOCM_LOOP	0x8000
+
+#define TIOCM_MODEM_BITS       TIOCM_OUT2      /* IRDA support */
+
+/* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */
+
+/* line disciplines */
+#define N_TTY		0
+#define N_SLIP		1
+#define N_MOUSE		2
+#define N_PPP		3
+#define N_STRIP		4
+#define N_AX25		5
+#define N_X25		6	/* X.25 async */
+#define N_6PACK		7
+#define N_MASC		8	/* Reserved for Mobitex module <kaz@cafe.net> */
+#define N_R3964		9	/* Reserved for Simatic R3964 module */
+#define N_PROFIBUS_FDL	10	/* Reserved for Profibus <Dave@mvhi.com> */
+#define N_IRDA		11	/* Linux IrDa - http://irda.sourceforge.net/ */
+#define N_SMSBLOCK	12	/* SMS block mode - for talking to GSM data cards about SMS messages */
+#define N_HDLC		13	/* synchronous HDLC */
+#define N_SYNC_PPP	14
+#define N_HCI		15  /* Bluetooth HCI UART */
+
+#include <asm-generic/termios.h>
+
+#endif /* _ASM_TERMIOS_H */
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/include/asm-frv/thread_info.h linux-2.6.10-rc1-mm3-frv/include/asm-frv/thread_info.h
--- /warthog/kernels/linux-2.6.10-rc1-mm3/include/asm-frv/thread_info.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/include/asm-frv/thread_info.h	2004-11-05 14:13:04.272464609 +0000
@@ -0,0 +1,158 @@
+/* thread_info.h: description
+ *
+ * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ * Derived from include/asm-i386/thread_info.h
+ *
+ * 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.
+ */
+
+#ifndef _ASM_THREAD_INFO_H
+#define _ASM_THREAD_INFO_H
+
+#ifdef __KERNEL__
+
+#ifndef __ASSEMBLY__
+#include <asm/processor.h>
+#endif
+
+/*
+ * low level task data that entry.S needs immediate access to
+ * - this struct should fit entirely inside of one cache line
+ * - this struct shares the supervisor stack pages
+ * - if the contents of this structure are changed, the assembly constants must also be changed
+ */
+#ifndef __ASSEMBLY__
+
+struct thread_info {
+	struct task_struct	*task;		/* main task structure */
+	struct exec_domain	*exec_domain;	/* execution domain */
+	unsigned long		flags;		/* low level flags */
+	unsigned long		status;		/* thread-synchronous flags */
+	__u32			cpu;		/* current CPU */
+	__s32			preempt_count;	/* 0 => preemptable, <0 => BUG */
+
+	mm_segment_t		addr_limit;	/* thread address space:
+					 	   0-0xBFFFFFFF for user-thead
+						   0-0xFFFFFFFF for kernel-thread
+						*/
+	struct restart_block    restart_block;
+
+	__u8			supervisor_stack[0];
+};
+
+#else /* !__ASSEMBLY__ */
+
+/* offsets into the thread_info struct for assembly code access */
+#define TI_TASK			0x00000000
+#define TI_EXEC_DOMAIN		0x00000004
+#define TI_FLAGS		0x00000008
+#define TI_STATUS		0x0000000C
+#define TI_CPU			0x00000010
+#define TI_PRE_COUNT		0x00000014
+#define TI_ADDR_LIMIT		0x00000018
+#define TI_RESTART_BLOCK	0x0000001C
+
+#endif
+
+#define PREEMPT_ACTIVE		0x4000000
+
+/*
+ * macros/functions for gaining access to the thread information structure
+ *
+ * preempt_count needs to be 1 initially, until the scheduler is functional.
+ */
+#ifndef __ASSEMBLY__
+
+#define INIT_THREAD_INFO(tsk)			\
+{						\
+	.task		= &tsk,			\
+	.exec_domain	= &default_exec_domain,	\
+	.flags		= 0,			\
+	.cpu		= 0,			\
+	.preempt_count	= 1,			\
+	.addr_limit	= KERNEL_DS,		\
+	.restart_block = {			\
+		.fn = do_no_restart_syscall,	\
+	},					\
+}
+
+#define init_thread_info	(init_thread_union.thread_info)
+#define init_stack		(init_thread_union.stack)
+
+#ifdef CONFIG_SMALL_TASKS
+#define THREAD_SIZE		4096
+#else
+#define THREAD_SIZE		8192
+#endif
+
+/* how to get the thread information struct from C */
+register struct thread_info *__current_thread_info asm("gr15");
+
+#define current_thread_info() ({ __current_thread_info; })
+
+/* thread information allocation */
+#ifdef CONFIG_DEBUG_STACK_USAGE
+#define alloc_thread_info(tsk)					\
+	({							\
+		struct thread_info *ret;			\
+								\
+		ret = kmalloc(THREAD_SIZE, GFP_KERNEL);		\
+		if (ret)					\
+			memset(ret, 0, THREAD_SIZE);		\
+		ret;						\
+	})
+#else
+#define alloc_thread_info(tsk)	kmalloc(THREAD_SIZE, GFP_KERNEL)
+#endif
+
+#define free_thread_info(info)	kfree(info)
+#define get_thread_info(ti)	get_task_struct((ti)->task)
+#define put_thread_info(ti)	put_task_struct((ti)->task)
+
+#else /* !__ASSEMBLY__ */
+
+#define THREAD_SIZE	8192
+
+#endif
+
+/*
+ * thread information flags
+ * - these are process state flags that various assembly files may need to access
+ * - pending work-to-be-done flags are in LSW
+ * - other flags in MSW
+ */
+#define TIF_SYSCALL_TRACE	0	/* syscall trace active */
+#define TIF_NOTIFY_RESUME	1	/* resumption notification requested */
+#define TIF_SIGPENDING		2	/* signal pending */
+#define TIF_NEED_RESCHED	3	/* rescheduling necessary */
+#define TIF_SINGLESTEP		4	/* restore singlestep on return to user mode */
+#define TIF_IRET		5	/* return with iret */
+#define TIF_POLLING_NRFLAG	16	/* true if poll_idle() is polling TIF_NEED_RESCHED */
+
+#define _TIF_SYSCALL_TRACE	(1 << TIF_SYSCALL_TRACE)
+#define _TIF_NOTIFY_RESUME	(1 << TIF_NOTIFY_RESUME)
+#define _TIF_SIGPENDING		(1 << TIF_SIGPENDING)
+#define _TIF_NEED_RESCHED	(1 << TIF_NEED_RESCHED)
+#define _TIF_SINGLESTEP		(1 << TIF_SINGLESTEP)
+#define _TIF_IRET		(1 << TIF_IRET)
+#define _TIF_POLLING_NRFLAG	(1 << TIF_POLLING_NRFLAG)
+
+#define _TIF_WORK_MASK		0x0000FFFE	/* work to do on interrupt/exception return */
+#define _TIF_ALLWORK_MASK	0x0000FFFF	/* work to do on any return to u-space */
+
+/*
+ * Thread-synchronous status.
+ *
+ * This is different from the flags in that nobody else
+ * ever touches our thread-synchronous status, so we don't
+ * have to worry about atomic accesses.
+ */
+#define TS_USEDFPM		0x0001	/* FPU/Media was used by this task this quantum (SMP) */
+
+#endif /* __KERNEL__ */
+
+#endif /* _ASM_THREAD_INFO_H */
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/include/asm-frv/timer-regs.h linux-2.6.10-rc1-mm3-frv/include/asm-frv/timer-regs.h
--- /warthog/kernels/linux-2.6.10-rc1-mm3/include/asm-frv/timer-regs.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/include/asm-frv/timer-regs.h	2004-11-05 14:13:04.276464271 +0000
@@ -0,0 +1,106 @@
+/* timer-regs.h: hardware timer register definitions
+ *
+ * Copyright (C) 2003 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * 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.
+ */
+
+#ifndef _ASM_TIMER_REGS_H
+#define _ASM_TIMER_REGS_H
+
+#include <asm/sections.h>
+
+extern unsigned long __nongprelbss __clkin_clock_speed_HZ;
+extern unsigned long __nongprelbss __ext_bus_clock_speed_HZ;
+extern unsigned long __nongprelbss __res_bus_clock_speed_HZ;
+extern unsigned long __nongprelbss __sdram_clock_speed_HZ;
+extern unsigned long __nongprelbss __core_bus_clock_speed_HZ;
+extern unsigned long __nongprelbss __core_clock_speed_HZ;
+extern unsigned long __nongprelbss __dsu_clock_speed_HZ;
+extern unsigned long __nongprelbss __serial_clock_speed_HZ;
+
+#define __get_CLKC()	({ *(volatile unsigned long *)(0xfeff9a00); })
+
+static inline void __set_CLKC(unsigned long v)
+{
+	int tmp;
+
+	asm volatile("	st%I0.p	%2,%M0		\n"
+		     "	setlos	%3,%1		\n"
+		     "	membar			\n"
+		     "0:			\n"
+		     "	subicc	%1,#1,%1,icc0	\n"
+		     "	bnc	icc0,#1,0b	\n"
+		     : "=m"(*(volatile unsigned long *) 0xfeff9a00), "=r"(tmp)
+		     : "r"(v), "i"(256)
+		     : "icc0");
+}
+
+#define __get_TCTR()	({ *(volatile unsigned long *)(0xfeff9418); })
+#define __get_TPRV()	({ *(volatile unsigned long *)(0xfeff9420); })
+#define __get_TPRCKSL()	({ *(volatile unsigned long *)(0xfeff9428); })
+#define __get_TCSR(T)	({ *(volatile unsigned long *)(0xfeff9400 + 8 * (T)); })
+#define __get_TxCKSL(T)	({ *(volatile unsigned long *)(0xfeff9430 + 8 * (T)); })
+
+#define __get_TCSR_DATA(T) ({ __get_TCSR(T) >> 24; })
+
+#define __set_TCTR(V)	do { *(volatile unsigned long *)(0xfeff9418) = (V); mb(); } while(0)
+#define __set_TPRV(V)	do { *(volatile unsigned long *)(0xfeff9420) = (V) << 24; mb(); } while(0)
+#define __set_TPRCKSL(V) do { *(volatile unsigned long *)(0xfeff9428) = (V); mb(); } while(0)
+#define __set_TCSR(T,V)	\
+do { *(volatile unsigned long *)(0xfeff9400 + 8 * (T)) = (V); mb(); } while(0)
+
+#define __set_TxCKSL(T,V) \
+do { *(volatile unsigned long *)(0xfeff9430 + 8 * (T)) = (V); mb(); } while(0)
+
+#define __set_TCSR_DATA(T,V) __set_TCSR(T, (V) << 24)
+#define __set_TxCKSL_DATA(T,V) __set_TxCKSL(T, TxCKSL_EIGHT | __TxCKSL_SELECT((V)))
+
+/* clock control register */
+#define CLKC_CMODE		0x0f000000
+#define CLKC_SLPL		0x000f0000
+#define CLKC_P0			0x00000100
+#define CLKC_CM			0x00000003
+
+#define CLKC_CMODE_s		24
+
+/* timer control register - non-readback mode */
+#define TCTR_MODE_0		0x00000000
+#define TCTR_MODE_2		0x04000000
+#define TCTR_MODE_4		0x08000000
+#define TCTR_MODE_5		0x0a000000
+#define TCTR_RL_LATCH		0x00000000
+#define TCTR_RL_RW_LOW8		0x10000000
+#define TCTR_RL_RW_HIGH8	0x20000000
+#define TCTR_RL_RW_LH8		0x30000000
+#define TCTR_SC_CTR0		0x00000000
+#define TCTR_SC_CTR1		0x40000000
+#define TCTR_SC_CTR2		0x80000000
+
+/* timer control register - readback mode */
+#define TCTR_CNT0		0x02000000
+#define TCTR_CNT1		0x04000000
+#define TCTR_CNT2		0x08000000
+#define TCTR_NSTATUS		0x10000000
+#define TCTR_NCOUNT		0x20000000
+#define TCTR_SC_READBACK	0xc0000000
+
+/* timer control status registers - non-readback mode */
+#define TCSRx_DATA		0xff000000
+
+/* timer control status registers - readback mode */
+#define TCSRx_OUTPUT		0x80000000
+#define TCSRx_NULLCOUNT		0x40000000
+#define TCSRx_RL		0x30000000
+#define TCSRx_MODE		0x07000000
+
+/* timer clock select registers */
+#define TxCKSL_SELECT		0x0f000000
+#define __TxCKSL_SELECT(X)	((X) << 24)
+#define TxCKSL_EIGHT		0xf0000000
+
+#endif /* _ASM_TIMER_REGS_H */
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/include/asm-frv/timex.h linux-2.6.10-rc1-mm3-frv/include/asm-frv/timex.h
--- /warthog/kernels/linux-2.6.10-rc1-mm3/include/asm-frv/timex.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/include/asm-frv/timex.h	2004-11-05 14:13:04.279464017 +0000
@@ -0,0 +1,25 @@
+/* timex.h: FR-V architecture timex specifications
+ */
+#ifndef _ASM_TIMEX_H
+#define _ASM_TIMEX_H
+
+#define CLOCK_TICK_RATE		1193180 /* Underlying HZ */
+#define CLOCK_TICK_FACTOR	20	/* Factor of both 1000000 and CLOCK_TICK_RATE */
+
+#define FINETUNE							\
+((((((long)LATCH * HZ - CLOCK_TICK_RATE) << SHIFT_HZ) *			\
+   (1000000/CLOCK_TICK_FACTOR) / (CLOCK_TICK_RATE/CLOCK_TICK_FACTOR))	\
+  << (SHIFT_SCALE-SHIFT_HZ)) / HZ)
+
+typedef unsigned long cycles_t;
+
+static inline cycles_t get_cycles(void)
+{
+	return 0;
+}
+
+#define vxtime_lock()		do {} while (0)
+#define vxtime_unlock()		do {} while (0)
+
+#endif
+
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/include/asm-frv/tlbflush.h linux-2.6.10-rc1-mm3-frv/include/asm-frv/tlbflush.h
--- /warthog/kernels/linux-2.6.10-rc1-mm3/include/asm-frv/tlbflush.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/include/asm-frv/tlbflush.h	2004-11-05 14:13:04.283463680 +0000
@@ -0,0 +1,76 @@
+/* tlbflush.h: TLB flushing functions
+ *
+ * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * 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.
+ */
+
+#ifndef _ASM_TLBFLUSH_H
+#define _ASM_TLBFLUSH_H
+
+#include <linux/config.h>
+#include <linux/mm.h>
+#include <asm/processor.h>
+
+#ifdef CONFIG_MMU
+
+#ifndef __ASSEMBLY__
+extern void asmlinkage __flush_tlb_all(void);
+extern void asmlinkage __flush_tlb_mm(unsigned long contextid);
+extern void asmlinkage __flush_tlb_page(unsigned long contextid, unsigned long start);
+extern void asmlinkage __flush_tlb_range(unsigned long contextid,
+					 unsigned long start, unsigned long end);
+#endif /* !__ASSEMBLY__ */
+
+#define flush_tlb_all()				\
+do {						\
+	preempt_disable();			\
+	__flush_tlb_all();			\
+	preempt_enable();			\
+} while(0)
+
+#define flush_tlb_mm(mm)			\
+do {						\
+	preempt_disable();			\
+	__flush_tlb_mm((mm)->context.id);	\
+	preempt_enable();			\
+} while(0)
+
+#define flush_tlb_range(vma,start,end)					\
+do {									\
+	preempt_disable();						\
+	__flush_tlb_range((vma)->vm_mm->context.id, start, end);	\
+	preempt_enable();						\
+} while(0)
+
+#define flush_tlb_page(vma,addr)				\
+do {								\
+	preempt_disable();					\
+	__flush_tlb_page((vma)->vm_mm->context.id, addr);	\
+	preempt_enable();					\
+} while(0)
+
+
+#define __flush_tlb_global()			flush_tlb_all()
+#define flush_tlb()				flush_tlb_all()
+#define flush_tlb_kernel_range(start, end)	flush_tlb_all()
+#define flush_tlb_pgtables(mm,start,end)	asm volatile("movgs gr0,scr0 ! movgs gr0,scr1");
+
+#else
+
+#define flush_tlb()				BUG()
+#define flush_tlb_all()				BUG()
+#define flush_tlb_mm(mm)			BUG()
+#define flush_tlb_page(vma,addr)		BUG()
+#define flush_tlb_range(mm,start,end)		BUG()
+#define flush_tlb_pgtables(mm,start,end)	BUG()
+#define flush_tlb_kernel_range(start, end)	BUG()
+
+#endif
+
+
+#endif /* _ASM_TLBFLUSH_H */
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/include/asm-frv/tlb.h linux-2.6.10-rc1-mm3-frv/include/asm-frv/tlb.h
--- /warthog/kernels/linux-2.6.10-rc1-mm3/include/asm-frv/tlb.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/include/asm-frv/tlb.h	2004-11-05 14:13:04.287463342 +0000
@@ -0,0 +1,23 @@
+#ifndef _ASM_TLB_H
+#define _ASM_TLB_H
+
+#include <asm/tlbflush.h>
+
+#define check_pgt_cache() do {} while(0)
+
+/*
+ * we don't need any special per-pte or per-vma handling...
+ */
+#define tlb_start_vma(tlb, vma)				do { } while (0)
+#define tlb_end_vma(tlb, vma)				do { } while (0)
+#define __tlb_remove_tlb_entry(tlb, ptep, address)	do { } while (0)
+
+/*
+ * .. because we flush the whole mm when it fills up
+ */
+#define tlb_flush(tlb)		flush_tlb_mm((tlb)->mm)
+
+#include <asm-generic/tlb.h>
+
+#endif /* _ASM_TLB_H */
+
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/include/asm-frv/topology.h linux-2.6.10-rc1-mm3-frv/include/asm-frv/topology.h
--- /warthog/kernels/linux-2.6.10-rc1-mm3/include/asm-frv/topology.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/include/asm-frv/topology.h	2004-11-05 14:13:04.290463088 +0000
@@ -0,0 +1,14 @@
+#ifndef _ASM_TOPOLOGY_H
+#define _ASM_TOPOLOGY_H
+
+#ifdef CONFIG_NUMA
+
+#error NUMA not supported yet
+
+#else /* !CONFIG_NUMA */
+
+#include <asm-generic/topology.h>
+
+#endif /* CONFIG_NUMA */
+
+#endif /* _ASM_TOPOLOGY_H */
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/include/asm-frv/types.h linux-2.6.10-rc1-mm3-frv/include/asm-frv/types.h
--- /warthog/kernels/linux-2.6.10-rc1-mm3/include/asm-frv/types.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/include/asm-frv/types.h	2004-11-05 14:13:04.294462751 +0000
@@ -0,0 +1,74 @@
+/* types.h: FRV types
+ *
+ * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * 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.
+ */
+
+#ifndef _ASM_TYPES_H
+#define _ASM_TYPES_H
+
+#ifndef __ASSEMBLY__
+
+typedef unsigned short umode_t;
+
+/*
+ * __xx is ok: it doesn't pollute the POSIX namespace. Use these in the
+ * header files exported to user space
+ */
+
+typedef __signed__ char __s8;
+typedef unsigned char __u8;
+
+typedef __signed__ short __s16;
+typedef unsigned short __u16;
+
+typedef __signed__ int __s32;
+typedef unsigned int __u32;
+
+#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
+typedef __signed__ long long __s64;
+typedef unsigned long long __u64;
+#endif
+
+#endif /* __ASSEMBLY__ */
+
+/*
+ * These aren't exported outside the kernel to avoid name space clashes
+ */
+#ifdef __KERNEL__
+
+#define BITS_PER_LONG 32
+
+#ifndef __ASSEMBLY__
+
+#include <linux/config.h>
+
+typedef signed char s8;
+typedef unsigned char u8;
+
+typedef signed short s16;
+typedef unsigned short u16;
+
+typedef signed int s32;
+typedef unsigned int u32;
+
+typedef signed long long s64;
+typedef unsigned long long u64;
+typedef u64 u_quad_t;
+
+/* Dma addresses are 32-bits wide.  */
+
+typedef u32 dma_addr_t;
+
+typedef unsigned short kmem_bufctl_t;
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* __KERNEL__ */
+
+#endif /* _ASM_TYPES_H */
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/include/asm-frv/uaccess.h linux-2.6.10-rc1-mm3-frv/include/asm-frv/uaccess.h
--- /warthog/kernels/linux-2.6.10-rc1-mm3/include/asm-frv/uaccess.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/include/asm-frv/uaccess.h	2004-11-05 14:13:04.299462328 +0000
@@ -0,0 +1,317 @@
+/* uaccess.h: userspace accessor functions
+ *
+ * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * 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.
+ */
+
+#ifndef _ASM_UACCESS_H
+#define _ASM_UACCESS_H
+
+/*
+ * User space memory access functions
+ */
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <asm/segment.h>
+#include <asm/sections.h>
+
+#define HAVE_ARCH_UNMAPPED_AREA	/* we decide where to put mmaps */
+
+#define __ptr(x) ((unsigned long *)(x))
+
+#define VERIFY_READ	0
+#define VERIFY_WRITE	1
+
+#define __addr_ok(addr) ((unsigned long)(addr) < get_addr_limit())
+
+/*
+ * check that a range of addresses falls within the current address limit
+ */
+static inline int ___range_ok(unsigned long addr, unsigned long size)
+{
+#ifdef CONFIG_MMU
+	int flag = -EFAULT, tmp;
+
+	asm volatile (
+		"	addcc	%3,%2,%1,icc0	\n"	/* set C-flag if addr+size>4GB */
+		"	subcc.p	%1,%4,gr0,icc1	\n"	/* jump if addr+size>limit */
+		"	bc	icc0,#0,0f	\n"
+		"	bhi	icc1,#0,0f	\n"
+		"	setlos	#0,%0		\n"	/* mark okay */
+		"0:				\n"
+		: "=r"(flag), "=&r"(tmp)
+		: "r"(addr), "r"(size), "r"(get_addr_limit()), "0"(flag)
+		);
+
+	return flag;
+
+#else
+
+	if (addr < memory_start ||
+	    addr > memory_end ||
+	    size > memory_end - memory_start ||
+	    addr + size > memory_end)
+		return -EFAULT;
+
+	return 0;
+#endif
+}
+
+#define __range_ok(addr,size) ___range_ok((unsigned long) (addr), (unsigned long) (size))
+
+#define access_ok(type,addr,size) (__range_ok((addr), (size)) == 0)
+#define __access_ok(addr,size) (__range_ok((addr), (size)) == 0)
+
+static inline int verify_area(int type, const void * addr, unsigned long size)
+{
+	return __range_ok(addr, size);
+}
+
+/*
+ * The exception table consists of pairs of addresses: the first is the
+ * address of an instruction that is allowed to fault, and the second is
+ * the address at which the program should continue.  No registers are
+ * modified, so it is entirely up to the continuation code to figure out
+ * what to do.
+ *
+ * All the routines below use bits of fixup code that are out of line
+ * with the main instruction path.  This means when everything is well,
+ * we don't even have to jump over them.  Further, they do not intrude
+ * on our cache or tlb entries.
+ */
+struct exception_table_entry
+{
+	unsigned long insn, fixup;
+};
+
+/* Returns 0 if exception not found and fixup otherwise.  */
+extern unsigned long search_exception_table(unsigned long);
+
+
+/*
+ * These are the main single-value transfer routines.  They automatically
+ * use the right size if we just have the right pointer type.
+ */
+#define __put_user(x, ptr)						\
+({									\
+	int __pu_err = 0;						\
+									\
+	typeof(*(ptr)) __pu_val = (x);					\
+									\
+	switch (sizeof (*(ptr))) {					\
+	case 1:								\
+		__put_user_asm(__pu_err, __pu_val, ptr, "b", "r");	\
+		break;							\
+	case 2:								\
+		__put_user_asm(__pu_err, __pu_val, ptr, "h", "r");	\
+		break;							\
+	case 4:								\
+		__put_user_asm(__pu_err, __pu_val, ptr, "",  "r");	\
+		break;							\
+	case 8:								\
+		__put_user_asm(__pu_err, __pu_val, ptr, "d", "e");	\
+		break;							\
+	default:							\
+		__pu_err = __put_user_bad();				\
+		break;							\
+	}								\
+	__pu_err;							\
+})
+
+#define put_user(x, ptr)			\
+({						\
+	typeof(&*ptr) _p = (ptr);		\
+	int _e;					\
+						\
+	_e = __range_ok(_p, sizeof(*_p));	\
+	if (_e == 0)				\
+		_e = __put_user((x), _p);	\
+	_e;					\
+})
+
+extern int __put_user_bad(void);
+
+/*
+ * Tell gcc we read from memory instead of writing: this is because
+ * we do not write to any memory gcc knows about, so there are no
+ * aliasing issues.
+ */
+
+#ifdef CONFIG_MMU
+
+#define __put_user_asm(err,x,ptr,dsize,constraint)					\
+do {											\
+	asm volatile("1:	st"dsize"%I1	%2,%M1	\n"				\
+		     "2:				\n"				\
+		     ".subsection 2			\n"				\
+		     "3:	setlos		%3,%0	\n"				\
+		     "		bra		2b	\n"				\
+		     ".previous				\n"				\
+		     ".section __ex_table,\"a\"		\n"				\
+		     "		.balign		8	\n"				\
+		     "		.long		1b,3b	\n"				\
+		     ".previous"							\
+		     : "=r" (err)							\
+		     : "m" (*__ptr(ptr)), constraint (x), "i"(-EFAULT), "0"(err)	\
+		     : "memory");							\
+} while (0)
+
+#else
+
+#define __put_user_asm(err,x,ptr,bwl,con)	\
+do {						\
+	asm("	st"bwl"%I0	%1,%M0	\n"	\
+	    "	membar			\n"	\
+	    :					\
+	    : "m" (*__ptr(ptr)), con (x)	\
+	    : "memory");			\
+} while (0)
+
+#endif
+
+/*****************************************************************************/
+/*
+ *
+ */
+#define __get_user(x, ptr)						\
+({									\
+	typeof(*(ptr)) __gu_val = 0;					\
+	int __gu_err = 0;						\
+									\
+	switch (sizeof(*(ptr))) {					\
+	case 1:								\
+		__get_user_asm(__gu_err, __gu_val, ptr, "ub", "=r");	\
+		break;							\
+	case 2:								\
+		__get_user_asm(__gu_err, __gu_val, ptr, "uh", "=r");	\
+		break;							\
+	case 4:								\
+		__get_user_asm(__gu_err, __gu_val, ptr, "", "=r");	\
+		break;							\
+	case 8:								\
+		__get_user_asm(__gu_err, __gu_val, ptr, "d", "=e");	\
+		break;							\
+	default:							\
+		__gu_err = __get_user_bad();				\
+		break;							\
+	}								\
+	(x) = __gu_val;							\
+	__gu_err;							\
+})
+
+#define get_user(x, ptr)			\
+({						\
+	typeof(&*ptr) _p = (ptr);		\
+	int _e;					\
+						\
+	_e = __range_ok(_p, sizeof(*_p));	\
+	if (likely(_e == 0))			\
+		_e = __get_user((x), _p);	\
+	else					\
+		(x) = (typeof(x)) 0;		\
+	_e;					\
+})
+
+extern int __get_user_bad(void);
+
+#ifdef CONFIG_MMU
+
+#define __get_user_asm(err,x,ptr,dtype,constraint)	\
+do {							\
+	asm("1:		ld"dtype"%I2	%M2,%1	\n"	\
+	    "2:					\n"	\
+	    ".subsection 2			\n"	\
+	    "3:		setlos		%3,%0	\n"	\
+	    "		setlos		#0,%1	\n"	\
+	    "		bra		2b	\n"	\
+	    ".previous				\n"	\
+	    ".section __ex_table,\"a\"		\n"	\
+	    "		.balign		8	\n"	\
+	    "		.long		1b,3b	\n"	\
+	    ".previous"					\
+	    : "=r" (err), constraint (x)		\
+	    : "m" (*__ptr(ptr)), "i"(-EFAULT), "0"(err)	\
+	    );						\
+} while(0)
+
+#else
+
+#define __get_user_asm(err,x,ptr,bwl,con)	\
+	asm("	ld"bwl"%I1	%M1,%0	\n"	\
+	    "	membar			\n"	\
+	    : con(x)				\
+	    : "m" (*__ptr(ptr)))
+
+#endif
+
+/*****************************************************************************/
+/*
+ *
+ */
+#ifdef CONFIG_MMU
+extern long __memset_user(void *dst, unsigned long count);
+extern long __memcpy_user(void *dst, const void *src, unsigned long count);
+
+#define clear_user(dst,count)			__memset_user((dst), (count))
+#define __copy_from_user_inatomic(to, from, n)	__memcpy_user((to), (from), (n))
+#define __copy_to_user_inatomic(to, from, n)	__memcpy_user((to), (from), (n))
+
+#else
+
+#define clear_user(dst,count)			(memset((dst), 0, (count)), 0)
+#define __copy_from_user_inatomic(to, from, n)	(memcpy((to), (from), (n)), 0)
+#define __copy_to_user_inatomic(to, from, n)	(memcpy((to), (from), (n)), 0)
+
+#endif
+
+static inline unsigned long __must_check
+__copy_to_user(void __user *to, const void *from, unsigned long n)
+{
+       might_sleep();
+       return __copy_to_user_inatomic(to, from, n);
+}
+
+static inline unsigned long
+__copy_from_user(void *to, const void __user *from, unsigned long n)
+{
+       might_sleep();
+       return __copy_from_user_inatomic(to, from, n);
+}
+
+static inline long copy_from_user(void *to, const void *from, unsigned long n)
+{
+	unsigned long ret = n;
+
+	if (likely(__access_ok(from, n)))
+		ret = __copy_from_user(to, from, n);
+
+	if (unlikely(ret != 0))
+		memset(to + (n - ret), 0, ret);
+
+	return ret;
+}
+
+static inline long copy_to_user(void *to, const void *from, unsigned long n)
+{
+	return likely(__access_ok(to, n)) ? __copy_to_user(to, from, n) : n;
+}
+
+#define copy_to_user_ret(to,from,n,retval)	({ if (copy_to_user(to,from,n)) return retval; })
+#define copy_from_user_ret(to,from,n,retval)	({ if (copy_from_user(to,from,n)) return retval; })
+
+extern long strncpy_from_user(char *dst, const char *src, long count);
+extern long strnlen_user(const char *src, long count);
+
+#define strlen_user(str) strnlen_user(str, 32767)
+
+extern unsigned long search_exception_table(unsigned long addr);
+
+#define copy_to_user_page(vma, page, vaddr, dst, src, len)	memcpy(dst, src, len)
+#define copy_from_user_page(vma, page, vaddr, dst, src, len)	memcpy(dst, src, len)
+
+#endif /* _ASM_UACCESS_H */
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/include/asm-frv/ucontext.h linux-2.6.10-rc1-mm3-frv/include/asm-frv/ucontext.h
--- /warthog/kernels/linux-2.6.10-rc1-mm3/include/asm-frv/ucontext.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/include/asm-frv/ucontext.h	2004-11-05 14:13:04.303461991 +0000
@@ -0,0 +1,12 @@
+#ifndef _ASM_UCONTEXT_H
+#define _ASM_UCONTEXT_H
+
+struct ucontext {
+	unsigned long		uc_flags;
+	struct ucontext		*uc_link;
+	stack_t			uc_stack;
+	struct sigcontext	uc_mcontext;
+	sigset_t		uc_sigmask;	/* mask last for extensibility */
+};
+
+#endif

^ permalink raw reply	[flat|nested] 87+ messages in thread

* [PATCH 16/20] FRV: Make calibrate_delay() optional
  2004-11-08 14:34 [PATCH 1/20] FRV: Fujitsu FR-V CPU arch maintainer record dhowells
                   ` (10 preceding siblings ...)
  2004-11-08 14:34 ` [PATCH 15/20] FRV: Fujitsu FR-V arch include files dhowells
@ 2004-11-08 14:34 ` dhowells
  2004-11-08 14:34 ` [PATCH 14/20] FRV: Fujitsu FR-V arch include files dhowells
                   ` (4 subsequent siblings)
  16 siblings, 0 replies; 87+ messages in thread
From: dhowells @ 2004-11-08 14:34 UTC (permalink / raw)
  To: torvalds, akpm, davidm; +Cc: linux-kernel, uclinux-dev

The attached patch makes calibrate_delay() optional. In this architecture, it's
a waste of time since we can predict exactly what it's going to come up with
just by looking at the CPU's hardware clock registers. Thus far, we haven't
seen a board with any clock not dependent on the CPU's clock.

Signed-Off-By: dhowells@redhat.com
---
diffstat calibrate-2610rc1mm3.diff
 arch/alpha/Kconfig         |    4 ++
 arch/arm/Kconfig           |    4 ++
 arch/arm26/Kconfig         |    4 ++
 arch/cris/Kconfig          |    4 ++
 arch/h8300/Kconfig         |    4 ++
 arch/i386/Kconfig          |    4 ++
 arch/ia64/Kconfig          |    4 ++
 arch/m32r/Kconfig          |    4 ++
 arch/m68k/Kconfig          |    4 ++
 arch/m68knommu/Kconfig     |    4 ++
 arch/mips/Kconfig          |    4 ++
 arch/parisc/Kconfig        |    4 ++
 arch/ppc/Kconfig           |    4 ++
 arch/ppc64/Kconfig         |    4 ++
 arch/s390/Kconfig          |    4 ++
 arch/sh/Kconfig            |    4 ++
 arch/sh64/Kconfig          |    4 ++
 arch/sparc/Kconfig         |    4 ++
 arch/sparc64/Kconfig       |    4 ++
 arch/um/Kconfig            |    4 ++
 arch/v850/Kconfig          |    3 +
 arch/x86_64/Kconfig        |    4 ++
 include/asm-m32r/smp.h     |    1 
 include/asm-x86_64/proto.h |    1 
 include/linux/delay.h      |    1 
 init/Makefile              |    2 +
 init/calibrate.c           |   79 +++++++++++++++++++++++++++++++++++++++++++++
 init/main.c                |   70 ---------------------------------------
 28 files changed, 169 insertions(+), 72 deletions(-)

diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/arch/alpha/Kconfig linux-2.6.10-rc1-mm3-frv/arch/alpha/Kconfig
--- /warthog/kernels/linux-2.6.10-rc1-mm3/arch/alpha/Kconfig	2004-10-19 10:41:41.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/arch/alpha/Kconfig	2004-11-05 14:13:03.000000000 +0000
@@ -28,6 +28,10 @@ config RWSEM_XCHGADD_ALGORITHM
 	bool
 	default y
 
+config GENERIC_CALIBRATE_DELAY
+	bool
+	default y
+
 config GENERIC_ISA_DMA
 	bool
 	default y
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/arch/arm/Kconfig linux-2.6.10-rc1-mm3-frv/arch/arm/Kconfig
--- /warthog/kernels/linux-2.6.10-rc1-mm3/arch/arm/Kconfig	2004-11-05 13:15:15.000000000 +0000
+++ linux-2.6.10-rc1-mm3-frv/arch/arm/Kconfig	2004-11-05 14:13:03.000000000 +0000
@@ -57,6 +57,10 @@ config RWSEM_GENERIC_SPINLOCK
 config RWSEM_XCHGADD_ALGORITHM
 	bool
 
+config GENERIC_CALIBRATE_DELAY
+	bool
+	default y
+
 config GENERIC_BUST_SPINLOCK
 	bool
 
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/arch/arm26/Kconfig linux-2.6.10-rc1-mm3-frv/arch/arm26/Kconfig
--- /warthog/kernels/linux-2.6.10-rc1-mm3/arch/arm26/Kconfig	2004-10-19 10:41:42.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/arch/arm26/Kconfig	2004-11-05 14:13:03.000000000 +0000
@@ -45,6 +45,10 @@ config RWSEM_GENERIC_SPINLOCK
 config RWSEM_XCHGADD_ALGORITHM
 	bool
 
+config GENERIC_CALIBRATE_DELAY
+	bool
+	default y
+
 config GENERIC_BUST_SPINLOCK
 	bool
 
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/arch/cris/Kconfig linux-2.6.10-rc1-mm3-frv/arch/cris/Kconfig
--- /warthog/kernels/linux-2.6.10-rc1-mm3/arch/cris/Kconfig	2004-10-19 10:41:42.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/arch/cris/Kconfig	2004-11-05 14:13:03.000000000 +0000
@@ -20,6 +20,10 @@ config RWSEM_GENERIC_SPINLOCK
 config RWSEM_XCHGADD_ALGORITHM
 	bool
 
+config GENERIC_CALIBRATE_DELAY
+	bool
+	default y
+
 config CRIS
 	bool
 	default y
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/arch/h8300/Kconfig linux-2.6.10-rc1-mm3-frv/arch/h8300/Kconfig
--- /warthog/kernels/linux-2.6.10-rc1-mm3/arch/h8300/Kconfig	2004-10-19 10:41:43.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/arch/h8300/Kconfig	2004-11-05 14:13:03.000000000 +0000
@@ -33,6 +33,10 @@ config RWSEM_XCHGADD_ALGORITHM
 	bool
 	default n
 
+config GENERIC_CALIBRATE_DELAY
+	bool
+	default y
+
 config ISA
 	bool
 	default y
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/arch/i386/Kconfig linux-2.6.10-rc1-mm3-frv/arch/i386/Kconfig
--- /warthog/kernels/linux-2.6.10-rc1-mm3/arch/i386/Kconfig	2004-11-05 13:15:17.000000000 +0000
+++ linux-2.6.10-rc1-mm3-frv/arch/i386/Kconfig	2004-11-05 14:13:03.000000000 +0000
@@ -373,6 +373,10 @@ config RWSEM_XCHGADD_ALGORITHM
 	depends on !M386
 	default y
 
+config GENERIC_CALIBRATE_DELAY
+	bool
+	default y
+
 config X86_PPRO_FENCE
 	bool
 	depends on M686 || M586MMX || M586TSC || M586 || M486 || M386
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/arch/ia64/Kconfig linux-2.6.10-rc1-mm3-frv/arch/ia64/Kconfig
--- /warthog/kernels/linux-2.6.10-rc1-mm3/arch/ia64/Kconfig	2004-11-05 13:15:18.000000000 +0000
+++ linux-2.6.10-rc1-mm3-frv/arch/ia64/Kconfig	2004-11-05 14:13:03.000000000 +0000
@@ -30,6 +30,10 @@ config RWSEM_XCHGADD_ALGORITHM
 	bool
 	default y
 
+config GENERIC_CALIBRATE_DELAY
+	bool
+	default y
+
 config TIME_INTERPOLATION
 	bool
 	default y
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/arch/m32r/Kconfig linux-2.6.10-rc1-mm3-frv/arch/m32r/Kconfig
--- /warthog/kernels/linux-2.6.10-rc1-mm3/arch/m32r/Kconfig	2004-10-19 10:41:44.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/arch/m32r/Kconfig	2004-11-05 14:13:03.000000000 +0000
@@ -189,6 +189,10 @@ config RWSEM_XCHGADD_ALGORITHM
 	bool
 	default n
 
+config GENERIC_CALIBRATE_DELAY
+	bool
+	default y
+
 config PREEMPT
 	bool "Preemptible Kernel"
 	help
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/arch/m68k/Kconfig linux-2.6.10-rc1-mm3-frv/arch/m68k/Kconfig
--- /warthog/kernels/linux-2.6.10-rc1-mm3/arch/m68k/Kconfig	2004-11-05 13:15:18.000000000 +0000
+++ linux-2.6.10-rc1-mm3-frv/arch/m68k/Kconfig	2004-11-05 14:13:03.000000000 +0000
@@ -21,6 +21,10 @@ config RWSEM_GENERIC_SPINLOCK
 config RWSEM_XCHGADD_ALGORITHM
 	bool
 
+config GENERIC_CALIBRATE_DELAY
+	bool
+	default y
+
 mainmenu "Linux/68k Kernel Configuration"
 
 source "init/Kconfig"
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/arch/m68knommu/Kconfig linux-2.6.10-rc1-mm3-frv/arch/m68knommu/Kconfig
--- /warthog/kernels/linux-2.6.10-rc1-mm3/arch/m68knommu/Kconfig	2004-11-05 13:15:18.000000000 +0000
+++ linux-2.6.10-rc1-mm3-frv/arch/m68knommu/Kconfig	2004-11-05 14:13:03.000000000 +0000
@@ -29,6 +29,10 @@ config RWSEM_XCHGADD_ALGORITHM
 	bool
 	default n
 
+config GENERIC_CALIBRATE_DELAY
+	bool
+	default y
+
 source "init/Kconfig"
 
 menu "Processor type and features"
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/arch/mips/Kconfig linux-2.6.10-rc1-mm3-frv/arch/mips/Kconfig
--- /warthog/kernels/linux-2.6.10-rc1-mm3/arch/mips/Kconfig	2004-10-19 10:41:44.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/arch/mips/Kconfig	2004-11-05 14:13:03.000000000 +0000
@@ -826,6 +826,10 @@ config RWSEM_GENERIC_SPINLOCK
 config RWSEM_XCHGADD_ALGORITHM
 	bool
 
+config GENERIC_CALIBRATE_DELAY
+	bool
+	default y
+
 config HAVE_DEC_LOCK
 	bool
 	default y
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/arch/parisc/Kconfig linux-2.6.10-rc1-mm3-frv/arch/parisc/Kconfig
--- /warthog/kernels/linux-2.6.10-rc1-mm3/arch/parisc/Kconfig	2004-10-19 10:41:45.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/arch/parisc/Kconfig	2004-11-05 14:13:03.000000000 +0000
@@ -32,6 +32,10 @@ config RWSEM_GENERIC_SPINLOCK
 config RWSEM_XCHGADD_ALGORITHM
 	bool
 
+config GENERIC_CALIBRATE_DELAY
+	bool
+	default y
+
 config GENERIC_ISA_DMA
 	bool
 
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/arch/ppc/Kconfig linux-2.6.10-rc1-mm3-frv/arch/ppc/Kconfig
--- /warthog/kernels/linux-2.6.10-rc1-mm3/arch/ppc/Kconfig	2004-11-05 13:15:20.000000000 +0000
+++ linux-2.6.10-rc1-mm3-frv/arch/ppc/Kconfig	2004-11-05 14:13:03.000000000 +0000
@@ -22,6 +22,10 @@ config RWSEM_XCHGADD_ALGORITHM
 	bool
 	default y
 
+config GENERIC_CALIBRATE_DELAY
+	bool
+	default y
+
 config HAVE_DEC_LOCK
 	bool
 	default y
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/arch/ppc64/Kconfig linux-2.6.10-rc1-mm3-frv/arch/ppc64/Kconfig
--- /warthog/kernels/linux-2.6.10-rc1-mm3/arch/ppc64/Kconfig	2004-11-05 13:15:19.000000000 +0000
+++ linux-2.6.10-rc1-mm3-frv/arch/ppc64/Kconfig	2004-11-05 14:13:03.000000000 +0000
@@ -20,6 +20,10 @@ config RWSEM_XCHGADD_ALGORITHM
 	bool
 	default y
 
+config GENERIC_CALIBRATE_DELAY
+	bool
+	default y
+
 config GENERIC_ISA_DMA
 	bool
 	default y
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/arch/s390/Kconfig linux-2.6.10-rc1-mm3-frv/arch/s390/Kconfig
--- /warthog/kernels/linux-2.6.10-rc1-mm3/arch/s390/Kconfig	2004-10-19 10:41:47.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/arch/s390/Kconfig	2004-11-05 14:13:03.000000000 +0000
@@ -14,6 +14,10 @@ config RWSEM_XCHGADD_ALGORITHM
 	bool
 	default y
 
+config GENERIC_CALIBRATE_DELAY
+	bool
+	default y
+
 config GENERIC_BUST_SPINLOCK
 	bool
 
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/arch/sh/Kconfig linux-2.6.10-rc1-mm3-frv/arch/sh/Kconfig
--- /warthog/kernels/linux-2.6.10-rc1-mm3/arch/sh/Kconfig	2004-11-05 13:15:21.000000000 +0000
+++ linux-2.6.10-rc1-mm3-frv/arch/sh/Kconfig	2004-11-05 14:13:03.000000000 +0000
@@ -25,6 +25,10 @@ config RWSEM_GENERIC_SPINLOCK
 config RWSEM_XCHGADD_ALGORITHM
 	bool
 
+config GENERIC_CALIBRATE_DELAY
+	bool
+	default y
+
 source "init/Kconfig"
 
 menu "System type"
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/arch/sh64/Kconfig linux-2.6.10-rc1-mm3-frv/arch/sh64/Kconfig
--- /warthog/kernels/linux-2.6.10-rc1-mm3/arch/sh64/Kconfig	2004-10-19 10:41:47.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/arch/sh64/Kconfig	2004-11-05 14:13:03.000000000 +0000
@@ -25,6 +25,10 @@ config RWSEM_GENERIC_SPINLOCK
 	bool
 	default y
 
+config GENERIC_CALIBRATE_DELAY
+	bool
+	default y
+
 config LOG_BUF_SHIFT
 	int
 	default 14
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/arch/sparc/Kconfig linux-2.6.10-rc1-mm3-frv/arch/sparc/Kconfig
--- /warthog/kernels/linux-2.6.10-rc1-mm3/arch/sparc/Kconfig	2004-11-05 13:15:21.000000000 +0000
+++ linux-2.6.10-rc1-mm3-frv/arch/sparc/Kconfig	2004-11-05 14:13:03.000000000 +0000
@@ -207,6 +207,10 @@ config RWSEM_GENERIC_SPINLOCK
 config RWSEM_XCHGADD_ALGORITHM
 	bool
 
+config GENERIC_CALIBRATE_DELAY
+	bool
+	default y
+
 config SUN_PM
 	bool
 	default y
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/arch/sparc64/Kconfig linux-2.6.10-rc1-mm3-frv/arch/sparc64/Kconfig
--- /warthog/kernels/linux-2.6.10-rc1-mm3/arch/sparc64/Kconfig	2004-11-05 13:15:21.000000000 +0000
+++ linux-2.6.10-rc1-mm3-frv/arch/sparc64/Kconfig	2004-11-05 14:13:03.000000000 +0000
@@ -186,6 +186,10 @@ config RWSEM_XCHGADD_ALGORITHM
 	bool
 	default y
 
+config GENERIC_CALIBRATE_DELAY
+	bool
+	default y
+
 choice
 	prompt "SPARC64 Huge TLB Page Size"
 	depends on HUGETLB_PAGE
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/arch/um/Kconfig linux-2.6.10-rc1-mm3-frv/arch/um/Kconfig
--- /warthog/kernels/linux-2.6.10-rc1-mm3/arch/um/Kconfig	2004-11-05 13:15:22.000000000 +0000
+++ linux-2.6.10-rc1-mm3-frv/arch/um/Kconfig	2004-11-05 14:13:03.000000000 +0000
@@ -31,6 +31,10 @@ config RWSEM_GENERIC_SPINLOCK
 	bool
 	default y
 
+config GENERIC_CALIBRATE_DELAY
+	bool
+	default y
+
 menu "UML-specific options"
 
 config MODE_TT
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/arch/v850/Kconfig linux-2.6.10-rc1-mm3-frv/arch/v850/Kconfig
--- /warthog/kernels/linux-2.6.10-rc1-mm3/arch/v850/Kconfig	2004-10-19 10:41:49.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/arch/v850/Kconfig	2004-11-05 14:13:03.000000000 +0000
@@ -19,6 +19,9 @@ config RWSEM_GENERIC_SPINLOCK
 config RWSEM_XCHGADD_ALGORITHM
 	bool
 	default n
+config GENERIC_CALIBRATE_DELAY
+	bool
+	default y
 
 # Turn off some random 386 crap that can affect device config
 config ISA
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/arch/x86_64/Kconfig linux-2.6.10-rc1-mm3-frv/arch/x86_64/Kconfig
--- /warthog/kernels/linux-2.6.10-rc1-mm3/arch/x86_64/Kconfig	2004-11-05 13:15:23.000000000 +0000
+++ linux-2.6.10-rc1-mm3-frv/arch/x86_64/Kconfig	2004-11-05 14:13:03.000000000 +0000
@@ -41,6 +41,10 @@ config RWSEM_GENERIC_SPINLOCK
 config RWSEM_XCHGADD_ALGORITHM
 	bool
 
+config GENERIC_CALIBRATE_DELAY
+	bool
+	default y
+
 config X86_CMPXCHG
 	bool
 	default y
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/include/asm-m32r/smp.h linux-2.6.10-rc1-mm3-frv/include/asm-m32r/smp.h
--- /warthog/kernels/linux-2.6.10-rc1-mm3/include/asm-m32r/smp.h	2004-10-19 10:42:13.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/include/asm-m32r/smp.h	2004-11-05 14:13:04.000000000 +0000
@@ -92,7 +92,6 @@ static __inline__ unsigned int num_booti
 }
 
 extern void smp_send_timer(void);
-extern void calibrate_delay(void);
 extern unsigned long send_IPI_mask_phys(cpumask_t, int, int);
 
 #endif	/* not __ASSEMBLY__ */
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/include/asm-x86_64/proto.h linux-2.6.10-rc1-mm3-frv/include/asm-x86_64/proto.h
--- /warthog/kernels/linux-2.6.10-rc1-mm3/include/asm-x86_64/proto.h	2004-11-05 13:15:49.000000000 +0000
+++ linux-2.6.10-rc1-mm3-frv/include/asm-x86_64/proto.h	2004-11-05 14:13:04.000000000 +0000
@@ -25,7 +25,6 @@ extern void ia32_syscall(void);
 extern void ia32_cstar_target(void); 
 extern void ia32_sysenter_target(void); 
 
-extern void calibrate_delay(void);
 extern void cpu_idle(void);
 extern void config_acpi_tables(void);
 extern void ia32_syscall(void);
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/include/linux/delay.h linux-2.6.10-rc1-mm3-frv/include/linux/delay.h
--- /warthog/kernels/linux-2.6.10-rc1-mm3/include/linux/delay.h	2004-10-19 10:42:16.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/include/linux/delay.h	2004-11-05 14:13:04.380455487 +0000
@@ -38,6 +38,7 @@ extern unsigned long loops_per_jiffy;
 #define ndelay(x)	udelay(((x)+999)/1000)
 #endif
 
+void calibrate_delay(void);
 void msleep(unsigned int msecs);
 unsigned long msleep_interruptible(unsigned int msecs);
 
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/init/calibrate.c linux-2.6.10-rc1-mm3-frv/init/calibrate.c
--- /warthog/kernels/linux-2.6.10-rc1-mm3/init/calibrate.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/init/calibrate.c	2004-11-05 14:13:04.000000000 +0000
@@ -0,0 +1,79 @@
+/* calibrate.c: default delay calibration
+ *
+ * Excised from init/main.c
+ *  Copyright (C) 1991, 1992  Linus Torvalds
+ */
+
+#include <linux/sched.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+
+static unsigned long preset_lpj;
+static int __init lpj_setup(char *str)
+{
+	preset_lpj = simple_strtoul(str,NULL,0);
+	return 1;
+}
+
+__setup("lpj=", lpj_setup);
+
+/*
+ * This is the number of bits of precision for the loops_per_jiffy.  Each
+ * bit takes on average 1.5/HZ seconds.  This (like the original) is a little
+ * better than 1%
+ */
+#define LPS_PREC 8
+
+void __devinit calibrate_delay(void)
+{
+	unsigned long ticks, loopbit;
+	int lps_precision = LPS_PREC;
+
+	if (preset_lpj) {
+		loops_per_jiffy = preset_lpj;
+		printk("Calibrating delay loop (skipped)... "
+			"%lu.%02lu BogoMIPS preset\n",
+			loops_per_jiffy/(500000/HZ),
+			(loops_per_jiffy/(5000/HZ)) % 100);
+	} else {
+		loops_per_jiffy = (1<<12);
+
+		printk(KERN_DEBUG "Calibrating delay loop... ");
+		while ((loops_per_jiffy <<= 1) != 0) {
+			/* wait for "start of" clock tick */
+			ticks = jiffies;
+			while (ticks == jiffies)
+				/* nothing */;
+			/* Go .. */
+			ticks = jiffies;
+			__delay(loops_per_jiffy);
+			ticks = jiffies - ticks;
+			if (ticks)
+				break;
+		}
+
+		/*
+		 * Do a binary approximation to get loops_per_jiffy set to
+		 * equal one clock (up to lps_precision bits)
+		 */
+		loops_per_jiffy >>= 1;
+		loopbit = loops_per_jiffy;
+		while (lps_precision-- && (loopbit >>= 1)) {
+			loops_per_jiffy |= loopbit;
+			ticks = jiffies;
+			while (ticks == jiffies)
+				/* nothing */;
+			ticks = jiffies;
+			__delay(loops_per_jiffy);
+			if (jiffies != ticks)	/* longer than 1 tick */
+				loops_per_jiffy &= ~loopbit;
+		}
+
+		/* Round the value and print it */
+		printk("%lu.%02lu BogoMIPS (lpj=%lu)\n",
+			loops_per_jiffy/(500000/HZ),
+			(loops_per_jiffy/(5000/HZ)) % 100,
+			loops_per_jiffy);
+	}
+
+}
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/init/main.c linux-2.6.10-rc1-mm3-frv/init/main.c
--- /warthog/kernels/linux-2.6.10-rc1-mm3/init/main.c	2004-11-05 13:15:51.000000000 +0000
+++ linux-2.6.10-rc1-mm3-frv/init/main.c	2004-11-05 14:13:04.499445437 +0000
@@ -184,15 +179,6 @@ static int __init obsolete_checksetup(ch
 	return 0;
 }
 
-static unsigned long preset_lpj;
-static int __init lpj_setup(char *str)
-{
-	preset_lpj = simple_strtoul(str,NULL,0);
-	return 1;
-}
-
-__setup("lpj=", lpj_setup);
-
 /*
  * This should be approx 2 Bo*oMips to start (note initial shift), and will
  * still work even if initially too large, it will just take slightly longer
@@ -201,67 +191,6 @@ unsigned long loops_per_jiffy = (1<<12);
 
 EXPORT_SYMBOL(loops_per_jiffy);
 
-/*
- * This is the number of bits of precision for the loops_per_jiffy.  Each
- * bit takes on average 1.5/HZ seconds.  This (like the original) is a little
- * better than 1%
- */
-#define LPS_PREC 8
-
-void __devinit calibrate_delay(void)
-{
-	unsigned long ticks, loopbit;
-	int lps_precision = LPS_PREC;
-
-	if (preset_lpj) {
-		loops_per_jiffy = preset_lpj;
-		printk("Calibrating delay loop (skipped)... "
-			"%lu.%02lu BogoMIPS preset\n",
-			loops_per_jiffy/(500000/HZ),
-			(loops_per_jiffy/(5000/HZ)) % 100);
-	} else {
-		loops_per_jiffy = (1<<12);
-
-		printk(KERN_DEBUG "Calibrating delay loop... ");
-		while ((loops_per_jiffy <<= 1) != 0) {
-			/* wait for "start of" clock tick */
-			ticks = jiffies;
-			while (ticks == jiffies)
-				/* nothing */;
-			/* Go .. */
-			ticks = jiffies;
-			__delay(loops_per_jiffy);
-			ticks = jiffies - ticks;
-			if (ticks)
-				break;
-		}
-
-		/*
-		 * Do a binary approximation to get loops_per_jiffy set to
-		 * equal one clock (up to lps_precision bits)
-		 */
-		loops_per_jiffy >>= 1;
-		loopbit = loops_per_jiffy;
-		while (lps_precision-- && (loopbit >>= 1)) {
-			loops_per_jiffy |= loopbit;
-			ticks = jiffies;
-			while (ticks == jiffies)
-				/* nothing */;
-			ticks = jiffies;
-			__delay(loops_per_jiffy);
-			if (jiffies != ticks)	/* longer than 1 tick */
-				loops_per_jiffy &= ~loopbit;
-		}
-
-		/* Round the value and print it */
-		printk("%lu.%02lu BogoMIPS (lpj=%lu)\n",
-			loops_per_jiffy/(500000/HZ),
-			(loops_per_jiffy/(5000/HZ)) % 100,
-			loops_per_jiffy);
-	}
-
-}
-
 static int __init debug_kernel(char *str)
 {
 	if (*str)
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/init/Makefile linux-2.6.10-rc1-mm3-frv/init/Makefile
--- /warthog/kernels/linux-2.6.10-rc1-mm3/init/Makefile	2004-06-18 13:42:40.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/init/Makefile	2004-11-05 14:13:04.504445015 +0000
@@ -3,6 +3,8 @@
 #
 
 obj-y				:= main.o version.o mounts.o initramfs.o
+obj-$(CONFIG_GENERIC_CALIBRATE_DELAY) += calibrate.o
+
 mounts-y			:= do_mounts.o
 mounts-$(CONFIG_DEVFS_FS)	+= do_mounts_devfs.o
 mounts-$(CONFIG_BLK_DEV_RAM)	+= do_mounts_rd.o

^ permalink raw reply	[flat|nested] 87+ messages in thread

* [PATCH 20/20] FRV: Add FDPIC ELF binary format driver
  2004-11-08 14:34 [PATCH 1/20] FRV: Fujitsu FR-V CPU arch maintainer record dhowells
                   ` (14 preceding siblings ...)
  2004-11-08 14:34 ` [PATCH 18/20] FRV: procfs changes for nommu changes dhowells
@ 2004-11-08 14:34 ` dhowells
  2004-11-08 14:34 ` [PATCH 19/20] FRV: change setup_arg_pages() to take stack pointer dhowells
  16 siblings, 0 replies; 87+ messages in thread
From: dhowells @ 2004-11-08 14:34 UTC (permalink / raw)
  To: torvalds, akpm, davidm; +Cc: linux-kernel, uclinux-dev

The attached patch adds a new binary format driver that allows a special
variety of ELF to be used that permits the dynamic sections that comprise an
executable, its dynamic loader and its shared libaries and its stack and data
to be located anywhere within the address space.

This is used to provide shared libraries and shared executables (at least, as
far as the read-only dynamic sections go) on uClinux. Not only that, but the
same binaries can be run on MMU linux without a problem.

This is achieved by:

 (1) Passing loadmaps to the dynamic loader (or to a statically linked
     executable) to indicate the whereabouts of the various dynamic sections.

 (2) Using a GOT inside the program.

 (3) Passing setup_arg_pages() the stack pointer to be.

 (4) Allowing the arch greated control over how an executable is laid out in
     memory in MMU Linux.

 (5) Rewriting mm/nommu.c to support MAP_PRIVATE on files, thus allowing _mmap_
     to handle sharing of private-readonly mappings.

Signed-Off-By: dhowells@redhat.com
---
diffstat binfmt-elf-fdpic-2610rc1mm3.diff
 fs/Kconfig.binfmt           |   13 
 fs/Makefile                 |    1 
 fs/binfmt_elf_fdpic.c       | 1093 ++++++++++++++++++++++++++++++++++++++++++++
 include/linux/elf-fdpic.h   |   68 ++
 include/linux/personality.h |    4 
 5 files changed, 1179 insertions(+)

diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/fs/binfmt_elf_fdpic.c linux-2.6.10-rc1-mm3-frv/fs/binfmt_elf_fdpic.c
--- /warthog/kernels/linux-2.6.10-rc1-mm3/fs/binfmt_elf_fdpic.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/fs/binfmt_elf_fdpic.c	2004-11-05 14:13:03.730510384 +0000
@@ -0,0 +1,1093 @@
+/* binfmt_elf_fdpic.c: FDPIC ELF binary format
+ *
+ * Copyright (C) 2003, 2004 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ * Derived from binfmt_elf.c
+ *
+ * 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.
+ */
+
+#include <linux/module.h>
+
+#include <linux/fs.h>
+#include <linux/stat.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/mman.h>
+#include <linux/errno.h>
+#include <linux/signal.h>
+#include <linux/binfmts.h>
+#include <linux/string.h>
+#include <linux/file.h>
+#include <linux/fcntl.h>
+#include <linux/slab.h>
+#include <linux/highmem.h>
+#include <linux/personality.h>
+#include <linux/ptrace.h>
+#include <linux/init.h>
+#include <linux/smp_lock.h>
+#include <linux/elf.h>
+#include <linux/elf-fdpic.h>
+#include <linux/elfcore.h>
+
+#include <asm/uaccess.h>
+#include <asm/param.h>
+#include <asm/pgalloc.h>
+
+typedef char *elf_caddr_t;
+#ifndef elf_addr_t
+#define elf_addr_t unsigned long
+#endif
+
+#if 0
+#define kdebug(fmt, ...) printk("FDPIC "fmt"\n" ,##__VA_ARGS__ )
+#else
+#define kdebug(fmt, ...) do {} while(0)
+#endif
+
+MODULE_LICENSE("GPL");
+
+static int load_elf_fdpic_binary(struct linux_binprm *bprm, struct pt_regs *regs);
+//static int load_elf_fdpic_library(struct file *);
+static int elf_fdpic_fetch_phdrs(struct elf_fdpic_params *params, struct file *file);
+static int elf_fdpic_map_file(struct elf_fdpic_params *params,
+			      struct file *file,
+			      struct mm_struct *mm,
+			      const char *what);
+
+static int create_elf_fdpic_tables(struct linux_binprm *bprm,
+				   struct mm_struct *mm,
+				   struct elf_fdpic_params *exec_params,
+				   struct elf_fdpic_params *interp_params);
+
+#ifndef CONFIG_MMU
+static int elf_fdpic_transfer_args_to_stack(struct linux_binprm *bprm, unsigned long *_sp);
+static int elf_fdpic_map_file_constdisp_on_uclinux(struct elf_fdpic_params *params,
+						   struct file *file,
+						   struct mm_struct *mm);
+#endif
+
+static int elf_fdpic_map_file_by_direct_mmap(struct elf_fdpic_params *params,
+					     struct file *file,
+					     struct mm_struct *mm);
+
+static struct linux_binfmt elf_fdpic_format = {
+	.module		= THIS_MODULE,
+	.load_binary	= load_elf_fdpic_binary,
+//	.load_shlib	= load_elf_fdpic_library,
+//	.core_dump	= elf_fdpic_core_dump,
+	.min_coredump	= ELF_EXEC_PAGESIZE,
+};
+
+static int __init init_elf_fdpic_binfmt(void)  { return register_binfmt(&elf_fdpic_format); }
+static void __exit exit_elf_fdpic_binfmt(void) { unregister_binfmt(&elf_fdpic_format); }
+
+module_init(init_elf_fdpic_binfmt)
+module_exit(exit_elf_fdpic_binfmt)
+
+static int is_elf_fdpic(struct elfhdr *hdr, struct file *file)
+{
+	if (memcmp(hdr->e_ident, ELFMAG, SELFMAG) != 0)
+		return 0;
+	if (hdr->e_type != ET_EXEC && hdr->e_type != ET_DYN)
+		return 0;
+	if (!elf_check_arch(hdr) || !elf_check_fdpic(hdr))
+		return 0;
+	if (!file->f_op || !file->f_op->mmap)
+		return 0;
+	return 1;
+}
+
+/*****************************************************************************/
+/*
+ * read the program headers table into memory
+ */
+static int elf_fdpic_fetch_phdrs(struct elf_fdpic_params *params, struct file *file)
+{
+	struct elf32_phdr *phdr;
+	unsigned long size;
+	int retval, loop;
+
+	if (params->hdr.e_phentsize != sizeof(struct elf_phdr))
+		return -ENOMEM;
+	if (params->hdr.e_phnum > 65536U / sizeof(struct elf_phdr))
+		return -ENOMEM;
+
+	size = params->hdr.e_phnum * sizeof(struct elf_phdr);
+	params->phdrs = kmalloc(size, GFP_KERNEL);
+	if (!params->phdrs)
+		return -ENOMEM;
+
+	retval = kernel_read(file, params->hdr.e_phoff, (char *) params->phdrs, size);
+	if (retval < 0)
+		return retval;
+
+	/* determine stack size for this binary */
+	phdr = params->phdrs;
+	for (loop = 0; loop < params->hdr.e_phnum; loop++, phdr++) {
+		if (phdr->p_type != PT_GNU_STACK)
+			continue;
+
+		if (phdr->p_flags & PF_X)
+			params->flags |= ELF_FDPIC_FLAG_EXEC_STACK;
+		else
+			params->flags |= ELF_FDPIC_FLAG_NOEXEC_STACK;
+
+		params->stack_size = phdr->p_memsz;
+		break;
+	}
+
+	return 0;
+} /* end elf_fdpic_fetch_phdrs() */
+
+/*****************************************************************************/
+/*
+ * load an fdpic binary into various bits of memory
+ */
+static int load_elf_fdpic_binary(struct linux_binprm *bprm, struct pt_regs *regs)
+{
+	struct elf_fdpic_params exec_params, interp_params;
+	struct elf_phdr *phdr;
+	unsigned long stack_size;
+	struct file *interpreter = NULL; /* to shut gcc up */
+	char *interpreter_name = NULL;
+	int executable_stack;
+	int retval, i;
+
+	memset(&exec_params, 0, sizeof(exec_params));
+	memset(&interp_params, 0, sizeof(interp_params));
+
+	exec_params.hdr = *(struct elfhdr *) bprm->buf;
+	exec_params.flags = ELF_FDPIC_FLAG_PRESENT | ELF_FDPIC_FLAG_EXECUTABLE;
+
+	/* check that this is a binary we know how to deal with */
+	retval = -ENOEXEC;
+	if (!is_elf_fdpic(&exec_params.hdr, bprm->file))
+		goto error;
+
+	/* read the program header table */
+	retval = elf_fdpic_fetch_phdrs(&exec_params, bprm->file);
+	if (retval < 0)
+		goto error;
+
+	/* scan for a program header that specifies an interpreter */
+	phdr = exec_params.phdrs;
+
+	for (i = 0; i < exec_params.hdr.e_phnum; i++, phdr++) {
+		switch (phdr->p_type) {
+		case PT_INTERP:
+			retval = -ENOMEM;
+			if (phdr->p_filesz > PATH_MAX)
+				goto error;
+			retval = -ENOENT;
+			if (phdr->p_filesz < 2)
+				goto error;
+
+			/* read the name of the interpreter into memory */
+			interpreter_name = (char *) kmalloc(phdr->p_filesz, GFP_KERNEL);
+			if (!interpreter_name)
+				goto error;
+
+			retval = kernel_read(bprm->file,
+					     phdr->p_offset,
+					     interpreter_name,
+					     phdr->p_filesz);
+			if (retval < 0)
+				goto error;
+
+			retval = -ENOENT;
+			if (interpreter_name[phdr->p_filesz - 1] != '\0')
+				goto error;
+
+			kdebug("Using ELF interpreter %s", interpreter_name);
+
+			/* replace the program with the interpreter */
+			interpreter = open_exec(interpreter_name);
+			retval = PTR_ERR(interpreter);
+			if (IS_ERR(interpreter)) {
+				interpreter = NULL;
+				goto error;
+			}
+
+			retval = kernel_read(interpreter, 0, bprm->buf, BINPRM_BUF_SIZE);
+			if (retval < 0)
+				goto error;
+
+			interp_params.hdr = *((struct elfhdr *) bprm->buf);
+			break;
+
+		case PT_LOAD:
+#ifdef CONFIG_MMU
+			if (exec_params.load_addr == 0)
+				exec_params.load_addr = phdr->p_vaddr;
+#endif
+			break;
+		}
+
+	}
+
+	if (elf_check_const_displacement(&exec_params.hdr))
+		exec_params.flags |= ELF_FDPIC_FLAG_CONSTDISP;
+
+	/* perform insanity checks on the interpreter */
+	if (interpreter_name) {
+		retval = -ELIBBAD;
+		if (!is_elf_fdpic(&interp_params.hdr, interpreter))
+			goto error;
+
+		interp_params.flags = ELF_FDPIC_FLAG_PRESENT;
+
+		/* read the interpreter's program header table */
+		retval = elf_fdpic_fetch_phdrs(&interp_params, interpreter);
+		if (retval < 0)
+			goto error;
+	}
+
+	stack_size = exec_params.stack_size;
+	if (stack_size < interp_params.stack_size)
+		stack_size = interp_params.stack_size;
+
+	if (exec_params.flags & ELF_FDPIC_FLAG_EXEC_STACK)
+		executable_stack = EXSTACK_ENABLE_X;
+	else if (exec_params.flags & ELF_FDPIC_FLAG_NOEXEC_STACK)
+		executable_stack = EXSTACK_DISABLE_X;
+	else if (interp_params.flags & ELF_FDPIC_FLAG_EXEC_STACK)
+		executable_stack = EXSTACK_ENABLE_X;
+	else if (interp_params.flags & ELF_FDPIC_FLAG_NOEXEC_STACK)
+		executable_stack = EXSTACK_DISABLE_X;
+	else
+		executable_stack = EXSTACK_DEFAULT;
+
+	retval = -ENOEXEC;
+	if (stack_size == 0)
+		goto error;
+
+	if (elf_check_const_displacement(&interp_params.hdr))
+		interp_params.flags |= ELF_FDPIC_FLAG_CONSTDISP;
+
+	/* flush all traces of the currently running executable */
+	retval = flush_old_exec(bprm);
+	if (retval)
+		goto error;
+
+	/* there's now no turning back... the old userspace image is dead,
+	 * defunct, deceased, etc. after this point we have to exit via
+	 * error_kill */
+	set_personality(PER_LINUX_FDPIC);
+	set_binfmt(&elf_fdpic_format);
+
+	current->mm->start_code = 0;
+	current->mm->end_code = 0;
+	current->mm->start_stack = 0;
+	current->mm->start_data = 0;
+	current->mm->end_data = 0;
+	current->mm->context.exec_fdpic_loadmap = 0;
+	current->mm->context.interp_fdpic_loadmap = 0;
+
+	current->flags &= ~PF_FORKNOEXEC;
+
+#ifdef CONFIG_MMU
+	elf_fdpic_arch_lay_out_mm(&exec_params,
+				  &interp_params,
+				  &current->mm->start_stack,
+				  &current->mm->start_brk);
+#endif
+
+	/* do this so that we can load the interpreter, if need be
+	 * - we will change some of these later
+	 */
+	current->mm->rss = 0;
+
+#ifdef CONFIG_MMU
+	retval = setup_arg_pages(bprm, current->mm->start_stack, executable_stack);
+	if (retval < 0) {
+		send_sig(SIGKILL, current, 0);
+		goto error_kill;
+	}
+#endif
+
+	/* load the executable and interpreter into memory */
+	retval = elf_fdpic_map_file(&exec_params, bprm->file, current->mm, "executable");
+	if (retval < 0)
+		goto error_kill;
+
+	if (interpreter_name) {
+		retval = elf_fdpic_map_file(&interp_params, interpreter, NULL, "interpreter");
+		if (retval < 0) {
+			printk(KERN_ERR "Unable to load interpreter\n");
+			goto error_kill;
+		}
+
+		allow_write_access(interpreter);
+		fput(interpreter);
+		interpreter = NULL;
+	}
+
+#ifdef CONFIG_MMU
+	if (!current->mm->start_brk)
+		current->mm->start_brk = current->mm->end_data;
+
+	current->mm->brk = current->mm->start_brk = PAGE_ALIGN(current->mm->start_brk);
+
+#else
+	/* create a stack and brk area big enough for everyone
+	 * - the brk heap starts at the bottom and works up
+	 * - the stack starts at the top and works down
+	 */
+	stack_size = (stack_size + PAGE_SIZE - 1) & PAGE_MASK;
+	if (stack_size < PAGE_SIZE * 2)
+		stack_size = PAGE_SIZE * 2;
+
+	current->mm->start_brk = do_mmap(NULL,
+					 0,
+					 stack_size,
+					 PROT_READ | PROT_WRITE | PROT_EXEC,
+					 MAP_PRIVATE | MAP_ANON | MAP_GROWSDOWN,
+					 0);
+
+	if (IS_ERR((void *) current->mm->start_brk)) {
+		retval = current->mm->start_brk;
+		current->mm->start_brk = 0;
+		goto error_kill;
+	}
+
+	down_write(&current->mm->mmap_sem);
+	if (do_mremap(current->mm->start_brk,
+		      stack_size,
+		      ksize((char *) current->mm->start_brk),
+		      0, 0
+		      ) == current->mm->start_brk
+	    )
+		stack_size = ksize((char *) current->mm->start_brk);
+	up_write(&current->mm->mmap_sem);
+
+	current->mm->brk = current->mm->start_brk;
+	current->mm->context.end_brk = current->mm->start_brk;
+	current->mm->context.end_brk += (stack_size > PAGE_SIZE) ? (stack_size - PAGE_SIZE) : 0;
+	current->mm->start_stack = current->mm->start_brk + stack_size;
+#endif
+
+	compute_creds(bprm);
+	current->flags &= ~PF_FORKNOEXEC;
+	if (create_elf_fdpic_tables(bprm, current->mm, &exec_params, &interp_params) < 0)
+		goto error_kill;
+
+	kdebug("- start_code  %lx",	(long) current->mm->start_code);
+	kdebug("- end_code    %lx",	(long) current->mm->end_code);
+	kdebug("- start_data  %lx",	(long) current->mm->start_data);
+	kdebug("- end_data    %lx",	(long) current->mm->end_data);
+	kdebug("- start_brk   %lx",	(long) current->mm->start_brk);
+	kdebug("- brk         %lx",	(long) current->mm->brk);
+#ifndef CONFIG_MMU
+	kdebug("- end_brk     %lx",	(long) current->mm->end_brk);
+#endif
+	kdebug("- start_stack %lx",	(long) current->mm->start_stack);
+
+#ifdef ELF_FDPIC_PLAT_INIT
+	/*
+	 * The ABI may specify that certain registers be set up in special
+	 * ways (on i386 %edx is the address of a DT_FINI function, for
+	 * example.  This macro performs whatever initialization to
+	 * the regs structure is required.
+	 */
+	ELF_FDPIC_PLAT_INIT(regs,
+			    exec_params.map_addr,
+			    interp_params.map_addr,
+			    interp_params.dynamic_addr ?: exec_params.dynamic_addr
+			    );
+#endif
+
+	/* everything is now ready... get the userspace context ready to roll */
+	start_thread(regs,
+		     interp_params.entry_addr ?: exec_params.entry_addr,
+		     current->mm->start_stack);
+
+	if (unlikely(current->ptrace & PT_PTRACED)) {
+		if (current->ptrace & PT_TRACE_EXEC)
+			ptrace_notify ((PTRACE_EVENT_EXEC << 8) | SIGTRAP);
+		else
+			send_sig(SIGTRAP, current, 0);
+	}
+
+	retval = 0;
+
+error:
+	if (interpreter) {
+		allow_write_access(interpreter);
+		fput(interpreter);
+	}
+	if (interpreter_name)
+		kfree(interpreter_name);
+	if (exec_params.phdrs)
+		kfree(exec_params.phdrs);
+	if (exec_params.loadmap)
+		kfree(exec_params.loadmap);
+	if (interp_params.phdrs)
+		kfree(interp_params.phdrs);
+	if (interp_params.loadmap)
+		kfree(interp_params.loadmap);
+	return retval;
+
+	/* unrecoverable error - kill the process */
+ error_kill:
+	send_sig(SIGSEGV, current, 0);
+	goto error;
+
+} /* end load_elf_fdpic_binary() */
+
+/*****************************************************************************/
+/*
+ * present useful information to the program
+ */
+static int create_elf_fdpic_tables(struct linux_binprm *bprm,
+				   struct mm_struct *mm,
+				   struct elf_fdpic_params *exec_params,
+				   struct elf_fdpic_params *interp_params)
+{
+	unsigned long sp, csp, nitems;
+	elf_caddr_t *argv, *envp;
+	size_t platform_len = 0, len;
+	char *k_platform, *u_platform, *p;
+	long hwcap;
+	int loop;
+
+	/* we're going to shovel a whole load of stuff onto the stack */
+#ifdef CONFIG_MMU
+	sp = bprm->p;
+#else
+	sp = mm->start_stack;
+
+	/* stack the program arguments and environment */
+	if (elf_fdpic_transfer_args_to_stack(bprm, &sp) < 0)
+		return -EFAULT;
+#endif
+
+	/* get hold of platform and hardware capabilities masks for the machine
+	 * we are running on.  In some cases (Sparc), this info is impossible
+	 * to get, in others (i386) it is merely difficult.
+	 */
+	hwcap = ELF_HWCAP;
+	k_platform = ELF_PLATFORM;
+
+	if (k_platform) {
+		platform_len = strlen(k_platform) + 1;
+		sp -= platform_len;
+		if (__copy_to_user(u_platform, k_platform, platform_len) != 0)
+			return -EFAULT;
+	}
+
+	u_platform = (char *) sp;
+
+#if defined(__i386__) && defined(CONFIG_SMP)
+	/* in some cases (e.g. Hyper-Threading), we want to avoid L1 evictions
+	 * by the processes running on the same package. One thing we can do
+	 * is to shuffle the initial stack for them.
+	 *
+	 * the conditionals here are unneeded, but kept in to make the
+	 * code behaviour the same as pre change unless we have hyperthreaded
+	 * processors. This keeps Mr Marcelo Person happier but should be
+	 * removed for 2.5
+	 */
+	if (smp_num_siblings > 1)
+		sp = sp - ((current->pid % 64) << 7);
+#endif
+
+	sp &= ~7UL;
+
+	/* stack the load map(s) */
+	len = sizeof(struct elf32_fdpic_loadmap);
+	len += sizeof(struct elf32_fdpic_loadseg) * exec_params->loadmap->nsegs;
+	sp = (sp - len) & ~7UL;
+	exec_params->map_addr = sp;
+
+	if (copy_to_user((void *) sp, exec_params->loadmap, len) != 0)
+		return -EFAULT;
+
+	current->mm->context.exec_fdpic_loadmap = (unsigned long) sp;
+
+	if (interp_params->loadmap) {
+		len = sizeof(struct elf32_fdpic_loadmap);
+		len += sizeof(struct elf32_fdpic_loadseg) * interp_params->loadmap->nsegs;
+		sp = (sp - len) & ~7UL;
+		interp_params->map_addr = sp;
+
+		if (copy_to_user((void *) sp, interp_params->loadmap, len) != 0)
+			return -EFAULT;
+
+		current->mm->context.interp_fdpic_loadmap = (unsigned long) sp;
+	}
+
+	/* force 16 byte _final_ alignment here for generality */
+#define DLINFO_ITEMS 13
+
+	nitems = 1 + DLINFO_ITEMS + (k_platform ? 1 : 0);
+#ifdef DLINFO_ARCH_ITEMS
+	nitems += DLINFO_ARCH_ITEMS;
+#endif
+
+	csp = sp;
+	sp -= nitems * 2 * sizeof(unsigned long);
+	sp -= (bprm->envc + 1) * sizeof(char *);	/* envv[] */
+	sp -= (bprm->argc + 1) * sizeof(char *);	/* argv[] */
+	sp -= 1 * sizeof(unsigned long);		/* argc */
+
+	csp -= sp & 15UL;
+	sp -= sp & 15UL;
+
+	/* put the ELF interpreter info on the stack */
+#define NEW_AUX_ENT(nr, id, val)						\
+	do {									\
+		struct { unsigned long _id, _val; } *ent = (void *) csp;	\
+		__put_user((id), &ent[nr]._id);					\
+		__put_user((val), &ent[nr]._val);				\
+	} while (0)
+
+	csp -= 2 * sizeof(unsigned long);
+	NEW_AUX_ENT(0, AT_NULL, 0);
+	if (k_platform) {
+		csp -= 2 * sizeof(unsigned long);
+		NEW_AUX_ENT(0, AT_PLATFORM, (elf_addr_t)(unsigned long) u_platform);
+	}
+
+	csp -= DLINFO_ITEMS * 2 * sizeof(unsigned long);
+	NEW_AUX_ENT( 0, AT_HWCAP,		hwcap);
+	NEW_AUX_ENT( 1, AT_PAGESZ,		PAGE_SIZE);
+	NEW_AUX_ENT( 2, AT_CLKTCK,		CLOCKS_PER_SEC);
+	NEW_AUX_ENT( 3, AT_PHDR,		exec_params->ph_addr);
+	NEW_AUX_ENT( 4, AT_PHENT,		sizeof(struct elf_phdr));
+	NEW_AUX_ENT( 5, AT_PHNUM,		exec_params->hdr.e_phnum);
+	NEW_AUX_ENT( 6,	AT_BASE,		interp_params->elfhdr_addr);
+	NEW_AUX_ENT( 7, AT_FLAGS,		0);
+	NEW_AUX_ENT( 8, AT_ENTRY,		exec_params->entry_addr);
+	NEW_AUX_ENT( 9, AT_UID,			(elf_addr_t) current->uid);
+	NEW_AUX_ENT(10, AT_EUID,		(elf_addr_t) current->euid);
+	NEW_AUX_ENT(11, AT_GID,			(elf_addr_t) current->gid);
+	NEW_AUX_ENT(12, AT_EGID,		(elf_addr_t) current->egid);
+
+#ifdef ARCH_DLINFO
+	/* ARCH_DLINFO must come last so platform specific code can enforce
+	 * special alignment requirements on the AUXV if necessary (eg. PPC).
+	 */
+	ARCH_DLINFO;
+#endif
+#undef NEW_AUX_ENT
+
+	/* allocate room for argv[] and envv[] */
+	csp -= (bprm->envc + 1) * sizeof(elf_caddr_t);
+	envp = (elf_caddr_t *) csp;
+	csp -= (bprm->argc + 1) * sizeof(elf_caddr_t);
+	argv = (elf_caddr_t *) csp;
+
+	/* stack argc */
+	csp -= sizeof(unsigned long);
+	__put_user(bprm->argc, (unsigned long *) csp);
+
+	if (csp != sp)
+		BUG();
+
+	/* fill in the argv[] array */
+#ifdef CONFIG_MMU
+	current->mm->arg_start = bprm->p;
+#else
+	current->mm->arg_start = current->mm->start_stack - (MAX_ARG_PAGES * PAGE_SIZE - bprm->p);
+#endif
+
+	p = (char *) current->mm->arg_start;
+	for (loop = bprm->argc; loop > 0; loop--) {
+		__put_user((elf_caddr_t) p, argv++);
+		len = strnlen_user(p, PAGE_SIZE * MAX_ARG_PAGES);
+		if (!len || len > PAGE_SIZE * MAX_ARG_PAGES)
+			return -EINVAL;
+		p += len;
+	}
+	__put_user(NULL, argv);
+	current->mm->arg_end = (unsigned long) p;
+
+	/* fill in the envv[] array */
+	current->mm->env_start = (unsigned long) p;
+	for (loop = bprm->envc; loop > 0; loop--) {
+		__put_user((elf_caddr_t)(unsigned long) p, envp++);
+		len = strnlen_user(p, PAGE_SIZE * MAX_ARG_PAGES);
+		if (!len || len > PAGE_SIZE * MAX_ARG_PAGES)
+			return -EINVAL;
+		p += len;
+	}
+	__put_user(NULL, envp);
+	current->mm->env_end = (unsigned long) p;
+
+	mm->start_stack = (unsigned long) sp;
+	return 0;
+} /* end create_elf_fdpic_tables() */
+
+/*****************************************************************************/
+/*
+ * transfer the program arguments and environment from the holding pages onto
+ * the stack
+ */
+#ifndef CONFIG_MMU
+static int elf_fdpic_transfer_args_to_stack(struct linux_binprm *bprm, unsigned long *_sp)
+{
+	unsigned long index, stop, sp;
+	char *src;
+	int ret = 0;
+
+	stop = bprm->p >> PAGE_SHIFT;
+	sp = *_sp;
+
+	for (index = MAX_ARG_PAGES - 1; index >= stop; index--) {
+		src = kmap(bprm->page[index]);
+		sp -= PAGE_SIZE;
+		if (copy_to_user((void *) sp, src, PAGE_SIZE) != 0)
+			ret = -EFAULT;
+		kunmap(bprm->page[index]);
+		if (ret < 0)
+			goto out;
+	}
+
+	*_sp = (*_sp - (MAX_ARG_PAGES * PAGE_SIZE - bprm->p)) & ~15;
+
+ out:
+	return ret;
+} /* end elf_fdpic_transfer_args_to_stack() */
+#endif
+
+/*****************************************************************************/
+/*
+ * load the appropriate binary image (executable or interpreter) into memory
+ * - we assume no MMU is available
+ * - if no other PIC bits are set in params->hdr->e_flags
+ *   - we assume that the LOADable segments in the binary are independently relocatable
+ *   - we assume R/O executable segments are shareable
+ * - else
+ *   - we assume the loadable parts of the image to require fixed displacement
+ *   - the image is not shareable
+ */
+static int elf_fdpic_map_file(struct elf_fdpic_params *params,
+			      struct file *file,
+			      struct mm_struct *mm,
+			      const char *what)
+{
+	struct elf32_fdpic_loadmap *loadmap;
+#ifdef CONFIG_MMU
+	struct elf32_fdpic_loadseg *mseg;
+#endif
+	struct elf32_fdpic_loadseg *seg;
+	struct elf32_phdr *phdr;
+	unsigned long load_addr, stop;
+	unsigned nloads, tmp;
+	size_t size;
+	int loop, ret;
+
+	/* allocate a load map table */
+	nloads = 0;
+	for (loop = 0; loop < params->hdr.e_phnum; loop++)
+		if (params->phdrs[loop].p_type == PT_LOAD)
+			nloads++;
+
+	if (nloads == 0)
+		return -ELIBBAD;
+
+	size = sizeof(*loadmap) + nloads * sizeof(*seg);
+	loadmap = kmalloc(size, GFP_KERNEL);
+	if (!loadmap)
+		return -ENOMEM;
+
+	params->loadmap = loadmap;
+	memset(loadmap, 0, size);
+
+	loadmap->version = ELF32_FDPIC_LOADMAP_VERSION;
+	loadmap->nsegs = nloads;
+
+	load_addr = params->load_addr;
+	seg = loadmap->segs;
+
+	/* map the requested LOADs into the memory space */
+	switch (params->flags & ELF_FDPIC_FLAG_ARRANGEMENT) {
+	case ELF_FDPIC_FLAG_CONSTDISP:
+	case ELF_FDPIC_FLAG_CONTIGUOUS:
+#ifndef CONFIG_MMU
+		ret = elf_fdpic_map_file_constdisp_on_uclinux(params, file, mm);
+		if (ret < 0)
+			return ret;
+		break;
+#endif
+	default:
+		ret = elf_fdpic_map_file_by_direct_mmap(params, file, mm);
+		if (ret < 0)
+			return ret;
+		break;
+	}
+
+	/* map the entry point */
+	if (params->hdr.e_entry) {
+		seg = loadmap->segs;
+		for (loop = loadmap->nsegs; loop > 0; loop--, seg++) {
+			if (params->hdr.e_entry >= seg->p_vaddr &&
+			    params->hdr.e_entry < seg->p_vaddr + seg->p_memsz
+			    ) {
+				params->entry_addr =
+					(params->hdr.e_entry - seg->p_vaddr) + seg->addr;
+				break;
+			}
+		}
+	}
+
+	/* determine where the program header table has wound up if mapped */
+	stop = params->hdr.e_phoff + params->hdr.e_phnum * sizeof (struct elf_phdr);
+	phdr = params->phdrs;
+
+	for (loop = 0; loop < params->hdr.e_phnum; loop++, phdr++) {
+		if (phdr->p_type != PT_LOAD)
+			continue;
+
+		if (phdr->p_offset > params->hdr.e_phoff ||
+		    phdr->p_offset + phdr->p_filesz < stop)
+			continue;
+
+		seg = loadmap->segs;
+		for (loop = loadmap->nsegs; loop > 0; loop--, seg++) {
+			if (phdr->p_vaddr >= seg->p_vaddr &&
+			    phdr->p_vaddr + phdr->p_filesz <= seg->p_vaddr + seg->p_memsz
+			    ) {
+				params->ph_addr = (phdr->p_vaddr - seg->p_vaddr) + seg->addr +
+					params->hdr.e_phoff - phdr->p_offset;
+				break;
+			}
+		}
+		break;
+	}
+
+	/* determine where the dynamic section has wound up if there is one */
+	phdr = params->phdrs;
+	for (loop = 0; loop < params->hdr.e_phnum; loop++, phdr++) {
+		if (phdr->p_type != PT_DYNAMIC)
+			continue;
+
+		seg = loadmap->segs;
+		for (loop = loadmap->nsegs; loop > 0; loop--, seg++) {
+			if (phdr->p_vaddr >= seg->p_vaddr &&
+			    phdr->p_vaddr + phdr->p_memsz <= seg->p_vaddr + seg->p_memsz
+			    ) {
+				params->dynamic_addr = (phdr->p_vaddr - seg->p_vaddr) + seg->addr;
+
+				/* check the dynamic section contains at least one item, and that
+				 * the last item is a NULL entry */
+				if (phdr->p_memsz == 0 ||
+				    phdr->p_memsz % sizeof(Elf32_Dyn) != 0)
+					goto dynamic_error;
+
+				tmp = phdr->p_memsz / sizeof(Elf32_Dyn);
+				if (((Elf32_Dyn *) params->dynamic_addr)[tmp - 1].d_tag != 0)
+					goto dynamic_error;
+				break;
+			}
+		}
+		break;
+	}
+
+	/* now elide adjacent segments in the load map on MMU linux
+	 * - on uClinux the holes between may actually be filled with system stuff or stuff from
+	 *   other processes
+	 */
+#ifdef CONFIG_MMU
+	nloads = loadmap->nsegs;
+	mseg = loadmap->segs;
+	seg = mseg + 1;
+	for (loop = 1; loop < nloads; loop++) {
+		/* see if we have a candidate for merging */
+		if (seg->p_vaddr - mseg->p_vaddr == seg->addr - mseg->addr) {
+			load_addr = PAGE_ALIGN(mseg->addr + mseg->p_memsz);
+			if (load_addr == (seg->addr & PAGE_MASK)) {
+				mseg->p_memsz += load_addr - (mseg->addr + mseg->p_memsz);
+				mseg->p_memsz += seg->addr & ~PAGE_MASK;
+				mseg->p_memsz += seg->p_memsz;
+				loadmap->nsegs--;
+				continue;
+			}
+		}
+
+		mseg++;
+		if (mseg != seg)
+			*mseg = *seg;
+	}
+#endif
+
+	kdebug("Mapped Object [%s]:", what);
+	kdebug("- elfhdr   : %lx", params->elfhdr_addr);
+	kdebug("- entry    : %lx", params->entry_addr);
+	kdebug("- PHDR[]   : %lx", params->ph_addr);
+	kdebug("- DYNAMIC[]: %lx", params->dynamic_addr);
+	seg = loadmap->segs;
+	for (loop = 0; loop < loadmap->nsegs; loop++, seg++)
+		kdebug("- LOAD[%d] : %08x-%08x [va=%x ms=%x]",
+		       loop,
+		       seg->addr, seg->addr + seg->p_memsz - 1,
+		       seg->p_vaddr, seg->p_memsz);
+
+	return 0;
+
+ dynamic_error:
+	printk("ELF FDPIC %s with invalid DYNAMIC section (inode=%lu)\n",
+	       what, file->f_dentry->d_inode->i_ino);
+	return -ELIBBAD;
+} /* end elf_fdpic_map_file() */
+
+/*****************************************************************************/
+/*
+ * map a file with constant displacement under uClinux
+ */
+#ifndef CONFIG_MMU
+static int elf_fdpic_map_file_constdisp_on_uclinux(struct elf_fdpic_params *params,
+						   struct file *file,
+						   struct mm_struct *mm)
+{
+	struct elf32_fdpic_loadseg *seg;
+	struct elf32_phdr *phdr;
+	unsigned long load_addr, base = ULONG_MAX, top = 0, maddr = 0, mflags;
+	loff_t fpos;
+	int loop, ret;
+
+	load_addr = params->load_addr;
+	seg = params->loadmap->segs;
+
+	/* determine the bounds of the contiguous overall allocation we must make */
+	phdr = params->phdrs;
+	for (loop = 0; loop < params->hdr.e_phnum; loop++, phdr++) {
+		if (params->phdrs[loop].p_type != PT_LOAD)
+			continue;
+
+		if (base > phdr->p_vaddr)
+			base = phdr->p_vaddr;
+		if (top < phdr->p_vaddr + phdr->p_memsz)
+			top = phdr->p_vaddr + phdr->p_memsz;
+	}
+
+	/* allocate one big anon block for everything */
+	mflags = MAP_PRIVATE;
+	if (params->flags & ELF_FDPIC_FLAG_EXECUTABLE)
+		mflags |= MAP_EXECUTABLE;
+
+	maddr = do_mmap(NULL, load_addr, top - base,
+			PROT_READ | PROT_WRITE | PROT_EXEC, mflags, 0);
+	if (IS_ERR((void *) maddr))
+		return (int) maddr;
+
+	if (load_addr != 0)
+		load_addr += PAGE_ALIGN(top - base);
+
+	/* and then load the file segments into it */
+	phdr = params->phdrs;
+	for (loop = 0; loop < params->hdr.e_phnum; loop++, phdr++) {
+		if (params->phdrs[loop].p_type != PT_LOAD)
+			continue;
+
+		fpos = phdr->p_offset;
+
+		seg->addr = maddr + (phdr->p_vaddr - base);
+		seg->p_vaddr = phdr->p_vaddr;
+		seg->p_memsz = phdr->p_memsz;
+
+		ret = file->f_op->read(file, (void *) seg->addr, phdr->p_filesz, &fpos);
+		if (ret < 0)
+			return ret;
+
+		/* map the ELF header address if in this segment */
+		if (phdr->p_offset == 0)
+			params->elfhdr_addr = seg->addr;
+
+		/* clear any space allocated but not loaded */
+		if (phdr->p_filesz < phdr->p_memsz)
+			clear_user((void *) (seg->addr + phdr->p_filesz),
+				   phdr->p_memsz - phdr->p_filesz);
+
+		if (mm) {
+			if (phdr->p_flags & PF_X) {
+				mm->start_code = seg->addr;
+				mm->end_code = seg->addr + phdr->p_memsz;
+			}
+			else if (!mm->start_data) {
+				mm->start_data = seg->addr;
+#ifndef CONFIG_MMU
+				mm->end_data = seg->addr + phdr->p_memsz;
+#endif
+			}
+
+#ifdef CONFIG_MMU
+			if (seg->addr + phdr->p_memsz > mm->end_data)
+				mm->end_data = seg->addr + phdr->p_memsz;
+#endif
+		}
+
+		seg++;
+	}
+
+	return 0;
+} /* end elf_fdpic_map_file_constdisp_on_uclinux() */
+#endif
+
+/*****************************************************************************/
+/*
+ * map a binary by direct mmap() of the individual PT_LOAD segments
+ */
+static int elf_fdpic_map_file_by_direct_mmap(struct elf_fdpic_params *params,
+					     struct file *file,
+					     struct mm_struct *mm)
+{
+	struct elf32_fdpic_loadseg *seg;
+	struct elf32_phdr *phdr;
+	unsigned long load_addr, delta_vaddr;
+	int loop, dvset;
+
+	load_addr = params->load_addr;
+	delta_vaddr = 0;
+	dvset = 0;
+
+	seg = params->loadmap->segs;
+
+	/* deal with each load segment separately */
+	phdr = params->phdrs;
+	for (loop = 0; loop < params->hdr.e_phnum; loop++, phdr++) {
+		unsigned long maddr, disp, excess, excess1;
+		int prot = 0, flags;
+
+		if (phdr->p_type != PT_LOAD)
+			continue;
+
+		kdebug("[LOAD] va=%lx of=%lx fs=%lx ms=%lx",
+		       phdr->p_vaddr, phdr->p_offset, phdr->p_filesz, phdr->p_memsz);
+
+		/* determine the mapping parameters */
+		if (phdr->p_flags & PF_R) prot |= PROT_READ;
+		if (phdr->p_flags & PF_W) prot |= PROT_WRITE;
+		if (phdr->p_flags & PF_X) prot |= PROT_EXEC;
+
+		flags = MAP_PRIVATE | MAP_DENYWRITE;
+		if (params->flags & ELF_FDPIC_FLAG_EXECUTABLE)
+			flags |= MAP_EXECUTABLE;
+
+		maddr = 0;
+
+		switch (params->flags & ELF_FDPIC_FLAG_ARRANGEMENT) {
+		case ELF_FDPIC_FLAG_INDEPENDENT:
+			/* PT_LOADs are independently locatable */
+			break;
+
+		case ELF_FDPIC_FLAG_HONOURVADDR:
+			/* the specified virtual address must be honoured */
+			maddr = phdr->p_vaddr;
+			flags |= MAP_FIXED;
+			break;
+
+		case ELF_FDPIC_FLAG_CONSTDISP:
+			/* constant displacement
+			 * - can be mapped anywhere, but must be mapped as a unit
+			 */
+			if (!dvset) {
+				maddr = load_addr;
+				delta_vaddr = phdr->p_vaddr;
+				dvset = 1;
+			}
+			else {
+				maddr = load_addr + phdr->p_vaddr - delta_vaddr;
+				flags |= MAP_FIXED;
+			}
+			break;
+
+		case ELF_FDPIC_FLAG_CONTIGUOUS:
+			/* contiguity handled later */
+			break;
+
+		default:
+			BUG();
+		}
+
+		maddr &= PAGE_MASK;
+
+		/* create the mapping */
+		disp = phdr->p_vaddr & ~PAGE_MASK;
+		maddr = do_mmap(file, maddr, phdr->p_memsz + disp, prot, flags,
+				phdr->p_offset - disp);
+
+		kdebug("mmap[%d] <file> sz=%lx pr=%x fl=%x of=%lx --> %08lx",
+		       loop, phdr->p_memsz + disp, prot, flags, phdr->p_offset - disp,
+		       maddr);
+
+		if (IS_ERR((void *) maddr))
+			return (int) maddr;
+
+		if ((params->flags & ELF_FDPIC_FLAG_ARRANGEMENT) == ELF_FDPIC_FLAG_CONTIGUOUS)
+			load_addr += PAGE_ALIGN(phdr->p_memsz + disp);
+
+		seg->addr = maddr + disp;
+		seg->p_vaddr = phdr->p_vaddr;
+		seg->p_memsz = phdr->p_memsz;
+
+		/* map the ELF header address if in this segment */
+		if (phdr->p_offset == 0)
+			params->elfhdr_addr = seg->addr;
+
+		/* clear the bit between beginning of mapping and beginning of PT_LOAD */
+		if (prot & PROT_WRITE && disp > 0) {
+			kdebug("clear[%d] ad=%lx sz=%lx", loop, maddr, disp);
+			clear_user((void *) maddr, disp);
+			maddr += disp;
+		}
+
+		/* clear any space allocated but not loaded
+		 * - on uClinux we can just clear the lot
+		 * - on MMU linux we'll get a SIGBUS beyond the last page
+		 *   extant in the file
+		 */
+		excess = phdr->p_memsz - phdr->p_filesz;
+		excess1 = PAGE_SIZE - ((maddr + phdr->p_filesz) & ~PAGE_MASK);
+
+#ifdef CONFIG_MMU
+
+		if (excess > excess1) {
+			unsigned long xaddr = maddr + phdr->p_filesz + excess1;
+			unsigned long xmaddr;
+
+			flags |= MAP_FIXED | MAP_ANONYMOUS;
+			xmaddr = do_mmap(NULL, xaddr, excess - excess1, prot, flags, 0);
+
+			kdebug("mmap[%d] <anon>"
+			       " ad=%lx sz=%lx pr=%x fl=%x of=0 --> %08lx",
+			       loop, xaddr, excess - excess1, prot, flags, xmaddr);
+
+			if (xmaddr != xaddr)
+				return -ENOMEM;
+		}
+
+		if (prot & PROT_WRITE && excess1 > 0) {
+			kdebug("clear[%d] ad=%lx sz=%lx",
+			       loop, maddr + phdr->p_filesz, excess1);
+			clear_user((void *) maddr + phdr->p_filesz, excess1);
+		}
+
+#else
+		if (excess > 0) {
+			kdebug("clear[%d] ad=%lx sz=%lx",
+			       loop, maddr + phdr->p_filesz, excess);
+			clear_user((void *) maddr + phdr->p_filesz, excess);
+		}
+#endif
+
+		if (mm) {
+			if (phdr->p_flags & PF_X) {
+				mm->start_code = maddr;
+				mm->end_code = maddr + phdr->p_memsz;
+			}
+			else if (!mm->start_data) {
+				mm->start_data = maddr;
+				mm->end_data = maddr + phdr->p_memsz;
+			}
+		}
+
+		seg++;
+	}
+
+	return 0;
+} /* end elf_fdpic_map_file_by_direct_mmap() */
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/fs/Kconfig.binfmt linux-2.6.10-rc1-mm3-frv/fs/Kconfig.binfmt
--- /warthog/kernels/linux-2.6.10-rc1-mm3/fs/Kconfig.binfmt	2004-06-18 13:41:29.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/fs/Kconfig.binfmt	2004-11-05 14:13:03.794504979 +0000
@@ -23,6 +23,19 @@ config BINFMT_ELF
 	  ld.so (check the file <file:Documentation/Changes> for location and
 	  latest version).
 
+config BINFMT_ELF_FDPIC
+	bool "Kernel support for FDPIC ELF binaries"
+	default y
+	depends on FRV
+	help
+	  ELF FDPIC binaries are based on ELF, but allow the individual load
+	  segments of a binary to be located in memory independently of each
+	  other. This makes this format ideal for use in environments where no
+	  MMU is available as it still permits text segments to be shared,
+	  even if data segments are not.
+
+	  It is also possible to run FDPIC ELF binaries on MMU linux also.
+
 config BINFMT_FLAT
 	tristate "Kernel support for flat binaries"
 	depends on !MMU || SUPERH
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/fs/Makefile linux-2.6.10-rc1-mm3-frv/fs/Makefile
--- /warthog/kernels/linux-2.6.10-rc1-mm3/fs/Makefile	2004-11-05 13:15:42.000000000 +0000
+++ linux-2.6.10-rc1-mm3-frv/fs/Makefile	2004-11-05 14:13:03.802504303 +0000
@@ -25,6 +25,7 @@ obj-$(CONFIG_BINFMT_MISC)	+= binfmt_misc
 obj-y				+= binfmt_script.o
 
 obj-$(CONFIG_BINFMT_ELF)	+= binfmt_elf.o
+obj-$(CONFIG_BINFMT_ELF_FDPIC)	+= binfmt_elf_fdpic.o
 obj-$(CONFIG_BINFMT_SOM)	+= binfmt_som.o
 obj-$(CONFIG_BINFMT_FLAT)	+= binfmt_flat.o
 
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/include/linux/elf-fdpic.h linux-2.6.10-rc1-mm3-frv/include/linux/elf-fdpic.h
--- /warthog/kernels/linux-2.6.10-rc1-mm3/include/linux/elf-fdpic.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/include/linux/elf-fdpic.h	2004-11-05 14:13:04.384455150 +0000
@@ -0,0 +1,68 @@
+/* elf-fdpic.h: FDPIC ELF load map
+ *
+ * Copyright (C) 2003 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * 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.
+ */
+
+#ifndef _LINUX_ELF_FDPIC_H
+#define _LINUX_ELF_FDPIC_H
+
+#include <linux/elf.h>
+
+#define PT_GNU_STACK    (PT_LOOS + 0x474e551)
+
+/* segment mappings for ELF FDPIC libraries/executables/interpreters */
+struct elf32_fdpic_loadseg {
+	Elf32_Addr	addr;		/* core address to which mapped */
+	Elf32_Addr	p_vaddr;	/* VMA recorded in file */
+	Elf32_Word	p_memsz;	/* allocation size recorded in file */
+};
+
+struct elf32_fdpic_loadmap {
+	Elf32_Half	version;	/* version of these structures, just in case... */
+	Elf32_Half	nsegs;		/* number of segments */
+	struct elf32_fdpic_loadseg segs[];
+};
+
+#define ELF32_FDPIC_LOADMAP_VERSION	0x0000
+
+/*
+ * binfmt binary parameters structure
+ */
+struct elf_fdpic_params {
+	struct elfhdr			hdr;		/* ref copy of ELF header */
+	struct elf_phdr			*phdrs;		/* ref copy of PT_PHDR table */
+	struct elf32_fdpic_loadmap	*loadmap;	/* loadmap to be passed to userspace */
+	unsigned long			elfhdr_addr;	/* mapped ELF header user address */
+	unsigned long			ph_addr;	/* mapped PT_PHDR user address */
+	unsigned long			map_addr;	/* mapped loadmap user address */
+	unsigned long			entry_addr;	/* mapped entry user address */
+	unsigned long			stack_size;	/* stack size requested (PT_GNU_STACK) */
+	unsigned long			dynamic_addr;	/* mapped PT_DYNAMIC user address */
+	unsigned long			load_addr;	/* user address at which to map binary */
+	unsigned long			flags;
+#define ELF_FDPIC_FLAG_ARRANGEMENT	0x0000000f	/* PT_LOAD arrangement flags */
+#define ELF_FDPIC_FLAG_INDEPENDENT	0x00000000	/* PT_LOADs can be put anywhere */
+#define ELF_FDPIC_FLAG_HONOURVADDR	0x00000001	/* PT_LOAD.vaddr must be honoured */
+#define ELF_FDPIC_FLAG_CONSTDISP	0x00000002	/* PT_LOADs require constant
+							 * displacement */
+#define ELF_FDPIC_FLAG_CONTIGUOUS	0x00000003	/* PT_LOADs should be contiguous */
+#define ELF_FDPIC_FLAG_EXEC_STACK	0x00000010	/* T if stack to be executable */
+#define ELF_FDPIC_FLAG_NOEXEC_STACK	0x00000020	/* T if stack not to be executable */
+#define ELF_FDPIC_FLAG_EXECUTABLE	0x00000040	/* T if this object is the executable */
+#define ELF_FDPIC_FLAG_PRESENT		0x80000000	/* T if this object is present */
+};
+
+#ifdef CONFIG_MMU
+extern void elf_fdpic_arch_lay_out_mm(struct elf_fdpic_params *exec_params,
+				      struct elf_fdpic_params *interp_params,
+				      unsigned long *start_stack,
+				      unsigned long *start_brk);
+#endif
+
+#endif /* _LINUX_ELF_FDPIC_H */
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/include/linux/personality.h linux-2.6.10-rc1-mm3-frv/include/linux/personality.h
--- /warthog/kernels/linux-2.6.10-rc1-mm3/include/linux/personality.h	2004-10-19 10:42:17.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/include/linux/personality.h	2004-11-05 14:13:04.434450927 +0000
@@ -18,6 +18,9 @@ extern int		__set_personality(unsigned l
  * These occupy the top three bytes.
  */
 enum {
+	FDPIC_FUNCPTRS =	0x0080000,	/* userspace function ptrs point to descriptors
+						 * (signal handling)
+						 */
 	MMAP_PAGE_ZERO =	0x0100000,
 	ADDR_COMPAT_LAYOUT =	0x0200000,
 	READ_IMPLIES_EXEC =	0x0400000,
@@ -43,6 +46,7 @@ enum {
 enum {
 	PER_LINUX =		0x0000,
 	PER_LINUX_32BIT =	0x0000 | ADDR_LIMIT_32BIT,
+	PER_LINUX_FDPIC =	0x0000 | FDPIC_FUNCPTRS,
 	PER_SVR4 =		0x0001 | STICKY_TIMEOUTS | MMAP_PAGE_ZERO,
 	PER_SVR3 =		0x0002 | STICKY_TIMEOUTS | SHORT_INODE,
 	PER_SCOSVR3 =		0x0003 | STICKY_TIMEOUTS |

^ permalink raw reply	[flat|nested] 87+ messages in thread

* [PATCH 17/20] FRV: Better mmap support in uClinux
       [not found] ` <20040401020550.GG3150@beast>
  2004-11-01 19:30   ` [PATCH 14/14] FRV: Better mmap support in uClinux dhowells
@ 2004-11-08 14:34   ` dhowells
  2004-11-09 12:57     ` Christoph Hellwig
                       ` (3 more replies)
  1 sibling, 4 replies; 87+ messages in thread
From: dhowells @ 2004-11-08 14:34 UTC (permalink / raw)
  To: torvalds, akpm, davidm; +Cc: linux-kernel, uclinux-dev

The attached patch changes mm/nommu.c to better support mmap() when MMU support
is disabled (as it is in uClinux).

This was discussed on the uclibc mailing list in a thread revolving around the
following message:

	Date: Thu, 1 Apr 2004 12:05:50 +1000
	From: David McCullough <davidm@snapgear.com>
	To: David Howells <dhowells@redhat.com>
	Cc: Alexandre Oliva <aoliva@redhat.com>, uclibc@uclibc.org
	Subject: Re: [uClibc] mmaps for malloc should be private
	Message-ID: <20040401020550.GG3150@beast>

The revised rules are:

 (1) Anonymous mappings can be shared or private, read or write.

 (2) Chardevs can be mapped shared, provided they supply a get_unmapped_area()
     file operation and use that to set the address of the mapping (as a frame
     buffer driver might do, for instance).

 (3) Files (and blockdevs) cannot be mapped shared since it is not really
     possible to honour this by writing any changes back to the backing device.

 (4) Files (or sections thereof) can be mapped read-only private, in which case
     the mapped bit will be read into memory and shared, and its address will
     be returned. Any excess beyond EOF will be cleared.

 (5) Files (or sections thereof) can be mapped writable private, in which case
     a private copy of the mapped bit will be read into a new bit memory, and
     its address will be returned. Any excess beyond EOF will be cleared.

Mappings are per MM structure still. You can only unmap what you've mapped.

Fork semantics are irrelevant, since there's no fork.

A global list of VMA's is maintained to keep track of the bits of memory
currently mapped on the system.

The new binfmt makes use of (4) to implement shared libraries.

Signed-Off-By: dhowells@redhat.com
---
diffstat nommu-2610rc1mm3.diff
 include/linux/mm.h |   30 +++
 mm/nommu.c         |  498 ++++++++++++++++++++++++++++++++++++-----------------
 2 files changed, 369 insertions(+), 159 deletions(-)

diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/include/linux/mm.h linux-2.6.10-rc1-mm3-frv/include/linux/mm.h
--- /warthog/kernels/linux-2.6.10-rc1-mm3/include/linux/mm.h	2004-11-05 13:15:50.000000000 +0000
+++ linux-2.6.10-rc1-mm3-frv/include/linux/mm.h	2004-11-05 17:44:09.120160519 +0000
@@ -58,6 +62,7 @@ extern int sysctl_legacy_va_layout;
  * space that has a special rule for the page-fault handlers (ie a shared
  * library, the executable area etc).
  */
+#ifdef CONFIG_MMU
 struct vm_area_struct {
 	struct mm_struct * vm_mm;	/* The address space we belong to. */
 	unsigned long vm_start;		/* Our start address within vm_mm. */
@@ -112,6 +117,31 @@ struct vm_area_struct {
 #endif
 };
 
+#else
+
+struct vm_area_struct {
+	struct list_head	vm_link;	/* system object list */
+	atomic_t		vm_usage;	/* count of refs */
+	unsigned long		vm_start;
+	unsigned long		vm_end;
+	pgprot_t		vm_page_prot;	/* access permissions of this VMA */
+	unsigned long		vm_flags;
+	unsigned long		vm_pgoff;
+	struct file		*vm_file;	/* file or device mapped */
+};
+
+struct mm_tblock_struct {
+	struct mm_tblock_struct	*next;
+	struct vm_area_struct	*vma;
+};
+
+extern struct list_head nommu_vma_list;
+extern struct rw_semaphore nommu_vma_sem;
+
+extern unsigned int kobjsize(const void *objp);
+
+#endif
+
 /*
  * vm_flags..
  */
@@ -612,6 +642,10 @@ int FASTCALL(set_page_dirty(struct page 
 int set_page_dirty_lock(struct page *page);
 int clear_page_dirty_for_io(struct page *page);
 
+extern unsigned long do_mremap(unsigned long addr,
+			       unsigned long old_len, unsigned long new_len,
+			       unsigned long flags, unsigned long new_addr);
+
 /*
  * Prototype to add a shrinker callback for ageable caches.
  * 
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/mm/nommu.c linux-2.6.10-rc1-mm3-frv/mm/nommu.c
--- /warthog/kernels/linux-2.6.10-rc1-mm3/mm/nommu.c	2004-11-05 13:15:52.000000000 +0000
+++ linux-2.6.10-rc1-mm3-frv/mm/nommu.c	2004-11-05 14:13:04.000000000 +0000
@@ -4,6 +4,7 @@
  *  Replacement code for mm functions to support CPU's that don't
  *  have any form of memory management unit (thus no virtual memory).
  *
+ *  Copyright (c) 2004      David Howells <dhowells@redhat.com>
  *  Copyright (c) 2000-2003 David McCullough <davidm@snapgear.com>
  *  Copyright (c) 2000-2001 D Jeff Dionne <jeff@uClinux.org>
  *  Copyright (c) 2002      Greg Ungerer <gerg@snapgear.com>
@@ -12,11 +13,12 @@
 #include <linux/mm.h>
 #include <linux/mman.h>
 #include <linux/swap.h>
-#include <linux/smp_lock.h>
+#include <linux/file.h>
 #include <linux/highmem.h>
 #include <linux/pagemap.h>
 #include <linux/slab.h>
 #include <linux/vmalloc.h>
+#include <linux/ptrace.h>
 #include <linux/blkdev.h>
 #include <linux/backing-dev.h>
 #include <linux/syscalls.h>
@@ -38,6 +40,14 @@ int sysctl_max_map_count = DEFAULT_MAX_M
 EXPORT_SYMBOL(sysctl_max_map_count);
 EXPORT_SYMBOL(mem_map);
 
+/* list of shareable VMAs */
+LIST_HEAD(nommu_vma_list);
+DECLARE_RWSEM(nommu_vma_sem);
+
+void __init prio_tree_init(void)
+{
+}
+
 /*
  * Handle all mappings that got truncated by a "truncate()"
  * system call.
@@ -161,7 +171,7 @@ long vwrite(char *buf, char *addr, unsig
 	/* Don't allow overflow */
 	if ((unsigned long) addr + count < count)
 		count = -(unsigned long) addr;
-	
+
 	memcpy(addr, buf, count);
 	return(count);
 }
@@ -217,7 +227,7 @@ asmlinkage unsigned long sys_brk(unsigne
 {
 	struct mm_struct *mm = current->mm;
 
-	if (brk < mm->end_code || brk < mm->start_brk || brk > mm->context.end_brk)
+	if (brk < mm->start_brk || brk > mm->context.end_brk)
 		return mm->brk;
 
 	if (mm->brk == brk)
@@ -276,33 +286,39 @@ static void show_process_blocks(void)
 }
 #endif /* DEBUG */
 
-unsigned long do_mmap_pgoff(
-	struct file * file,
-	unsigned long addr,
-	unsigned long len,
-	unsigned long prot,
-	unsigned long flags,
-	unsigned long pgoff)
-{
-	void * result;
-	struct mm_tblock_struct * tblock;
+unsigned long do_mmap_pgoff(struct file *file,
+			    unsigned long addr,
+			    unsigned long len,
+			    unsigned long prot,
+			    unsigned long flags,
+			    unsigned long pgoff)
+{
+	struct mm_tblock_struct *tblock = NULL;
+	struct vm_area_struct *vma = NULL, *pvma;
+	struct list_head *p;
 	unsigned int vm_flags;
+	void *result;
+	int ret, chrdev;
 
 	/*
 	 * Get the !CONFIG_MMU specific checks done first
 	 */
-	if ((flags & MAP_SHARED) && (prot & PROT_WRITE) && (file)) {
-		printk("MAP_SHARED not supported (cannot write mappings to disk)\n");
+	chrdev = 0;
+	if (file)
+		chrdev = S_ISCHR(file->f_dentry->d_inode->i_mode);
+
+	if ((flags & MAP_SHARED) && (prot & PROT_WRITE) && file && !chrdev) {
+		printk("MAP_SHARED not completely supported (cannot detect page dirtying)\n");
 		return -EINVAL;
 	}
-	
-	if ((prot & PROT_WRITE) && (flags & MAP_PRIVATE)) {
-		printk("Private writable mappings not supported\n");
+
+	if (flags & MAP_FIXED || addr) {
+		/* printk("can't do fixed-address/overlay mmap of RAM\n"); */
 		return -EINVAL;
 	}
-	
+
 	/*
-	 *	now all the standard checks
+	 * now all the standard checks
 	 */
 	if (file && (!file->f_op || !file->f_op->mmap))
 		return -ENODEV;
@@ -317,148 +333,291 @@ unsigned long do_mmap_pgoff(
 	if ((pgoff + (len >> PAGE_SHIFT)) < pgoff)
 		return -EINVAL;
 
+	/* we're going to need to record the mapping if it works */
+	tblock = kmalloc(sizeof(struct mm_tblock_struct), GFP_KERNEL);
+	if (!tblock)
+		goto error_getting_tblock;
+	memset(tblock, 0, sizeof(*tblock));
+
 	/* Do simple checking here so the lower-level routines won't have
 	 * to. we assume access permissions have been handled by the open
 	 * of the memory object, so we don't do any here.
 	 */
-	vm_flags = calc_vm_flags(prot,flags) /* | mm->def_flags */ | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC;
+	vm_flags = calc_vm_flags(prot,flags) /* | mm->def_flags */
+		| VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC;
+
+	if (!chrdev) {
+		/* share any file segment that's mapped read-only */
+		if (((flags & MAP_PRIVATE) && !(prot & PROT_WRITE) && file) ||
+		    ((flags & MAP_SHARED) && !(prot & PROT_WRITE) && file))
+			vm_flags |= VM_SHARED | VM_MAYSHARE;
+
+		/* refuse to let anyone share files with this process if it's being traced -
+		 * otherwise breakpoints set in it may interfere with another untraced process
+		 */
+		if (!chrdev && current->ptrace & PT_PTRACED)
+			vm_flags &= ~(VM_SHARED | VM_MAYSHARE);
+	}
+	else {
+		/* permit sharing of character devices at any time */
+		vm_flags |= VM_MAYSHARE;
+		if (flags & MAP_SHARED)
+			vm_flags |= VM_SHARED;
+	}
+
+	/* if we want to share, we need to search for VMAs created by another mmap() call that
+	 * overlap with our proposed mapping
+	 * - we can only share with an exact match on regular files
+	 * - shared mappings on character devices are permitted to overlap inexactly as far as we
+	 *   are concerned, but in that case, sharing is handled in the driver rather than here
+	 */
+	down_write(&nommu_vma_sem);
+	if (!chrdev && vm_flags & VM_SHARED) {
+		unsigned long pglen = (len + PAGE_SIZE - 1) >> PAGE_SHIFT;
+		unsigned long vmpglen;
+
+		list_for_each_entry(vma, &nommu_vma_list, vm_link) {
+			if (!(vma->vm_flags & VM_SHARED))
+				continue;
+
+			if (vma->vm_file->f_dentry->d_inode != file->f_dentry->d_inode)
+				continue;
+
+			if (vma->vm_pgoff >= pgoff + pglen)
+				continue;
+
+			vmpglen = (vma->vm_end - vma->vm_start + PAGE_SIZE - 1) >> PAGE_SHIFT;
+			if (pgoff >= vma->vm_pgoff + vmpglen)
+				continue;
+
+			if (vmpglen != pglen || vma->vm_pgoff != pgoff) {
+				if (flags & MAP_SHARED)
+					goto sharing_violation;
+				continue;
+			}
+
+			/* we've found a VMA we can share */
+			atomic_inc(&vma->vm_usage);
+
+			tblock->vma = vma;
+			result = (void *) vma->vm_start;
+			goto shared;
+		}
+	}
+
+	/* obtain the address to map to. we verify (or select) it and ensure
+	 * that it represents a valid section of the address space
+	 * - this is the hook for quasi-memory character devices
+	 */
+	if (file && file->f_op && file->f_op->get_unmapped_area)
+		addr = file->f_op->get_unmapped_area(file, addr, len, pgoff, flags);
+
+	if (IS_ERR((void *) addr)) {
+		ret = addr;
+		goto error;
+	}
+
+	/* we're going to need a VMA struct as well */
+	vma = kmalloc(sizeof(struct vm_area_struct), GFP_KERNEL);
+	if (!vma)
+		goto error_getting_vma;
+
+	INIT_LIST_HEAD(&vma->vm_link);
+	atomic_set(&vma->vm_usage, 1);
+	if (file)
+		get_file(file);
+	vma->vm_file	= file;
+	vma->vm_flags	= vm_flags;
+	vma->vm_start	= addr;
+	vma->vm_end	= addr + len;
+	vma->vm_pgoff	= pgoff;
+
+	tblock->vma = vma;
 
 	/*
 	 * determine the object being mapped and call the appropriate
-	 * specific mapper. 
+	 * specific mapper.
 	 */
 	if (file) {
-		struct vm_area_struct vma;
-		int error;
-
+		ret = -ENODEV;
 		if (!file->f_op)
-			return -ENODEV;
-
-		vma.vm_start = addr;
-		vma.vm_end = addr + len;
-		vma.vm_flags = vm_flags;
-		vma.vm_pgoff = pgoff;
+			goto error;
 
 #ifdef MAGIC_ROM_PTR
 		/* First, try simpler routine designed to give us a ROM pointer. */
 
 		if (file->f_op->romptr && !(prot & PROT_WRITE)) {
-			error = file->f_op->romptr(file, &vma);
+			ret = file->f_op->romptr(file, vma);
 #ifdef DEBUG
-			printk("romptr mmap returned %d, start 0x%.8x\n", error,
-					vma.vm_start);
+			printk("romptr mmap returned %d (st=%lx)\n",
+			       ret, vma->vm_start);
 #endif
-			if (!error)
-				return vma.vm_start;
-			else if (error != -ENOSYS)
-				return error;
+			result = (void *) vma->vm_start;
+			if (!ret)
+				goto done;
+			else if (ret != -ENOSYS)
+				goto error;
 		} else
 #endif /* MAGIC_ROM_PTR */
 		/* Then try full mmap routine, which might return a RAM pointer,
 		   or do something truly complicated. */
-		   
+
 		if (file->f_op->mmap) {
-			error = file->f_op->mmap(file, &vma);
-				   
+			ret = file->f_op->mmap(file, vma);
+
 #ifdef DEBUG
-			printk("f_op->mmap() returned %d/%lx\n", error, vma.vm_start);
+			printk("f_op->mmap() returned %d (st=%lx)\n",
+			       ret, vma->vm_start);
 #endif
-			if (!error)
-				return vma.vm_start;
-			else if (error != -ENOSYS)
-				return error;
-		} else
-			return -ENODEV; /* No mapping operations defined */
+			result = (void *) vma->vm_start;
+			if (!ret)
+				goto done;
+			else if (ret != -ENOSYS)
+				goto error;
+		} else {
+			ret = -ENODEV; /* No mapping operations defined */
+			goto error;
+		}
 
 		/* An ENOSYS error indicates that mmap isn't possible (as opposed to
 		   tried but failed) so we'll fall through to the copy. */
 	}
 
-	tblock = (struct mm_tblock_struct *)
-                        kmalloc(sizeof(struct mm_tblock_struct), GFP_KERNEL);
-	if (!tblock) {
-		printk("Allocation of tblock for %lu byte allocation from process %d failed\n", len, current->pid);
-		show_free_areas();
-		return -ENOMEM;
-	}
-
-	tblock->rblock = (struct mm_rblock_struct *)
-			kmalloc(sizeof(struct mm_rblock_struct), GFP_KERNEL);
-
-	if (!tblock->rblock) {
-		printk("Allocation of rblock for %lu byte allocation from process %d failed\n", len, current->pid);
-		show_free_areas();
-		kfree(tblock);
-		return -ENOMEM;
-	}
-
+	/* allocate some memory to hold the mapping */
+	ret = -ENOMEM;
 	result = kmalloc(len, GFP_KERNEL);
 	if (!result) {
-		printk("Allocation of length %lu from process %d failed\n", len,
-				current->pid);
+		printk("Allocation of length %lu from process %d failed\n",
+		       len, current->pid);
 		show_free_areas();
-		kfree(tblock->rblock);
-		kfree(tblock);
-		return -ENOMEM;
+		goto error;
 	}
 
-	tblock->rblock->refcount = 1;
-	tblock->rblock->kblock = result;
-	tblock->rblock->size = len;
-	
-	realalloc += kobjsize(result);
-	askedalloc += len;
+	vma->vm_start = (unsigned long) result;
+	vma->vm_end = vma->vm_start + len;
 
-#ifdef WARN_ON_SLACK	
-	if ((len+WARN_ON_SLACK) <= kobjsize(result))
-		printk("Allocation of %lu bytes from process %d has %lu bytes of slack\n", len, current->pid, kobjsize(result)-len);
+#ifdef WARN_ON_SLACK
+	if (len + WARN_ON_SLACK <= kobjsize(result))
+		printk("Allocation of %lu bytes from process %d has %lu bytes of slack\n",
+		       len, current->pid, kobjsize(result) - len);
 #endif
-	
+
 	if (file) {
-		int error;
 		mm_segment_t old_fs = get_fs();
+		loff_t fpos;
+
+		fpos = pgoff;
+		fpos <<= PAGE_SHIFT;
+
 		set_fs(KERNEL_DS);
-		error = file->f_op->read(file, (char *) result, len, &file->f_pos);
+		ret = file->f_op->read(file, (char *) result, len, &fpos);
 		set_fs(old_fs);
-		if (error < 0) {
-			kfree(result);
-			kfree(tblock->rblock);
-			kfree(tblock);
-			return error;
-		}
-		if (error < len)
-			memset(result+error, '\0', len-error);
+
+		if (ret < 0)
+			goto error2;
+		if (ret < len)
+			memset(result + ret, 0, len - ret);
 	} else {
-		memset(result, '\0', len);
+		memset(result, 0, len);
 	}
 
-	realalloc += kobjsize(tblock);
-	askedalloc += sizeof(struct mm_tblock_struct);
+	if (prot & PROT_EXEC)
+		flush_icache_range((unsigned long) result, (unsigned long) result + len);
+
+ done:
+	realalloc += kobjsize(result);
+	askedalloc += len;
 
-	realalloc += kobjsize(tblock->rblock);
-	askedalloc += sizeof(struct mm_rblock_struct);
+	realalloc += kobjsize(vma);
+	askedalloc += sizeof(*vma);
 
-	tblock->next = current->mm->context.tblock.next;
-	current->mm->context.tblock.next = tblock;
 	current->mm->total_vm += len >> PAGE_SHIFT;
 
+	list_for_each(p, &nommu_vma_list) {
+		pvma = list_entry(p, struct vm_area_struct, vm_link);
+		if (pvma->vm_start > vma->vm_start)
+			break;
+	}
+	list_add_tail(&vma->vm_link, p);
+
+ shared:
+	realalloc += kobjsize(tblock);
+	askedalloc += sizeof(*tblock);
+
+	tblock->next = current->mm->context.tblock;
+	current->mm->context.tblock = tblock;
+
+	up_write(&nommu_vma_sem);
+
 #ifdef DEBUG
 	printk("do_mmap:\n");
 	show_process_blocks();
-#endif	  
+#endif
+
+	return (unsigned long) result;
 
-	return (unsigned long)result;
+ error2:
+	kfree(result);
+ error:
+	up_write(&nommu_vma_sem);
+	kfree(tblock);
+	if (vma) {
+		fput(vma->vm_file);
+		kfree(vma);
+	}
+	return ret;
+
+ sharing_violation:
+	up_write(&nommu_vma_sem);
+	printk("Attempt to share mismatched mappings\n");
+	kfree(tblock);
+	return -EINVAL;
+
+ error_getting_vma:
+	up_write(&nommu_vma_sem);
+	kfree(tblock);
+	printk("Allocation of tblock for %lu byte allocation from process %d failed\n",
+	       len, current->pid);
+	show_free_areas();
+	return -ENOMEM;
+
+ error_getting_tblock:
+	printk("Allocation of tblock for %lu byte allocation from process %d failed\n",
+	       len, current->pid);
+	show_free_areas();
+	return -ENOMEM;
 }
 
-int do_munmap(struct mm_struct * mm, unsigned long addr, size_t len)
+static void put_vma(struct vm_area_struct *vma)
 {
-	struct mm_tblock_struct * tblock, *tmp;
+	if (vma) {
+		down_write(&nommu_vma_sem);
+		if (atomic_dec_and_test(&vma->vm_usage)) {
+			list_del_init(&vma->vm_link);
+
+			if (!(vma->vm_flags & VM_IO) && vma->vm_start) {
+				realalloc -= kobjsize((void *) vma->vm_start);
+				askedalloc -= vma->vm_end - vma->vm_start;
+				if (vma->vm_file)
+					fput(vma->vm_file);
+				kfree((void *) vma->vm_start);
+			}
+
+			realalloc -= kobjsize(vma);
+			askedalloc -= sizeof(*vma);
+			kfree(vma);
+		}
+		up_write(&nommu_vma_sem);
+	}
+}
+
+int do_munmap(struct mm_struct *mm, unsigned long addr, size_t len)
+{
+	struct mm_tblock_struct *tblock, **parent;
 
 #ifdef MAGIC_ROM_PTR
-	/*
-	 * For efficiency's sake, if the pointer is obviously in ROM,
-	 * don't bother walking the lists to free it.
-	 */
+	/* For efficiency's sake, if the pointer is obviously in ROM,
+	   don't bother walking the lists to free it */
 	if (is_in_rom(addr))
 		return 0;
 #endif
@@ -467,38 +626,28 @@ int do_munmap(struct mm_struct * mm, uns
 	printk("do_munmap:\n");
 #endif
 
-	tmp = &mm->context.tblock; /* dummy head */
-	while ((tblock=tmp->next) && tblock->rblock &&
-			tblock->rblock->kblock != (void*)addr) 
-		tmp = tblock;
-		
+	for (parent = &mm->context.tblock; *parent; parent = &(*parent)->next)
+		if ((*parent)->vma->vm_start == addr)
+			break;
+	tblock = *parent;
+
 	if (!tblock) {
 		printk("munmap of non-mmaped memory by process %d (%s): %p\n",
-				current->pid, current->comm, (void*)addr);
+		       current->pid, current->comm, (void *) addr);
 		return -EINVAL;
 	}
-	if (tblock->rblock) {
-		if (!--tblock->rblock->refcount) {
-			if (tblock->rblock->kblock) {
-				realalloc -= kobjsize(tblock->rblock->kblock);
-				askedalloc -= tblock->rblock->size;
-				kfree(tblock->rblock->kblock);
-			}
-			
-			realalloc -= kobjsize(tblock->rblock);
-			askedalloc -= sizeof(struct mm_rblock_struct);
-			kfree(tblock->rblock);
-		}
-	}
-	tmp->next = tblock->next;
+
+	put_vma(tblock->vma);
+
+	*parent = tblock->next;
 	realalloc -= kobjsize(tblock);
-	askedalloc -= sizeof(struct mm_tblock_struct);
+	askedalloc -= sizeof(*tblock);
 	kfree(tblock);
 	mm->total_vm -= len >> PAGE_SHIFT;
 
 #ifdef DEBUG
 	show_process_blocks();
-#endif	  
+#endif
 
 	return 0;
 }
@@ -507,38 +656,27 @@ int do_munmap(struct mm_struct * mm, uns
 void exit_mmap(struct mm_struct * mm)
 {
 	struct mm_tblock_struct *tmp;
-	mm->total_vm = 0;
-
-	if (!mm)
-		return;
 
+	if (mm) {
 #ifdef DEBUG
-	printk("Exit_mmap:\n");
+		printk("Exit_mmap:\n");
 #endif
 
-	while((tmp = mm->context.tblock.next)) {
-		if (tmp->rblock) {
-			if (!--tmp->rblock->refcount) {
-				if (tmp->rblock->kblock) {
-					realalloc -= kobjsize(tmp->rblock->kblock);
-					askedalloc -= tmp->rblock->size;
-					kfree(tmp->rblock->kblock);
-				}
-				realalloc -= kobjsize(tmp->rblock);
-				askedalloc -= sizeof(struct mm_rblock_struct);
-				kfree(tmp->rblock);
-			}
-			tmp->rblock = 0;
+		mm->total_vm = 0;
+
+		while ((tmp = mm->context.tblock)) {
+			mm->context.tblock = tmp->next;
+			put_vma(tmp->vma);
+
+			realalloc -= kobjsize(tmp);
+			askedalloc -= sizeof(*tmp);
+			kfree(tmp);
 		}
-		mm->context.tblock.next = tmp->next;
-		realalloc -= kobjsize(tmp);
-		askedalloc -= sizeof(struct mm_tblock_struct);
-		kfree(tmp);
-	}
 
 #ifdef DEBUG
-	show_process_blocks();
-#endif	  
+		show_process_blocks();
+#endif
+	}
 }
 
 asmlinkage long sys_munmap(unsigned long addr, size_t len)
@@ -557,6 +695,54 @@ unsigned long do_brk(unsigned long addr,
 	return -ENOMEM;
 }
 
+/*
+ * Expand (or shrink) an existing mapping, potentially moving it at the
+ * same time (controlled by the MREMAP_MAYMOVE flag and available VM space)
+ *
+ * MREMAP_FIXED option added 5-Dec-1999 by Benjamin LaHaise
+ * This option implies MREMAP_MAYMOVE.
+ *
+ * on uClinux, we only permit changing a mapping's size, and only as long as it stays within the
+ * hole allocated by the kmalloc() call in do_mmap_pgoff() and the block is not shareable
+ */
+unsigned long do_mremap(unsigned long addr,
+			unsigned long old_len, unsigned long new_len,
+			unsigned long flags, unsigned long new_addr)
+{
+	struct mm_tblock_struct *tblock = NULL;
+
+	/* insanity checks first */
+	if (new_len == 0)
+		return (unsigned long) -EINVAL;
+
+	if (flags & MREMAP_FIXED && new_addr != addr)
+		return (unsigned long) -EINVAL;
+
+	for (tblock = current->mm->context.tblock; tblock; tblock = tblock->next)
+		if (tblock->vma->vm_start == addr)
+			goto found;
+
+	return (unsigned long) -EINVAL;
+
+ found:
+	if (tblock->vma->vm_end != tblock->vma->vm_start + old_len)
+		return (unsigned long) -EFAULT;
+
+	if (tblock->vma->vm_flags & VM_MAYSHARE)
+		return (unsigned long) -EPERM;
+
+	if (new_len > kobjsize((void *) addr))
+		return (unsigned long) -ENOMEM;
+
+	/* all checks complete - do it */
+	tblock->vma->vm_end = tblock->vma->vm_start + new_len;
+
+	askedalloc -= old_len;
+	askedalloc += new_len;
+
+	return tblock->vma->vm_start;
+}
+
 struct vm_area_struct * find_vma(struct mm_struct * mm, unsigned long addr)
 {
 	return NULL;
@@ -578,12 +764,6 @@ int remap_pfn_range(struct vm_area_struc
 	return -EPERM;
 }
 
-unsigned long get_unmapped_area(struct file *file, unsigned long addr,
-	unsigned long len, unsigned long pgoff, unsigned long flags)
-{
-	return -ENOMEM;
-}
-
 void swap_unplug_io_fn(struct backing_dev_info *bdi, struct page *page)
 {
 }

^ permalink raw reply	[flat|nested] 87+ messages in thread

* [PATCH 18/20] FRV: procfs changes for nommu changes
  2004-11-08 14:34 [PATCH 1/20] FRV: Fujitsu FR-V CPU arch maintainer record dhowells
                   ` (13 preceding siblings ...)
  2004-11-08 14:34 ` [PATCH 13/20] " dhowells
@ 2004-11-08 14:34 ` dhowells
  2004-11-08 14:34 ` [PATCH 20/20] FRV: Add FDPIC ELF binary format driver dhowells
  2004-11-08 14:34 ` [PATCH 19/20] FRV: change setup_arg_pages() to take stack pointer dhowells
  16 siblings, 0 replies; 87+ messages in thread
From: dhowells @ 2004-11-08 14:34 UTC (permalink / raw)
  To: torvalds, akpm, davidm; +Cc: linux-kernel, uclinux-dev

The attached patch splits some memory-related procfs files into MMU and !MMU
versions and places them in separate conditionally-compiled files. A header
file local to the fs/proc/ directory is used to declare functions and the like.

Additionally, a !MMU-only proc file (/proc/maps) is provided so that master VMA
list in a uClinux kernel is viewable.

Signed-Off-By: dhowells@redhat.com
---
diffstat nommu-proc-2610rc1mm3.diff
 Makefile     |    4 -
 array.c      |    1 
 base.c       |   43 ------------------
 internal.h   |   48 ++++++++++++++++++++
 mmu.c        |   67 ++++++++++++++++++++++++++++
 nommu.c      |  140 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 proc_misc.c  |   50 ++-------------------
 task_mmu.c   |   32 +++++++++++++
 task_nommu.c |   71 ++++++++++++++++++++++-------
 9 files changed, 350 insertions(+), 106 deletions(-)

diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/fs/proc/array.c linux-2.6.10-rc1-mm3-frv/fs/proc/array.c
--- /warthog/kernels/linux-2.6.10-rc1-mm3/fs/proc/array.c	2004-11-05 13:15:43.000000000 +0000
+++ linux-2.6.10-rc1-mm3-frv/fs/proc/array.c	2004-11-05 14:13:03.809503712 +0000
@@ -79,6 +79,7 @@
 #include <asm/pgtable.h>
 #include <asm/io.h>
 #include <asm/processor.h>
+#include "internal.h"
 
 /* Gcc optimizes away "strlen(x)" for constant x */
 #define ADDBUF(buffer, string) \
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/fs/proc/base.c linux-2.6.10-rc1-mm3-frv/fs/proc/base.c
--- /warthog/kernels/linux-2.6.10-rc1-mm3/fs/proc/base.c	2004-11-05 13:15:43.000000000 +0000
+++ linux-2.6.10-rc1-mm3-frv/fs/proc/base.c	2004-11-05 14:13:03.825502360 +0000
@@ -33,6 +33,7 @@
 #include <linux/mount.h>
 #include <linux/security.h>
 #include <linux/ptrace.h>
+#include "internal.h"
 
 /*
  * For hysterical raisins we keep the same inumbers as in the old procfs.
@@ -192,21 +193,6 @@ static struct pid_entry tid_attr_stuff[]
 
 #undef E
 
-static inline struct task_struct *proc_task(struct inode *inode)
-{
-	return PROC_I(inode)->task;
-}
-
-static inline int proc_type(struct inode *inode)
-{
-	return PROC_I(inode)->type;
-}
-
-int proc_tid_stat(struct task_struct*,char*);
-int proc_tgid_stat(struct task_struct*,char*);
-int proc_pid_status(struct task_struct*,char*);
-int proc_pid_statm(struct task_struct*,char*);
-
 static int proc_fd_link(struct inode *inode, struct dentry **dentry, struct vfsmount **mnt)
 {
 	struct task_struct *task = proc_task(inode);
@@ -231,33 +217,6 @@ static int proc_fd_link(struct inode *in
 	return -ENOENT;
 }
 
-static int proc_exe_link(struct inode *inode, struct dentry **dentry, struct vfsmount **mnt)
-{
-	struct vm_area_struct * vma;
-	int result = -ENOENT;
-	struct task_struct *task = proc_task(inode);
-	struct mm_struct * mm = get_task_mm(task);
-
-	if (!mm)
-		goto out;
-	down_read(&mm->mmap_sem);
-	vma = mm->mmap;
-	while (vma) {
-		if ((vma->vm_flags & VM_EXECUTABLE) && 
-		    vma->vm_file) {
-			*mnt = mntget(vma->vm_file->f_vfsmnt);
-			*dentry = dget(vma->vm_file->f_dentry);
-			result = 0;
-			break;
-		}
-		vma = vma->vm_next;
-	}
-	up_read(&mm->mmap_sem);
-	mmput(mm);
-out:
-	return result;
-}
-
 static int proc_cwd_link(struct inode *inode, struct dentry **dentry, struct vfsmount **mnt)
 {
 	struct fs_struct *fs;
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/fs/proc/internal.h linux-2.6.10-rc1-mm3-frv/fs/proc/internal.h
--- /warthog/kernels/linux-2.6.10-rc1-mm3/fs/proc/internal.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/fs/proc/internal.h	2004-11-05 14:13:03.830501938 +0000
@@ -0,0 +1,48 @@
+/* internal.h: internal procfs definitions
+ *
+ * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * 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.
+ */
+
+#include <linux/proc_fs.h>
+
+struct vmalloc_info {
+	unsigned long	used;
+	unsigned long	largest_chunk;
+};
+
+#ifdef CONFIG_MMU
+#define VMALLOC_TOTAL (VMALLOC_END - VMALLOC_START)
+extern void get_vmalloc_info(struct vmalloc_info *vmi);
+#else
+
+#define VMALLOC_TOTAL 0UL
+#define get_vmalloc_info(vmi)			\
+do {						\
+	(vmi)->used = 0;			\
+	(vmi)->largest_chunk = 0;		\
+} while(0)
+
+#endif
+
+extern void create_seq_entry(char *name, mode_t mode, struct file_operations *f);
+extern int proc_exe_link(struct inode *, struct dentry **, struct vfsmount **);
+extern int proc_tid_stat(struct task_struct *,  char *);
+extern int proc_tgid_stat(struct task_struct *, char *);
+extern int proc_pid_status(struct task_struct *, char *);
+extern int proc_pid_statm(struct task_struct *, char *);
+
+static inline struct task_struct *proc_task(struct inode *inode)
+{
+	return PROC_I(inode)->task;
+}
+
+static inline int proc_type(struct inode *inode)
+{
+	return PROC_I(inode)->type;
+}
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/fs/proc/Makefile linux-2.6.10-rc1-mm3-frv/fs/proc/Makefile
--- /warthog/kernels/linux-2.6.10-rc1-mm3/fs/proc/Makefile	2004-11-05 13:15:43.000000000 +0000
+++ linux-2.6.10-rc1-mm3-frv/fs/proc/Makefile	2004-11-05 14:13:03.839501178 +0000
@@ -4,8 +4,8 @@
 
 obj-$(CONFIG_PROC_FS) += proc.o
 
-proc-y			:= task_nommu.o
-proc-$(CONFIG_MMU)	:= task_mmu.o
+proc-y			:= nommu.o task_nommu.o
+proc-$(CONFIG_MMU)	:= mmu.o task_mmu.o
 
 proc-y       += inode.o root.o base.o generic.o array.o \
 		kmsg.o proc_tty.o proc_misc.o
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/fs/proc/mmu.c linux-2.6.10-rc1-mm3-frv/fs/proc/mmu.c
--- /warthog/kernels/linux-2.6.10-rc1-mm3/fs/proc/mmu.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/fs/proc/mmu.c	2004-11-05 14:13:03.000000000 +0000
@@ -0,0 +1,67 @@
+/* mmu.c: mmu memory info files
+ *
+ * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * 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.
+ */
+
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/time.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/mman.h>
+#include <linux/proc_fs.h>
+#include <linux/mm.h>
+#include <linux/mmzone.h>
+#include <linux/pagemap.h>
+#include <linux/swap.h>
+#include <linux/slab.h>
+#include <linux/smp.h>
+#include <linux/seq_file.h>
+#include <linux/hugetlb.h>
+#include <linux/vmalloc.h>
+#include <asm/uaccess.h>
+#include <asm/pgtable.h>
+#include <asm/tlb.h>
+#include <asm/div64.h>
+#include "internal.h"
+
+void get_vmalloc_info(struct vmalloc_info *vmi)
+{
+	struct vm_struct *vma;
+	unsigned long free_area_size;
+	unsigned long prev_end;
+
+	vmi->used = 0;
+
+	if (!vmlist) {
+		vmi->largest_chunk = VMALLOC_TOTAL;
+	}
+	else {
+		vmi->largest_chunk = 0;
+
+		prev_end = VMALLOC_START;
+
+		read_lock(&vmlist_lock);
+
+		for (vma = vmlist; vma; vma = vma->next) {
+			vmi->used += vma->size;
+
+			free_area_size = (unsigned long) vma->addr - prev_end;
+			if (vmi->largest_chunk < free_area_size)
+				vmi->largest_chunk = free_area_size;
+
+			prev_end = vma->size + (unsigned long) vma->addr;
+		}
+
+		if (VMALLOC_END - prev_end > vmi->largest_chunk)
+			vmi->largest_chunk = VMALLOC_END - prev_end;
+
+		read_unlock(&vmlist_lock);
+	}
+}
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/fs/proc/nommu.c linux-2.6.10-rc1-mm3-frv/fs/proc/nommu.c
--- /warthog/kernels/linux-2.6.10-rc1-mm3/fs/proc/nommu.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/fs/proc/nommu.c	2004-11-05 14:13:03.000000000 +0000
@@ -0,0 +1,140 @@
+/* nommu.c: mmu-less memory info files
+ *
+ * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * 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.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/time.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/mman.h>
+#include <linux/proc_fs.h>
+#include <linux/mm.h>
+#include <linux/mmzone.h>
+#include <linux/pagemap.h>
+#include <linux/swap.h>
+#include <linux/slab.h>
+#include <linux/smp.h>
+#include <linux/seq_file.h>
+#include <linux/hugetlb.h>
+#include <linux/vmalloc.h>
+#include <asm/uaccess.h>
+#include <asm/pgtable.h>
+#include <asm/tlb.h>
+#include <asm/div64.h>
+#include "internal.h"
+
+/*
+ * display a list of all the VMAs the kernel knows about
+ * - nommu kernals have a single flat list
+ */
+static int nommu_vma_list_show(struct seq_file *m, void *v)
+{
+	struct vm_area_struct *map;
+	unsigned long ino = 0;
+	struct file *file;
+	dev_t dev = 0;
+	int flags, len;
+
+	map = list_entry((struct list_head *) v,
+			 struct vm_area_struct, vm_link);
+
+	flags = map->vm_flags;
+	file = map->vm_file;
+
+	if (file) {
+		struct inode *inode = map->vm_file->f_dentry->d_inode;
+		dev = inode->i_sb->s_dev;
+		ino = inode->i_ino;
+	}
+
+	seq_printf(m,
+		   "%08lx-%08lx %c%c%c%c %08lx %02x:%02x %lu %n",
+		   map->vm_start,
+		   map->vm_end,
+		   flags & VM_READ ? 'r' : '-',
+		   flags & VM_WRITE ? 'w' : '-',
+		   flags & VM_EXEC ? 'x' : '-',
+		   flags & VM_MAYSHARE ? 's' : 'p',
+		   map->vm_pgoff << PAGE_SHIFT,
+		   MAJOR(dev), MINOR(dev), ino, &len);
+
+	if (file) {
+		len = 25 + sizeof(void *) * 6 - len;
+		if (len < 1)
+			len = 1;
+		seq_printf(m, "%*c", len, ' ');
+		seq_path(m, file->f_vfsmnt, file->f_dentry, "");
+	}
+
+	seq_putc(m, '\n');
+	return 0;
+}
+
+static void *nommu_vma_list_start(struct seq_file *m, loff_t *_pos)
+{
+	struct list_head *_p;
+	loff_t pos = *_pos;
+	void *next = NULL;
+
+	down_read(&nommu_vma_sem);
+
+	list_for_each(_p, &nommu_vma_list) {
+		if (pos == 0) {
+			next = _p;
+			break;
+		}
+	}
+
+	return next;
+}
+
+static void nommu_vma_list_stop(struct seq_file *m, void *v)
+{
+	up_read(&nommu_vma_sem);
+}
+
+static void *nommu_vma_list_next(struct seq_file *m, void *v, loff_t *pos)
+{
+	struct list_head *_p = v;
+
+	(*pos)++;
+
+	_p = _p->next;
+	return (_p != &nommu_vma_list) ? _p : NULL;
+}
+
+static struct seq_operations proc_nommu_vma_list_seqop = {
+	.start	= nommu_vma_list_start,
+	.next	= nommu_vma_list_next,
+	.stop	= nommu_vma_list_stop,
+	.show	= nommu_vma_list_show
+};
+
+static int proc_nommu_vma_list_open(struct inode *inode, struct file *file)
+{
+	return seq_open(file, &proc_nommu_vma_list_seqop);
+}
+
+static struct file_operations proc_nommu_vma_list_operations = {
+	.open    = proc_nommu_vma_list_open,
+	.read    = seq_read,
+	.llseek  = seq_lseek,
+	.release = seq_release,
+};
+
+static int __init proc_nommu_init(void)
+{
+	create_seq_entry("maps", S_IRUGO, &proc_nommu_vma_list_operations);
+	return 0;
+}
+
+module_init(proc_nommu_init);
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/fs/proc/proc_misc.c linux-2.6.10-rc1-mm3-frv/fs/proc/proc_misc.c
--- /warthog/kernels/linux-2.6.10-rc1-mm3/fs/proc/proc_misc.c	2004-11-05 13:15:43.000000000 +0000
+++ linux-2.6.10-rc1-mm3-frv/fs/proc/proc_misc.c	2004-11-05 14:13:03.865498982 +0000
@@ -50,6 +50,7 @@
 #include <asm/io.h>
 #include <asm/tlb.h>
 #include <asm/div64.h>
+#include "internal.h"
 
 #define LOAD_INT(x) ((x) >> FSHIFT)
 #define LOAD_FRAC(x) LOAD_INT(((x) & (FIXED_1-1)) * 100)
@@ -96,41 +97,6 @@ static int loadavg_read_proc(char *page,
 	return proc_calc_metrics(page, start, off, count, eof, len);
 }
 
-struct vmalloc_info {
-	unsigned long used;
-	unsigned long largest_chunk;
-};
-
-static struct vmalloc_info get_vmalloc_info(void)
-{
-	unsigned long prev_end = VMALLOC_START;
-	struct vm_struct* vma;
-	struct vmalloc_info vmi;
-	vmi.used = 0;
-
-	read_lock(&vmlist_lock);
-
-	if(!vmlist)
-		vmi.largest_chunk = (VMALLOC_END-VMALLOC_START);
-	else
-		vmi.largest_chunk = 0;
-
-	for (vma = vmlist; vma; vma = vma->next) {
-		unsigned long free_area_size =
-			(unsigned long)vma->addr - prev_end;
-		vmi.used += vma->size;
-		if (vmi.largest_chunk < free_area_size )
-
-			vmi.largest_chunk = free_area_size;
-		prev_end = vma->size + (unsigned long)vma->addr;
-	}
-	if(VMALLOC_END-prev_end > vmi.largest_chunk)
-		vmi.largest_chunk = VMALLOC_END-prev_end;
-
-	read_unlock(&vmlist_lock);
-	return vmi;
-}
-
 static int uptime_read_proc(char *page, char **start, off_t off,
 				 int count, int *eof, void *data)
 {
@@ -159,7 +125,6 @@ static int meminfo_read_proc(char *page,
 	unsigned long inactive;
 	unsigned long active;
 	unsigned long free;
-	unsigned long vmtot;
 	unsigned long committed;
 	unsigned long allowed;
 	struct vmalloc_info vmi;
@@ -177,10 +142,7 @@ static int meminfo_read_proc(char *page,
 	allowed = ((totalram_pages - hugetlb_total_pages())
 		* sysctl_overcommit_ratio / 100) + total_swap_pages;
 
-	vmtot = (VMALLOC_END-VMALLOC_START)>>10;
-	vmi = get_vmalloc_info();
-	vmi.used >>= 10;
-	vmi.largest_chunk >>= 10;
+	get_vmalloc_info(&vmi);
 
 	/*
 	 * Tagged format, for easy grepping and expansion.
@@ -229,9 +191,9 @@ static int meminfo_read_proc(char *page,
 		K(allowed),
 		K(committed),
 		K(ps.nr_page_table_pages),
-		vmtot,
-		vmi.used,
-		vmi.largest_chunk
+		VMALLOC_TOTAL >> 10,
+		vmi.used >> 10,
+		vmi.largest_chunk >> 10
 		);
 
 		len += hugetlb_report_meminfo(page + len);
@@ -578,7 +539,7 @@ static struct file_operations proc_sysrq
 
 struct proc_dir_entry *proc_root_kcore;
 
-static void create_seq_entry(char *name, mode_t mode, struct file_operations *f)
+void create_seq_entry(char *name, mode_t mode, struct file_operations *f)
 {
 	struct proc_dir_entry *entry;
 	entry = create_proc_entry(name, mode, NULL);
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/fs/proc/task_mmu.c linux-2.6.10-rc1-mm3-frv/fs/proc/task_mmu.c
--- /warthog/kernels/linux-2.6.10-rc1-mm3/fs/proc/task_mmu.c	2004-11-05 13:15:44.000000000 +0000
+++ linux-2.6.10-rc1-mm3-frv/fs/proc/task_mmu.c	2004-11-05 14:13:03.000000000 +0000
@@ -1,8 +1,10 @@
 #include <linux/mm.h>
 #include <linux/hugetlb.h>
+#include <linux/mount.h>
 #include <linux/seq_file.h>
 #include <asm/elf.h>
 #include <asm/uaccess.h>
+#include "internal.h"
 
 char *task_mem(struct mm_struct *mm, char *buffer)
 {
@@ -45,6 +47,36 @@ int task_statm(struct mm_struct *mm, int
 	return mm->total_vm;
 }
 
+int proc_exe_link(struct inode *inode, struct dentry **dentry, struct vfsmount **mnt)
+{
+	struct vm_area_struct * vma;
+	int result = -ENOENT;
+	struct task_struct *task = proc_task(inode);
+	struct mm_struct * mm = get_task_mm(task);
+
+	if (!mm)
+		goto out;
+	down_read(&mm->mmap_sem);
+
+	vma = mm->mmap;
+	while (vma) {
+		if ((vma->vm_flags & VM_EXECUTABLE) && vma->vm_file)
+			break;
+		vma = vma->vm_next;
+	}
+
+	if (vma) {
+		*mnt = mntget(vma->vm_file->f_vfsmnt);
+		*dentry = dget(vma->vm_file->f_dentry);
+		result = 0;
+	}
+
+	up_read(&mm->mmap_sem);
+	mmput(mm);
+out:
+	return result;
+}
+
 static int show_map(struct seq_file *m, void *v)
 {
 	struct vm_area_struct *map = v;
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/fs/proc/task_nommu.c linux-2.6.10-rc1-mm3-frv/fs/proc/task_nommu.c
--- /warthog/kernels/linux-2.6.10-rc1-mm3/fs/proc/task_nommu.c	2004-10-19 10:42:09.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/fs/proc/task_nommu.c	2004-11-05 14:13:03.000000000 +0000
@@ -1,7 +1,9 @@
 
 #include <linux/mm.h>
 #include <linux/file.h>
+#include <linux/mount.h>
 #include <linux/seq_file.h>
+#include "internal.h"
 
 /*
  * Logic: we've got two memory sums for each process, "shared", and
@@ -15,19 +17,19 @@ char *task_mem(struct mm_struct *mm, cha
 	struct mm_tblock_struct *tblock;
         
 	down_read(&mm->mmap_sem);
-	for (tblock = &mm->context.tblock; tblock; tblock = tblock->next) {
-		if (!tblock->rblock)
+	for (tblock = mm->context.tblock; tblock; tblock = tblock->next) {
+		if (!tblock->vma)
 			continue;
 		bytes += kobjsize(tblock);
 		if (atomic_read(&mm->mm_count) > 1 ||
-		    tblock->rblock->refcount > 1) {
-			sbytes += kobjsize(tblock->rblock->kblock);
-			sbytes += kobjsize(tblock->rblock);
+		    atomic_read(&tblock->vma->vm_usage) > 1) {
+			sbytes += kobjsize((void *) tblock->vma->vm_start);
+			sbytes += kobjsize(tblock->vma);
 		} else {
-			bytes += kobjsize(tblock->rblock->kblock);
-			bytes += kobjsize(tblock->rblock);
-			slack += kobjsize(tblock->rblock->kblock) -
-					tblock->rblock->size;
+			bytes += kobjsize((void *) tblock->vma->vm_start);
+			bytes += kobjsize(tblock->vma);
+			slack += kobjsize((void *) tblock->vma->vm_start) -
+				(tblock->vma->vm_end - tblock->vma->vm_start);
 		}
 	}
 
@@ -69,9 +71,9 @@ unsigned long task_vsize(struct mm_struc
 	unsigned long vsize = 0;
 
 	down_read(&mm->mmap_sem);
-	for (tbp = &mm->context.tblock; tbp; tbp = tbp->next) {
-		if (tbp->rblock)
-			vsize += kobjsize(tbp->rblock->kblock);
+	for (tbp = mm->context.tblock; tbp; tbp = tbp->next) {
+		if (tbp->vma)
+			vsize += kobjsize((void *) tbp->vma->vm_start);
 	}
 	up_read(&mm->mmap_sem);
 	return vsize;
@@ -84,12 +86,11 @@ int task_statm(struct mm_struct *mm, int
 	int size = kobjsize(mm);
 
 	down_read(&mm->mmap_sem);
-	for (tbp = &mm->context.tblock; tbp; tbp = tbp->next) {
-		if (tbp->next)
-			size += kobjsize(tbp->next);
-		if (tbp->rblock) {
-			size += kobjsize(tbp->rblock);
-			size += kobjsize(tbp->rblock->kblock);
+	for (tbp = mm->context.tblock; tbp; tbp = tbp->next) {
+		size += kobjsize(tbp);
+		if (tbp->vma) {
+			size += kobjsize(tbp->vma);
+			size += kobjsize((void *) tbp->vma->vm_start);
 		}
 	}
 
@@ -100,6 +101,40 @@ int task_statm(struct mm_struct *mm, int
 	return size;
 }
 
+int proc_exe_link(struct inode *inode, struct dentry **dentry, struct vfsmount **mnt)
+{
+	struct mm_tblock_struct *tblock;
+	struct vm_area_struct * vma;
+	int result = -ENOENT;
+	struct task_struct *task = proc_task(inode);
+	struct mm_struct * mm = get_task_mm(task);
+
+	if (!mm)
+		goto out;
+	down_read(&mm->mmap_sem);
+
+	tblock = mm->context.tblock;
+	vma = NULL;
+	while (tblock) {
+		if ((tblock->vma->vm_flags & VM_EXECUTABLE) && tblock->vma->vm_file) {
+			vma = tblock->vma;
+			break;
+		}
+		tblock = tblock->next;
+	}
+
+	if (vma) {
+		*mnt = mntget(vma->vm_file->f_vfsmnt);
+		*dentry = dget(vma->vm_file->f_dentry);
+		result = 0;
+	}
+
+	up_read(&mm->mmap_sem);
+	mmput(mm);
+out:
+	return result;
+}
+
 /*
  * Albert D. Cahalan suggested to fake entries for the traditional
  * sections here.  This might be worth investigating.

^ permalink raw reply	[flat|nested] 87+ messages in thread

* [PATCH 19/20] FRV: change setup_arg_pages() to take stack pointer
  2004-11-08 14:34 [PATCH 1/20] FRV: Fujitsu FR-V CPU arch maintainer record dhowells
                   ` (15 preceding siblings ...)
  2004-11-08 14:34 ` [PATCH 20/20] FRV: Add FDPIC ELF binary format driver dhowells
@ 2004-11-08 14:34 ` dhowells
  16 siblings, 0 replies; 87+ messages in thread
From: dhowells @ 2004-11-08 14:34 UTC (permalink / raw)
  To: torvalds, akpm, davidm; +Cc: linux-kernel, uclinux-dev

The attached patch changes setup_arg_pages() to take the proposed initial stack
top for the new executable image. This makes it easier for the binfmt to place
the stack at a non-fixed location, such as happens in !MMU configurations.

Signed-Off-By: dhowells@redhat.com
---
diffstat setup_arg_pages-2610rc1mm3.diff
 arch/x86_64/ia32/ia32_aout.c   |    5 +++--
 arch/x86_64/ia32/ia32_binfmt.c |    7 ++++---
 fs/binfmt_aout.c               |    2 +-
 fs/binfmt_elf.c                |    2 +-
 fs/binfmt_som.c                |    2 +-
 fs/exec.c                      |   12 +++++++-----
 include/linux/binfmts.h        |    4 +++-
 7 files changed, 20 insertions(+), 14 deletions(-)

diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/arch/x86_64/ia32/ia32_aout.c linux-2.6.10-rc1-mm3-frv/arch/x86_64/ia32/ia32_aout.c
--- /warthog/kernels/linux-2.6.10-rc1-mm3/arch/x86_64/ia32/ia32_aout.c	2004-10-27 17:32:14.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/arch/x86_64/ia32/ia32_aout.c	2004-11-05 14:13:03.000000000 +0000
@@ -35,7 +35,8 @@
 #undef WARN_OLD
 #undef CORE_DUMP /* probably broken */
 
-extern int ia32_setup_arg_pages(struct linux_binprm *bprm, int exec_stack);
+extern int ia32_setup_arg_pages(struct linux_binprm *bprm,
+				unsigned long stack_top, int exec_stack);
 
 static int load_aout_binary(struct linux_binprm *, struct pt_regs * regs);
 static int load_aout_library(struct file*);
@@ -396,7 +397,7 @@ beyond_if:
 
 	set_brk(current->mm->start_brk, current->mm->brk);
 
-	retval = ia32_setup_arg_pages(bprm, EXSTACK_DEFAULT);
+	retval = ia32_setup_arg_pages(bprm, IA32_STACK_TOP, EXSTACK_DEFAULT);
 	if (retval < 0) { 
 		/* Someone check-me: is this error path enough? */ 
 		send_sig(SIGKILL, current, 0); 
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/arch/x86_64/ia32/ia32_binfmt.c linux-2.6.10-rc1-mm3-frv/arch/x86_64/ia32/ia32_binfmt.c
--- /warthog/kernels/linux-2.6.10-rc1-mm3/arch/x86_64/ia32/ia32_binfmt.c	2004-10-27 17:32:14.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/arch/x86_64/ia32/ia32_binfmt.c	2004-11-05 14:13:03.000000000 +0000
@@ -273,8 +273,9 @@ do {							\
 #define load_elf_binary load_elf32_binary
 
 #define ELF_PLAT_INIT(r, load_addr)	elf32_init(r)
-#define setup_arg_pages(bprm, exec_stack)	ia32_setup_arg_pages(bprm, exec_stack)
-int ia32_setup_arg_pages(struct linux_binprm *bprm, int executable_stack);
+#define setup_arg_pages(bprm, stack_top, exec_stack) \
+	ia32_setup_arg_pages(bprm, stack_top, exec_stack)
+int ia32_setup_arg_pages(struct linux_binprm *bprm, unsigned long stack_top, int executable_stack);
 
 #undef start_thread
 #define start_thread(regs,new_rip,new_rsp) do { \
@@ -329,7 +330,7 @@ static void elf32_init(struct pt_regs *r
 	me->thread.es = __USER_DS;
 }
 
-int setup_arg_pages(struct linux_binprm *bprm, int executable_stack)
+int setup_arg_pages(struct linux_binprm *bprm, unsigned long stack_top, int executable_stack)
 {
 	unsigned long stack_base;
 	struct vm_area_struct *mpnt;
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/fs/binfmt_aout.c linux-2.6.10-rc1-mm3-frv/fs/binfmt_aout.c
--- /warthog/kernels/linux-2.6.10-rc1-mm3/fs/binfmt_aout.c	2004-10-27 17:32:30.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/fs/binfmt_aout.c	2004-11-05 14:13:03.000000000 +0000
@@ -415,7 +415,7 @@ beyond_if:
 
 	set_brk(current->mm->start_brk, current->mm->brk);
 
-	retval = setup_arg_pages(bprm, EXSTACK_DEFAULT);
+	retval = setup_arg_pages(bprm, STACK_TOP, EXSTACK_DEFAULT);
 	if (retval < 0) { 
 		/* Someone check-me: is this error path enough? */ 
 		send_sig(SIGKILL, current, 0); 
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/fs/binfmt_elf.c linux-2.6.10-rc1-mm3-frv/fs/binfmt_elf.c
--- /warthog/kernels/linux-2.6.10-rc1-mm3/fs/binfmt_elf.c	2004-11-05 13:15:39.000000000 +0000
+++ linux-2.6.10-rc1-mm3-frv/fs/binfmt_elf.c	2004-11-05 14:13:03.000000000 +0000
@@ -718,7 +718,7 @@ static int load_elf_binary(struct linux_
 	   change some of these later */
 	current->mm->rss = 0;
 	current->mm->free_area_cache = current->mm->mmap_base;
-	retval = setup_arg_pages(bprm, executable_stack);
+	retval = setup_arg_pages(bprm, STACK_TOP, executable_stack);
 	if (retval < 0) {
 		send_sig(SIGKILL, current, 0);
 		goto out_free_dentry;
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/fs/binfmt_som.c linux-2.6.10-rc1-mm3-frv/fs/binfmt_som.c
--- /warthog/kernels/linux-2.6.10-rc1-mm3/fs/binfmt_som.c	2004-06-18 13:43:59.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/fs/binfmt_som.c	2004-11-05 14:13:03.000000000 +0000
@@ -254,7 +254,7 @@ load_som_binary(struct linux_binprm * bp
 
 	set_binfmt(&som_format);
 	compute_creds(bprm);
-	setup_arg_pages(bprm, EXSTACK_DEFAULT);
+	setup_arg_pages(bprm, STACK_TOP, EXSTACK_DEFAULT);
 
 	create_som_tables(bprm);
 
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/fs/exec.c linux-2.6.10-rc1-mm3-frv/fs/exec.c
--- /warthog/kernels/linux-2.6.10-rc1-mm3/fs/exec.c	2004-11-05 13:15:39.000000000 +0000
+++ linux-2.6.10-rc1-mm3-frv/fs/exec.c	2004-11-05 14:13:03.769507090 +0000
@@ -342,7 +341,9 @@ out_sig:
 	force_sig(SIGKILL, current);
 }
 
-int setup_arg_pages(struct linux_binprm *bprm, int executable_stack)
+int setup_arg_pages(struct linux_binprm *bprm,
+		    unsigned long stack_top,
+		    int executable_stack)
 {
 	unsigned long stack_base;
 	struct vm_area_struct *mpnt;
@@ -386,7 +387,7 @@ int setup_arg_pages(struct linux_binprm 
 	stack_base = current->signal->rlim[RLIMIT_STACK].rlim_max;
 	if (stack_base > (1 << 30))
 		stack_base = 1 << 30;
-	stack_base = PAGE_ALIGN(STACK_TOP - stack_base);
+	stack_base = PAGE_ALIGN(stack_top - stack_base);
 
 	mm->arg_start = stack_base;
 	arg_size = i << PAGE_SHIFT;
@@ -395,9 +396,9 @@ int setup_arg_pages(struct linux_binprm 
 	while (i < MAX_ARG_PAGES)
 		bprm->page[i++] = NULL;
 #else
-	stack_base = STACK_TOP - MAX_ARG_PAGES * PAGE_SIZE;
+	stack_base = stack_top - MAX_ARG_PAGES * PAGE_SIZE;
 	mm->arg_start = bprm->p + stack_base;
-	arg_size = STACK_TOP - (PAGE_MASK & (unsigned long) mm->arg_start);
+	arg_size = stack_top - (PAGE_MASK & (unsigned long) mm->arg_start);
 #endif
 
 	bprm->p += stack_base;
@@ -425,7 +426,7 @@ int setup_arg_pages(struct linux_binprm 
 			(PAGE_SIZE - 1 + (unsigned long) bprm->p);
 #else
 		mpnt->vm_start = PAGE_MASK & (unsigned long) bprm->p;
-		mpnt->vm_end = STACK_TOP;
+		mpnt->vm_end = stack_top;
 #endif
 		/* Adjust stack execute permissions; explicitly enable
 		 * for EXSTACK_ENABLE_X, disable for EXSTACK_DISABLE_X
diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/include/linux/binfmts.h linux-2.6.10-rc1-mm3-frv/include/linux/binfmts.h
--- /warthog/kernels/linux-2.6.10-rc1-mm3/include/linux/binfmts.h	2004-09-16 12:06:20.000000000 +0100
+++ linux-2.6.10-rc1-mm3-frv/include/linux/binfmts.h	2004-11-05 14:13:04.353457768 +0000
@@ -74,7 +74,9 @@ extern int flush_old_exec(struct linux_b
 #define EXSTACK_DISABLE_X 1	/* Disable executable stacks */
 #define EXSTACK_ENABLE_X  2	/* Enable executable stacks */
 
-extern int setup_arg_pages(struct linux_binprm * bprm, int executable_stack);
+extern int setup_arg_pages(struct linux_binprm * bprm,
+			   unsigned long stack_top,
+			   int executable_stack);
 extern int copy_strings(int argc,char __user * __user * argv,struct linux_binprm *bprm); 
 extern int copy_strings_kernel(int argc,char ** argv,struct linux_binprm *bprm);
 extern void compute_creds(struct linux_binprm *binprm);

^ permalink raw reply	[flat|nested] 87+ messages in thread

* Re: [PATCH 17/20] FRV: Better mmap support in uClinux
  2004-11-08 14:34   ` [PATCH 17/20] " dhowells
@ 2004-11-09 12:57     ` Christoph Hellwig
  2004-11-09 13:55     ` David Howells
                       ` (2 subsequent siblings)
  3 siblings, 0 replies; 87+ messages in thread
From: Christoph Hellwig @ 2004-11-09 12:57 UTC (permalink / raw)
  To: dhowells; +Cc: torvalds, akpm, davidm, linux-kernel, uclinux-dev

> +/* list of shareable VMAs */
> +LIST_HEAD(nommu_vma_list);
> +DECLARE_RWSEM(nommu_vma_sem);

As I told you this absolutely should be static.


^ permalink raw reply	[flat|nested] 87+ messages in thread

* Re: [PATCH 17/20] FRV: Better mmap support in uClinux
  2004-11-08 14:34   ` [PATCH 17/20] " dhowells
  2004-11-09 12:57     ` Christoph Hellwig
@ 2004-11-09 13:55     ` David Howells
  2004-11-09 14:02       ` Christoph Hellwig
  2004-11-19  5:29     ` Matt Mackall
  2004-11-19 16:26     ` David Howells
  3 siblings, 1 reply; 87+ messages in thread
From: David Howells @ 2004-11-09 13:55 UTC (permalink / raw)
  To: Christoph Hellwig; +Cc: torvalds, akpm, davidm, linux-kernel, uclinux-dev


> > +/* list of shareable VMAs */
> > +LIST_HEAD(nommu_vma_list);
> > +DECLARE_RWSEM(nommu_vma_sem);
> 
> As I told you this absolutely should be static.

Yes, you did. I ignored you. You also said that I shouldn't put any proc stuff
in mm/.

David

^ permalink raw reply	[flat|nested] 87+ messages in thread

* Re: [PATCH 17/20] FRV: Better mmap support in uClinux
  2004-11-09 13:55     ` David Howells
@ 2004-11-09 14:02       ` Christoph Hellwig
  0 siblings, 0 replies; 87+ messages in thread
From: Christoph Hellwig @ 2004-11-09 14:02 UTC (permalink / raw)
  To: David Howells
  Cc: Christoph Hellwig, torvalds, akpm, davidm, linux-kernel, uclinux-dev

On Tue, Nov 09, 2004 at 01:55:26PM +0000, David Howells wrote:
> 
> > > +/* list of shareable VMAs */
> > > +LIST_HEAD(nommu_vma_list);
> > > +DECLARE_RWSEM(nommu_vma_sem);
> > 
> > As I told you this absolutely should be static.
> 
> Yes, you did. I ignored you. You also said that I shouldn't put any proc stuff
> in mm/.

I didn't say you should put any proc stuff into mm/ but that's it propably
more readablewhen kept in fs/proc/.

But again - global lists are really, really bad.  If you want to access it
add proper acessor functions.


^ permalink raw reply	[flat|nested] 87+ messages in thread

* Re: [PATCH 7/20] FRV: Fujitsu FR-V CPU arch implementation part 5
  2004-11-08 14:34 ` [PATCH 7/20] FRV: Fujitsu FR-V CPU arch implementation part 5 dhowells
@ 2004-11-09 15:09   ` Geert Uytterhoeven
  0 siblings, 0 replies; 87+ messages in thread
From: Geert Uytterhoeven @ 2004-11-09 15:09 UTC (permalink / raw)
  To: dhowells
  Cc: Linus Torvalds, Andrew Morton, davidm, Linux Kernel Development,
	uClinux list

On Mon, 8 Nov 2004 dhowells@redhat.com wrote:
> --- /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/kernel/ptrace.c	1970-01-01 01:00:00.000000000 +0100
> +++ linux-2.6.10-rc1-mm3-frv/arch/frv/kernel/ptrace.c	2004-11-05 14:13:03.199555230 +0000
> @@ -0,0 +1,771 @@
> +/*
> + *  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

Although we feel flattered that some components of the FRV port are based on
the m68k port, perhaps you can update the actual pathnames in the source files?
:-)

The same comment is valid for arch/frv/kernel/time.c.

Gr{oetje,eeting}s,

						Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
							    -- Linus Torvalds

^ permalink raw reply	[flat|nested] 87+ messages in thread

* Re: [PATCH 12/14] FRV: Generate more useful debug info
  2004-11-02 11:21   ` David Howells
  2004-11-03  1:48     ` Linus Torvalds
@ 2004-11-12 14:57     ` Daniel Jacobowitz
  2004-11-12 15:15     ` David Howells
  2 siblings, 0 replies; 87+ messages in thread
From: Daniel Jacobowitz @ 2004-11-12 14:57 UTC (permalink / raw)
  To: David Howells; +Cc: linux-kernel

On Tue, Nov 02, 2004 at 11:21:36AM +0000, David Howells wrote:
> 
> > Generates rejects against Sam's tree and appears to be unrelated to FRV,
> > yes?
> 
> I know not Sam's tree.
> 
> It's a generic thing. "gcc -g" does not cause compiled .S files to include
> debugging information, and -O1 optimised code is more debuggable than -O2
> optimised code.

FYI, "gcc -g" _should_ cause .S files to include assembler debugging
information.  If it doesn't, that's a bug in your port.

*asm_debug:
%{gstabs*:--gstabs}%{!gstabs*:%{g*:--gdwarf2}}

-- 
Daniel Jacobowitz

^ permalink raw reply	[flat|nested] 87+ messages in thread

* Re: [PATCH 12/14] FRV: Generate more useful debug info
  2004-11-02 11:21   ` David Howells
  2004-11-03  1:48     ` Linus Torvalds
  2004-11-12 14:57     ` Daniel Jacobowitz
@ 2004-11-12 15:15     ` David Howells
  2004-11-12 15:20       ` Daniel Jacobowitz
  2 siblings, 1 reply; 87+ messages in thread
From: David Howells @ 2004-11-12 15:15 UTC (permalink / raw)
  To: Daniel Jacobowitz; +Cc: linux-kernel


> FYI, "gcc -g" _should_ cause .S files to include assembler debugging
> information.  If it doesn't, that's a bug in your port.

It appears you may have a point. Running FRV compiler with gcc -g on a .S file
does not pass any sort of -g flag to the assembler. It does with the i386
compiler.

David

^ permalink raw reply	[flat|nested] 87+ messages in thread

* Re: [PATCH 12/14] FRV: Generate more useful debug info
  2004-11-12 15:15     ` David Howells
@ 2004-11-12 15:20       ` Daniel Jacobowitz
  0 siblings, 0 replies; 87+ messages in thread
From: Daniel Jacobowitz @ 2004-11-12 15:20 UTC (permalink / raw)
  To: David Howells; +Cc: linux-kernel

On Fri, Nov 12, 2004 at 03:15:18PM +0000, David Howells wrote:
> 
> > FYI, "gcc -g" _should_ cause .S files to include assembler debugging
> > information.  If it doesn't, that's a bug in your port.
> 
> It appears you may have a point. Running FRV compiler with gcc -g on a .S file
> does not pass any sort of -g flag to the assembler. It does with the i386
> compiler.

You're probably not selecting the right assembler to feature-test at
build time.  Check these:
     && defined(HAVE_AS_GDWARF2_DEBUG_FLAG) && defined(HAVE_AS_GSTABS_DEBUG_FLAG)

-- 
Daniel Jacobowitz

^ permalink raw reply	[flat|nested] 87+ messages in thread

* Re: [PATCH 17/20] FRV: Better mmap support in uClinux
  2004-11-08 14:34   ` [PATCH 17/20] " dhowells
  2004-11-09 12:57     ` Christoph Hellwig
  2004-11-09 13:55     ` David Howells
@ 2004-11-19  5:29     ` Matt Mackall
  2004-11-19 16:26     ` David Howells
  3 siblings, 0 replies; 87+ messages in thread
From: Matt Mackall @ 2004-11-19  5:29 UTC (permalink / raw)
  To: dhowells; +Cc: torvalds, akpm, davidm, linux-kernel, uclinux-dev

On Mon, Nov 08, 2004 at 02:34:20PM +0000, dhowells@redhat.com wrote:

>  (3) Files (and blockdevs) cannot be mapped shared since it is not
>  really possible to honour this by writing any changes back to the
>  backing device.

[way behind on email]

I think this could be done at msync, munmap and exit time? You end up
flushing the entire mapping, but it's still correct (and POSIX
compliant).

And, if you wanted to be really clever, you could store a hash of each
page to detect changes and avoid the extra I/O.

-- 
Mathematics is the supreme nostalgia of our time.

^ permalink raw reply	[flat|nested] 87+ messages in thread

* Re: [PATCH 17/20] FRV: Better mmap support in uClinux
  2004-11-08 14:34   ` [PATCH 17/20] " dhowells
                       ` (2 preceding siblings ...)
  2004-11-19  5:29     ` Matt Mackall
@ 2004-11-19 16:26     ` David Howells
  2004-11-19 16:56       ` Matt Mackall
  2004-11-19 17:06       ` David Howells
  3 siblings, 2 replies; 87+ messages in thread
From: David Howells @ 2004-11-19 16:26 UTC (permalink / raw)
  To: Matt Mackall; +Cc: torvalds, akpm, davidm, linux-kernel, uclinux-dev


> >  (3) Files (and blockdevs) cannot be mapped shared since it is not
> >  really possible to honour this by writing any changes back to the
> >  backing device.
> 
> [way behind on email]
> 
> I think this could be done at msync, munmap and exit time? You end up
> flushing the entire mapping, but it's still correct (and POSIX
> compliant).

Don't forget write() too. If someone does a write, that would have to be
written over the mapping too. Obviously this is not impossible.

> And, if you wanted to be really clever, you could store a hash of each
> page to detect changes and avoid the extra I/O.

It'd probably have to be something like an md5 sum.

Okay, technically, we could probably emulate it, but is it worth it? I think
it's something to bear in mind for another time.

More to the point, perhaps, is making shared memory stuff work.

David

^ permalink raw reply	[flat|nested] 87+ messages in thread

* Re: [PATCH 17/20] FRV: Better mmap support in uClinux
  2004-11-19 16:26     ` David Howells
@ 2004-11-19 16:56       ` Matt Mackall
  2004-11-19 17:06       ` David Howells
  1 sibling, 0 replies; 87+ messages in thread
From: Matt Mackall @ 2004-11-19 16:56 UTC (permalink / raw)
  To: David Howells; +Cc: torvalds, akpm, davidm, linux-kernel, uclinux-dev

On Fri, Nov 19, 2004 at 04:26:43PM +0000, David Howells wrote:
> 
> > >  (3) Files (and blockdevs) cannot be mapped shared since it is not
> > >  really possible to honour this by writing any changes back to the
> > >  backing device.
> > 
> > [way behind on email]
> > 
> > I think this could be done at msync, munmap and exit time? You end up
> > flushing the entire mapping, but it's still correct (and POSIX
> > compliant).
> 
> Don't forget write() too. If someone does a write, that would have to be
> written over the mapping too. Obviously this is not impossible.

I don't see such a requirement, but it'd be nice, yes.
 
> > And, if you wanted to be really clever, you could store a hash of each
> > page to detect changes and avoid the extra I/O.
> 
> It'd probably have to be something like an md5 sum.

Arguably, it needn't be cryptographically strong. But that's another
discussion.

> Okay, technically, we could probably emulate it, but is it worth it? I think
> it's something to bear in mind for another time.

Well I wasn't volunteering, just pointing out it's not as hard as
claimed. Thankfully all the boxes I currently have to care about are
not so special.

-- 
Mathematics is the supreme nostalgia of our time.

^ permalink raw reply	[flat|nested] 87+ messages in thread

* Re: [PATCH 17/20] FRV: Better mmap support in uClinux
  2004-11-19 16:26     ` David Howells
  2004-11-19 16:56       ` Matt Mackall
@ 2004-11-19 17:06       ` David Howells
  2004-11-19 17:42         ` Linus Torvalds
  1 sibling, 1 reply; 87+ messages in thread
From: David Howells @ 2004-11-19 17:06 UTC (permalink / raw)
  To: Matt Mackall; +Cc: torvalds, akpm, davidm, linux-kernel, uclinux-dev


> > Don't forget write() too. If someone does a write, that would have to be
> > written over the mapping too. Obviously this is not impossible.
> 
> I don't see such a requirement, but it'd be nice, yes.

I think it is a requirement. With normal Linux, if you do a write that crosses
a shared mmap it will change the mmapped data.

David

^ permalink raw reply	[flat|nested] 87+ messages in thread

* Re: [PATCH 17/20] FRV: Better mmap support in uClinux
  2004-11-19 17:06       ` David Howells
@ 2004-11-19 17:42         ` Linus Torvalds
  0 siblings, 0 replies; 87+ messages in thread
From: Linus Torvalds @ 2004-11-19 17:42 UTC (permalink / raw)
  To: David Howells; +Cc: Matt Mackall, akpm, davidm, linux-kernel, uclinux-dev



On Fri, 19 Nov 2004, David Howells wrote:
> 
> > > Don't forget write() too. If someone does a write, that would have to be
> > > written over the mapping too. Obviously this is not impossible.
> > 
> > I don't see such a requirement, but it'd be nice, yes.
> 
> I think it is a requirement. With normal Linux, if you do a write that crosses
> a shared mmap it will change the mmapped data.

Indeed. 

Some other UNIXes are broken in this regard, and there are cache coherency 
issues on some platforms that people who depend on this behaviour may need 
to be aware of, but in general Linux has always gone for coherenct mmap's.

POSIX doesn't require it, but quite frankly, non-coherent shared mmap just 
isn't worth it. You might as well not support it at all at that point.

[ I think at least HP-UX used to be broken in this regard, but HP-UX had
  such atrocious mmap behaviour _anyway_ that I don't understand how
  anybody could use it (you couldn't munmap partial mappings etc). I think
  they finally fixed it a few years ago and updated their source base from
  some totally ancient BSD to something a bit more modern. ]

			Linus

^ permalink raw reply	[flat|nested] 87+ messages in thread

end of thread, other threads:[~2004-11-19 17:42 UTC | newest]

Thread overview: 87+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <76b4a884-2c3c-11d9-91a1-0002b3163499@redhat.com>
2004-11-01 19:30 ` [PATCH 4/14] FRV: Bitops fixes dhowells
2004-11-02  8:19   ` Andrew Morton
2004-11-01 19:30 ` [PATCH 3/14] FRV: Fujitsu FR-V arch documentation dhowells
2004-11-01 19:30 ` [PATCH 5/14] FRV: Fork fixes dhowells
2004-11-01 19:30 ` [PATCH 8/14] FRV: GP-REL data support dhowells
2004-11-02  8:18   ` Andrew Morton
2004-11-02  9:48   ` Christoph Hellwig
2004-11-02 16:34   ` David Howells
2004-11-03 10:42     ` Christoph Hellwig
2004-11-01 19:30 ` [PATCH 11/14] FRV: Add FDPIC ELF binary format driver dhowells
2004-11-02  8:18   ` Andrew Morton
2004-11-02 11:07   ` Andrew Morton
2004-11-02 16:47   ` David Howells
2004-11-02 17:23     ` Andi Kleen
2004-11-01 19:30 ` [PATCH 10/14] FRV: Make calibrate_delay() optional dhowells
2004-11-02  0:06   ` john stultz
2004-11-02  8:17   ` Andrew Morton
2004-11-02  9:36   ` Christoph Hellwig
2004-11-02 11:01   ` David Howells
2004-11-02 16:29   ` David Howells
2004-11-03 10:40     ` Christoph Hellwig
2004-11-01 19:30 ` [PATCH 9/14] FRV: CONFIG_MMU fixes dhowells
2004-11-02  9:43   ` Christoph Hellwig
2004-11-03 15:06   ` David Howells
2004-11-03 15:13     ` Christoph Hellwig
2004-11-03 15:30     ` David Howells
2004-11-01 19:30 ` [PATCH 7/14] FRV: GDB stub dependent additional BUG()'s dhowells
2004-11-02  9:34   ` Christoph Hellwig
2004-11-02 16:09   ` David Howells
2004-11-03 10:39     ` Christoph Hellwig
2004-11-03 13:41     ` David Howells
2004-11-01 19:30 ` [PATCH 6/14] FRV: IDE fixes dhowells
2004-11-01 22:53   ` Alan Cox
2004-11-02  0:13     ` Bartlomiej Zolnierkiewicz
2004-11-02 10:57     ` David Howells
2004-11-01 19:30 ` [PATCH 13/14] FRV: Convert extern inline -> static inline dhowells
2004-11-01 19:30 ` [PATCH 12/14] FRV: Generate more useful debug info dhowells
2004-11-02  0:29   ` Andrew Morton
2004-11-02 11:21   ` David Howells
2004-11-03  1:48     ` Linus Torvalds
2004-11-03  1:52       ` Linus Torvalds
2004-11-03 20:40         ` Florian Weimer
2004-11-03 20:42           ` Linus Torvalds
2004-11-03 13:38       ` David Howells
2004-11-03 15:32         ` Linus Torvalds
2004-11-12 14:57     ` Daniel Jacobowitz
2004-11-12 15:15     ` David Howells
2004-11-12 15:20       ` Daniel Jacobowitz
     [not found] ` <20040401020550.GG3150@beast>
2004-11-01 19:30   ` [PATCH 14/14] FRV: Better mmap support in uClinux dhowells
2004-11-02  9:54     ` Christoph Hellwig
2004-11-02 16:43     ` David Howells
2004-11-03 10:45       ` Christoph Hellwig
2004-11-08 14:34   ` [PATCH 17/20] " dhowells
2004-11-09 12:57     ` Christoph Hellwig
2004-11-09 13:55     ` David Howells
2004-11-09 14:02       ` Christoph Hellwig
2004-11-19  5:29     ` Matt Mackall
2004-11-19 16:26     ` David Howells
2004-11-19 16:56       ` Matt Mackall
2004-11-19 17:06       ` David Howells
2004-11-19 17:42         ` Linus Torvalds
2004-11-02  0:21 ` [PATCH 1/14] FRV: Fujitsu FR-V CPU arch implementation Andrew Morton
2004-11-02 23:46 ` [uClinux-dev] " Christoph Hellwig
     [not found] ` <200411011930.iA1JUKFH023161@warthog.cambridge.redhat.com>
2004-11-02 23:24   ` [uClinux-dev] [PATCH 2/14] FRV: Fujitsu FR-V arch include files Christoph Hellwig
2004-11-03 17:26   ` David Howells
2004-11-03 19:46 ` [uClinux-dev] [PATCH 1/14] FRV: Fujitsu FR-V CPU arch implementation David Howells
2004-11-03 20:32   ` Christoph Hellwig
2004-11-04 11:54 ` David Howells
2004-11-08 14:34 [PATCH 1/20] FRV: Fujitsu FR-V CPU arch maintainer record dhowells
2004-11-08 14:34 ` [PATCH 2/20] FRV: Fujitsu FR-V arch documentation dhowells
2004-11-08 14:34 ` [PATCH 6/20] FRV: Fujitsu FR-V CPU arch implementation part 4 dhowells
2004-11-08 14:34 ` [PATCH 4/20] FRV: Fujitsu FR-V CPU arch implementation part 2 dhowells
2004-11-08 14:34 ` [PATCH 5/20] FRV: Fujitsu FR-V CPU arch implementation part 3 dhowells
2004-11-08 14:34 ` [PATCH 7/20] FRV: Fujitsu FR-V CPU arch implementation part 5 dhowells
2004-11-09 15:09   ` Geert Uytterhoeven
2004-11-08 14:34 ` [PATCH 3/20] FRV: Fujitsu FR-V CPU arch implementation part 1 dhowells
2004-11-08 14:34 ` [PATCH 8/20] FRV: Fujitsu FR-V CPU arch implementation part 6 dhowells
2004-11-08 14:34 ` [PATCH 9/20] FRV: Fujitsu FR-V CPU arch implementation part 7 dhowells
2004-11-08 14:34 ` [PATCH 11/20] FRV: Fujitsu FR-V CPU arch implementation part 9 dhowells
2004-11-08 14:34 ` [PATCH 10/20] FRV: Fujitsu FR-V CPU arch implementation part 8 dhowells
2004-11-08 14:34 ` [PATCH 15/20] FRV: Fujitsu FR-V arch include files dhowells
2004-11-08 14:34 ` [PATCH 16/20] FRV: Make calibrate_delay() optional dhowells
2004-11-08 14:34 ` [PATCH 14/20] FRV: Fujitsu FR-V arch include files dhowells
2004-11-08 14:34 ` [PATCH 13/20] " dhowells
2004-11-08 14:34 ` [PATCH 18/20] FRV: procfs changes for nommu changes dhowells
2004-11-08 14:34 ` [PATCH 20/20] FRV: Add FDPIC ELF binary format driver dhowells
2004-11-08 14:34 ` [PATCH 19/20] FRV: change setup_arg_pages() to take stack pointer dhowells

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).