aboutsummaryrefslogtreecommitdiffstats
path: root/arch/m68knommu/kernel
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
commit1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch)
tree0bba044c4ce775e45a88a51686b5d9f90697ea9d /arch/m68knommu/kernel
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history, even though we have it. We can create a separate "historical" git archive of that later if we want to, and in the meantime it's about 3.2GB when imported into git - space that would just make the early git days unnecessarily complicated, when we don't have a lot of good infrastructure for it. Let it rip!
Diffstat (limited to 'arch/m68knommu/kernel')
-rw-r--r--arch/m68knommu/kernel/Makefile11
-rw-r--r--arch/m68knommu/kernel/asm-offsets.c101
-rw-r--r--arch/m68knommu/kernel/comempci.c989
-rw-r--r--arch/m68knommu/kernel/dma.c36
-rw-r--r--arch/m68knommu/kernel/entry.S143
-rw-r--r--arch/m68knommu/kernel/init_task.c43
-rw-r--r--arch/m68knommu/kernel/m68k_ksyms.c104
-rw-r--r--arch/m68knommu/kernel/module.c128
-rw-r--r--arch/m68knommu/kernel/process.c442
-rw-r--r--arch/m68knommu/kernel/ptrace.c383
-rw-r--r--arch/m68knommu/kernel/semaphore.c134
-rw-r--r--arch/m68knommu/kernel/setup.c347
-rw-r--r--arch/m68knommu/kernel/signal.c788
-rw-r--r--arch/m68knommu/kernel/sys_m68k.c208
-rw-r--r--arch/m68knommu/kernel/syscalltable.S308
-rw-r--r--arch/m68knommu/kernel/time.c198
-rw-r--r--arch/m68knommu/kernel/traps.c320
-rw-r--r--arch/m68knommu/kernel/vmlinux.lds.S348
18 files changed, 5031 insertions, 0 deletions
diff --git a/arch/m68knommu/kernel/Makefile b/arch/m68knommu/kernel/Makefile
new file mode 100644
index 000000000000..1c6cd1ab571e
--- /dev/null
+++ b/arch/m68knommu/kernel/Makefile
@@ -0,0 +1,11 @@
1#
2# Makefile for arch/m68knommu/kernel.
3#
4
5extra-y := vmlinux.lds
6
7obj-y += dma.o entry.o init_task.o m68k_ksyms.o process.o ptrace.o semaphore.o \
8 setup.o signal.o syscalltable.o sys_m68k.o time.o traps.o
9
10obj-$(CONFIG_MODULES) += module.o
11obj-$(CONFIG_COMEMPCI) += comempci.o
diff --git a/arch/m68knommu/kernel/asm-offsets.c b/arch/m68knommu/kernel/asm-offsets.c
new file mode 100644
index 000000000000..cd3ffe12653e
--- /dev/null
+++ b/arch/m68knommu/kernel/asm-offsets.c
@@ -0,0 +1,101 @@
1/*
2 * This program is used to generate definitions needed by
3 * assembly language modules.
4 *
5 * We use the technique used in the OSF Mach kernel code:
6 * generate asm statements containing #defines,
7 * compile this file to assembler, and then extract the
8 * #defines from the assembly-language output.
9 */
10
11#include <linux/stddef.h>
12#include <linux/sched.h>
13#include <linux/kernel_stat.h>
14#include <linux/ptrace.h>
15#include <linux/hardirq.h>
16#include <asm/bootinfo.h>
17#include <asm/irq.h>
18#include <asm/thread_info.h>
19
20#define DEFINE(sym, val) \
21 asm volatile("\n->" #sym " %0 " #val : : "i" (val))
22
23#define BLANK() asm volatile("\n->" : : )
24
25int main(void)
26{
27 /* offsets into the task struct */
28 DEFINE(TASK_STATE, offsetof(struct task_struct, state));
29 DEFINE(TASK_FLAGS, offsetof(struct task_struct, flags));
30 DEFINE(TASK_PTRACE, offsetof(struct task_struct, ptrace));
31 DEFINE(TASK_BLOCKED, offsetof(struct task_struct, blocked));
32 DEFINE(TASK_THREAD, offsetof(struct task_struct, thread));
33 DEFINE(TASK_THREAD_INFO, offsetof(struct task_struct, thread_info));
34 DEFINE(TASK_MM, offsetof(struct task_struct, mm));
35 DEFINE(TASK_ACTIVE_MM, offsetof(struct task_struct, active_mm));
36
37 /* offsets into the kernel_stat struct */
38 DEFINE(STAT_IRQ, offsetof(struct kernel_stat, irqs));
39
40 /* offsets into the irq_cpustat_t struct */
41 DEFINE(CPUSTAT_SOFTIRQ_PENDING, offsetof(irq_cpustat_t, __softirq_pending));
42
43 /* offsets into the thread struct */
44 DEFINE(THREAD_KSP, offsetof(struct thread_struct, ksp));
45 DEFINE(THREAD_USP, offsetof(struct thread_struct, usp));
46 DEFINE(THREAD_SR, offsetof(struct thread_struct, sr));
47 DEFINE(THREAD_FS, offsetof(struct thread_struct, fs));
48 DEFINE(THREAD_CRP, offsetof(struct thread_struct, crp));
49 DEFINE(THREAD_ESP0, offsetof(struct thread_struct, esp0));
50 DEFINE(THREAD_FPREG, offsetof(struct thread_struct, fp));
51 DEFINE(THREAD_FPCNTL, offsetof(struct thread_struct, fpcntl));
52 DEFINE(THREAD_FPSTATE, offsetof(struct thread_struct, fpstate));
53
54 /* offsets into the pt_regs */
55 DEFINE(PT_D0, offsetof(struct pt_regs, d0));
56 DEFINE(PT_ORIG_D0, offsetof(struct pt_regs, orig_d0));
57 DEFINE(PT_D1, offsetof(struct pt_regs, d1));
58 DEFINE(PT_D2, offsetof(struct pt_regs, d2));
59 DEFINE(PT_D3, offsetof(struct pt_regs, d3));
60 DEFINE(PT_D4, offsetof(struct pt_regs, d4));
61 DEFINE(PT_D5, offsetof(struct pt_regs, d5));
62 DEFINE(PT_A0, offsetof(struct pt_regs, a0));
63 DEFINE(PT_A1, offsetof(struct pt_regs, a1));
64 DEFINE(PT_A2, offsetof(struct pt_regs, a2));
65 DEFINE(PT_PC, offsetof(struct pt_regs, pc));
66 DEFINE(PT_SR, offsetof(struct pt_regs, sr));
67
68#ifdef CONFIG_COLDFIRE
69 /* bitfields are a bit difficult */
70 DEFINE(PT_FORMATVEC, offsetof(struct pt_regs, sr) - 2);
71#else
72 /* bitfields are a bit difficult */
73 DEFINE(PT_VECTOR, offsetof(struct pt_regs, pc) + 4);
74 /* offsets into the irq_handler struct */
75 DEFINE(IRQ_HANDLER, offsetof(struct irq_node, handler));
76 DEFINE(IRQ_DEVID, offsetof(struct irq_node, dev_id));
77 DEFINE(IRQ_NEXT, offsetof(struct irq_node, next));
78#endif
79
80 /* offsets into the kernel_stat struct */
81 DEFINE(STAT_IRQ, offsetof(struct kernel_stat, irqs));
82
83 /* signal defines */
84 DEFINE(SIGSEGV, SIGSEGV);
85 DEFINE(SEGV_MAPERR, SEGV_MAPERR);
86 DEFINE(SIGTRAP, SIGTRAP);
87 DEFINE(TRAP_TRACE, TRAP_TRACE);
88
89 DEFINE(PT_PTRACED, PT_PTRACED);
90 DEFINE(PT_DTRACE, PT_DTRACE);
91
92 DEFINE(THREAD_SIZE, THREAD_SIZE);
93
94 /* Offsets in thread_info structure */
95 DEFINE(TI_TASK, offsetof(struct thread_info, task));
96 DEFINE(TI_EXECDOMAIN, offsetof(struct thread_info, exec_domain));
97 DEFINE(TI_FLAGS, offsetof(struct thread_info, flags));
98 DEFINE(TI_CPU, offsetof(struct thread_info, cpu));
99
100 return 0;
101}
diff --git a/arch/m68knommu/kernel/comempci.c b/arch/m68knommu/kernel/comempci.c
new file mode 100644
index 000000000000..8670938f1107
--- /dev/null
+++ b/arch/m68knommu/kernel/comempci.c
@@ -0,0 +1,989 @@
1/*****************************************************************************/
2
3/*
4 * comemlite.c -- PCI access code for embedded CO-MEM Lite PCI controller.
5 *
6 * (C) Copyright 1999-2003, Greg Ungerer (gerg@snapgear.com).
7 * (C) Copyright 2000, Lineo (www.lineo.com)
8 */
9
10/*****************************************************************************/
11
12#include <linux/config.h>
13#include <linux/kernel.h>
14#include <linux/types.h>
15#include <linux/pci.h>
16#include <linux/ptrace.h>
17#include <linux/spinlock.h>
18#include <linux/interrupt.h>
19#include <linux/sched.h>
20#include <asm/coldfire.h>
21#include <asm/mcfsim.h>
22#include <asm/irq.h>
23#include <asm/anchor.h>
24
25#ifdef CONFIG_eLIA
26#include <asm/elia.h>
27#endif
28
29/*****************************************************************************/
30
31/*
32 * Debug configuration defines. DEBUGRES sets debugging output for
33 * the resource allocation phase. DEBUGPCI traces on pcibios_ function
34 * calls, and DEBUGIO traces all accesses to devices on the PCI bus.
35 */
36/*#define DEBUGRES 1*/
37/*#define DEBUGPCI 1*/
38/*#define DEBUGIO 1*/
39
40/*****************************************************************************/
41
42/*
43 * PCI markers for bus present and active slots.
44 */
45int pci_bus_is_present = 0;
46unsigned long pci_slotmask = 0;
47
48/*
49 * We may or may not need to swap the bytes of PCI bus tranfers.
50 * The endianess is re-roder automatically by the CO-MEM, but it
51 * will get the wrong byte order for a pure data stream.
52 */
53#define pci_byteswap 0
54
55
56/*
57 * Resource tracking. The CO-MEM part creates a virtual address
58 * space that all the PCI devices live in - it is not in any way
59 * directly mapped into the ColdFire address space. So we can
60 * really assign any resources we like to devices, as long as
61 * they do not clash with other PCI devices.
62 */
63unsigned int pci_iobase = PCIBIOS_MIN_IO; /* Arbitrary start address */
64unsigned int pci_membase = PCIBIOS_MIN_MEM; /* Arbitrary start address */
65
66#define PCI_MINIO 0x100 /* 256 byte minimum I/O */
67#define PCI_MINMEM 0x00010000 /* 64k minimum chunk */
68
69/*
70 * The CO-MEM's shared memory segment is visible inside the PCI
71 * memory address space. We need to keep track of the address that
72 * this is mapped at, to setup the bus masters pointers.
73 */
74unsigned int pci_shmemaddr;
75
76/*****************************************************************************/
77
78void pci_interrupt(int irq, void *id, struct pt_regs *fp);
79
80/*****************************************************************************/
81
82/*
83 * Some platforms have custom ways of reseting the PCI bus.
84 */
85
86void pci_resetbus(void)
87{
88#ifdef CONFIG_eLIA
89 int i;
90
91#ifdef DEBUGPCI
92 printk(KERN_DEBUG "pci_resetbus()\n");
93#endif
94
95 *((volatile unsigned short *) (MCF_MBAR+MCFSIM_PADDR)) |= eLIA_PCIRESET;
96 for (i = 0; (i < 1000); i++) {
97 *((volatile unsigned short *) (MCF_MBAR + MCFSIM_PADAT)) =
98 (ppdata | eLIA_PCIRESET);
99 }
100
101
102 *((volatile unsigned short *) (MCF_MBAR + MCFSIM_PADAT)) = ppdata;
103#endif
104}
105
106/*****************************************************************************/
107
108int pcibios_assign_resource_slot(int slot)
109{
110 volatile unsigned long *rp;
111 volatile unsigned char *ip;
112 unsigned int idsel, addr, val, align, i;
113 int bar;
114
115#ifdef DEBUGPCI
116 printk(KERN_INFO "pcibios_assign_resource_slot(slot=%x)\n", slot);
117#endif
118
119 rp = (volatile unsigned long *) COMEM_BASE;
120 idsel = COMEM_DA_ADDR(0x1 << (slot + 16));
121
122 /* Try to assign resource to each BAR */
123 for (bar = 0; (bar < 6); bar++) {
124 addr = COMEM_PCIBUS + PCI_BASE_ADDRESS_0 + (bar * 4);
125 rp[LREG(COMEM_DAHBASE)] = COMEM_DA_CFGRD | idsel;
126 val = rp[LREG(addr)];
127#ifdef DEBUGRES
128 printk(KERN_DEBUG "-----------------------------------"
129 "-------------------------------------\n");
130 printk(KERN_DEBUG "BAR[%d]: read=%08x ", bar, val);
131#endif
132
133 rp[LREG(COMEM_DAHBASE)] = COMEM_DA_CFGWR | idsel;
134 rp[LREG(addr)] = 0xffffffff;
135
136 rp[LREG(COMEM_DAHBASE)] = COMEM_DA_CFGRD | idsel;
137 val = rp[LREG(addr)];
138#ifdef DEBUGRES
139 printk(KERN_DEBUG "write=%08x ", val);
140#endif
141 if (val == 0) {
142#ifdef DEBUGRES
143 printk(KERN_DEBUG "\n");
144#endif
145 continue;
146 }
147
148 /* Determine space required by BAR */
149 /* FIXME: this should go backwords from 0x80000000... */
150 for (i = 0; (i < 32); i++) {
151 if ((0x1 << i) & (val & 0xfffffffc))
152 break;
153 }
154
155#ifdef DEBUGRES
156 printk(KERN_DEBUG "size=%08x(%d)\n", (0x1 << i), i);
157#endif
158 i = 0x1 << i;
159
160 /* Assign a resource */
161 if (val & PCI_BASE_ADDRESS_SPACE_IO) {
162 if (i < PCI_MINIO)
163 i = PCI_MINIO;
164#ifdef DEBUGRES
165 printk(KERN_DEBUG "BAR[%d]: IO size=%08x iobase=%08x\n",
166 bar, i, pci_iobase);
167#endif
168 if (i > 0xffff) {
169 /* Invalid size?? */
170 val = 0 | PCI_BASE_ADDRESS_SPACE_IO;
171#ifdef DEBUGRES
172 printk(KERN_DEBUG "BAR[%d]: too big for IO??\n", bar);
173#endif
174 } else {
175 /* Check for un-alignment */
176 if ((align = pci_iobase % i))
177 pci_iobase += (i - align);
178 val = pci_iobase | PCI_BASE_ADDRESS_SPACE_IO;
179 pci_iobase += i;
180 }
181 } else {
182 if (i < PCI_MINMEM)
183 i = PCI_MINMEM;
184#ifdef DEBUGRES
185 printk(KERN_DEBUG "BAR[%d]: MEMORY size=%08x membase=%08x\n",
186 bar, i, pci_membase);
187#endif
188 /* Check for un-alignment */
189 if ((align = pci_membase % i))
190 pci_membase += (i - align);
191 val = pci_membase | PCI_BASE_ADDRESS_SPACE_MEMORY;
192 pci_membase += i;
193 }
194
195 /* Write resource back into BAR register */
196 rp[LREG(COMEM_DAHBASE)] = COMEM_DA_CFGWR | idsel;
197 rp[LREG(addr)] = val;
198#ifdef DEBUGRES
199 printk(KERN_DEBUG "BAR[%d]: assigned bar=%08x\n", bar, val);
200#endif
201 }
202
203#ifdef DEBUGRES
204 printk(KERN_DEBUG "-----------------------------------"
205 "-------------------------------------\n");
206#endif
207
208 /* Assign IRQ if one is wanted... */
209 ip = (volatile unsigned char *) (COMEM_BASE + COMEM_PCIBUS);
210 rp[LREG(COMEM_DAHBASE)] = COMEM_DA_CFGRD | idsel;
211
212 addr = (PCI_INTERRUPT_PIN & 0xfc) + (~PCI_INTERRUPT_PIN & 0x03);
213 if (ip[addr]) {
214 rp[LREG(COMEM_DAHBASE)] = COMEM_DA_CFGWR | idsel;
215 addr = (PCI_INTERRUPT_LINE & 0xfc)+(~PCI_INTERRUPT_LINE & 0x03);
216 ip[addr] = 25;
217#ifdef DEBUGRES
218 printk(KERN_DEBUG "IRQ LINE=25\n");
219#endif
220 }
221
222 return(0);
223}
224
225/*****************************************************************************/
226
227int pcibios_enable_slot(int slot)
228{
229 volatile unsigned long *rp;
230 volatile unsigned short *wp;
231 unsigned int idsel, addr;
232 unsigned short cmd;
233
234#ifdef DEBUGPCI
235 printk(KERN_DEBUG "pcibios_enbale_slot(slot=%x)\n", slot);
236#endif
237
238 rp = (volatile unsigned long *) COMEM_BASE;
239 wp = (volatile unsigned short *) COMEM_BASE;
240 idsel = COMEM_DA_ADDR(0x1 << (slot + 16));
241
242 /* Get current command settings */
243 addr = COMEM_PCIBUS + PCI_COMMAND;
244 addr = (addr & ~0x3) + (~addr & 0x02);
245 rp[LREG(COMEM_DAHBASE)] = COMEM_DA_CFGRD | idsel;
246 cmd = wp[WREG(addr)];
247 /*val = ((val & 0xff) << 8) | ((val >> 8) & 0xff);*/
248
249 /* Enable I/O and memory accesses to this device */
250 rp[LREG(COMEM_DAHBASE)] = COMEM_DA_CFGWR | idsel;
251 cmd |= PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER;
252 wp[WREG(addr)] = cmd;
253
254 return(0);
255}
256
257/*****************************************************************************/
258
259void pcibios_assign_resources(void)
260{
261 volatile unsigned long *rp;
262 unsigned long sel, id;
263 int slot;
264
265 rp = (volatile unsigned long *) COMEM_BASE;
266
267 /*
268 * Do a quick scan of the PCI bus and see what is here.
269 */
270 for (slot = COMEM_MINDEV; (slot <= COMEM_MAXDEV); slot++) {
271 sel = COMEM_DA_CFGRD | COMEM_DA_ADDR(0x1 << (slot + 16));
272 rp[LREG(COMEM_DAHBASE)] = sel;
273 rp[LREG(COMEM_PCIBUS)] = 0; /* Clear bus */
274 id = rp[LREG(COMEM_PCIBUS)];
275 if ((id != 0) && ((id & 0xffff0000) != (sel & 0xffff0000))) {
276 printk(KERN_INFO "PCI: slot=%d id=%08x\n", slot, (int) id);
277 pci_slotmask |= 0x1 << slot;
278 pcibios_assign_resource_slot(slot);
279 pcibios_enable_slot(slot);
280 }
281 }
282}
283
284/*****************************************************************************/
285
286int pcibios_init(void)
287{
288 volatile unsigned long *rp;
289 unsigned long sel, id;
290 int slot;
291
292#ifdef DEBUGPCI
293 printk(KERN_DEBUG "pcibios_init()\n");
294#endif
295
296 pci_resetbus();
297
298 /*
299 * Do some sort of basic check to see if the CO-MEM part
300 * is present... This works ok, but I think we really need
301 * something better...
302 */
303 rp = (volatile unsigned long *) COMEM_BASE;
304 if ((rp[LREG(COMEM_LBUSCFG)] & 0xff) != 0x50) {
305 printk(KERN_INFO "PCI: no PCI bus present\n");
306 return(0);
307 }
308
309#ifdef COMEM_BRIDGEDEV
310 /*
311 * Setup the PCI bridge device first. It needs resources too,
312 * so that bus masters can get to its shared memory.
313 */
314 slot = COMEM_BRIDGEDEV;
315 sel = COMEM_DA_CFGRD | COMEM_DA_ADDR(0x1 << (slot + 16));
316 rp[LREG(COMEM_DAHBASE)] = sel;
317 rp[LREG(COMEM_PCIBUS)] = 0; /* Clear bus */
318 id = rp[LREG(COMEM_PCIBUS)];
319 if ((id == 0) || ((id & 0xffff0000) == (sel & 0xffff0000))) {
320 printk(KERN_INFO "PCI: no PCI bus bridge present\n");
321 return(0);
322 }
323
324 printk(KERN_INFO "PCI: bridge device at slot=%d id=%08x\n", slot, (int) id);
325 pci_slotmask |= 0x1 << slot;
326 pci_shmemaddr = pci_membase;
327 pcibios_assign_resource_slot(slot);
328 pcibios_enable_slot(slot);
329#endif
330
331 pci_bus_is_present = 1;
332
333 /* Get PCI irq for local vectoring */
334 if (request_irq(COMEM_IRQ, pci_interrupt, 0, "PCI bridge", NULL)) {
335 printk(KERN_WARNING "PCI: failed to acquire interrupt %d\n", COMEM_IRQ);
336 } else {
337 mcf_autovector(COMEM_IRQ);
338 }
339
340 pcibios_assign_resources();
341
342 return(0);
343}
344
345/*****************************************************************************/
346
347char *pcibios_setup(char *option)
348{
349 /* Nothing for us to handle. */
350 return(option);
351}
352/*****************************************************************************/
353
354void pcibios_fixup_bus(struct pci_bus *b)
355{
356}
357
358/*****************************************************************************/
359
360void pcibios_align_resource(void *data, struct resource *res, unsigned long size, unsigned long align)
361{
362}
363
364/*****************************************************************************/
365
366int pcibios_enable_device(struct pci_dev *dev, int mask)
367{
368 int slot;
369
370 slot = PCI_SLOT(dev->devfn);
371 if ((dev->bus == 0) && (pci_slotmask & (1 << slot)))
372 pcibios_enable_slot(slot);
373 return(0);
374}
375
376/*****************************************************************************/
377
378void pcibios_update_resource(struct pci_dev *dev, struct resource *root, struct resource *r, int resource)
379{
380 printk(KERN_WARNING "%s(%d): no support for changing PCI resources...\n",
381 __FILE__, __LINE__);
382}
383
384
385/*****************************************************************************/
386
387/*
388 * Local routines to interrcept the standard I/O and vector handling
389 * code. Don't include this 'till now - initialization code above needs
390 * access to the real code too.
391 */
392#include <asm/mcfpci.h>
393
394/*****************************************************************************/
395
396void pci_outb(unsigned char val, unsigned int addr)
397{
398 volatile unsigned long *rp;
399 volatile unsigned char *bp;
400
401#ifdef DEBUGIO
402 printk(KERN_DEBUG "pci_outb(val=%02x,addr=%x)\n", val, addr);
403#endif
404
405 rp = (volatile unsigned long *) COMEM_BASE;
406 bp = (volatile unsigned char *) COMEM_BASE;
407 rp[LREG(COMEM_DAHBASE)] = COMEM_DA_IOWR | COMEM_DA_ADDR(addr);
408 addr = (addr & ~0x3) + (~addr & 0x03);
409 bp[(COMEM_PCIBUS + COMEM_DA_OFFSET(addr))] = val;
410}
411
412/*****************************************************************************/
413
414void pci_outw(unsigned short val, unsigned int addr)
415{
416 volatile unsigned long *rp;
417 volatile unsigned short *sp;
418
419#ifdef DEBUGIO
420 printk(KERN_DEBUG "pci_outw(val=%04x,addr=%x)\n", val, addr);
421#endif
422
423 rp = (volatile unsigned long *) COMEM_BASE;
424 sp = (volatile unsigned short *) COMEM_BASE;
425 rp[LREG(COMEM_DAHBASE)] = COMEM_DA_IOWR | COMEM_DA_ADDR(addr);
426 addr = (addr & ~0x3) + (~addr & 0x02);
427 if (pci_byteswap)
428 val = ((val & 0xff) << 8) | ((val >> 8) & 0xff);
429 sp[WREG(COMEM_PCIBUS + COMEM_DA_OFFSET(addr))] = val;
430}
431
432/*****************************************************************************/
433
434void pci_outl(unsigned int val, unsigned int addr)
435{
436 volatile unsigned long *rp;
437 volatile unsigned int *lp;
438
439#ifdef DEBUGIO
440 printk(KERN_DEBUG "pci_outl(val=%08x,addr=%x)\n", val, addr);
441#endif
442
443 rp = (volatile unsigned long *) COMEM_BASE;
444 lp = (volatile unsigned int *) COMEM_BASE;
445 rp[LREG(COMEM_DAHBASE)] = COMEM_DA_IOWR | COMEM_DA_ADDR(addr);
446
447 if (pci_byteswap)
448 val = (val << 24) | ((val & 0x0000ff00) << 8) |
449 ((val & 0x00ff0000) >> 8) | (val >> 24);
450
451 lp[LREG(COMEM_PCIBUS + COMEM_DA_OFFSET(addr))] = val;
452}
453
454/*****************************************************************************/
455
456unsigned long pci_blmask[] = {
457 0x000000e0,
458 0x000000d0,
459 0x000000b0,
460 0x00000070
461};
462
463unsigned char pci_inb(unsigned int addr)
464{
465 volatile unsigned long *rp;
466 volatile unsigned char *bp;
467 unsigned long r;
468 unsigned char val;
469
470#ifdef DEBUGIO
471 printk(KERN_DEBUG "pci_inb(addr=%x)\n", addr);
472#endif
473
474 rp = (volatile unsigned long *) COMEM_BASE;
475 bp = (volatile unsigned char *) COMEM_BASE;
476
477 r = COMEM_DA_IORD | COMEM_DA_ADDR(addr) | pci_blmask[(addr & 0x3)];
478 rp[LREG(COMEM_DAHBASE)] = r;
479
480 addr = (addr & ~0x3) + (~addr & 0x3);
481 val = bp[(COMEM_PCIBUS + COMEM_DA_OFFSET(addr))];
482 return(val);
483}
484
485/*****************************************************************************/
486
487unsigned long pci_bwmask[] = {
488 0x000000c0,
489 0x000000c0,
490 0x00000030,
491 0x00000030
492};
493
494unsigned short pci_inw(unsigned int addr)
495{
496 volatile unsigned long *rp;
497 volatile unsigned short *sp;
498 unsigned long r;
499 unsigned short val;
500
501#ifdef DEBUGIO
502 printk(KERN_DEBUG "pci_inw(addr=%x)", addr);
503#endif
504
505 rp = (volatile unsigned long *) COMEM_BASE;
506 r = COMEM_DA_IORD | COMEM_DA_ADDR(addr) | pci_bwmask[(addr & 0x3)];
507 rp[LREG(COMEM_DAHBASE)] = r;
508
509 sp = (volatile unsigned short *) COMEM_BASE;
510 addr = (addr & ~0x3) + (~addr & 0x02);
511 val = sp[WREG(COMEM_PCIBUS + COMEM_DA_OFFSET(addr))];
512 if (pci_byteswap)
513 val = ((val & 0xff) << 8) | ((val >> 8) & 0xff);
514#ifdef DEBUGIO
515 printk(KERN_DEBUG "=%04x\n", val);
516#endif
517 return(val);
518}
519
520/*****************************************************************************/
521
522unsigned int pci_inl(unsigned int addr)
523{
524 volatile unsigned long *rp;
525 volatile unsigned int *lp;
526 unsigned int val;
527
528#ifdef DEBUGIO
529 printk(KERN_DEBUG "pci_inl(addr=%x)", addr);
530#endif
531
532 rp = (volatile unsigned long *) COMEM_BASE;
533 lp = (volatile unsigned int *) COMEM_BASE;
534 rp[LREG(COMEM_DAHBASE)] = COMEM_DA_IORD | COMEM_DA_ADDR(addr);
535 val = lp[LREG(COMEM_PCIBUS + COMEM_DA_OFFSET(addr))];
536
537 if (pci_byteswap)
538 val = (val << 24) | ((val & 0x0000ff00) << 8) |
539 ((val & 0x00ff0000) >> 8) | (val >> 24);
540
541#ifdef DEBUGIO
542 printk(KERN_DEBUG "=%08x\n", val);
543#endif
544 return(val);
545}
546
547/*****************************************************************************/
548
549void pci_outsb(void *addr, void *buf, int len)
550{
551 volatile unsigned long *rp;
552 volatile unsigned char *bp;
553 unsigned char *dp = (unsigned char *) buf;
554 unsigned int a = (unsigned int) addr;
555
556#ifdef DEBUGIO
557 printk(KERN_DEBUG "pci_outsb(addr=%x,buf=%x,len=%d)\n", (int)addr, (int)buf, len);
558#endif
559
560 rp = (volatile unsigned long *) COMEM_BASE;
561 rp[LREG(COMEM_DAHBASE)] = COMEM_DA_IOWR | COMEM_DA_ADDR(a);
562
563 a = (a & ~0x3) + (~a & 0x03);
564 bp = (volatile unsigned char *)
565 (COMEM_BASE + COMEM_PCIBUS + COMEM_DA_OFFSET(a));
566
567 while (len--)
568 *bp = *dp++;
569}
570
571/*****************************************************************************/
572
573void pci_outsw(void *addr, void *buf, int len)
574{
575 volatile unsigned long *rp;
576 volatile unsigned short *wp;
577 unsigned short w, *dp = (unsigned short *) buf;
578 unsigned int a = (unsigned int) addr;
579
580#ifdef DEBUGIO
581 printk(KERN_DEBUG "pci_outsw(addr=%x,buf=%x,len=%d)\n", (int)addr, (int)buf, len);
582#endif
583
584 rp = (volatile unsigned long *) COMEM_BASE;
585 rp[LREG(COMEM_DAHBASE)] = COMEM_DA_IOWR | COMEM_DA_ADDR(a);
586
587 a = (a & ~0x3) + (~a & 0x2);
588 wp = (volatile unsigned short *)
589 (COMEM_BASE + COMEM_PCIBUS + COMEM_DA_OFFSET(a));
590
591 while (len--) {
592 w = *dp++;
593 if (pci_byteswap)
594 w = ((w & 0xff) << 8) | ((w >> 8) & 0xff);
595 *wp = w;
596 }
597}
598
599/*****************************************************************************/
600
601void pci_outsl(void *addr, void *buf, int len)
602{
603 volatile unsigned long *rp;
604 volatile unsigned long *lp;
605 unsigned long l, *dp = (unsigned long *) buf;
606 unsigned int a = (unsigned int) addr;
607
608#ifdef DEBUGIO
609 printk(KERN_DEBUG "pci_outsl(addr=%x,buf=%x,len=%d)\n", (int)addr, (int)buf, len);
610#endif
611
612 rp = (volatile unsigned long *) COMEM_BASE;
613 rp[LREG(COMEM_DAHBASE)] = COMEM_DA_IOWR | COMEM_DA_ADDR(a);
614
615 lp = (volatile unsigned long *)
616 (COMEM_BASE + COMEM_PCIBUS + COMEM_DA_OFFSET(a));
617
618 while (len--) {
619 l = *dp++;
620 if (pci_byteswap)
621 l = (l << 24) | ((l & 0x0000ff00) << 8) |
622 ((l & 0x00ff0000) >> 8) | (l >> 24);
623 *lp = l;
624 }
625}
626
627/*****************************************************************************/
628
629void pci_insb(void *addr, void *buf, int len)
630{
631 volatile unsigned long *rp;
632 volatile unsigned char *bp;
633 unsigned char *dp = (unsigned char *) buf;
634 unsigned int a = (unsigned int) addr;
635
636#ifdef DEBUGIO
637 printk(KERN_DEBUG "pci_insb(addr=%x,buf=%x,len=%d)\n", (int)addr, (int)buf, len);
638#endif
639
640 rp = (volatile unsigned long *) COMEM_BASE;
641 rp[LREG(COMEM_DAHBASE)] = COMEM_DA_IORD | COMEM_DA_ADDR(a);
642
643 a = (a & ~0x3) + (~a & 0x03);
644 bp = (volatile unsigned char *)
645 (COMEM_BASE + COMEM_PCIBUS + COMEM_DA_OFFSET(a));
646
647 while (len--)
648 *dp++ = *bp;
649}
650
651/*****************************************************************************/
652
653void pci_insw(void *addr, void *buf, int len)
654{
655 volatile unsigned long *rp;
656 volatile unsigned short *wp;
657 unsigned short w, *dp = (unsigned short *) buf;
658 unsigned int a = (unsigned int) addr;
659
660#ifdef DEBUGIO
661 printk(KERN_DEBUG "pci_insw(addr=%x,buf=%x,len=%d)\n", (int)addr, (int)buf, len);
662#endif
663
664 rp = (volatile unsigned long *) COMEM_BASE;
665 rp[LREG(COMEM_DAHBASE)] = COMEM_DA_IORD | COMEM_DA_ADDR(a);
666
667 a = (a & ~0x3) + (~a & 0x2);
668 wp = (volatile unsigned short *)
669 (COMEM_BASE + COMEM_PCIBUS + COMEM_DA_OFFSET(a));
670
671 while (len--) {
672 w = *wp;
673 if (pci_byteswap)
674 w = ((w & 0xff) << 8) | ((w >> 8) & 0xff);
675 *dp++ = w;
676 }
677}
678
679/*****************************************************************************/
680
681void pci_insl(void *addr, void *buf, int len)
682{
683 volatile unsigned long *rp;
684 volatile unsigned long *lp;
685 unsigned long l, *dp = (unsigned long *) buf;
686 unsigned int a = (unsigned int) addr;
687
688#ifdef DEBUGIO
689 printk(KERN_DEBUG "pci_insl(addr=%x,buf=%x,len=%d)\n", (int)addr, (int)buf, len);
690#endif
691
692 rp = (volatile unsigned long *) COMEM_BASE;
693 rp[LREG(COMEM_DAHBASE)] = COMEM_DA_IORD | COMEM_DA_ADDR(a);
694
695 lp = (volatile unsigned long *)
696 (COMEM_BASE + COMEM_PCIBUS + COMEM_DA_OFFSET(a));
697
698 while (len--) {
699 l = *lp;
700 if (pci_byteswap)
701 l = (l << 24) | ((l & 0x0000ff00) << 8) |
702 ((l & 0x00ff0000) >> 8) | (l >> 24);
703 *dp++ = l;
704 }
705}
706
707/*****************************************************************************/
708
709struct pci_localirqlist {
710 void (*handler)(int, void *, struct pt_regs *);
711 const char *device;
712 void *dev_id;
713};
714
715struct pci_localirqlist pci_irqlist[COMEM_MAXPCI];
716
717/*****************************************************************************/
718
719int pci_request_irq(unsigned int irq,
720 void (*handler)(int, void *, struct pt_regs *),
721 unsigned long flags, const char *device, void *dev_id)
722{
723 int i;
724
725#ifdef DEBUGIO
726 printk(KERN_DEBUG "pci_request_irq(irq=%d,handler=%x,flags=%x,device=%s,"
727 "dev_id=%x)\n", irq, (int) handler, (int) flags, device,
728 (int) dev_id);
729#endif
730
731 /* Check if this interrupt handler is already lodged */
732 for (i = 0; (i < COMEM_MAXPCI); i++) {
733 if (pci_irqlist[i].handler == handler)
734 return(0);
735 }
736
737 /* Find a free spot to put this handler */
738 for (i = 0; (i < COMEM_MAXPCI); i++) {
739 if (pci_irqlist[i].handler == 0) {
740 pci_irqlist[i].handler = handler;
741 pci_irqlist[i].device = device;
742 pci_irqlist[i].dev_id = dev_id;
743 return(0);
744 }
745 }
746
747 /* Couldn't fit?? */
748 return(1);
749}
750
751/*****************************************************************************/
752
753void pci_free_irq(unsigned int irq, void *dev_id)
754{
755 int i;
756
757#ifdef DEBUGIO
758 printk(KERN_DEBUG "pci_free_irq(irq=%d,dev_id=%x)\n", irq, (int) dev_id);
759#endif
760
761 if (dev_id == (void *) NULL)
762 return;
763
764 /* Check if this interrupt handler is lodged */
765 for (i = 0; (i < COMEM_MAXPCI); i++) {
766 if (pci_irqlist[i].dev_id == dev_id) {
767 pci_irqlist[i].handler = NULL;
768 pci_irqlist[i].device = NULL;
769 pci_irqlist[i].dev_id = NULL;
770 break;
771 }
772 }
773}
774
775/*****************************************************************************/
776
777void pci_interrupt(int irq, void *id, struct pt_regs *fp)
778{
779 int i;
780
781#ifdef DEBUGIO
782 printk(KERN_DEBUG "pci_interrupt(irq=%d,id=%x,fp=%x)\n", irq, (int) id, (int) fp);
783#endif
784
785 for (i = 0; (i < COMEM_MAXPCI); i++) {
786 if (pci_irqlist[i].handler)
787 (*pci_irqlist[i].handler)(irq,pci_irqlist[i].dev_id,fp);
788 }
789}
790
791/*****************************************************************************/
792
793/*
794 * The shared memory region is broken up into contiguous 512 byte
795 * regions for easy allocation... This is not an optimal solution
796 * but it makes allocation and freeing regions really easy.
797 */
798
799#define PCI_MEMSLOTSIZE 512
800#define PCI_MEMSLOTS (COMEM_SHMEMSIZE / PCI_MEMSLOTSIZE)
801
802char pci_shmemmap[PCI_MEMSLOTS];
803
804
805void *pci_bmalloc(int size)
806{
807 int i, j, nrslots;
808
809#ifdef DEBUGIO
810 printk(KERN_DEBUG "pci_bmalloc(size=%d)\n", size);
811#endif
812
813 if (size <= 0)
814 return((void *) NULL);
815
816 nrslots = (size - 1) / PCI_MEMSLOTSIZE;
817
818 for (i = 0; (i < (PCI_MEMSLOTS-nrslots)); i++) {
819 if (pci_shmemmap[i] == 0) {
820 for (j = i+1; (j < (i+nrslots)); j++) {
821 if (pci_shmemmap[j])
822 goto restart;
823 }
824
825 for (j = i; (j <= i+nrslots); j++)
826 pci_shmemmap[j] = 1;
827 break;
828 }
829restart:
830 }
831
832 return((void *) (COMEM_BASE + COMEM_SHMEM + (i * PCI_MEMSLOTSIZE)));
833}
834
835/*****************************************************************************/
836
837void pci_bmfree(void *mp, int size)
838{
839 int i, j, nrslots;
840
841#ifdef DEBUGIO
842 printk(KERN_DEBUG "pci_bmfree(mp=%x,size=%d)\n", (int) mp, size);
843#endif
844
845 nrslots = size / PCI_MEMSLOTSIZE;
846 i = (((unsigned long) mp) - (COMEM_BASE + COMEM_SHMEM)) /
847 PCI_MEMSLOTSIZE;
848
849 for (j = i; (j < (i+nrslots)); j++)
850 pci_shmemmap[j] = 0;
851}
852
853/*****************************************************************************/
854
855unsigned long pci_virt_to_bus(volatile void *address)
856{
857 unsigned long l;
858
859#ifdef DEBUGIO
860 printk(KERN_DEBUG "pci_virt_to_bus(address=%x)", (int) address);
861#endif
862
863 l = ((unsigned long) address) - COMEM_BASE;
864#ifdef DEBUGIO
865 printk(KERN_DEBUG "=%x\n", (int) (l+pci_shmemaddr));
866#endif
867 return(l + pci_shmemaddr);
868}
869
870/*****************************************************************************/
871
872void *pci_bus_to_virt(unsigned long address)
873{
874 unsigned long l;
875
876#ifdef DEBUGIO
877 printk(KERN_DEBUG "pci_bus_to_virt(address=%x)", (int) address);
878#endif
879
880 l = address - pci_shmemaddr;
881#ifdef DEBUGIO
882 printk(KERN_DEBUG "=%x\n", (int) (address + COMEM_BASE));
883#endif
884 return((void *) (address + COMEM_BASE));
885}
886
887/*****************************************************************************/
888
889void pci_bmcpyto(void *dst, void *src, int len)
890{
891 unsigned long *dp, *sp, val;
892 unsigned char *dcp, *scp;
893 int i, j;
894
895#ifdef DEBUGIO
896 printk(KERN_DEBUG "pci_bmcpyto(dst=%x,src=%x,len=%d)\n", (int)dst, (int)src, len);
897#endif
898
899 dp = (unsigned long *) dst;
900 sp = (unsigned long *) src;
901 i = len >> 2;
902
903#if 0
904 printk(KERN_INFO "DATA:");
905 scp = (unsigned char *) sp;
906 for (i = 0; (i < len); i++) {
907 if ((i % 16) == 0) printk(KERN_INFO "\n%04x: ", i);
908 printk(KERN_INFO "%02x ", *scp++);
909 }
910 printk(KERN_INFO "\n");
911#endif
912
913 for (j = 0; (i >= 0); i--, j++) {
914 val = *sp++;
915 val = (val << 24) | ((val & 0x0000ff00) << 8) |
916 ((val & 0x00ff0000) >> 8) | (val >> 24);
917 *dp++ = val;
918 }
919
920 if (len & 0x3) {
921 dcp = (unsigned char *) dp;
922 scp = ((unsigned char *) sp) + 3;
923 for (i = 0; (i < (len & 0x3)); i++)
924 *dcp++ = *scp--;
925 }
926}
927
928/*****************************************************************************/
929
930void pci_bmcpyfrom(void *dst, void *src, int len)
931{
932 unsigned long *dp, *sp, val;
933 unsigned char *dcp, *scp;
934 int i;
935
936#ifdef DEBUGIO
937 printk(KERN_DEBUG "pci_bmcpyfrom(dst=%x,src=%x,len=%d)\n",(int)dst,(int)src,len);
938#endif
939
940 dp = (unsigned long *) dst;
941 sp = (unsigned long *) src;
942 i = len >> 2;
943
944 for (; (i >= 0); i--) {
945 val = *sp++;
946 val = (val << 24) | ((val & 0x0000ff00) << 8) |
947 ((val & 0x00ff0000) >> 8) | (val >> 24);
948 *dp++ = val;
949 }
950
951 if (len & 0x3) {
952 dcp = ((unsigned char *) dp) + 3;
953 scp = (unsigned char *) sp;
954 for (i = 0; (i < (len & 0x3)); i++)
955 *dcp++ = *scp--;
956 }
957
958#if 0
959 printk(KERN_INFO "DATA:");
960 dcp = (unsigned char *) dst;
961 for (i = 0; (i < len); i++) {
962 if ((i % 16) == 0) printk(KERN_INFO "\n%04x: ", i);
963 printk(KERN_INFO "%02x ", *dcp++);
964 }
965 printk(KERN_INFO "\n");
966#endif
967}
968
969/*****************************************************************************/
970
971void *pci_alloc_consistent(struct pci_dev *dev, size_t size, dma_addr_t *dma_addr)
972{
973 void *mp;
974 if ((mp = pci_bmalloc(size)) != NULL) {
975 dma_addr = mp - (COMEM_BASE + COMEM_SHMEM);
976 return(mp);
977 }
978 *dma_addr = (dma_addr_t) NULL;
979 return(NULL);
980}
981
982/*****************************************************************************/
983
984void pci_free_consistent(struct pci_dev *dev, size_t size, void *cpu_addr, dma_addr_t dma_addr)
985{
986 pci_bmfree(cpu_addr, size);
987}
988
989/*****************************************************************************/
diff --git a/arch/m68knommu/kernel/dma.c b/arch/m68knommu/kernel/dma.c
new file mode 100644
index 000000000000..14b19c4161f4
--- /dev/null
+++ b/arch/m68knommu/kernel/dma.c
@@ -0,0 +1,36 @@
1/*
2 * Dynamic DMA mapping support.
3 *
4 * We never have any address translations to worry about, so this
5 * is just alloc/free.
6 */
7
8#include <linux/types.h>
9#include <linux/mm.h>
10#include <linux/string.h>
11#include <linux/pci.h>
12#include <asm/io.h>
13
14void *dma_alloc_coherent(struct device *dev, size_t size,
15 dma_addr_t *dma_handle, int gfp)
16{
17 void *ret;
18 /* ignore region specifiers */
19 gfp &= ~(__GFP_DMA | __GFP_HIGHMEM);
20
21 if (dev == NULL || (*dev->dma_mask < 0xffffffff))
22 gfp |= GFP_DMA;
23 ret = (void *)__get_free_pages(gfp, get_order(size));
24
25 if (ret != NULL) {
26 memset(ret, 0, size);
27 *dma_handle = virt_to_phys(ret);
28 }
29 return ret;
30}
31
32void dma_free_coherent(struct device *dev, size_t size,
33 void *vaddr, dma_addr_t dma_handle)
34{
35 free_pages((unsigned long)vaddr, get_order(size));
36}
diff --git a/arch/m68knommu/kernel/entry.S b/arch/m68knommu/kernel/entry.S
new file mode 100644
index 000000000000..8b1f47239b9a
--- /dev/null
+++ b/arch/m68knommu/kernel/entry.S
@@ -0,0 +1,143 @@
1/*
2 * linux/arch/m68knommu/kernel/entry.S
3 *
4 * Copyright (C) 1999-2002, Greg Ungerer (gerg@snapgear.com)
5 * Copyright (C) 1998 D. Jeff Dionne <jeff@lineo.ca>,
6 * Kenneth Albanowski <kjahds@kjahds.com>,
7 * Copyright (C) 2000 Lineo Inc. (www.lineo.com)
8 *
9 * Based on:
10 *
11 * linux/arch/m68k/kernel/entry.S
12 *
13 * Copyright (C) 1991, 1992 Linus Torvalds
14 *
15 * This file is subject to the terms and conditions of the GNU General Public
16 * License. See the file README.legal in the main directory of this archive
17 * for more details.
18 *
19 * Linux/m68k support by Hamish Macdonald
20 *
21 * 68060 fixes by Jesper Skov
22 * ColdFire support by Greg Ungerer (gerg@snapgear.com)
23 * 5307 fixes by David W. Miller
24 * linux 2.4 support David McCullough <davidm@snapgear.com>
25 */
26
27#include <linux/config.h>
28#include <linux/sys.h>
29#include <linux/linkage.h>
30#include <asm/thread_info.h>
31#include <asm/errno.h>
32#include <asm/setup.h>
33#include <asm/segment.h>
34#include <asm/asm-offsets.h>
35#include <asm/entry.h>
36
37.text
38
39.globl buserr
40.globl trap
41.globl ret_from_exception
42.globl ret_from_signal
43.globl sys_fork
44.globl sys_clone
45.globl sys_vfork
46
47ENTRY(buserr)
48 SAVE_ALL
49 moveq #-1,%d0
50 movel %d0,%sp@(PT_ORIG_D0)
51 movel %sp,%sp@- /* stack frame pointer argument */
52 jsr buserr_c
53 addql #4,%sp
54 jra ret_from_exception
55
56ENTRY(trap)
57 SAVE_ALL
58 moveq #-1,%d0
59 movel %d0,%sp@(PT_ORIG_D0)
60 movel %sp,%sp@- /* stack frame pointer argument */
61 jsr trap_c
62 addql #4,%sp
63 jra ret_from_exception
64
65#ifdef TRAP_DBG_INTERRUPT
66
67.globl dbginterrupt
68ENTRY(dbginterrupt)
69 SAVE_ALL
70 moveq #-1,%d0
71 movel %d0,%sp@(PT_ORIG_D0)
72 movel %sp,%sp@- /* stack frame pointer argument */
73 jsr dbginterrupt_c
74 addql #4,%sp
75 jra ret_from_exception
76#endif
77
78ENTRY(reschedule)
79 /* save top of frame */
80 pea %sp@
81 jbsr set_esp0
82 addql #4,%sp
83 pea ret_from_exception
84 jmp schedule
85
86ENTRY(ret_from_fork)
87 movel %d1,%sp@-
88 jsr schedule_tail
89 addql #4,%sp
90 jra ret_from_exception
91
92ENTRY(sys_fork)
93 SAVE_SWITCH_STACK
94 pea %sp@(SWITCH_STACK_SIZE)
95 jbsr m68k_fork
96 addql #4,%sp
97 RESTORE_SWITCH_STACK
98 rts
99
100ENTRY(sys_vfork)
101 SAVE_SWITCH_STACK
102 pea %sp@(SWITCH_STACK_SIZE)
103 jbsr m68k_vfork
104 addql #4,%sp
105 RESTORE_SWITCH_STACK
106 rts
107
108ENTRY(sys_clone)
109 SAVE_SWITCH_STACK
110 pea %sp@(SWITCH_STACK_SIZE)
111 jbsr m68k_clone
112 addql #4,%sp
113 RESTORE_SWITCH_STACK
114 rts
115
116ENTRY(sys_sigsuspend)
117 SAVE_SWITCH_STACK
118 pea %sp@(SWITCH_STACK_SIZE)
119 jbsr do_sigsuspend
120 addql #4,%sp
121 RESTORE_SWITCH_STACK
122 rts
123
124ENTRY(sys_rt_sigsuspend)
125 SAVE_SWITCH_STACK
126 pea %sp@(SWITCH_STACK_SIZE)
127 jbsr do_rt_sigsuspend
128 addql #4,%sp
129 RESTORE_SWITCH_STACK
130 rts
131
132ENTRY(sys_sigreturn)
133 SAVE_SWITCH_STACK
134 jbsr do_sigreturn
135 RESTORE_SWITCH_STACK
136 rts
137
138ENTRY(sys_rt_sigreturn)
139 SAVE_SWITCH_STACK
140 jbsr do_rt_sigreturn
141 RESTORE_SWITCH_STACK
142 rts
143
diff --git a/arch/m68knommu/kernel/init_task.c b/arch/m68knommu/kernel/init_task.c
new file mode 100644
index 000000000000..3897043a126a
--- /dev/null
+++ b/arch/m68knommu/kernel/init_task.c
@@ -0,0 +1,43 @@
1/*
2 * linux/arch/m68knommu/kernel/init_task.c
3 */
4#include <linux/mm.h>
5#include <linux/module.h>
6#include <linux/sched.h>
7#include <linux/init.h>
8#include <linux/init_task.h>
9#include <linux/fs.h>
10#include <linux/mqueue.h>
11
12#include <asm/uaccess.h>
13#include <asm/pgtable.h>
14
15static struct fs_struct init_fs = INIT_FS;
16static struct files_struct init_files = INIT_FILES;
17static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
18static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
19struct mm_struct init_mm = INIT_MM(init_mm);
20
21EXPORT_SYMBOL(init_mm);
22
23/*
24 * Initial task structure.
25 *
26 * All other task structs will be allocated on slabs in fork.c
27 */
28__asm__(".align 4");
29struct task_struct init_task = INIT_TASK(init_task);
30
31EXPORT_SYMBOL(init_task);
32
33/*
34 * Initial thread structure.
35 *
36 * We need to make sure that this is 8192-byte aligned due to the
37 * way process stacks are handled. This is done by having a special
38 * "init_task" linker map entry..
39 */
40union thread_union init_thread_union
41 __attribute__((__section__(".data.init_task"))) =
42 { INIT_THREAD_INFO(init_task) };
43
diff --git a/arch/m68knommu/kernel/m68k_ksyms.c b/arch/m68knommu/kernel/m68k_ksyms.c
new file mode 100644
index 000000000000..e93a5ad56496
--- /dev/null
+++ b/arch/m68knommu/kernel/m68k_ksyms.c
@@ -0,0 +1,104 @@
1#include <linux/module.h>
2#include <linux/linkage.h>
3#include <linux/sched.h>
4#include <linux/string.h>
5#include <linux/mm.h>
6#include <linux/user.h>
7#include <linux/elfcore.h>
8#include <linux/in6.h>
9#include <linux/interrupt.h>
10#include <linux/config.h>
11
12#include <asm/setup.h>
13#include <asm/machdep.h>
14#include <asm/pgalloc.h>
15#include <asm/irq.h>
16#include <asm/io.h>
17#include <asm/semaphore.h>
18#include <asm/checksum.h>
19#include <asm/current.h>
20
21extern void dump_thread(struct pt_regs *, struct user *);
22extern int dump_fpu(struct pt_regs *, elf_fpregset_t *);
23
24/* platform dependent support */
25
26EXPORT_SYMBOL(__ioremap);
27EXPORT_SYMBOL(iounmap);
28EXPORT_SYMBOL(dump_fpu);
29EXPORT_SYMBOL(dump_thread);
30EXPORT_SYMBOL(strnlen);
31EXPORT_SYMBOL(strrchr);
32EXPORT_SYMBOL(strstr);
33EXPORT_SYMBOL(strchr);
34EXPORT_SYMBOL(strcat);
35EXPORT_SYMBOL(strlen);
36EXPORT_SYMBOL(strcmp);
37EXPORT_SYMBOL(strncmp);
38
39EXPORT_SYMBOL(ip_fast_csum);
40
41EXPORT_SYMBOL(mach_enable_irq);
42EXPORT_SYMBOL(mach_disable_irq);
43EXPORT_SYMBOL(kernel_thread);
44
45/* Networking helper routines. */
46EXPORT_SYMBOL(csum_partial_copy);
47
48/* The following are special because they're not called
49 explicitly (the C compiler generates them). Fortunately,
50 their interface isn't gonna change any time soon now, so
51 it's OK to leave it out of version control. */
52EXPORT_SYMBOL(memcpy);
53EXPORT_SYMBOL(memset);
54EXPORT_SYMBOL(memcmp);
55EXPORT_SYMBOL(memscan);
56EXPORT_SYMBOL(memmove);
57
58EXPORT_SYMBOL(__down_failed);
59EXPORT_SYMBOL(__down_failed_interruptible);
60EXPORT_SYMBOL(__down_failed_trylock);
61EXPORT_SYMBOL(__up_wakeup);
62
63EXPORT_SYMBOL(get_wchan);
64
65/*
66 * libgcc functions - functions that are used internally by the
67 * compiler... (prototypes are not correct though, but that
68 * doesn't really matter since they're not versioned).
69 */
70extern void __ashldi3(void);
71extern void __ashrdi3(void);
72extern void __divsi3(void);
73extern void __lshrdi3(void);
74extern void __modsi3(void);
75extern void __muldi3(void);
76extern void __mulsi3(void);
77extern void __udivsi3(void);
78extern void __umodsi3(void);
79
80 /* gcc lib functions */
81EXPORT_SYMBOL(__ashldi3);
82EXPORT_SYMBOL(__ashrdi3);
83EXPORT_SYMBOL(__divsi3);
84EXPORT_SYMBOL(__lshrdi3);
85EXPORT_SYMBOL(__modsi3);
86EXPORT_SYMBOL(__muldi3);
87EXPORT_SYMBOL(__mulsi3);
88EXPORT_SYMBOL(__udivsi3);
89EXPORT_SYMBOL(__umodsi3);
90
91EXPORT_SYMBOL(is_in_rom);
92
93#ifdef CONFIG_COLDFIRE
94extern unsigned int *dma_device_address;
95extern unsigned long dma_base_addr, _ramend;
96EXPORT_SYMBOL(dma_base_addr);
97EXPORT_SYMBOL(dma_device_address);
98EXPORT_SYMBOL(_ramend);
99
100extern asmlinkage void trap(void);
101extern void *_ramvec;
102EXPORT_SYMBOL(trap);
103EXPORT_SYMBOL(_ramvec);
104#endif /* CONFIG_COLDFIRE */
diff --git a/arch/m68knommu/kernel/module.c b/arch/m68knommu/kernel/module.c
new file mode 100644
index 000000000000..3b1a2ff61ddc
--- /dev/null
+++ b/arch/m68knommu/kernel/module.c
@@ -0,0 +1,128 @@
1#include <linux/moduleloader.h>
2#include <linux/elf.h>
3#include <linux/vmalloc.h>
4#include <linux/fs.h>
5#include <linux/string.h>
6#include <linux/kernel.h>
7
8#if 0
9#define DEBUGP printk
10#else
11#define DEBUGP(fmt...)
12#endif
13
14void *module_alloc(unsigned long size)
15{
16 if (size == 0)
17 return NULL;
18 return vmalloc(size);
19}
20
21
22/* Free memory returned from module_alloc */
23void module_free(struct module *mod, void *module_region)
24{
25 vfree(module_region);
26 /* FIXME: If module_region == mod->init_region, trim exception
27 table entries. */
28}
29
30/* We don't need anything special. */
31int module_frob_arch_sections(Elf_Ehdr *hdr,
32 Elf_Shdr *sechdrs,
33 char *secstrings,
34 struct module *mod)
35{
36 return 0;
37}
38
39int apply_relocate(Elf32_Shdr *sechdrs,
40 const char *strtab,
41 unsigned int symindex,
42 unsigned int relsec,
43 struct module *me)
44{
45 unsigned int i;
46 Elf32_Rel *rel = (void *)sechdrs[relsec].sh_addr;
47 Elf32_Sym *sym;
48 uint32_t *location;
49
50 DEBUGP("Applying relocate section %u to %u\n", relsec,
51 sechdrs[relsec].sh_info);
52 for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) {
53 /* This is where to make the change */
54 location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr
55 + rel[i].r_offset;
56 /* This is the symbol it is referring to. Note that all
57 undefined symbols have been resolved. */
58 sym = (Elf32_Sym *)sechdrs[symindex].sh_addr
59 + ELF32_R_SYM(rel[i].r_info);
60
61 switch (ELF32_R_TYPE(rel[i].r_info)) {
62 case R_68K_32:
63 /* We add the value into the location given */
64 *location += sym->st_value;
65 break;
66 case R_68K_PC32:
67 /* Add the value, subtract its postition */
68 *location += sym->st_value - (uint32_t)location;
69 break;
70 default:
71 printk(KERN_ERR "module %s: Unknown relocation: %u\n",
72 me->name, ELF32_R_TYPE(rel[i].r_info));
73 return -ENOEXEC;
74 }
75 }
76 return 0;
77}
78
79int apply_relocate_add(Elf32_Shdr *sechdrs,
80 const char *strtab,
81 unsigned int symindex,
82 unsigned int relsec,
83 struct module *me)
84{
85 unsigned int i;
86 Elf32_Rela *rel = (void *)sechdrs[relsec].sh_addr;
87 Elf32_Sym *sym;
88 uint32_t *location;
89
90 DEBUGP("Applying relocate_add section %u to %u\n", relsec,
91 sechdrs[relsec].sh_info);
92 for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) {
93 /* This is where to make the change */
94 location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr
95 + rel[i].r_offset;
96 /* This is the symbol it is referring to. Note that all
97 undefined symbols have been resolved. */
98 sym = (Elf32_Sym *)sechdrs[symindex].sh_addr
99 + ELF32_R_SYM(rel[i].r_info);
100
101 switch (ELF32_R_TYPE(rel[i].r_info)) {
102 case R_68K_32:
103 /* We add the value into the location given */
104 *location = rel[i].r_addend + sym->st_value;
105 break;
106 case R_68K_PC32:
107 /* Add the value, subtract its postition */
108 *location = rel[i].r_addend + sym->st_value - (uint32_t)location;
109 break;
110 default:
111 printk(KERN_ERR "module %s: Unknown relocation: %u\n",
112 me->name, ELF32_R_TYPE(rel[i].r_info));
113 return -ENOEXEC;
114 }
115 }
116 return 0;
117}
118
119int module_finalize(const Elf_Ehdr *hdr,
120 const Elf_Shdr *sechdrs,
121 struct module *me)
122{
123 return 0;
124}
125
126void module_arch_cleanup(struct module *mod)
127{
128}
diff --git a/arch/m68knommu/kernel/process.c b/arch/m68knommu/kernel/process.c
new file mode 100644
index 000000000000..2b6c9d32b7a6
--- /dev/null
+++ b/arch/m68knommu/kernel/process.c
@@ -0,0 +1,442 @@
1/*
2 * linux/arch/m68knommu/kernel/process.c
3 *
4 * Copyright (C) 1995 Hamish Macdonald
5 *
6 * 68060 fixes by Jesper Skov
7 *
8 * uClinux changes
9 * Copyright (C) 2000-2002, David McCullough <davidm@snapgear.com>
10 */
11
12/*
13 * This file handles the architecture-dependent parts of process handling..
14 */
15
16#include <linux/config.h>
17#include <linux/module.h>
18#include <linux/errno.h>
19#include <linux/sched.h>
20#include <linux/kernel.h>
21#include <linux/mm.h>
22#include <linux/smp.h>
23#include <linux/smp_lock.h>
24#include <linux/stddef.h>
25#include <linux/unistd.h>
26#include <linux/ptrace.h>
27#include <linux/slab.h>
28#include <linux/user.h>
29#include <linux/a.out.h>
30#include <linux/interrupt.h>
31#include <linux/reboot.h>
32
33#include <asm/uaccess.h>
34#include <asm/system.h>
35#include <asm/traps.h>
36#include <asm/machdep.h>
37#include <asm/setup.h>
38#include <asm/pgtable.h>
39
40asmlinkage void ret_from_fork(void);
41
42
43/*
44 * The idle loop on an m68knommu..
45 */
46void default_idle(void)
47{
48 while(1) {
49 if (need_resched())
50 __asm__("stop #0x2000" : : : "cc");
51 schedule();
52 }
53}
54
55void (*idle)(void) = default_idle;
56
57/*
58 * The idle thread. There's no useful work to be
59 * done, so just try to conserve power and have a
60 * low exit latency (ie sit in a loop waiting for
61 * somebody to say that they'd like to reschedule)
62 */
63void cpu_idle(void)
64{
65 /* endless idle loop with no priority at all */
66 idle();
67}
68
69void machine_restart(char * __unused)
70{
71 if (mach_reset)
72 mach_reset();
73 for (;;);
74}
75
76EXPORT_SYMBOL(machine_restart);
77
78void machine_halt(void)
79{
80 if (mach_halt)
81 mach_halt();
82 for (;;);
83}
84
85EXPORT_SYMBOL(machine_halt);
86
87void machine_power_off(void)
88{
89 if (mach_power_off)
90 mach_power_off();
91 for (;;);
92}
93
94EXPORT_SYMBOL(machine_power_off);
95
96void show_regs(struct pt_regs * regs)
97{
98 printk(KERN_NOTICE "\n");
99 printk(KERN_NOTICE "Format %02x Vector: %04x PC: %08lx Status: %04x %s\n",
100 regs->format, regs->vector, regs->pc, regs->sr, print_tainted());
101 printk(KERN_NOTICE "ORIG_D0: %08lx D0: %08lx A2: %08lx A1: %08lx\n",
102 regs->orig_d0, regs->d0, regs->a2, regs->a1);
103 printk(KERN_NOTICE "A0: %08lx D5: %08lx D4: %08lx\n",
104 regs->a0, regs->d5, regs->d4);
105 printk(KERN_NOTICE "D3: %08lx D2: %08lx D1: %08lx\n",
106 regs->d3, regs->d2, regs->d1);
107 if (!(regs->sr & PS_S))
108 printk(KERN_NOTICE "USP: %08lx\n", rdusp());
109}
110
111/*
112 * Create a kernel thread
113 */
114int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
115{
116 int retval;
117 long clone_arg = flags | CLONE_VM;
118 mm_segment_t fs;
119
120 fs = get_fs();
121 set_fs(KERNEL_DS);
122
123 __asm__ __volatile__ (
124 "movel %%sp, %%d2\n\t"
125 "movel %5, %%d1\n\t"
126 "movel %1, %%d0\n\t"
127 "trap #0\n\t"
128 "cmpl %%sp, %%d2\n\t"
129 "jeq 1f\n\t"
130 "movel %3, %%sp@-\n\t"
131 "jsr %4@\n\t"
132 "movel %2, %%d0\n\t"
133 "trap #0\n"
134 "1:\n\t"
135 "movel %%d0, %0\n"
136 : "=d" (retval)
137 : "i" (__NR_clone),
138 "i" (__NR_exit),
139 "a" (arg),
140 "a" (fn),
141 "a" (clone_arg)
142 : "cc", "%d0", "%d1", "%d2");
143
144 set_fs(fs);
145 return retval;
146}
147
148void flush_thread(void)
149{
150#ifdef CONFIG_FPU
151 unsigned long zero = 0;
152#endif
153 set_fs(USER_DS);
154 current->thread.fs = __USER_DS;
155#ifdef CONFIG_FPU
156 if (!FPU_IS_EMU)
157 asm volatile (".chip 68k/68881\n\t"
158 "frestore %0@\n\t"
159 ".chip 68k" : : "a" (&zero));
160#endif
161}
162
163/*
164 * "m68k_fork()".. By the time we get here, the
165 * non-volatile registers have also been saved on the
166 * stack. We do some ugly pointer stuff here.. (see
167 * also copy_thread)
168 */
169
170asmlinkage int m68k_fork(struct pt_regs *regs)
171{
172 /* fork almost works, enough to trick you into looking elsewhere :-( */
173 return(-EINVAL);
174}
175
176asmlinkage int m68k_vfork(struct pt_regs *regs)
177{
178 return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, rdusp(), regs, 0, NULL, NULL);
179}
180
181asmlinkage int m68k_clone(struct pt_regs *regs)
182{
183 unsigned long clone_flags;
184 unsigned long newsp;
185
186 /* syscall2 puts clone_flags in d1 and usp in d2 */
187 clone_flags = regs->d1;
188 newsp = regs->d2;
189 if (!newsp)
190 newsp = rdusp();
191 return do_fork(clone_flags, newsp, regs, 0, NULL, NULL);
192}
193
194int copy_thread(int nr, unsigned long clone_flags,
195 unsigned long usp, unsigned long topstk,
196 struct task_struct * p, struct pt_regs * regs)
197{
198 struct pt_regs * childregs;
199 struct switch_stack * childstack, *stack;
200 unsigned long stack_offset, *retp;
201
202 stack_offset = THREAD_SIZE - sizeof(struct pt_regs);
203 childregs = (struct pt_regs *) ((unsigned long) p->thread_info + stack_offset);
204
205 *childregs = *regs;
206 childregs->d0 = 0;
207
208 retp = ((unsigned long *) regs);
209 stack = ((struct switch_stack *) retp) - 1;
210
211 childstack = ((struct switch_stack *) childregs) - 1;
212 *childstack = *stack;
213 childstack->retpc = (unsigned long)ret_from_fork;
214
215 p->thread.usp = usp;
216 p->thread.ksp = (unsigned long)childstack;
217 /*
218 * Must save the current SFC/DFC value, NOT the value when
219 * the parent was last descheduled - RGH 10-08-96
220 */
221 p->thread.fs = get_fs().seg;
222
223#ifdef CONFIG_FPU
224 if (!FPU_IS_EMU) {
225 /* Copy the current fpu state */
226 asm volatile ("fsave %0" : : "m" (p->thread.fpstate[0]) : "memory");
227
228 if (p->thread.fpstate[0])
229 asm volatile ("fmovemx %/fp0-%/fp7,%0\n\t"
230 "fmoveml %/fpiar/%/fpcr/%/fpsr,%1"
231 : : "m" (p->thread.fp[0]), "m" (p->thread.fpcntl[0])
232 : "memory");
233 /* Restore the state in case the fpu was busy */
234 asm volatile ("frestore %0" : : "m" (p->thread.fpstate[0]));
235 }
236#endif
237
238 return 0;
239}
240
241/* Fill in the fpu structure for a core dump. */
242
243int dump_fpu(struct pt_regs *regs, struct user_m68kfp_struct *fpu)
244{
245#ifdef CONFIG_FPU
246 char fpustate[216];
247
248 if (FPU_IS_EMU) {
249 int i;
250
251 memcpy(fpu->fpcntl, current->thread.fpcntl, 12);
252 memcpy(fpu->fpregs, current->thread.fp, 96);
253 /* Convert internal fpu reg representation
254 * into long double format
255 */
256 for (i = 0; i < 24; i += 3)
257 fpu->fpregs[i] = ((fpu->fpregs[i] & 0xffff0000) << 15) |
258 ((fpu->fpregs[i] & 0x0000ffff) << 16);
259 return 1;
260 }
261
262 /* First dump the fpu context to avoid protocol violation. */
263 asm volatile ("fsave %0" :: "m" (fpustate[0]) : "memory");
264 if (!fpustate[0])
265 return 0;
266
267 asm volatile ("fmovem %/fpiar/%/fpcr/%/fpsr,%0"
268 :: "m" (fpu->fpcntl[0])
269 : "memory");
270 asm volatile ("fmovemx %/fp0-%/fp7,%0"
271 :: "m" (fpu->fpregs[0])
272 : "memory");
273#endif
274 return 1;
275}
276
277/*
278 * fill in the user structure for a core dump..
279 */
280void dump_thread(struct pt_regs * regs, struct user * dump)
281{
282 struct switch_stack *sw;
283
284 /* changed the size calculations - should hopefully work better. lbt */
285 dump->magic = CMAGIC;
286 dump->start_code = 0;
287 dump->start_stack = rdusp() & ~(PAGE_SIZE - 1);
288 dump->u_tsize = ((unsigned long) current->mm->end_code) >> PAGE_SHIFT;
289 dump->u_dsize = ((unsigned long) (current->mm->brk +
290 (PAGE_SIZE-1))) >> PAGE_SHIFT;
291 dump->u_dsize -= dump->u_tsize;
292 dump->u_ssize = 0;
293
294 if (dump->start_stack < TASK_SIZE)
295 dump->u_ssize = ((unsigned long) (TASK_SIZE - dump->start_stack)) >> PAGE_SHIFT;
296
297 dump->u_ar0 = (struct user_regs_struct *)((int)&dump->regs - (int)dump);
298 sw = ((struct switch_stack *)regs) - 1;
299 dump->regs.d1 = regs->d1;
300 dump->regs.d2 = regs->d2;
301 dump->regs.d3 = regs->d3;
302 dump->regs.d4 = regs->d4;
303 dump->regs.d5 = regs->d5;
304 dump->regs.d6 = sw->d6;
305 dump->regs.d7 = sw->d7;
306 dump->regs.a0 = regs->a0;
307 dump->regs.a1 = regs->a1;
308 dump->regs.a2 = regs->a2;
309 dump->regs.a3 = sw->a3;
310 dump->regs.a4 = sw->a4;
311 dump->regs.a5 = sw->a5;
312 dump->regs.a6 = sw->a6;
313 dump->regs.d0 = regs->d0;
314 dump->regs.orig_d0 = regs->orig_d0;
315 dump->regs.stkadj = regs->stkadj;
316 dump->regs.sr = regs->sr;
317 dump->regs.pc = regs->pc;
318 dump->regs.fmtvec = (regs->format << 12) | regs->vector;
319 /* dump floating point stuff */
320 dump->u_fpvalid = dump_fpu (regs, &dump->m68kfp);
321}
322
323/*
324 * Generic dumping code. Used for panic and debug.
325 */
326void dump(struct pt_regs *fp)
327{
328 unsigned long *sp;
329 unsigned char *tp;
330 int i;
331
332 printk(KERN_EMERG "\nCURRENT PROCESS:\n\n");
333 printk(KERN_EMERG "COMM=%s PID=%d\n", current->comm, current->pid);
334
335 if (current->mm) {
336 printk(KERN_EMERG "TEXT=%08x-%08x DATA=%08x-%08x BSS=%08x-%08x\n",
337 (int) current->mm->start_code,
338 (int) current->mm->end_code,
339 (int) current->mm->start_data,
340 (int) current->mm->end_data,
341 (int) current->mm->end_data,
342 (int) current->mm->brk);
343 printk(KERN_EMERG "USER-STACK=%08x KERNEL-STACK=%08x\n\n",
344 (int) current->mm->start_stack,
345 (int)(((unsigned long) current) + THREAD_SIZE));
346 }
347
348 printk(KERN_EMERG "PC: %08lx\n", fp->pc);
349 printk(KERN_EMERG "SR: %08lx SP: %08lx\n", (long) fp->sr, (long) fp);
350 printk(KERN_EMERG "d0: %08lx d1: %08lx d2: %08lx d3: %08lx\n",
351 fp->d0, fp->d1, fp->d2, fp->d3);
352 printk(KERN_EMERG "d4: %08lx d5: %08lx a0: %08lx a1: %08lx\n",
353 fp->d4, fp->d5, fp->a0, fp->a1);
354 printk(KERN_EMERG "\nUSP: %08x TRAPFRAME: %08x\n", (unsigned int) rdusp(),
355 (unsigned int) fp);
356
357 printk(KERN_EMERG "\nCODE:");
358 tp = ((unsigned char *) fp->pc) - 0x20;
359 for (sp = (unsigned long *) tp, i = 0; (i < 0x40); i += 4) {
360 if ((i % 0x10) == 0)
361 printk(KERN_EMERG "\n%08x: ", (int) (tp + i));
362 printk(KERN_EMERG "%08x ", (int) *sp++);
363 }
364 printk(KERN_EMERG "\n");
365
366 printk(KERN_EMERG "\nKERNEL STACK:");
367 tp = ((unsigned char *) fp) - 0x40;
368 for (sp = (unsigned long *) tp, i = 0; (i < 0xc0); i += 4) {
369 if ((i % 0x10) == 0)
370 printk(KERN_EMERG "\n%08x: ", (int) (tp + i));
371 printk(KERN_EMERG "%08x ", (int) *sp++);
372 }
373 printk(KERN_EMERG "\n");
374 printk(KERN_EMERG "\n");
375
376 printk(KERN_EMERG "\nUSER STACK:");
377 tp = (unsigned char *) (rdusp() - 0x10);
378 for (sp = (unsigned long *) tp, i = 0; (i < 0x80); i += 4) {
379 if ((i % 0x10) == 0)
380 printk(KERN_EMERG "\n%08x: ", (int) (tp + i));
381 printk(KERN_EMERG "%08x ", (int) *sp++);
382 }
383 printk(KERN_EMERG "\n\n");
384}
385
386/*
387 * sys_execve() executes a new program.
388 */
389asmlinkage int sys_execve(char *name, char **argv, char **envp)
390{
391 int error;
392 char * filename;
393 struct pt_regs *regs = (struct pt_regs *) &name;
394
395 lock_kernel();
396 filename = getname(name);
397 error = PTR_ERR(filename);
398 if (IS_ERR(filename))
399 goto out;
400 error = do_execve(filename, argv, envp, regs);
401 putname(filename);
402out:
403 unlock_kernel();
404 return error;
405}
406
407unsigned long get_wchan(struct task_struct *p)
408{
409 unsigned long fp, pc;
410 unsigned long stack_page;
411 int count = 0;
412 if (!p || p == current || p->state == TASK_RUNNING)
413 return 0;
414
415 stack_page = (unsigned long)p;
416 fp = ((struct switch_stack *)p->thread.ksp)->a6;
417 do {
418 if (fp < stack_page+sizeof(struct thread_info) ||
419 fp >= 8184+stack_page)
420 return 0;
421 pc = ((unsigned long *)fp)[1];
422 if (!in_sched_functions(pc))
423 return pc;
424 fp = *(unsigned long *) fp;
425 } while (count++ < 16);
426 return 0;
427}
428
429/*
430 * Return saved PC of a blocked thread.
431 */
432unsigned long thread_saved_pc(struct task_struct *tsk)
433{
434 struct switch_stack *sw = (struct switch_stack *)tsk->thread.ksp;
435
436 /* Check whether the thread is blocked in resume() */
437 if (in_sched_functions(sw->retpc))
438 return ((unsigned long *)sw->a6)[1];
439 else
440 return sw->retpc;
441}
442
diff --git a/arch/m68knommu/kernel/ptrace.c b/arch/m68knommu/kernel/ptrace.c
new file mode 100644
index 000000000000..15cf79080b15
--- /dev/null
+++ b/arch/m68knommu/kernel/ptrace.c
@@ -0,0 +1,383 @@
1/*
2 * linux/arch/m68knommu/kernel/ptrace.c
3 *
4 * Copyright (C) 1994 by Hamish Macdonald
5 * Taken from linux/kernel/ptrace.c and modified for M680x0.
6 * linux/kernel/ptrace.c is by Ross Biro 1/23/92, edited by Linus Torvalds
7 *
8 * This file is subject to the terms and conditions of the GNU General
9 * Public License. See the file COPYING in the main directory of
10 * this archive for more details.
11 */
12
13#include <linux/kernel.h>
14#include <linux/sched.h>
15#include <linux/mm.h>
16#include <linux/smp.h>
17#include <linux/smp_lock.h>
18#include <linux/errno.h>
19#include <linux/ptrace.h>
20#include <linux/user.h>
21#include <linux/config.h>
22
23#include <asm/uaccess.h>
24#include <asm/page.h>
25#include <asm/pgtable.h>
26#include <asm/system.h>
27#include <asm/processor.h>
28
29/*
30 * does not yet catch signals sent when the child dies.
31 * in exit.c or in signal.c.
32 */
33
34/* determines which bits in the SR the user has access to. */
35/* 1 = access 0 = no access */
36#define SR_MASK 0x001f
37
38/* sets the trace bits. */
39#define TRACE_BITS 0x8000
40
41/* Find the stack offset for a register, relative to thread.esp0. */
42#define PT_REG(reg) ((long)&((struct pt_regs *)0)->reg)
43#define SW_REG(reg) ((long)&((struct switch_stack *)0)->reg \
44 - sizeof(struct switch_stack))
45/* Mapping from PT_xxx to the stack offset at which the register is
46 saved. Notice that usp has no stack-slot and needs to be treated
47 specially (see get_reg/put_reg below). */
48static int regoff[] = {
49 PT_REG(d1), PT_REG(d2), PT_REG(d3), PT_REG(d4),
50 PT_REG(d5), SW_REG(d6), SW_REG(d7), PT_REG(a0),
51 PT_REG(a1), PT_REG(a2), SW_REG(a3), SW_REG(a4),
52 SW_REG(a5), SW_REG(a6), PT_REG(d0), -1,
53 PT_REG(orig_d0), PT_REG(sr), PT_REG(pc),
54};
55
56/*
57 * Get contents of register REGNO in task TASK.
58 */
59static inline long get_reg(struct task_struct *task, int regno)
60{
61 unsigned long *addr;
62
63 if (regno == PT_USP)
64 addr = &task->thread.usp;
65 else if (regno < sizeof(regoff)/sizeof(regoff[0]))
66 addr = (unsigned long *)(task->thread.esp0 + regoff[regno]);
67 else
68 return 0;
69 return *addr;
70}
71
72/*
73 * Write contents of register REGNO in task TASK.
74 */
75static inline int put_reg(struct task_struct *task, int regno,
76 unsigned long data)
77{
78 unsigned long *addr;
79
80 if (regno == PT_USP)
81 addr = &task->thread.usp;
82 else if (regno < sizeof(regoff)/sizeof(regoff[0]))
83 addr = (unsigned long *) (task->thread.esp0 + regoff[regno]);
84 else
85 return -1;
86 *addr = data;
87 return 0;
88}
89
90/*
91 * Called by kernel/ptrace.c when detaching..
92 *
93 * Make sure the single step bit is not set.
94 */
95void ptrace_disable(struct task_struct *child)
96{
97 unsigned long tmp;
98 /* make sure the single step bit is not set. */
99 tmp = get_reg(child, PT_SR) & ~(TRACE_BITS << 16);
100 put_reg(child, PT_SR, tmp);
101}
102
103asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
104{
105 struct task_struct *child;
106 int ret;
107
108 lock_kernel();
109 ret = -EPERM;
110 if (request == PTRACE_TRACEME) {
111 /* are we already being traced? */
112 if (current->ptrace & PT_PTRACED)
113 goto out;
114 /* set the ptrace bit in the process flags. */
115 current->ptrace |= PT_PTRACED;
116 ret = 0;
117 goto out;
118 }
119 ret = -ESRCH;
120 read_lock(&tasklist_lock);
121 child = find_task_by_pid(pid);
122 if (child)
123 get_task_struct(child);
124 read_unlock(&tasklist_lock);
125 if (!child)
126 goto out;
127
128 ret = -EPERM;
129 if (pid == 1) /* you may not mess with init */
130 goto out_tsk;
131
132 if (request == PTRACE_ATTACH) {
133 ret = ptrace_attach(child);
134 goto out_tsk;
135 }
136 ret = ptrace_check_attach(child, request == PTRACE_KILL);
137 if (ret < 0)
138 goto out_tsk;
139
140 switch (request) {
141 /* when I and D space are separate, these will need to be fixed. */
142 case PTRACE_PEEKTEXT: /* read word at location addr. */
143 case PTRACE_PEEKDATA: {
144 unsigned long tmp;
145 int copied;
146
147 copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0);
148 ret = -EIO;
149 if (copied != sizeof(tmp))
150 break;
151 ret = put_user(tmp,(unsigned long *) data);
152 break;
153 }
154
155 /* read the word at location addr in the USER area. */
156 case PTRACE_PEEKUSR: {
157 unsigned long tmp;
158
159 ret = -EIO;
160 if ((addr & 3) || addr < 0 ||
161 addr > sizeof(struct user) - 3)
162 break;
163
164 tmp = 0; /* Default return condition */
165 addr = addr >> 2; /* temporary hack. */
166 ret = -EIO;
167 if (addr < 19) {
168 tmp = get_reg(child, addr);
169 if (addr == PT_SR)
170 tmp >>= 16;
171 } else if (addr >= 21 && addr < 49) {
172 tmp = child->thread.fp[addr - 21];
173#ifdef CONFIG_M68KFPU_EMU
174 /* Convert internal fpu reg representation
175 * into long double format
176 */
177 if (FPU_IS_EMU && (addr < 45) && !(addr % 3))
178 tmp = ((tmp & 0xffff0000) << 15) |
179 ((tmp & 0x0000ffff) << 16);
180#endif
181 } else if (addr == 49) {
182 tmp = child->mm->start_code;
183 } else if (addr == 50) {
184 tmp = child->mm->start_data;
185 } else if (addr == 51) {
186 tmp = child->mm->end_code;
187 } else
188 break;
189 ret = put_user(tmp,(unsigned long *) data);
190 break;
191 }
192
193 /* when I and D space are separate, this will have to be fixed. */
194 case PTRACE_POKETEXT: /* write the word at location addr. */
195 case PTRACE_POKEDATA:
196 ret = 0;
197 if (access_process_vm(child, addr, &data, sizeof(data), 1) == sizeof(data))
198 break;
199 ret = -EIO;
200 break;
201
202 case PTRACE_POKEUSR: /* write the word at location addr in the USER area */
203 ret = -EIO;
204 if ((addr & 3) || addr < 0 ||
205 addr > sizeof(struct user) - 3)
206 break;
207
208 addr = addr >> 2; /* temporary hack. */
209
210 if (addr == PT_SR) {
211 data &= SR_MASK;
212 data <<= 16;
213 data |= get_reg(child, PT_SR) & ~(SR_MASK << 16);
214 }
215 if (addr < 19) {
216 if (put_reg(child, addr, data))
217 break;
218 ret = 0;
219 break;
220 }
221 if (addr >= 21 && addr < 48)
222 {
223#ifdef CONFIG_M68KFPU_EMU
224 /* Convert long double format
225 * into internal fpu reg representation
226 */
227 if (FPU_IS_EMU && (addr < 45) && !(addr % 3)) {
228 data = (unsigned long)data << 15;
229 data = (data & 0xffff0000) |
230 ((data & 0x0000ffff) >> 1);
231 }
232#endif
233 child->thread.fp[addr - 21] = data;
234 ret = 0;
235 }
236 break;
237
238 case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */
239 case PTRACE_CONT: { /* restart after signal. */
240 long tmp;
241
242 ret = -EIO;
243 if ((unsigned long) data > _NSIG)
244 break;
245 if (request == PTRACE_SYSCALL)
246 set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
247 else
248 clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
249 child->exit_code = data;
250 /* make sure the single step bit is not set. */
251 tmp = get_reg(child, PT_SR) & ~(TRACE_BITS << 16);
252 put_reg(child, PT_SR, tmp);
253 wake_up_process(child);
254 ret = 0;
255 break;
256 }
257
258 /*
259 * make the child exit. Best I can do is send it a sigkill.
260 * perhaps it should be put in the status that it wants to
261 * exit.
262 */
263 case PTRACE_KILL: {
264 long tmp;
265
266 ret = 0;
267 if (child->exit_state == EXIT_ZOMBIE) /* already dead */
268 break;
269 child->exit_code = SIGKILL;
270 /* make sure the single step bit is not set. */
271 tmp = get_reg(child, PT_SR) & ~(TRACE_BITS << 16);
272 put_reg(child, PT_SR, tmp);
273 wake_up_process(child);
274 break;
275 }
276
277 case PTRACE_SINGLESTEP: { /* set the trap flag. */
278 long tmp;
279
280 ret = -EIO;
281 if ((unsigned long) data > _NSIG)
282 break;
283 clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
284 tmp = get_reg(child, PT_SR) | (TRACE_BITS << 16);
285 put_reg(child, PT_SR, tmp);
286
287 child->exit_code = data;
288 /* give it a chance to run. */
289 wake_up_process(child);
290 ret = 0;
291 break;
292 }
293
294 case PTRACE_DETACH: /* detach a process that was attached. */
295 ret = ptrace_detach(child, data);
296 break;
297
298 case PTRACE_GETREGS: { /* Get all gp regs from the child. */
299 int i;
300 unsigned long tmp;
301 for (i = 0; i < 19; i++) {
302 tmp = get_reg(child, i);
303 if (i == PT_SR)
304 tmp >>= 16;
305 if (put_user(tmp, (unsigned long *) data)) {
306 ret = -EFAULT;
307 break;
308 }
309 data += sizeof(long);
310 }
311 ret = 0;
312 break;
313 }
314
315 case PTRACE_SETREGS: { /* Set all gp regs in the child. */
316 int i;
317 unsigned long tmp;
318 for (i = 0; i < 19; i++) {
319 if (get_user(tmp, (unsigned long *) data)) {
320 ret = -EFAULT;
321 break;
322 }
323 if (i == PT_SR) {
324 tmp &= SR_MASK;
325 tmp <<= 16;
326 tmp |= get_reg(child, PT_SR) & ~(SR_MASK << 16);
327 }
328 put_reg(child, i, tmp);
329 data += sizeof(long);
330 }
331 ret = 0;
332 break;
333 }
334
335#ifdef PTRACE_GETFPREGS
336 case PTRACE_GETFPREGS: { /* Get the child FPU state. */
337 ret = 0;
338 if (copy_to_user((void *)data, &child->thread.fp,
339 sizeof(struct user_m68kfp_struct)))
340 ret = -EFAULT;
341 break;
342 }
343#endif
344
345#ifdef PTRACE_SETFPREGS
346 case PTRACE_SETFPREGS: { /* Set the child FPU state. */
347 ret = 0;
348 if (copy_from_user(&child->thread.fp, (void *)data,
349 sizeof(struct user_m68kfp_struct)))
350 ret = -EFAULT;
351 break;
352 }
353#endif
354
355 default:
356 ret = -EIO;
357 break;
358 }
359out_tsk:
360 put_task_struct(child);
361out:
362 unlock_kernel();
363 return ret;
364}
365
366asmlinkage void syscall_trace(void)
367{
368 if (!test_thread_flag(TIF_SYSCALL_TRACE))
369 return;
370 if (!(current->ptrace & PT_PTRACED))
371 return;
372 ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
373 ? 0x80 : 0));
374 /*
375 * this isn't the same as continuing with a signal, but it will do
376 * for normal use. strace only continues with a signal if the
377 * stopping signal is not SIGTRAP. -brl
378 */
379 if (current->exit_code) {
380 send_sig(current->exit_code, current, 1);
381 current->exit_code = 0;
382 }
383}
diff --git a/arch/m68knommu/kernel/semaphore.c b/arch/m68knommu/kernel/semaphore.c
new file mode 100644
index 000000000000..c083f4772add
--- /dev/null
+++ b/arch/m68knommu/kernel/semaphore.c
@@ -0,0 +1,134 @@
1/*
2 * Generic semaphore code. Buyer beware. Do your own
3 * specific changes in <asm/semaphore-helper.h>
4 */
5
6#include <linux/config.h>
7#include <linux/sched.h>
8#include <linux/err.h>
9#include <linux/init.h>
10#include <asm/semaphore-helper.h>
11
12#ifndef CONFIG_RMW_INSNS
13spinlock_t semaphore_wake_lock;
14#endif
15
16/*
17 * Semaphores are implemented using a two-way counter:
18 * The "count" variable is decremented for each process
19 * that tries to sleep, while the "waking" variable is
20 * incremented when the "up()" code goes to wake up waiting
21 * processes.
22 *
23 * Notably, the inline "up()" and "down()" functions can
24 * efficiently test if they need to do any extra work (up
25 * needs to do something only if count was negative before
26 * the increment operation.
27 *
28 * waking_non_zero() (from asm/semaphore.h) must execute
29 * atomically.
30 *
31 * When __up() is called, the count was negative before
32 * incrementing it, and we need to wake up somebody.
33 *
34 * This routine adds one to the count of processes that need to
35 * wake up and exit. ALL waiting processes actually wake up but
36 * only the one that gets to the "waking" field first will gate
37 * through and acquire the semaphore. The others will go back
38 * to sleep.
39 *
40 * Note that these functions are only called when there is
41 * contention on the lock, and as such all this is the
42 * "non-critical" part of the whole semaphore business. The
43 * critical part is the inline stuff in <asm/semaphore.h>
44 * where we want to avoid any extra jumps and calls.
45 */
46void __up(struct semaphore *sem)
47{
48 wake_one_more(sem);
49 wake_up(&sem->wait);
50}
51
52/*
53 * Perform the "down" function. Return zero for semaphore acquired,
54 * return negative for signalled out of the function.
55 *
56 * If called from __down, the return is ignored and the wait loop is
57 * not interruptible. This means that a task waiting on a semaphore
58 * using "down()" cannot be killed until someone does an "up()" on
59 * the semaphore.
60 *
61 * If called from __down_interruptible, the return value gets checked
62 * upon return. If the return value is negative then the task continues
63 * with the negative value in the return register (it can be tested by
64 * the caller).
65 *
66 * Either form may be used in conjunction with "up()".
67 *
68 */
69
70
71#define DOWN_HEAD(task_state) \
72 \
73 \
74 current->state = (task_state); \
75 add_wait_queue(&sem->wait, &wait); \
76 \
77 /* \
78 * Ok, we're set up. sem->count is known to be less than zero \
79 * so we must wait. \
80 * \
81 * We can let go the lock for purposes of waiting. \
82 * We re-acquire it after awaking so as to protect \
83 * all semaphore operations. \
84 * \
85 * If "up()" is called before we call waking_non_zero() then \
86 * we will catch it right away. If it is called later then \
87 * we will have to go through a wakeup cycle to catch it. \
88 * \
89 * Multiple waiters contend for the semaphore lock to see \
90 * who gets to gate through and who has to wait some more. \
91 */ \
92 for (;;) {
93
94#define DOWN_TAIL(task_state) \
95 current->state = (task_state); \
96 } \
97 current->state = TASK_RUNNING; \
98 remove_wait_queue(&sem->wait, &wait);
99
100void __sched __down(struct semaphore * sem)
101{
102 DECLARE_WAITQUEUE(wait, current);
103
104 DOWN_HEAD(TASK_UNINTERRUPTIBLE)
105 if (waking_non_zero(sem))
106 break;
107 schedule();
108 DOWN_TAIL(TASK_UNINTERRUPTIBLE)
109}
110
111int __sched __down_interruptible(struct semaphore * sem)
112{
113 DECLARE_WAITQUEUE(wait, current);
114 int ret = 0;
115
116 DOWN_HEAD(TASK_INTERRUPTIBLE)
117
118 ret = waking_non_zero_interruptible(sem, current);
119 if (ret)
120 {
121 if (ret == 1)
122 /* ret != 0 only if we get interrupted -arca */
123 ret = 0;
124 break;
125 }
126 schedule();
127 DOWN_TAIL(TASK_INTERRUPTIBLE)
128 return ret;
129}
130
131int __down_trylock(struct semaphore * sem)
132{
133 return waking_non_zero_trylock(sem);
134}
diff --git a/arch/m68knommu/kernel/setup.c b/arch/m68knommu/kernel/setup.c
new file mode 100644
index 000000000000..557238596dcb
--- /dev/null
+++ b/arch/m68knommu/kernel/setup.c
@@ -0,0 +1,347 @@
1/*
2 * linux/arch/m68knommu/kernel/setup.c
3 *
4 * Copyright (C) 1999-2004 Greg Ungerer (gerg@snapgear.com)
5 * Copyright (C) 1998,1999 D. Jeff Dionne <jeff@lineo.ca>
6 * Copyleft ()) 2000 James D. Schettine {james@telos-systems.com}
7 * Copyright (C) 1998 Kenneth Albanowski <kjahds@kjahds.com>
8 * Copyright (C) 1995 Hamish Macdonald
9 * Copyright (C) 2000 Lineo Inc. (www.lineo.com)
10 * Copyright (C) 2001 Lineo, Inc. <www.lineo.com>
11 *
12 * 68VZ328 Fixes/support Evan Stawnyczy <e@lineo.ca>
13 */
14
15/*
16 * This file handles the architecture-dependent parts of system setup
17 */
18
19#include <linux/config.h>
20#include <linux/kernel.h>
21#include <linux/sched.h>
22#include <linux/delay.h>
23#include <linux/interrupt.h>
24#include <linux/fs.h>
25#include <linux/fb.h>
26#include <linux/console.h>
27#include <linux/genhd.h>
28#include <linux/errno.h>
29#include <linux/string.h>
30#include <linux/major.h>
31#include <linux/bootmem.h>
32#include <linux/seq_file.h>
33#include <linux/root_dev.h>
34#include <linux/init.h>
35
36#include <asm/setup.h>
37#include <asm/irq.h>
38#include <asm/machdep.h>
39
40#ifdef CONFIG_BLK_DEV_INITRD
41#include <asm/pgtable.h>
42#endif
43
44unsigned long rom_length;
45unsigned long memory_start;
46unsigned long memory_end;
47
48char command_line[COMMAND_LINE_SIZE];
49
50/* setup some dummy routines */
51static void dummy_waitbut(void)
52{
53}
54
55void (*mach_sched_init) (irqreturn_t (*handler)(int, void *, struct pt_regs *)) = NULL;
56void (*mach_tick)( void ) = NULL;
57/* machine dependent keyboard functions */
58int (*mach_keyb_init) (void) = NULL;
59int (*mach_kbdrate) (struct kbd_repeat *) = NULL;
60void (*mach_kbd_leds) (unsigned int) = NULL;
61/* machine dependent irq functions */
62void (*mach_init_IRQ) (void) = NULL;
63irqreturn_t (*(*mach_default_handler)[]) (int, void *, struct pt_regs *) = NULL;
64void (*mach_enable_irq) (unsigned int) = NULL;
65void (*mach_disable_irq) (unsigned int) = NULL;
66int (*mach_get_irq_list) (struct seq_file *, void *) = NULL;
67void (*mach_process_int) (int irq, struct pt_regs *fp) = NULL;
68void (*mach_trap_init) (void);
69/* machine dependent timer functions */
70unsigned long (*mach_gettimeoffset) (void) = NULL;
71void (*mach_gettod) (int*, int*, int*, int*, int*, int*) = NULL;
72int (*mach_hwclk) (int, struct hwclk_time*) = NULL;
73int (*mach_set_clock_mmss) (unsigned long) = NULL;
74void (*mach_mksound)( unsigned int count, unsigned int ticks ) = NULL;
75void (*mach_reset)( void ) = NULL;
76void (*waitbut)(void) = dummy_waitbut;
77void (*mach_debug_init)(void) = NULL;
78void (*mach_halt)( void ) = NULL;
79void (*mach_power_off)( void ) = NULL;
80
81
82#ifdef CONFIG_M68000
83 #define CPU "MC68000"
84#endif
85#ifdef CONFIG_M68328
86 #define CPU "MC68328"
87#endif
88#ifdef CONFIG_M68EZ328
89 #define CPU "MC68EZ328"
90#endif
91#ifdef CONFIG_M68VZ328
92 #define CPU "MC68VZ328"
93#endif
94#ifdef CONFIG_M68332
95 #define CPU "MC68332"
96#endif
97#ifdef CONFIG_M68360
98 #define CPU "MC68360"
99#endif
100#if defined(CONFIG_M5206)
101 #define CPU "COLDFIRE(m5206)"
102#endif
103#if defined(CONFIG_M5206e)
104 #define CPU "COLDFIRE(m5206e)"
105#endif
106#if defined(CONFIG_M5249)
107 #define CPU "COLDFIRE(m5249)"
108#endif
109#if defined(CONFIG_M527x)
110 #define CPU "COLDFIRE(m5270/5271/5274/5275)"
111#endif
112#if defined(CONFIG_M5272)
113 #define CPU "COLDFIRE(m5272)"
114#endif
115#if defined(CONFIG_M528x)
116 #define CPU "COLDFIRE(m5280/5282)"
117#endif
118#if defined(CONFIG_M5307)
119 #define CPU "COLDFIRE(m5307)"
120#endif
121#if defined(CONFIG_M5407)
122 #define CPU "COLDFIRE(m5407)"
123#endif
124#ifndef CPU
125 #define CPU "UNKOWN"
126#endif
127
128/* (es) */
129/* note: why is this defined here? the must be a better place to put this */
130#if defined( CONFIG_TELOS) || defined( CONFIG_UCDIMM ) || defined( CONFIG_UCSIMM ) || defined(CONFIG_DRAGEN2) || (defined( CONFIG_PILOT ) && defined( CONFIG_M68328 ))
131#define CAT_ROMARRAY
132#endif
133/* (/es) */
134
135extern int _stext, _etext, _sdata, _edata, _sbss, _ebss, _end;
136extern int _ramstart, _ramend;
137
138void setup_arch(char **cmdline_p)
139{
140 int bootmap_size;
141
142#if defined(CAT_ROMARRAY) && defined(DEBUG)
143 extern int __data_rom_start;
144 extern int __data_start;
145 int *romarray = (int *)((int) &__data_rom_start +
146 (int)&_edata - (int)&__data_start);
147#endif
148
149 memory_start = PAGE_ALIGN(_ramstart);
150 memory_end = _ramend; /* by now the stack is part of the init task */
151
152 init_mm.start_code = (unsigned long) &_stext;
153 init_mm.end_code = (unsigned long) &_etext;
154 init_mm.end_data = (unsigned long) &_edata;
155 init_mm.brk = (unsigned long) 0;
156
157 config_BSP(&command_line[0], sizeof(command_line));
158
159 printk(KERN_INFO "\x0F\r\n\nuClinux/" CPU "\n");
160
161#ifdef CONFIG_UCDIMM
162 printk(KERN_INFO "uCdimm by Lineo, Inc. <www.lineo.com>\n");
163#endif
164#ifdef CONFIG_M68VZ328
165 printk(KERN_INFO "M68VZ328 support by Evan Stawnyczy <e@lineo.ca>\n");
166#endif
167#ifdef CONFIG_COLDFIRE
168 printk(KERN_INFO "COLDFIRE port done by Greg Ungerer, gerg@snapgear.com\n");
169#ifdef CONFIG_M5307
170 printk(KERN_INFO "Modified for M5307 by Dave Miller, dmiller@intellistor.com\n");
171#endif
172#ifdef CONFIG_ELITE
173 printk(KERN_INFO "Modified for M5206eLITE by Rob Scott, rscott@mtrob.fdns.net\n");
174#endif
175#ifdef CONFIG_TELOS
176 printk(KERN_INFO "Modified for Omnia ToolVox by James D. Schettine, james@telos-systems.com\n");
177#endif
178#endif
179 printk(KERN_INFO "Flat model support (C) 1998,1999 Kenneth Albanowski, D. Jeff Dionne\n");
180
181#if defined( CONFIG_PILOT ) && defined( CONFIG_M68328 )
182 printk(KERN_INFO "TRG SuperPilot FLASH card support <info@trgnet.com>\n");
183#endif
184
185#if defined( CONFIG_PILOT ) && defined( CONFIG_M68EZ328 )
186 printk(KERN_INFO "PalmV support by Lineo Inc. <jeff@uclinux.com>\n");
187#endif
188
189#ifdef CONFIG_M68EZ328ADS
190 printk(KERN_INFO "M68EZ328ADS board support (C) 1999 Vladimir Gurevich <vgurevic@cisco.com>\n");
191#endif
192
193#ifdef CONFIG_ALMA_ANS
194 printk(KERN_INFO "Alma Electronics board support (C) 1999 Vladimir Gurevich <vgurevic@cisco.com>\n");
195#endif
196#if defined (CONFIG_M68360)
197 printk(KERN_INFO "QUICC port done by SED Systems <hamilton@sedsystems.ca>,\n");
198 printk(KERN_INFO "based on 2.0.38 port by Lineo Inc. <mleslie@lineo.com>.\n");
199#endif
200#ifdef CONFIG_DRAGEN2
201 printk(KERN_INFO "DragonEngine II board support by Georges Menie\n");
202#endif
203
204#ifdef DEBUG
205 printk(KERN_DEBUG "KERNEL -> TEXT=0x%06x-0x%06x DATA=0x%06x-0x%06x "
206 "BSS=0x%06x-0x%06x\n", (int) &_stext, (int) &_etext,
207 (int) &_sdata, (int) &_edata,
208 (int) &_sbss, (int) &_ebss);
209 printk(KERN_DEBUG "KERNEL -> ROMFS=0x%06x-0x%06x MEM=0x%06x-0x%06x "
210 "STACK=0x%06x-0x%06x\n",
211#ifdef CAT_ROMARRAY
212 (int) romarray, ((int) romarray) + romarray[2],
213#else
214 (int) &_ebss, (int) memory_start,
215#endif
216 (int) memory_start, (int) memory_end,
217 (int) memory_end, (int) _ramend);
218#endif
219
220 /* Keep a copy of command line */
221 *cmdline_p = &command_line[0];
222 memcpy(saved_command_line, command_line, COMMAND_LINE_SIZE);
223 saved_command_line[COMMAND_LINE_SIZE-1] = 0;
224
225#ifdef DEBUG
226 if (strlen(*cmdline_p))
227 printk(KERN_DEBUG "Command line: '%s'\n", *cmdline_p);
228#endif
229
230#if defined(CONFIG_FRAMEBUFFER_CONSOLE) && defined(CONFIG_DUMMY_CONSOLE)
231 conswitchp = &dummy_con;
232#endif
233
234 /*
235 * Give all the memory to the bootmap allocator, tell it to put the
236 * boot mem_map at the start of memory.
237 */
238 bootmap_size = init_bootmem_node(
239 NODE_DATA(0),
240 memory_start >> PAGE_SHIFT, /* map goes here */
241 PAGE_OFFSET >> PAGE_SHIFT, /* 0 on coldfire */
242 memory_end >> PAGE_SHIFT);
243 /*
244 * Free the usable memory, we have to make sure we do not free
245 * the bootmem bitmap so we then reserve it after freeing it :-)
246 */
247 free_bootmem(memory_start, memory_end - memory_start);
248 reserve_bootmem(memory_start, bootmap_size);
249
250 /*
251 * Get kmalloc into gear.
252 */
253 paging_init();
254}
255
256int get_cpuinfo(char * buffer)
257{
258 char *cpu, *mmu, *fpu;
259 u_long clockfreq;
260
261 cpu = CPU;
262 mmu = "none";
263 fpu = "none";
264
265#ifdef CONFIG_COLDFIRE
266 clockfreq = (loops_per_jiffy*HZ)*3;
267#else
268 clockfreq = (loops_per_jiffy*HZ)*16;
269#endif
270
271 return(sprintf(buffer, "CPU:\t\t%s\n"
272 "MMU:\t\t%s\n"
273 "FPU:\t\t%s\n"
274 "Clocking:\t%lu.%1luMHz\n"
275 "BogoMips:\t%lu.%02lu\n"
276 "Calibration:\t%lu loops\n",
277 cpu, mmu, fpu,
278 clockfreq/1000000,(clockfreq/100000)%10,
279 (loops_per_jiffy*HZ)/500000,((loops_per_jiffy*HZ)/5000)%100,
280 (loops_per_jiffy*HZ)));
281
282}
283
284/*
285 * Get CPU information for use by the procfs.
286 */
287
288static int show_cpuinfo(struct seq_file *m, void *v)
289{
290 char *cpu, *mmu, *fpu;
291 u_long clockfreq;
292
293 cpu = CPU;
294 mmu = "none";
295 fpu = "none";
296
297#ifdef CONFIG_COLDFIRE
298 clockfreq = (loops_per_jiffy*HZ)*3;
299#else
300 clockfreq = (loops_per_jiffy*HZ)*16;
301#endif
302
303 seq_printf(m, "CPU:\t\t%s\n"
304 "MMU:\t\t%s\n"
305 "FPU:\t\t%s\n"
306 "Clocking:\t%lu.%1luMHz\n"
307 "BogoMips:\t%lu.%02lu\n"
308 "Calibration:\t%lu loops\n",
309 cpu, mmu, fpu,
310 clockfreq/1000000,(clockfreq/100000)%10,
311 (loops_per_jiffy*HZ)/500000,((loops_per_jiffy*HZ)/5000)%100,
312 (loops_per_jiffy*HZ));
313
314 return 0;
315}
316
317static void *c_start(struct seq_file *m, loff_t *pos)
318{
319 return *pos < NR_CPUS ? ((void *) 0x12345678) : NULL;
320}
321
322static void *c_next(struct seq_file *m, void *v, loff_t *pos)
323{
324 ++*pos;
325 return c_start(m, pos);
326}
327
328static void c_stop(struct seq_file *m, void *v)
329{
330}
331
332struct seq_operations cpuinfo_op = {
333 .start = c_start,
334 .next = c_next,
335 .stop = c_stop,
336 .show = show_cpuinfo,
337};
338
339void arch_gettod(int *year, int *mon, int *day, int *hour,
340 int *min, int *sec)
341{
342 if (mach_gettod)
343 mach_gettod(year, mon, day, hour, min, sec);
344 else
345 *year = *mon = *day = *hour = *min = *sec = 0;
346}
347
diff --git a/arch/m68knommu/kernel/signal.c b/arch/m68knommu/kernel/signal.c
new file mode 100644
index 000000000000..30dceb59a462
--- /dev/null
+++ b/arch/m68knommu/kernel/signal.c
@@ -0,0 +1,788 @@
1/*
2 * linux/arch/m68knommu/kernel/signal.c
3 *
4 * Copyright (C) 1991, 1992 Linus Torvalds
5 *
6 * This file is subject to the terms and conditions of the GNU General Public
7 * License. See the file COPYING in the main directory of this archive
8 * for more details.
9 */
10
11/*
12 * Linux/m68k support by Hamish Macdonald
13 *
14 * 68060 fixes by Jesper Skov
15 *
16 * 1997-12-01 Modified for POSIX.1b signals by Andreas Schwab
17 *
18 * mathemu support by Roman Zippel
19 * (Note: fpstate in the signal context is completely ignored for the emulator
20 * and the internal floating point format is put on stack)
21 */
22
23/*
24 * ++roman (07/09/96): implemented signal stacks (specially for tosemu on
25 * Atari :-) Current limitation: Only one sigstack can be active at one time.
26 * If a second signal with SA_ONSTACK set arrives while working on a sigstack,
27 * SA_ONSTACK is ignored. This behaviour avoids lots of trouble with nested
28 * signal handlers!
29 */
30
31#include <linux/sched.h>
32#include <linux/mm.h>
33#include <linux/kernel.h>
34#include <linux/signal.h>
35#include <linux/syscalls.h>
36#include <linux/errno.h>
37#include <linux/wait.h>
38#include <linux/ptrace.h>
39#include <linux/unistd.h>
40#include <linux/stddef.h>
41#include <linux/highuid.h>
42#include <linux/tty.h>
43#include <linux/personality.h>
44#include <linux/binfmts.h>
45
46#include <asm/setup.h>
47#include <asm/uaccess.h>
48#include <asm/pgtable.h>
49#include <asm/traps.h>
50#include <asm/ucontext.h>
51
52#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
53
54asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs);
55
56/*
57 * Atomically swap in the new signal mask, and wait for a signal.
58 */
59asmlinkage int do_sigsuspend(struct pt_regs *regs)
60{
61 old_sigset_t mask = regs->d3;
62 sigset_t saveset;
63
64 mask &= _BLOCKABLE;
65 spin_lock_irq(&current->sighand->siglock);
66 saveset = current->blocked;
67 siginitset(&current->blocked, mask);
68 recalc_sigpending();
69 spin_unlock_irq(&current->sighand->siglock);
70
71 regs->d0 = -EINTR;
72 while (1) {
73 current->state = TASK_INTERRUPTIBLE;
74 schedule();
75 if (do_signal(&saveset, regs))
76 return -EINTR;
77 }
78}
79
80asmlinkage int
81do_rt_sigsuspend(struct pt_regs *regs)
82{
83 sigset_t *unewset = (sigset_t *)regs->d1;
84 size_t sigsetsize = (size_t)regs->d2;
85 sigset_t saveset, newset;
86
87 /* XXX: Don't preclude handling different sized sigset_t's. */
88 if (sigsetsize != sizeof(sigset_t))
89 return -EINVAL;
90
91 if (copy_from_user(&newset, unewset, sizeof(newset)))
92 return -EFAULT;
93 sigdelsetmask(&newset, ~_BLOCKABLE);
94
95 spin_lock_irq(&current->sighand->siglock);
96 saveset = current->blocked;
97 current->blocked = newset;
98 recalc_sigpending();
99 spin_unlock_irq(&current->sighand->siglock);
100
101 regs->d0 = -EINTR;
102 while (1) {
103 current->state = TASK_INTERRUPTIBLE;
104 schedule();
105 if (do_signal(&saveset, regs))
106 return -EINTR;
107 }
108}
109
110asmlinkage int
111sys_sigaction(int sig, const struct old_sigaction *act,
112 struct old_sigaction *oact)
113{
114 struct k_sigaction new_ka, old_ka;
115 int ret;
116
117 if (act) {
118 old_sigset_t mask;
119 if (!access_ok(VERIFY_READ, act, sizeof(*act)) ||
120 __get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
121 __get_user(new_ka.sa.sa_restorer, &act->sa_restorer))
122 return -EFAULT;
123 __get_user(new_ka.sa.sa_flags, &act->sa_flags);
124 __get_user(mask, &act->sa_mask);
125 siginitset(&new_ka.sa.sa_mask, mask);
126 }
127
128 ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
129
130 if (!ret && oact) {
131 if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) ||
132 __put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
133 __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer))
134 return -EFAULT;
135 __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
136 __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
137 }
138
139 return ret;
140}
141
142asmlinkage int
143sys_sigaltstack(const stack_t *uss, stack_t *uoss)
144{
145 return do_sigaltstack(uss, uoss, rdusp());
146}
147
148
149/*
150 * Do a signal return; undo the signal stack.
151 *
152 * Keep the return code on the stack quadword aligned!
153 * That makes the cache flush below easier.
154 */
155
156struct sigframe
157{
158 char *pretcode;
159 int sig;
160 int code;
161 struct sigcontext *psc;
162 char retcode[8];
163 unsigned long extramask[_NSIG_WORDS-1];
164 struct sigcontext sc;
165};
166
167struct rt_sigframe
168{
169 char *pretcode;
170 int sig;
171 struct siginfo *pinfo;
172 void *puc;
173 char retcode[8];
174 struct siginfo info;
175 struct ucontext uc;
176};
177
178#ifdef CONFIG_FPU
179
180static unsigned char fpu_version = 0; /* version number of fpu, set by setup_frame */
181
182static inline int restore_fpu_state(struct sigcontext *sc)
183{
184 int err = 1;
185
186 if (FPU_IS_EMU) {
187 /* restore registers */
188 memcpy(current->thread.fpcntl, sc->sc_fpcntl, 12);
189 memcpy(current->thread.fp, sc->sc_fpregs, 24);
190 return 0;
191 }
192
193 if (sc->sc_fpstate[0]) {
194 /* Verify the frame format. */
195 if (sc->sc_fpstate[0] != fpu_version)
196 goto out;
197
198 __asm__ volatile (".chip 68k/68881\n\t"
199 "fmovemx %0,%/fp0-%/fp1\n\t"
200 "fmoveml %1,%/fpcr/%/fpsr/%/fpiar\n\t"
201 ".chip 68k"
202 : /* no outputs */
203 : "m" (*sc->sc_fpregs), "m" (*sc->sc_fpcntl));
204 }
205 __asm__ volatile (".chip 68k/68881\n\t"
206 "frestore %0\n\t"
207 ".chip 68k" : : "m" (*sc->sc_fpstate));
208 err = 0;
209
210out:
211 return err;
212}
213
214#define FPCONTEXT_SIZE 216
215#define uc_fpstate uc_filler[0]
216#define uc_formatvec uc_filler[FPCONTEXT_SIZE/4]
217#define uc_extra uc_filler[FPCONTEXT_SIZE/4+1]
218
219static inline int rt_restore_fpu_state(struct ucontext *uc)
220{
221 unsigned char fpstate[FPCONTEXT_SIZE];
222 int context_size = 0;
223 fpregset_t fpregs;
224 int err = 1;
225
226 if (FPU_IS_EMU) {
227 /* restore fpu control register */
228 if (__copy_from_user(current->thread.fpcntl,
229 &uc->uc_mcontext.fpregs.f_pcr, 12))
230 goto out;
231 /* restore all other fpu register */
232 if (__copy_from_user(current->thread.fp,
233 uc->uc_mcontext.fpregs.f_fpregs, 96))
234 goto out;
235 return 0;
236 }
237
238 if (__get_user(*(long *)fpstate, (long *)&uc->uc_fpstate))
239 goto out;
240 if (fpstate[0]) {
241 context_size = fpstate[1];
242
243 /* Verify the frame format. */
244 if (fpstate[0] != fpu_version)
245 goto out;
246 if (__copy_from_user(&fpregs, &uc->uc_mcontext.fpregs,
247 sizeof(fpregs)))
248 goto out;
249 __asm__ volatile (".chip 68k/68881\n\t"
250 "fmovemx %0,%/fp0-%/fp7\n\t"
251 "fmoveml %1,%/fpcr/%/fpsr/%/fpiar\n\t"
252 ".chip 68k"
253 : /* no outputs */
254 : "m" (*fpregs.f_fpregs),
255 "m" (fpregs.f_pcr));
256 }
257 if (context_size &&
258 __copy_from_user(fpstate + 4, (long *)&uc->uc_fpstate + 1,
259 context_size))
260 goto out;
261 __asm__ volatile (".chip 68k/68881\n\t"
262 "frestore %0\n\t"
263 ".chip 68k" : : "m" (*fpstate));
264 err = 0;
265
266out:
267 return err;
268}
269
270#endif
271
272static inline int
273restore_sigcontext(struct pt_regs *regs, struct sigcontext *usc, void *fp,
274 int *pd0)
275{
276 int formatvec;
277 struct sigcontext context;
278 int err = 0;
279
280 /* get previous context */
281 if (copy_from_user(&context, usc, sizeof(context)))
282 goto badframe;
283
284 /* restore passed registers */
285 regs->d1 = context.sc_d1;
286 regs->a0 = context.sc_a0;
287 regs->a1 = context.sc_a1;
288 regs->sr = (regs->sr & 0xff00) | (context.sc_sr & 0xff);
289 regs->pc = context.sc_pc;
290 regs->orig_d0 = -1; /* disable syscall checks */
291 wrusp(context.sc_usp);
292 formatvec = context.sc_formatvec;
293 regs->format = formatvec >> 12;
294 regs->vector = formatvec & 0xfff;
295
296#ifdef CONFIG_FPU
297 err = restore_fpu_state(&context);
298#endif
299
300 *pd0 = context.sc_d0;
301 return err;
302
303badframe:
304 return 1;
305}
306
307static inline int
308rt_restore_ucontext(struct pt_regs *regs, struct switch_stack *sw,
309 struct ucontext *uc, int *pd0)
310{
311 int temp;
312 greg_t *gregs = uc->uc_mcontext.gregs;
313 unsigned long usp;
314 int err;
315
316 err = __get_user(temp, &uc->uc_mcontext.version);
317 if (temp != MCONTEXT_VERSION)
318 goto badframe;
319 /* restore passed registers */
320 err |= __get_user(regs->d0, &gregs[0]);
321 err |= __get_user(regs->d1, &gregs[1]);
322 err |= __get_user(regs->d2, &gregs[2]);
323 err |= __get_user(regs->d3, &gregs[3]);
324 err |= __get_user(regs->d4, &gregs[4]);
325 err |= __get_user(regs->d5, &gregs[5]);
326 err |= __get_user(sw->d6, &gregs[6]);
327 err |= __get_user(sw->d7, &gregs[7]);
328 err |= __get_user(regs->a0, &gregs[8]);
329 err |= __get_user(regs->a1, &gregs[9]);
330 err |= __get_user(regs->a2, &gregs[10]);
331 err |= __get_user(sw->a3, &gregs[11]);
332 err |= __get_user(sw->a4, &gregs[12]);
333 err |= __get_user(sw->a5, &gregs[13]);
334 err |= __get_user(sw->a6, &gregs[14]);
335 err |= __get_user(usp, &gregs[15]);
336 wrusp(usp);
337 err |= __get_user(regs->pc, &gregs[16]);
338 err |= __get_user(temp, &gregs[17]);
339 regs->sr = (regs->sr & 0xff00) | (temp & 0xff);
340 regs->orig_d0 = -1; /* disable syscall checks */
341 regs->format = temp >> 12;
342 regs->vector = temp & 0xfff;
343
344 if (do_sigaltstack(&uc->uc_stack, NULL, usp) == -EFAULT)
345 goto badframe;
346
347 *pd0 = regs->d0;
348 return err;
349
350badframe:
351 return 1;
352}
353
354asmlinkage int do_sigreturn(unsigned long __unused)
355{
356 struct switch_stack *sw = (struct switch_stack *) &__unused;
357 struct pt_regs *regs = (struct pt_regs *) (sw + 1);
358 unsigned long usp = rdusp();
359 struct sigframe *frame = (struct sigframe *)(usp - 4);
360 sigset_t set;
361 int d0;
362
363 if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
364 goto badframe;
365 if (__get_user(set.sig[0], &frame->sc.sc_mask) ||
366 (_NSIG_WORDS > 1 &&
367 __copy_from_user(&set.sig[1], &frame->extramask,
368 sizeof(frame->extramask))))
369 goto badframe;
370
371 sigdelsetmask(&set, ~_BLOCKABLE);
372 spin_lock_irq(&current->sighand->siglock);
373 current->blocked = set;
374 recalc_sigpending();
375 spin_unlock_irq(&current->sighand->siglock);
376
377 if (restore_sigcontext(regs, &frame->sc, frame + 1, &d0))
378 goto badframe;
379 return d0;
380
381badframe:
382 force_sig(SIGSEGV, current);
383 return 0;
384}
385
386asmlinkage int do_rt_sigreturn(unsigned long __unused)
387{
388 struct switch_stack *sw = (struct switch_stack *) &__unused;
389 struct pt_regs *regs = (struct pt_regs *) (sw + 1);
390 unsigned long usp = rdusp();
391 struct rt_sigframe *frame = (struct rt_sigframe *)(usp - 4);
392 sigset_t set;
393 int d0;
394
395 if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
396 goto badframe;
397 if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
398 goto badframe;
399
400 sigdelsetmask(&set, ~_BLOCKABLE);
401 spin_lock_irq(&current->sighand->siglock);
402 current->blocked = set;
403 recalc_sigpending();
404 spin_unlock_irq(&current->sighand->siglock);
405
406 if (rt_restore_ucontext(regs, sw, &frame->uc, &d0))
407 goto badframe;
408 return d0;
409
410badframe:
411 force_sig(SIGSEGV, current);
412 return 0;
413}
414
415#ifdef CONFIG_FPU
416/*
417 * Set up a signal frame.
418 */
419
420static inline void save_fpu_state(struct sigcontext *sc, struct pt_regs *regs)
421{
422 if (FPU_IS_EMU) {
423 /* save registers */
424 memcpy(sc->sc_fpcntl, current->thread.fpcntl, 12);
425 memcpy(sc->sc_fpregs, current->thread.fp, 24);
426 return;
427 }
428
429 __asm__ volatile (".chip 68k/68881\n\t"
430 "fsave %0\n\t"
431 ".chip 68k"
432 : : "m" (*sc->sc_fpstate) : "memory");
433
434 if (sc->sc_fpstate[0]) {
435 fpu_version = sc->sc_fpstate[0];
436 __asm__ volatile (".chip 68k/68881\n\t"
437 "fmovemx %/fp0-%/fp1,%0\n\t"
438 "fmoveml %/fpcr/%/fpsr/%/fpiar,%1\n\t"
439 ".chip 68k"
440 : /* no outputs */
441 : "m" (*sc->sc_fpregs),
442 "m" (*sc->sc_fpcntl)
443 : "memory");
444 }
445}
446
447static inline int rt_save_fpu_state(struct ucontext *uc, struct pt_regs *regs)
448{
449 unsigned char fpstate[FPCONTEXT_SIZE];
450 int context_size = 0;
451 int err = 0;
452
453 if (FPU_IS_EMU) {
454 /* save fpu control register */
455 err |= copy_to_user(&uc->uc_mcontext.fpregs.f_pcr,
456 current->thread.fpcntl, 12);
457 /* save all other fpu register */
458 err |= copy_to_user(uc->uc_mcontext.fpregs.f_fpregs,
459 current->thread.fp, 96);
460 return err;
461 }
462
463 __asm__ volatile (".chip 68k/68881\n\t"
464 "fsave %0\n\t"
465 ".chip 68k"
466 : : "m" (*fpstate) : "memory");
467
468 err |= __put_user(*(long *)fpstate, (long *)&uc->uc_fpstate);
469 if (fpstate[0]) {
470 fpregset_t fpregs;
471 context_size = fpstate[1];
472 fpu_version = fpstate[0];
473 __asm__ volatile (".chip 68k/68881\n\t"
474 "fmovemx %/fp0-%/fp7,%0\n\t"
475 "fmoveml %/fpcr/%/fpsr/%/fpiar,%1\n\t"
476 ".chip 68k"
477 : /* no outputs */
478 : "m" (*fpregs.f_fpregs),
479 "m" (fpregs.f_pcr)
480 : "memory");
481 err |= copy_to_user(&uc->uc_mcontext.fpregs, &fpregs,
482 sizeof(fpregs));
483 }
484 if (context_size)
485 err |= copy_to_user((long *)&uc->uc_fpstate + 1, fpstate + 4,
486 context_size);
487 return err;
488}
489
490#endif
491
492static void setup_sigcontext(struct sigcontext *sc, struct pt_regs *regs,
493 unsigned long mask)
494{
495 sc->sc_mask = mask;
496 sc->sc_usp = rdusp();
497 sc->sc_d0 = regs->d0;
498 sc->sc_d1 = regs->d1;
499 sc->sc_a0 = regs->a0;
500 sc->sc_a1 = regs->a1;
501 sc->sc_sr = regs->sr;
502 sc->sc_pc = regs->pc;
503 sc->sc_formatvec = regs->format << 12 | regs->vector;
504#ifdef CONFIG_FPU
505 save_fpu_state(sc, regs);
506#endif
507}
508
509static inline int rt_setup_ucontext(struct ucontext *uc, struct pt_regs *regs)
510{
511 struct switch_stack *sw = (struct switch_stack *)regs - 1;
512 greg_t *gregs = uc->uc_mcontext.gregs;
513 int err = 0;
514
515 err |= __put_user(MCONTEXT_VERSION, &uc->uc_mcontext.version);
516 err |= __put_user(regs->d0, &gregs[0]);
517 err |= __put_user(regs->d1, &gregs[1]);
518 err |= __put_user(regs->d2, &gregs[2]);
519 err |= __put_user(regs->d3, &gregs[3]);
520 err |= __put_user(regs->d4, &gregs[4]);
521 err |= __put_user(regs->d5, &gregs[5]);
522 err |= __put_user(sw->d6, &gregs[6]);
523 err |= __put_user(sw->d7, &gregs[7]);
524 err |= __put_user(regs->a0, &gregs[8]);
525 err |= __put_user(regs->a1, &gregs[9]);
526 err |= __put_user(regs->a2, &gregs[10]);
527 err |= __put_user(sw->a3, &gregs[11]);
528 err |= __put_user(sw->a4, &gregs[12]);
529 err |= __put_user(sw->a5, &gregs[13]);
530 err |= __put_user(sw->a6, &gregs[14]);
531 err |= __put_user(rdusp(), &gregs[15]);
532 err |= __put_user(regs->pc, &gregs[16]);
533 err |= __put_user(regs->sr, &gregs[17]);
534#ifdef CONFIG_FPU
535 err |= rt_save_fpu_state(uc, regs);
536#endif
537 return err;
538}
539
540static inline void push_cache (unsigned long vaddr)
541{
542}
543
544static inline void *
545get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size)
546{
547 unsigned long usp;
548
549 /* Default to using normal stack. */
550 usp = rdusp();
551
552 /* This is the X/Open sanctioned signal stack switching. */
553 if (ka->sa.sa_flags & SA_ONSTACK) {
554 if (!on_sig_stack(usp))
555 usp = current->sas_ss_sp + current->sas_ss_size;
556 }
557 return (void *)((usp - frame_size) & -8UL);
558}
559
560static void setup_frame (int sig, struct k_sigaction *ka,
561 sigset_t *set, struct pt_regs *regs)
562{
563 struct sigframe *frame;
564 struct sigcontext context;
565 int err = 0;
566
567 frame = get_sigframe(ka, regs, sizeof(*frame));
568
569 err |= __put_user((current_thread_info()->exec_domain
570 && current_thread_info()->exec_domain->signal_invmap
571 && sig < 32
572 ? current_thread_info()->exec_domain->signal_invmap[sig]
573 : sig),
574 &frame->sig);
575
576 err |= __put_user(regs->vector, &frame->code);
577 err |= __put_user(&frame->sc, &frame->psc);
578
579 if (_NSIG_WORDS > 1)
580 err |= copy_to_user(frame->extramask, &set->sig[1],
581 sizeof(frame->extramask));
582
583 setup_sigcontext(&context, regs, set->sig[0]);
584 err |= copy_to_user (&frame->sc, &context, sizeof(context));
585
586 /* Set up to return from userspace. */
587 err |= __put_user(frame->retcode, &frame->pretcode);
588 /* moveq #,d0; trap #0 */
589 err |= __put_user(0x70004e40 + (__NR_sigreturn << 16),
590 (long *)(frame->retcode));
591
592 if (err)
593 goto give_sigsegv;
594
595 push_cache ((unsigned long) &frame->retcode);
596
597 /* Set up registers for signal handler */
598 wrusp ((unsigned long) frame);
599 regs->pc = (unsigned long) ka->sa.sa_handler;
600
601adjust_stack:
602 /* Prepare to skip over the extra stuff in the exception frame. */
603 if (regs->stkadj) {
604 struct pt_regs *tregs =
605 (struct pt_regs *)((ulong)regs + regs->stkadj);
606#if DEBUG
607 printk(KERN_DEBUG "Performing stackadjust=%04x\n", regs->stkadj);
608#endif
609 /* This must be copied with decreasing addresses to
610 handle overlaps. */
611 tregs->vector = 0;
612 tregs->format = 0;
613 tregs->pc = regs->pc;
614 tregs->sr = regs->sr;
615 }
616 return;
617
618give_sigsegv:
619 force_sigsegv(sig, current);
620 goto adjust_stack;
621}
622
623static void setup_rt_frame (int sig, struct k_sigaction *ka, siginfo_t *info,
624 sigset_t *set, struct pt_regs *regs)
625{
626 struct rt_sigframe *frame;
627 int err = 0;
628
629 frame = get_sigframe(ka, regs, sizeof(*frame));
630
631 err |= __put_user((current_thread_info()->exec_domain
632 && current_thread_info()->exec_domain->signal_invmap
633 && sig < 32
634 ? current_thread_info()->exec_domain->signal_invmap[sig]
635 : sig),
636 &frame->sig);
637 err |= __put_user(&frame->info, &frame->pinfo);
638 err |= __put_user(&frame->uc, &frame->puc);
639 err |= copy_siginfo_to_user(&frame->info, info);
640
641 /* Create the ucontext. */
642 err |= __put_user(0, &frame->uc.uc_flags);
643 err |= __put_user(0, &frame->uc.uc_link);
644 err |= __put_user((void *)current->sas_ss_sp,
645 &frame->uc.uc_stack.ss_sp);
646 err |= __put_user(sas_ss_flags(rdusp()),
647 &frame->uc.uc_stack.ss_flags);
648 err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
649 err |= rt_setup_ucontext(&frame->uc, regs);
650 err |= copy_to_user (&frame->uc.uc_sigmask, set, sizeof(*set));
651
652 /* Set up to return from userspace. */
653 err |= __put_user(frame->retcode, &frame->pretcode);
654 /* moveq #,d0; notb d0; trap #0 */
655 err |= __put_user(0x70004600 + ((__NR_rt_sigreturn ^ 0xff) << 16),
656 (long *)(frame->retcode + 0));
657 err |= __put_user(0x4e40, (short *)(frame->retcode + 4));
658
659 if (err)
660 goto give_sigsegv;
661
662 push_cache ((unsigned long) &frame->retcode);
663
664 /* Set up registers for signal handler */
665 wrusp ((unsigned long) frame);
666 regs->pc = (unsigned long) ka->sa.sa_handler;
667
668adjust_stack:
669 /* Prepare to skip over the extra stuff in the exception frame. */
670 if (regs->stkadj) {
671 struct pt_regs *tregs =
672 (struct pt_regs *)((ulong)regs + regs->stkadj);
673#if DEBUG
674 printk(KERN_DEBUG "Performing stackadjust=%04x\n", regs->stkadj);
675#endif
676 /* This must be copied with decreasing addresses to
677 handle overlaps. */
678 tregs->vector = 0;
679 tregs->format = 0;
680 tregs->pc = regs->pc;
681 tregs->sr = regs->sr;
682 }
683 return;
684
685give_sigsegv:
686 force_sigsegv(sig, current);
687 goto adjust_stack;
688}
689
690static inline void
691handle_restart(struct pt_regs *regs, struct k_sigaction *ka, int has_handler)
692{
693 switch (regs->d0) {
694 case -ERESTARTNOHAND:
695 if (!has_handler)
696 goto do_restart;
697 regs->d0 = -EINTR;
698 break;
699
700 case -ERESTARTSYS:
701 if (has_handler && !(ka->sa.sa_flags & SA_RESTART)) {
702 regs->d0 = -EINTR;
703 break;
704 }
705 /* fallthrough */
706 case -ERESTARTNOINTR:
707 do_restart:
708 regs->d0 = regs->orig_d0;
709 regs->pc -= 2;
710 break;
711 }
712}
713
714/*
715 * OK, we're invoking a handler
716 */
717static void
718handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info,
719 sigset_t *oldset, struct pt_regs *regs)
720{
721 /* are we from a system call? */
722 if (regs->orig_d0 >= 0)
723 /* If so, check system call restarting.. */
724 handle_restart(regs, ka, 1);
725
726 /* set up the stack frame */
727 if (ka->sa.sa_flags & SA_SIGINFO)
728 setup_rt_frame(sig, ka, info, oldset, regs);
729 else
730 setup_frame(sig, ka, oldset, regs);
731
732 if (ka->sa.sa_flags & SA_ONESHOT)
733 ka->sa.sa_handler = SIG_DFL;
734
735 if (!(ka->sa.sa_flags & SA_NODEFER)) {
736 spin_lock_irq(&current->sighand->siglock);
737 sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
738 sigaddset(&current->blocked,sig);
739 recalc_sigpending();
740 spin_unlock_irq(&current->sighand->siglock);
741 }
742}
743
744/*
745 * Note that 'init' is a special process: it doesn't get signals it doesn't
746 * want to handle. Thus you cannot kill init even with a SIGKILL even by
747 * mistake.
748 */
749asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs)
750{
751 struct k_sigaction ka;
752 siginfo_t info;
753 int signr;
754
755 /*
756 * We want the common case to go fast, which
757 * is why we may in certain cases get here from
758 * kernel mode. Just return without doing anything
759 * if so.
760 */
761 if (!user_mode(regs))
762 return 1;
763
764 if (!oldset)
765 oldset = &current->blocked;
766
767 signr = get_signal_to_deliver(&info, &ka, regs, NULL);
768 if (signr > 0) {
769 /* Whee! Actually deliver the signal. */
770 handle_signal(signr, &ka, &info, oldset, regs);
771 return 1;
772 }
773
774 /* Did we come from a system call? */
775 if (regs->orig_d0 >= 0) {
776 /* Restart the system call - no handlers present */
777 if (regs->d0 == -ERESTARTNOHAND
778 || regs->d0 == -ERESTARTSYS
779 || regs->d0 == -ERESTARTNOINTR) {
780 regs->d0 = regs->orig_d0;
781 regs->pc -= 2;
782 } else if (regs->d0 == -ERESTART_RESTARTBLOCK) {
783 regs->d0 = __NR_restart_syscall;
784 regs->pc -= 2;
785 }
786 }
787 return 0;
788}
diff --git a/arch/m68knommu/kernel/sys_m68k.c b/arch/m68knommu/kernel/sys_m68k.c
new file mode 100644
index 000000000000..d87e1e0a1336
--- /dev/null
+++ b/arch/m68knommu/kernel/sys_m68k.c
@@ -0,0 +1,208 @@
1/*
2 * linux/arch/m68knommu/kernel/sys_m68k.c
3 *
4 * This file contains various random system calls that
5 * have a non-standard calling sequence on the Linux/m68k
6 * platform.
7 */
8
9#include <linux/errno.h>
10#include <linux/sched.h>
11#include <linux/mm.h>
12#include <linux/smp.h>
13#include <linux/smp_lock.h>
14#include <linux/sem.h>
15#include <linux/msg.h>
16#include <linux/shm.h>
17#include <linux/stat.h>
18#include <linux/syscalls.h>
19#include <linux/mman.h>
20#include <linux/file.h>
21#include <linux/utsname.h>
22
23#include <asm/setup.h>
24#include <asm/uaccess.h>
25#include <asm/cachectl.h>
26#include <asm/traps.h>
27#include <asm/ipc.h>
28#include <asm/cacheflush.h>
29
30/*
31 * sys_pipe() is the normal C calling standard for creating
32 * a pipe. It's not the way unix traditionally does this, though.
33 */
34asmlinkage int sys_pipe(unsigned long * fildes)
35{
36 int fd[2];
37 int error;
38
39 error = do_pipe(fd);
40 if (!error) {
41 if (copy_to_user(fildes, fd, 2*sizeof(int)))
42 error = -EFAULT;
43 }
44 return error;
45}
46
47/* common code for old and new mmaps */
48static inline long do_mmap2(
49 unsigned long addr, unsigned long len,
50 unsigned long prot, unsigned long flags,
51 unsigned long fd, unsigned long pgoff)
52{
53 int error = -EBADF;
54 struct file * file = NULL;
55
56 flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
57 if (!(flags & MAP_ANONYMOUS)) {
58 file = fget(fd);
59 if (!file)
60 goto out;
61 }
62
63 down_write(&current->mm->mmap_sem);
64 error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
65 up_write(&current->mm->mmap_sem);
66
67 if (file)
68 fput(file);
69out:
70 return error;
71}
72
73asmlinkage long sys_mmap2(unsigned long addr, unsigned long len,
74 unsigned long prot, unsigned long flags,
75 unsigned long fd, unsigned long pgoff)
76{
77 return do_mmap2(addr, len, prot, flags, fd, pgoff);
78}
79
80/*
81 * Perform the select(nd, in, out, ex, tv) and mmap() system
82 * calls. Linux/m68k cloned Linux/i386, which didn't use to be able to
83 * handle more than 4 system call parameters, so these system calls
84 * used a memory block for parameter passing..
85 */
86
87struct mmap_arg_struct {
88 unsigned long addr;
89 unsigned long len;
90 unsigned long prot;
91 unsigned long flags;
92 unsigned long fd;
93 unsigned long offset;
94};
95
96asmlinkage int old_mmap(struct mmap_arg_struct *arg)
97{
98 struct mmap_arg_struct a;
99 int error = -EFAULT;
100
101 if (copy_from_user(&a, arg, sizeof(a)))
102 goto out;
103
104 error = -EINVAL;
105 if (a.offset & ~PAGE_MASK)
106 goto out;
107
108 a.flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
109
110 error = do_mmap2(a.addr, a.len, a.prot, a.flags, a.fd, a.offset >> PAGE_SHIFT);
111out:
112 return error;
113}
114
115struct sel_arg_struct {
116 unsigned long n;
117 fd_set *inp, *outp, *exp;
118 struct timeval *tvp;
119};
120
121asmlinkage int old_select(struct sel_arg_struct *arg)
122{
123 struct sel_arg_struct a;
124
125 if (copy_from_user(&a, arg, sizeof(a)))
126 return -EFAULT;
127 /* sys_select() does the appropriate kernel locking */
128 return sys_select(a.n, a.inp, a.outp, a.exp, a.tvp);
129}
130
131/*
132 * sys_ipc() is the de-multiplexer for the SysV IPC calls..
133 *
134 * This is really horribly ugly.
135 */
136asmlinkage int sys_ipc (uint call, int first, int second,
137 int third, void *ptr, long fifth)
138{
139 int version;
140
141 version = call >> 16; /* hack for backward compatibility */
142 call &= 0xffff;
143
144 if (call <= SEMCTL)
145 switch (call) {
146 case SEMOP:
147 return sys_semop (first, (struct sembuf *)ptr, second);
148 case SEMGET:
149 return sys_semget (first, second, third);
150 case SEMCTL: {
151 union semun fourth;
152 if (!ptr)
153 return -EINVAL;
154 if (get_user(fourth.__pad, (void **) ptr))
155 return -EFAULT;
156 return sys_semctl (first, second, third, fourth);
157 }
158 default:
159 return -EINVAL;
160 }
161 if (call <= MSGCTL)
162 switch (call) {
163 case MSGSND:
164 return sys_msgsnd (first, (struct msgbuf *) ptr,
165 second, third);
166 case MSGRCV:
167 switch (version) {
168 case 0: {
169 struct ipc_kludge tmp;
170 if (!ptr)
171 return -EINVAL;
172 if (copy_from_user (&tmp,
173 (struct ipc_kludge *)ptr,
174 sizeof (tmp)))
175 return -EFAULT;
176 return sys_msgrcv (first, tmp.msgp, second,
177 tmp.msgtyp, third);
178 }
179 default:
180 return sys_msgrcv (first,
181 (struct msgbuf *) ptr,
182 second, fifth, third);
183 }
184 case MSGGET:
185 return sys_msgget ((key_t) first, second);
186 case MSGCTL:
187 return sys_msgctl (first, second,
188 (struct msqid_ds *) ptr);
189 default:
190 return -EINVAL;
191 }
192
193 return -EINVAL;
194}
195
196/* sys_cacheflush -- flush (part of) the processor cache. */
197asmlinkage int
198sys_cacheflush (unsigned long addr, int scope, int cache, unsigned long len)
199{
200 flush_cache_all();
201 return(0);
202}
203
204asmlinkage int sys_getpagesize(void)
205{
206 return PAGE_SIZE;
207}
208
diff --git a/arch/m68knommu/kernel/syscalltable.S b/arch/m68knommu/kernel/syscalltable.S
new file mode 100644
index 000000000000..897deaa06b01
--- /dev/null
+++ b/arch/m68knommu/kernel/syscalltable.S
@@ -0,0 +1,308 @@
1/*
2 * linux/arch/m68knommu/kernel/syscalltable.S
3 *
4 * Copyright (C) 2002, Greg Ungerer (gerg@snapgear.com)
5 *
6 * Based on older entry.S files, the following copyrights apply:
7 *
8 * Copyright (C) 1998 D. Jeff Dionne <jeff@lineo.ca>,
9 * Kenneth Albanowski <kjahds@kjahds.com>,
10 * Copyright (C) 2000 Lineo Inc. (www.lineo.com)
11 * Copyright (C) 1991, 1992 Linus Torvalds
12 */
13
14#include <linux/config.h>
15#include <linux/sys.h>
16#include <linux/linkage.h>
17#include <asm/unistd.h>
18
19.text
20ALIGN
21ENTRY(sys_call_table)
22 .long sys_ni_syscall /* 0 - old "setup()" system call*/
23 .long sys_exit
24 .long sys_fork
25 .long sys_read
26 .long sys_write
27 .long sys_open /* 5 */
28 .long sys_close
29 .long sys_waitpid
30 .long sys_creat
31 .long sys_link
32 .long sys_unlink /* 10 */
33 .long sys_execve
34 .long sys_chdir
35 .long sys_time
36 .long sys_mknod
37 .long sys_chmod /* 15 */
38 .long sys_chown16
39 .long sys_ni_syscall /* old break syscall holder */
40 .long sys_stat
41 .long sys_lseek
42 .long sys_getpid /* 20 */
43 .long sys_mount
44 .long sys_oldumount
45 .long sys_setuid16
46 .long sys_getuid16
47 .long sys_stime /* 25 */
48 .long sys_ptrace
49 .long sys_alarm
50 .long sys_fstat
51 .long sys_pause
52 .long sys_utime /* 30 */
53 .long sys_ni_syscall /* old stty syscall holder */
54 .long sys_ni_syscall /* old gtty syscall holder */
55 .long sys_access
56 .long sys_nice
57 .long sys_ni_syscall /* 35 */ /* old ftime syscall holder */
58 .long sys_sync
59 .long sys_kill
60 .long sys_rename
61 .long sys_mkdir
62 .long sys_rmdir /* 40 */
63 .long sys_dup
64 .long sys_pipe
65 .long sys_times
66 .long sys_ni_syscall /* old prof syscall holder */
67 .long sys_brk /* 45 */
68 .long sys_setgid16
69 .long sys_getgid16
70 .long sys_signal
71 .long sys_geteuid16
72 .long sys_getegid16 /* 50 */
73 .long sys_acct
74 .long sys_umount /* recycled never used phys() */
75 .long sys_ni_syscall /* old lock syscall holder */
76 .long sys_ioctl
77 .long sys_fcntl /* 55 */
78 .long sys_ni_syscall /* old mpx syscall holder */
79 .long sys_setpgid
80 .long sys_ni_syscall /* old ulimit syscall holder */
81 .long sys_ni_syscall
82 .long sys_umask /* 60 */
83 .long sys_chroot
84 .long sys_ustat
85 .long sys_dup2
86 .long sys_getppid
87 .long sys_getpgrp /* 65 */
88 .long sys_setsid
89 .long sys_sigaction
90 .long sys_sgetmask
91 .long sys_ssetmask
92 .long sys_setreuid16 /* 70 */
93 .long sys_setregid16
94 .long sys_sigsuspend
95 .long sys_sigpending
96 .long sys_sethostname
97 .long sys_setrlimit /* 75 */
98 .long sys_old_getrlimit
99 .long sys_getrusage
100 .long sys_gettimeofday
101 .long sys_settimeofday
102 .long sys_getgroups16 /* 80 */
103 .long sys_setgroups16
104 .long old_select
105 .long sys_symlink
106 .long sys_lstat
107 .long sys_readlink /* 85 */
108 .long sys_uselib
109 .long sys_ni_syscall /* sys_swapon */
110 .long sys_reboot
111 .long old_readdir
112 .long old_mmap /* 90 */
113 .long sys_munmap
114 .long sys_truncate
115 .long sys_ftruncate
116 .long sys_fchmod
117 .long sys_fchown16 /* 95 */
118 .long sys_getpriority
119 .long sys_setpriority
120 .long sys_ni_syscall /* old profil syscall holder */
121 .long sys_statfs
122 .long sys_fstatfs /* 100 */
123 .long sys_ni_syscall /* ioperm for i386 */
124 .long sys_socketcall
125 .long sys_syslog
126 .long sys_setitimer
127 .long sys_getitimer /* 105 */
128 .long sys_newstat
129 .long sys_newlstat
130 .long sys_newfstat
131 .long sys_ni_syscall
132 .long sys_ni_syscall /* iopl for i386 */ /* 110 */
133 .long sys_vhangup
134 .long sys_ni_syscall /* obsolete idle() syscall */
135 .long sys_ni_syscall /* vm86old for i386 */
136 .long sys_wait4
137 .long sys_ni_syscall /* 115 */ /* sys_swapoff */
138 .long sys_sysinfo
139 .long sys_ipc
140 .long sys_fsync
141 .long sys_sigreturn
142 .long sys_clone /* 120 */
143 .long sys_setdomainname
144 .long sys_newuname
145 .long sys_cacheflush /* modify_ldt for i386 */
146 .long sys_adjtimex
147 .long sys_ni_syscall /* 125 */ /* sys_mprotect */
148 .long sys_sigprocmask
149 .long sys_ni_syscall /* old "creat_module" */
150 .long sys_init_module
151 .long sys_delete_module
152 .long sys_ni_syscall /* 130: old "get_kernel_syms" */
153 .long sys_quotactl
154 .long sys_getpgid
155 .long sys_fchdir
156 .long sys_bdflush
157 .long sys_sysfs /* 135 */
158 .long sys_personality
159 .long sys_ni_syscall /* for afs_syscall */
160 .long sys_setfsuid16
161 .long sys_setfsgid16
162 .long sys_llseek /* 140 */
163 .long sys_getdents
164 .long sys_select
165 .long sys_flock
166 .long sys_ni_syscall /* sys_msync */
167 .long sys_readv /* 145 */
168 .long sys_writev
169 .long sys_getsid
170 .long sys_fdatasync
171 .long sys_sysctl
172 .long sys_ni_syscall /* 150 */ /* sys_mlock */
173 .long sys_ni_syscall /* sys_munlock */
174 .long sys_ni_syscall /* sys_mlockall */
175 .long sys_ni_syscall /* sys_munlockall */
176 .long sys_sched_setparam
177 .long sys_sched_getparam /* 155 */
178 .long sys_sched_setscheduler
179 .long sys_sched_getscheduler
180 .long sys_sched_yield
181 .long sys_sched_get_priority_max
182 .long sys_sched_get_priority_min /* 160 */
183 .long sys_sched_rr_get_interval
184 .long sys_nanosleep
185 .long sys_ni_syscall /* sys_mremap */
186 .long sys_setresuid16
187 .long sys_getresuid16 /* 165 */
188 .long sys_getpagesize /* sys_getpagesize */
189 .long sys_ni_syscall /* old "query_module" */
190 .long sys_poll
191 .long sys_ni_syscall /* sys_nfsservctl */
192 .long sys_setresgid16 /* 170 */
193 .long sys_getresgid16
194 .long sys_prctl
195 .long sys_rt_sigreturn
196 .long sys_rt_sigaction
197 .long sys_rt_sigprocmask /* 175 */
198 .long sys_rt_sigpending
199 .long sys_rt_sigtimedwait
200 .long sys_rt_sigqueueinfo
201 .long sys_rt_sigsuspend
202 .long sys_pread64 /* 180 */
203 .long sys_pwrite64
204 .long sys_lchown16
205 .long sys_getcwd
206 .long sys_capget
207 .long sys_capset /* 185 */
208 .long sys_sigaltstack
209 .long sys_sendfile
210 .long sys_ni_syscall /* streams1 */
211 .long sys_ni_syscall /* streams2 */
212 .long sys_vfork /* 190 */
213 .long sys_getrlimit
214 .long sys_mmap2
215 .long sys_truncate64
216 .long sys_ftruncate64
217 .long sys_stat64 /* 195 */
218 .long sys_lstat64
219 .long sys_fstat64
220 .long sys_chown
221 .long sys_getuid
222 .long sys_getgid /* 200 */
223 .long sys_geteuid
224 .long sys_getegid
225 .long sys_setreuid
226 .long sys_setregid
227 .long sys_getgroups /* 205 */
228 .long sys_setgroups
229 .long sys_fchown
230 .long sys_setresuid
231 .long sys_getresuid
232 .long sys_setresgid /* 210 */
233 .long sys_getresgid
234 .long sys_lchown
235 .long sys_setuid
236 .long sys_setgid
237 .long sys_setfsuid /* 215 */
238 .long sys_setfsgid
239 .long sys_pivot_root
240 .long sys_ni_syscall
241 .long sys_ni_syscall
242 .long sys_getdents64 /* 220 */
243 .long sys_gettid
244 .long sys_tkill
245 .long sys_setxattr
246 .long sys_lsetxattr
247 .long sys_fsetxattr /* 225 */
248 .long sys_getxattr
249 .long sys_lgetxattr
250 .long sys_fgetxattr
251 .long sys_listxattr
252 .long sys_llistxattr /* 230 */
253 .long sys_flistxattr
254 .long sys_removexattr
255 .long sys_lremovexattr
256 .long sys_fremovexattr
257 .long sys_futex /* 235 */
258 .long sys_sendfile64
259 .long sys_ni_syscall /* sys_mincore */
260 .long sys_ni_syscall /* sys_madvise */
261 .long sys_fcntl64
262 .long sys_readahead /* 240 */
263 .long sys_io_setup
264 .long sys_io_destroy
265 .long sys_io_getevents
266 .long sys_io_submit
267 .long sys_io_cancel /* 245 */
268 .long sys_fadvise64
269 .long sys_exit_group
270 .long sys_lookup_dcookie
271 .long sys_epoll_create
272 .long sys_epoll_ctl /* 250 */
273 .long sys_epoll_wait
274 .long sys_ni_syscall /* sys_remap_file_pages */
275 .long sys_set_tid_address
276 .long sys_timer_create
277 .long sys_timer_settime /* 255 */
278 .long sys_timer_gettime
279 .long sys_timer_getoverrun
280 .long sys_timer_delete
281 .long sys_clock_settime
282 .long sys_clock_gettime /* 260 */
283 .long sys_clock_getres
284 .long sys_clock_nanosleep
285 .long sys_statfs64
286 .long sys_fstatfs64
287 .long sys_tgkill /* 265 */
288 .long sys_utimes
289 .long sys_fadvise64_64
290 .long sys_mbind
291 .long sys_get_mempolicy
292 .long sys_set_mempolicy /* 270 */
293 .long sys_mq_open
294 .long sys_mq_unlink
295 .long sys_mq_timedsend
296 .long sys_mq_timedreceive
297 .long sys_mq_notify /* 275 */
298 .long sys_mq_getsetattr
299 .long sys_waitid
300 .long sys_ni_syscall /* sys_setaltroot */
301 .long sys_ni_syscall /* sys_add_key */
302 .long sys_ni_syscall /* 280 */ /* sys_request_key */
303 .long sys_ni_syscall /* sys_keyctl */
304
305 .rept NR_syscalls-(.-sys_call_table)/4
306 .long sys_ni_syscall
307 .endr
308
diff --git a/arch/m68knommu/kernel/time.c b/arch/m68knommu/kernel/time.c
new file mode 100644
index 000000000000..5c3ca671627c
--- /dev/null
+++ b/arch/m68knommu/kernel/time.c
@@ -0,0 +1,198 @@
1/*
2 * linux/arch/m68knommu/kernel/time.c
3 *
4 * Copyright (C) 1991, 1992, 1995 Linus Torvalds
5 *
6 * This file contains the m68k-specific time handling details.
7 * Most of the stuff is located in the machine specific files.
8 *
9 * 1997-09-10 Updated NTP code according to technical memorandum Jan '96
10 * "A Kernel Model for Precision Timekeeping" by Dave Mills
11 */
12
13#include <linux/config.h>
14#include <linux/errno.h>
15#include <linux/module.h>
16#include <linux/sched.h>
17#include <linux/kernel.h>
18#include <linux/param.h>
19#include <linux/string.h>
20#include <linux/mm.h>
21#include <linux/profile.h>
22#include <linux/time.h>
23#include <linux/timex.h>
24
25#include <asm/machdep.h>
26#include <asm/io.h>
27
28#define TICK_SIZE (tick_nsec / 1000)
29
30u64 jiffies_64 = INITIAL_JIFFIES;
31
32EXPORT_SYMBOL(jiffies_64);
33
34extern unsigned long wall_jiffies;
35
36
37static inline int set_rtc_mmss(unsigned long nowtime)
38{
39 if (mach_set_clock_mmss)
40 return mach_set_clock_mmss (nowtime);
41 return -1;
42}
43
44/*
45 * timer_interrupt() needs to keep up the real-time clock,
46 * as well as call the "do_timer()" routine every clocktick
47 */
48static irqreturn_t timer_interrupt(int irq, void *dummy, struct pt_regs * regs)
49{
50 /* last time the cmos clock got updated */
51 static long last_rtc_update=0;
52
53 /* may need to kick the hardware timer */
54 if (mach_tick)
55 mach_tick();
56
57 write_seqlock(&xtime_lock);
58
59 do_timer(regs);
60#ifndef CONFIG_SMP
61 update_process_times(user_mode(regs));
62#endif
63 if (current->pid)
64 profile_tick(CPU_PROFILING, regs);
65
66 /*
67 * If we have an externally synchronized Linux clock, then update
68 * CMOS clock accordingly every ~11 minutes. Set_rtc_mmss() has to be
69 * called as close as possible to 500 ms before the new second starts.
70 */
71 if ((time_status & STA_UNSYNC) == 0 &&
72 xtime.tv_sec > last_rtc_update + 660 &&
73 (xtime.tv_nsec / 1000) >= 500000 - ((unsigned) TICK_SIZE) / 2 &&
74 (xtime.tv_nsec / 1000) <= 500000 + ((unsigned) TICK_SIZE) / 2) {
75 if (set_rtc_mmss(xtime.tv_sec) == 0)
76 last_rtc_update = xtime.tv_sec;
77 else
78 last_rtc_update = xtime.tv_sec - 600; /* do it again in 60 s */
79 }
80#ifdef CONFIG_HEARTBEAT
81 /* use power LED as a heartbeat instead -- much more useful
82 for debugging -- based on the version for PReP by Cort */
83 /* acts like an actual heart beat -- ie thump-thump-pause... */
84 if (mach_heartbeat) {
85 static unsigned cnt = 0, period = 0, dist = 0;
86
87 if (cnt == 0 || cnt == dist)
88 mach_heartbeat( 1 );
89 else if (cnt == 7 || cnt == dist+7)
90 mach_heartbeat( 0 );
91
92 if (++cnt > period) {
93 cnt = 0;
94 /* The hyperbolic function below modifies the heartbeat period
95 * length in dependency of the current (5min) load. It goes
96 * through the points f(0)=126, f(1)=86, f(5)=51,
97 * f(inf)->30. */
98 period = ((672<<FSHIFT)/(5*avenrun[0]+(7<<FSHIFT))) + 30;
99 dist = period / 4;
100 }
101 }
102#endif /* CONFIG_HEARTBEAT */
103
104 write_sequnlock(&xtime_lock);
105 return(IRQ_HANDLED);
106}
107
108void time_init(void)
109{
110 unsigned int year, mon, day, hour, min, sec;
111
112 extern void arch_gettod(int *year, int *mon, int *day, int *hour,
113 int *min, int *sec);
114
115 arch_gettod(&year, &mon, &day, &hour, &min, &sec);
116
117 if ((year += 1900) < 1970)
118 year += 100;
119 xtime.tv_sec = mktime(year, mon, day, hour, min, sec);
120 xtime.tv_nsec = 0;
121 wall_to_monotonic.tv_sec = -xtime.tv_sec;
122
123 mach_sched_init(timer_interrupt);
124}
125
126/*
127 * This version of gettimeofday has near microsecond resolution.
128 */
129void do_gettimeofday(struct timeval *tv)
130{
131 unsigned long flags;
132 unsigned long lost, seq;
133 unsigned long usec, sec;
134
135 do {
136 seq = read_seqbegin_irqsave(&xtime_lock, flags);
137 usec = mach_gettimeoffset ? mach_gettimeoffset() : 0;
138 lost = jiffies - wall_jiffies;
139 if (lost)
140 usec += lost * (1000000 / HZ);
141 sec = xtime.tv_sec;
142 usec += (xtime.tv_nsec / 1000);
143 } while (read_seqretry_irqrestore(&xtime_lock, seq, flags));
144
145 while (usec >= 1000000) {
146 usec -= 1000000;
147 sec++;
148 }
149
150 tv->tv_sec = sec;
151 tv->tv_usec = usec;
152}
153
154EXPORT_SYMBOL(do_gettimeofday);
155
156int do_settimeofday(struct timespec *tv)
157{
158 time_t wtm_sec, sec = tv->tv_sec;
159 long wtm_nsec, nsec = tv->tv_nsec;
160
161 if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC)
162 return -EINVAL;
163
164 write_seqlock_irq(&xtime_lock);
165 /*
166 * This is revolting. We need to set the xtime.tv_usec
167 * correctly. However, the value in this location is
168 * is value at the last tick.
169 * Discover what correction gettimeofday
170 * would have done, and then undo it!
171 */
172 if (mach_gettimeoffset)
173 nsec -= (mach_gettimeoffset() * 1000);
174
175 wtm_sec = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec);
176 wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec);
177
178 set_normalized_timespec(&xtime, sec, nsec);
179 set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
180
181 time_adjust = 0; /* stop active adjtime() */
182 time_status |= STA_UNSYNC;
183 time_maxerror = NTP_PHASE_LIMIT;
184 time_esterror = NTP_PHASE_LIMIT;
185 write_sequnlock_irq(&xtime_lock);
186 clock_was_set();
187 return 0;
188}
189
190/*
191 * Scheduler clock - returns current time in nanosec units.
192 */
193unsigned long long sched_clock(void)
194{
195 return (unsigned long long)jiffies * (1000000000 / HZ);
196}
197
198EXPORT_SYMBOL(do_settimeofday);
diff --git a/arch/m68knommu/kernel/traps.c b/arch/m68knommu/kernel/traps.c
new file mode 100644
index 000000000000..ad7dc6347f19
--- /dev/null
+++ b/arch/m68knommu/kernel/traps.c
@@ -0,0 +1,320 @@
1/*
2 * linux/arch/m68knommu/kernel/traps.c
3 *
4 * Copyright (C) 1993, 1994 by Hamish Macdonald
5 *
6 * 68040 fixes by Michael Rausch
7 * 68040 fixes by Martin Apel
8 * 68060 fixes by Roman Hodek
9 * 68060 fixes by Jesper Skov
10 *
11 * This file is subject to the terms and conditions of the GNU General Public
12 * License. See the file COPYING in the main directory of this archive
13 * for more details.
14 */
15
16/*
17 * Sets up all exception vectors
18 */
19#include <linux/config.h>
20#include <linux/sched.h>
21#include <linux/signal.h>
22#include <linux/kernel.h>
23#include <linux/mm.h>
24#include <linux/types.h>
25#include <linux/a.out.h>
26#include <linux/user.h>
27#include <linux/string.h>
28#include <linux/linkage.h>
29#include <linux/init.h>
30#include <linux/ptrace.h>
31
32#include <asm/setup.h>
33#include <asm/fpu.h>
34#include <asm/system.h>
35#include <asm/uaccess.h>
36#include <asm/traps.h>
37#include <asm/pgtable.h>
38#include <asm/machdep.h>
39#include <asm/siginfo.h>
40
41static char *vec_names[] = {
42 "RESET SP", "RESET PC", "BUS ERROR", "ADDRESS ERROR",
43 "ILLEGAL INSTRUCTION", "ZERO DIVIDE", "CHK", "TRAPcc",
44 "PRIVILEGE VIOLATION", "TRACE", "LINE 1010", "LINE 1111",
45 "UNASSIGNED RESERVED 12", "COPROCESSOR PROTOCOL VIOLATION",
46 "FORMAT ERROR", "UNINITIALIZED INTERRUPT",
47 "UNASSIGNED RESERVED 16", "UNASSIGNED RESERVED 17",
48 "UNASSIGNED RESERVED 18", "UNASSIGNED RESERVED 19",
49 "UNASSIGNED RESERVED 20", "UNASSIGNED RESERVED 21",
50 "UNASSIGNED RESERVED 22", "UNASSIGNED RESERVED 23",
51 "SPURIOUS INTERRUPT", "LEVEL 1 INT", "LEVEL 2 INT", "LEVEL 3 INT",
52 "LEVEL 4 INT", "LEVEL 5 INT", "LEVEL 6 INT", "LEVEL 7 INT",
53 "SYSCALL", "TRAP #1", "TRAP #2", "TRAP #3",
54 "TRAP #4", "TRAP #5", "TRAP #6", "TRAP #7",
55 "TRAP #8", "TRAP #9", "TRAP #10", "TRAP #11",
56 "TRAP #12", "TRAP #13", "TRAP #14", "TRAP #15",
57 "FPCP BSUN", "FPCP INEXACT", "FPCP DIV BY 0", "FPCP UNDERFLOW",
58 "FPCP OPERAND ERROR", "FPCP OVERFLOW", "FPCP SNAN",
59 "FPCP UNSUPPORTED OPERATION",
60 "MMU CONFIGURATION ERROR"
61};
62
63void __init trap_init(void)
64{
65 if (mach_trap_init)
66 mach_trap_init();
67}
68
69void die_if_kernel(char *str, struct pt_regs *fp, int nr)
70{
71 if (!(fp->sr & PS_S))
72 return;
73
74 console_verbose();
75 printk(KERN_EMERG "%s: %08x\n",str,nr);
76 printk(KERN_EMERG "PC: [<%08lx>]\nSR: %04x SP: %p a2: %08lx\n",
77 fp->pc, fp->sr, fp, fp->a2);
78 printk(KERN_EMERG "d0: %08lx d1: %08lx d2: %08lx d3: %08lx\n",
79 fp->d0, fp->d1, fp->d2, fp->d3);
80 printk(KERN_EMERG "d4: %08lx d5: %08lx a0: %08lx a1: %08lx\n",
81 fp->d4, fp->d5, fp->a0, fp->a1);
82
83 printk(KERN_EMERG "Process %s (pid: %d, stackpage=%08lx)\n",
84 current->comm, current->pid, PAGE_SIZE+(unsigned long)current);
85 show_stack(NULL, (unsigned long *)fp);
86 do_exit(SIGSEGV);
87}
88
89asmlinkage void buserr_c(struct frame *fp)
90{
91 /* Only set esp0 if coming from user mode */
92 if (user_mode(&fp->ptregs))
93 current->thread.esp0 = (unsigned long) fp;
94
95#if DEBUG
96 printk (KERN_DEBUG "*** Bus Error *** Format is %x\n", fp->ptregs.format);
97#endif
98
99 die_if_kernel("bad frame format",&fp->ptregs,0);
100#if DEBUG
101 printk(KERN_DEBUG "Unknown SIGSEGV - 4\n");
102#endif
103 force_sig(SIGSEGV, current);
104}
105
106
107int kstack_depth_to_print = 48;
108
109void show_stack(struct task_struct *task, unsigned long *esp)
110{
111 unsigned long *stack, *endstack, addr;
112 extern char _start, _etext;
113 int i;
114
115 if (esp == NULL)
116 esp = (unsigned long *) &esp;
117
118 stack = esp;
119 addr = (unsigned long) esp;
120 endstack = (unsigned long *) PAGE_ALIGN(addr);
121
122 printk(KERN_EMERG "Stack from %08lx:", (unsigned long)stack);
123 for (i = 0; i < kstack_depth_to_print; i++) {
124 if (stack + 1 > endstack)
125 break;
126 if (i % 8 == 0)
127 printk(KERN_EMERG "\n ");
128 printk(KERN_EMERG " %08lx", *stack++);
129 }
130
131 printk(KERN_EMERG "\nCall Trace:");
132 i = 0;
133 while (stack + 1 <= endstack) {
134 addr = *stack++;
135 /*
136 * If the address is either in the text segment of the
137 * kernel, or in the region which contains vmalloc'ed
138 * memory, it *may* be the address of a calling
139 * routine; if so, print it so that someone tracing
140 * down the cause of the crash will be able to figure
141 * out the call path that was taken.
142 */
143 if (((addr >= (unsigned long) &_start) &&
144 (addr <= (unsigned long) &_etext))) {
145 if (i % 4 == 0)
146 printk(KERN_EMERG "\n ");
147 printk(KERN_EMERG " [<%08lx>]", addr);
148 i++;
149 }
150 }
151 printk(KERN_EMERG "\n");
152}
153
154void bad_super_trap(struct frame *fp)
155{
156 console_verbose();
157 if (fp->ptregs.vector < 4*sizeof(vec_names)/sizeof(vec_names[0]))
158 printk (KERN_WARNING "*** %s *** FORMAT=%X\n",
159 vec_names[(fp->ptregs.vector) >> 2],
160 fp->ptregs.format);
161 else
162 printk (KERN_WARNING "*** Exception %d *** FORMAT=%X\n",
163 (fp->ptregs.vector) >> 2,
164 fp->ptregs.format);
165 printk (KERN_WARNING "Current process id is %d\n", current->pid);
166 die_if_kernel("BAD KERNEL TRAP", &fp->ptregs, 0);
167}
168
169asmlinkage void trap_c(struct frame *fp)
170{
171 int sig;
172 siginfo_t info;
173
174 if (fp->ptregs.sr & PS_S) {
175 if ((fp->ptregs.vector >> 2) == VEC_TRACE) {
176 /* traced a trapping instruction */
177 current->ptrace |= PT_DTRACE;
178 } else
179 bad_super_trap(fp);
180 return;
181 }
182
183 /* send the appropriate signal to the user program */
184 switch ((fp->ptregs.vector) >> 2) {
185 case VEC_ADDRERR:
186 info.si_code = BUS_ADRALN;
187 sig = SIGBUS;
188 break;
189 case VEC_ILLEGAL:
190 case VEC_LINE10:
191 case VEC_LINE11:
192 info.si_code = ILL_ILLOPC;
193 sig = SIGILL;
194 break;
195 case VEC_PRIV:
196 info.si_code = ILL_PRVOPC;
197 sig = SIGILL;
198 break;
199 case VEC_COPROC:
200 info.si_code = ILL_COPROC;
201 sig = SIGILL;
202 break;
203 case VEC_TRAP1: /* gdbserver breakpoint */
204 fp->ptregs.pc -= 2;
205 info.si_code = TRAP_TRACE;
206 sig = SIGTRAP;
207 break;
208 case VEC_TRAP2:
209 case VEC_TRAP3:
210 case VEC_TRAP4:
211 case VEC_TRAP5:
212 case VEC_TRAP6:
213 case VEC_TRAP7:
214 case VEC_TRAP8:
215 case VEC_TRAP9:
216 case VEC_TRAP10:
217 case VEC_TRAP11:
218 case VEC_TRAP12:
219 case VEC_TRAP13:
220 case VEC_TRAP14:
221 info.si_code = ILL_ILLTRP;
222 sig = SIGILL;
223 break;
224 case VEC_FPBRUC:
225 case VEC_FPOE:
226 case VEC_FPNAN:
227 info.si_code = FPE_FLTINV;
228 sig = SIGFPE;
229 break;
230 case VEC_FPIR:
231 info.si_code = FPE_FLTRES;
232 sig = SIGFPE;
233 break;
234 case VEC_FPDIVZ:
235 info.si_code = FPE_FLTDIV;
236 sig = SIGFPE;
237 break;
238 case VEC_FPUNDER:
239 info.si_code = FPE_FLTUND;
240 sig = SIGFPE;
241 break;
242 case VEC_FPOVER:
243 info.si_code = FPE_FLTOVF;
244 sig = SIGFPE;
245 break;
246 case VEC_ZERODIV:
247 info.si_code = FPE_INTDIV;
248 sig = SIGFPE;
249 break;
250 case VEC_CHK:
251 case VEC_TRAP:
252 info.si_code = FPE_INTOVF;
253 sig = SIGFPE;
254 break;
255 case VEC_TRACE: /* ptrace single step */
256 info.si_code = TRAP_TRACE;
257 sig = SIGTRAP;
258 break;
259 case VEC_TRAP15: /* breakpoint */
260 info.si_code = TRAP_BRKPT;
261 sig = SIGTRAP;
262 break;
263 default:
264 info.si_code = ILL_ILLOPC;
265 sig = SIGILL;
266 break;
267 }
268 info.si_signo = sig;
269 info.si_errno = 0;
270 switch (fp->ptregs.format) {
271 default:
272 info.si_addr = (void *) fp->ptregs.pc;
273 break;
274 case 2:
275 info.si_addr = (void *) fp->un.fmt2.iaddr;
276 break;
277 case 7:
278 info.si_addr = (void *) fp->un.fmt7.effaddr;
279 break;
280 case 9:
281 info.si_addr = (void *) fp->un.fmt9.iaddr;
282 break;
283 case 10:
284 info.si_addr = (void *) fp->un.fmta.daddr;
285 break;
286 case 11:
287 info.si_addr = (void *) fp->un.fmtb.daddr;
288 break;
289 }
290 force_sig_info (sig, &info, current);
291}
292
293asmlinkage void set_esp0(unsigned long ssp)
294{
295 current->thread.esp0 = ssp;
296}
297
298
299/*
300 * The architecture-independent backtrace generator
301 */
302void dump_stack(void)
303{
304 unsigned long stack;
305
306 show_stack(current, &stack);
307}
308
309#ifdef CONFIG_M68KFPU_EMU
310asmlinkage void fpemu_signal(int signal, int code, void *addr)
311{
312 siginfo_t info;
313
314 info.si_signo = signal;
315 info.si_errno = 0;
316 info.si_code = code;
317 info.si_addr = addr;
318 force_sig_info(signal, &info, current);
319}
320#endif
diff --git a/arch/m68knommu/kernel/vmlinux.lds.S b/arch/m68knommu/kernel/vmlinux.lds.S
new file mode 100644
index 000000000000..31cb12892da5
--- /dev/null
+++ b/arch/m68knommu/kernel/vmlinux.lds.S
@@ -0,0 +1,348 @@
1/*
2 * vmlinux.lds.S -- master linker script for m68knommu arch
3 *
4 * (C) Copyright 2002-2004, Greg Ungerer <gerg@snapgear.com>
5 *
6 * This ends up looking compilcated, because of the number of
7 * address variations for ram and rom/flash layouts. The real
8 * work of the linker script is all at the end, and reasonably
9 * strait forward.
10 */
11
12#include <linux/config.h>
13#include <asm-generic/vmlinux.lds.h>
14
15/*
16 * Original Palm pilot (same for Xcopilot).
17 * There is really only a rom target for this.
18 */
19#ifdef CONFIG_PILOT3
20#define ROMVEC_START 0x10c00000
21#define ROMVEC_LENGTH 0x10400
22#define ROM_START 0x10c10400
23#define ROM_LENGTH 0xfec00
24#define ROM_END 0x10d00000
25#define RAMVEC_START 0x00000000
26#define RAMVEC_LENGTH 0x400
27#define RAM_START 0x10000400
28#define RAM_LENGTH 0xffc00
29#define RAM_END 0x10100000
30#define _ramend _ram_end_notused
31#define DATA_ADDR RAM_START
32#endif
33
34/*
35 * Same setup on both the uCsimm and uCdimm.
36 */
37#if defined(CONFIG_UCSIMM) || defined(CONFIG_UCDIMM)
38#ifdef CONFIG_RAMKERNEL
39#define ROMVEC_START 0x10c10000
40#define ROMVEC_LENGTH 0x400
41#define ROM_START 0x10c10400
42#define ROM_LENGTH 0x1efc00
43#define ROM_END 0x10e00000
44#define RAMVEC_START 0x00000000
45#define RAMVEC_LENGTH 0x400
46#define RAM_START 0x00020400
47#define RAM_LENGTH 0x7dfc00
48#define RAM_END 0x00800000
49#endif
50#ifdef CONFIG_ROMKERNEL
51#define ROMVEC_START 0x10c10000
52#define ROMVEC_LENGTH 0x400
53#define ROM_START 0x10c10400
54#define ROM_LENGTH 0x1efc00
55#define ROM_END 0x10e00000
56#define RAMVEC_START 0x00000000
57#define RAMVEC_LENGTH 0x400
58#define RAM_START 0x00020000
59#define RAM_LENGTH 0x600000
60#define RAM_END 0x00800000
61#endif
62#ifdef CONFIG_HIMEMKERNEL
63#define ROMVEC_START 0x00600000
64#define ROMVEC_LENGTH 0x400
65#define ROM_START 0x00600400
66#define ROM_LENGTH 0x1efc00
67#define ROM_END 0x007f0000
68#define RAMVEC_START 0x00000000
69#define RAMVEC_LENGTH 0x400
70#define RAM_START 0x00020000
71#define RAM_LENGTH 0x5e0000
72#define RAM_END 0x00600000
73#endif
74#endif
75
76#ifdef CONFIG_DRAGEN2
77#define RAM_START 0x10000
78#define RAM_LENGTH 0x7f0000
79#endif
80
81#ifdef CONFIG_UCQUICC
82#define ROMVEC_START 0x00000000
83#define ROMVEC_LENGTH 0x404
84#define ROM_START 0x00000404
85#define ROM_LENGTH 0x1ff6fc
86#define ROM_END 0x00200000
87#define RAMVEC_START 0x00200000
88#define RAMVEC_LENGTH 0x404
89#define RAM_START 0x00200404
90#define RAM_LENGTH 0x1ff6fc
91#define RAM_END 0x00400000
92#endif
93
94/*
95 * The standard Arnewsh 5206 board only has 1MiB of ram. Not normally
96 * enough to be useful. Assume the user has fitted something larger,
97 * at least 4MiB in size. No point in not letting the kernel completely
98 * link, it will be obvious if it is too big when they go to load it.
99 */
100#if defined(CONFIG_ARN5206)
101#define RAM_START 0x10000
102#define RAM_LENGTH 0x3f0000
103#endif
104
105/*
106 * The Motorola 5206eLITE board only has 1MiB of static RAM.
107 */
108#if defined(CONFIG_ELITE)
109#define RAM_START 0x30020000
110#define RAM_END 0xe0000
111#endif
112
113/*
114 * All the Motorola eval boards have the same basic arrangement.
115 * The end of RAM will vary depending on how much ram is fitted,
116 * but this isn't important here, we assume at least 4MiB.
117 */
118#if defined(CONFIG_M5206eC3) || defined(CONFIG_M5249C3) || \
119 defined(CONFIG_M5272C3) || defined(CONFIG_M5307C3) || \
120 defined(CONFIG_ARN5307) || defined(CONFIG_M5407C3) || \
121 defined(CONFIG_M5271EVB) || defined(CONFIG_M5275EVB)
122#define RAM_START 0x20000
123#define RAM_LENGTH 0x3e0000
124#endif
125
126/*
127 * The senTec COBRA5272 board has nearly the same memory layout as
128 * the M5272C3. We assume 16MiB ram.
129 */
130#if defined(CONFIG_COBRA5272)
131#define RAM_START 0x20000
132#define RAM_LENGTH 0xfe0000
133#endif
134
135#if defined(CONFIG_M5282EVB)
136#define RAM_START 0x10000
137#define RAM_LENGTH 0x3f0000
138#endif
139
140/*
141 * The senTec COBRA5282 board has the same memory layout as the M5282EVB.
142 */
143#if defined(CONFIG_COBRA5282)
144#define RAM_START 0x10000
145#define RAM_LENGTH 0x3f0000
146#endif
147
148/*
149 * These flash boot boards use all of ram for operation. Again the
150 * actual memory size is not important here, assume at least 4MiB.
151 * They currently have no support for running in flash.
152 */
153#if defined(CONFIG_NETtel) || defined(CONFIG_eLIA) || \
154 defined(CONFIG_DISKtel) || defined(CONFIG_SECUREEDGEMP3) || \
155 defined(CONFIG_HW_FEITH)
156#define RAM_START 0x400
157#define RAM_LENGTH 0x3ffc00
158#endif
159
160/*
161 * Sneha Boards mimimun memmory
162 * The end of RAM will vary depending on how much ram is fitted,
163 * but this isn't important here, we assume at least 4MiB.
164 */
165#if defined(CONFIG_CPU16B)
166#define RAM_START 0x20000
167#define RAM_LENGTH 0x3e0000
168#endif
169
170
171#if defined(CONFIG_RAMKERNEL)
172#define TEXT ram
173#define DATA ram
174#define INIT ram
175#define BSS ram
176#endif
177#if defined(CONFIG_ROMKERNEL) || defined(CONFIG_HIMEMKERNEL)
178#define TEXT rom
179#define DATA ram
180#define INIT ram
181#define BSS ram
182#endif
183
184#ifndef DATA_ADDR
185#define DATA_ADDR
186#endif
187
188
189OUTPUT_ARCH(m68k)
190ENTRY(_start)
191
192MEMORY {
193#ifdef RAMVEC_START
194 ramvec : ORIGIN = RAMVEC_START, LENGTH = RAMVEC_LENGTH
195#endif
196 ram : ORIGIN = RAM_START, LENGTH = RAM_LENGTH
197#ifdef RAM_END
198 eram : ORIGIN = RAM_END, LENGTH = 0
199#endif
200#ifdef ROM_START
201 romvec : ORIGIN = ROMVEC_START, LENGTH = ROMVEC_LENGTH
202 rom : ORIGIN = ROM_START, LENGTH = ROM_LENGTH
203 erom : ORIGIN = ROM_END, LENGTH = 0
204#endif
205}
206
207jiffies = jiffies_64 + 4;
208
209SECTIONS {
210
211#ifdef ROMVEC_START
212 . = ROMVEC_START ;
213 .romvec : {
214 __rom_start = . ;
215 _romvec = .;
216 *(.data.initvect)
217 } > romvec
218#endif
219
220 .text : {
221 _stext = . ;
222 *(.text)
223 SCHED_TEXT
224 *(.text.lock)
225
226 . = ALIGN(16); /* Exception table */
227 __start___ex_table = .;
228 *(__ex_table)
229 __stop___ex_table = .;
230
231 *(.rodata) *(.rodata.*)
232 *(__vermagic) /* Kernel version magic */
233 *(.rodata1)
234 *(.rodata.str1.1)
235
236 /* Kernel symbol table: Normal symbols */
237 . = ALIGN(4);
238 __start___ksymtab = .;
239 *(__ksymtab)
240 __stop___ksymtab = .;
241
242 /* Kernel symbol table: GPL-only symbols */
243 __start___ksymtab_gpl = .;
244 *(__ksymtab_gpl)
245 __stop___ksymtab_gpl = .;
246
247 /* Kernel symbol table: Normal symbols */
248 __start___kcrctab = .;
249 *(__kcrctab)
250 __stop___kcrctab = .;
251
252 /* Kernel symbol table: GPL-only symbols */
253 __start___kcrctab_gpl = .;
254 *(__kcrctab_gpl)
255 __stop___kcrctab_gpl = .;
256
257 /* Kernel symbol table: strings */
258 *(__ksymtab_strings)
259
260 /* Built-in module parameters */
261 __start___param = .;
262 *(__param)
263 __stop___param = .;
264
265 . = ALIGN(4) ;
266 _etext = . ;
267 } > TEXT
268
269#ifdef ROM_END
270 . = ROM_END ;
271 .erom : {
272 __rom_end = . ;
273 } > erom
274#endif
275#ifdef RAMVEC_START
276 . = RAMVEC_START ;
277 .ramvec : {
278 __ramvec = .;
279 } > ramvec
280#endif
281
282 .data DATA_ADDR : {
283 . = ALIGN(4);
284 _sdata = . ;
285 *(.data)
286 . = ALIGN(8192) ;
287 *(.data.init_task)
288 _edata = . ;
289 } > DATA
290
291 .init : {
292 . = ALIGN(4096);
293 __init_begin = .;
294 _sinittext = .;
295 *(.init.text)
296 _einittext = .;
297 *(.init.data)
298 . = ALIGN(16);
299 __setup_start = .;
300 *(.init.setup)
301 __setup_end = .;
302 __initcall_start = .;
303 *(.initcall1.init)
304 *(.initcall2.init)
305 *(.initcall3.init)
306 *(.initcall4.init)
307 *(.initcall5.init)
308 *(.initcall6.init)
309 *(.initcall7.init)
310 __initcall_end = .;
311 __con_initcall_start = .;
312 *(.con_initcall.init)
313 __con_initcall_end = .;
314 __security_initcall_start = .;
315 *(.security_initcall.init)
316 __security_initcall_end = .;
317 . = ALIGN(4);
318 __initramfs_start = .;
319 *(.init.ramfs)
320 __initramfs_end = .;
321 . = ALIGN(4096);
322 __init_end = .;
323 } > INIT
324
325 /DISCARD/ : {
326 *(.exit.text)
327 *(.exit.data)
328 *(.exitcall.exit)
329 }
330
331 .bss : {
332 . = ALIGN(4);
333 _sbss = . ;
334 *(.bss)
335 *(COMMON)
336 . = ALIGN(4) ;
337 _ebss = . ;
338 } > BSS
339
340#ifdef RAM_END
341 . = RAM_END ;
342 .eram : {
343 __ramend = . ;
344 _ramend = . ;
345 } > eram
346#endif
347}
348