aboutsummaryrefslogtreecommitdiff
path: root/arch/m68knommu/kernel
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 15:20:36 -0700
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 15:20:36 -0700
commit1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch)
tree0bba044c4ce775e45a88a51686b5d9f90697ea9d /arch/m68knommu/kernel
downloadlinux-linaro-stable-1da177e4c3f41524e886b7f1b8a0c1fc7321cac2.tar.gz
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history, even though we have it. We can create a separate "historical" git archive of that later if we want to, and in the meantime it's about 3.2GB when imported into git - space that would just make the early git days unnecessarily complicated, when we don't have a lot of good infrastructure for it. Let it rip!
Diffstat (limited to 'arch/m68knommu/kernel')
-rw-r--r--arch/m68knommu/kernel/Makefile11
-rw-r--r--arch/m68knommu/kernel/asm-offsets.c101
-rw-r--r--arch/m68knommu/kernel/comempci.c989
-rw-r--r--arch/m68knommu/kernel/dma.c36
-rw-r--r--arch/m68knommu/kernel/entry.S143
-rw-r--r--arch/m68knommu/kernel/init_task.c43
-rw-r--r--arch/m68knommu/kernel/m68k_ksyms.c104
-rw-r--r--arch/m68knommu/kernel/module.c128
-rw-r--r--arch/m68knommu/kernel/process.c442
-rw-r--r--arch/m68knommu/kernel/ptrace.c383
-rw-r--r--arch/m68knommu/kernel/semaphore.c134
-rw-r--r--arch/m68knommu/kernel/setup.c347
-rw-r--r--arch/m68knommu/kernel/signal.c788
-rw-r--r--arch/m68knommu/kernel/sys_m68k.c208
-rw-r--r--arch/m68knommu/kernel/syscalltable.S308
-rw-r--r--arch/m68knommu/kernel/time.c198
-rw-r--r--arch/m68knommu/kernel/traps.c320
-rw-r--r--arch/m68knommu/kernel/vmlinux.lds.S348
18 files changed, 5031 insertions, 0 deletions
diff --git a/arch/m68knommu/kernel/Makefile b/arch/m68knommu/kernel/Makefile
new file mode 100644
index 000000000000..1c6cd1ab571e
--- /dev/null
+++ b/arch/m68knommu/kernel/Makefile
@@ -0,0 +1,11 @@
+#
+# Makefile for arch/m68knommu/kernel.
+#
+
+extra-y := vmlinux.lds
+
+obj-y += dma.o entry.o init_task.o m68k_ksyms.o process.o ptrace.o semaphore.o \
+ setup.o signal.o syscalltable.o sys_m68k.o time.o traps.o
+
+obj-$(CONFIG_MODULES) += module.o
+obj-$(CONFIG_COMEMPCI) += comempci.o
diff --git a/arch/m68knommu/kernel/asm-offsets.c b/arch/m68knommu/kernel/asm-offsets.c
new file mode 100644
index 000000000000..cd3ffe12653e
--- /dev/null
+++ b/arch/m68knommu/kernel/asm-offsets.c
@@ -0,0 +1,101 @@
+/*
+ * This program is used to generate definitions needed by
+ * assembly language modules.
+ *
+ * We use the technique used in the OSF Mach kernel code:
+ * generate asm statements containing #defines,
+ * compile this file to assembler, and then extract the
+ * #defines from the assembly-language output.
+ */
+
+#include <linux/stddef.h>
+#include <linux/sched.h>
+#include <linux/kernel_stat.h>
+#include <linux/ptrace.h>
+#include <linux/hardirq.h>
+#include <asm/bootinfo.h>
+#include <asm/irq.h>
+#include <asm/thread_info.h>
+
+#define DEFINE(sym, val) \
+ asm volatile("\n->" #sym " %0 " #val : : "i" (val))
+
+#define BLANK() asm volatile("\n->" : : )
+
+int main(void)
+{
+ /* offsets into the task struct */
+ DEFINE(TASK_STATE, offsetof(struct task_struct, state));
+ DEFINE(TASK_FLAGS, offsetof(struct task_struct, flags));
+ DEFINE(TASK_PTRACE, offsetof(struct task_struct, ptrace));
+ DEFINE(TASK_BLOCKED, offsetof(struct task_struct, blocked));
+ DEFINE(TASK_THREAD, offsetof(struct task_struct, thread));
+ DEFINE(TASK_THREAD_INFO, offsetof(struct task_struct, thread_info));
+ DEFINE(TASK_MM, offsetof(struct task_struct, mm));
+ DEFINE(TASK_ACTIVE_MM, offsetof(struct task_struct, active_mm));
+
+ /* offsets into the kernel_stat struct */
+ DEFINE(STAT_IRQ, offsetof(struct kernel_stat, irqs));
+
+ /* offsets into the irq_cpustat_t struct */
+ DEFINE(CPUSTAT_SOFTIRQ_PENDING, offsetof(irq_cpustat_t, __softirq_pending));
+
+ /* offsets into the thread struct */
+ DEFINE(THREAD_KSP, offsetof(struct thread_struct, ksp));
+ DEFINE(THREAD_USP, offsetof(struct thread_struct, usp));
+ DEFINE(THREAD_SR, offsetof(struct thread_struct, sr));
+ DEFINE(THREAD_FS, offsetof(struct thread_struct, fs));
+ DEFINE(THREAD_CRP, offsetof(struct thread_struct, crp));
+ DEFINE(THREAD_ESP0, offsetof(struct thread_struct, esp0));
+ DEFINE(THREAD_FPREG, offsetof(struct thread_struct, fp));
+ DEFINE(THREAD_FPCNTL, offsetof(struct thread_struct, fpcntl));
+ DEFINE(THREAD_FPSTATE, offsetof(struct thread_struct, fpstate));
+
+ /* offsets into the pt_regs */
+ DEFINE(PT_D0, offsetof(struct pt_regs, d0));
+ DEFINE(PT_ORIG_D0, offsetof(struct pt_regs, orig_d0));
+ DEFINE(PT_D1, offsetof(struct pt_regs, d1));
+ DEFINE(PT_D2, offsetof(struct pt_regs, d2));
+ DEFINE(PT_D3, offsetof(struct pt_regs, d3));
+ DEFINE(PT_D4, offsetof(struct pt_regs, d4));
+ DEFINE(PT_D5, offsetof(struct pt_regs, d5));
+ DEFINE(PT_A0, offsetof(struct pt_regs, a0));
+ DEFINE(PT_A1, offsetof(struct pt_regs, a1));
+ DEFINE(PT_A2, offsetof(struct pt_regs, a2));
+ DEFINE(PT_PC, offsetof(struct pt_regs, pc));
+ DEFINE(PT_SR, offsetof(struct pt_regs, sr));
+
+#ifdef CONFIG_COLDFIRE
+ /* bitfields are a bit difficult */
+ DEFINE(PT_FORMATVEC, offsetof(struct pt_regs, sr) - 2);
+#else
+ /* bitfields are a bit difficult */
+ DEFINE(PT_VECTOR, offsetof(struct pt_regs, pc) + 4);
+ /* offsets into the irq_handler struct */
+ DEFINE(IRQ_HANDLER, offsetof(struct irq_node, handler));
+ DEFINE(IRQ_DEVID, offsetof(struct irq_node, dev_id));
+ DEFINE(IRQ_NEXT, offsetof(struct irq_node, next));
+#endif
+
+ /* offsets into the kernel_stat struct */
+ DEFINE(STAT_IRQ, offsetof(struct kernel_stat, irqs));
+
+ /* signal defines */
+ DEFINE(SIGSEGV, SIGSEGV);
+ DEFINE(SEGV_MAPERR, SEGV_MAPERR);
+ DEFINE(SIGTRAP, SIGTRAP);
+ DEFINE(TRAP_TRACE, TRAP_TRACE);
+
+ DEFINE(PT_PTRACED, PT_PTRACED);
+ DEFINE(PT_DTRACE, PT_DTRACE);
+
+ DEFINE(THREAD_SIZE, THREAD_SIZE);
+
+ /* Offsets in thread_info structure */
+ DEFINE(TI_TASK, offsetof(struct thread_info, task));
+ DEFINE(TI_EXECDOMAIN, offsetof(struct thread_info, exec_domain));
+ DEFINE(TI_FLAGS, offsetof(struct thread_info, flags));
+ DEFINE(TI_CPU, offsetof(struct thread_info, cpu));
+
+ return 0;
+}
diff --git a/arch/m68knommu/kernel/comempci.c b/arch/m68knommu/kernel/comempci.c
new file mode 100644
index 000000000000..8670938f1107
--- /dev/null
+++ b/arch/m68knommu/kernel/comempci.c
@@ -0,0 +1,989 @@
+/*****************************************************************************/
+
+/*
+ * comemlite.c -- PCI access code for embedded CO-MEM Lite PCI controller.
+ *
+ * (C) Copyright 1999-2003, Greg Ungerer (gerg@snapgear.com).
+ * (C) Copyright 2000, Lineo (www.lineo.com)
+ */
+
+/*****************************************************************************/
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/ptrace.h>
+#include <linux/spinlock.h>
+#include <linux/interrupt.h>
+#include <linux/sched.h>
+#include <asm/coldfire.h>
+#include <asm/mcfsim.h>
+#include <asm/irq.h>
+#include <asm/anchor.h>
+
+#ifdef CONFIG_eLIA
+#include <asm/elia.h>
+#endif
+
+/*****************************************************************************/
+
+/*
+ * Debug configuration defines. DEBUGRES sets debugging output for
+ * the resource allocation phase. DEBUGPCI traces on pcibios_ function
+ * calls, and DEBUGIO traces all accesses to devices on the PCI bus.
+ */
+/*#define DEBUGRES 1*/
+/*#define DEBUGPCI 1*/
+/*#define DEBUGIO 1*/
+
+/*****************************************************************************/
+
+/*
+ * PCI markers for bus present and active slots.
+ */
+int pci_bus_is_present = 0;
+unsigned long pci_slotmask = 0;
+
+/*
+ * We may or may not need to swap the bytes of PCI bus tranfers.
+ * The endianess is re-roder automatically by the CO-MEM, but it
+ * will get the wrong byte order for a pure data stream.
+ */
+#define pci_byteswap 0
+
+
+/*
+ * Resource tracking. The CO-MEM part creates a virtual address
+ * space that all the PCI devices live in - it is not in any way
+ * directly mapped into the ColdFire address space. So we can
+ * really assign any resources we like to devices, as long as
+ * they do not clash with other PCI devices.
+ */
+unsigned int pci_iobase = PCIBIOS_MIN_IO; /* Arbitrary start address */
+unsigned int pci_membase = PCIBIOS_MIN_MEM; /* Arbitrary start address */
+
+#define PCI_MINIO 0x100 /* 256 byte minimum I/O */
+#define PCI_MINMEM 0x00010000 /* 64k minimum chunk */
+
+/*
+ * The CO-MEM's shared memory segment is visible inside the PCI
+ * memory address space. We need to keep track of the address that
+ * this is mapped at, to setup the bus masters pointers.
+ */
+unsigned int pci_shmemaddr;
+
+/*****************************************************************************/
+
+void pci_interrupt(int irq, void *id, struct pt_regs *fp);
+
+/*****************************************************************************/
+
+/*
+ * Some platforms have custom ways of reseting the PCI bus.
+ */
+
+void pci_resetbus(void)
+{
+#ifdef CONFIG_eLIA
+ int i;
+
+#ifdef DEBUGPCI
+ printk(KERN_DEBUG "pci_resetbus()\n");
+#endif
+
+ *((volatile unsigned short *) (MCF_MBAR+MCFSIM_PADDR)) |= eLIA_PCIRESET;
+ for (i = 0; (i < 1000); i++) {
+ *((volatile unsigned short *) (MCF_MBAR + MCFSIM_PADAT)) =
+ (ppdata | eLIA_PCIRESET);
+ }
+
+
+ *((volatile unsigned short *) (MCF_MBAR + MCFSIM_PADAT)) = ppdata;
+#endif
+}
+
+/*****************************************************************************/
+
+int pcibios_assign_resource_slot(int slot)
+{
+ volatile unsigned long *rp;
+ volatile unsigned char *ip;
+ unsigned int idsel, addr, val, align, i;
+ int bar;
+
+#ifdef DEBUGPCI
+ printk(KERN_INFO "pcibios_assign_resource_slot(slot=%x)\n", slot);
+#endif
+
+ rp = (volatile unsigned long *) COMEM_BASE;
+ idsel = COMEM_DA_ADDR(0x1 << (slot + 16));
+
+ /* Try to assign resource to each BAR */
+ for (bar = 0; (bar < 6); bar++) {
+ addr = COMEM_PCIBUS + PCI_BASE_ADDRESS_0 + (bar * 4);
+ rp[LREG(COMEM_DAHBASE)] = COMEM_DA_CFGRD | idsel;
+ val = rp[LREG(addr)];
+#ifdef DEBUGRES
+ printk(KERN_DEBUG "-----------------------------------"
+ "-------------------------------------\n");
+ printk(KERN_DEBUG "BAR[%d]: read=%08x ", bar, val);
+#endif
+
+ rp[LREG(COMEM_DAHBASE)] = COMEM_DA_CFGWR | idsel;
+ rp[LREG(addr)] = 0xffffffff;
+
+ rp[LREG(COMEM_DAHBASE)] = COMEM_DA_CFGRD | idsel;
+ val = rp[LREG(addr)];
+#ifdef DEBUGRES
+ printk(KERN_DEBUG "write=%08x ", val);
+#endif
+ if (val == 0) {
+#ifdef DEBUGRES
+ printk(KERN_DEBUG "\n");
+#endif
+ continue;
+ }
+
+ /* Determine space required by BAR */
+ /* FIXME: this should go backwords from 0x80000000... */
+ for (i = 0; (i < 32); i++) {
+ if ((0x1 << i) & (val & 0xfffffffc))
+ break;
+ }
+
+#ifdef DEBUGRES
+ printk(KERN_DEBUG "size=%08x(%d)\n", (0x1 << i), i);
+#endif
+ i = 0x1 << i;
+
+ /* Assign a resource */
+ if (val & PCI_BASE_ADDRESS_SPACE_IO) {
+ if (i < PCI_MINIO)
+ i = PCI_MINIO;
+#ifdef DEBUGRES
+ printk(KERN_DEBUG "BAR[%d]: IO size=%08x iobase=%08x\n",
+ bar, i, pci_iobase);
+#endif
+ if (i > 0xffff) {
+ /* Invalid size?? */
+ val = 0 | PCI_BASE_ADDRESS_SPACE_IO;
+#ifdef DEBUGRES
+ printk(KERN_DEBUG "BAR[%d]: too big for IO??\n", bar);
+#endif
+ } else {
+ /* Check for un-alignment */
+ if ((align = pci_iobase % i))
+ pci_iobase += (i - align);
+ val = pci_iobase | PCI_BASE_ADDRESS_SPACE_IO;
+ pci_iobase += i;
+ }
+ } else {
+ if (i < PCI_MINMEM)
+ i = PCI_MINMEM;
+#ifdef DEBUGRES
+ printk(KERN_DEBUG "BAR[%d]: MEMORY size=%08x membase=%08x\n",
+ bar, i, pci_membase);
+#endif
+ /* Check for un-alignment */
+ if ((align = pci_membase % i))
+ pci_membase += (i - align);
+ val = pci_membase | PCI_BASE_ADDRESS_SPACE_MEMORY;
+ pci_membase += i;
+ }
+
+ /* Write resource back into BAR register */
+ rp[LREG(COMEM_DAHBASE)] = COMEM_DA_CFGWR | idsel;
+ rp[LREG(addr)] = val;
+#ifdef DEBUGRES
+ printk(KERN_DEBUG "BAR[%d]: assigned bar=%08x\n", bar, val);
+#endif
+ }
+
+#ifdef DEBUGRES
+ printk(KERN_DEBUG "-----------------------------------"
+ "-------------------------------------\n");
+#endif
+
+ /* Assign IRQ if one is wanted... */
+ ip = (volatile unsigned char *) (COMEM_BASE + COMEM_PCIBUS);
+ rp[LREG(COMEM_DAHBASE)] = COMEM_DA_CFGRD | idsel;
+
+ addr = (PCI_INTERRUPT_PIN & 0xfc) + (~PCI_INTERRUPT_PIN & 0x03);
+ if (ip[addr]) {
+ rp[LREG(COMEM_DAHBASE)] = COMEM_DA_CFGWR | idsel;
+ addr = (PCI_INTERRUPT_LINE & 0xfc)+(~PCI_INTERRUPT_LINE & 0x03);
+ ip[addr] = 25;
+#ifdef DEBUGRES
+ printk(KERN_DEBUG "IRQ LINE=25\n");
+#endif
+ }
+
+ return(0);
+}
+
+/*****************************************************************************/
+
+int pcibios_enable_slot(int slot)
+{
+ volatile unsigned long *rp;
+ volatile unsigned short *wp;
+ unsigned int idsel, addr;
+ unsigned short cmd;
+
+#ifdef DEBUGPCI
+ printk(KERN_DEBUG "pcibios_enbale_slot(slot=%x)\n", slot);
+#endif
+
+ rp = (volatile unsigned long *) COMEM_BASE;
+ wp = (volatile unsigned short *) COMEM_BASE;
+ idsel = COMEM_DA_ADDR(0x1 << (slot + 16));
+
+ /* Get current command settings */
+ addr = COMEM_PCIBUS + PCI_COMMAND;
+ addr = (addr & ~0x3) + (~addr & 0x02);
+ rp[LREG(COMEM_DAHBASE)] = COMEM_DA_CFGRD | idsel;
+ cmd = wp[WREG(addr)];
+ /*val = ((val & 0xff) << 8) | ((val >> 8) & 0xff);*/
+
+ /* Enable I/O and memory accesses to this device */
+ rp[LREG(COMEM_DAHBASE)] = COMEM_DA_CFGWR | idsel;
+ cmd |= PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER;
+ wp[WREG(addr)] = cmd;
+
+ return(0);
+}
+
+/*****************************************************************************/
+
+void pcibios_assign_resources(void)
+{
+ volatile unsigned long *rp;
+ unsigned long sel, id;
+ int slot;
+
+ rp = (volatile unsigned long *) COMEM_BASE;
+
+ /*
+ * Do a quick scan of the PCI bus and see what is here.
+ */
+ for (slot = COMEM_MINDEV; (slot <= COMEM_MAXDEV); slot++) {
+ sel = COMEM_DA_CFGRD | COMEM_DA_ADDR(0x1 << (slot + 16));
+ rp[LREG(COMEM_DAHBASE)] = sel;
+ rp[LREG(COMEM_PCIBUS)] = 0; /* Clear bus */
+ id = rp[LREG(COMEM_PCIBUS)];
+ if ((id != 0) && ((id & 0xffff0000) != (sel & 0xffff0000))) {
+ printk(KERN_INFO "PCI: slot=%d id=%08x\n", slot, (int) id);
+ pci_slotmask |= 0x1 << slot;
+ pcibios_assign_resource_slot(slot);
+ pcibios_enable_slot(slot);
+ }
+ }
+}
+
+/*****************************************************************************/
+
+int pcibios_init(void)
+{
+ volatile unsigned long *rp;
+ unsigned long sel, id;
+ int slot;
+
+#ifdef DEBUGPCI
+ printk(KERN_DEBUG "pcibios_init()\n");
+#endif
+
+ pci_resetbus();
+
+ /*
+ * Do some sort of basic check to see if the CO-MEM part
+ * is present... This works ok, but I think we really need
+ * something better...
+ */
+ rp = (volatile unsigned long *) COMEM_BASE;
+ if ((rp[LREG(COMEM_LBUSCFG)] & 0xff) != 0x50) {
+ printk(KERN_INFO "PCI: no PCI bus present\n");
+ return(0);
+ }
+
+#ifdef COMEM_BRIDGEDEV
+ /*
+ * Setup the PCI bridge device first. It needs resources too,
+ * so that bus masters can get to its shared memory.
+ */
+ slot = COMEM_BRIDGEDEV;
+ sel = COMEM_DA_CFGRD | COMEM_DA_ADDR(0x1 << (slot + 16));
+ rp[LREG(COMEM_DAHBASE)] = sel;
+ rp[LREG(COMEM_PCIBUS)] = 0; /* Clear bus */
+ id = rp[LREG(COMEM_PCIBUS)];
+ if ((id == 0) || ((id & 0xffff0000) == (sel & 0xffff0000))) {
+ printk(KERN_INFO "PCI: no PCI bus bridge present\n");
+ return(0);
+ }
+
+ printk(KERN_INFO "PCI: bridge device at slot=%d id=%08x\n", slot, (int) id);
+ pci_slotmask |= 0x1 << slot;
+ pci_shmemaddr = pci_membase;
+ pcibios_assign_resource_slot(slot);
+ pcibios_enable_slot(slot);
+#endif
+
+ pci_bus_is_present = 1;
+
+ /* Get PCI irq for local vectoring */
+ if (request_irq(COMEM_IRQ, pci_interrupt, 0, "PCI bridge", NULL)) {
+ printk(KERN_WARNING "PCI: failed to acquire interrupt %d\n", COMEM_IRQ);
+ } else {
+ mcf_autovector(COMEM_IRQ);
+ }
+
+ pcibios_assign_resources();
+
+ return(0);
+}
+
+/*****************************************************************************/
+
+char *pcibios_setup(char *option)
+{
+ /* Nothing for us to handle. */
+ return(option);
+}
+/*****************************************************************************/
+
+void pcibios_fixup_bus(struct pci_bus *b)
+{
+}
+
+/*****************************************************************************/
+
+void pcibios_align_resource(void *data, struct resource *res, unsigned long size, unsigned long align)
+{
+}
+
+/*****************************************************************************/
+
+int pcibios_enable_device(struct pci_dev *dev, int mask)
+{
+ int slot;
+
+ slot = PCI_SLOT(dev->devfn);
+ if ((dev->bus == 0) && (pci_slotmask & (1 << slot)))
+ pcibios_enable_slot(slot);
+ return(0);
+}
+
+/*****************************************************************************/
+
+void pcibios_update_resource(struct pci_dev *dev, struct resource *root, struct resource *r, int resource)
+{
+ printk(KERN_WARNING "%s(%d): no support for changing PCI resources...\n",
+ __FILE__, __LINE__);
+}
+
+
+/*****************************************************************************/
+
+/*
+ * Local routines to interrcept the standard I/O and vector handling
+ * code. Don't include this 'till now - initialization code above needs
+ * access to the real code too.
+ */
+#include <asm/mcfpci.h>
+
+/*****************************************************************************/
+
+void pci_outb(unsigned char val, unsigned int addr)
+{
+ volatile unsigned long *rp;
+ volatile unsigned char *bp;
+
+#ifdef DEBUGIO
+ printk(KERN_DEBUG "pci_outb(val=%02x,addr=%x)\n", val, addr);
+#endif
+
+ rp = (volatile unsigned long *) COMEM_BASE;
+ bp = (volatile unsigned char *) COMEM_BASE;
+ rp[LREG(COMEM_DAHBASE)] = COMEM_DA_IOWR | COMEM_DA_ADDR(addr);
+ addr = (addr & ~0x3) + (~addr & 0x03);
+ bp[(COMEM_PCIBUS + COMEM_DA_OFFSET(addr))] = val;
+}
+
+/*****************************************************************************/
+
+void pci_outw(unsigned short val, unsigned int addr)
+{
+ volatile unsigned long *rp;
+ volatile unsigned short *sp;
+
+#ifdef DEBUGIO
+ printk(KERN_DEBUG "pci_outw(val=%04x,addr=%x)\n", val, addr);
+#endif
+
+ rp = (volatile unsigned long *) COMEM_BASE;
+ sp = (volatile unsigned short *) COMEM_BASE;
+ rp[LREG(COMEM_DAHBASE)] = COMEM_DA_IOWR | COMEM_DA_ADDR(addr);
+ addr = (addr & ~0x3) + (~addr & 0x02);
+ if (pci_byteswap)
+ val = ((val & 0xff) << 8) | ((val >> 8) & 0xff);
+ sp[WREG(COMEM_PCIBUS + COMEM_DA_OFFSET(addr))] = val;
+}
+
+/*****************************************************************************/
+
+void pci_outl(unsigned int val, unsigned int addr)
+{
+ volatile unsigned long *rp;
+ volatile unsigned int *lp;
+
+#ifdef DEBUGIO
+ printk(KERN_DEBUG "pci_outl(val=%08x,addr=%x)\n", val, addr);
+#endif
+
+ rp = (volatile unsigned long *) COMEM_BASE;
+ lp = (volatile unsigned int *) COMEM_BASE;
+ rp[LREG(COMEM_DAHBASE)] = COMEM_DA_IOWR | COMEM_DA_ADDR(addr);
+
+ if (pci_byteswap)
+ val = (val << 24) | ((val & 0x0000ff00) << 8) |
+ ((val & 0x00ff0000) >> 8) | (val >> 24);
+
+ lp[LREG(COMEM_PCIBUS + COMEM_DA_OFFSET(addr))] = val;
+}
+
+/*****************************************************************************/
+
+unsigned long pci_blmask[] = {
+ 0x000000e0,
+ 0x000000d0,
+ 0x000000b0,
+ 0x00000070
+};
+
+unsigned char pci_inb(unsigned int addr)
+{
+ volatile unsigned long *rp;
+ volatile unsigned char *bp;
+ unsigned long r;
+ unsigned char val;
+
+#ifdef DEBUGIO
+ printk(KERN_DEBUG "pci_inb(addr=%x)\n", addr);
+#endif
+
+ rp = (volatile unsigned long *) COMEM_BASE;
+ bp = (volatile unsigned char *) COMEM_BASE;
+
+ r = COMEM_DA_IORD | COMEM_DA_ADDR(addr) | pci_blmask[(addr & 0x3)];
+ rp[LREG(COMEM_DAHBASE)] = r;
+
+ addr = (addr & ~0x3) + (~addr & 0x3);
+ val = bp[(COMEM_PCIBUS + COMEM_DA_OFFSET(addr))];
+ return(val);
+}
+
+/*****************************************************************************/
+
+unsigned long pci_bwmask[] = {
+ 0x000000c0,
+ 0x000000c0,
+ 0x00000030,
+ 0x00000030
+};
+
+unsigned short pci_inw(unsigned int addr)
+{
+ volatile unsigned long *rp;
+ volatile unsigned short *sp;
+ unsigned long r;
+ unsigned short val;
+
+#ifdef DEBUGIO
+ printk(KERN_DEBUG "pci_inw(addr=%x)", addr);
+#endif
+
+ rp = (volatile unsigned long *) COMEM_BASE;
+ r = COMEM_DA_IORD | COMEM_DA_ADDR(addr) | pci_bwmask[(addr & 0x3)];
+ rp[LREG(COMEM_DAHBASE)] = r;
+
+ sp = (volatile unsigned short *) COMEM_BASE;
+ addr = (addr & ~0x3) + (~addr & 0x02);
+ val = sp[WREG(COMEM_PCIBUS + COMEM_DA_OFFSET(addr))];
+ if (pci_byteswap)
+ val = ((val & 0xff) << 8) | ((val >> 8) & 0xff);
+#ifdef DEBUGIO
+ printk(KERN_DEBUG "=%04x\n", val);
+#endif
+ return(val);
+}
+
+/*****************************************************************************/
+
+unsigned int pci_inl(unsigned int addr)
+{
+ volatile unsigned long *rp;
+ volatile unsigned int *lp;
+ unsigned int val;
+
+#ifdef DEBUGIO
+ printk(KERN_DEBUG "pci_inl(addr=%x)", addr);
+#endif
+
+ rp = (volatile unsigned long *) COMEM_BASE;
+ lp = (volatile unsigned int *) COMEM_BASE;
+ rp[LREG(COMEM_DAHBASE)] = COMEM_DA_IORD | COMEM_DA_ADDR(addr);
+ val = lp[LREG(COMEM_PCIBUS + COMEM_DA_OFFSET(addr))];
+
+ if (pci_byteswap)
+ val = (val << 24) | ((val & 0x0000ff00) << 8) |
+ ((val & 0x00ff0000) >> 8) | (val >> 24);
+
+#ifdef DEBUGIO
+ printk(KERN_DEBUG "=%08x\n", val);
+#endif
+ return(val);
+}
+
+/*****************************************************************************/
+
+void pci_outsb(void *addr, void *buf, int len)
+{
+ volatile unsigned long *rp;
+ volatile unsigned char *bp;
+ unsigned char *dp = (unsigned char *) buf;
+ unsigned int a = (unsigned int) addr;
+
+#ifdef DEBUGIO
+ printk(KERN_DEBUG "pci_outsb(addr=%x,buf=%x,len=%d)\n", (int)addr, (int)buf, len);
+#endif
+
+ rp = (volatile unsigned long *) COMEM_BASE;
+ rp[LREG(COMEM_DAHBASE)] = COMEM_DA_IOWR | COMEM_DA_ADDR(a);
+
+ a = (a & ~0x3) + (~a & 0x03);
+ bp = (volatile unsigned char *)
+ (COMEM_BASE + COMEM_PCIBUS + COMEM_DA_OFFSET(a));
+
+ while (len--)
+ *bp = *dp++;
+}
+
+/*****************************************************************************/
+
+void pci_outsw(void *addr, void *buf, int len)
+{
+ volatile unsigned long *rp;
+ volatile unsigned short *wp;
+ unsigned short w, *dp = (unsigned short *) buf;
+ unsigned int a = (unsigned int) addr;
+
+#ifdef DEBUGIO
+ printk(KERN_DEBUG "pci_outsw(addr=%x,buf=%x,len=%d)\n", (int)addr, (int)buf, len);
+#endif
+
+ rp = (volatile unsigned long *) COMEM_BASE;
+ rp[LREG(COMEM_DAHBASE)] = COMEM_DA_IOWR | COMEM_DA_ADDR(a);
+
+ a = (a & ~0x3) + (~a & 0x2);
+ wp = (volatile unsigned short *)
+ (COMEM_BASE + COMEM_PCIBUS + COMEM_DA_OFFSET(a));
+
+ while (len--) {
+ w = *dp++;
+ if (pci_byteswap)
+ w = ((w & 0xff) << 8) | ((w >> 8) & 0xff);
+ *wp = w;
+ }
+}
+
+/*****************************************************************************/
+
+void pci_outsl(void *addr, void *buf, int len)
+{
+ volatile unsigned long *rp;
+ volatile unsigned long *lp;
+ unsigned long l, *dp = (unsigned long *) buf;
+ unsigned int a = (unsigned int) addr;
+
+#ifdef DEBUGIO
+ printk(KERN_DEBUG "pci_outsl(addr=%x,buf=%x,len=%d)\n", (int)addr, (int)buf, len);
+#endif
+
+ rp = (volatile unsigned long *) COMEM_BASE;
+ rp[LREG(COMEM_DAHBASE)] = COMEM_DA_IOWR | COMEM_DA_ADDR(a);
+
+ lp = (volatile unsigned long *)
+ (COMEM_BASE + COMEM_PCIBUS + COMEM_DA_OFFSET(a));
+
+ while (len--) {
+ l = *dp++;
+ if (pci_byteswap)
+ l = (l << 24) | ((l & 0x0000ff00) << 8) |
+ ((l & 0x00ff0000) >> 8) | (l >> 24);
+ *lp = l;
+ }
+}
+
+/*****************************************************************************/
+
+void pci_insb(void *addr, void *buf, int len)
+{
+ volatile unsigned long *rp;
+ volatile unsigned char *bp;
+ unsigned char *dp = (unsigned char *) buf;
+ unsigned int a = (unsigned int) addr;
+
+#ifdef DEBUGIO
+ printk(KERN_DEBUG "pci_insb(addr=%x,buf=%x,len=%d)\n", (int)addr, (int)buf, len);
+#endif
+
+ rp = (volatile unsigned long *) COMEM_BASE;
+ rp[LREG(COMEM_DAHBASE)] = COMEM_DA_IORD | COMEM_DA_ADDR(a);
+
+ a = (a & ~0x3) + (~a & 0x03);
+ bp = (volatile unsigned char *)
+ (COMEM_BASE + COMEM_PCIBUS + COMEM_DA_OFFSET(a));
+
+ while (len--)
+ *dp++ = *bp;
+}
+
+/*****************************************************************************/
+
+void pci_insw(void *addr, void *buf, int len)
+{
+ volatile unsigned long *rp;
+ volatile unsigned short *wp;
+ unsigned short w, *dp = (unsigned short *) buf;
+ unsigned int a = (unsigned int) addr;
+
+#ifdef DEBUGIO
+ printk(KERN_DEBUG "pci_insw(addr=%x,buf=%x,len=%d)\n", (int)addr, (int)buf, len);
+#endif
+
+ rp = (volatile unsigned long *) COMEM_BASE;
+ rp[LREG(COMEM_DAHBASE)] = COMEM_DA_IORD | COMEM_DA_ADDR(a);
+
+ a = (a & ~0x3) + (~a & 0x2);
+ wp = (volatile unsigned short *)
+ (COMEM_BASE + COMEM_PCIBUS + COMEM_DA_OFFSET(a));
+
+ while (len--) {
+ w = *wp;
+ if (pci_byteswap)
+ w = ((w & 0xff) << 8) | ((w >> 8) & 0xff);
+ *dp++ = w;
+ }
+}
+
+/*****************************************************************************/
+
+void pci_insl(void *addr, void *buf, int len)
+{
+ volatile unsigned long *rp;
+ volatile unsigned long *lp;
+ unsigned long l, *dp = (unsigned long *) buf;
+ unsigned int a = (unsigned int) addr;
+
+#ifdef DEBUGIO
+ printk(KERN_DEBUG "pci_insl(addr=%x,buf=%x,len=%d)\n", (int)addr, (int)buf, len);
+#endif
+
+ rp = (volatile unsigned long *) COMEM_BASE;
+ rp[LREG(COMEM_DAHBASE)] = COMEM_DA_IORD | COMEM_DA_ADDR(a);
+
+ lp = (volatile unsigned long *)
+ (COMEM_BASE + COMEM_PCIBUS + COMEM_DA_OFFSET(a));
+
+ while (len--) {
+ l = *lp;
+ if (pci_byteswap)
+ l = (l << 24) | ((l & 0x0000ff00) << 8) |
+ ((l & 0x00ff0000) >> 8) | (l >> 24);
+ *dp++ = l;
+ }
+}
+
+/*****************************************************************************/
+
+struct pci_localirqlist {
+ void (*handler)(int, void *, struct pt_regs *);
+ const char *device;
+ void *dev_id;
+};
+
+struct pci_localirqlist pci_irqlist[COMEM_MAXPCI];
+
+/*****************************************************************************/
+
+int pci_request_irq(unsigned int irq,
+ void (*handler)(int, void *, struct pt_regs *),
+ unsigned long flags, const char *device, void *dev_id)
+{
+ int i;
+
+#ifdef DEBUGIO
+ printk(KERN_DEBUG "pci_request_irq(irq=%d,handler=%x,flags=%x,device=%s,"
+ "dev_id=%x)\n", irq, (int) handler, (int) flags, device,
+ (int) dev_id);
+#endif
+
+ /* Check if this interrupt handler is already lodged */
+ for (i = 0; (i < COMEM_MAXPCI); i++) {
+ if (pci_irqlist[i].handler == handler)
+ return(0);
+ }
+
+ /* Find a free spot to put this handler */
+ for (i = 0; (i < COMEM_MAXPCI); i++) {
+ if (pci_irqlist[i].handler == 0) {
+ pci_irqlist[i].handler = handler;
+ pci_irqlist[i].device = device;
+ pci_irqlist[i].dev_id = dev_id;
+ return(0);
+ }
+ }
+
+ /* Couldn't fit?? */
+ return(1);
+}
+
+/*****************************************************************************/
+
+void pci_free_irq(unsigned int irq, void *dev_id)
+{
+ int i;
+
+#ifdef DEBUGIO
+ printk(KERN_DEBUG "pci_free_irq(irq=%d,dev_id=%x)\n", irq, (int) dev_id);
+#endif
+
+ if (dev_id == (void *) NULL)
+ return;
+
+ /* Check if this interrupt handler is lodged */
+ for (i = 0; (i < COMEM_MAXPCI); i++) {
+ if (pci_irqlist[i].dev_id == dev_id) {
+ pci_irqlist[i].handler = NULL;
+ pci_irqlist[i].device = NULL;
+ pci_irqlist[i].dev_id = NULL;
+ break;
+ }
+ }
+}
+
+/*****************************************************************************/
+
+void pci_interrupt(int irq, void *id, struct pt_regs *fp)
+{
+ int i;
+
+#ifdef DEBUGIO
+ printk(KERN_DEBUG "pci_interrupt(irq=%d,id=%x,fp=%x)\n", irq, (int) id, (int) fp);
+#endif
+
+ for (i = 0; (i < COMEM_MAXPCI); i++) {
+ if (pci_irqlist[i].handler)
+ (*pci_irqlist[i].handler)(irq,pci_irqlist[i].dev_id,fp);
+ }
+}
+
+/*****************************************************************************/
+
+/*
+ * The shared memory region is broken up into contiguous 512 byte
+ * regions for easy allocation... This is not an optimal solution
+ * but it makes allocation and freeing regions really easy.
+ */
+
+#define PCI_MEMSLOTSIZE 512
+#define PCI_MEMSLOTS (COMEM_SHMEMSIZE / PCI_MEMSLOTSIZE)
+
+char pci_shmemmap[PCI_MEMSLOTS];
+
+
+void *pci_bmalloc(int size)
+{
+ int i, j, nrslots;
+
+#ifdef DEBUGIO
+ printk(KERN_DEBUG "pci_bmalloc(size=%d)\n", size);
+#endif
+
+ if (size <= 0)
+ return((void *) NULL);
+
+ nrslots = (size - 1) / PCI_MEMSLOTSIZE;
+
+ for (i = 0; (i < (PCI_MEMSLOTS-nrslots)); i++) {
+ if (pci_shmemmap[i] == 0) {
+ for (j = i+1; (j < (i+nrslots)); j++) {
+ if (pci_shmemmap[j])
+ goto restart;
+ }
+
+ for (j = i; (j <= i+nrslots); j++)
+ pci_shmemmap[j] = 1;
+ break;
+ }
+restart:
+ }
+
+ return((void *) (COMEM_BASE + COMEM_SHMEM + (i * PCI_MEMSLOTSIZE)));
+}
+
+/*****************************************************************************/
+
+void pci_bmfree(void *mp, int size)
+{
+ int i, j, nrslots;
+
+#ifdef DEBUGIO
+ printk(KERN_DEBUG "pci_bmfree(mp=%x,size=%d)\n", (int) mp, size);
+#endif
+
+ nrslots = size / PCI_MEMSLOTSIZE;
+ i = (((unsigned long) mp) - (COMEM_BASE + COMEM_SHMEM)) /
+ PCI_MEMSLOTSIZE;
+
+ for (j = i; (j < (i+nrslots)); j++)
+ pci_shmemmap[j] = 0;
+}
+
+/*****************************************************************************/
+
+unsigned long pci_virt_to_bus(volatile void *address)
+{
+ unsigned long l;
+
+#ifdef DEBUGIO
+ printk(KERN_DEBUG "pci_virt_to_bus(address=%x)", (int) address);
+#endif
+
+ l = ((unsigned long) address) - COMEM_BASE;
+#ifdef DEBUGIO
+ printk(KERN_DEBUG "=%x\n", (int) (l+pci_shmemaddr));
+#endif
+ return(l + pci_shmemaddr);
+}
+
+/*****************************************************************************/
+
+void *pci_bus_to_virt(unsigned long address)
+{
+ unsigned long l;
+
+#ifdef DEBUGIO
+ printk(KERN_DEBUG "pci_bus_to_virt(address=%x)", (int) address);
+#endif
+
+ l = address - pci_shmemaddr;
+#ifdef DEBUGIO
+ printk(KERN_DEBUG "=%x\n", (int) (address + COMEM_BASE));
+#endif
+ return((void *) (address + COMEM_BASE));
+}
+
+/*****************************************************************************/
+
+void pci_bmcpyto(void *dst, void *src, int len)
+{
+ unsigned long *dp, *sp, val;
+ unsigned char *dcp, *scp;
+ int i, j;
+
+#ifdef DEBUGIO
+ printk(KERN_DEBUG "pci_bmcpyto(dst=%x,src=%x,len=%d)\n", (int)dst, (int)src, len);
+#endif
+
+ dp = (unsigned long *) dst;
+ sp = (unsigned long *) src;
+ i = len >> 2;
+
+#if 0
+ printk(KERN_INFO "DATA:");
+ scp = (unsigned char *) sp;
+ for (i = 0; (i < len); i++) {
+ if ((i % 16) == 0) printk(KERN_INFO "\n%04x: ", i);
+ printk(KERN_INFO "%02x ", *scp++);
+ }
+ printk(KERN_INFO "\n");
+#endif
+
+ for (j = 0; (i >= 0); i--, j++) {
+ val = *sp++;
+ val = (val << 24) | ((val & 0x0000ff00) << 8) |
+ ((val & 0x00ff0000) >> 8) | (val >> 24);
+ *dp++ = val;
+ }
+
+ if (len & 0x3) {
+ dcp = (unsigned char *) dp;
+ scp = ((unsigned char *) sp) + 3;
+ for (i = 0; (i < (len & 0x3)); i++)
+ *dcp++ = *scp--;
+ }
+}
+
+/*****************************************************************************/
+
+void pci_bmcpyfrom(void *dst, void *src, int len)
+{
+ unsigned long *dp, *sp, val;
+ unsigned char *dcp, *scp;
+ int i;
+
+#ifdef DEBUGIO
+ printk(KERN_DEBUG "pci_bmcpyfrom(dst=%x,src=%x,len=%d)\n",(int)dst,(int)src,len);
+#endif
+
+ dp = (unsigned long *) dst;
+ sp = (unsigned long *) src;
+ i = len >> 2;
+
+ for (; (i >= 0); i--) {
+ val = *sp++;
+ val = (val << 24) | ((val & 0x0000ff00) << 8) |
+ ((val & 0x00ff0000) >> 8) | (val >> 24);
+ *dp++ = val;
+ }
+
+ if (len & 0x3) {
+ dcp = ((unsigned char *) dp) + 3;
+ scp = (unsigned char *) sp;
+ for (i = 0; (i < (len & 0x3)); i++)
+ *dcp++ = *scp--;
+ }
+
+#if 0
+ printk(KERN_INFO "DATA:");
+ dcp = (unsigned char *) dst;
+ for (i = 0; (i < len); i++) {
+ if ((i % 16) == 0) printk(KERN_INFO "\n%04x: ", i);
+ printk(KERN_INFO "%02x ", *dcp++);
+ }
+ printk(KERN_INFO "\n");
+#endif
+}
+
+/*****************************************************************************/
+
+void *pci_alloc_consistent(struct pci_dev *dev, size_t size, dma_addr_t *dma_addr)
+{
+ void *mp;
+ if ((mp = pci_bmalloc(size)) != NULL) {
+ dma_addr = mp - (COMEM_BASE + COMEM_SHMEM);
+ return(mp);
+ }
+ *dma_addr = (dma_addr_t) NULL;
+ return(NULL);
+}
+
+/*****************************************************************************/
+
+void pci_free_consistent(struct pci_dev *dev, size_t size, void *cpu_addr, dma_addr_t dma_addr)
+{
+ pci_bmfree(cpu_addr, size);
+}
+
+/*****************************************************************************/
diff --git a/arch/m68knommu/kernel/dma.c b/arch/m68knommu/kernel/dma.c
new file mode 100644
index 000000000000..14b19c4161f4
--- /dev/null
+++ b/arch/m68knommu/kernel/dma.c
@@ -0,0 +1,36 @@
+/*
+ * Dynamic DMA mapping support.
+ *
+ * We never have any address translations to worry about, so this
+ * is just alloc/free.
+ */
+
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/string.h>
+#include <linux/pci.h>
+#include <asm/io.h>
+
+void *dma_alloc_coherent(struct device *dev, size_t size,
+ dma_addr_t *dma_handle, int gfp)
+{
+ void *ret;
+ /* ignore region specifiers */
+ gfp &= ~(__GFP_DMA | __GFP_HIGHMEM);
+
+ if (dev == NULL || (*dev->dma_mask < 0xffffffff))
+ gfp |= GFP_DMA;
+ ret = (void *)__get_free_pages(gfp, get_order(size));
+
+ if (ret != NULL) {
+ memset(ret, 0, size);
+ *dma_handle = virt_to_phys(ret);
+ }
+ return ret;
+}
+
+void dma_free_coherent(struct device *dev, size_t size,
+ void *vaddr, dma_addr_t dma_handle)
+{
+ free_pages((unsigned long)vaddr, get_order(size));
+}
diff --git a/arch/m68knommu/kernel/entry.S b/arch/m68knommu/kernel/entry.S
new file mode 100644
index 000000000000..8b1f47239b9a
--- /dev/null
+++ b/arch/m68knommu/kernel/entry.S
@@ -0,0 +1,143 @@
+/*
+ * linux/arch/m68knommu/kernel/entry.S
+ *
+ * Copyright (C) 1999-2002, Greg Ungerer (gerg@snapgear.com)
+ * Copyright (C) 1998 D. Jeff Dionne <jeff@lineo.ca>,
+ * Kenneth Albanowski <kjahds@kjahds.com>,
+ * Copyright (C) 2000 Lineo Inc. (www.lineo.com)
+ *
+ * Based on:
+ *
+ * linux/arch/m68k/kernel/entry.S
+ *
+ * Copyright (C) 1991, 1992 Linus Torvalds
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file README.legal in the main directory of this archive
+ * for more details.
+ *
+ * Linux/m68k support by Hamish Macdonald
+ *
+ * 68060 fixes by Jesper Skov
+ * ColdFire support by Greg Ungerer (gerg@snapgear.com)
+ * 5307 fixes by David W. Miller
+ * linux 2.4 support David McCullough <davidm@snapgear.com>
+ */
+
+#include <linux/config.h>
+#include <linux/sys.h>
+#include <linux/linkage.h>
+#include <asm/thread_info.h>
+#include <asm/errno.h>
+#include <asm/setup.h>
+#include <asm/segment.h>
+#include <asm/asm-offsets.h>
+#include <asm/entry.h>
+
+.text
+
+.globl buserr
+.globl trap
+.globl ret_from_exception
+.globl ret_from_signal
+.globl sys_fork
+.globl sys_clone
+.globl sys_vfork
+
+ENTRY(buserr)
+ SAVE_ALL
+ moveq #-1,%d0
+ movel %d0,%sp@(PT_ORIG_D0)
+ movel %sp,%sp@- /* stack frame pointer argument */
+ jsr buserr_c
+ addql #4,%sp
+ jra ret_from_exception
+
+ENTRY(trap)
+ SAVE_ALL
+ moveq #-1,%d0
+ movel %d0,%sp@(PT_ORIG_D0)
+ movel %sp,%sp@- /* stack frame pointer argument */
+ jsr trap_c
+ addql #4,%sp
+ jra ret_from_exception
+
+#ifdef TRAP_DBG_INTERRUPT
+
+.globl dbginterrupt
+ENTRY(dbginterrupt)
+ SAVE_ALL
+ moveq #-1,%d0
+ movel %d0,%sp@(PT_ORIG_D0)
+ movel %sp,%sp@- /* stack frame pointer argument */
+ jsr dbginterrupt_c
+ addql #4,%sp
+ jra ret_from_exception
+#endif
+
+ENTRY(reschedule)
+ /* save top of frame */
+ pea %sp@
+ jbsr set_esp0
+ addql #4,%sp
+ pea ret_from_exception
+ jmp schedule
+
+ENTRY(ret_from_fork)
+ movel %d1,%sp@-
+ jsr schedule_tail
+ addql #4,%sp
+ jra ret_from_exception
+
+ENTRY(sys_fork)
+ SAVE_SWITCH_STACK
+ pea %sp@(SWITCH_STACK_SIZE)
+ jbsr m68k_fork
+ addql #4,%sp
+ RESTORE_SWITCH_STACK
+ rts
+
+ENTRY(sys_vfork)
+ SAVE_SWITCH_STACK
+ pea %sp@(SWITCH_STACK_SIZE)
+ jbsr m68k_vfork
+ addql #4,%sp
+ RESTORE_SWITCH_STACK
+ rts
+
+ENTRY(sys_clone)
+ SAVE_SWITCH_STACK
+ pea %sp@(SWITCH_STACK_SIZE)
+ jbsr m68k_clone
+ addql #4,%sp
+ RESTORE_SWITCH_STACK
+ rts
+
+ENTRY(sys_sigsuspend)
+ SAVE_SWITCH_STACK
+ pea %sp@(SWITCH_STACK_SIZE)
+ jbsr do_sigsuspend
+ addql #4,%sp
+ RESTORE_SWITCH_STACK
+ rts
+
+ENTRY(sys_rt_sigsuspend)
+ SAVE_SWITCH_STACK
+ pea %sp@(SWITCH_STACK_SIZE)
+ jbsr do_rt_sigsuspend
+ addql #4,%sp
+ RESTORE_SWITCH_STACK
+ rts
+
+ENTRY(sys_sigreturn)
+ SAVE_SWITCH_STACK
+ jbsr do_sigreturn
+ RESTORE_SWITCH_STACK
+ rts
+
+ENTRY(sys_rt_sigreturn)
+ SAVE_SWITCH_STACK
+ jbsr do_rt_sigreturn
+ RESTORE_SWITCH_STACK
+ rts
+
diff --git a/arch/m68knommu/kernel/init_task.c b/arch/m68knommu/kernel/init_task.c
new file mode 100644
index 000000000000..3897043a126a
--- /dev/null
+++ b/arch/m68knommu/kernel/init_task.c
@@ -0,0 +1,43 @@
+/*
+ * linux/arch/m68knommu/kernel/init_task.c
+ */
+#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 task structure.
+ *
+ * All other task structs will be allocated on slabs in fork.c
+ */
+__asm__(".align 4");
+struct task_struct init_task = INIT_TASK(init_task);
+
+EXPORT_SYMBOL(init_task);
+
+/*
+ * Initial thread structure.
+ *
+ * We need to make sure that this is 8192-byte 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) };
+
diff --git a/arch/m68knommu/kernel/m68k_ksyms.c b/arch/m68knommu/kernel/m68k_ksyms.c
new file mode 100644
index 000000000000..e93a5ad56496
--- /dev/null
+++ b/arch/m68knommu/kernel/m68k_ksyms.c
@@ -0,0 +1,104 @@
+#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/machdep.h>
+#include <asm/pgalloc.h>
+#include <asm/irq.h>
+#include <asm/io.h>
+#include <asm/semaphore.h>
+#include <asm/checksum.h>
+#include <asm/current.h>
+
+extern void dump_thread(struct pt_regs *, struct user *);
+extern int dump_fpu(struct pt_regs *, elf_fpregset_t *);
+
+/* platform dependent support */
+
+EXPORT_SYMBOL(__ioremap);
+EXPORT_SYMBOL(iounmap);
+EXPORT_SYMBOL(dump_fpu);
+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(ip_fast_csum);
+
+EXPORT_SYMBOL(mach_enable_irq);
+EXPORT_SYMBOL(mach_disable_irq);
+EXPORT_SYMBOL(kernel_thread);
+
+/* 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(memcpy);
+EXPORT_SYMBOL(memset);
+EXPORT_SYMBOL(memcmp);
+EXPORT_SYMBOL(memscan);
+EXPORT_SYMBOL(memmove);
+
+EXPORT_SYMBOL(__down_failed);
+EXPORT_SYMBOL(__down_failed_interruptible);
+EXPORT_SYMBOL(__down_failed_trylock);
+EXPORT_SYMBOL(__up_wakeup);
+
+EXPORT_SYMBOL(get_wchan);
+
+/*
+ * 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 __ashldi3(void);
+extern void __ashrdi3(void);
+extern void __divsi3(void);
+extern void __lshrdi3(void);
+extern void __modsi3(void);
+extern void __muldi3(void);
+extern void __mulsi3(void);
+extern void __udivsi3(void);
+extern void __umodsi3(void);
+
+ /* gcc lib functions */
+EXPORT_SYMBOL(__ashldi3);
+EXPORT_SYMBOL(__ashrdi3);
+EXPORT_SYMBOL(__divsi3);
+EXPORT_SYMBOL(__lshrdi3);
+EXPORT_SYMBOL(__modsi3);
+EXPORT_SYMBOL(__muldi3);
+EXPORT_SYMBOL(__mulsi3);
+EXPORT_SYMBOL(__udivsi3);
+EXPORT_SYMBOL(__umodsi3);
+
+EXPORT_SYMBOL(is_in_rom);
+
+#ifdef CONFIG_COLDFIRE
+extern unsigned int *dma_device_address;
+extern unsigned long dma_base_addr, _ramend;
+EXPORT_SYMBOL(dma_base_addr);
+EXPORT_SYMBOL(dma_device_address);
+EXPORT_SYMBOL(_ramend);
+
+extern asmlinkage void trap(void);
+extern void *_ramvec;
+EXPORT_SYMBOL(trap);
+EXPORT_SYMBOL(_ramvec);
+#endif /* CONFIG_COLDFIRE */
diff --git a/arch/m68knommu/kernel/module.c b/arch/m68knommu/kernel/module.c
new file mode 100644
index 000000000000..3b1a2ff61ddc
--- /dev/null
+++ b/arch/m68knommu/kernel/module.c
@@ -0,0 +1,128 @@
+#include <linux/moduleloader.h>
+#include <linux/elf.h>
+#include <linux/vmalloc.h>
+#include <linux/fs.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
+
+#if 0
+#define DEBUGP printk
+#else
+#define DEBUGP(fmt...)
+#endif
+
+void *module_alloc(unsigned long size)
+{
+ if (size == 0)
+ return NULL;
+ return vmalloc(size);
+}
+
+
+/* Free memory returned from module_alloc */
+void module_free(struct module *mod, void *module_region)
+{
+ vfree(module_region);
+ /* FIXME: If module_region == mod->init_region, trim exception
+ table entries. */
+}
+
+/* We don't need anything special. */
+int module_frob_arch_sections(Elf_Ehdr *hdr,
+ Elf_Shdr *sechdrs,
+ char *secstrings,
+ struct module *mod)
+{
+ return 0;
+}
+
+int apply_relocate(Elf32_Shdr *sechdrs,
+ const char *strtab,
+ unsigned int symindex,
+ unsigned int relsec,
+ struct module *me)
+{
+ unsigned int i;
+ Elf32_Rel *rel = (void *)sechdrs[relsec].sh_addr;
+ Elf32_Sym *sym;
+ uint32_t *location;
+
+ DEBUGP("Applying relocate section %u to %u\n", relsec,
+ sechdrs[relsec].sh_info);
+ for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) {
+ /* This is where to make the change */
+ location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr
+ + rel[i].r_offset;
+ /* This is the symbol it is referring to. Note that all
+ undefined symbols have been resolved. */
+ sym = (Elf32_Sym *)sechdrs[symindex].sh_addr
+ + ELF32_R_SYM(rel[i].r_info);
+
+ switch (ELF32_R_TYPE(rel[i].r_info)) {
+ case R_68K_32:
+ /* We add the value into the location given */
+ *location += sym->st_value;
+ break;
+ case R_68K_PC32:
+ /* Add the value, subtract its postition */
+ *location += sym->st_value - (uint32_t)location;
+ break;
+ default:
+ printk(KERN_ERR "module %s: Unknown relocation: %u\n",
+ me->name, ELF32_R_TYPE(rel[i].r_info));
+ return -ENOEXEC;
+ }
+ }
+ return 0;
+}
+
+int apply_relocate_add(Elf32_Shdr *sechdrs,
+ const char *strtab,
+ unsigned int symindex,
+ unsigned int relsec,
+ struct module *me)
+{
+ unsigned int i;
+ Elf32_Rela *rel = (void *)sechdrs[relsec].sh_addr;
+ Elf32_Sym *sym;
+ uint32_t *location;
+
+ DEBUGP("Applying relocate_add section %u to %u\n", relsec,
+ sechdrs[relsec].sh_info);
+ for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) {
+ /* This is where to make the change */
+ location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr
+ + rel[i].r_offset;
+ /* This is the symbol it is referring to. Note that all
+ undefined symbols have been resolved. */
+ sym = (Elf32_Sym *)sechdrs[symindex].sh_addr
+ + ELF32_R_SYM(rel[i].r_info);
+
+ switch (ELF32_R_TYPE(rel[i].r_info)) {
+ case R_68K_32:
+ /* We add the value into the location given */
+ *location = rel[i].r_addend + sym->st_value;
+ break;
+ case R_68K_PC32:
+ /* Add the value, subtract its postition */
+ *location = rel[i].r_addend + sym->st_value - (uint32_t)location;
+ break;
+ default:
+ printk(KERN_ERR "module %s: Unknown relocation: %u\n",
+ me->name, ELF32_R_TYPE(rel[i].r_info));
+ return -ENOEXEC;
+ }
+ }
+ return 0;
+}
+
+int module_finalize(const Elf_Ehdr *hdr,
+ const Elf_Shdr *sechdrs,
+ struct module *me)
+{
+ return 0;
+}
+
+void module_arch_cleanup(struct module *mod)
+{
+}
diff --git a/arch/m68knommu/kernel/process.c b/arch/m68knommu/kernel/process.c
new file mode 100644
index 000000000000..2b6c9d32b7a6
--- /dev/null
+++ b/arch/m68knommu/kernel/process.c
@@ -0,0 +1,442 @@
+/*
+ * linux/arch/m68knommu/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/module.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/a.out.h>
+#include <linux/interrupt.h>
+#include <linux/reboot.h>
+
+#include <asm/uaccess.h>
+#include <asm/system.h>
+#include <asm/traps.h>
+#include <asm/machdep.h>
+#include <asm/setup.h>
+#include <asm/pgtable.h>
+
+asmlinkage void ret_from_fork(void);
+
+
+/*
+ * The idle loop on an m68knommu..
+ */
+void default_idle(void)
+{
+ while(1) {
+ if (need_resched())
+ __asm__("stop #0x2000" : : : "cc");
+ schedule();
+ }
+}
+
+void (*idle)(void) = default_idle;
+
+/*
+ * The idle thread. There's no useful work to be
+ * done, so just try to conserve power and have a
+ * low exit latency (ie sit in a loop waiting for
+ * somebody to say that they'd like to reschedule)
+ */
+void cpu_idle(void)
+{
+ /* endless idle loop with no priority at all */
+ idle();
+}
+
+void machine_restart(char * __unused)
+{
+ if (mach_reset)
+ mach_reset();
+ for (;;);
+}
+
+EXPORT_SYMBOL(machine_restart);
+
+void machine_halt(void)
+{
+ if (mach_halt)
+ mach_halt();
+ for (;;);
+}
+
+EXPORT_SYMBOL(machine_halt);
+
+void machine_power_off(void)
+{
+ if (mach_power_off)
+ mach_power_off();
+ for (;;);
+}
+
+EXPORT_SYMBOL(machine_power_off);
+
+void show_regs(struct pt_regs * regs)
+{
+ printk(KERN_NOTICE "\n");
+ printk(KERN_NOTICE "Format %02x Vector: %04x PC: %08lx Status: %04x %s\n",
+ regs->format, regs->vector, regs->pc, regs->sr, print_tainted());
+ printk(KERN_NOTICE "ORIG_D0: %08lx D0: %08lx A2: %08lx A1: %08lx\n",
+ regs->orig_d0, regs->d0, regs->a2, regs->a1);
+ printk(KERN_NOTICE "A0: %08lx D5: %08lx D4: %08lx\n",
+ regs->a0, regs->d5, regs->d4);
+ printk(KERN_NOTICE "D3: %08lx D2: %08lx D1: %08lx\n",
+ regs->d3, regs->d2, regs->d1);
+ if (!(regs->sr & PS_S))
+ printk(KERN_NOTICE "USP: %08lx\n", rdusp());
+}
+
+/*
+ * Create a kernel thread
+ */
+int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
+{
+ int retval;
+ long clone_arg = flags | CLONE_VM;
+ mm_segment_t fs;
+
+ fs = get_fs();
+ set_fs(KERNEL_DS);
+
+ __asm__ __volatile__ (
+ "movel %%sp, %%d2\n\t"
+ "movel %5, %%d1\n\t"
+ "movel %1, %%d0\n\t"
+ "trap #0\n\t"
+ "cmpl %%sp, %%d2\n\t"
+ "jeq 1f\n\t"
+ "movel %3, %%sp@-\n\t"
+ "jsr %4@\n\t"
+ "movel %2, %%d0\n\t"
+ "trap #0\n"
+ "1:\n\t"
+ "movel %%d0, %0\n"
+ : "=d" (retval)
+ : "i" (__NR_clone),
+ "i" (__NR_exit),
+ "a" (arg),
+ "a" (fn),
+ "a" (clone_arg)
+ : "cc", "%d0", "%d1", "%d2");
+
+ set_fs(fs);
+ return retval;
+}
+
+void flush_thread(void)
+{
+#ifdef CONFIG_FPU
+ unsigned long zero = 0;
+#endif
+ set_fs(USER_DS);
+ current->thread.fs = __USER_DS;
+#ifdef CONFIG_FPU
+ if (!FPU_IS_EMU)
+ asm volatile (".chip 68k/68881\n\t"
+ "frestore %0@\n\t"
+ ".chip 68k" : : "a" (&zero));
+#endif
+}
+
+/*
+ * "m68k_fork()".. By the time we get here, the
+ * non-volatile registers have also been saved on the
+ * stack. We do some ugly pointer stuff here.. (see
+ * also copy_thread)
+ */
+
+asmlinkage int m68k_fork(struct pt_regs *regs)
+{
+ /* fork almost works, enough to trick you into looking elsewhere :-( */
+ return(-EINVAL);
+}
+
+asmlinkage int m68k_vfork(struct pt_regs *regs)
+{
+ return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, rdusp(), regs, 0, NULL, NULL);
+}
+
+asmlinkage int m68k_clone(struct pt_regs *regs)
+{
+ unsigned long clone_flags;
+ unsigned long newsp;
+
+ /* syscall2 puts clone_flags in d1 and usp in d2 */
+ clone_flags = regs->d1;
+ newsp = regs->d2;
+ if (!newsp)
+ newsp = rdusp();
+ return do_fork(clone_flags, newsp, regs, 0, NULL, NULL);
+}
+
+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 * childregs;
+ struct switch_stack * childstack, *stack;
+ unsigned long stack_offset, *retp;
+
+ stack_offset = THREAD_SIZE - sizeof(struct pt_regs);
+ childregs = (struct pt_regs *) ((unsigned long) p->thread_info + stack_offset);
+
+ *childregs = *regs;
+ childregs->d0 = 0;
+
+ retp = ((unsigned long *) regs);
+ stack = ((struct switch_stack *) retp) - 1;
+
+ childstack = ((struct switch_stack *) childregs) - 1;
+ *childstack = *stack;
+ childstack->retpc = (unsigned long)ret_from_fork;
+
+ p->thread.usp = usp;
+ p->thread.ksp = (unsigned long)childstack;
+ /*
+ * Must save the current SFC/DFC value, NOT the value when
+ * the parent was last descheduled - RGH 10-08-96
+ */
+ p->thread.fs = get_fs().seg;
+
+#ifdef CONFIG_FPU
+ if (!FPU_IS_EMU) {
+ /* Copy the current fpu state */
+ asm volatile ("fsave %0" : : "m" (p->thread.fpstate[0]) : "memory");
+
+ if (p->thread.fpstate[0])
+ asm volatile ("fmovemx %/fp0-%/fp7,%0\n\t"
+ "fmoveml %/fpiar/%/fpcr/%/fpsr,%1"
+ : : "m" (p->thread.fp[0]), "m" (p->thread.fpcntl[0])
+ : "memory");
+ /* Restore the state in case the fpu was busy */
+ asm volatile ("frestore %0" : : "m" (p->thread.fpstate[0]));
+ }
+#endif
+
+ return 0;
+}
+
+/* Fill in the fpu structure for a core dump. */
+
+int dump_fpu(struct pt_regs *regs, struct user_m68kfp_struct *fpu)
+{
+#ifdef CONFIG_FPU
+ char fpustate[216];
+
+ if (FPU_IS_EMU) {
+ int i;
+
+ memcpy(fpu->fpcntl, current->thread.fpcntl, 12);
+ memcpy(fpu->fpregs, current->thread.fp, 96);
+ /* Convert internal fpu reg representation
+ * into long double format
+ */
+ for (i = 0; i < 24; i += 3)
+ fpu->fpregs[i] = ((fpu->fpregs[i] & 0xffff0000) << 15) |
+ ((fpu->fpregs[i] & 0x0000ffff) << 16);
+ return 1;
+ }
+
+ /* First dump the fpu context to avoid protocol violation. */
+ asm volatile ("fsave %0" :: "m" (fpustate[0]) : "memory");
+ if (!fpustate[0])
+ return 0;
+
+ asm volatile ("fmovem %/fpiar/%/fpcr/%/fpsr,%0"
+ :: "m" (fpu->fpcntl[0])
+ : "memory");
+ asm volatile ("fmovemx %/fp0-%/fp7,%0"
+ :: "m" (fpu->fpregs[0])
+ : "memory");
+#endif
+ return 1;
+}
+
+/*
+ * fill in the user structure for a core dump..
+ */
+void dump_thread(struct pt_regs * regs, struct user * dump)
+{
+ struct switch_stack *sw;
+
+ /* changed the size calculations - should hopefully work better. lbt */
+ dump->magic = CMAGIC;
+ dump->start_code = 0;
+ dump->start_stack = rdusp() & ~(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->u_ar0 = (struct user_regs_struct *)((int)&dump->regs - (int)dump);
+ sw = ((struct switch_stack *)regs) - 1;
+ dump->regs.d1 = regs->d1;
+ dump->regs.d2 = regs->d2;
+ dump->regs.d3 = regs->d3;
+ dump->regs.d4 = regs->d4;
+ dump->regs.d5 = regs->d5;
+ dump->regs.d6 = sw->d6;
+ dump->regs.d7 = sw->d7;
+ dump->regs.a0 = regs->a0;
+ dump->regs.a1 = regs->a1;
+ dump->regs.a2 = regs->a2;
+ dump->regs.a3 = sw->a3;
+ dump->regs.a4 = sw->a4;
+ dump->regs.a5 = sw->a5;
+ dump->regs.a6 = sw->a6;
+ dump->regs.d0 = regs->d0;
+ dump->regs.orig_d0 = regs->orig_d0;
+ dump->regs.stkadj = regs->stkadj;
+ dump->regs.sr = regs->sr;
+ dump->regs.pc = regs->pc;
+ dump->regs.fmtvec = (regs->format << 12) | regs->vector;
+ /* dump floating point stuff */
+ dump->u_fpvalid = dump_fpu (regs, &dump->m68kfp);
+}
+
+/*
+ * Generic dumping code. Used for panic and debug.
+ */
+void dump(struct pt_regs *fp)
+{
+ unsigned long *sp;
+ unsigned char *tp;
+ int i;
+
+ printk(KERN_EMERG "\nCURRENT PROCESS:\n\n");
+ printk(KERN_EMERG "COMM=%s PID=%d\n", current->comm, current->pid);
+
+ if (current->mm) {
+ printk(KERN_EMERG "TEXT=%08x-%08x DATA=%08x-%08x BSS=%08x-%08x\n",
+ (int) current->mm->start_code,
+ (int) current->mm->end_code,
+ (int) current->mm->start_data,
+ (int) current->mm->end_data,
+ (int) current->mm->end_data,
+ (int) current->mm->brk);
+ printk(KERN_EMERG "USER-STACK=%08x KERNEL-STACK=%08x\n\n",
+ (int) current->mm->start_stack,
+ (int)(((unsigned long) current) + THREAD_SIZE));
+ }
+
+ printk(KERN_EMERG "PC: %08lx\n", fp->pc);
+ printk(KERN_EMERG "SR: %08lx SP: %08lx\n", (long) fp->sr, (long) fp);
+ printk(KERN_EMERG "d0: %08lx d1: %08lx d2: %08lx d3: %08lx\n",
+ fp->d0, fp->d1, fp->d2, fp->d3);
+ printk(KERN_EMERG "d4: %08lx d5: %08lx a0: %08lx a1: %08lx\n",
+ fp->d4, fp->d5, fp->a0, fp->a1);
+ printk(KERN_EMERG "\nUSP: %08x TRAPFRAME: %08x\n", (unsigned int) rdusp(),
+ (unsigned int) fp);
+
+ printk(KERN_EMERG "\nCODE:");
+ tp = ((unsigned char *) fp->pc) - 0x20;
+ for (sp = (unsigned long *) tp, i = 0; (i < 0x40); i += 4) {
+ if ((i % 0x10) == 0)
+ printk(KERN_EMERG "\n%08x: ", (int) (tp + i));
+ printk(KERN_EMERG "%08x ", (int) *sp++);
+ }
+ printk(KERN_EMERG "\n");
+
+ printk(KERN_EMERG "\nKERNEL STACK:");
+ tp = ((unsigned char *) fp) - 0x40;
+ for (sp = (unsigned long *) tp, i = 0; (i < 0xc0); i += 4) {
+ if ((i % 0x10) == 0)
+ printk(KERN_EMERG "\n%08x: ", (int) (tp + i));
+ printk(KERN_EMERG "%08x ", (int) *sp++);
+ }
+ printk(KERN_EMERG "\n");
+ printk(KERN_EMERG "\n");
+
+ printk(KERN_EMERG "\nUSER STACK:");
+ tp = (unsigned char *) (rdusp() - 0x10);
+ for (sp = (unsigned long *) tp, i = 0; (i < 0x80); i += 4) {
+ if ((i % 0x10) == 0)
+ printk(KERN_EMERG "\n%08x: ", (int) (tp + i));
+ printk(KERN_EMERG "%08x ", (int) *sp++);
+ }
+ printk(KERN_EMERG "\n\n");
+}
+
+/*
+ * sys_execve() executes a new program.
+ */
+asmlinkage int sys_execve(char *name, char **argv, char **envp)
+{
+ int error;
+ char * filename;
+ struct pt_regs *regs = (struct pt_regs *) &name;
+
+ lock_kernel();
+ filename = getname(name);
+ error = PTR_ERR(filename);
+ if (IS_ERR(filename))
+ goto out;
+ error = do_execve(filename, argv, envp, regs);
+ putname(filename);
+out:
+ unlock_kernel();
+ return error;
+}
+
+unsigned long get_wchan(struct task_struct *p)
+{
+ unsigned long fp, pc;
+ unsigned long stack_page;
+ int count = 0;
+ if (!p || p == current || p->state == TASK_RUNNING)
+ return 0;
+
+ stack_page = (unsigned long)p;
+ fp = ((struct switch_stack *)p->thread.ksp)->a6;
+ do {
+ if (fp < stack_page+sizeof(struct thread_info) ||
+ fp >= 8184+stack_page)
+ return 0;
+ pc = ((unsigned long *)fp)[1];
+ if (!in_sched_functions(pc))
+ return pc;
+ fp = *(unsigned long *) fp;
+ } while (count++ < 16);
+ return 0;
+}
+
+/*
+ * Return saved PC of a blocked thread.
+ */
+unsigned long thread_saved_pc(struct task_struct *tsk)
+{
+ struct switch_stack *sw = (struct switch_stack *)tsk->thread.ksp;
+
+ /* Check whether the thread is blocked in resume() */
+ if (in_sched_functions(sw->retpc))
+ return ((unsigned long *)sw->a6)[1];
+ else
+ return sw->retpc;
+}
+
diff --git a/arch/m68knommu/kernel/ptrace.c b/arch/m68knommu/kernel/ptrace.c
new file mode 100644
index 000000000000..15cf79080b15
--- /dev/null
+++ b/arch/m68knommu/kernel/ptrace.c
@@ -0,0 +1,383 @@
+/*
+ * linux/arch/m68knommu/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 <asm/uaccess.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/system.h>
+#include <asm/processor.h>
+
+/*
+ * does not yet catch signals sent when the child dies.
+ * in exit.c or in signal.c.
+ */
+
+/* determines which bits in the SR the user has access to. */
+/* 1 = access 0 = no access */
+#define SR_MASK 0x001f
+
+/* sets the trace bits. */
+#define TRACE_BITS 0x8000
+
+/* Find the stack offset for a register, relative to thread.esp0. */
+#define PT_REG(reg) ((long)&((struct pt_regs *)0)->reg)
+#define SW_REG(reg) ((long)&((struct switch_stack *)0)->reg \
+ - sizeof(struct switch_stack))
+/* Mapping from PT_xxx to the stack offset at which the register is
+ saved. Notice that usp has no stack-slot and needs to be treated
+ specially (see get_reg/put_reg below). */
+static int regoff[] = {
+ PT_REG(d1), PT_REG(d2), PT_REG(d3), PT_REG(d4),
+ PT_REG(d5), SW_REG(d6), SW_REG(d7), PT_REG(a0),
+ PT_REG(a1), PT_REG(a2), SW_REG(a3), SW_REG(a4),
+ SW_REG(a5), SW_REG(a6), PT_REG(d0), -1,
+ PT_REG(orig_d0), PT_REG(sr), PT_REG(pc),
+};
+
+/*
+ * Get contents of register REGNO in task TASK.
+ */
+static inline long get_reg(struct task_struct *task, int regno)
+{
+ unsigned long *addr;
+
+ if (regno == PT_USP)
+ addr = &task->thread.usp;
+ else if (regno < sizeof(regoff)/sizeof(regoff[0]))
+ addr = (unsigned long *)(task->thread.esp0 + regoff[regno]);
+ else
+ return 0;
+ return *addr;
+}
+
+/*
+ * Write contents of register REGNO in task TASK.
+ */
+static inline int put_reg(struct task_struct *task, int regno,
+ unsigned long data)
+{
+ unsigned long *addr;
+
+ if (regno == PT_USP)
+ addr = &task->thread.usp;
+ else if (regno < sizeof(regoff)/sizeof(regoff[0]))
+ addr = (unsigned long *) (task->thread.esp0 + regoff[regno]);
+ else
+ return -1;
+ *addr = data;
+ return 0;
+}
+
+/*
+ * Called by kernel/ptrace.c when detaching..
+ *
+ * Make sure the single step bit is not set.
+ */
+void ptrace_disable(struct task_struct *child)
+{
+ unsigned long tmp;
+ /* make sure the single step bit is not set. */
+ tmp = get_reg(child, PT_SR) & ~(TRACE_BITS << 16);
+ put_reg(child, PT_SR, tmp);
+}
+
+asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
+{
+ struct task_struct *child;
+ int ret;
+
+ lock_kernel();
+ ret = -EPERM;
+ if (request == PTRACE_TRACEME) {
+ /* are we already being traced? */
+ if (current->ptrace & PT_PTRACED)
+ 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: {
+ unsigned long tmp;
+ int copied;
+
+ copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0);
+ ret = -EIO;
+ 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: {
+ unsigned long tmp;
+
+ ret = -EIO;
+ if ((addr & 3) || addr < 0 ||
+ addr > sizeof(struct user) - 3)
+ break;
+
+ tmp = 0; /* Default return condition */
+ addr = addr >> 2; /* temporary hack. */
+ ret = -EIO;
+ if (addr < 19) {
+ tmp = get_reg(child, addr);
+ if (addr == PT_SR)
+ tmp >>= 16;
+ } else if (addr >= 21 && addr < 49) {
+ tmp = child->thread.fp[addr - 21];
+#ifdef CONFIG_M68KFPU_EMU
+ /* Convert internal fpu reg representation
+ * into long double format
+ */
+ if (FPU_IS_EMU && (addr < 45) && !(addr % 3))
+ tmp = ((tmp & 0xffff0000) << 15) |
+ ((tmp & 0x0000ffff) << 16);
+#endif
+ } else if (addr == 49) {
+ tmp = child->mm->start_code;
+ } else if (addr == 50) {
+ tmp = child->mm->start_data;
+ } else if (addr == 51) {
+ tmp = child->mm->end_code;
+ } else
+ break;
+ 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 = 0;
+ if (access_process_vm(child, addr, &data, sizeof(data), 1) == sizeof(data))
+ break;
+ ret = -EIO;
+ break;
+
+ case PTRACE_POKEUSR: /* write the word at location addr in the USER area */
+ ret = -EIO;
+ if ((addr & 3) || addr < 0 ||
+ addr > sizeof(struct user) - 3)
+ break;
+
+ addr = addr >> 2; /* temporary hack. */
+
+ if (addr == PT_SR) {
+ data &= SR_MASK;
+ data <<= 16;
+ data |= get_reg(child, PT_SR) & ~(SR_MASK << 16);
+ }
+ if (addr < 19) {
+ if (put_reg(child, addr, data))
+ break;
+ ret = 0;
+ break;
+ }
+ if (addr >= 21 && addr < 48)
+ {
+#ifdef CONFIG_M68KFPU_EMU
+ /* Convert long double format
+ * into internal fpu reg representation
+ */
+ if (FPU_IS_EMU && (addr < 45) && !(addr % 3)) {
+ data = (unsigned long)data << 15;
+ data = (data & 0xffff0000) |
+ ((data & 0x0000ffff) >> 1);
+ }
+#endif
+ child->thread.fp[addr - 21] = data;
+ ret = 0;
+ }
+ break;
+
+ case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */
+ case PTRACE_CONT: { /* restart after signal. */
+ long tmp;
+
+ 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;
+ /* make sure the single step bit is not set. */
+ tmp = get_reg(child, PT_SR) & ~(TRACE_BITS << 16);
+ put_reg(child, PT_SR, tmp);
+ 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: {
+ long tmp;
+
+ ret = 0;
+ if (child->exit_state == EXIT_ZOMBIE) /* already dead */
+ break;
+ child->exit_code = SIGKILL;
+ /* make sure the single step bit is not set. */
+ tmp = get_reg(child, PT_SR) & ~(TRACE_BITS << 16);
+ put_reg(child, PT_SR, tmp);
+ wake_up_process(child);
+ break;
+ }
+
+ case PTRACE_SINGLESTEP: { /* set the trap flag. */
+ long tmp;
+
+ ret = -EIO;
+ if ((unsigned long) data > _NSIG)
+ break;
+ clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
+ tmp = get_reg(child, PT_SR) | (TRACE_BITS << 16);
+ put_reg(child, PT_SR, tmp);
+
+ child->exit_code = data;
+ /* give it a chance to run. */
+ 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 gp regs from the child. */
+ int i;
+ unsigned long tmp;
+ for (i = 0; i < 19; i++) {
+ tmp = get_reg(child, i);
+ if (i == PT_SR)
+ tmp >>= 16;
+ if (put_user(tmp, (unsigned long *) data)) {
+ ret = -EFAULT;
+ break;
+ }
+ data += sizeof(long);
+ }
+ ret = 0;
+ break;
+ }
+
+ case PTRACE_SETREGS: { /* Set all gp regs in the child. */
+ int i;
+ unsigned long tmp;
+ for (i = 0; i < 19; i++) {
+ if (get_user(tmp, (unsigned long *) data)) {
+ ret = -EFAULT;
+ break;
+ }
+ if (i == PT_SR) {
+ tmp &= SR_MASK;
+ tmp <<= 16;
+ tmp |= get_reg(child, PT_SR) & ~(SR_MASK << 16);
+ }
+ put_reg(child, i, tmp);
+ data += sizeof(long);
+ }
+ ret = 0;
+ break;
+ }
+
+#ifdef PTRACE_GETFPREGS
+ case PTRACE_GETFPREGS: { /* Get the child FPU state. */
+ ret = 0;
+ if (copy_to_user((void *)data, &child->thread.fp,
+ sizeof(struct user_m68kfp_struct)))
+ ret = -EFAULT;
+ break;
+ }
+#endif
+
+#ifdef PTRACE_SETFPREGS
+ case PTRACE_SETFPREGS: { /* Set the child FPU state. */
+ ret = 0;
+ if (copy_from_user(&child->thread.fp, (void *)data,
+ sizeof(struct user_m68kfp_struct)))
+ ret = -EFAULT;
+ break;
+ }
+#endif
+
+ default:
+ ret = -EIO;
+ break;
+ }
+out_tsk:
+ put_task_struct(child);
+out:
+ unlock_kernel();
+ return ret;
+}
+
+asmlinkage void syscall_trace(void)
+{
+ if (!test_thread_flag(TIF_SYSCALL_TRACE))
+ return;
+ if (!(current->ptrace & PT_PTRACED))
+ return;
+ ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
+ ? 0x80 : 0));
+ /*
+ * this isn't the same as continuing with a signal, but it will do
+ * for normal use. strace only continues with a signal if the
+ * stopping signal is not SIGTRAP. -brl
+ */
+ if (current->exit_code) {
+ send_sig(current->exit_code, current, 1);
+ current->exit_code = 0;
+ }
+}
diff --git a/arch/m68knommu/kernel/semaphore.c b/arch/m68knommu/kernel/semaphore.c
new file mode 100644
index 000000000000..c083f4772add
--- /dev/null
+++ b/arch/m68knommu/kernel/semaphore.c
@@ -0,0 +1,134 @@
+/*
+ * Generic semaphore code. Buyer beware. Do your own
+ * specific changes in <asm/semaphore-helper.h>
+ */
+
+#include <linux/config.h>
+#include <linux/sched.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <asm/semaphore-helper.h>
+
+#ifndef CONFIG_RMW_INSNS
+spinlock_t semaphore_wake_lock;
+#endif
+
+/*
+ * Semaphores are implemented using a two-way counter:
+ * The "count" variable is decremented for each process
+ * that tries to sleep, while the "waking" variable is
+ * incremented when the "up()" code goes to wake up waiting
+ * processes.
+ *
+ * Notably, the inline "up()" and "down()" functions can
+ * efficiently test if they need to do any extra work (up
+ * needs to do something only if count was negative before
+ * the increment operation.
+ *
+ * waking_non_zero() (from asm/semaphore.h) must execute
+ * atomically.
+ *
+ * When __up() is called, the count was negative before
+ * incrementing it, and we need to wake up somebody.
+ *
+ * This routine adds one to the count of processes that need to
+ * wake up and exit. ALL waiting processes actually wake up but
+ * only the one that gets to the "waking" field first will gate
+ * through and acquire the semaphore. The others will go back
+ * to sleep.
+ *
+ * Note that these functions are only called when there is
+ * contention on the lock, and as such all this is the
+ * "non-critical" part of the whole semaphore business. The
+ * critical part is the inline stuff in <asm/semaphore.h>
+ * where we want to avoid any extra jumps and calls.
+ */
+void __up(struct semaphore *sem)
+{
+ wake_one_more(sem);
+ wake_up(&sem->wait);
+}
+
+/*
+ * Perform the "down" function. Return zero for semaphore acquired,
+ * return negative for signalled out of the function.
+ *
+ * If called from __down, the return is ignored and the wait loop is
+ * not interruptible. This means that a task waiting on a semaphore
+ * using "down()" cannot be killed until someone does an "up()" on
+ * the semaphore.
+ *
+ * If called from __down_interruptible, the return value gets checked
+ * upon return. If the return value is negative then the task continues
+ * with the negative value in the return register (it can be tested by
+ * the caller).
+ *
+ * Either form may be used in conjunction with "up()".
+ *
+ */
+
+
+#define DOWN_HEAD(task_state) \
+ \
+ \
+ current->state = (task_state); \
+ add_wait_queue(&sem->wait, &wait); \
+ \
+ /* \
+ * Ok, we're set up. sem->count is known to be less than zero \
+ * so we must wait. \
+ * \
+ * We can let go the lock for purposes of waiting. \
+ * We re-acquire it after awaking so as to protect \
+ * all semaphore operations. \
+ * \
+ * If "up()" is called before we call waking_non_zero() then \
+ * we will catch it right away. If it is called later then \
+ * we will have to go through a wakeup cycle to catch it. \
+ * \
+ * Multiple waiters contend for the semaphore lock to see \
+ * who gets to gate through and who has to wait some more. \
+ */ \
+ for (;;) {
+
+#define DOWN_TAIL(task_state) \
+ current->state = (task_state); \
+ } \
+ current->state = TASK_RUNNING; \
+ remove_wait_queue(&sem->wait, &wait);
+
+void __sched __down(struct semaphore * sem)
+{
+ DECLARE_WAITQUEUE(wait, current);
+
+ DOWN_HEAD(TASK_UNINTERRUPTIBLE)
+ if (waking_non_zero(sem))
+ break;
+ schedule();
+ DOWN_TAIL(TASK_UNINTERRUPTIBLE)
+}
+
+int __sched __down_interruptible(struct semaphore * sem)
+{
+ DECLARE_WAITQUEUE(wait, current);
+ int ret = 0;
+
+ DOWN_HEAD(TASK_INTERRUPTIBLE)
+
+ ret = waking_non_zero_interruptible(sem, current);
+ if (ret)
+ {
+ if (ret == 1)
+ /* ret != 0 only if we get interrupted -arca */
+ ret = 0;
+ break;
+ }
+ schedule();
+ DOWN_TAIL(TASK_INTERRUPTIBLE)
+ return ret;
+}
+
+int __down_trylock(struct semaphore * sem)
+{
+ return waking_non_zero_trylock(sem);
+}
diff --git a/arch/m68knommu/kernel/setup.c b/arch/m68knommu/kernel/setup.c
new file mode 100644
index 000000000000..557238596dcb
--- /dev/null
+++ b/arch/m68knommu/kernel/setup.c
@@ -0,0 +1,347 @@
+/*
+ * linux/arch/m68knommu/kernel/setup.c
+ *
+ * Copyright (C) 1999-2004 Greg Ungerer (gerg@snapgear.com)
+ * Copyright (C) 1998,1999 D. Jeff Dionne <jeff@lineo.ca>
+ * Copyleft ()) 2000 James D. Schettine {james@telos-systems.com}
+ * 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>
+ *
+ * 68VZ328 Fixes/support Evan Stawnyczy <e@lineo.ca>
+ */
+
+/*
+ * This file handles the architecture-dependent parts of system setup
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/fs.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/seq_file.h>
+#include <linux/root_dev.h>
+#include <linux/init.h>
+
+#include <asm/setup.h>
+#include <asm/irq.h>
+#include <asm/machdep.h>
+
+#ifdef CONFIG_BLK_DEV_INITRD
+#include <asm/pgtable.h>
+#endif
+
+unsigned long rom_length;
+unsigned long memory_start;
+unsigned long memory_end;
+
+char command_line[COMMAND_LINE_SIZE];
+
+/* setup some dummy routines */
+static void dummy_waitbut(void)
+{
+}
+
+void (*mach_sched_init) (irqreturn_t (*handler)(int, void *, struct pt_regs *)) = NULL;
+void (*mach_tick)( void ) = NULL;
+/* machine dependent keyboard functions */
+int (*mach_keyb_init) (void) = NULL;
+int (*mach_kbdrate) (struct kbd_repeat *) = NULL;
+void (*mach_kbd_leds) (unsigned int) = NULL;
+/* machine dependent irq functions */
+void (*mach_init_IRQ) (void) = NULL;
+irqreturn_t (*(*mach_default_handler)[]) (int, void *, struct pt_regs *) = NULL;
+void (*mach_enable_irq) (unsigned int) = NULL;
+void (*mach_disable_irq) (unsigned int) = NULL;
+int (*mach_get_irq_list) (struct seq_file *, void *) = NULL;
+void (*mach_process_int) (int irq, struct pt_regs *fp) = NULL;
+void (*mach_trap_init) (void);
+/* machine dependent timer functions */
+unsigned long (*mach_gettimeoffset) (void) = NULL;
+void (*mach_gettod) (int*, int*, int*, int*, int*, int*) = NULL;
+int (*mach_hwclk) (int, struct hwclk_time*) = NULL;
+int (*mach_set_clock_mmss) (unsigned long) = NULL;
+void (*mach_mksound)( unsigned int count, unsigned int ticks ) = NULL;
+void (*mach_reset)( void ) = NULL;
+void (*waitbut)(void) = dummy_waitbut;
+void (*mach_debug_init)(void) = NULL;
+void (*mach_halt)( void ) = NULL;
+void (*mach_power_off)( void ) = NULL;
+
+
+#ifdef CONFIG_M68000
+ #define CPU "MC68000"
+#endif
+#ifdef CONFIG_M68328
+ #define CPU "MC68328"
+#endif
+#ifdef CONFIG_M68EZ328
+ #define CPU "MC68EZ328"
+#endif
+#ifdef CONFIG_M68VZ328
+ #define CPU "MC68VZ328"
+#endif
+#ifdef CONFIG_M68332
+ #define CPU "MC68332"
+#endif
+#ifdef CONFIG_M68360
+ #define CPU "MC68360"
+#endif
+#if defined(CONFIG_M5206)
+ #define CPU "COLDFIRE(m5206)"
+#endif
+#if defined(CONFIG_M5206e)
+ #define CPU "COLDFIRE(m5206e)"
+#endif
+#if defined(CONFIG_M5249)
+ #define CPU "COLDFIRE(m5249)"
+#endif
+#if defined(CONFIG_M527x)
+ #define CPU "COLDFIRE(m5270/5271/5274/5275)"
+#endif
+#if defined(CONFIG_M5272)
+ #define CPU "COLDFIRE(m5272)"
+#endif
+#if defined(CONFIG_M528x)
+ #define CPU "COLDFIRE(m5280/5282)"
+#endif
+#if defined(CONFIG_M5307)
+ #define CPU "COLDFIRE(m5307)"
+#endif
+#if defined(CONFIG_M5407)
+ #define CPU "COLDFIRE(m5407)"
+#endif
+#ifndef CPU
+ #define CPU "UNKOWN"
+#endif
+
+/* (es) */
+/* note: why is this defined here? the must be a better place to put this */
+#if defined( CONFIG_TELOS) || defined( CONFIG_UCDIMM ) || defined( CONFIG_UCSIMM ) || defined(CONFIG_DRAGEN2) || (defined( CONFIG_PILOT ) && defined( CONFIG_M68328 ))
+#define CAT_ROMARRAY
+#endif
+/* (/es) */
+
+extern int _stext, _etext, _sdata, _edata, _sbss, _ebss, _end;
+extern int _ramstart, _ramend;
+
+void setup_arch(char **cmdline_p)
+{
+ int bootmap_size;
+
+#if defined(CAT_ROMARRAY) && defined(DEBUG)
+ extern int __data_rom_start;
+ extern int __data_start;
+ int *romarray = (int *)((int) &__data_rom_start +
+ (int)&_edata - (int)&__data_start);
+#endif
+
+ memory_start = PAGE_ALIGN(_ramstart);
+ memory_end = _ramend; /* by now the stack is part of the init task */
+
+ init_mm.start_code = (unsigned long) &_stext;
+ init_mm.end_code = (unsigned long) &_etext;
+ init_mm.end_data = (unsigned long) &_edata;
+ init_mm.brk = (unsigned long) 0;
+
+ config_BSP(&command_line[0], sizeof(command_line));
+
+ printk(KERN_INFO "\x0F\r\n\nuClinux/" CPU "\n");
+
+#ifdef CONFIG_UCDIMM
+ printk(KERN_INFO "uCdimm by Lineo, Inc. <www.lineo.com>\n");
+#endif
+#ifdef CONFIG_M68VZ328
+ printk(KERN_INFO "M68VZ328 support by Evan Stawnyczy <e@lineo.ca>\n");
+#endif
+#ifdef CONFIG_COLDFIRE
+ printk(KERN_INFO "COLDFIRE port done by Greg Ungerer, gerg@snapgear.com\n");
+#ifdef CONFIG_M5307
+ printk(KERN_INFO "Modified for M5307 by Dave Miller, dmiller@intellistor.com\n");
+#endif
+#ifdef CONFIG_ELITE
+ printk(KERN_INFO "Modified for M5206eLITE by Rob Scott, rscott@mtrob.fdns.net\n");
+#endif
+#ifdef CONFIG_TELOS
+ printk(KERN_INFO "Modified for Omnia ToolVox by James D. Schettine, james@telos-systems.com\n");
+#endif
+#endif
+ printk(KERN_INFO "Flat model support (C) 1998,1999 Kenneth Albanowski, D. Jeff Dionne\n");
+
+#if defined( CONFIG_PILOT ) && defined( CONFIG_M68328 )
+ printk(KERN_INFO "TRG SuperPilot FLASH card support <info@trgnet.com>\n");
+#endif
+
+#if defined( CONFIG_PILOT ) && defined( CONFIG_M68EZ328 )
+ printk(KERN_INFO "PalmV support by Lineo Inc. <jeff@uclinux.com>\n");
+#endif
+
+#ifdef CONFIG_M68EZ328ADS
+ printk(KERN_INFO "M68EZ328ADS board support (C) 1999 Vladimir Gurevich <vgurevic@cisco.com>\n");
+#endif
+
+#ifdef CONFIG_ALMA_ANS
+ printk(KERN_INFO "Alma Electronics board support (C) 1999 Vladimir Gurevich <vgurevic@cisco.com>\n");
+#endif
+#if defined (CONFIG_M68360)
+ printk(KERN_INFO "QUICC port done by SED Systems <hamilton@sedsystems.ca>,\n");
+ printk(KERN_INFO "based on 2.0.38 port by Lineo Inc. <mleslie@lineo.com>.\n");
+#endif
+#ifdef CONFIG_DRAGEN2
+ printk(KERN_INFO "DragonEngine II board support by Georges Menie\n");
+#endif
+
+#ifdef DEBUG
+ printk(KERN_DEBUG "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);
+ printk(KERN_DEBUG "KERNEL -> ROMFS=0x%06x-0x%06x MEM=0x%06x-0x%06x "
+ "STACK=0x%06x-0x%06x\n",
+#ifdef CAT_ROMARRAY
+ (int) romarray, ((int) romarray) + romarray[2],
+#else
+ (int) &_ebss, (int) memory_start,
+#endif
+ (int) memory_start, (int) memory_end,
+ (int) memory_end, (int) _ramend);
+#endif
+
+ /* Keep a copy of command line */
+ *cmdline_p = &command_line[0];
+ memcpy(saved_command_line, command_line, COMMAND_LINE_SIZE);
+ saved_command_line[COMMAND_LINE_SIZE-1] = 0;
+
+#ifdef DEBUG
+ if (strlen(*cmdline_p))
+ printk(KERN_DEBUG "Command line: '%s'\n", *cmdline_p);
+#endif
+
+#if defined(CONFIG_FRAMEBUFFER_CONSOLE) && defined(CONFIG_DUMMY_CONSOLE)
+ conswitchp = &dummy_con;
+#endif
+
+ /*
+ * Give all the memory to the bootmap allocator, tell it to put the
+ * boot mem_map at the start of memory.
+ */
+ bootmap_size = init_bootmem_node(
+ NODE_DATA(0),
+ memory_start >> PAGE_SHIFT, /* map goes here */
+ PAGE_OFFSET >> PAGE_SHIFT, /* 0 on coldfire */
+ memory_end >> PAGE_SHIFT);
+ /*
+ * Free the usable memory, we have to make sure we do not free
+ * the bootmem bitmap so we then reserve it after freeing it :-)
+ */
+ free_bootmem(memory_start, memory_end - memory_start);
+ reserve_bootmem(memory_start, bootmap_size);
+
+ /*
+ * Get kmalloc into gear.
+ */
+ paging_init();
+}
+
+int get_cpuinfo(char * buffer)
+{
+ char *cpu, *mmu, *fpu;
+ u_long clockfreq;
+
+ cpu = CPU;
+ mmu = "none";
+ fpu = "none";
+
+#ifdef CONFIG_COLDFIRE
+ clockfreq = (loops_per_jiffy*HZ)*3;
+#else
+ clockfreq = (loops_per_jiffy*HZ)*16;
+#endif
+
+ return(sprintf(buffer, "CPU:\t\t%s\n"
+ "MMU:\t\t%s\n"
+ "FPU:\t\t%s\n"
+ "Clocking:\t%lu.%1luMHz\n"
+ "BogoMips:\t%lu.%02lu\n"
+ "Calibration:\t%lu loops\n",
+ cpu, mmu, fpu,
+ clockfreq/1000000,(clockfreq/100000)%10,
+ (loops_per_jiffy*HZ)/500000,((loops_per_jiffy*HZ)/5000)%100,
+ (loops_per_jiffy*HZ)));
+
+}
+
+/*
+ * Get CPU information for use by the procfs.
+ */
+
+static int show_cpuinfo(struct seq_file *m, void *v)
+{
+ char *cpu, *mmu, *fpu;
+ u_long clockfreq;
+
+ cpu = CPU;
+ mmu = "none";
+ fpu = "none";
+
+#ifdef CONFIG_COLDFIRE
+ clockfreq = (loops_per_jiffy*HZ)*3;
+#else
+ clockfreq = (loops_per_jiffy*HZ)*16;
+#endif
+
+ seq_printf(m, "CPU:\t\t%s\n"
+ "MMU:\t\t%s\n"
+ "FPU:\t\t%s\n"
+ "Clocking:\t%lu.%1luMHz\n"
+ "BogoMips:\t%lu.%02lu\n"
+ "Calibration:\t%lu loops\n",
+ cpu, mmu, fpu,
+ clockfreq/1000000,(clockfreq/100000)%10,
+ (loops_per_jiffy*HZ)/500000,((loops_per_jiffy*HZ)/5000)%100,
+ (loops_per_jiffy*HZ));
+
+ return 0;
+}
+
+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)
+{
+ if (mach_gettod)
+ mach_gettod(year, mon, day, hour, min, sec);
+ else
+ *year = *mon = *day = *hour = *min = *sec = 0;
+}
+
diff --git a/arch/m68knommu/kernel/signal.c b/arch/m68knommu/kernel/signal.c
new file mode 100644
index 000000000000..30dceb59a462
--- /dev/null
+++ b/arch/m68knommu/kernel/signal.c
@@ -0,0 +1,788 @@
+/*
+ * linux/arch/m68knommu/kernel/signal.c
+ *
+ * Copyright (C) 1991, 1992 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.
+ */
+
+/*
+ * Linux/m68k support by Hamish Macdonald
+ *
+ * 68060 fixes by Jesper Skov
+ *
+ * 1997-12-01 Modified for POSIX.1b signals by Andreas Schwab
+ *
+ * mathemu support by Roman Zippel
+ * (Note: fpstate in the signal context is completely ignored for the emulator
+ * and the internal floating point format is put on stack)
+ */
+
+/*
+ * ++roman (07/09/96): implemented signal stacks (specially for tosemu on
+ * Atari :-) Current limitation: Only one sigstack can be active at one time.
+ * If a second signal with SA_ONSTACK set arrives while working on a sigstack,
+ * SA_ONSTACK is ignored. This behaviour avoids lots of trouble with nested
+ * signal handlers!
+ */
+
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/kernel.h>
+#include <linux/signal.h>
+#include <linux/syscalls.h>
+#include <linux/errno.h>
+#include <linux/wait.h>
+#include <linux/ptrace.h>
+#include <linux/unistd.h>
+#include <linux/stddef.h>
+#include <linux/highuid.h>
+#include <linux/tty.h>
+#include <linux/personality.h>
+#include <linux/binfmts.h>
+
+#include <asm/setup.h>
+#include <asm/uaccess.h>
+#include <asm/pgtable.h>
+#include <asm/traps.h>
+#include <asm/ucontext.h>
+
+#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
+
+asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs);
+
+/*
+ * Atomically swap in the new signal mask, and wait for a signal.
+ */
+asmlinkage int do_sigsuspend(struct pt_regs *regs)
+{
+ old_sigset_t mask = regs->d3;
+ 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);
+
+ regs->d0 = -EINTR;
+ while (1) {
+ current->state = TASK_INTERRUPTIBLE;
+ schedule();
+ if (do_signal(&saveset, regs))
+ return -EINTR;
+ }
+}
+
+asmlinkage int
+do_rt_sigsuspend(struct pt_regs *regs)
+{
+ sigset_t *unewset = (sigset_t *)regs->d1;
+ size_t sigsetsize = (size_t)regs->d2;
+ 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);
+
+ regs->d0 = -EINTR;
+ while (1) {
+ current->state = TASK_INTERRUPTIBLE;
+ schedule();
+ if (do_signal(&saveset, regs))
+ return -EINTR;
+ }
+}
+
+asmlinkage int
+sys_sigaction(int sig, const struct old_sigaction *act,
+ struct old_sigaction *oact)
+{
+ struct k_sigaction new_ka, old_ka;
+ int ret;
+
+ if (act) {
+ old_sigset_t mask;
+ if (!access_ok(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 (!access_ok(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 *uss, stack_t *uoss)
+{
+ return do_sigaltstack(uss, uoss, rdusp());
+}
+
+
+/*
+ * Do a signal return; undo the signal stack.
+ *
+ * Keep the return code on the stack quadword aligned!
+ * That makes the cache flush below easier.
+ */
+
+struct sigframe
+{
+ char *pretcode;
+ int sig;
+ int code;
+ struct sigcontext *psc;
+ char retcode[8];
+ unsigned long extramask[_NSIG_WORDS-1];
+ struct sigcontext sc;
+};
+
+struct rt_sigframe
+{
+ char *pretcode;
+ int sig;
+ struct siginfo *pinfo;
+ void *puc;
+ char retcode[8];
+ struct siginfo info;
+ struct ucontext uc;
+};
+
+#ifdef CONFIG_FPU
+
+static unsigned char fpu_version = 0; /* version number of fpu, set by setup_frame */
+
+static inline int restore_fpu_state(struct sigcontext *sc)
+{
+ int err = 1;
+
+ if (FPU_IS_EMU) {
+ /* restore registers */
+ memcpy(current->thread.fpcntl, sc->sc_fpcntl, 12);
+ memcpy(current->thread.fp, sc->sc_fpregs, 24);
+ return 0;
+ }
+
+ if (sc->sc_fpstate[0]) {
+ /* Verify the frame format. */
+ if (sc->sc_fpstate[0] != fpu_version)
+ goto out;
+
+ __asm__ volatile (".chip 68k/68881\n\t"
+ "fmovemx %0,%/fp0-%/fp1\n\t"
+ "fmoveml %1,%/fpcr/%/fpsr/%/fpiar\n\t"
+ ".chip 68k"
+ : /* no outputs */
+ : "m" (*sc->sc_fpregs), "m" (*sc->sc_fpcntl));
+ }
+ __asm__ volatile (".chip 68k/68881\n\t"
+ "frestore %0\n\t"
+ ".chip 68k" : : "m" (*sc->sc_fpstate));
+ err = 0;
+
+out:
+ return err;
+}
+
+#define FPCONTEXT_SIZE 216
+#define uc_fpstate uc_filler[0]
+#define uc_formatvec uc_filler[FPCONTEXT_SIZE/4]
+#define uc_extra uc_filler[FPCONTEXT_SIZE/4+1]
+
+static inline int rt_restore_fpu_state(struct ucontext *uc)
+{
+ unsigned char fpstate[FPCONTEXT_SIZE];
+ int context_size = 0;
+ fpregset_t fpregs;
+ int err = 1;
+
+ if (FPU_IS_EMU) {
+ /* restore fpu control register */
+ if (__copy_from_user(current->thread.fpcntl,
+ &uc->uc_mcontext.fpregs.f_pcr, 12))
+ goto out;
+ /* restore all other fpu register */
+ if (__copy_from_user(current->thread.fp,
+ uc->uc_mcontext.fpregs.f_fpregs, 96))
+ goto out;
+ return 0;
+ }
+
+ if (__get_user(*(long *)fpstate, (long *)&uc->uc_fpstate))
+ goto out;
+ if (fpstate[0]) {
+ context_size = fpstate[1];
+
+ /* Verify the frame format. */
+ if (fpstate[0] != fpu_version)
+ goto out;
+ if (__copy_from_user(&fpregs, &uc->uc_mcontext.fpregs,
+ sizeof(fpregs)))
+ goto out;
+ __asm__ volatile (".chip 68k/68881\n\t"
+ "fmovemx %0,%/fp0-%/fp7\n\t"
+ "fmoveml %1,%/fpcr/%/fpsr/%/fpiar\n\t"
+ ".chip 68k"
+ : /* no outputs */
+ : "m" (*fpregs.f_fpregs),
+ "m" (fpregs.f_pcr));
+ }
+ if (context_size &&
+ __copy_from_user(fpstate + 4, (long *)&uc->uc_fpstate + 1,
+ context_size))
+ goto out;
+ __asm__ volatile (".chip 68k/68881\n\t"
+ "frestore %0\n\t"
+ ".chip 68k" : : "m" (*fpstate));
+ err = 0;
+
+out:
+ return err;
+}
+
+#endif
+
+static inline int
+restore_sigcontext(struct pt_regs *regs, struct sigcontext *usc, void *fp,
+ int *pd0)
+{
+ int formatvec;
+ struct sigcontext context;
+ int err = 0;
+
+ /* get previous context */
+ if (copy_from_user(&context, usc, sizeof(context)))
+ goto badframe;
+
+ /* restore passed registers */
+ regs->d1 = context.sc_d1;
+ regs->a0 = context.sc_a0;
+ regs->a1 = context.sc_a1;
+ regs->sr = (regs->sr & 0xff00) | (context.sc_sr & 0xff);
+ regs->pc = context.sc_pc;
+ regs->orig_d0 = -1; /* disable syscall checks */
+ wrusp(context.sc_usp);
+ formatvec = context.sc_formatvec;
+ regs->format = formatvec >> 12;
+ regs->vector = formatvec & 0xfff;
+
+#ifdef CONFIG_FPU
+ err = restore_fpu_state(&context);
+#endif
+
+ *pd0 = context.sc_d0;
+ return err;
+
+badframe:
+ return 1;
+}
+
+static inline int
+rt_restore_ucontext(struct pt_regs *regs, struct switch_stack *sw,
+ struct ucontext *uc, int *pd0)
+{
+ int temp;
+ greg_t *gregs = uc->uc_mcontext.gregs;
+ unsigned long usp;
+ int err;
+
+ err = __get_user(temp, &uc->uc_mcontext.version);
+ if (temp != MCONTEXT_VERSION)
+ goto badframe;
+ /* restore passed registers */
+ err |= __get_user(regs->d0, &gregs[0]);
+ err |= __get_user(regs->d1, &gregs[1]);
+ err |= __get_user(regs->d2, &gregs[2]);
+ err |= __get_user(regs->d3, &gregs[3]);
+ err |= __get_user(regs->d4, &gregs[4]);
+ err |= __get_user(regs->d5, &gregs[5]);
+ err |= __get_user(sw->d6, &gregs[6]);
+ err |= __get_user(sw->d7, &gregs[7]);
+ err |= __get_user(regs->a0, &gregs[8]);
+ err |= __get_user(regs->a1, &gregs[9]);
+ err |= __get_user(regs->a2, &gregs[10]);
+ err |= __get_user(sw->a3, &gregs[11]);
+ err |= __get_user(sw->a4, &gregs[12]);
+ err |= __get_user(sw->a5, &gregs[13]);
+ err |= __get_user(sw->a6, &gregs[14]);
+ err |= __get_user(usp, &gregs[15]);
+ wrusp(usp);
+ err |= __get_user(regs->pc, &gregs[16]);
+ err |= __get_user(temp, &gregs[17]);
+ regs->sr = (regs->sr & 0xff00) | (temp & 0xff);
+ regs->orig_d0 = -1; /* disable syscall checks */
+ regs->format = temp >> 12;
+ regs->vector = temp & 0xfff;
+
+ if (do_sigaltstack(&uc->uc_stack, NULL, usp) == -EFAULT)
+ goto badframe;
+
+ *pd0 = regs->d0;
+ return err;
+
+badframe:
+ return 1;
+}
+
+asmlinkage int do_sigreturn(unsigned long __unused)
+{
+ struct switch_stack *sw = (struct switch_stack *) &__unused;
+ struct pt_regs *regs = (struct pt_regs *) (sw + 1);
+ unsigned long usp = rdusp();
+ struct sigframe *frame = (struct sigframe *)(usp - 4);
+ sigset_t set;
+ int d0;
+
+ if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
+ goto badframe;
+ if (__get_user(set.sig[0], &frame->sc.sc_mask) ||
+ (_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(regs, &frame->sc, frame + 1, &d0))
+ goto badframe;
+ return d0;
+
+badframe:
+ force_sig(SIGSEGV, current);
+ return 0;
+}
+
+asmlinkage int do_rt_sigreturn(unsigned long __unused)
+{
+ struct switch_stack *sw = (struct switch_stack *) &__unused;
+ struct pt_regs *regs = (struct pt_regs *) (sw + 1);
+ unsigned long usp = rdusp();
+ struct rt_sigframe *frame = (struct rt_sigframe *)(usp - 4);
+ sigset_t set;
+ int d0;
+
+ if (!access_ok(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 (rt_restore_ucontext(regs, sw, &frame->uc, &d0))
+ goto badframe;
+ return d0;
+
+badframe:
+ force_sig(SIGSEGV, current);
+ return 0;
+}
+
+#ifdef CONFIG_FPU
+/*
+ * Set up a signal frame.
+ */
+
+static inline void save_fpu_state(struct sigcontext *sc, struct pt_regs *regs)
+{
+ if (FPU_IS_EMU) {
+ /* save registers */
+ memcpy(sc->sc_fpcntl, current->thread.fpcntl, 12);
+ memcpy(sc->sc_fpregs, current->thread.fp, 24);
+ return;
+ }
+
+ __asm__ volatile (".chip 68k/68881\n\t"
+ "fsave %0\n\t"
+ ".chip 68k"
+ : : "m" (*sc->sc_fpstate) : "memory");
+
+ if (sc->sc_fpstate[0]) {
+ fpu_version = sc->sc_fpstate[0];
+ __asm__ volatile (".chip 68k/68881\n\t"
+ "fmovemx %/fp0-%/fp1,%0\n\t"
+ "fmoveml %/fpcr/%/fpsr/%/fpiar,%1\n\t"
+ ".chip 68k"
+ : /* no outputs */
+ : "m" (*sc->sc_fpregs),
+ "m" (*sc->sc_fpcntl)
+ : "memory");
+ }
+}
+
+static inline int rt_save_fpu_state(struct ucontext *uc, struct pt_regs *regs)
+{
+ unsigned char fpstate[FPCONTEXT_SIZE];
+ int context_size = 0;
+ int err = 0;
+
+ if (FPU_IS_EMU) {
+ /* save fpu control register */
+ err |= copy_to_user(&uc->uc_mcontext.fpregs.f_pcr,
+ current->thread.fpcntl, 12);
+ /* save all other fpu register */
+ err |= copy_to_user(uc->uc_mcontext.fpregs.f_fpregs,
+ current->thread.fp, 96);
+ return err;
+ }
+
+ __asm__ volatile (".chip 68k/68881\n\t"
+ "fsave %0\n\t"
+ ".chip 68k"
+ : : "m" (*fpstate) : "memory");
+
+ err |= __put_user(*(long *)fpstate, (long *)&uc->uc_fpstate);
+ if (fpstate[0]) {
+ fpregset_t fpregs;
+ context_size = fpstate[1];
+ fpu_version = fpstate[0];
+ __asm__ volatile (".chip 68k/68881\n\t"
+ "fmovemx %/fp0-%/fp7,%0\n\t"
+ "fmoveml %/fpcr/%/fpsr/%/fpiar,%1\n\t"
+ ".chip 68k"
+ : /* no outputs */
+ : "m" (*fpregs.f_fpregs),
+ "m" (fpregs.f_pcr)
+ : "memory");
+ err |= copy_to_user(&uc->uc_mcontext.fpregs, &fpregs,
+ sizeof(fpregs));
+ }
+ if (context_size)
+ err |= copy_to_user((long *)&uc->uc_fpstate + 1, fpstate + 4,
+ context_size);
+ return err;
+}
+
+#endif
+
+static void setup_sigcontext(struct sigcontext *sc, struct pt_regs *regs,
+ unsigned long mask)
+{
+ sc->sc_mask = mask;
+ sc->sc_usp = rdusp();
+ sc->sc_d0 = regs->d0;
+ sc->sc_d1 = regs->d1;
+ sc->sc_a0 = regs->a0;
+ sc->sc_a1 = regs->a1;
+ sc->sc_sr = regs->sr;
+ sc->sc_pc = regs->pc;
+ sc->sc_formatvec = regs->format << 12 | regs->vector;
+#ifdef CONFIG_FPU
+ save_fpu_state(sc, regs);
+#endif
+}
+
+static inline int rt_setup_ucontext(struct ucontext *uc, struct pt_regs *regs)
+{
+ struct switch_stack *sw = (struct switch_stack *)regs - 1;
+ greg_t *gregs = uc->uc_mcontext.gregs;
+ int err = 0;
+
+ err |= __put_user(MCONTEXT_VERSION, &uc->uc_mcontext.version);
+ err |= __put_user(regs->d0, &gregs[0]);
+ err |= __put_user(regs->d1, &gregs[1]);
+ err |= __put_user(regs->d2, &gregs[2]);
+ err |= __put_user(regs->d3, &gregs[3]);
+ err |= __put_user(regs->d4, &gregs[4]);
+ err |= __put_user(regs->d5, &gregs[5]);
+ err |= __put_user(sw->d6, &gregs[6]);
+ err |= __put_user(sw->d7, &gregs[7]);
+ err |= __put_user(regs->a0, &gregs[8]);
+ err |= __put_user(regs->a1, &gregs[9]);
+ err |= __put_user(regs->a2, &gregs[10]);
+ err |= __put_user(sw->a3, &gregs[11]);
+ err |= __put_user(sw->a4, &gregs[12]);
+ err |= __put_user(sw->a5, &gregs[13]);
+ err |= __put_user(sw->a6, &gregs[14]);
+ err |= __put_user(rdusp(), &gregs[15]);
+ err |= __put_user(regs->pc, &gregs[16]);
+ err |= __put_user(regs->sr, &gregs[17]);
+#ifdef CONFIG_FPU
+ err |= rt_save_fpu_state(uc, regs);
+#endif
+ return err;
+}
+
+static inline void push_cache (unsigned long vaddr)
+{
+}
+
+static inline void *
+get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size)
+{
+ unsigned long usp;
+
+ /* Default to using normal stack. */
+ usp = rdusp();
+
+ /* This is the X/Open sanctioned signal stack switching. */
+ if (ka->sa.sa_flags & SA_ONSTACK) {
+ if (!on_sig_stack(usp))
+ usp = current->sas_ss_sp + current->sas_ss_size;
+ }
+ return (void *)((usp - frame_size) & -8UL);
+}
+
+static void setup_frame (int sig, struct k_sigaction *ka,
+ sigset_t *set, struct pt_regs *regs)
+{
+ struct sigframe *frame;
+ struct sigcontext context;
+ int err = 0;
+
+ frame = get_sigframe(ka, regs, sizeof(*frame));
+
+ err |= __put_user((current_thread_info()->exec_domain
+ && current_thread_info()->exec_domain->signal_invmap
+ && sig < 32
+ ? current_thread_info()->exec_domain->signal_invmap[sig]
+ : sig),
+ &frame->sig);
+
+ err |= __put_user(regs->vector, &frame->code);
+ err |= __put_user(&frame->sc, &frame->psc);
+
+ if (_NSIG_WORDS > 1)
+ err |= copy_to_user(frame->extramask, &set->sig[1],
+ sizeof(frame->extramask));
+
+ setup_sigcontext(&context, regs, set->sig[0]);
+ err |= copy_to_user (&frame->sc, &context, sizeof(context));
+
+ /* Set up to return from userspace. */
+ err |= __put_user(frame->retcode, &frame->pretcode);
+ /* moveq #,d0; trap #0 */
+ err |= __put_user(0x70004e40 + (__NR_sigreturn << 16),
+ (long *)(frame->retcode));
+
+ if (err)
+ goto give_sigsegv;
+
+ push_cache ((unsigned long) &frame->retcode);
+
+ /* Set up registers for signal handler */
+ wrusp ((unsigned long) frame);
+ regs->pc = (unsigned long) ka->sa.sa_handler;
+
+adjust_stack:
+ /* Prepare to skip over the extra stuff in the exception frame. */
+ if (regs->stkadj) {
+ struct pt_regs *tregs =
+ (struct pt_regs *)((ulong)regs + regs->stkadj);
+#if DEBUG
+ printk(KERN_DEBUG "Performing stackadjust=%04x\n", regs->stkadj);
+#endif
+ /* This must be copied with decreasing addresses to
+ handle overlaps. */
+ tregs->vector = 0;
+ tregs->format = 0;
+ tregs->pc = regs->pc;
+ tregs->sr = regs->sr;
+ }
+ return;
+
+give_sigsegv:
+ force_sigsegv(sig, current);
+ goto adjust_stack;
+}
+
+static void setup_rt_frame (int sig, struct k_sigaction *ka, siginfo_t *info,
+ sigset_t *set, struct pt_regs *regs)
+{
+ struct rt_sigframe *frame;
+ int err = 0;
+
+ frame = get_sigframe(ka, regs, sizeof(*frame));
+
+ err |= __put_user((current_thread_info()->exec_domain
+ && current_thread_info()->exec_domain->signal_invmap
+ && sig < 32
+ ? current_thread_info()->exec_domain->signal_invmap[sig]
+ : sig),
+ &frame->sig);
+ err |= __put_user(&frame->info, &frame->pinfo);
+ err |= __put_user(&frame->uc, &frame->puc);
+ err |= copy_siginfo_to_user(&frame->info, info);
+
+ /* Create the ucontext. */
+ err |= __put_user(0, &frame->uc.uc_flags);
+ err |= __put_user(0, &frame->uc.uc_link);
+ err |= __put_user((void *)current->sas_ss_sp,
+ &frame->uc.uc_stack.ss_sp);
+ err |= __put_user(sas_ss_flags(rdusp()),
+ &frame->uc.uc_stack.ss_flags);
+ err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
+ err |= rt_setup_ucontext(&frame->uc, regs);
+ err |= copy_to_user (&frame->uc.uc_sigmask, set, sizeof(*set));
+
+ /* Set up to return from userspace. */
+ err |= __put_user(frame->retcode, &frame->pretcode);
+ /* moveq #,d0; notb d0; trap #0 */
+ err |= __put_user(0x70004600 + ((__NR_rt_sigreturn ^ 0xff) << 16),
+ (long *)(frame->retcode + 0));
+ err |= __put_user(0x4e40, (short *)(frame->retcode + 4));
+
+ if (err)
+ goto give_sigsegv;
+
+ push_cache ((unsigned long) &frame->retcode);
+
+ /* Set up registers for signal handler */
+ wrusp ((unsigned long) frame);
+ regs->pc = (unsigned long) ka->sa.sa_handler;
+
+adjust_stack:
+ /* Prepare to skip over the extra stuff in the exception frame. */
+ if (regs->stkadj) {
+ struct pt_regs *tregs =
+ (struct pt_regs *)((ulong)regs + regs->stkadj);
+#if DEBUG
+ printk(KERN_DEBUG "Performing stackadjust=%04x\n", regs->stkadj);
+#endif
+ /* This must be copied with decreasing addresses to
+ handle overlaps. */
+ tregs->vector = 0;
+ tregs->format = 0;
+ tregs->pc = regs->pc;
+ tregs->sr = regs->sr;
+ }
+ return;
+
+give_sigsegv:
+ force_sigsegv(sig, current);
+ goto adjust_stack;
+}
+
+static inline void
+handle_restart(struct pt_regs *regs, struct k_sigaction *ka, int has_handler)
+{
+ switch (regs->d0) {
+ case -ERESTARTNOHAND:
+ if (!has_handler)
+ goto do_restart;
+ regs->d0 = -EINTR;
+ break;
+
+ case -ERESTARTSYS:
+ if (has_handler && !(ka->sa.sa_flags & SA_RESTART)) {
+ regs->d0 = -EINTR;
+ break;
+ }
+ /* fallthrough */
+ case -ERESTARTNOINTR:
+ do_restart:
+ regs->d0 = regs->orig_d0;
+ regs->pc -= 2;
+ break;
+ }
+}
+
+/*
+ * OK, we're invoking a handler
+ */
+static void
+handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info,
+ sigset_t *oldset, struct pt_regs *regs)
+{
+ /* are we from a system call? */
+ if (regs->orig_d0 >= 0)
+ /* If so, check system call restarting.. */
+ handle_restart(regs, ka, 1);
+
+ /* 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_ONESHOT)
+ ka->sa.sa_handler = SIG_DFL;
+
+ 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);
+ }
+}
+
+/*
+ * 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.
+ */
+asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs)
+{
+ 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 (!oldset)
+ oldset = &current->blocked;
+
+ signr = get_signal_to_deliver(&info, &ka, regs, NULL);
+ if (signr > 0) {
+ /* Whee! Actually deliver the signal. */
+ handle_signal(signr, &ka, &info, oldset, regs);
+ return 1;
+ }
+
+ /* Did we come from a system call? */
+ if (regs->orig_d0 >= 0) {
+ /* Restart the system call - no handlers present */
+ if (regs->d0 == -ERESTARTNOHAND
+ || regs->d0 == -ERESTARTSYS
+ || regs->d0 == -ERESTARTNOINTR) {
+ regs->d0 = regs->orig_d0;
+ regs->pc -= 2;
+ } else if (regs->d0 == -ERESTART_RESTARTBLOCK) {
+ regs->d0 = __NR_restart_syscall;
+ regs->pc -= 2;
+ }
+ }
+ return 0;
+}
diff --git a/arch/m68knommu/kernel/sys_m68k.c b/arch/m68knommu/kernel/sys_m68k.c
new file mode 100644
index 000000000000..d87e1e0a1336
--- /dev/null
+++ b/arch/m68knommu/kernel/sys_m68k.c
@@ -0,0 +1,208 @@
+/*
+ * linux/arch/m68knommu/kernel/sys_m68k.c
+ *
+ * This file contains various random system calls that
+ * have a non-standard calling sequence on the Linux/m68k
+ * platform.
+ */
+
+#include <linux/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/syscalls.h>
+#include <linux/mman.h>
+#include <linux/file.h>
+#include <linux/utsname.h>
+
+#include <asm/setup.h>
+#include <asm/uaccess.h>
+#include <asm/cachectl.h>
+#include <asm/traps.h>
+#include <asm/ipc.h>
+#include <asm/cacheflush.h>
+
+/*
+ * sys_pipe() is the normal C calling standard for creating
+ * a pipe. It's not the way unix traditionally does this, though.
+ */
+asmlinkage int 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;
+}
+
+/* common code for old and new mmaps */
+static inline long do_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;
+ }
+
+ 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;
+}
+
+asmlinkage long sys_mmap2(unsigned long addr, unsigned long len,
+ unsigned long prot, unsigned long flags,
+ unsigned long fd, unsigned long pgoff)
+{
+ return do_mmap2(addr, len, prot, flags, fd, pgoff);
+}
+
+/*
+ * Perform the select(nd, in, out, ex, tv) and mmap() system
+ * calls. Linux/m68k cloned Linux/i386, which didn't use to be able to
+ * handle more than 4 system call parameters, so these system calls
+ * used a memory block for parameter passing..
+ */
+
+struct mmap_arg_struct {
+ unsigned long addr;
+ unsigned long len;
+ unsigned long prot;
+ unsigned long flags;
+ unsigned long fd;
+ unsigned long offset;
+};
+
+asmlinkage int old_mmap(struct mmap_arg_struct *arg)
+{
+ struct mmap_arg_struct a;
+ int error = -EFAULT;
+
+ if (copy_from_user(&a, arg, sizeof(a)))
+ goto out;
+
+ error = -EINVAL;
+ if (a.offset & ~PAGE_MASK)
+ goto out;
+
+ a.flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
+
+ error = do_mmap2(a.addr, a.len, a.prot, a.flags, a.fd, a.offset >> PAGE_SHIFT);
+out:
+ return error;
+}
+
+struct sel_arg_struct {
+ unsigned long n;
+ fd_set *inp, *outp, *exp;
+ struct timeval *tvp;
+};
+
+asmlinkage int old_select(struct sel_arg_struct *arg)
+{
+ struct sel_arg_struct a;
+
+ if (copy_from_user(&a, arg, sizeof(a)))
+ return -EFAULT;
+ /* sys_select() does the appropriate kernel locking */
+ return sys_select(a.n, a.inp, a.outp, a.exp, a.tvp);
+}
+
+/*
+ * sys_ipc() is the de-multiplexer for the SysV IPC calls..
+ *
+ * This is really horribly ugly.
+ */
+asmlinkage int sys_ipc (uint call, int first, int second,
+ int third, void *ptr, long fifth)
+{
+ int version;
+
+ version = call >> 16; /* hack for backward compatibility */
+ call &= 0xffff;
+
+ if (call <= SEMCTL)
+ switch (call) {
+ case SEMOP:
+ return sys_semop (first, (struct sembuf *)ptr, second);
+ case SEMGET:
+ return sys_semget (first, second, third);
+ case SEMCTL: {
+ union semun fourth;
+ if (!ptr)
+ return -EINVAL;
+ if (get_user(fourth.__pad, (void **) ptr))
+ return -EFAULT;
+ return sys_semctl (first, second, third, fourth);
+ }
+ default:
+ return -EINVAL;
+ }
+ if (call <= MSGCTL)
+ switch (call) {
+ case MSGSND:
+ return sys_msgsnd (first, (struct msgbuf *) 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 *)ptr,
+ sizeof (tmp)))
+ return -EFAULT;
+ return sys_msgrcv (first, tmp.msgp, second,
+ tmp.msgtyp, third);
+ }
+ default:
+ return sys_msgrcv (first,
+ (struct msgbuf *) ptr,
+ second, fifth, third);
+ }
+ case MSGGET:
+ return sys_msgget ((key_t) first, second);
+ case MSGCTL:
+ return sys_msgctl (first, second,
+ (struct msqid_ds *) ptr);
+ default:
+ return -EINVAL;
+ }
+
+ return -EINVAL;
+}
+
+/* sys_cacheflush -- flush (part of) the processor cache. */
+asmlinkage int
+sys_cacheflush (unsigned long addr, int scope, int cache, unsigned long len)
+{
+ flush_cache_all();
+ return(0);
+}
+
+asmlinkage int sys_getpagesize(void)
+{
+ return PAGE_SIZE;
+}
+
diff --git a/arch/m68knommu/kernel/syscalltable.S b/arch/m68knommu/kernel/syscalltable.S
new file mode 100644
index 000000000000..897deaa06b01
--- /dev/null
+++ b/arch/m68knommu/kernel/syscalltable.S
@@ -0,0 +1,308 @@
+/*
+ * linux/arch/m68knommu/kernel/syscalltable.S
+ *
+ * Copyright (C) 2002, Greg Ungerer (gerg@snapgear.com)
+ *
+ * Based on older entry.S files, the following copyrights apply:
+ *
+ * Copyright (C) 1998 D. Jeff Dionne <jeff@lineo.ca>,
+ * Kenneth Albanowski <kjahds@kjahds.com>,
+ * Copyright (C) 2000 Lineo Inc. (www.lineo.com)
+ * Copyright (C) 1991, 1992 Linus Torvalds
+ */
+
+#include <linux/config.h>
+#include <linux/sys.h>
+#include <linux/linkage.h>
+#include <asm/unistd.h>
+
+.text
+ALIGN
+ENTRY(sys_call_table)
+ .long sys_ni_syscall /* 0 - old "setup()" system call*/
+ .long sys_exit
+ .long sys_fork
+ .long sys_read
+ .long sys_write
+ .long sys_open /* 5 */
+ .long sys_close
+ .long sys_waitpid
+ .long sys_creat
+ .long sys_link
+ .long sys_unlink /* 10 */
+ .long sys_execve
+ .long sys_chdir
+ .long sys_time
+ .long sys_mknod
+ .long sys_chmod /* 15 */
+ .long sys_chown16
+ .long sys_ni_syscall /* old break syscall holder */
+ .long sys_stat
+ .long sys_lseek
+ .long sys_getpid /* 20 */
+ .long sys_mount
+ .long sys_oldumount
+ .long sys_setuid16
+ .long sys_getuid16
+ .long sys_stime /* 25 */
+ .long sys_ptrace
+ .long sys_alarm
+ .long sys_fstat
+ .long sys_pause
+ .long sys_utime /* 30 */
+ .long sys_ni_syscall /* old stty syscall holder */
+ .long sys_ni_syscall /* old gtty syscall holder */
+ .long sys_access
+ .long sys_nice
+ .long sys_ni_syscall /* 35 */ /* old ftime syscall holder */
+ .long sys_sync
+ .long sys_kill
+ .long sys_rename
+ .long sys_mkdir
+ .long sys_rmdir /* 40 */
+ .long sys_dup
+ .long sys_pipe
+ .long sys_times
+ .long sys_ni_syscall /* old prof syscall holder */
+ .long sys_brk /* 45 */
+ .long sys_setgid16
+ .long sys_getgid16
+ .long sys_signal
+ .long sys_geteuid16
+ .long sys_getegid16 /* 50 */
+ .long sys_acct
+ .long sys_umount /* recycled never used phys() */
+ .long sys_ni_syscall /* old lock syscall holder */
+ .long sys_ioctl
+ .long sys_fcntl /* 55 */
+ .long sys_ni_syscall /* old mpx syscall holder */
+ .long sys_setpgid
+ .long sys_ni_syscall /* old ulimit syscall holder */
+ .long sys_ni_syscall
+ .long sys_umask /* 60 */
+ .long sys_chroot
+ .long sys_ustat
+ .long sys_dup2
+ .long sys_getppid
+ .long sys_getpgrp /* 65 */
+ .long sys_setsid
+ .long sys_sigaction
+ .long sys_sgetmask
+ .long sys_ssetmask
+ .long sys_setreuid16 /* 70 */
+ .long sys_setregid16
+ .long sys_sigsuspend
+ .long sys_sigpending
+ .long sys_sethostname
+ .long sys_setrlimit /* 75 */
+ .long sys_old_getrlimit
+ .long sys_getrusage
+ .long sys_gettimeofday
+ .long sys_settimeofday
+ .long sys_getgroups16 /* 80 */
+ .long sys_setgroups16
+ .long old_select
+ .long sys_symlink
+ .long sys_lstat
+ .long sys_readlink /* 85 */
+ .long sys_uselib
+ .long sys_ni_syscall /* sys_swapon */
+ .long sys_reboot
+ .long old_readdir
+ .long old_mmap /* 90 */
+ .long sys_munmap
+ .long sys_truncate
+ .long sys_ftruncate
+ .long sys_fchmod
+ .long sys_fchown16 /* 95 */
+ .long sys_getpriority
+ .long sys_setpriority
+ .long sys_ni_syscall /* old profil syscall holder */
+ .long sys_statfs
+ .long sys_fstatfs /* 100 */
+ .long sys_ni_syscall /* ioperm for i386 */
+ .long sys_socketcall
+ .long sys_syslog
+ .long sys_setitimer
+ .long sys_getitimer /* 105 */
+ .long sys_newstat
+ .long sys_newlstat
+ .long sys_newfstat
+ .long sys_ni_syscall
+ .long sys_ni_syscall /* 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_ni_syscall /* 115 */ /* sys_swapoff */
+ .long sys_sysinfo
+ .long sys_ipc
+ .long sys_fsync
+ .long sys_sigreturn
+ .long sys_clone /* 120 */
+ .long sys_setdomainname
+ .long sys_newuname
+ .long sys_cacheflush /* modify_ldt for i386 */
+ .long sys_adjtimex
+ .long sys_ni_syscall /* 125 */ /* sys_mprotect */
+ .long sys_sigprocmask
+ .long sys_ni_syscall /* old "creat_module" */
+ .long sys_init_module
+ .long sys_delete_module
+ .long sys_ni_syscall /* 130: old "get_kernel_syms" */
+ .long sys_quotactl
+ .long sys_getpgid
+ .long sys_fchdir
+ .long sys_bdflush
+ .long sys_sysfs /* 135 */
+ .long sys_personality
+ .long sys_ni_syscall /* for afs_syscall */
+ .long sys_setfsuid16
+ .long sys_setfsgid16
+ .long sys_llseek /* 140 */
+ .long sys_getdents
+ .long sys_select
+ .long sys_flock
+ .long sys_ni_syscall /* sys_msync */
+ .long sys_readv /* 145 */
+ .long sys_writev
+ .long sys_getsid
+ .long sys_fdatasync
+ .long sys_sysctl
+ .long sys_ni_syscall /* 150 */ /* sys_mlock */
+ .long sys_ni_syscall /* sys_munlock */
+ .long sys_ni_syscall /* sys_mlockall */
+ .long sys_ni_syscall /* sys_munlockall */
+ .long sys_sched_setparam
+ .long sys_sched_getparam /* 155 */
+ .long sys_sched_setscheduler
+ .long sys_sched_getscheduler
+ .long sys_sched_yield
+ .long sys_sched_get_priority_max
+ .long sys_sched_get_priority_min /* 160 */
+ .long sys_sched_rr_get_interval
+ .long sys_nanosleep
+ .long sys_ni_syscall /* sys_mremap */
+ .long sys_setresuid16
+ .long sys_getresuid16 /* 165 */
+ .long sys_getpagesize /* sys_getpagesize */
+ .long sys_ni_syscall /* old "query_module" */
+ .long sys_poll
+ .long sys_ni_syscall /* sys_nfsservctl */
+ .long sys_setresgid16 /* 170 */
+ .long sys_getresgid16
+ .long sys_prctl
+ .long sys_rt_sigreturn
+ .long sys_rt_sigaction
+ .long sys_rt_sigprocmask /* 175 */
+ .long sys_rt_sigpending
+ .long sys_rt_sigtimedwait
+ .long sys_rt_sigqueueinfo
+ .long sys_rt_sigsuspend
+ .long sys_pread64 /* 180 */
+ .long sys_pwrite64
+ .long sys_lchown16
+ .long sys_getcwd
+ .long sys_capget
+ .long sys_capset /* 185 */
+ .long sys_sigaltstack
+ .long sys_sendfile
+ .long sys_ni_syscall /* streams1 */
+ .long sys_ni_syscall /* streams2 */
+ .long sys_vfork /* 190 */
+ .long sys_getrlimit
+ .long sys_mmap2
+ .long sys_truncate64
+ .long sys_ftruncate64
+ .long sys_stat64 /* 195 */
+ .long sys_lstat64
+ .long sys_fstat64
+ .long sys_chown
+ .long sys_getuid
+ .long sys_getgid /* 200 */
+ .long sys_geteuid
+ .long sys_getegid
+ .long sys_setreuid
+ .long sys_setregid
+ .long sys_getgroups /* 205 */
+ .long sys_setgroups
+ .long sys_fchown
+ .long sys_setresuid
+ .long sys_getresuid
+ .long sys_setresgid /* 210 */
+ .long sys_getresgid
+ .long sys_lchown
+ .long sys_setuid
+ .long sys_setgid
+ .long sys_setfsuid /* 215 */
+ .long sys_setfsgid
+ .long sys_pivot_root
+ .long sys_ni_syscall
+ .long sys_ni_syscall
+ .long sys_getdents64 /* 220 */
+ .long sys_gettid
+ .long sys_tkill
+ .long sys_setxattr
+ .long sys_lsetxattr
+ .long sys_fsetxattr /* 225 */
+ .long sys_getxattr
+ .long sys_lgetxattr
+ .long sys_fgetxattr
+ .long sys_listxattr
+ .long sys_llistxattr /* 230 */
+ .long sys_flistxattr
+ .long sys_removexattr
+ .long sys_lremovexattr
+ .long sys_fremovexattr
+ .long sys_futex /* 235 */
+ .long sys_sendfile64
+ .long sys_ni_syscall /* sys_mincore */
+ .long sys_ni_syscall /* sys_madvise */
+ .long sys_fcntl64
+ .long sys_readahead /* 240 */
+ .long sys_io_setup
+ .long sys_io_destroy
+ .long sys_io_getevents
+ .long sys_io_submit
+ .long sys_io_cancel /* 245 */
+ .long sys_fadvise64
+ .long sys_exit_group
+ .long sys_lookup_dcookie
+ .long sys_epoll_create
+ .long sys_epoll_ctl /* 250 */
+ .long sys_epoll_wait
+ .long sys_ni_syscall /* sys_remap_file_pages */
+ .long sys_set_tid_address
+ .long sys_timer_create
+ .long sys_timer_settime /* 255 */
+ .long sys_timer_gettime
+ .long sys_timer_getoverrun
+ .long sys_timer_delete
+ .long sys_clock_settime
+ .long sys_clock_gettime /* 260 */
+ .long sys_clock_getres
+ .long sys_clock_nanosleep
+ .long sys_statfs64
+ .long sys_fstatfs64
+ .long sys_tgkill /* 265 */
+ .long sys_utimes
+ .long sys_fadvise64_64
+ .long sys_mbind
+ .long sys_get_mempolicy
+ .long sys_set_mempolicy /* 270 */
+ .long sys_mq_open
+ .long sys_mq_unlink
+ .long sys_mq_timedsend
+ .long sys_mq_timedreceive
+ .long sys_mq_notify /* 275 */
+ .long sys_mq_getsetattr
+ .long sys_waitid
+ .long sys_ni_syscall /* sys_setaltroot */
+ .long sys_ni_syscall /* sys_add_key */
+ .long sys_ni_syscall /* 280 */ /* sys_request_key */
+ .long sys_ni_syscall /* sys_keyctl */
+
+ .rept NR_syscalls-(.-sys_call_table)/4
+ .long sys_ni_syscall
+ .endr
+
diff --git a/arch/m68knommu/kernel/time.c b/arch/m68knommu/kernel/time.c
new file mode 100644
index 000000000000..5c3ca671627c
--- /dev/null
+++ b/arch/m68knommu/kernel/time.c
@@ -0,0 +1,198 @@
+/*
+ * linux/arch/m68knommu/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>
+#include <linux/errno.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/param.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/profile.h>
+#include <linux/time.h>
+#include <linux/timex.h>
+
+#include <asm/machdep.h>
+#include <asm/io.h>
+
+#define TICK_SIZE (tick_nsec / 1000)
+
+u64 jiffies_64 = INITIAL_JIFFIES;
+
+EXPORT_SYMBOL(jiffies_64);
+
+extern unsigned long wall_jiffies;
+
+
+static inline int set_rtc_mmss(unsigned long nowtime)
+{
+ if (mach_set_clock_mmss)
+ return mach_set_clock_mmss (nowtime);
+ return -1;
+}
+
+/*
+ * timer_interrupt() needs to keep up the real-time clock,
+ * as well as call the "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;
+
+ /* may need to kick the hardware timer */
+ if (mach_tick)
+ mach_tick();
+
+ write_seqlock(&xtime_lock);
+
+ do_timer(regs);
+#ifndef CONFIG_SMP
+ update_process_times(user_mode(regs));
+#endif
+ if (current->pid)
+ 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
+ /* use power LED as a heartbeat instead -- much more useful
+ for debugging -- based on the version for PReP by Cort */
+ /* acts like an actual heart beat -- ie thump-thump-pause... */
+ if (mach_heartbeat) {
+ static unsigned cnt = 0, period = 0, dist = 0;
+
+ if (cnt == 0 || cnt == dist)
+ mach_heartbeat( 1 );
+ else if (cnt == 7 || cnt == dist+7)
+ mach_heartbeat( 0 );
+
+ if (++cnt > period) {
+ cnt = 0;
+ /* The hyperbolic function below modifies the heartbeat period
+ * length in dependency of the current (5min) load. It goes
+ * through the points f(0)=126, f(1)=86, f(5)=51,
+ * f(inf)->30. */
+ period = ((672<<FSHIFT)/(5*avenrun[0]+(7<<FSHIFT))) + 30;
+ dist = period / 4;
+ }
+ }
+#endif /* CONFIG_HEARTBEAT */
+
+ write_sequnlock(&xtime_lock);
+ return(IRQ_HANDLED);
+}
+
+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);
+
+ 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;
+ wall_to_monotonic.tv_sec = -xtime.tv_sec;
+
+ mach_sched_init(timer_interrupt);
+}
+
+/*
+ * This version of gettimeofday has near microsecond resolution.
+ */
+void do_gettimeofday(struct timeval *tv)
+{
+ unsigned long flags;
+ unsigned long lost, seq;
+ unsigned long usec, sec;
+
+ do {
+ seq = read_seqbegin_irqsave(&xtime_lock, flags);
+ usec = mach_gettimeoffset ? mach_gettimeoffset() : 0;
+ lost = jiffies - wall_jiffies;
+ if (lost)
+ usec += lost * (1000000 / HZ);
+ sec = xtime.tv_sec;
+ usec += (xtime.tv_nsec / 1000);
+ } while (read_seqretry_irqrestore(&xtime_lock, seq, flags));
+
+ while (usec >= 1000000) {
+ usec -= 1000000;
+ sec++;
+ }
+
+ tv->tv_sec = sec;
+ tv->tv_usec = usec;
+}
+
+EXPORT_SYMBOL(do_gettimeofday);
+
+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 the xtime.tv_usec
+ * correctly. However, the value in this location is
+ * is value at the last tick.
+ * Discover what correction gettimeofday
+ * would have done, and then undo it!
+ */
+ if (mach_gettimeoffset)
+ nsec -= (mach_gettimeoffset() * 1000);
+
+ 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 (unsigned long long)jiffies * (1000000000 / HZ);
+}
+
+EXPORT_SYMBOL(do_settimeofday);
diff --git a/arch/m68knommu/kernel/traps.c b/arch/m68knommu/kernel/traps.c
new file mode 100644
index 000000000000..ad7dc6347f19
--- /dev/null
+++ b/arch/m68knommu/kernel/traps.c
@@ -0,0 +1,320 @@
+/*
+ * linux/arch/m68knommu/kernel/traps.c
+ *
+ * Copyright (C) 1993, 1994 by Hamish Macdonald
+ *
+ * 68040 fixes by Michael Rausch
+ * 68040 fixes by Martin Apel
+ * 68060 fixes by Roman Hodek
+ * 68060 fixes by Jesper Skov
+ *
+ * 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.
+ */
+
+/*
+ * Sets up all exception vectors
+ */
+#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/a.out.h>
+#include <linux/user.h>
+#include <linux/string.h>
+#include <linux/linkage.h>
+#include <linux/init.h>
+#include <linux/ptrace.h>
+
+#include <asm/setup.h>
+#include <asm/fpu.h>
+#include <asm/system.h>
+#include <asm/uaccess.h>
+#include <asm/traps.h>
+#include <asm/pgtable.h>
+#include <asm/machdep.h>
+#include <asm/siginfo.h>
+
+static char *vec_names[] = {
+ "RESET SP", "RESET PC", "BUS ERROR", "ADDRESS ERROR",
+ "ILLEGAL INSTRUCTION", "ZERO DIVIDE", "CHK", "TRAPcc",
+ "PRIVILEGE VIOLATION", "TRACE", "LINE 1010", "LINE 1111",
+ "UNASSIGNED RESERVED 12", "COPROCESSOR PROTOCOL VIOLATION",
+ "FORMAT ERROR", "UNINITIALIZED INTERRUPT",
+ "UNASSIGNED RESERVED 16", "UNASSIGNED RESERVED 17",
+ "UNASSIGNED RESERVED 18", "UNASSIGNED RESERVED 19",
+ "UNASSIGNED RESERVED 20", "UNASSIGNED RESERVED 21",
+ "UNASSIGNED RESERVED 22", "UNASSIGNED RESERVED 23",
+ "SPURIOUS INTERRUPT", "LEVEL 1 INT", "LEVEL 2 INT", "LEVEL 3 INT",
+ "LEVEL 4 INT", "LEVEL 5 INT", "LEVEL 6 INT", "LEVEL 7 INT",
+ "SYSCALL", "TRAP #1", "TRAP #2", "TRAP #3",
+ "TRAP #4", "TRAP #5", "TRAP #6", "TRAP #7",
+ "TRAP #8", "TRAP #9", "TRAP #10", "TRAP #11",
+ "TRAP #12", "TRAP #13", "TRAP #14", "TRAP #15",
+ "FPCP BSUN", "FPCP INEXACT", "FPCP DIV BY 0", "FPCP UNDERFLOW",
+ "FPCP OPERAND ERROR", "FPCP OVERFLOW", "FPCP SNAN",
+ "FPCP UNSUPPORTED OPERATION",
+ "MMU CONFIGURATION ERROR"
+};
+
+void __init trap_init(void)
+{
+ if (mach_trap_init)
+ mach_trap_init();
+}
+
+void die_if_kernel(char *str, struct pt_regs *fp, int nr)
+{
+ if (!(fp->sr & PS_S))
+ return;
+
+ console_verbose();
+ printk(KERN_EMERG "%s: %08x\n",str,nr);
+ printk(KERN_EMERG "PC: [<%08lx>]\nSR: %04x SP: %p a2: %08lx\n",
+ fp->pc, fp->sr, fp, fp->a2);
+ printk(KERN_EMERG "d0: %08lx d1: %08lx d2: %08lx d3: %08lx\n",
+ fp->d0, fp->d1, fp->d2, fp->d3);
+ printk(KERN_EMERG "d4: %08lx d5: %08lx a0: %08lx a1: %08lx\n",
+ fp->d4, fp->d5, fp->a0, fp->a1);
+
+ printk(KERN_EMERG "Process %s (pid: %d, stackpage=%08lx)\n",
+ current->comm, current->pid, PAGE_SIZE+(unsigned long)current);
+ show_stack(NULL, (unsigned long *)fp);
+ do_exit(SIGSEGV);
+}
+
+asmlinkage void buserr_c(struct frame *fp)
+{
+ /* Only set esp0 if coming from user mode */
+ if (user_mode(&fp->ptregs))
+ current->thread.esp0 = (unsigned long) fp;
+
+#if DEBUG
+ printk (KERN_DEBUG "*** Bus Error *** Format is %x\n", fp->ptregs.format);
+#endif
+
+ die_if_kernel("bad frame format",&fp->ptregs,0);
+#if DEBUG
+ printk(KERN_DEBUG "Unknown SIGSEGV - 4\n");
+#endif
+ force_sig(SIGSEGV, current);
+}
+
+
+int kstack_depth_to_print = 48;
+
+void show_stack(struct task_struct *task, unsigned long *esp)
+{
+ unsigned long *stack, *endstack, addr;
+ extern char _start, _etext;
+ int i;
+
+ if (esp == NULL)
+ esp = (unsigned long *) &esp;
+
+ stack = esp;
+ addr = (unsigned long) esp;
+ endstack = (unsigned long *) PAGE_ALIGN(addr);
+
+ printk(KERN_EMERG "Stack from %08lx:", (unsigned long)stack);
+ for (i = 0; i < kstack_depth_to_print; i++) {
+ if (stack + 1 > endstack)
+ break;
+ if (i % 8 == 0)
+ printk(KERN_EMERG "\n ");
+ printk(KERN_EMERG " %08lx", *stack++);
+ }
+
+ printk(KERN_EMERG "\nCall Trace:");
+ i = 0;
+ while (stack + 1 <= endstack) {
+ addr = *stack++;
+ /*
+ * If the address is either in the text segment of the
+ * kernel, or in the region which contains vmalloc'ed
+ * memory, it *may* be the address of a calling
+ * routine; if so, print it so that someone tracing
+ * down the cause of the crash will be able to figure
+ * out the call path that was taken.
+ */
+ if (((addr >= (unsigned long) &_start) &&
+ (addr <= (unsigned long) &_etext))) {
+ if (i % 4 == 0)
+ printk(KERN_EMERG "\n ");
+ printk(KERN_EMERG " [<%08lx>]", addr);
+ i++;
+ }
+ }
+ printk(KERN_EMERG "\n");
+}
+
+void bad_super_trap(struct frame *fp)
+{
+ console_verbose();
+ if (fp->ptregs.vector < 4*sizeof(vec_names)/sizeof(vec_names[0]))
+ printk (KERN_WARNING "*** %s *** FORMAT=%X\n",
+ vec_names[(fp->ptregs.vector) >> 2],
+ fp->ptregs.format);
+ else
+ printk (KERN_WARNING "*** Exception %d *** FORMAT=%X\n",
+ (fp->ptregs.vector) >> 2,
+ fp->ptregs.format);
+ printk (KERN_WARNING "Current process id is %d\n", current->pid);
+ die_if_kernel("BAD KERNEL TRAP", &fp->ptregs, 0);
+}
+
+asmlinkage void trap_c(struct frame *fp)
+{
+ int sig;
+ siginfo_t info;
+
+ if (fp->ptregs.sr & PS_S) {
+ if ((fp->ptregs.vector >> 2) == VEC_TRACE) {
+ /* traced a trapping instruction */
+ current->ptrace |= PT_DTRACE;
+ } else
+ bad_super_trap(fp);
+ return;
+ }
+
+ /* send the appropriate signal to the user program */
+ switch ((fp->ptregs.vector) >> 2) {
+ case VEC_ADDRERR:
+ info.si_code = BUS_ADRALN;
+ sig = SIGBUS;
+ break;
+ case VEC_ILLEGAL:
+ case VEC_LINE10:
+ case VEC_LINE11:
+ info.si_code = ILL_ILLOPC;
+ sig = SIGILL;
+ break;
+ case VEC_PRIV:
+ info.si_code = ILL_PRVOPC;
+ sig = SIGILL;
+ break;
+ case VEC_COPROC:
+ info.si_code = ILL_COPROC;
+ sig = SIGILL;
+ break;
+ case VEC_TRAP1: /* gdbserver breakpoint */
+ fp->ptregs.pc -= 2;
+ info.si_code = TRAP_TRACE;
+ sig = SIGTRAP;
+ break;
+ case VEC_TRAP2:
+ case VEC_TRAP3:
+ case VEC_TRAP4:
+ case VEC_TRAP5:
+ case VEC_TRAP6:
+ case VEC_TRAP7:
+ case VEC_TRAP8:
+ case VEC_TRAP9:
+ case VEC_TRAP10:
+ case VEC_TRAP11:
+ case VEC_TRAP12:
+ case VEC_TRAP13:
+ case VEC_TRAP14:
+ info.si_code = ILL_ILLTRP;
+ sig = SIGILL;
+ break;
+ case VEC_FPBRUC:
+ case VEC_FPOE:
+ case VEC_FPNAN:
+ info.si_code = FPE_FLTINV;
+ sig = SIGFPE;
+ break;
+ case VEC_FPIR:
+ info.si_code = FPE_FLTRES;
+ sig = SIGFPE;
+ break;
+ case VEC_FPDIVZ:
+ info.si_code = FPE_FLTDIV;
+ sig = SIGFPE;
+ break;
+ case VEC_FPUNDER:
+ info.si_code = FPE_FLTUND;
+ sig = SIGFPE;
+ break;
+ case VEC_FPOVER:
+ info.si_code = FPE_FLTOVF;
+ sig = SIGFPE;
+ break;
+ case VEC_ZERODIV:
+ info.si_code = FPE_INTDIV;
+ sig = SIGFPE;
+ break;
+ case VEC_CHK:
+ case VEC_TRAP:
+ info.si_code = FPE_INTOVF;
+ sig = SIGFPE;
+ break;
+ case VEC_TRACE: /* ptrace single step */
+ info.si_code = TRAP_TRACE;
+ sig = SIGTRAP;
+ break;
+ case VEC_TRAP15: /* breakpoint */
+ info.si_code = TRAP_BRKPT;
+ sig = SIGTRAP;
+ break;
+ default:
+ info.si_code = ILL_ILLOPC;
+ sig = SIGILL;
+ break;
+ }
+ info.si_signo = sig;
+ info.si_errno = 0;
+ switch (fp->ptregs.format) {
+ default:
+ info.si_addr = (void *) fp->ptregs.pc;
+ break;
+ case 2:
+ info.si_addr = (void *) fp->un.fmt2.iaddr;
+ break;
+ case 7:
+ info.si_addr = (void *) fp->un.fmt7.effaddr;
+ break;
+ case 9:
+ info.si_addr = (void *) fp->un.fmt9.iaddr;
+ break;
+ case 10:
+ info.si_addr = (void *) fp->un.fmta.daddr;
+ break;
+ case 11:
+ info.si_addr = (void *) fp->un.fmtb.daddr;
+ break;
+ }
+ force_sig_info (sig, &info, current);
+}
+
+asmlinkage void set_esp0(unsigned long ssp)
+{
+ current->thread.esp0 = ssp;
+}
+
+
+/*
+ * The architecture-independent backtrace generator
+ */
+void dump_stack(void)
+{
+ unsigned long stack;
+
+ show_stack(current, &stack);
+}
+
+#ifdef CONFIG_M68KFPU_EMU
+asmlinkage void fpemu_signal(int signal, int code, void *addr)
+{
+ siginfo_t info;
+
+ info.si_signo = signal;
+ info.si_errno = 0;
+ info.si_code = code;
+ info.si_addr = addr;
+ force_sig_info(signal, &info, current);
+}
+#endif
diff --git a/arch/m68knommu/kernel/vmlinux.lds.S b/arch/m68knommu/kernel/vmlinux.lds.S
new file mode 100644
index 000000000000..31cb12892da5
--- /dev/null
+++ b/arch/m68knommu/kernel/vmlinux.lds.S
@@ -0,0 +1,348 @@
+/*
+ * vmlinux.lds.S -- master linker script for m68knommu arch
+ *
+ * (C) Copyright 2002-2004, Greg Ungerer <gerg@snapgear.com>
+ *
+ * This ends up looking compilcated, because of the number of
+ * address variations for ram and rom/flash layouts. The real
+ * work of the linker script is all at the end, and reasonably
+ * strait forward.
+ */
+
+#include <linux/config.h>
+#include <asm-generic/vmlinux.lds.h>
+
+/*
+ * Original Palm pilot (same for Xcopilot).
+ * There is really only a rom target for this.
+ */
+#ifdef CONFIG_PILOT3
+#define ROMVEC_START 0x10c00000
+#define ROMVEC_LENGTH 0x10400
+#define ROM_START 0x10c10400
+#define ROM_LENGTH 0xfec00
+#define ROM_END 0x10d00000
+#define RAMVEC_START 0x00000000
+#define RAMVEC_LENGTH 0x400
+#define RAM_START 0x10000400
+#define RAM_LENGTH 0xffc00
+#define RAM_END 0x10100000
+#define _ramend _ram_end_notused
+#define DATA_ADDR RAM_START
+#endif
+
+/*
+ * Same setup on both the uCsimm and uCdimm.
+ */
+#if defined(CONFIG_UCSIMM) || defined(CONFIG_UCDIMM)
+#ifdef CONFIG_RAMKERNEL
+#define ROMVEC_START 0x10c10000
+#define ROMVEC_LENGTH 0x400
+#define ROM_START 0x10c10400
+#define ROM_LENGTH 0x1efc00
+#define ROM_END 0x10e00000
+#define RAMVEC_START 0x00000000
+#define RAMVEC_LENGTH 0x400
+#define RAM_START 0x00020400
+#define RAM_LENGTH 0x7dfc00
+#define RAM_END 0x00800000
+#endif
+#ifdef CONFIG_ROMKERNEL
+#define ROMVEC_START 0x10c10000
+#define ROMVEC_LENGTH 0x400
+#define ROM_START 0x10c10400
+#define ROM_LENGTH 0x1efc00
+#define ROM_END 0x10e00000
+#define RAMVEC_START 0x00000000
+#define RAMVEC_LENGTH 0x400
+#define RAM_START 0x00020000
+#define RAM_LENGTH 0x600000
+#define RAM_END 0x00800000
+#endif
+#ifdef CONFIG_HIMEMKERNEL
+#define ROMVEC_START 0x00600000
+#define ROMVEC_LENGTH 0x400
+#define ROM_START 0x00600400
+#define ROM_LENGTH 0x1efc00
+#define ROM_END 0x007f0000
+#define RAMVEC_START 0x00000000
+#define RAMVEC_LENGTH 0x400
+#define RAM_START 0x00020000
+#define RAM_LENGTH 0x5e0000
+#define RAM_END 0x00600000
+#endif
+#endif
+
+#ifdef CONFIG_DRAGEN2
+#define RAM_START 0x10000
+#define RAM_LENGTH 0x7f0000
+#endif
+
+#ifdef CONFIG_UCQUICC
+#define ROMVEC_START 0x00000000
+#define ROMVEC_LENGTH 0x404
+#define ROM_START 0x00000404
+#define ROM_LENGTH 0x1ff6fc
+#define ROM_END 0x00200000
+#define RAMVEC_START 0x00200000
+#define RAMVEC_LENGTH 0x404
+#define RAM_START 0x00200404
+#define RAM_LENGTH 0x1ff6fc
+#define RAM_END 0x00400000
+#endif
+
+/*
+ * The standard Arnewsh 5206 board only has 1MiB of ram. Not normally
+ * enough to be useful. Assume the user has fitted something larger,
+ * at least 4MiB in size. No point in not letting the kernel completely
+ * link, it will be obvious if it is too big when they go to load it.
+ */
+#if defined(CONFIG_ARN5206)
+#define RAM_START 0x10000
+#define RAM_LENGTH 0x3f0000
+#endif
+
+/*
+ * The Motorola 5206eLITE board only has 1MiB of static RAM.
+ */
+#if defined(CONFIG_ELITE)
+#define RAM_START 0x30020000
+#define RAM_END 0xe0000
+#endif
+
+/*
+ * All the Motorola eval boards have the same basic arrangement.
+ * The end of RAM will vary depending on how much ram is fitted,
+ * but this isn't important here, we assume at least 4MiB.
+ */
+#if defined(CONFIG_M5206eC3) || defined(CONFIG_M5249C3) || \
+ defined(CONFIG_M5272C3) || defined(CONFIG_M5307C3) || \
+ defined(CONFIG_ARN5307) || defined(CONFIG_M5407C3) || \
+ defined(CONFIG_M5271EVB) || defined(CONFIG_M5275EVB)
+#define RAM_START 0x20000
+#define RAM_LENGTH 0x3e0000
+#endif
+
+/*
+ * The senTec COBRA5272 board has nearly the same memory layout as
+ * the M5272C3. We assume 16MiB ram.
+ */
+#if defined(CONFIG_COBRA5272)
+#define RAM_START 0x20000
+#define RAM_LENGTH 0xfe0000
+#endif
+
+#if defined(CONFIG_M5282EVB)
+#define RAM_START 0x10000
+#define RAM_LENGTH 0x3f0000
+#endif
+
+/*
+ * The senTec COBRA5282 board has the same memory layout as the M5282EVB.
+ */
+#if defined(CONFIG_COBRA5282)
+#define RAM_START 0x10000
+#define RAM_LENGTH 0x3f0000
+#endif
+
+/*
+ * These flash boot boards use all of ram for operation. Again the
+ * actual memory size is not important here, assume at least 4MiB.
+ * They currently have no support for running in flash.
+ */
+#if defined(CONFIG_NETtel) || defined(CONFIG_eLIA) || \
+ defined(CONFIG_DISKtel) || defined(CONFIG_SECUREEDGEMP3) || \
+ defined(CONFIG_HW_FEITH)
+#define RAM_START 0x400
+#define RAM_LENGTH 0x3ffc00
+#endif
+
+/*
+ * Sneha Boards mimimun memmory
+ * The end of RAM will vary depending on how much ram is fitted,
+ * but this isn't important here, we assume at least 4MiB.
+ */
+#if defined(CONFIG_CPU16B)
+#define RAM_START 0x20000
+#define RAM_LENGTH 0x3e0000
+#endif
+
+
+#if defined(CONFIG_RAMKERNEL)
+#define TEXT ram
+#define DATA ram
+#define INIT ram
+#define BSS ram
+#endif
+#if defined(CONFIG_ROMKERNEL) || defined(CONFIG_HIMEMKERNEL)
+#define TEXT rom
+#define DATA ram
+#define INIT ram
+#define BSS ram
+#endif
+
+#ifndef DATA_ADDR
+#define DATA_ADDR
+#endif
+
+
+OUTPUT_ARCH(m68k)
+ENTRY(_start)
+
+MEMORY {
+#ifdef RAMVEC_START
+ ramvec : ORIGIN = RAMVEC_START, LENGTH = RAMVEC_LENGTH
+#endif
+ ram : ORIGIN = RAM_START, LENGTH = RAM_LENGTH
+#ifdef RAM_END
+ eram : ORIGIN = RAM_END, LENGTH = 0
+#endif
+#ifdef ROM_START
+ romvec : ORIGIN = ROMVEC_START, LENGTH = ROMVEC_LENGTH
+ rom : ORIGIN = ROM_START, LENGTH = ROM_LENGTH
+ erom : ORIGIN = ROM_END, LENGTH = 0
+#endif
+}
+
+jiffies = jiffies_64 + 4;
+
+SECTIONS {
+
+#ifdef ROMVEC_START
+ . = ROMVEC_START ;
+ .romvec : {
+ __rom_start = . ;
+ _romvec = .;
+ *(.data.initvect)
+ } > romvec
+#endif
+
+ .text : {
+ _stext = . ;
+ *(.text)
+ SCHED_TEXT
+ *(.text.lock)
+
+ . = ALIGN(16); /* Exception table */
+ __start___ex_table = .;
+ *(__ex_table)
+ __stop___ex_table = .;
+
+ *(.rodata) *(.rodata.*)
+ *(__vermagic) /* Kernel version magic */
+ *(.rodata1)
+ *(.rodata.str1.1)
+
+ /* Kernel symbol table: Normal symbols */
+ . = ALIGN(4);
+ __start___ksymtab = .;
+ *(__ksymtab)
+ __stop___ksymtab = .;
+
+ /* Kernel symbol table: GPL-only symbols */
+ __start___ksymtab_gpl = .;
+ *(__ksymtab_gpl)
+ __stop___ksymtab_gpl = .;
+
+ /* Kernel symbol table: Normal symbols */
+ __start___kcrctab = .;
+ *(__kcrctab)
+ __stop___kcrctab = .;
+
+ /* Kernel symbol table: GPL-only symbols */
+ __start___kcrctab_gpl = .;
+ *(__kcrctab_gpl)
+ __stop___kcrctab_gpl = .;
+
+ /* Kernel symbol table: strings */
+ *(__ksymtab_strings)
+
+ /* Built-in module parameters */
+ __start___param = .;
+ *(__param)
+ __stop___param = .;
+
+ . = ALIGN(4) ;
+ _etext = . ;
+ } > TEXT
+
+#ifdef ROM_END
+ . = ROM_END ;
+ .erom : {
+ __rom_end = . ;
+ } > erom
+#endif
+#ifdef RAMVEC_START
+ . = RAMVEC_START ;
+ .ramvec : {
+ __ramvec = .;
+ } > ramvec
+#endif
+
+ .data DATA_ADDR : {
+ . = ALIGN(4);
+ _sdata = . ;
+ *(.data)
+ . = ALIGN(8192) ;
+ *(.data.init_task)
+ _edata = . ;
+ } > DATA
+
+ .init : {
+ . = ALIGN(4096);
+ __init_begin = .;
+ _sinittext = .;
+ *(.init.text)
+ _einittext = .;
+ *(.init.data)
+ . = ALIGN(16);
+ __setup_start = .;
+ *(.init.setup)
+ __setup_end = .;
+ __initcall_start = .;
+ *(.initcall1.init)
+ *(.initcall2.init)
+ *(.initcall3.init)
+ *(.initcall4.init)
+ *(.initcall5.init)
+ *(.initcall6.init)
+ *(.initcall7.init)
+ __initcall_end = .;
+ __con_initcall_start = .;
+ *(.con_initcall.init)
+ __con_initcall_end = .;
+ __security_initcall_start = .;
+ *(.security_initcall.init)
+ __security_initcall_end = .;
+ . = ALIGN(4);
+ __initramfs_start = .;
+ *(.init.ramfs)
+ __initramfs_end = .;
+ . = ALIGN(4096);
+ __init_end = .;
+ } > INIT
+
+ /DISCARD/ : {
+ *(.exit.text)
+ *(.exit.data)
+ *(.exitcall.exit)
+ }
+
+ .bss : {
+ . = ALIGN(4);
+ _sbss = . ;
+ *(.bss)
+ *(COMMON)
+ . = ALIGN(4) ;
+ _ebss = . ;
+ } > BSS
+
+#ifdef RAM_END
+ . = RAM_END ;
+ .eram : {
+ __ramend = . ;
+ _ramend = . ;
+ } > eram
+#endif
+}
+