Linux-2.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!
This commit is contained in:
Linus Torvalds
2005-04-16 15:20:36 -07:00
commit 1da177e4c3
17291 changed files with 6718755 additions and 0 deletions

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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);
}
/*****************************************************************************/

View File

@@ -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));
}

View File

@@ -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

View File

@@ -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) };

View File

@@ -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 */

View File

@@ -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)
{
}

View File

@@ -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;
}

View File

@@ -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;
}
}

View File

@@ -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);
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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);

View File

@@ -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

View File

@@ -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
}