aboutsummaryrefslogtreecommitdiffstats
path: root/arch/m68k/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'arch/m68k/kernel')
-rw-r--r--arch/m68k/kernel/Makefile18
-rw-r--r--arch/m68k/kernel/asm-offsets.c109
-rw-r--r--arch/m68k/kernel/bios32.c515
-rw-r--r--arch/m68k/kernel/entry.S712
-rw-r--r--arch/m68k/kernel/head.S3940
-rw-r--r--arch/m68k/kernel/ints.c281
-rw-r--r--arch/m68k/kernel/m68k_ksyms.c88
-rw-r--r--arch/m68k/kernel/module.c128
-rw-r--r--arch/m68k/kernel/process.c405
-rw-r--r--arch/m68k/kernel/ptrace.c393
-rw-r--r--arch/m68k/kernel/semaphore.c133
-rw-r--r--arch/m68k/kernel/setup.c545
-rw-r--r--arch/m68k/kernel/signal.c1025
-rw-r--r--arch/m68k/kernel/sun3-head.S104
-rw-r--r--arch/m68k/kernel/sys_m68k.c671
-rw-r--r--arch/m68k/kernel/time.c187
-rw-r--r--arch/m68k/kernel/traps.c1227
-rw-r--r--arch/m68k/kernel/vmlinux-std.lds95
-rw-r--r--arch/m68k/kernel/vmlinux-sun3.lds95
-rw-r--r--arch/m68k/kernel/vmlinux.lds.S11
20 files changed, 10682 insertions, 0 deletions
diff --git a/arch/m68k/kernel/Makefile b/arch/m68k/kernel/Makefile
new file mode 100644
index 000000000000..458925c471a1
--- /dev/null
+++ b/arch/m68k/kernel/Makefile
@@ -0,0 +1,18 @@
1#
2# Makefile for the linux kernel.
3#
4
5ifndef CONFIG_SUN3
6 extra-y := head.o
7else
8 extra-y := sun3-head.o
9endif
10extra-y += vmlinux.lds
11
12obj-y := entry.o process.o traps.o ints.o signal.o ptrace.o \
13 sys_m68k.o time.o semaphore.o setup.o m68k_ksyms.o
14
15obj-$(CONFIG_PCI) += bios32.o
16obj-$(CONFIG_MODULES) += module.o
17
18EXTRA_AFLAGS := -traditional
diff --git a/arch/m68k/kernel/asm-offsets.c b/arch/m68k/kernel/asm-offsets.c
new file mode 100644
index 000000000000..cee3317b8665
--- /dev/null
+++ b/arch/m68k/kernel/asm-offsets.c
@@ -0,0 +1,109 @@
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 <asm/bootinfo.h>
15#include <asm/irq.h>
16#include <asm/amigahw.h>
17#include <linux/font.h>
18
19#define DEFINE(sym, val) \
20 asm volatile("\n->" #sym " %0 " #val : : "i" (val))
21
22int main(void)
23{
24 /* offsets into the task struct */
25 DEFINE(TASK_STATE, offsetof(struct task_struct, state));
26 DEFINE(TASK_FLAGS, offsetof(struct task_struct, flags));
27 DEFINE(TASK_PTRACE, offsetof(struct task_struct, ptrace));
28 DEFINE(TASK_WORK, offsetof(struct task_struct, thread.work));
29 DEFINE(TASK_NEEDRESCHED, offsetof(struct task_struct, thread.work.need_resched));
30 DEFINE(TASK_SYSCALL_TRACE, offsetof(struct task_struct, thread.work.syscall_trace));
31 DEFINE(TASK_SIGPENDING, offsetof(struct task_struct, thread.work.sigpending));
32 DEFINE(TASK_NOTIFY_RESUME, offsetof(struct task_struct, thread.work.notify_resume));
33 DEFINE(TASK_THREAD, offsetof(struct task_struct, thread));
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 thread struct */
38 DEFINE(THREAD_KSP, offsetof(struct thread_struct, ksp));
39 DEFINE(THREAD_USP, offsetof(struct thread_struct, usp));
40 DEFINE(THREAD_SR, offsetof(struct thread_struct, sr));
41 DEFINE(THREAD_FS, offsetof(struct thread_struct, fs));
42 DEFINE(THREAD_CRP, offsetof(struct thread_struct, crp));
43 DEFINE(THREAD_ESP0, offsetof(struct thread_struct, esp0));
44 DEFINE(THREAD_FPREG, offsetof(struct thread_struct, fp));
45 DEFINE(THREAD_FPCNTL, offsetof(struct thread_struct, fpcntl));
46 DEFINE(THREAD_FPSTATE, offsetof(struct thread_struct, fpstate));
47
48 /* offsets into the pt_regs */
49 DEFINE(PT_D0, offsetof(struct pt_regs, d0));
50 DEFINE(PT_ORIG_D0, offsetof(struct pt_regs, orig_d0));
51 DEFINE(PT_D1, offsetof(struct pt_regs, d1));
52 DEFINE(PT_D2, offsetof(struct pt_regs, d2));
53 DEFINE(PT_D3, offsetof(struct pt_regs, d3));
54 DEFINE(PT_D4, offsetof(struct pt_regs, d4));
55 DEFINE(PT_D5, offsetof(struct pt_regs, d5));
56 DEFINE(PT_A0, offsetof(struct pt_regs, a0));
57 DEFINE(PT_A1, offsetof(struct pt_regs, a1));
58 DEFINE(PT_A2, offsetof(struct pt_regs, a2));
59 DEFINE(PT_PC, offsetof(struct pt_regs, pc));
60 DEFINE(PT_SR, offsetof(struct pt_regs, sr));
61 /* bitfields are a bit difficult */
62 DEFINE(PT_VECTOR, offsetof(struct pt_regs, pc) + 4);
63
64 /* offsets into the irq_handler struct */
65 DEFINE(IRQ_HANDLER, offsetof(struct irq_node, handler));
66 DEFINE(IRQ_DEVID, offsetof(struct irq_node, dev_id));
67 DEFINE(IRQ_NEXT, offsetof(struct irq_node, next));
68
69 /* offsets into the kernel_stat struct */
70 DEFINE(STAT_IRQ, offsetof(struct kernel_stat, irqs));
71
72 /* offsets into the irq_cpustat_t struct */
73 DEFINE(CPUSTAT_SOFTIRQ_PENDING, offsetof(irq_cpustat_t, __softirq_pending));
74
75 /* offsets into the bi_record struct */
76 DEFINE(BIR_TAG, offsetof(struct bi_record, tag));
77 DEFINE(BIR_SIZE, offsetof(struct bi_record, size));
78 DEFINE(BIR_DATA, offsetof(struct bi_record, data));
79
80 /* offsets into font_desc (drivers/video/console/font.h) */
81 DEFINE(FONT_DESC_IDX, offsetof(struct font_desc, idx));
82 DEFINE(FONT_DESC_NAME, offsetof(struct font_desc, name));
83 DEFINE(FONT_DESC_WIDTH, offsetof(struct font_desc, width));
84 DEFINE(FONT_DESC_HEIGHT, offsetof(struct font_desc, height));
85 DEFINE(FONT_DESC_DATA, offsetof(struct font_desc, data));
86 DEFINE(FONT_DESC_PREF, offsetof(struct font_desc, pref));
87
88 /* signal defines */
89 DEFINE(SIGSEGV, SIGSEGV);
90 DEFINE(SEGV_MAPERR, SEGV_MAPERR);
91 DEFINE(SIGTRAP, SIGTRAP);
92 DEFINE(TRAP_TRACE, TRAP_TRACE);
93
94 /* offsets into the custom struct */
95 DEFINE(CUSTOMBASE, &custom);
96 DEFINE(C_INTENAR, offsetof(struct CUSTOM, intenar));
97 DEFINE(C_INTREQR, offsetof(struct CUSTOM, intreqr));
98 DEFINE(C_INTENA, offsetof(struct CUSTOM, intena));
99 DEFINE(C_INTREQ, offsetof(struct CUSTOM, intreq));
100 DEFINE(C_SERDATR, offsetof(struct CUSTOM, serdatr));
101 DEFINE(C_SERDAT, offsetof(struct CUSTOM, serdat));
102 DEFINE(C_SERPER, offsetof(struct CUSTOM, serper));
103 DEFINE(CIAABASE, &ciaa);
104 DEFINE(CIABBASE, &ciab);
105 DEFINE(C_PRA, offsetof(struct CIA, pra));
106 DEFINE(ZTWOBASE, zTwoBase);
107
108 return 0;
109}
diff --git a/arch/m68k/kernel/bios32.c b/arch/m68k/kernel/bios32.c
new file mode 100644
index 000000000000..a901685eb6a9
--- /dev/null
+++ b/arch/m68k/kernel/bios32.c
@@ -0,0 +1,515 @@
1/*
2 * bios32.c - PCI BIOS functions for m68k systems.
3 *
4 * Written by Wout Klaren.
5 *
6 * Based on the DEC Alpha bios32.c by Dave Rusling and David Mosberger.
7 */
8
9#include <linux/config.h>
10#include <linux/init.h>
11#include <linux/kernel.h>
12
13#if 0
14# define DBG_DEVS(args) printk args
15#else
16# define DBG_DEVS(args)
17#endif
18
19#ifdef CONFIG_PCI
20
21/*
22 * PCI support for Linux/m68k. Currently only the Hades is supported.
23 *
24 * The support for PCI bridges in the DEC Alpha version has
25 * been removed in this version.
26 */
27
28#include <linux/pci.h>
29#include <linux/slab.h>
30#include <linux/mm.h>
31
32#include <asm/io.h>
33#include <asm/pci.h>
34#include <asm/uaccess.h>
35
36#define KB 1024
37#define MB (1024*KB)
38#define GB (1024*MB)
39
40#define MAJOR_REV 0
41#define MINOR_REV 5
42
43/*
44 * Align VAL to ALIGN, which must be a power of two.
45 */
46
47#define ALIGN(val,align) (((val) + ((align) - 1)) & ~((align) - 1))
48
49/*
50 * Offsets relative to the I/O and memory base addresses from where resources
51 * are allocated.
52 */
53
54#define IO_ALLOC_OFFSET 0x00004000
55#define MEM_ALLOC_OFFSET 0x04000000
56
57/*
58 * Declarations of hardware specific initialisation functions.
59 */
60
61extern struct pci_bus_info *init_hades_pci(void);
62
63/*
64 * Bus info structure of the PCI bus. A pointer to this structure is
65 * put in the sysdata member of the pci_bus structure.
66 */
67
68static struct pci_bus_info *bus_info;
69
70static int pci_modify = 1; /* If set, layout the PCI bus ourself. */
71static int skip_vga; /* If set do not modify base addresses
72 of vga cards.*/
73static int disable_pci_burst; /* If set do not allow PCI bursts. */
74
75static unsigned int io_base;
76static unsigned int mem_base;
77
78/*
79 * static void disable_dev(struct pci_dev *dev)
80 *
81 * Disable PCI device DEV so that it does not respond to I/O or memory
82 * accesses.
83 *
84 * Parameters:
85 *
86 * dev - device to disable.
87 */
88
89static void __init disable_dev(struct pci_dev *dev)
90{
91 unsigned short cmd;
92
93 if (((dev->class >> 8 == PCI_CLASS_NOT_DEFINED_VGA) ||
94 (dev->class >> 8 == PCI_CLASS_DISPLAY_VGA) ||
95 (dev->class >> 8 == PCI_CLASS_DISPLAY_XGA)) && skip_vga)
96 return;
97
98 pci_read_config_word(dev, PCI_COMMAND, &cmd);
99
100 cmd &= (~PCI_COMMAND_IO & ~PCI_COMMAND_MEMORY & ~PCI_COMMAND_MASTER);
101 pci_write_config_word(dev, PCI_COMMAND, cmd);
102}
103
104/*
105 * static void layout_dev(struct pci_dev *dev)
106 *
107 * Layout memory and I/O for a device.
108 *
109 * Parameters:
110 *
111 * device - device to layout memory and I/O for.
112 */
113
114static void __init layout_dev(struct pci_dev *dev)
115{
116 unsigned short cmd;
117 unsigned int base, mask, size, reg;
118 unsigned int alignto;
119 int i;
120
121 /*
122 * Skip video cards if requested.
123 */
124
125 if (((dev->class >> 8 == PCI_CLASS_NOT_DEFINED_VGA) ||
126 (dev->class >> 8 == PCI_CLASS_DISPLAY_VGA) ||
127 (dev->class >> 8 == PCI_CLASS_DISPLAY_XGA)) && skip_vga)
128 return;
129
130 pci_read_config_word(dev, PCI_COMMAND, &cmd);
131
132 for (reg = PCI_BASE_ADDRESS_0, i = 0; reg <= PCI_BASE_ADDRESS_5; reg += 4, i++)
133 {
134 /*
135 * Figure out how much space and of what type this
136 * device wants.
137 */
138
139 pci_write_config_dword(dev, reg, 0xffffffff);
140 pci_read_config_dword(dev, reg, &base);
141
142 if (!base)
143 {
144 /* this base-address register is unused */
145 dev->resource[i].start = 0;
146 dev->resource[i].end = 0;
147 dev->resource[i].flags = 0;
148 continue;
149 }
150
151 /*
152 * We've read the base address register back after
153 * writing all ones and so now we must decode it.
154 */
155
156 if (base & PCI_BASE_ADDRESS_SPACE_IO)
157 {
158 /*
159 * I/O space base address register.
160 */
161
162 cmd |= PCI_COMMAND_IO;
163
164 base &= PCI_BASE_ADDRESS_IO_MASK;
165 mask = (~base << 1) | 0x1;
166 size = (mask & base) & 0xffffffff;
167
168 /*
169 * Align to multiple of size of minimum base.
170 */
171
172 alignto = max_t(unsigned int, 0x040, size);
173 base = ALIGN(io_base, alignto);
174 io_base = base + size;
175 pci_write_config_dword(dev, reg, base | PCI_BASE_ADDRESS_SPACE_IO);
176
177 dev->resource[i].start = base;
178 dev->resource[i].end = dev->resource[i].start + size - 1;
179 dev->resource[i].flags = IORESOURCE_IO | PCI_BASE_ADDRESS_SPACE_IO;
180
181 DBG_DEVS(("layout_dev: IO address: %lX\n", base));
182 }
183 else
184 {
185 unsigned int type;
186
187 /*
188 * Memory space base address register.
189 */
190
191 cmd |= PCI_COMMAND_MEMORY;
192 type = base & PCI_BASE_ADDRESS_MEM_TYPE_MASK;
193 base &= PCI_BASE_ADDRESS_MEM_MASK;
194 mask = (~base << 1) | 0x1;
195 size = (mask & base) & 0xffffffff;
196 switch (type)
197 {
198 case PCI_BASE_ADDRESS_MEM_TYPE_32:
199 case PCI_BASE_ADDRESS_MEM_TYPE_64:
200 break;
201
202 case PCI_BASE_ADDRESS_MEM_TYPE_1M:
203 printk("bios32 WARNING: slot %d, function %d "
204 "requests memory below 1MB---don't "
205 "know how to do that.\n",
206 PCI_SLOT(dev->devfn),
207 PCI_FUNC(dev->devfn));
208 continue;
209 }
210
211 /*
212 * Align to multiple of size of minimum base.
213 */
214
215 alignto = max_t(unsigned int, 0x1000, size);
216 base = ALIGN(mem_base, alignto);
217 mem_base = base + size;
218 pci_write_config_dword(dev, reg, base);
219
220 dev->resource[i].start = base;
221 dev->resource[i].end = dev->resource[i].start + size - 1;
222 dev->resource[i].flags = IORESOURCE_MEM;
223
224 if (type == PCI_BASE_ADDRESS_MEM_TYPE_64)
225 {
226 /*
227 * 64-bit address, set the highest 32 bits
228 * to zero.
229 */
230
231 reg += 4;
232 pci_write_config_dword(dev, reg, 0);
233
234 i++;
235 dev->resource[i].start = 0;
236 dev->resource[i].end = 0;
237 dev->resource[i].flags = 0;
238 }
239 }
240 }
241
242 /*
243 * Enable device:
244 */
245
246 if (dev->class >> 8 == PCI_CLASS_NOT_DEFINED ||
247 dev->class >> 8 == PCI_CLASS_NOT_DEFINED_VGA ||
248 dev->class >> 8 == PCI_CLASS_DISPLAY_VGA ||
249 dev->class >> 8 == PCI_CLASS_DISPLAY_XGA)
250 {
251 /*
252 * All of these (may) have I/O scattered all around
253 * and may not use i/o-base address registers at all.
254 * So we just have to always enable I/O to these
255 * devices.
256 */
257 cmd |= PCI_COMMAND_IO;
258 }
259
260 pci_write_config_word(dev, PCI_COMMAND, cmd | PCI_COMMAND_MASTER);
261
262 pci_write_config_byte(dev, PCI_LATENCY_TIMER, (disable_pci_burst) ? 0 : 32);
263
264 if (bus_info != NULL)
265 bus_info->conf_device(dev); /* Machine dependent configuration. */
266
267 DBG_DEVS(("layout_dev: bus %d slot 0x%x VID 0x%x DID 0x%x class 0x%x\n",
268 dev->bus->number, PCI_SLOT(dev->devfn), dev->vendor, dev->device, dev->class));
269}
270
271/*
272 * static void layout_bus(struct pci_bus *bus)
273 *
274 * Layout memory and I/O for all devices on the given bus.
275 *
276 * Parameters:
277 *
278 * bus - bus.
279 */
280
281static void __init layout_bus(struct pci_bus *bus)
282{
283 unsigned int bio, bmem;
284 struct pci_dev *dev;
285
286 DBG_DEVS(("layout_bus: starting bus %d\n", bus->number));
287
288 if (!bus->devices && !bus->children)
289 return;
290
291 /*
292 * Align the current bases on appropriate boundaries (4K for
293 * IO and 1MB for memory).
294 */
295
296 bio = io_base = ALIGN(io_base, 4*KB);
297 bmem = mem_base = ALIGN(mem_base, 1*MB);
298
299 /*
300 * PCI devices might have been setup by a PCI BIOS emulation
301 * running under TOS. In these cases there is a
302 * window during which two devices may have an overlapping
303 * address range. To avoid this causing trouble, we first
304 * turn off the I/O and memory address decoders for all PCI
305 * devices. They'll be re-enabled only once all address
306 * decoders are programmed consistently.
307 */
308
309 DBG_DEVS(("layout_bus: disable_dev for bus %d\n", bus->number));
310
311 for (dev = bus->devices; dev; dev = dev->sibling)
312 {
313 if ((dev->class >> 16 != PCI_BASE_CLASS_BRIDGE) ||
314 (dev->class >> 8 == PCI_CLASS_BRIDGE_PCMCIA))
315 disable_dev(dev);
316 }
317
318 /*
319 * Allocate space to each device:
320 */
321
322 DBG_DEVS(("layout_bus: starting bus %d devices\n", bus->number));
323
324 for (dev = bus->devices; dev; dev = dev->sibling)
325 {
326 if ((dev->class >> 16 != PCI_BASE_CLASS_BRIDGE) ||
327 (dev->class >> 8 == PCI_CLASS_BRIDGE_PCMCIA))
328 layout_dev(dev);
329 }
330
331 DBG_DEVS(("layout_bus: bus %d finished\n", bus->number));
332}
333
334/*
335 * static void pcibios_fixup(void)
336 *
337 * Layout memory and I/O of all devices on the PCI bus if 'pci_modify' is
338 * true. This might be necessary because not every m68k machine with a PCI
339 * bus has a PCI BIOS. This function should be called right after
340 * pci_scan_bus() in pcibios_init().
341 */
342
343static void __init pcibios_fixup(void)
344{
345 if (pci_modify)
346 {
347 /*
348 * Set base addresses for allocation of I/O and memory space.
349 */
350
351 io_base = bus_info->io_space.start + IO_ALLOC_OFFSET;
352 mem_base = bus_info->mem_space.start + MEM_ALLOC_OFFSET;
353
354 /*
355 * Scan the tree, allocating PCI memory and I/O space.
356 */
357
358 layout_bus(pci_bus_b(pci_root.next));
359 }
360
361 /*
362 * Fix interrupt assignments, etc.
363 */
364
365 bus_info->fixup(pci_modify);
366}
367
368/*
369 * static void pcibios_claim_resources(struct pci_bus *bus)
370 *
371 * Claim all resources that are assigned to devices on the given bus.
372 *
373 * Parameters:
374 *
375 * bus - bus.
376 */
377
378static void __init pcibios_claim_resources(struct pci_bus *bus)
379{
380 struct pci_dev *dev;
381 int i;
382
383 while (bus)
384 {
385 for (dev = bus->devices; (dev != NULL); dev = dev->sibling)
386 {
387 for (i = 0; i < PCI_NUM_RESOURCES; i++)
388 {
389 struct resource *r = &dev->resource[i];
390 struct resource *pr;
391 struct pci_bus_info *bus_info = (struct pci_bus_info *) dev->sysdata;
392
393 if ((r->start == 0) || (r->parent != NULL))
394 continue;
395#if 1
396 if (r->flags & IORESOURCE_IO)
397 pr = &bus_info->io_space;
398 else
399 pr = &bus_info->mem_space;
400#else
401 if (r->flags & IORESOURCE_IO)
402 pr = &ioport_resource;
403 else
404 pr = &iomem_resource;
405#endif
406 if (request_resource(pr, r) < 0)
407 {
408 printk(KERN_ERR "PCI: Address space collision on region %d of device %s\n", i, dev->name);
409 }
410 }
411 }
412
413 if (bus->children)
414 pcibios_claim_resources(bus->children);
415
416 bus = bus->next;
417 }
418}
419
420/*
421 * int pcibios_assign_resource(struct pci_dev *dev, int i)
422 *
423 * Assign a new address to a PCI resource.
424 *
425 * Parameters:
426 *
427 * dev - device.
428 * i - resource.
429 *
430 * Result: 0 if successful.
431 */
432
433int __init pcibios_assign_resource(struct pci_dev *dev, int i)
434{
435 struct resource *r = &dev->resource[i];
436 struct resource *pr = pci_find_parent_resource(dev, r);
437 unsigned long size = r->end + 1;
438
439 if (!pr)
440 return -EINVAL;
441
442 if (r->flags & IORESOURCE_IO)
443 {
444 if (size > 0x100)
445 return -EFBIG;
446
447 if (allocate_resource(pr, r, size, bus_info->io_space.start +
448 IO_ALLOC_OFFSET, bus_info->io_space.end, 1024))
449 return -EBUSY;
450 }
451 else
452 {
453 if (allocate_resource(pr, r, size, bus_info->mem_space.start +
454 MEM_ALLOC_OFFSET, bus_info->mem_space.end, size))
455 return -EBUSY;
456 }
457
458 if (i < 6)
459 pci_write_config_dword(dev, PCI_BASE_ADDRESS_0 + 4 * i, r->start);
460
461 return 0;
462}
463
464void __init pcibios_fixup_bus(struct pci_bus *bus)
465{
466 struct pci_dev *dev;
467 void *sysdata;
468
469 sysdata = (bus->parent) ? bus->parent->sysdata : bus->sysdata;
470
471 for (dev = bus->devices; (dev != NULL); dev = dev->sibling)
472 dev->sysdata = sysdata;
473}
474
475void __init pcibios_init(void)
476{
477 printk("Linux/m68k PCI BIOS32 revision %x.%02x\n", MAJOR_REV, MINOR_REV);
478
479 bus_info = NULL;
480#ifdef CONFIG_HADES
481 if (MACH_IS_HADES)
482 bus_info = init_hades_pci();
483#endif
484 if (bus_info != NULL)
485 {
486 printk("PCI: Probing PCI hardware\n");
487 pci_scan_bus(0, bus_info->m68k_pci_ops, bus_info);
488 pcibios_fixup();
489 pcibios_claim_resources(pci_root);
490 }
491 else
492 printk("PCI: No PCI bus detected\n");
493}
494
495char * __init pcibios_setup(char *str)
496{
497 if (!strcmp(str, "nomodify"))
498 {
499 pci_modify = 0;
500 return NULL;
501 }
502 else if (!strcmp(str, "skipvga"))
503 {
504 skip_vga = 1;
505 return NULL;
506 }
507 else if (!strcmp(str, "noburst"))
508 {
509 disable_pci_burst = 1;
510 return NULL;
511 }
512
513 return str;
514}
515#endif /* CONFIG_PCI */
diff --git a/arch/m68k/kernel/entry.S b/arch/m68k/kernel/entry.S
new file mode 100644
index 000000000000..e964015a31dc
--- /dev/null
+++ b/arch/m68k/kernel/entry.S
@@ -0,0 +1,712 @@
1/* -*- mode: asm -*-
2 *
3 * linux/arch/m68k/kernel/entry.S
4 *
5 * Copyright (C) 1991, 1992 Linus Torvalds
6 *
7 * This file is subject to the terms and conditions of the GNU General Public
8 * License. See the file README.legal in the main directory of this archive
9 * for more details.
10 *
11 * Linux/m68k support by Hamish Macdonald
12 *
13 * 68060 fixes by Jesper Skov
14 *
15 */
16
17/*
18 * entry.S contains the system-call and fault low-level handling routines.
19 * This also contains the timer-interrupt handler, as well as all interrupts
20 * and faults that can result in a task-switch.
21 *
22 * NOTE: This code handles signal-recognition, which happens every time
23 * after a timer-interrupt and after each system call.
24 *
25 */
26
27/*
28 * 12/03/96 Jes: Currently we only support m68k single-cpu systems, so
29 * all pointers that used to be 'current' are now entry
30 * number 0 in the 'current_set' list.
31 *
32 * 6/05/00 RZ: addedd writeback completion after return from sighandler
33 * for 68040
34 */
35
36#include <linux/config.h>
37#include <linux/linkage.h>
38#include <asm/entry.h>
39#include <asm/errno.h>
40#include <asm/setup.h>
41#include <asm/segment.h>
42#include <asm/traps.h>
43#include <asm/unistd.h>
44
45#include <asm/offsets.h>
46
47.globl system_call, buserr, trap
48.globl resume, ret_from_exception
49.globl ret_from_signal
50.globl inthandler, sys_call_table
51.globl sys_fork, sys_clone, sys_vfork
52.globl ret_from_interrupt, bad_interrupt
53
54.text
55ENTRY(buserr)
56 SAVE_ALL_INT
57 GET_CURRENT(%d0)
58 movel %sp,%sp@- | stack frame pointer argument
59 bsrl buserr_c
60 addql #4,%sp
61 jra ret_from_exception
62
63ENTRY(trap)
64 SAVE_ALL_INT
65 GET_CURRENT(%d0)
66 movel %sp,%sp@- | stack frame pointer argument
67 bsrl trap_c
68 addql #4,%sp
69 jra ret_from_exception
70
71 | After a fork we jump here directly from resume,
72 | so that %d1 contains the previous task
73 | schedule_tail now used regardless of CONFIG_SMP
74ENTRY(ret_from_fork)
75 movel %d1,%sp@-
76 jsr schedule_tail
77 addql #4,%sp
78 jra ret_from_exception
79
80badsys:
81 movel #-ENOSYS,%sp@(PT_D0)
82 jra ret_from_exception
83
84do_trace:
85 movel #-ENOSYS,%sp@(PT_D0) | needed for strace
86 subql #4,%sp
87 SAVE_SWITCH_STACK
88 jbsr syscall_trace
89 RESTORE_SWITCH_STACK
90 addql #4,%sp
91 movel %sp@(PT_ORIG_D0),%d1
92 movel #-ENOSYS,%d0
93 cmpl #NR_syscalls,%d1
94 jcc 1f
95 jbsr @(sys_call_table,%d1:l:4)@(0)
961: movel %d0,%sp@(PT_D0) | save the return value
97 subql #4,%sp | dummy return address
98 SAVE_SWITCH_STACK
99 jbsr syscall_trace
100
101ret_from_signal:
102 RESTORE_SWITCH_STACK
103 addql #4,%sp
104/* on 68040 complete pending writebacks if any */
105#ifdef CONFIG_M68040
106 bfextu %sp@(PT_VECTOR){#0,#4},%d0
107 subql #7,%d0 | bus error frame ?
108 jbne 1f
109 movel %sp,%sp@-
110 jbsr berr_040cleanup
111 addql #4,%sp
1121:
113#endif
114 jra ret_from_exception
115
116ENTRY(system_call)
117 SAVE_ALL_SYS
118
119 GET_CURRENT(%d1)
120 | save top of frame
121 movel %sp,%curptr@(TASK_THREAD+THREAD_ESP0)
122
123 tstb %curptr@(TASK_SYSCALL_TRACE)
124 jne do_trace
125 cmpl #NR_syscalls,%d0
126 jcc badsys
127 jbsr @(sys_call_table,%d0:l:4)@(0)
128 movel %d0,%sp@(PT_D0) | save the return value
129
130 |oriw #0x0700,%sr
131 movel %curptr@(TASK_WORK),%d0
132 jne syscall_exit_work
1331: RESTORE_ALL
134
135syscall_exit_work:
136 btst #5,%sp@(PT_SR) | check if returning to kernel
137 bnes 1b | if so, skip resched, signals
138 tstw %d0
139 jeq do_signal_return
140 tstb %d0
141 jne do_delayed_trace
142
143 pea resume_userspace
144 jmp schedule
145
146ret_from_exception:
147 btst #5,%sp@(PT_SR) | check if returning to kernel
148 bnes 1f | if so, skip resched, signals
149 | only allow interrupts when we are really the last one on the
150 | kernel stack, otherwise stack overflow can occur during
151 | heavy interrupt load
152 andw #ALLOWINT,%sr
153
154resume_userspace:
155 movel %curptr@(TASK_WORK),%d0
156 lsrl #8,%d0
157 jne exit_work
1581: RESTORE_ALL
159
160exit_work:
161 | save top of frame
162 movel %sp,%curptr@(TASK_THREAD+THREAD_ESP0)
163 tstb %d0
164 jeq do_signal_return
165
166 pea resume_userspace
167 jmp schedule
168
169do_signal_return:
170 |andw #ALLOWINT,%sr
171 subql #4,%sp | dummy return address
172 SAVE_SWITCH_STACK
173 pea %sp@(SWITCH_STACK_SIZE)
174 clrl %sp@-
175 bsrl do_signal
176 addql #8,%sp
177 RESTORE_SWITCH_STACK
178 addql #4,%sp
179 jbra resume_userspace
180
181do_delayed_trace:
182 bclr #7,%sp@(PT_SR) | clear trace bit in SR
183 pea 1 | send SIGTRAP
184 movel %curptr,%sp@-
185 pea LSIGTRAP
186 jbsr send_sig
187 addql #8,%sp
188 addql #4,%sp
189 jbra resume_userspace
190
191
192#if 0
193#ifdef CONFIG_AMIGA
194ami_inthandler:
195 addql #1,irq_stat+CPUSTAT_LOCAL_IRQ_COUNT
196 SAVE_ALL_INT
197 GET_CURRENT(%d0)
198
199 bfextu %sp@(PT_VECTOR){#4,#12},%d0
200 movel %d0,%a0
201 addql #1,%a0@(kstat+STAT_IRQ-VECOFF(VEC_SPUR))
202 movel %a0@(autoirq_list-VECOFF(VEC_SPUR)),%a0
203
204| amiga vector int handler get the req mask instead of irq vector
205 lea CUSTOMBASE,%a1
206 movew %a1@(C_INTREQR),%d0
207 andw %a1@(C_INTENAR),%d0
208
209| prepare stack (push frame pointer, dev_id & req mask)
210 pea %sp@
211 movel %a0@(IRQ_DEVID),%sp@-
212 movel %d0,%sp@-
213 pea %pc@(ret_from_interrupt:w)
214 jbra @(IRQ_HANDLER,%a0)@(0)
215
216ENTRY(nmi_handler)
217 rte
218#endif
219#endif
220
221/*
222** This is the main interrupt handler, responsible for calling process_int()
223*/
224inthandler:
225 SAVE_ALL_INT
226 GET_CURRENT(%d0)
227 addqb #1,%curptr@(TASK_INFO+TINFO_PREEMPT+2)
228 | put exception # in d0
229 bfextu %sp@(PT_VECTOR){#4,#10},%d0
230
231 movel %sp,%sp@-
232 movel %d0,%sp@- | put vector # on stack
233#if defined(MACH_Q40_ONLY) && defined(CONFIG_BLK_DEV_FD)
234 btstb #4,0xff000000 | Q40 floppy needs very special treatment ...
235 jbeq 1f
236 btstb #3,0xff000004
237 jbeq 1f
238 jbsr floppy_hardint
239 jbra 3f
2401:
241#endif
242 jbsr process_int | process the IRQ
2433: addql #8,%sp | pop parameters off stack
244
245ret_from_interrupt:
246 subqb #1,%curptr@(TASK_INFO+TINFO_PREEMPT+2)
247 jeq 1f
2482:
249 RESTORE_ALL
2501:
251 moveq #(~ALLOWINT>>8)&0xff,%d0
252 andb %sp@(PT_SR),%d0
253 jne 2b
254
255 /* check if we need to do software interrupts */
256 tstl irq_stat+CPUSTAT_SOFTIRQ_PENDING
257 jeq ret_from_exception
258 pea ret_from_exception
259 jra do_softirq
260
261
262/* Handler for uninitialized and spurious interrupts */
263
264bad_interrupt:
265 addql #1,num_spurious
266 rte
267
268ENTRY(sys_fork)
269 SAVE_SWITCH_STACK
270 pea %sp@(SWITCH_STACK_SIZE)
271 jbsr m68k_fork
272 addql #4,%sp
273 RESTORE_SWITCH_STACK
274 rts
275
276ENTRY(sys_clone)
277 SAVE_SWITCH_STACK
278 pea %sp@(SWITCH_STACK_SIZE)
279 jbsr m68k_clone
280 addql #4,%sp
281 RESTORE_SWITCH_STACK
282 rts
283
284ENTRY(sys_vfork)
285 SAVE_SWITCH_STACK
286 pea %sp@(SWITCH_STACK_SIZE)
287 jbsr m68k_vfork
288 addql #4,%sp
289 RESTORE_SWITCH_STACK
290 rts
291
292ENTRY(sys_sigsuspend)
293 SAVE_SWITCH_STACK
294 pea %sp@(SWITCH_STACK_SIZE)
295 jbsr do_sigsuspend
296 addql #4,%sp
297 RESTORE_SWITCH_STACK
298 rts
299
300ENTRY(sys_rt_sigsuspend)
301 SAVE_SWITCH_STACK
302 pea %sp@(SWITCH_STACK_SIZE)
303 jbsr do_rt_sigsuspend
304 addql #4,%sp
305 RESTORE_SWITCH_STACK
306 rts
307
308ENTRY(sys_sigreturn)
309 SAVE_SWITCH_STACK
310 jbsr do_sigreturn
311 RESTORE_SWITCH_STACK
312 rts
313
314ENTRY(sys_rt_sigreturn)
315 SAVE_SWITCH_STACK
316 jbsr do_rt_sigreturn
317 RESTORE_SWITCH_STACK
318 rts
319
320resume:
321 /*
322 * Beware - when entering resume, prev (the current task) is
323 * in a0, next (the new task) is in a1,so don't change these
324 * registers until their contents are no longer needed.
325 */
326
327 /* save sr */
328 movew %sr,%a0@(TASK_THREAD+THREAD_SR)
329
330 /* save fs (sfc,%dfc) (may be pointing to kernel memory) */
331 movec %sfc,%d0
332 movew %d0,%a0@(TASK_THREAD+THREAD_FS)
333
334 /* save usp */
335 /* it is better to use a movel here instead of a movew 8*) */
336 movec %usp,%d0
337 movel %d0,%a0@(TASK_THREAD+THREAD_USP)
338
339 /* save non-scratch registers on stack */
340 SAVE_SWITCH_STACK
341
342 /* save current kernel stack pointer */
343 movel %sp,%a0@(TASK_THREAD+THREAD_KSP)
344
345 /* save floating point context */
346#ifndef CONFIG_M68KFPU_EMU_ONLY
347#ifdef CONFIG_M68KFPU_EMU
348 tstl m68k_fputype
349 jeq 3f
350#endif
351 fsave %a0@(TASK_THREAD+THREAD_FPSTATE)
352
353#if defined(CONFIG_M68060)
354#if !defined(CPU_M68060_ONLY)
355 btst #3,m68k_cputype+3
356 beqs 1f
357#endif
358 /* The 060 FPU keeps status in bits 15-8 of the first longword */
359 tstb %a0@(TASK_THREAD+THREAD_FPSTATE+2)
360 jeq 3f
361#if !defined(CPU_M68060_ONLY)
362 jra 2f
363#endif
364#endif /* CONFIG_M68060 */
365#if !defined(CPU_M68060_ONLY)
3661: tstb %a0@(TASK_THREAD+THREAD_FPSTATE)
367 jeq 3f
368#endif
3692: fmovemx %fp0-%fp7,%a0@(TASK_THREAD+THREAD_FPREG)
370 fmoveml %fpcr/%fpsr/%fpiar,%a0@(TASK_THREAD+THREAD_FPCNTL)
3713:
372#endif /* CONFIG_M68KFPU_EMU_ONLY */
373 /* Return previous task in %d1 */
374 movel %curptr,%d1
375
376 /* switch to new task (a1 contains new task) */
377 movel %a1,%curptr
378
379 /* restore floating point context */
380#ifndef CONFIG_M68KFPU_EMU_ONLY
381#ifdef CONFIG_M68KFPU_EMU
382 tstl m68k_fputype
383 jeq 4f
384#endif
385#if defined(CONFIG_M68060)
386#if !defined(CPU_M68060_ONLY)
387 btst #3,m68k_cputype+3
388 beqs 1f
389#endif
390 /* The 060 FPU keeps status in bits 15-8 of the first longword */
391 tstb %a1@(TASK_THREAD+THREAD_FPSTATE+2)
392 jeq 3f
393#if !defined(CPU_M68060_ONLY)
394 jra 2f
395#endif
396#endif /* CONFIG_M68060 */
397#if !defined(CPU_M68060_ONLY)
3981: tstb %a1@(TASK_THREAD+THREAD_FPSTATE)
399 jeq 3f
400#endif
4012: fmovemx %a1@(TASK_THREAD+THREAD_FPREG),%fp0-%fp7
402 fmoveml %a1@(TASK_THREAD+THREAD_FPCNTL),%fpcr/%fpsr/%fpiar
4033: frestore %a1@(TASK_THREAD+THREAD_FPSTATE)
4044:
405#endif /* CONFIG_M68KFPU_EMU_ONLY */
406
407 /* restore the kernel stack pointer */
408 movel %a1@(TASK_THREAD+THREAD_KSP),%sp
409
410 /* restore non-scratch registers */
411 RESTORE_SWITCH_STACK
412
413 /* restore user stack pointer */
414 movel %a1@(TASK_THREAD+THREAD_USP),%a0
415 movel %a0,%usp
416
417 /* restore fs (sfc,%dfc) */
418 movew %a1@(TASK_THREAD+THREAD_FS),%a0
419 movec %a0,%sfc
420 movec %a0,%dfc
421
422 /* restore status register */
423 movew %a1@(TASK_THREAD+THREAD_SR),%sr
424
425 rts
426
427.data
428ALIGN
429sys_call_table:
430 .long sys_ni_syscall /* 0 - old "setup()" system call*/
431 .long sys_exit
432 .long sys_fork
433 .long sys_read
434 .long sys_write
435 .long sys_open /* 5 */
436 .long sys_close
437 .long sys_waitpid
438 .long sys_creat
439 .long sys_link
440 .long sys_unlink /* 10 */
441 .long sys_execve
442 .long sys_chdir
443 .long sys_time
444 .long sys_mknod
445 .long sys_chmod /* 15 */
446 .long sys_chown16
447 .long sys_ni_syscall /* old break syscall holder */
448 .long sys_stat
449 .long sys_lseek
450 .long sys_getpid /* 20 */
451 .long sys_mount
452 .long sys_oldumount
453 .long sys_setuid16
454 .long sys_getuid16
455 .long sys_stime /* 25 */
456 .long sys_ptrace
457 .long sys_alarm
458 .long sys_fstat
459 .long sys_pause
460 .long sys_utime /* 30 */
461 .long sys_ni_syscall /* old stty syscall holder */
462 .long sys_ni_syscall /* old gtty syscall holder */
463 .long sys_access
464 .long sys_nice
465 .long sys_ni_syscall /* 35 */ /* old ftime syscall holder */
466 .long sys_sync
467 .long sys_kill
468 .long sys_rename
469 .long sys_mkdir
470 .long sys_rmdir /* 40 */
471 .long sys_dup
472 .long sys_pipe
473 .long sys_times
474 .long sys_ni_syscall /* old prof syscall holder */
475 .long sys_brk /* 45 */
476 .long sys_setgid16
477 .long sys_getgid16
478 .long sys_signal
479 .long sys_geteuid16
480 .long sys_getegid16 /* 50 */
481 .long sys_acct
482 .long sys_umount /* recycled never used phys() */
483 .long sys_ni_syscall /* old lock syscall holder */
484 .long sys_ioctl
485 .long sys_fcntl /* 55 */
486 .long sys_ni_syscall /* old mpx syscall holder */
487 .long sys_setpgid
488 .long sys_ni_syscall /* old ulimit syscall holder */
489 .long sys_ni_syscall
490 .long sys_umask /* 60 */
491 .long sys_chroot
492 .long sys_ustat
493 .long sys_dup2
494 .long sys_getppid
495 .long sys_getpgrp /* 65 */
496 .long sys_setsid
497 .long sys_sigaction
498 .long sys_sgetmask
499 .long sys_ssetmask
500 .long sys_setreuid16 /* 70 */
501 .long sys_setregid16
502 .long sys_sigsuspend
503 .long sys_sigpending
504 .long sys_sethostname
505 .long sys_setrlimit /* 75 */
506 .long sys_old_getrlimit
507 .long sys_getrusage
508 .long sys_gettimeofday
509 .long sys_settimeofday
510 .long sys_getgroups16 /* 80 */
511 .long sys_setgroups16
512 .long old_select
513 .long sys_symlink
514 .long sys_lstat
515 .long sys_readlink /* 85 */
516 .long sys_uselib
517 .long sys_swapon
518 .long sys_reboot
519 .long old_readdir
520 .long old_mmap /* 90 */
521 .long sys_munmap
522 .long sys_truncate
523 .long sys_ftruncate
524 .long sys_fchmod
525 .long sys_fchown16 /* 95 */
526 .long sys_getpriority
527 .long sys_setpriority
528 .long sys_ni_syscall /* old profil syscall holder */
529 .long sys_statfs
530 .long sys_fstatfs /* 100 */
531 .long sys_ni_syscall /* ioperm for i386 */
532 .long sys_socketcall
533 .long sys_syslog
534 .long sys_setitimer
535 .long sys_getitimer /* 105 */
536 .long sys_newstat
537 .long sys_newlstat
538 .long sys_newfstat
539 .long sys_ni_syscall
540 .long sys_ni_syscall /* 110 */ /* iopl for i386 */
541 .long sys_vhangup
542 .long sys_ni_syscall /* obsolete idle() syscall */
543 .long sys_ni_syscall /* vm86old for i386 */
544 .long sys_wait4
545 .long sys_swapoff /* 115 */
546 .long sys_sysinfo
547 .long sys_ipc
548 .long sys_fsync
549 .long sys_sigreturn
550 .long sys_clone /* 120 */
551 .long sys_setdomainname
552 .long sys_newuname
553 .long sys_cacheflush /* modify_ldt for i386 */
554 .long sys_adjtimex
555 .long sys_mprotect /* 125 */
556 .long sys_sigprocmask
557 .long sys_ni_syscall /* old "create_module" */
558 .long sys_init_module
559 .long sys_delete_module
560 .long sys_ni_syscall /* 130 - old "get_kernel_syms" */
561 .long sys_quotactl
562 .long sys_getpgid
563 .long sys_fchdir
564 .long sys_bdflush
565 .long sys_sysfs /* 135 */
566 .long sys_personality
567 .long sys_ni_syscall /* for afs_syscall */
568 .long sys_setfsuid16
569 .long sys_setfsgid16
570 .long sys_llseek /* 140 */
571 .long sys_getdents
572 .long sys_select
573 .long sys_flock
574 .long sys_msync
575 .long sys_readv /* 145 */
576 .long sys_writev
577 .long sys_getsid
578 .long sys_fdatasync
579 .long sys_sysctl
580 .long sys_mlock /* 150 */
581 .long sys_munlock
582 .long sys_mlockall
583 .long sys_munlockall
584 .long sys_sched_setparam
585 .long sys_sched_getparam /* 155 */
586 .long sys_sched_setscheduler
587 .long sys_sched_getscheduler
588 .long sys_sched_yield
589 .long sys_sched_get_priority_max
590 .long sys_sched_get_priority_min /* 160 */
591 .long sys_sched_rr_get_interval
592 .long sys_nanosleep
593 .long sys_mremap
594 .long sys_setresuid16
595 .long sys_getresuid16 /* 165 */
596 .long sys_getpagesize
597 .long sys_ni_syscall /* old sys_query_module */
598 .long sys_poll
599 .long sys_nfsservctl
600 .long sys_setresgid16 /* 170 */
601 .long sys_getresgid16
602 .long sys_prctl
603 .long sys_rt_sigreturn
604 .long sys_rt_sigaction
605 .long sys_rt_sigprocmask /* 175 */
606 .long sys_rt_sigpending
607 .long sys_rt_sigtimedwait
608 .long sys_rt_sigqueueinfo
609 .long sys_rt_sigsuspend
610 .long sys_pread64 /* 180 */
611 .long sys_pwrite64
612 .long sys_lchown16;
613 .long sys_getcwd
614 .long sys_capget
615 .long sys_capset /* 185 */
616 .long sys_sigaltstack
617 .long sys_sendfile
618 .long sys_ni_syscall /* streams1 */
619 .long sys_ni_syscall /* streams2 */
620 .long sys_vfork /* 190 */
621 .long sys_getrlimit
622 .long sys_mmap2
623 .long sys_truncate64
624 .long sys_ftruncate64
625 .long sys_stat64 /* 195 */
626 .long sys_lstat64
627 .long sys_fstat64
628 .long sys_chown
629 .long sys_getuid
630 .long sys_getgid /* 200 */
631 .long sys_geteuid
632 .long sys_getegid
633 .long sys_setreuid
634 .long sys_setregid
635 .long sys_getgroups /* 205 */
636 .long sys_setgroups
637 .long sys_fchown
638 .long sys_setresuid
639 .long sys_getresuid
640 .long sys_setresgid /* 210 */
641 .long sys_getresgid
642 .long sys_lchown
643 .long sys_setuid
644 .long sys_setgid
645 .long sys_setfsuid /* 215 */
646 .long sys_setfsgid
647 .long sys_pivot_root
648 .long sys_ni_syscall
649 .long sys_ni_syscall
650 .long sys_getdents64 /* 220 */
651 .long sys_gettid
652 .long sys_tkill
653 .long sys_setxattr
654 .long sys_lsetxattr
655 .long sys_fsetxattr /* 225 */
656 .long sys_getxattr
657 .long sys_lgetxattr
658 .long sys_fgetxattr
659 .long sys_listxattr
660 .long sys_llistxattr /* 230 */
661 .long sys_flistxattr
662 .long sys_removexattr
663 .long sys_lremovexattr
664 .long sys_fremovexattr
665 .long sys_futex /* 235 */
666 .long sys_sendfile64
667 .long sys_mincore
668 .long sys_madvise
669 .long sys_fcntl64
670 .long sys_readahead /* 240 */
671 .long sys_io_setup
672 .long sys_io_destroy
673 .long sys_io_getevents
674 .long sys_io_submit
675 .long sys_io_cancel /* 245 */
676 .long sys_fadvise64
677 .long sys_exit_group
678 .long sys_lookup_dcookie
679 .long sys_epoll_create
680 .long sys_epoll_ctl /* 250 */
681 .long sys_epoll_wait
682 .long sys_remap_file_pages
683 .long sys_set_tid_address
684 .long sys_timer_create
685 .long sys_timer_settime /* 255 */
686 .long sys_timer_gettime
687 .long sys_timer_getoverrun
688 .long sys_timer_delete
689 .long sys_clock_settime
690 .long sys_clock_gettime /* 260 */
691 .long sys_clock_getres
692 .long sys_clock_nanosleep
693 .long sys_statfs64
694 .long sys_fstatfs64
695 .long sys_tgkill /* 265 */
696 .long sys_utimes
697 .long sys_fadvise64_64
698 .long sys_mbind
699 .long sys_get_mempolicy
700 .long sys_set_mempolicy /* 270 */
701 .long sys_mq_open
702 .long sys_mq_unlink
703 .long sys_mq_timedsend
704 .long sys_mq_timedreceive
705 .long sys_mq_notify /* 275 */
706 .long sys_mq_getsetattr
707 .long sys_waitid
708 .long sys_ni_syscall /* for sys_vserver */
709 .long sys_add_key
710 .long sys_request_key /* 280 */
711 .long sys_keyctl
712
diff --git a/arch/m68k/kernel/head.S b/arch/m68k/kernel/head.S
new file mode 100644
index 000000000000..7cd6de17c20d
--- /dev/null
+++ b/arch/m68k/kernel/head.S
@@ -0,0 +1,3940 @@
1/* -*- mode: asm -*-
2**
3** head.S -- This file contains the initial boot code for the
4** Linux/68k kernel.
5**
6** Copyright 1993 by Hamish Macdonald
7**
8** 68040 fixes by Michael Rausch
9** 68060 fixes by Roman Hodek
10** MMU cleanup by Randy Thelen
11** Final MMU cleanup by Roman Zippel
12**
13** Atari support by Andreas Schwab, using ideas of Robert de Vries
14** and Bjoern Brauel
15** VME Support by Richard Hirst
16**
17** 94/11/14 Andreas Schwab: put kernel at PAGESIZE
18** 94/11/18 Andreas Schwab: remove identity mapping of STRAM for Atari
19** ++ Bjoern & Roman: ATARI-68040 support for the Medusa
20** 95/11/18 Richard Hirst: Added MVME166 support
21** 96/04/26 Guenther Kelleter: fixed identity mapping for Falcon with
22** Magnum- and FX-alternate ram
23** 98/04/25 Phil Blundell: added HP300 support
24** 1998/08/30 David Kilzer: Added support for font_desc structures
25** for linux-2.1.115
26** 9/02/11 Richard Zidlicky: added Q40 support (initial vesion 99/01/01)
27** 2004/05/13 Kars de Jong: Finalised HP300 support
28**
29** This file is subject to the terms and conditions of the GNU General Public
30** License. See the file README.legal in the main directory of this archive
31** for more details.
32**
33*/
34
35/*
36 * Linux startup code.
37 *
38 * At this point, the boot loader has:
39 * Disabled interrupts
40 * Disabled caches
41 * Put us in supervisor state.
42 *
43 * The kernel setup code takes the following steps:
44 * . Raise interrupt level
45 * . Set up initial kernel memory mapping.
46 * . This sets up a mapping of the 4M of memory the kernel is located in.
47 * . It also does a mapping of any initial machine specific areas.
48 * . Enable the MMU
49 * . Enable cache memories
50 * . Jump to kernel startup
51 *
52 * Much of the file restructuring was to accomplish:
53 * 1) Remove register dependency through-out the file.
54 * 2) Increase use of subroutines to perform functions
55 * 3) Increase readability of the code
56 *
57 * Of course, readability is a subjective issue, so it will never be
58 * argued that that goal was accomplished. It was merely a goal.
59 * A key way to help make code more readable is to give good
60 * documentation. So, the first thing you will find is exaustive
61 * write-ups on the structure of the file, and the features of the
62 * functional subroutines.
63 *
64 * General Structure:
65 * ------------------
66 * Without a doubt the single largest chunk of head.S is spent
67 * mapping the kernel and I/O physical space into the logical range
68 * for the kernel.
69 * There are new subroutines and data structures to make MMU
70 * support cleaner and easier to understand.
71 * First, you will find a routine call "mmu_map" which maps
72 * a logical to a physical region for some length given a cache
73 * type on behalf of the caller. This routine makes writing the
74 * actual per-machine specific code very simple.
75 * A central part of the code, but not a subroutine in itself,
76 * is the mmu_init code which is broken down into mapping the kernel
77 * (the same for all machines) and mapping machine-specific I/O
78 * regions.
79 * Also, there will be a description of engaging the MMU and
80 * caches.
81 * You will notice that there is a chunk of code which
82 * can emit the entire MMU mapping of the machine. This is present
83 * only in debug modes and can be very helpful.
84 * Further, there is a new console driver in head.S that is
85 * also only engaged in debug mode. Currently, it's only supported
86 * on the Macintosh class of machines. However, it is hoped that
87 * others will plug-in support for specific machines.
88 *
89 * ######################################################################
90 *
91 * mmu_map
92 * -------
93 * mmu_map was written for two key reasons. First, it was clear
94 * that it was very difficult to read the previous code for mapping
95 * regions of memory. Second, the Macintosh required such extensive
96 * memory allocations that it didn't make sense to propagate the
97 * existing code any further.
98 * mmu_map requires some parameters:
99 *
100 * mmu_map (logical, physical, length, cache_type)
101 *
102 * While this essentially describes the function in the abstract, you'll
103 * find more indepth description of other parameters at the implementation site.
104 *
105 * mmu_get_root_table_entry
106 * ------------------------
107 * mmu_get_ptr_table_entry
108 * -----------------------
109 * mmu_get_page_table_entry
110 * ------------------------
111 *
112 * These routines are used by other mmu routines to get a pointer into
113 * a table, if necessary a new table is allocated. These routines are working
114 * basically like pmd_alloc() and pte_alloc() in <asm/pgtable.h>. The root
115 * table needs of course only to be allocated once in mmu_get_root_table_entry,
116 * so that here also some mmu specific initialization is done. The second page
117 * at the start of the kernel (the first page is unmapped later) is used for
118 * the kernel_pg_dir. It must be at a position known at link time (as it's used
119 * to initialize the init task struct) and since it needs special cache
120 * settings, it's the easiest to use this page, the rest of the page is used
121 * for further pointer tables.
122 * mmu_get_page_table_entry allocates always a whole page for page tables, this
123 * means 1024 pages and so 4MB of memory can be mapped. It doesn't make sense
124 * to manage page tables in smaller pieces as nearly all mappings have that
125 * size.
126 *
127 * ######################################################################
128 *
129 *
130 * ######################################################################
131 *
132 * mmu_engage
133 * ----------
134 * Thanks to a small helping routine enabling the mmu got quite simple
135 * and there is only one way left. mmu_engage makes a complete a new mapping
136 * that only includes the absolute necessary to be able to jump to the final
137 * postion and to restore the original mapping.
138 * As this code doesn't need a transparent translation register anymore this
139 * means all registers are free to be used by machines that needs them for
140 * other purposes.
141 *
142 * ######################################################################
143 *
144 * mmu_print
145 * ---------
146 * This algorithm will print out the page tables of the system as
147 * appropriate for an 030 or an 040. This is useful for debugging purposes
148 * and as such is enclosed in #ifdef MMU_PRINT/#endif clauses.
149 *
150 * ######################################################################
151 *
152 * console_init
153 * ------------
154 * The console is also able to be turned off. The console in head.S
155 * is specifically for debugging and can be very useful. It is surrounded by
156 * #ifdef CONSOLE/#endif clauses so it doesn't have to ship in known-good
157 * kernels. It's basic algorithm is to determine the size of the screen
158 * (in height/width and bit depth) and then use that information for
159 * displaying an 8x8 font or an 8x16 (widthxheight). I prefer the 8x8 for
160 * debugging so I can see more good data. But it was trivial to add support
161 * for both fonts, so I included it.
162 * Also, the algorithm for plotting pixels is abstracted so that in
163 * theory other platforms could add support for different kinds of frame
164 * buffers. This could be very useful.
165 *
166 * console_put_penguin
167 * -------------------
168 * An important part of any Linux bring up is the penguin and there's
169 * nothing like getting the Penguin on the screen! This algorithm will work
170 * on any machine for which there is a console_plot_pixel.
171 *
172 * console_scroll
173 * --------------
174 * My hope is that the scroll algorithm does the right thing on the
175 * various platforms, but it wouldn't be hard to add the test conditions
176 * and new code if it doesn't.
177 *
178 * console_putc
179 * -------------
180 *
181 * ######################################################################
182 *
183 * Register usage has greatly simplified within head.S. Every subroutine
184 * saves and restores all registers that it modifies (except it returns a
185 * value in there of course). So the only register that needs to be initialized
186 * is the stack pointer.
187 * All other init code and data is now placed in the init section, so it will
188 * be automatically freed at the end of the kernel initialization.
189 *
190 * ######################################################################
191 *
192 * options
193 * -------
194 * There are many options available in a build of this file. I've
195 * taken the time to describe them here to save you the time of searching
196 * for them and trying to understand what they mean.
197 *
198 * CONFIG_xxx: These are the obvious machine configuration defines created
199 * during configuration. These are defined in include/linux/autoconf.h.
200 *
201 * CONSOLE: There is support for head.S console in this file. This
202 * console can talk to a Mac frame buffer, but could easily be extrapolated
203 * to extend it to support other platforms.
204 *
205 * TEST_MMU: This is a test harness for running on any given machine but
206 * getting an MMU dump for another class of machine. The classes of machines
207 * that can be tested are any of the makes (Atari, Amiga, Mac, VME, etc.)
208 * and any of the models (030, 040, 060, etc.).
209 *
210 * NOTE: TEST_MMU is NOT permanent! It is scheduled to be removed
211 * When head.S boots on Atari, Amiga, Macintosh, and VME
212 * machines. At that point the underlying logic will be
213 * believed to be solid enough to be trusted, and TEST_MMU
214 * can be dropped. Do note that that will clean up the
215 * head.S code significantly as large blocks of #if/#else
216 * clauses can be removed.
217 *
218 * MMU_NOCACHE_KERNEL: On the Macintosh platform there was an inquiry into
219 * determing why devices don't appear to work. A test case was to remove
220 * the cacheability of the kernel bits.
221 *
222 * MMU_PRINT: There is a routine built into head.S that can display the
223 * MMU data structures. It outputs its result through the serial_putc
224 * interface. So where ever that winds up driving data, that's where the
225 * mmu struct will appear. On the Macintosh that's typically the console.
226 *
227 * SERIAL_DEBUG: There are a series of putc() macro statements
228 * scattered through out the code to give progress of status to the
229 * person sitting at the console. This constant determines whether those
230 * are used.
231 *
232 * DEBUG: This is the standard DEBUG flag that can be set for building
233 * the kernel. It has the effect adding additional tests into
234 * the code.
235 *
236 * FONT_6x11:
237 * FONT_8x8:
238 * FONT_8x16:
239 * In theory these could be determined at run time or handed
240 * over by the booter. But, let's be real, it's a fine hard
241 * coded value. (But, you will notice the code is run-time
242 * flexible!) A pointer to the font's struct font_desc
243 * is kept locally in Lconsole_font. It is used to determine
244 * font size information dynamically.
245 *
246 * Atari constants:
247 * USE_PRINTER: Use the printer port for serial debug.
248 * USE_SCC_B: Use the SCC port A (Serial2) for serial debug.
249 * USE_SCC_A: Use the SCC port B (Modem2) for serial debug.
250 * USE_MFP: Use the ST-MFP port (Modem1) for serial debug.
251 *
252 * Macintosh constants:
253 * MAC_SERIAL_DEBUG: Turns on serial debug output for the Macintosh.
254 * MAC_USE_SCC_A: Use the SCC port A (modem) for serial debug.
255 * MAC_USE_SCC_B: Use the SCC port B (printer) for serial debug (default).
256 */
257
258#include <linux/config.h>
259#include <linux/linkage.h>
260#include <linux/init.h>
261#include <asm/bootinfo.h>
262#include <asm/setup.h>
263#include <asm/entry.h>
264#include <asm/pgtable.h>
265#include <asm/page.h>
266#include <asm/offsets.h>
267
268#ifdef CONFIG_MAC
269
270#include <asm/machw.h>
271
272/*
273 * Macintosh console support
274 */
275
276#define CONSOLE
277#define CONSOLE_PENGUIN
278
279/*
280 * Macintosh serial debug support; outputs boot info to the printer
281 * and/or modem serial ports
282 */
283#undef MAC_SERIAL_DEBUG
284
285/*
286 * Macintosh serial debug port selection; define one or both;
287 * requires MAC_SERIAL_DEBUG to be defined
288 */
289#define MAC_USE_SCC_A /* Macintosh modem serial port */
290#define MAC_USE_SCC_B /* Macintosh printer serial port */
291
292#endif /* CONFIG_MAC */
293
294#undef MMU_PRINT
295#undef MMU_NOCACHE_KERNEL
296#define SERIAL_DEBUG
297#undef DEBUG
298
299/*
300 * For the head.S console, there are three supported fonts, 6x11, 8x16 and 8x8.
301 * The 8x8 font is harder to read but fits more on the screen.
302 */
303#define FONT_8x8 /* default */
304/* #define FONT_8x16 */ /* 2nd choice */
305/* #define FONT_6x11 */ /* 3rd choice */
306
307.globl kernel_pg_dir
308.globl availmem
309.globl m68k_pgtable_cachemode
310.globl m68k_supervisor_cachemode
311#ifdef CONFIG_MVME16x
312.globl mvme_bdid
313#endif
314#ifdef CONFIG_Q40
315.globl q40_mem_cptr
316#endif
317
318CPUTYPE_040 = 1 /* indicates an 040 */
319CPUTYPE_060 = 2 /* indicates an 060 */
320CPUTYPE_0460 = 3 /* if either above are set, this is set */
321CPUTYPE_020 = 4 /* indicates an 020 */
322
323/* Translation control register */
324TC_ENABLE = 0x8000
325TC_PAGE8K = 0x4000
326TC_PAGE4K = 0x0000
327
328/* Transparent translation registers */
329TTR_ENABLE = 0x8000 /* enable transparent translation */
330TTR_ANYMODE = 0x4000 /* user and kernel mode access */
331TTR_KERNELMODE = 0x2000 /* only kernel mode access */
332TTR_USERMODE = 0x0000 /* only user mode access */
333TTR_CI = 0x0400 /* inhibit cache */
334TTR_RW = 0x0200 /* read/write mode */
335TTR_RWM = 0x0100 /* read/write mask */
336TTR_FCB2 = 0x0040 /* function code base bit 2 */
337TTR_FCB1 = 0x0020 /* function code base bit 1 */
338TTR_FCB0 = 0x0010 /* function code base bit 0 */
339TTR_FCM2 = 0x0004 /* function code mask bit 2 */
340TTR_FCM1 = 0x0002 /* function code mask bit 1 */
341TTR_FCM0 = 0x0001 /* function code mask bit 0 */
342
343/* Cache Control registers */
344CC6_ENABLE_D = 0x80000000 /* enable data cache (680[46]0) */
345CC6_FREEZE_D = 0x40000000 /* freeze data cache (68060) */
346CC6_ENABLE_SB = 0x20000000 /* enable store buffer (68060) */
347CC6_PUSH_DPI = 0x10000000 /* disable CPUSH invalidation (68060) */
348CC6_HALF_D = 0x08000000 /* half-cache mode for data cache (68060) */
349CC6_ENABLE_B = 0x00800000 /* enable branch cache (68060) */
350CC6_CLRA_B = 0x00400000 /* clear all entries in branch cache (68060) */
351CC6_CLRU_B = 0x00200000 /* clear user entries in branch cache (68060) */
352CC6_ENABLE_I = 0x00008000 /* enable instruction cache (680[46]0) */
353CC6_FREEZE_I = 0x00004000 /* freeze instruction cache (68060) */
354CC6_HALF_I = 0x00002000 /* half-cache mode for instruction cache (68060) */
355CC3_ALLOC_WRITE = 0x00002000 /* write allocate mode(68030) */
356CC3_ENABLE_DB = 0x00001000 /* enable data burst (68030) */
357CC3_CLR_D = 0x00000800 /* clear data cache (68030) */
358CC3_CLRE_D = 0x00000400 /* clear entry in data cache (68030) */
359CC3_FREEZE_D = 0x00000200 /* freeze data cache (68030) */
360CC3_ENABLE_D = 0x00000100 /* enable data cache (68030) */
361CC3_ENABLE_IB = 0x00000010 /* enable instruction burst (68030) */
362CC3_CLR_I = 0x00000008 /* clear instruction cache (68030) */
363CC3_CLRE_I = 0x00000004 /* clear entry in instruction cache (68030) */
364CC3_FREEZE_I = 0x00000002 /* freeze instruction cache (68030) */
365CC3_ENABLE_I = 0x00000001 /* enable instruction cache (68030) */
366
367/* Miscellaneous definitions */
368PAGESIZE = 4096
369PAGESHIFT = 12
370
371ROOT_TABLE_SIZE = 128
372PTR_TABLE_SIZE = 128
373PAGE_TABLE_SIZE = 64
374ROOT_INDEX_SHIFT = 25
375PTR_INDEX_SHIFT = 18
376PAGE_INDEX_SHIFT = 12
377
378#ifdef DEBUG
379/* When debugging use readable names for labels */
380#ifdef __STDC__
381#define L(name) .head.S.##name
382#else
383#define L(name) .head.S./**/name
384#endif
385#else
386#ifdef __STDC__
387#define L(name) .L##name
388#else
389#define L(name) .L/**/name
390#endif
391#endif
392
393/* The __INITDATA stuff is a no-op when ftrace or kgdb are turned on */
394#ifndef __INITDATA
395#define __INITDATA .data
396#define __FINIT .previous
397#endif
398
399/* Several macros to make the writing of subroutines easier:
400 * - func_start marks the beginning of the routine which setups the frame
401 * register and saves the registers, it also defines another macro
402 * to automatically restore the registers again.
403 * - func_return marks the end of the routine and simply calls the prepared
404 * macro to restore registers and jump back to the caller.
405 * - func_define generates another macro to automatically put arguments
406 * onto the stack call the subroutine and cleanup the stack again.
407 */
408
409/* Within subroutines these macros can be used to access the arguments
410 * on the stack. With STACK some allocated memory on the stack can be
411 * accessed and ARG0 points to the return address (used by mmu_engage).
412 */
413#define STACK %a6@(stackstart)
414#define ARG0 %a6@(4)
415#define ARG1 %a6@(8)
416#define ARG2 %a6@(12)
417#define ARG3 %a6@(16)
418#define ARG4 %a6@(20)
419
420.macro func_start name,saveregs,stack=0
421L(\name):
422 linkw %a6,#-\stack
423 moveml \saveregs,%sp@-
424.set stackstart,-\stack
425
426.macro func_return_\name
427 moveml %sp@+,\saveregs
428 unlk %a6
429 rts
430.endm
431.endm
432
433.macro func_return name
434 func_return_\name
435.endm
436
437.macro func_call name
438 jbsr L(\name)
439.endm
440
441.macro move_stack nr,arg1,arg2,arg3,arg4
442.if \nr
443 move_stack "(\nr-1)",\arg2,\arg3,\arg4
444 movel \arg1,%sp@-
445.endif
446.endm
447
448.macro func_define name,nr=0
449.macro \name arg1,arg2,arg3,arg4
450 move_stack \nr,\arg1,\arg2,\arg3,\arg4
451 func_call \name
452.if \nr
453 lea %sp@(\nr*4),%sp
454.endif
455.endm
456.endm
457
458func_define mmu_map,4
459func_define mmu_map_tt,4
460func_define mmu_fixup_page_mmu_cache,1
461func_define mmu_temp_map,2
462func_define mmu_engage
463func_define mmu_get_root_table_entry,1
464func_define mmu_get_ptr_table_entry,2
465func_define mmu_get_page_table_entry,2
466func_define mmu_print
467func_define get_new_page
468#if defined(CONFIG_HP300) || defined(CONFIG_APOLLO)
469func_define set_leds
470#endif
471
472.macro mmu_map_eq arg1,arg2,arg3
473 mmu_map \arg1,\arg1,\arg2,\arg3
474.endm
475
476.macro get_bi_record record
477 pea \record
478 func_call get_bi_record
479 addql #4,%sp
480.endm
481
482func_define serial_putc,1
483func_define console_putc,1
484
485func_define console_init
486func_define console_put_stats
487func_define console_put_penguin
488func_define console_plot_pixel,3
489func_define console_scroll
490
491.macro putc ch
492#if defined(CONSOLE) || defined(SERIAL_DEBUG)
493 pea \ch
494#endif
495#ifdef CONSOLE
496 func_call console_putc
497#endif
498#ifdef SERIAL_DEBUG
499 func_call serial_putc
500#endif
501#if defined(CONSOLE) || defined(SERIAL_DEBUG)
502 addql #4,%sp
503#endif
504.endm
505
506.macro dputc ch
507#ifdef DEBUG
508 putc \ch
509#endif
510.endm
511
512func_define putn,1
513
514.macro dputn nr
515#ifdef DEBUG
516 putn \nr
517#endif
518.endm
519
520.macro puts string
521#if defined(CONSOLE) || defined(SERIAL_DEBUG)
522 __INITDATA
523.Lstr\@:
524 .string "\string"
525 __FINIT
526 pea %pc@(.Lstr\@)
527 func_call puts
528 addql #4,%sp
529#endif
530.endm
531
532.macro dputs string
533#ifdef DEBUG
534 puts "\string"
535#endif
536.endm
537
538#define is_not_amiga(lab) cmpl &MACH_AMIGA,%pc@(m68k_machtype); jne lab
539#define is_not_atari(lab) cmpl &MACH_ATARI,%pc@(m68k_machtype); jne lab
540#define is_not_mac(lab) cmpl &MACH_MAC,%pc@(m68k_machtype); jne lab
541#define is_not_mvme147(lab) cmpl &MACH_MVME147,%pc@(m68k_machtype); jne lab
542#define is_not_mvme16x(lab) cmpl &MACH_MVME16x,%pc@(m68k_machtype); jne lab
543#define is_not_bvme6000(lab) cmpl &MACH_BVME6000,%pc@(m68k_machtype); jne lab
544#define is_mvme147(lab) cmpl &MACH_MVME147,%pc@(m68k_machtype); jeq lab
545#define is_mvme16x(lab) cmpl &MACH_MVME16x,%pc@(m68k_machtype); jeq lab
546#define is_bvme6000(lab) cmpl &MACH_BVME6000,%pc@(m68k_machtype); jeq lab
547#define is_not_hp300(lab) cmpl &MACH_HP300,%pc@(m68k_machtype); jne lab
548#define is_not_apollo(lab) cmpl &MACH_APOLLO,%pc@(m68k_machtype); jne lab
549#define is_not_q40(lab) cmpl &MACH_Q40,%pc@(m68k_machtype); jne lab
550#define is_not_sun3x(lab) cmpl &MACH_SUN3X,%pc@(m68k_machtype); jne lab
551
552#define hasnt_leds(lab) cmpl &MACH_HP300,%pc@(m68k_machtype); \
553 jeq 42f; \
554 cmpl &MACH_APOLLO,%pc@(m68k_machtype); \
555 jne lab ;\
556 42:\
557
558#define is_040_or_060(lab) btst &CPUTYPE_0460,%pc@(L(cputype)+3); jne lab
559#define is_not_040_or_060(lab) btst &CPUTYPE_0460,%pc@(L(cputype)+3); jeq lab
560#define is_040(lab) btst &CPUTYPE_040,%pc@(L(cputype)+3); jne lab
561#define is_060(lab) btst &CPUTYPE_060,%pc@(L(cputype)+3); jne lab
562#define is_not_060(lab) btst &CPUTYPE_060,%pc@(L(cputype)+3); jeq lab
563#define is_020(lab) btst &CPUTYPE_020,%pc@(L(cputype)+3); jne lab
564#define is_not_020(lab) btst &CPUTYPE_020,%pc@(L(cputype)+3); jeq lab
565
566/* On the HP300 we use the on-board LEDs for debug output before
567 the console is running. Writing a 1 bit turns the corresponding LED
568 _off_ - on the 340 bit 7 is towards the back panel of the machine. */
569.macro leds mask
570#if defined(CONFIG_HP300) || defined(CONFIG_APOLLO)
571 hasnt_leds(.Lled\@)
572 pea \mask
573 func_call set_leds
574 addql #4,%sp
575.Lled\@:
576#endif
577.endm
578
579.text
580ENTRY(_stext)
581/*
582 * Version numbers of the bootinfo interface
583 * The area from _stext to _start will later be used as kernel pointer table
584 */
585 bras 1f /* Jump over bootinfo version numbers */
586
587 .long BOOTINFOV_MAGIC
588 .long MACH_AMIGA, AMIGA_BOOTI_VERSION
589 .long MACH_ATARI, ATARI_BOOTI_VERSION
590 .long MACH_MVME147, MVME147_BOOTI_VERSION
591 .long MACH_MVME16x, MVME16x_BOOTI_VERSION
592 .long MACH_BVME6000, BVME6000_BOOTI_VERSION
593 .long MACH_MAC, MAC_BOOTI_VERSION
594 .long MACH_Q40, Q40_BOOTI_VERSION
595 .long MACH_HP300, HP300_BOOTI_VERSION
596 .long 0
5971: jra __start
598
599.equ kernel_pg_dir,_stext
600
601.equ .,_stext+PAGESIZE
602
603ENTRY(_start)
604 jra __start
605__INIT
606ENTRY(__start)
607/*
608 * Setup initial stack pointer
609 */
610 lea %pc@(_stext),%sp
611
612/*
613 * Record the CPU and machine type.
614 */
615 get_bi_record BI_MACHTYPE
616 lea %pc@(m68k_machtype),%a1
617 movel %a0@,%a1@
618
619 get_bi_record BI_FPUTYPE
620 lea %pc@(m68k_fputype),%a1
621 movel %a0@,%a1@
622
623 get_bi_record BI_MMUTYPE
624 lea %pc@(m68k_mmutype),%a1
625 movel %a0@,%a1@
626
627 get_bi_record BI_CPUTYPE
628 lea %pc@(m68k_cputype),%a1
629 movel %a0@,%a1@
630
631 leds 0x1
632
633#ifdef CONFIG_MAC
634/*
635 * For Macintosh, we need to determine the display parameters early (at least
636 * while debugging it).
637 */
638
639 is_not_mac(L(test_notmac))
640
641 get_bi_record BI_MAC_VADDR
642 lea %pc@(L(mac_videobase)),%a1
643 movel %a0@,%a1@
644
645 get_bi_record BI_MAC_VDEPTH
646 lea %pc@(L(mac_videodepth)),%a1
647 movel %a0@,%a1@
648
649 get_bi_record BI_MAC_VDIM
650 lea %pc@(L(mac_dimensions)),%a1
651 movel %a0@,%a1@
652
653 get_bi_record BI_MAC_VROW
654 lea %pc@(L(mac_rowbytes)),%a1
655 movel %a0@,%a1@
656
657#ifdef MAC_SERIAL_DEBUG
658 get_bi_record BI_MAC_SCCBASE
659 lea %pc@(L(mac_sccbase)),%a1
660 movel %a0@,%a1@
661#endif /* MAC_SERIAL_DEBUG */
662
663#if 0
664 /*
665 * Clear the screen
666 */
667 lea %pc@(L(mac_videobase)),%a0
668 movel %a0@,%a1
669 lea %pc@(L(mac_dimensions)),%a0
670 movel %a0@,%d1
671 swap %d1 /* #rows is high bytes */
672 andl #0xFFFF,%d1 /* rows */
673 subl #10,%d1
674 lea %pc@(L(mac_rowbytes)),%a0
675loopy2:
676 movel %a0@,%d0
677 subql #1,%d0
678loopx2:
679 moveb #0x55, %a1@+
680 dbra %d0,loopx2
681 dbra %d1,loopy2
682#endif
683
684L(test_notmac):
685#endif /* CONFIG_MAC */
686
687
688/*
689 * There are ultimately two pieces of information we want for all kinds of
690 * processors CpuType and CacheBits. The CPUTYPE was passed in from booter
691 * and is converted here from a booter type definition to a separate bit
692 * number which allows for the standard is_0x0 macro tests.
693 */
694 movel %pc@(m68k_cputype),%d0
695 /*
696 * Assume it's an 030
697 */
698 clrl %d1
699
700 /*
701 * Test the BootInfo cputype for 060
702 */
703 btst #CPUB_68060,%d0
704 jeq 1f
705 bset #CPUTYPE_060,%d1
706 bset #CPUTYPE_0460,%d1
707 jra 3f
7081:
709 /*
710 * Test the BootInfo cputype for 040
711 */
712 btst #CPUB_68040,%d0
713 jeq 2f
714 bset #CPUTYPE_040,%d1
715 bset #CPUTYPE_0460,%d1
716 jra 3f
7172:
718 /*
719 * Test the BootInfo cputype for 020
720 */
721 btst #CPUB_68020,%d0
722 jeq 3f
723 bset #CPUTYPE_020,%d1
724 jra 3f
7253:
726 /*
727 * Record the cpu type
728 */
729 lea %pc@(L(cputype)),%a0
730 movel %d1,%a0@
731
732 /*
733 * NOTE:
734 *
735 * Now the macros are valid:
736 * is_040_or_060
737 * is_not_040_or_060
738 * is_040
739 * is_060
740 * is_not_060
741 */
742
743 /*
744 * Determine the cache mode for pages holding MMU tables
745 * and for supervisor mode, unused for '020 and '030
746 */
747 clrl %d0
748 clrl %d1
749
750 is_not_040_or_060(L(save_cachetype))
751
752 /*
753 * '040 or '060
754 * d1 := cacheable write-through
755 * NOTE: The 68040 manual strongly recommends non-cached for MMU tables,
756 * but we have been using write-through since at least 2.0.29 so I
757 * guess it is OK.
758 */
759#ifdef CONFIG_060_WRITETHROUGH
760 /*
761 * If this is a 68060 board using drivers with cache coherency
762 * problems, then supervisor memory accesses need to be write-through
763 * also; otherwise, we want copyback.
764 */
765
766 is_not_060(1f)
767 movel #_PAGE_CACHE040W,%d0
768 jra L(save_cachetype)
769#endif /* CONFIG_060_WRITETHROUGH */
7701:
771 movew #_PAGE_CACHE040,%d0
772
773 movel #_PAGE_CACHE040W,%d1
774
775L(save_cachetype):
776 /* Save cache mode for supervisor mode and page tables
777 */
778 lea %pc@(m68k_supervisor_cachemode),%a0
779 movel %d0,%a0@
780 lea %pc@(m68k_pgtable_cachemode),%a0
781 movel %d1,%a0@
782
783/*
784 * raise interrupt level
785 */
786 movew #0x2700,%sr
787
788/*
789 If running on an Atari, determine the I/O base of the
790 serial port and test if we are running on a Medusa or Hades.
791 This test is necessary here, because on the Hades the serial
792 port is only accessible in the high I/O memory area.
793
794 The test whether it is a Medusa is done by writing to the byte at
795 phys. 0x0. This should result in a bus error on all other machines.
796
797 ...should, but doesn't. The Afterburner040 for the Falcon has the
798 same behaviour (0x0..0x7 are no ROM shadow). So we have to do
799 another test to distinguish Medusa and AB040. This is a
800 read attempt for 0x00ff82fe phys. that should bus error on a Falcon
801 (+AB040), but is in the range where the Medusa always asserts DTACK.
802
803 The test for the Hades is done by reading address 0xb0000000. This
804 should give a bus error on the Medusa.
805 */
806
807#ifdef CONFIG_ATARI
808 is_not_atari(L(notypetest))
809
810 /* get special machine type (Medusa/Hades/AB40) */
811 moveq #0,%d3 /* default if tag doesn't exist */
812 get_bi_record BI_ATARI_MCH_TYPE
813 tstl %d0
814 jbmi 1f
815 movel %a0@,%d3
816 lea %pc@(atari_mch_type),%a0
817 movel %d3,%a0@
8181:
819 /* On the Hades, the iobase must be set up before opening the
820 * serial port. There are no I/O regs at 0x00ffxxxx at all. */
821 moveq #0,%d0
822 cmpl #ATARI_MACH_HADES,%d3
823 jbne 1f
824 movel #0xff000000,%d0 /* Hades I/O base addr: 0xff000000 */
8251: lea %pc@(L(iobase)),%a0
826 movel %d0,%a0@
827
828L(notypetest):
829#endif
830
831#ifdef CONFIG_VME
832 is_mvme147(L(getvmetype))
833 is_bvme6000(L(getvmetype))
834 is_not_mvme16x(L(gvtdone))
835
836 /* See if the loader has specified the BI_VME_TYPE tag. Recent
837 * versions of VMELILO and TFTPLILO do this. We have to do this
838 * early so we know how to handle console output. If the tag
839 * doesn't exist then we use the Bug for output on MVME16x.
840 */
841L(getvmetype):
842 get_bi_record BI_VME_TYPE
843 tstl %d0
844 jbmi 1f
845 movel %a0@,%d3
846 lea %pc@(vme_brdtype),%a0
847 movel %d3,%a0@
8481:
849#ifdef CONFIG_MVME16x
850 is_not_mvme16x(L(gvtdone))
851
852 /* Need to get the BRD_ID info to differentiate between 162, 167,
853 * etc. This is available as a BI_VME_BRDINFO tag with later
854 * versions of VMELILO and TFTPLILO, otherwise we call the Bug.
855 */
856 get_bi_record BI_VME_BRDINFO
857 tstl %d0
858 jpl 1f
859
860 /* Get pointer to board ID data from Bug */
861 movel %d2,%sp@-
862 trap #15
863 .word 0x70 /* trap 0x70 - .BRD_ID */
864 movel %sp@+,%a0
8651:
866 lea %pc@(mvme_bdid),%a1
867 /* Structure is 32 bytes long */
868 movel %a0@+,%a1@+
869 movel %a0@+,%a1@+
870 movel %a0@+,%a1@+
871 movel %a0@+,%a1@+
872 movel %a0@+,%a1@+
873 movel %a0@+,%a1@+
874 movel %a0@+,%a1@+
875 movel %a0@+,%a1@+
876#endif
877
878L(gvtdone):
879
880#endif
881
882#ifdef CONFIG_HP300
883 is_not_hp300(L(nothp))
884
885 /* Get the address of the UART for serial debugging */
886 get_bi_record BI_HP300_UART_ADDR
887 tstl %d0
888 jbmi 1f
889 movel %a0@,%d3
890 lea %pc@(L(uartbase)),%a0
891 movel %d3,%a0@
892 get_bi_record BI_HP300_UART_SCODE
893 tstl %d0
894 jbmi 1f
895 movel %a0@,%d3
896 lea %pc@(L(uart_scode)),%a0
897 movel %d3,%a0@
8981:
899L(nothp):
900#endif
901
902/*
903 * Initialize serial port
904 */
905 jbsr L(serial_init)
906
907/*
908 * Initialize console
909 */
910#ifdef CONFIG_MAC
911 is_not_mac(L(nocon))
912#ifdef CONSOLE
913 console_init
914#ifdef CONSOLE_PENGUIN
915 console_put_penguin
916#endif /* CONSOLE_PENGUIN */
917 console_put_stats
918#endif /* CONSOLE */
919L(nocon):
920#endif /* CONFIG_MAC */
921
922
923 putc '\n'
924 putc 'A'
925 leds 0x2
926 dputn %pc@(L(cputype))
927 dputn %pc@(m68k_supervisor_cachemode)
928 dputn %pc@(m68k_pgtable_cachemode)
929 dputc '\n'
930
931/*
932 * Save physical start address of kernel
933 */
934 lea %pc@(L(phys_kernel_start)),%a0
935 lea %pc@(_stext),%a1
936 subl #_stext,%a1
937 addl #PAGE_OFFSET,%a1
938 movel %a1,%a0@
939
940 putc 'B'
941
942 leds 0x4
943
944/*
945 * mmu_init
946 *
947 * This block of code does what's necessary to map in the various kinds
948 * of machines for execution of Linux.
949 * First map the first 4 MB of kernel code & data
950 */
951
952 mmu_map #PAGE_OFFSET,%pc@(L(phys_kernel_start)),#4*1024*1024,\
953 %pc@(m68k_supervisor_cachemode)
954
955 putc 'C'
956
957#ifdef CONFIG_AMIGA
958
959L(mmu_init_amiga):
960
961 is_not_amiga(L(mmu_init_not_amiga))
962/*
963 * mmu_init_amiga
964 */
965
966 putc 'D'
967
968 is_not_040_or_060(1f)
969
970 /*
971 * 040: Map the 16Meg range physical 0x0 upto logical 0x8000.0000
972 */
973 mmu_map #0x80000000,#0,#0x01000000,#_PAGE_NOCACHE_S
974 /*
975 * Map the Zorro III I/O space with transparent translation
976 * for frame buffer memory etc.
977 */
978 mmu_map_tt #1,#0x40000000,#0x20000000,#_PAGE_NOCACHE_S
979
980 jbra L(mmu_init_done)
981
9821:
983 /*
984 * 030: Map the 32Meg range physical 0x0 upto logical 0x8000.0000
985 */
986 mmu_map #0x80000000,#0,#0x02000000,#_PAGE_NOCACHE030
987 mmu_map_tt #1,#0x40000000,#0x20000000,#_PAGE_NOCACHE030
988
989 jbra L(mmu_init_done)
990
991L(mmu_init_not_amiga):
992#endif
993
994#ifdef CONFIG_ATARI
995
996L(mmu_init_atari):
997
998 is_not_atari(L(mmu_init_not_atari))
999
1000 putc 'E'
1001
1002/* On the Atari, we map the I/O region (phys. 0x00ffxxxx) by mapping
1003 the last 16 MB of virtual address space to the first 16 MB (i.e.
1004 0xffxxxxxx -> 0x00xxxxxx). For this, an additional pointer table is
1005 needed. I/O ranges are marked non-cachable.
1006
1007 For the Medusa it is better to map the I/O region transparently
1008 (i.e. 0xffxxxxxx -> 0xffxxxxxx), because some I/O registers are
1009 accessible only in the high area.
1010
1011 On the Hades all I/O registers are only accessible in the high
1012 area.
1013*/
1014
1015 /* I/O base addr for non-Medusa, non-Hades: 0x00000000 */
1016 moveq #0,%d0
1017 movel %pc@(atari_mch_type),%d3
1018 cmpl #ATARI_MACH_MEDUSA,%d3
1019 jbeq 2f
1020 cmpl #ATARI_MACH_HADES,%d3
1021 jbne 1f
10222: movel #0xff000000,%d0 /* Medusa/Hades base addr: 0xff000000 */
10231: movel %d0,%d3
1024
1025 is_040_or_060(L(spata68040))
1026
1027 /* Map everything non-cacheable, though not all parts really
1028 * need to disable caches (crucial only for 0xff8000..0xffffff
1029 * (standard I/O) and 0xf00000..0xf3ffff (IDE)). The remainder
1030 * isn't really used, except for sometimes peeking into the
1031 * ROMs (mirror at phys. 0x0), so caching isn't necessary for
1032 * this. */
1033 mmu_map #0xff000000,%d3,#0x01000000,#_PAGE_NOCACHE030
1034
1035 jbra L(mmu_init_done)
1036
1037L(spata68040):
1038
1039 mmu_map #0xff000000,%d3,#0x01000000,#_PAGE_NOCACHE_S
1040
1041 jbra L(mmu_init_done)
1042
1043L(mmu_init_not_atari):
1044#endif
1045
1046#ifdef CONFIG_Q40
1047 is_not_q40(L(notq40))
1048 /*
1049 * add transparent mapping for 0xff00 0000 - 0xffff ffff
1050 * non-cached serialized etc..
1051 * this includes master chip, DAC, RTC and ISA ports
1052 * 0xfe000000-0xfeffffff is for screen and ROM
1053 */
1054
1055 putc 'Q'
1056
1057 mmu_map_tt #0,#0xfe000000,#0x01000000,#_PAGE_CACHE040W
1058 mmu_map_tt #1,#0xff000000,#0x01000000,#_PAGE_NOCACHE_S
1059
1060 jbra L(mmu_init_done)
1061
1062L(notq40):
1063#endif
1064
1065#ifdef CONFIG_HP300
1066 is_not_hp300(L(nothp300))
1067
1068 /* On the HP300, we map the ROM, INTIO and DIO regions (phys. 0x00xxxxxx)
1069 * by mapping 32MB (on 020/030) or 16 MB (on 040) from 0xf0xxxxxx -> 0x00xxxxxx).
1070 * The ROM mapping is needed because the LEDs are mapped there too.
1071 */
1072
1073 is_040(1f)
1074
1075 /*
1076 * 030: Map the 32Meg range physical 0x0 upto logical 0xf000.0000
1077 */
1078 mmu_map #0xf0000000,#0,#0x02000000,#_PAGE_NOCACHE030
1079
1080 jbra L(mmu_init_done)
1081
10821:
1083 /*
1084 * 040: Map the 16Meg range physical 0x0 upto logical 0xf000.0000
1085 */
1086 mmu_map #0xf0000000,#0,#0x01000000,#_PAGE_NOCACHE_S
1087
1088 jbra L(mmu_init_done)
1089
1090L(nothp300):
1091#endif /* CONFIG_HP300 */
1092
1093#ifdef CONFIG_MVME147
1094
1095 is_not_mvme147(L(not147))
1096
1097 /*
1098 * On MVME147 we have already created kernel page tables for
1099 * 4MB of RAM at address 0, so now need to do a transparent
1100 * mapping of the top of memory space. Make it 0.5GByte for now,
1101 * so we can access on-board i/o areas.
1102 */
1103
1104 mmu_map_tt #1,#0xe0000000,#0x20000000,#_PAGE_NOCACHE030
1105
1106 jbra L(mmu_init_done)
1107
1108L(not147):
1109#endif /* CONFIG_MVME147 */
1110
1111#ifdef CONFIG_MVME16x
1112
1113 is_not_mvme16x(L(not16x))
1114
1115 /*
1116 * On MVME16x we have already created kernel page tables for
1117 * 4MB of RAM at address 0, so now need to do a transparent
1118 * mapping of the top of memory space. Make it 0.5GByte for now.
1119 * Supervisor only access, so transparent mapping doesn't
1120 * clash with User code virtual address space.
1121 * this covers IO devices, PROM and SRAM. The PROM and SRAM
1122 * mapping is needed to allow 167Bug to run.
1123 * IO is in the range 0xfff00000 to 0xfffeffff.
1124 * PROM is 0xff800000->0xffbfffff and SRAM is
1125 * 0xffe00000->0xffe1ffff.
1126 */
1127
1128 mmu_map_tt #1,#0xe0000000,#0x20000000,#_PAGE_NOCACHE_S
1129
1130 jbra L(mmu_init_done)
1131
1132L(not16x):
1133#endif /* CONFIG_MVME162 | CONFIG_MVME167 */
1134
1135#ifdef CONFIG_BVME6000
1136
1137 is_not_bvme6000(L(not6000))
1138
1139 /*
1140 * On BVME6000 we have already created kernel page tables for
1141 * 4MB of RAM at address 0, so now need to do a transparent
1142 * mapping of the top of memory space. Make it 0.5GByte for now,
1143 * so we can access on-board i/o areas.
1144 * Supervisor only access, so transparent mapping doesn't
1145 * clash with User code virtual address space.
1146 */
1147
1148 mmu_map_tt #1,#0xe0000000,#0x20000000,#_PAGE_NOCACHE_S
1149
1150 jbra L(mmu_init_done)
1151
1152L(not6000):
1153#endif /* CONFIG_BVME6000 */
1154
1155/*
1156 * mmu_init_mac
1157 *
1158 * The Macintosh mappings are less clear.
1159 *
1160 * Even as of this writing, it is unclear how the
1161 * Macintosh mappings will be done. However, as
1162 * the first author of this code I'm proposing the
1163 * following model:
1164 *
1165 * Map the kernel (that's already done),
1166 * Map the I/O (on most machines that's the
1167 * 0x5000.0000 ... 0x5300.0000 range,
1168 * Map the video frame buffer using as few pages
1169 * as absolutely (this requirement mostly stems from
1170 * the fact that when the frame buffer is at
1171 * 0x0000.0000 then we know there is valid RAM just
1172 * above the screen that we don't want to waste!).
1173 *
1174 * By the way, if the frame buffer is at 0x0000.0000
1175 * then the Macintosh is known as an RBV based Mac.
1176 *
1177 * By the way 2, the code currently maps in a bunch of
1178 * regions. But I'd like to cut that out. (And move most
1179 * of the mappings up into the kernel proper ... or only
1180 * map what's necessary.)
1181 */
1182
1183#ifdef CONFIG_MAC
1184
1185L(mmu_init_mac):
1186
1187 is_not_mac(L(mmu_init_not_mac))
1188
1189 putc 'F'
1190
1191 is_not_040_or_060(1f)
1192
1193 moveq #_PAGE_NOCACHE_S,%d3
1194 jbra 2f
11951:
1196 moveq #_PAGE_NOCACHE030,%d3
11972:
1198 /*
1199 * Mac Note: screen address of logical 0xF000.0000 -> <screen physical>
1200 * we simply map the 4MB that contains the videomem
1201 */
1202
1203 movel #VIDEOMEMMASK,%d0
1204 andl %pc@(L(mac_videobase)),%d0
1205
1206 mmu_map #VIDEOMEMBASE,%d0,#VIDEOMEMSIZE,%d3
1207 /* ROM from 4000 0000 to 4200 0000 (only for mac_reset()) */
1208 mmu_map_eq #0x40000000,#0x02000000,%d3
1209 /* IO devices (incl. serial port) from 5000 0000 to 5300 0000 */
1210 mmu_map_eq #0x50000000,#0x03000000,%d3
1211 /* Nubus slot space (video at 0xF0000000, rom at 0xF0F80000) */
1212 mmu_map_tt #1,#0xf8000000,#0x08000000,%d3
1213
1214 jbra L(mmu_init_done)
1215
1216L(mmu_init_not_mac):
1217#endif
1218
1219#ifdef CONFIG_SUN3X
1220 is_not_sun3x(L(notsun3x))
1221
1222 /* oh, the pain.. We're gonna want the prom code after
1223 * starting the MMU, so we copy the mappings, translating
1224 * from 8k -> 4k pages as we go.
1225 */
1226
1227 /* copy maps from 0xfee00000 to 0xff000000 */
1228 movel #0xfee00000, %d0
1229 moveq #ROOT_INDEX_SHIFT, %d1
1230 lsrl %d1,%d0
1231 mmu_get_root_table_entry %d0
1232
1233 movel #0xfee00000, %d0
1234 moveq #PTR_INDEX_SHIFT, %d1
1235 lsrl %d1,%d0
1236 andl #PTR_TABLE_SIZE-1, %d0
1237 mmu_get_ptr_table_entry %a0,%d0
1238
1239 movel #0xfee00000, %d0
1240 moveq #PAGE_INDEX_SHIFT, %d1
1241 lsrl %d1,%d0
1242 andl #PAGE_TABLE_SIZE-1, %d0
1243 mmu_get_page_table_entry %a0,%d0
1244
1245 /* this is where the prom page table lives */
1246 movel 0xfefe00d4, %a1
1247 movel %a1@, %a1
1248
1249 movel #((0x200000 >> 13)-1), %d1
1250
12511:
1252 movel %a1@+, %d3
1253 movel %d3,%a0@+
1254 addl #0x1000,%d3
1255 movel %d3,%a0@+
1256
1257 dbra %d1,1b
1258
1259 /* setup tt1 for I/O */
1260 mmu_map_tt #1,#0x40000000,#0x40000000,#_PAGE_NOCACHE_S
1261 jbra L(mmu_init_done)
1262
1263L(notsun3x):
1264#endif
1265
1266#ifdef CONFIG_APOLLO
1267 is_not_apollo(L(notapollo))
1268
1269 putc 'P'
1270 mmu_map #0x80000000,#0,#0x02000000,#_PAGE_NOCACHE030
1271
1272L(notapollo):
1273 jbra L(mmu_init_done)
1274#endif
1275
1276L(mmu_init_done):
1277
1278 putc 'G'
1279 leds 0x8
1280
1281/*
1282 * mmu_fixup
1283 *
1284 * On the 040 class machines, all pages that are used for the
1285 * mmu have to be fixed up. According to Motorola, pages holding mmu
1286 * tables should be non-cacheable on a '040 and write-through on a
1287 * '060. But analysis of the reasons for this, and practical
1288 * experience, showed that write-through also works on a '040.
1289 *
1290 * Allocated memory so far goes from kernel_end to memory_start that
1291 * is used for all kind of tables, for that the cache attributes
1292 * are now fixed.
1293 */
1294L(mmu_fixup):
1295
1296 is_not_040_or_060(L(mmu_fixup_done))
1297
1298#ifdef MMU_NOCACHE_KERNEL
1299 jbra L(mmu_fixup_done)
1300#endif
1301
1302 /* first fix the page at the start of the kernel, that
1303 * contains also kernel_pg_dir.
1304 */
1305 movel %pc@(L(phys_kernel_start)),%d0
1306 subl #PAGE_OFFSET,%d0
1307 lea %pc@(_stext),%a0
1308 subl %d0,%a0
1309 mmu_fixup_page_mmu_cache %a0
1310
1311 movel %pc@(L(kernel_end)),%a0
1312 subl %d0,%a0
1313 movel %pc@(L(memory_start)),%a1
1314 subl %d0,%a1
1315 bra 2f
13161:
1317 mmu_fixup_page_mmu_cache %a0
1318 addw #PAGESIZE,%a0
13192:
1320 cmpl %a0,%a1
1321 jgt 1b
1322
1323L(mmu_fixup_done):
1324
1325#ifdef MMU_PRINT
1326 mmu_print
1327#endif
1328
1329/*
1330 * mmu_engage
1331 *
1332 * This chunk of code performs the gruesome task of engaging the MMU.
1333 * The reason its gruesome is because when the MMU becomes engaged it
1334 * maps logical addresses to physical addresses. The Program Counter
1335 * register is then passed through the MMU before the next instruction
1336 * is fetched (the instruction following the engage MMU instruction).
1337 * This may mean one of two things:
1338 * 1. The Program Counter falls within the logical address space of
1339 * the kernel of which there are two sub-possibilities:
1340 * A. The PC maps to the correct instruction (logical PC == physical
1341 * code location), or
1342 * B. The PC does not map through and the processor will read some
1343 * data (or instruction) which is not the logically next instr.
1344 * As you can imagine, A is good and B is bad.
1345 * Alternatively,
1346 * 2. The Program Counter does not map through the MMU. The processor
1347 * will take a Bus Error.
1348 * Clearly, 2 is bad.
1349 * It doesn't take a wiz kid to figure you want 1.A.
1350 * This code creates that possibility.
1351 * There are two possible 1.A. states (we now ignore the other above states):
1352 * A. The kernel is located at physical memory addressed the same as
1353 * the logical memory for the kernel, i.e., 0x01000.
1354 * B. The kernel is located some where else. e.g., 0x0400.0000
1355 *
1356 * Under some conditions the Macintosh can look like A or B.
1357 * [A friend and I once noted that Apple hardware engineers should be
1358 * wacked twice each day: once when they show up at work (as in, Whack!,
1359 * "This is for the screwy hardware we know you're going to design today."),
1360 * and also at the end of the day (as in, Whack! "I don't know what
1361 * you designed today, but I'm sure it wasn't good."). -- rst]
1362 *
1363 * This code works on the following premise:
1364 * If the kernel start (%d5) is within the first 16 Meg of RAM,
1365 * then create a mapping for the kernel at logical 0x8000.0000 to
1366 * the physical location of the pc. And, create a transparent
1367 * translation register for the first 16 Meg. Then, after the MMU
1368 * is engaged, the PC can be moved up into the 0x8000.0000 range
1369 * and then the transparent translation can be turned off and then
1370 * the PC can jump to the correct logical location and it will be
1371 * home (finally). This is essentially the code that the Amiga used
1372 * to use. Now, it's generalized for all processors. Which means
1373 * that a fresh (but temporary) mapping has to be created. The mapping
1374 * is made in page 0 (an as of yet unused location -- except for the
1375 * stack!). This temporary mapping will only require 1 pointer table
1376 * and a single page table (it can map 256K).
1377 *
1378 * OK, alternatively, imagine that the Program Counter is not within
1379 * the first 16 Meg. Then, just use Transparent Translation registers
1380 * to do the right thing.
1381 *
1382 * Last, if _start is already at 0x01000, then there's nothing special
1383 * to do (in other words, in a degenerate case of the first case above,
1384 * do nothing).
1385 *
1386 * Let's do it.
1387 *
1388 *
1389 */
1390
1391 putc 'H'
1392
1393 mmu_engage
1394
1395/*
1396 * After this point no new memory is allocated and
1397 * the start of available memory is stored in availmem.
1398 * (The bootmem allocator requires now the physicall address.)
1399 */
1400
1401 movel L(memory_start),availmem
1402
1403#ifdef CONFIG_AMIGA
1404 is_not_amiga(1f)
1405 /* fixup the Amiga custom register location before printing */
1406 clrl L(custom)
14071:
1408#endif
1409
1410#ifdef CONFIG_ATARI
1411 is_not_atari(1f)
1412 /* fixup the Atari iobase register location before printing */
1413 movel #0xff000000,L(iobase)
14141:
1415#endif
1416
1417#ifdef CONFIG_MAC
1418 is_not_mac(1f)
1419 movel #~VIDEOMEMMASK,%d0
1420 andl L(mac_videobase),%d0
1421 addl #VIDEOMEMBASE,%d0
1422 movel %d0,L(mac_videobase)
1423#if defined(CONSOLE)
1424 movel %pc@(L(phys_kernel_start)),%d0
1425 subl #PAGE_OFFSET,%d0
1426 subl %d0,L(console_font)
1427 subl %d0,L(console_font_data)
1428#endif
1429#ifdef MAC_SERIAL_DEBUG
1430 orl #0x50000000,L(mac_sccbase)
1431#endif
14321:
1433#endif
1434
1435#ifdef CONFIG_HP300
1436 is_not_hp300(1f)
1437 /*
1438 * Fix up the iobase register to point to the new location of the LEDs.
1439 */
1440 movel #0xf0000000,L(iobase)
1441
1442 /*
1443 * Energise the FPU and caches.
1444 */
1445 is_040(1f)
1446 movel #0x60,0xf05f400c
1447 jbra 2f
1448
1449 /*
1450 * 040: slightly different, apparently.
1451 */
14521: movew #0,0xf05f400e
1453 movew #0x64,0xf05f400e
14542:
1455#endif
1456
1457#ifdef CONFIG_SUN3X
1458 is_not_sun3x(1f)
1459
1460 /* enable copro */
1461 oriw #0x4000,0x61000000
14621:
1463#endif
1464
1465#ifdef CONFIG_APOLLO
1466 is_not_apollo(1f)
1467
1468 /*
1469 * Fix up the iobase before printing
1470 */
1471 movel #0x80000000,L(iobase)
14721:
1473#endif
1474
1475 putc 'I'
1476 leds 0x10
1477
1478/*
1479 * Enable caches
1480 */
1481
1482 is_not_040_or_060(L(cache_not_680460))
1483
1484L(cache680460):
1485 .chip 68040
1486 nop
1487 cpusha %bc
1488 nop
1489
1490 is_060(L(cache68060))
1491
1492 movel #CC6_ENABLE_D+CC6_ENABLE_I,%d0
1493 /* MMU stuff works in copyback mode now, so enable the cache */
1494 movec %d0,%cacr
1495 jra L(cache_done)
1496
1497L(cache68060):
1498 movel #CC6_ENABLE_D+CC6_ENABLE_I+CC6_ENABLE_SB+CC6_PUSH_DPI+CC6_ENABLE_B+CC6_CLRA_B,%d0
1499 /* MMU stuff works in copyback mode now, so enable the cache */
1500 movec %d0,%cacr
1501 /* enable superscalar dispatch in PCR */
1502 moveq #1,%d0
1503 .chip 68060
1504 movec %d0,%pcr
1505
1506 jbra L(cache_done)
1507L(cache_not_680460):
1508L(cache68030):
1509 .chip 68030
1510 movel #CC3_ENABLE_DB+CC3_CLR_D+CC3_ENABLE_D+CC3_ENABLE_IB+CC3_CLR_I+CC3_ENABLE_I,%d0
1511 movec %d0,%cacr
1512
1513 jra L(cache_done)
1514 .chip 68k
1515L(cache_done):
1516
1517 putc 'J'
1518
1519/*
1520 * Setup initial stack pointer
1521 */
1522 lea init_task,%curptr
1523 lea init_thread_union+THREAD_SIZE,%sp
1524
1525 putc 'K'
1526
1527 subl %a6,%a6 /* clear a6 for gdb */
1528
1529/*
1530 * The new 64bit printf support requires an early exception initialization.
1531 */
1532 jbsr base_trap_init
1533
1534/* jump to the kernel start */
1535
1536 putc '\n'
1537 leds 0x55
1538
1539 jbsr start_kernel
1540
1541/*
1542 * Find a tag record in the bootinfo structure
1543 * The bootinfo structure is located right after the kernel bss
1544 * Returns: d0: size (-1 if not found)
1545 * a0: data pointer (end-of-records if not found)
1546 */
1547func_start get_bi_record,%d1
1548
1549 movel ARG1,%d0
1550 lea %pc@(_end),%a0
15511: tstw %a0@(BIR_TAG)
1552 jeq 3f
1553 cmpw %a0@(BIR_TAG),%d0
1554 jeq 2f
1555 addw %a0@(BIR_SIZE),%a0
1556 jra 1b
15572: moveq #0,%d0
1558 movew %a0@(BIR_SIZE),%d0
1559 lea %a0@(BIR_DATA),%a0
1560 jra 4f
15613: moveq #-1,%d0
1562 lea %a0@(BIR_SIZE),%a0
15634:
1564func_return get_bi_record
1565
1566
1567/*
1568 * MMU Initialization Begins Here
1569 *
1570 * The structure of the MMU tables on the 68k machines
1571 * is thus:
1572 * Root Table
1573 * Logical addresses are translated through
1574 * a hierarchical translation mechanism where the high-order
1575 * seven bits of the logical address (LA) are used as an
1576 * index into the "root table." Each entry in the root
1577 * table has a bit which specifies if it's a valid pointer to a
1578 * pointer table. Each entry defines a 32KMeg range of memory.
1579 * If an entry is invalid then that logical range of 32M is
1580 * invalid and references to that range of memory (when the MMU
1581 * is enabled) will fault. If the entry is valid, then it does
1582 * one of two things. On 040/060 class machines, it points to
1583 * a pointer table which then describes more finely the memory
1584 * within that 32M range. On 020/030 class machines, a technique
1585 * called "early terminating descriptors" are used. This technique
1586 * allows an entire 32Meg to be described by a single entry in the
1587 * root table. Thus, this entry in the root table, contains the
1588 * physical address of the memory or I/O at the logical address
1589 * which the entry represents and it also contains the necessary
1590 * cache bits for this region.
1591 *
1592 * Pointer Tables
1593 * Per the Root Table, there will be one or more
1594 * pointer tables. Each pointer table defines a 32M range.
1595 * Not all of the 32M range need be defined. Again, the next
1596 * seven bits of the logical address are used an index into
1597 * the pointer table to point to page tables (if the pointer
1598 * is valid). There will undoubtedly be more than one
1599 * pointer table for the kernel because each pointer table
1600 * defines a range of only 32M. Valid pointer table entries
1601 * point to page tables, or are early terminating entries
1602 * themselves.
1603 *
1604 * Page Tables
1605 * Per the Pointer Tables, each page table entry points
1606 * to the physical page in memory that supports the logical
1607 * address that translates to the particular index.
1608 *
1609 * In short, the Logical Address gets translated as follows:
1610 * bits 31..26 - index into the Root Table
1611 * bits 25..18 - index into the Pointer Table
1612 * bits 17..12 - index into the Page Table
1613 * bits 11..0 - offset into a particular 4K page
1614 *
1615 * The algorithms which follows do one thing: they abstract
1616 * the MMU hardware. For example, there are three kinds of
1617 * cache settings that are relevant. Either, memory is
1618 * being mapped in which case it is either Kernel Code (or
1619 * the RamDisk) or it is MMU data. On the 030, the MMU data
1620 * option also describes the kernel. Or, I/O is being mapped
1621 * in which case it has its own kind of cache bits. There
1622 * are constants which abstract these notions from the code that
1623 * actually makes the call to map some range of memory.
1624 *
1625 *
1626 *
1627 */
1628
1629#ifdef MMU_PRINT
1630/*
1631 * mmu_print
1632 *
1633 * This algorithm will print out the current MMU mappings.
1634 *
1635 * Input:
1636 * %a5 points to the root table. Everything else is calculated
1637 * from this.
1638 */
1639
1640#define mmu_next_valid 0
1641#define mmu_start_logical 4
1642#define mmu_next_logical 8
1643#define mmu_start_physical 12
1644#define mmu_next_physical 16
1645
1646#define MMU_PRINT_INVALID -1
1647#define MMU_PRINT_VALID 1
1648#define MMU_PRINT_UNINITED 0
1649
1650#define putZc(z,n) jbne 1f; putc z; jbra 2f; 1: putc n; 2:
1651
1652func_start mmu_print,%a0-%a6/%d0-%d7
1653
1654 movel %pc@(L(kernel_pgdir_ptr)),%a5
1655 lea %pc@(L(mmu_print_data)),%a0
1656 movel #MMU_PRINT_UNINITED,%a0@(mmu_next_valid)
1657
1658 is_not_040_or_060(mmu_030_print)
1659
1660mmu_040_print:
1661 puts "\nMMU040\n"
1662 puts "rp:"
1663 putn %a5
1664 putc '\n'
1665#if 0
1666 /*
1667 * The following #if/#endif block is a tight algorithm for dumping the 040
1668 * MMU Map in gory detail. It really isn't that practical unless the
1669 * MMU Map algorithm appears to go awry and you need to debug it at the
1670 * entry per entry level.
1671 */
1672 movel #ROOT_TABLE_SIZE,%d5
1673#if 0
1674 movel %a5@+,%d7 | Burn an entry to skip the kernel mappings,
1675 subql #1,%d5 | they (might) work
1676#endif
16771: tstl %d5
1678 jbeq mmu_print_done
1679 subq #1,%d5
1680 movel %a5@+,%d7
1681 btst #1,%d7
1682 jbeq 1b
1683
16842: putn %d7
1685 andil #0xFFFFFE00,%d7
1686 movel %d7,%a4
1687 movel #PTR_TABLE_SIZE,%d4
1688 putc ' '
16893: tstl %d4
1690 jbeq 11f
1691 subq #1,%d4
1692 movel %a4@+,%d7
1693 btst #1,%d7
1694 jbeq 3b
1695
16964: putn %d7
1697 andil #0xFFFFFF00,%d7
1698 movel %d7,%a3
1699 movel #PAGE_TABLE_SIZE,%d3
17005: movel #8,%d2
17016: tstl %d3
1702 jbeq 31f
1703 subq #1,%d3
1704 movel %a3@+,%d6
1705 btst #0,%d6
1706 jbeq 6b
17077: tstl %d2
1708 jbeq 8f
1709 subq #1,%d2
1710 putc ' '
1711 jbra 91f
17128: putc '\n'
1713 movel #8+1+8+1+1,%d2
17149: putc ' '
1715 dbra %d2,9b
1716 movel #7,%d2
171791: putn %d6
1718 jbra 6b
1719
172031: putc '\n'
1721 movel #8+1,%d2
172232: putc ' '
1723 dbra %d2,32b
1724 jbra 3b
1725
172611: putc '\n'
1727 jbra 1b
1728#endif /* MMU 040 Dumping code that's gory and detailed */
1729
1730 lea %pc@(kernel_pg_dir),%a5
1731 movel %a5,%a0 /* a0 has the address of the root table ptr */
1732 movel #0x00000000,%a4 /* logical address */
1733 moveql #0,%d0
173440:
1735 /* Increment the logical address and preserve in d5 */
1736 movel %a4,%d5
1737 addil #PAGESIZE<<13,%d5
1738 movel %a0@+,%d6
1739 btst #1,%d6
1740 jbne 41f
1741 jbsr mmu_print_tuple_invalidate
1742 jbra 48f
174341:
1744 movel #0,%d1
1745 andil #0xfffffe00,%d6
1746 movel %d6,%a1
174742:
1748 movel %a4,%d5
1749 addil #PAGESIZE<<6,%d5
1750 movel %a1@+,%d6
1751 btst #1,%d6
1752 jbne 43f
1753 jbsr mmu_print_tuple_invalidate
1754 jbra 47f
175543:
1756 movel #0,%d2
1757 andil #0xffffff00,%d6
1758 movel %d6,%a2
175944:
1760 movel %a4,%d5
1761 addil #PAGESIZE,%d5
1762 movel %a2@+,%d6
1763 btst #0,%d6
1764 jbne 45f
1765 jbsr mmu_print_tuple_invalidate
1766 jbra 46f
176745:
1768 moveml %d0-%d1,%sp@-
1769 movel %a4,%d0
1770 movel %d6,%d1
1771 andil #0xfffff4e0,%d1
1772 lea %pc@(mmu_040_print_flags),%a6
1773 jbsr mmu_print_tuple
1774 moveml %sp@+,%d0-%d1
177546:
1776 movel %d5,%a4
1777 addq #1,%d2
1778 cmpib #64,%d2
1779 jbne 44b
178047:
1781 movel %d5,%a4
1782 addq #1,%d1
1783 cmpib #128,%d1
1784 jbne 42b
178548:
1786 movel %d5,%a4 /* move to the next logical address */
1787 addq #1,%d0
1788 cmpib #128,%d0
1789 jbne 40b
1790
1791 .chip 68040
1792 movec %dtt1,%d0
1793 movel %d0,%d1
1794 andiw #0x8000,%d1 /* is it valid ? */
1795 jbeq 1f /* No, bail out */
1796
1797 movel %d0,%d1
1798 andil #0xff000000,%d1 /* Get the address */
1799 putn %d1
1800 puts "=="
1801 putn %d1
1802
1803 movel %d0,%d6
1804 jbsr mmu_040_print_flags_tt
18051:
1806 movec %dtt0,%d0
1807 movel %d0,%d1
1808 andiw #0x8000,%d1 /* is it valid ? */
1809 jbeq 1f /* No, bail out */
1810
1811 movel %d0,%d1
1812 andil #0xff000000,%d1 /* Get the address */
1813 putn %d1
1814 puts "=="
1815 putn %d1
1816
1817 movel %d0,%d6
1818 jbsr mmu_040_print_flags_tt
18191:
1820 .chip 68k
1821
1822 jbra mmu_print_done
1823
1824mmu_040_print_flags:
1825 btstl #10,%d6
1826 putZc(' ','G') /* global bit */
1827 btstl #7,%d6
1828 putZc(' ','S') /* supervisor bit */
1829mmu_040_print_flags_tt:
1830 btstl #6,%d6
1831 jbne 3f
1832 putc 'C'
1833 btstl #5,%d6
1834 putZc('w','c') /* write through or copy-back */
1835 jbra 4f
18363:
1837 putc 'N'
1838 btstl #5,%d6
1839 putZc('s',' ') /* serialized non-cacheable, or non-cacheable */
18404:
1841 rts
1842
1843mmu_030_print_flags:
1844 btstl #6,%d6
1845 putZc('C','I') /* write through or copy-back */
1846 rts
1847
1848mmu_030_print:
1849 puts "\nMMU030\n"
1850 puts "\nrp:"
1851 putn %a5
1852 putc '\n'
1853 movel %a5,%d0
1854 andil #0xfffffff0,%d0
1855 movel %d0,%a0
1856 movel #0x00000000,%a4 /* logical address */
1857 movel #0,%d0
185830:
1859 movel %a4,%d5
1860 addil #PAGESIZE<<13,%d5
1861 movel %a0@+,%d6
1862 btst #1,%d6 /* is it a table ptr? */
1863 jbne 31f /* yes */
1864 btst #0,%d6 /* is it early terminating? */
1865 jbeq 1f /* no */
1866 jbsr mmu_030_print_helper
1867 jbra 38f
18681:
1869 jbsr mmu_print_tuple_invalidate
1870 jbra 38f
187131:
1872 movel #0,%d1
1873 andil #0xfffffff0,%d6
1874 movel %d6,%a1
187532:
1876 movel %a4,%d5
1877 addil #PAGESIZE<<6,%d5
1878 movel %a1@+,%d6
1879 btst #1,%d6 /* is it a table ptr? */
1880 jbne 33f /* yes */
1881 btst #0,%d6 /* is it a page descriptor? */
1882 jbeq 1f /* no */
1883 jbsr mmu_030_print_helper
1884 jbra 37f
18851:
1886 jbsr mmu_print_tuple_invalidate
1887 jbra 37f
188833:
1889 movel #0,%d2
1890 andil #0xfffffff0,%d6
1891 movel %d6,%a2
189234:
1893 movel %a4,%d5
1894 addil #PAGESIZE,%d5
1895 movel %a2@+,%d6
1896 btst #0,%d6
1897 jbne 35f
1898 jbsr mmu_print_tuple_invalidate
1899 jbra 36f
190035:
1901 jbsr mmu_030_print_helper
190236:
1903 movel %d5,%a4
1904 addq #1,%d2
1905 cmpib #64,%d2
1906 jbne 34b
190737:
1908 movel %d5,%a4
1909 addq #1,%d1
1910 cmpib #128,%d1
1911 jbne 32b
191238:
1913 movel %d5,%a4 /* move to the next logical address */
1914 addq #1,%d0
1915 cmpib #128,%d0
1916 jbne 30b
1917
1918mmu_print_done:
1919 puts "\n\n"
1920
1921func_return mmu_print
1922
1923
1924mmu_030_print_helper:
1925 moveml %d0-%d1,%sp@-
1926 movel %a4,%d0
1927 movel %d6,%d1
1928 lea %pc@(mmu_030_print_flags),%a6
1929 jbsr mmu_print_tuple
1930 moveml %sp@+,%d0-%d1
1931 rts
1932
1933mmu_print_tuple_invalidate:
1934 moveml %a0/%d7,%sp@-
1935
1936 lea %pc@(L(mmu_print_data)),%a0
1937 tstl %a0@(mmu_next_valid)
1938 jbmi mmu_print_tuple_invalidate_exit
1939
1940 movel #MMU_PRINT_INVALID,%a0@(mmu_next_valid)
1941
1942 putn %a4
1943
1944 puts "##\n"
1945
1946mmu_print_tuple_invalidate_exit:
1947 moveml %sp@+,%a0/%d7
1948 rts
1949
1950
1951mmu_print_tuple:
1952 moveml %d0-%d7/%a0,%sp@-
1953
1954 lea %pc@(L(mmu_print_data)),%a0
1955
1956 tstl %a0@(mmu_next_valid)
1957 jble mmu_print_tuple_print
1958
1959 cmpl %a0@(mmu_next_physical),%d1
1960 jbeq mmu_print_tuple_increment
1961
1962mmu_print_tuple_print:
1963 putn %d0
1964 puts "->"
1965 putn %d1
1966
1967 movel %d1,%d6
1968 jbsr %a6@
1969
1970mmu_print_tuple_record:
1971 movel #MMU_PRINT_VALID,%a0@(mmu_next_valid)
1972
1973 movel %d1,%a0@(mmu_next_physical)
1974
1975mmu_print_tuple_increment:
1976 movel %d5,%d7
1977 subl %a4,%d7
1978 addl %d7,%a0@(mmu_next_physical)
1979
1980mmu_print_tuple_exit:
1981 moveml %sp@+,%d0-%d7/%a0
1982 rts
1983
1984mmu_print_machine_cpu_types:
1985 puts "machine: "
1986
1987 is_not_amiga(1f)
1988 puts "amiga"
1989 jbra 9f
19901:
1991 is_not_atari(2f)
1992 puts "atari"
1993 jbra 9f
19942:
1995 is_not_mac(3f)
1996 puts "macintosh"
1997 jbra 9f
19983: puts "unknown"
19999: putc '\n'
2000
2001 puts "cputype: 0"
2002 is_not_060(1f)
2003 putc '6'
2004 jbra 9f
20051:
2006 is_not_040_or_060(2f)
2007 putc '4'
2008 jbra 9f
20092: putc '3'
20109: putc '0'
2011 putc '\n'
2012
2013 rts
2014#endif /* MMU_PRINT */
2015
2016/*
2017 * mmu_map_tt
2018 *
2019 * This is a specific function which works on all 680x0 machines.
2020 * On 030, 040 & 060 it will attempt to use Transparent Translation
2021 * registers (tt1).
2022 * On 020 it will call the standard mmu_map which will use early
2023 * terminating descriptors.
2024 */
2025func_start mmu_map_tt,%d0/%d1/%a0,4
2026
2027 dputs "mmu_map_tt:"
2028 dputn ARG1
2029 dputn ARG2
2030 dputn ARG3
2031 dputn ARG4
2032 dputc '\n'
2033
2034 is_020(L(do_map))
2035
2036 /* Extract the highest bit set
2037 */
2038 bfffo ARG3{#0,#32},%d1
2039 cmpw #8,%d1
2040 jcc L(do_map)
2041
2042 /* And get the mask
2043 */
2044 moveq #-1,%d0
2045 lsrl %d1,%d0
2046 lsrl #1,%d0
2047
2048 /* Mask the address
2049 */
2050 movel %d0,%d1
2051 notl %d1
2052 andl ARG2,%d1
2053
2054 /* Generate the upper 16bit of the tt register
2055 */
2056 lsrl #8,%d0
2057 orl %d0,%d1
2058 clrw %d1
2059
2060 is_040_or_060(L(mmu_map_tt_040))
2061
2062 /* set 030 specific bits (read/write access for supervisor mode
2063 * (highest function code set, lower two bits masked))
2064 */
2065 orw #TTR_ENABLE+TTR_RWM+TTR_FCB2+TTR_FCM1+TTR_FCM0,%d1
2066 movel ARG4,%d0
2067 btst #6,%d0
2068 jeq 1f
2069 orw #TTR_CI,%d1
2070
20711: lea STACK,%a0
2072 dputn %d1
2073 movel %d1,%a0@
2074 .chip 68030
2075 tstl ARG1
2076 jne 1f
2077 pmove %a0@,%tt0
2078 jra 2f
20791: pmove %a0@,%tt1
20802: .chip 68k
2081 jra L(mmu_map_tt_done)
2082
2083 /* set 040 specific bits
2084 */
2085L(mmu_map_tt_040):
2086 orw #TTR_ENABLE+TTR_KERNELMODE,%d1
2087 orl ARG4,%d1
2088 dputn %d1
2089
2090 .chip 68040
2091 tstl ARG1
2092 jne 1f
2093 movec %d1,%itt0
2094 movec %d1,%dtt0
2095 jra 2f
20961: movec %d1,%itt1
2097 movec %d1,%dtt1
20982: .chip 68k
2099
2100 jra L(mmu_map_tt_done)
2101
2102L(do_map):
2103 mmu_map_eq ARG2,ARG3,ARG4
2104
2105L(mmu_map_tt_done):
2106
2107func_return mmu_map_tt
2108
2109/*
2110 * mmu_map
2111 *
2112 * This routine will map a range of memory using a pointer
2113 * table and allocating the pages on the fly from the kernel.
2114 * The pointer table does not have to be already linked into
2115 * the root table, this routine will do that if necessary.
2116 *
2117 * NOTE
2118 * This routine will assert failure and use the serial_putc
2119 * routines in the case of a run-time error. For example,
2120 * if the address is already mapped.
2121 *
2122 * NOTE-2
2123 * This routine will use early terminating descriptors
2124 * where possible for the 68020+68851 and 68030 type
2125 * processors.
2126 */
2127func_start mmu_map,%d0-%d4/%a0-%a4
2128
2129 dputs "\nmmu_map:"
2130 dputn ARG1
2131 dputn ARG2
2132 dputn ARG3
2133 dputn ARG4
2134 dputc '\n'
2135
2136 /* Get logical address and round it down to 256KB
2137 */
2138 movel ARG1,%d0
2139 andl #-(PAGESIZE*PAGE_TABLE_SIZE),%d0
2140 movel %d0,%a3
2141
2142 /* Get the end address
2143 */
2144 movel ARG1,%a4
2145 addl ARG3,%a4
2146 subql #1,%a4
2147
2148 /* Get physical address and round it down to 256KB
2149 */
2150 movel ARG2,%d0
2151 andl #-(PAGESIZE*PAGE_TABLE_SIZE),%d0
2152 movel %d0,%a2
2153
2154 /* Add page attributes to the physical address
2155 */
2156 movel ARG4,%d0
2157 orw #_PAGE_PRESENT+_PAGE_ACCESSED+_PAGE_DIRTY,%d0
2158 addw %d0,%a2
2159
2160 dputn %a2
2161 dputn %a3
2162 dputn %a4
2163
2164 is_not_040_or_060(L(mmu_map_030))
2165
2166 addw #_PAGE_GLOBAL040,%a2
2167/*
2168 * MMU 040 & 060 Support
2169 *
2170 * The MMU usage for the 040 and 060 is different enough from
2171 * the 030 and 68851 that there is separate code. This comment
2172 * block describes the data structures and algorithms built by
2173 * this code.
2174 *
2175 * The 040 does not support early terminating descriptors, as
2176 * the 030 does. Therefore, a third level of table is needed
2177 * for the 040, and that would be the page table. In Linux,
2178 * page tables are allocated directly from the memory above the
2179 * kernel.
2180 *
2181 */
2182
2183L(mmu_map_040):
2184 /* Calculate the offset into the root table
2185 */
2186 movel %a3,%d0
2187 moveq #ROOT_INDEX_SHIFT,%d1
2188 lsrl %d1,%d0
2189 mmu_get_root_table_entry %d0
2190
2191 /* Calculate the offset into the pointer table
2192 */
2193 movel %a3,%d0
2194 moveq #PTR_INDEX_SHIFT,%d1
2195 lsrl %d1,%d0
2196 andl #PTR_TABLE_SIZE-1,%d0
2197 mmu_get_ptr_table_entry %a0,%d0
2198
2199 /* Calculate the offset into the page table
2200 */
2201 movel %a3,%d0
2202 moveq #PAGE_INDEX_SHIFT,%d1
2203 lsrl %d1,%d0
2204 andl #PAGE_TABLE_SIZE-1,%d0
2205 mmu_get_page_table_entry %a0,%d0
2206
2207 /* The page table entry must not no be busy
2208 */
2209 tstl %a0@
2210 jne L(mmu_map_error)
2211
2212 /* Do the mapping and advance the pointers
2213 */
2214 movel %a2,%a0@
22152:
2216 addw #PAGESIZE,%a2
2217 addw #PAGESIZE,%a3
2218
2219 /* Ready with mapping?
2220 */
2221 lea %a3@(-1),%a0
2222 cmpl %a0,%a4
2223 jhi L(mmu_map_040)
2224 jra L(mmu_map_done)
2225
2226L(mmu_map_030):
2227 /* Calculate the offset into the root table
2228 */
2229 movel %a3,%d0
2230 moveq #ROOT_INDEX_SHIFT,%d1
2231 lsrl %d1,%d0
2232 mmu_get_root_table_entry %d0
2233
2234 /* Check if logical address 32MB aligned,
2235 * so we can try to map it once
2236 */
2237 movel %a3,%d0
2238 andl #(PTR_TABLE_SIZE*PAGE_TABLE_SIZE*PAGESIZE-1)&(-ROOT_TABLE_SIZE),%d0
2239 jne 1f
2240
2241 /* Is there enough to map for 32MB at once
2242 */
2243 lea %a3@(PTR_TABLE_SIZE*PAGE_TABLE_SIZE*PAGESIZE-1),%a1
2244 cmpl %a1,%a4
2245 jcs 1f
2246
2247 addql #1,%a1
2248
2249 /* The root table entry must not no be busy
2250 */
2251 tstl %a0@
2252 jne L(mmu_map_error)
2253
2254 /* Do the mapping and advance the pointers
2255 */
2256 dputs "early term1"
2257 dputn %a2
2258 dputn %a3
2259 dputn %a1
2260 dputc '\n'
2261 movel %a2,%a0@
2262
2263 movel %a1,%a3
2264 lea %a2@(PTR_TABLE_SIZE*PAGE_TABLE_SIZE*PAGESIZE),%a2
2265 jra L(mmu_mapnext_030)
22661:
2267 /* Calculate the offset into the pointer table
2268 */
2269 movel %a3,%d0
2270 moveq #PTR_INDEX_SHIFT,%d1
2271 lsrl %d1,%d0
2272 andl #PTR_TABLE_SIZE-1,%d0
2273 mmu_get_ptr_table_entry %a0,%d0
2274
2275 /* The pointer table entry must not no be busy
2276 */
2277 tstl %a0@
2278 jne L(mmu_map_error)
2279
2280 /* Do the mapping and advance the pointers
2281 */
2282 dputs "early term2"
2283 dputn %a2
2284 dputn %a3
2285 dputc '\n'
2286 movel %a2,%a0@
2287
2288 addl #PAGE_TABLE_SIZE*PAGESIZE,%a2
2289 addl #PAGE_TABLE_SIZE*PAGESIZE,%a3
2290
2291L(mmu_mapnext_030):
2292 /* Ready with mapping?
2293 */
2294 lea %a3@(-1),%a0
2295 cmpl %a0,%a4
2296 jhi L(mmu_map_030)
2297 jra L(mmu_map_done)
2298
2299L(mmu_map_error):
2300
2301 dputs "mmu_map error:"
2302 dputn %a2
2303 dputn %a3
2304 dputc '\n'
2305
2306L(mmu_map_done):
2307
2308func_return mmu_map
2309
2310/*
2311 * mmu_fixup
2312 *
2313 * On the 040 class machines, all pages that are used for the
2314 * mmu have to be fixed up.
2315 */
2316
2317func_start mmu_fixup_page_mmu_cache,%d0/%a0
2318
2319 dputs "mmu_fixup_page_mmu_cache"
2320 dputn ARG1
2321
2322 /* Calculate the offset into the root table
2323 */
2324 movel ARG1,%d0
2325 moveq #ROOT_INDEX_SHIFT,%d1
2326 lsrl %d1,%d0
2327 mmu_get_root_table_entry %d0
2328
2329 /* Calculate the offset into the pointer table
2330 */
2331 movel ARG1,%d0
2332 moveq #PTR_INDEX_SHIFT,%d1
2333 lsrl %d1,%d0
2334 andl #PTR_TABLE_SIZE-1,%d0
2335 mmu_get_ptr_table_entry %a0,%d0
2336
2337 /* Calculate the offset into the page table
2338 */
2339 movel ARG1,%d0
2340 moveq #PAGE_INDEX_SHIFT,%d1
2341 lsrl %d1,%d0
2342 andl #PAGE_TABLE_SIZE-1,%d0
2343 mmu_get_page_table_entry %a0,%d0
2344
2345 movel %a0@,%d0
2346 andil #_CACHEMASK040,%d0
2347 orl %pc@(m68k_pgtable_cachemode),%d0
2348 movel %d0,%a0@
2349
2350 dputc '\n'
2351
2352func_return mmu_fixup_page_mmu_cache
2353
2354/*
2355 * mmu_temp_map
2356 *
2357 * create a temporary mapping to enable the mmu,
2358 * this we don't need any transparation translation tricks.
2359 */
2360
2361func_start mmu_temp_map,%d0/%d1/%a0/%a1
2362
2363 dputs "mmu_temp_map"
2364 dputn ARG1
2365 dputn ARG2
2366 dputc '\n'
2367
2368 lea %pc@(L(temp_mmap_mem)),%a1
2369
2370 /* Calculate the offset in the root table
2371 */
2372 movel ARG2,%d0
2373 moveq #ROOT_INDEX_SHIFT,%d1
2374 lsrl %d1,%d0
2375 mmu_get_root_table_entry %d0
2376
2377 /* Check if the table is temporary allocated, so we have to reuse it
2378 */
2379 movel %a0@,%d0
2380 cmpl %pc@(L(memory_start)),%d0
2381 jcc 1f
2382
2383 /* Temporary allocate a ptr table and insert it into the root table
2384 */
2385 movel %a1@,%d0
2386 addl #PTR_TABLE_SIZE*4,%a1@
2387 orw #_PAGE_TABLE+_PAGE_ACCESSED,%d0
2388 movel %d0,%a0@
2389 dputs " (new)"
23901:
2391 dputn %d0
2392 /* Mask the root table entry for the ptr table
2393 */
2394 andw #-ROOT_TABLE_SIZE,%d0
2395 movel %d0,%a0
2396
2397 /* Calculate the offset into the pointer table
2398 */
2399 movel ARG2,%d0
2400 moveq #PTR_INDEX_SHIFT,%d1
2401 lsrl %d1,%d0
2402 andl #PTR_TABLE_SIZE-1,%d0
2403 lea %a0@(%d0*4),%a0
2404 dputn %a0
2405
2406 /* Check if a temporary page table is already allocated
2407 */
2408 movel %a0@,%d0
2409 jne 1f
2410
2411 /* Temporary allocate a page table and insert it into the ptr table
2412 */
2413 movel %a1@,%d0
2414 /* The 512 should be PAGE_TABLE_SIZE*4, but that violates the
2415 alignment restriction for pointer tables on the '0[46]0. */
2416 addl #512,%a1@
2417 orw #_PAGE_TABLE+_PAGE_ACCESSED,%d0
2418 movel %d0,%a0@
2419 dputs " (new)"
24201:
2421 dputn %d0
2422 /* Mask the ptr table entry for the page table
2423 */
2424 andw #-PTR_TABLE_SIZE,%d0
2425 movel %d0,%a0
2426
2427 /* Calculate the offset into the page table
2428 */
2429 movel ARG2,%d0
2430 moveq #PAGE_INDEX_SHIFT,%d1
2431 lsrl %d1,%d0
2432 andl #PAGE_TABLE_SIZE-1,%d0
2433 lea %a0@(%d0*4),%a0
2434 dputn %a0
2435
2436 /* Insert the address into the page table
2437 */
2438 movel ARG1,%d0
2439 andw #-PAGESIZE,%d0
2440 orw #_PAGE_PRESENT+_PAGE_ACCESSED+_PAGE_DIRTY,%d0
2441 movel %d0,%a0@
2442 dputn %d0
2443
2444 dputc '\n'
2445
2446func_return mmu_temp_map
2447
2448func_start mmu_engage,%d0-%d2/%a0-%a3
2449
2450 moveq #ROOT_TABLE_SIZE-1,%d0
2451 /* Temporarily use a different root table. */
2452 lea %pc@(L(kernel_pgdir_ptr)),%a0
2453 movel %a0@,%a2
2454 movel %pc@(L(memory_start)),%a1
2455 movel %a1,%a0@
2456 movel %a2,%a0
24571:
2458 movel %a0@+,%a1@+
2459 dbra %d0,1b
2460
2461 lea %pc@(L(temp_mmap_mem)),%a0
2462 movel %a1,%a0@
2463
2464 movew #PAGESIZE-1,%d0
24651:
2466 clrl %a1@+
2467 dbra %d0,1b
2468
2469 lea %pc@(1b),%a0
2470 movel #1b,%a1
2471 /* Skip temp mappings if phys == virt */
2472 cmpl %a0,%a1
2473 jeq 1f
2474
2475 mmu_temp_map %a0,%a0
2476 mmu_temp_map %a0,%a1
2477
2478 addw #PAGESIZE,%a0
2479 addw #PAGESIZE,%a1
2480 mmu_temp_map %a0,%a0
2481 mmu_temp_map %a0,%a1
24821:
2483 movel %pc@(L(memory_start)),%a3
2484 movel %pc@(L(phys_kernel_start)),%d2
2485
2486 is_not_040_or_060(L(mmu_engage_030))
2487
2488L(mmu_engage_040):
2489 .chip 68040
2490 nop
2491 cinva %bc
2492 nop
2493 pflusha
2494 nop
2495 movec %a3,%srp
2496 movel #TC_ENABLE+TC_PAGE4K,%d0
2497 movec %d0,%tc /* enable the MMU */
2498 jmp 1f:l
24991: nop
2500 movec %a2,%srp
2501 nop
2502 cinva %bc
2503 nop
2504 pflusha
2505 .chip 68k
2506 jra L(mmu_engage_cleanup)
2507
2508L(mmu_engage_030_temp):
2509 .space 12
2510L(mmu_engage_030):
2511 .chip 68030
2512 lea %pc@(L(mmu_engage_030_temp)),%a0
2513 movel #0x80000002,%a0@
2514 movel %a3,%a0@(4)
2515 movel #0x0808,%d0
2516 movec %d0,%cacr
2517 pmove %a0@,%srp
2518 pflusha
2519 /*
2520 * enable,super root enable,4096 byte pages,7 bit root index,
2521 * 7 bit pointer index, 6 bit page table index.
2522 */
2523 movel #0x82c07760,%a0@(8)
2524 pmove %a0@(8),%tc /* enable the MMU */
2525 jmp 1f:l
25261: movel %a2,%a0@(4)
2527 movel #0x0808,%d0
2528 movec %d0,%cacr
2529 pmove %a0@,%srp
2530 pflusha
2531 .chip 68k
2532
2533L(mmu_engage_cleanup):
2534 subl #PAGE_OFFSET,%d2
2535 subl %d2,%a2
2536 movel %a2,L(kernel_pgdir_ptr)
2537 subl %d2,%fp
2538 subl %d2,%sp
2539 subl %d2,ARG0
2540
2541func_return mmu_engage
2542
2543func_start mmu_get_root_table_entry,%d0/%a1
2544
2545#if 0
2546 dputs "mmu_get_root_table_entry:"
2547 dputn ARG1
2548 dputs " ="
2549#endif
2550
2551 movel %pc@(L(kernel_pgdir_ptr)),%a0
2552 tstl %a0
2553 jne 2f
2554
2555 dputs "\nmmu_init:"
2556
2557 /* Find the start of free memory, get_bi_record does this for us,
2558 * as the bootinfo structure is located directly behind the kernel
2559 * and and we simply search for the last entry.
2560 */
2561 get_bi_record BI_LAST
2562 addw #PAGESIZE-1,%a0
2563 movel %a0,%d0
2564 andw #-PAGESIZE,%d0
2565
2566 dputn %d0
2567
2568 lea %pc@(L(memory_start)),%a0
2569 movel %d0,%a0@
2570 lea %pc@(L(kernel_end)),%a0
2571 movel %d0,%a0@
2572
2573 /* we have to return the first page at _stext since the init code
2574 * in mm/init.c simply expects kernel_pg_dir there, the rest of
2575 * page is used for further ptr tables in get_ptr_table.
2576 */
2577 lea %pc@(_stext),%a0
2578 lea %pc@(L(mmu_cached_pointer_tables)),%a1
2579 movel %a0,%a1@
2580 addl #ROOT_TABLE_SIZE*4,%a1@
2581
2582 lea %pc@(L(mmu_num_pointer_tables)),%a1
2583 addql #1,%a1@
2584
2585 /* clear the page
2586 */
2587 movel %a0,%a1
2588 movew #PAGESIZE/4-1,%d0
25891:
2590 clrl %a1@+
2591 dbra %d0,1b
2592
2593 lea %pc@(L(kernel_pgdir_ptr)),%a1
2594 movel %a0,%a1@
2595
2596 dputn %a0
2597 dputc '\n'
25982:
2599 movel ARG1,%d0
2600 lea %a0@(%d0*4),%a0
2601
2602#if 0
2603 dputn %a0
2604 dputc '\n'
2605#endif
2606
2607func_return mmu_get_root_table_entry
2608
2609
2610
2611func_start mmu_get_ptr_table_entry,%d0/%a1
2612
2613#if 0
2614 dputs "mmu_get_ptr_table_entry:"
2615 dputn ARG1
2616 dputn ARG2
2617 dputs " ="
2618#endif
2619
2620 movel ARG1,%a0
2621 movel %a0@,%d0
2622 jne 2f
2623
2624 /* Keep track of the number of pointer tables we use
2625 */
2626 dputs "\nmmu_get_new_ptr_table:"
2627 lea %pc@(L(mmu_num_pointer_tables)),%a0
2628 movel %a0@,%d0
2629 addql #1,%a0@
2630
2631 /* See if there is a free pointer table in our cache of pointer tables
2632 */
2633 lea %pc@(L(mmu_cached_pointer_tables)),%a1
2634 andw #7,%d0
2635 jne 1f
2636
2637 /* Get a new pointer table page from above the kernel memory
2638 */
2639 get_new_page
2640 movel %a0,%a1@
26411:
2642 /* There is an unused pointer table in our cache... use it
2643 */
2644 movel %a1@,%d0
2645 addl #PTR_TABLE_SIZE*4,%a1@
2646
2647 dputn %d0
2648 dputc '\n'
2649
2650 /* Insert the new pointer table into the root table
2651 */
2652 movel ARG1,%a0
2653 orw #_PAGE_TABLE+_PAGE_ACCESSED,%d0
2654 movel %d0,%a0@
26552:
2656 /* Extract the pointer table entry
2657 */
2658 andw #-PTR_TABLE_SIZE,%d0
2659 movel %d0,%a0
2660 movel ARG2,%d0
2661 lea %a0@(%d0*4),%a0
2662
2663#if 0
2664 dputn %a0
2665 dputc '\n'
2666#endif
2667
2668func_return mmu_get_ptr_table_entry
2669
2670
2671func_start mmu_get_page_table_entry,%d0/%a1
2672
2673#if 0
2674 dputs "mmu_get_page_table_entry:"
2675 dputn ARG1
2676 dputn ARG2
2677 dputs " ="
2678#endif
2679
2680 movel ARG1,%a0
2681 movel %a0@,%d0
2682 jne 2f
2683
2684 /* If the page table entry doesn't exist, we allocate a complete new
2685 * page and use it as one continues big page table which can cover
2686 * 4MB of memory, nearly almost all mappings have that alignment.
2687 */
2688 get_new_page
2689 addw #_PAGE_TABLE+_PAGE_ACCESSED,%a0
2690
2691 /* align pointer table entry for a page of page tables
2692 */
2693 movel ARG1,%d0
2694 andw #-(PAGESIZE/PAGE_TABLE_SIZE),%d0
2695 movel %d0,%a1
2696
2697 /* Insert the page tables into the pointer entries
2698 */
2699 moveq #PAGESIZE/PAGE_TABLE_SIZE/4-1,%d0
27001:
2701 movel %a0,%a1@+
2702 lea %a0@(PAGE_TABLE_SIZE*4),%a0
2703 dbra %d0,1b
2704
2705 /* Now we can get the initialized pointer table entry
2706 */
2707 movel ARG1,%a0
2708 movel %a0@,%d0
27092:
2710 /* Extract the page table entry
2711 */
2712 andw #-PAGE_TABLE_SIZE,%d0
2713 movel %d0,%a0
2714 movel ARG2,%d0
2715 lea %a0@(%d0*4),%a0
2716
2717#if 0
2718 dputn %a0
2719 dputc '\n'
2720#endif
2721
2722func_return mmu_get_page_table_entry
2723
2724/*
2725 * get_new_page
2726 *
2727 * Return a new page from the memory start and clear it.
2728 */
2729func_start get_new_page,%d0/%a1
2730
2731 dputs "\nget_new_page:"
2732
2733 /* allocate the page and adjust memory_start
2734 */
2735 lea %pc@(L(memory_start)),%a0
2736 movel %a0@,%a1
2737 addl #PAGESIZE,%a0@
2738
2739 /* clear the new page
2740 */
2741 movel %a1,%a0
2742 movew #PAGESIZE/4-1,%d0
27431:
2744 clrl %a1@+
2745 dbra %d0,1b
2746
2747 dputn %a0
2748 dputc '\n'
2749
2750func_return get_new_page
2751
2752
2753
2754/*
2755 * Debug output support
2756 * Atarians have a choice between the parallel port, the serial port
2757 * from the MFP or a serial port of the SCC
2758 */
2759
2760#ifdef CONFIG_MAC
2761
2762L(scc_initable_mac):
2763 .byte 9,12 /* Reset */
2764 .byte 4,0x44 /* x16, 1 stopbit, no parity */
2765 .byte 3,0xc0 /* receiver: 8 bpc */
2766 .byte 5,0xe2 /* transmitter: 8 bpc, assert dtr/rts */
2767 .byte 9,0 /* no interrupts */
2768 .byte 10,0 /* NRZ */
2769 .byte 11,0x50 /* use baud rate generator */
2770 .byte 12,10,13,0 /* 9600 baud */
2771 .byte 14,1 /* Baud rate generator enable */
2772 .byte 3,0xc1 /* enable receiver */
2773 .byte 5,0xea /* enable transmitter */
2774 .byte -1
2775 .even
2776#endif
2777
2778#ifdef CONFIG_ATARI
2779/* #define USE_PRINTER */
2780/* #define USE_SCC_B */
2781/* #define USE_SCC_A */
2782#define USE_MFP
2783
2784#if defined(USE_SCC_A) || defined(USE_SCC_B)
2785#define USE_SCC
2786/* Initialisation table for SCC */
2787L(scc_initable):
2788 .byte 9,12 /* Reset */
2789 .byte 4,0x44 /* x16, 1 stopbit, no parity */
2790 .byte 3,0xc0 /* receiver: 8 bpc */
2791 .byte 5,0xe2 /* transmitter: 8 bpc, assert dtr/rts */
2792 .byte 9,0 /* no interrupts */
2793 .byte 10,0 /* NRZ */
2794 .byte 11,0x50 /* use baud rate generator */
2795 .byte 12,24,13,0 /* 9600 baud */
2796 .byte 14,2,14,3 /* use master clock for BRG, enable */
2797 .byte 3,0xc1 /* enable receiver */
2798 .byte 5,0xea /* enable transmitter */
2799 .byte -1
2800 .even
2801#endif
2802
2803#ifdef USE_PRINTER
2804
2805LPSG_SELECT = 0xff8800
2806LPSG_READ = 0xff8800
2807LPSG_WRITE = 0xff8802
2808LPSG_IO_A = 14
2809LPSG_IO_B = 15
2810LPSG_CONTROL = 7
2811LSTMFP_GPIP = 0xfffa01
2812LSTMFP_DDR = 0xfffa05
2813LSTMFP_IERB = 0xfffa09
2814
2815#elif defined(USE_SCC_B)
2816
2817LSCC_CTRL = 0xff8c85
2818LSCC_DATA = 0xff8c87
2819
2820#elif defined(USE_SCC_A)
2821
2822LSCC_CTRL = 0xff8c81
2823LSCC_DATA = 0xff8c83
2824
2825#elif defined(USE_MFP)
2826
2827LMFP_UCR = 0xfffa29
2828LMFP_TDCDR = 0xfffa1d
2829LMFP_TDDR = 0xfffa25
2830LMFP_TSR = 0xfffa2d
2831LMFP_UDR = 0xfffa2f
2832
2833#endif
2834#endif /* CONFIG_ATARI */
2835
2836/*
2837 * Serial port output support.
2838 */
2839
2840/*
2841 * Initialize serial port hardware for 9600/8/1
2842 */
2843func_start serial_init,%d0/%d1/%a0/%a1
2844 /*
2845 * Some of the register usage that follows
2846 * CONFIG_AMIGA
2847 * a0 = pointer to boot info record
2848 * d0 = boot info offset
2849 * CONFIG_ATARI
2850 * a0 = address of SCC
2851 * a1 = Liobase address/address of scc_initable
2852 * d0 = init data for serial port
2853 * CONFIG_MAC
2854 * a0 = address of SCC
2855 * a1 = address of scc_initable_mac
2856 * d0 = init data for serial port
2857 */
2858
2859#ifdef CONFIG_AMIGA
2860#define SERIAL_DTR 7
2861#define SERIAL_CNTRL CIABBASE+C_PRA
2862
2863 is_not_amiga(1f)
2864 lea %pc@(L(custom)),%a0
2865 movel #-ZTWOBASE,%a0@
2866 bclr #SERIAL_DTR,SERIAL_CNTRL-ZTWOBASE
2867 get_bi_record BI_AMIGA_SERPER
2868 movew %a0@,CUSTOMBASE+C_SERPER-ZTWOBASE
2869| movew #61,CUSTOMBASE+C_SERPER-ZTWOBASE
28701:
2871#endif
2872#ifdef CONFIG_ATARI
2873 is_not_atari(4f)
2874 movel %pc@(L(iobase)),%a1
2875#if defined(USE_PRINTER)
2876 bclr #0,%a1@(LSTMFP_IERB)
2877 bclr #0,%a1@(LSTMFP_DDR)
2878 moveb #LPSG_CONTROL,%a1@(LPSG_SELECT)
2879 moveb #0xff,%a1@(LPSG_WRITE)
2880 moveb #LPSG_IO_B,%a1@(LPSG_SELECT)
2881 clrb %a1@(LPSG_WRITE)
2882 moveb #LPSG_IO_A,%a1@(LPSG_SELECT)
2883 moveb %a1@(LPSG_READ),%d0
2884 bset #5,%d0
2885 moveb %d0,%a1@(LPSG_WRITE)
2886#elif defined(USE_SCC)
2887 lea %a1@(LSCC_CTRL),%a0
2888 lea %pc@(L(scc_initable)),%a1
28892: moveb %a1@+,%d0
2890 jmi 3f
2891 moveb %d0,%a0@
2892 moveb %a1@+,%a0@
2893 jra 2b
28943: clrb %a0@
2895#elif defined(USE_MFP)
2896 bclr #1,%a1@(LMFP_TSR)
2897 moveb #0x88,%a1@(LMFP_UCR)
2898 andb #0x70,%a1@(LMFP_TDCDR)
2899 moveb #2,%a1@(LMFP_TDDR)
2900 orb #1,%a1@(LMFP_TDCDR)
2901 bset #1,%a1@(LMFP_TSR)
2902#endif
2903 jra L(serial_init_done)
29044:
2905#endif
2906#ifdef CONFIG_MAC
2907 is_not_mac(L(serial_init_not_mac))
2908#ifdef MAC_SERIAL_DEBUG
2909#if !defined(MAC_USE_SCC_A) && !defined(MAC_USE_SCC_B)
2910#define MAC_USE_SCC_B
2911#endif
2912#define mac_scc_cha_b_ctrl_offset 0x0
2913#define mac_scc_cha_a_ctrl_offset 0x2
2914#define mac_scc_cha_b_data_offset 0x4
2915#define mac_scc_cha_a_data_offset 0x6
2916
2917#ifdef MAC_USE_SCC_A
2918 /* Initialize channel A */
2919 movel %pc@(L(mac_sccbase)),%a0
2920 lea %pc@(L(scc_initable_mac)),%a1
29215: moveb %a1@+,%d0
2922 jmi 6f
2923 moveb %d0,%a0@(mac_scc_cha_a_ctrl_offset)
2924 moveb %a1@+,%a0@(mac_scc_cha_a_ctrl_offset)
2925 jra 5b
29266:
2927#endif /* MAC_USE_SCC_A */
2928
2929#ifdef MAC_USE_SCC_B
2930 /* Initialize channel B */
2931#ifndef MAC_USE_SCC_A /* Load mac_sccbase only if needed */
2932 movel %pc@(L(mac_sccbase)),%a0
2933#endif /* MAC_USE_SCC_A */
2934 lea %pc@(L(scc_initable_mac)),%a1
29357: moveb %a1@+,%d0
2936 jmi 8f
2937 moveb %d0,%a0@(mac_scc_cha_b_ctrl_offset)
2938 moveb %a1@+,%a0@(mac_scc_cha_b_ctrl_offset)
2939 jra 7b
29408:
2941#endif /* MAC_USE_SCC_B */
2942#endif /* MAC_SERIAL_DEBUG */
2943
2944 jra L(serial_init_done)
2945L(serial_init_not_mac):
2946#endif /* CONFIG_MAC */
2947
2948#ifdef CONFIG_Q40
2949 is_not_q40(2f)
2950/* debug output goes into SRAM, so we don't do it unless requested
2951 - check for '%LX$' signature in SRAM */
2952 lea %pc@(q40_mem_cptr),%a1
2953 move.l #0xff020010,%a1@ /* must be inited - also used by debug=mem */
2954 move.l #0xff020000,%a1
2955 cmp.b #'%',%a1@
2956 bne 2f /*nodbg*/
2957 addq.w #4,%a1
2958 cmp.b #'L',%a1@
2959 bne 2f /*nodbg*/
2960 addq.w #4,%a1
2961 cmp.b #'X',%a1@
2962 bne 2f /*nodbg*/
2963 addq.w #4,%a1
2964 cmp.b #'$',%a1@
2965 bne 2f /*nodbg*/
2966 /* signature OK */
2967 lea %pc@(L(q40_do_debug)),%a1
2968 tas %a1@
2969/*nodbg: q40_do_debug is 0 by default*/
29702:
2971#endif
2972
2973#ifdef CONFIG_APOLLO
2974/* We count on the PROM initializing SIO1 */
2975#endif
2976
2977#ifdef CONFIG_HP300
2978/* We count on the boot loader initialising the UART */
2979#endif
2980
2981L(serial_init_done):
2982func_return serial_init
2983
2984/*
2985 * Output character on serial port.
2986 */
2987func_start serial_putc,%d0/%d1/%a0/%a1
2988
2989 movel ARG1,%d0
2990 cmpib #'\n',%d0
2991 jbne 1f
2992
2993 /* A little safe recursion is good for the soul */
2994 serial_putc #'\r'
29951:
2996
2997#ifdef CONFIG_AMIGA
2998 is_not_amiga(2f)
2999 andw #0x00ff,%d0
3000 oriw #0x0100,%d0
3001 movel %pc@(L(custom)),%a0
3002 movew %d0,%a0@(CUSTOMBASE+C_SERDAT)
30031: movew %a0@(CUSTOMBASE+C_SERDATR),%d0
3004 andw #0x2000,%d0
3005 jeq 1b
3006 jra L(serial_putc_done)
30072:
3008#endif
3009
3010#ifdef CONFIG_MAC
3011 is_not_mac(5f)
3012
3013#ifdef MAC_SERIAL_DEBUG
3014
3015#ifdef MAC_USE_SCC_A
3016 movel %pc@(L(mac_sccbase)),%a1
30173: btst #2,%a1@(mac_scc_cha_a_ctrl_offset)
3018 jeq 3b
3019 moveb %d0,%a1@(mac_scc_cha_a_data_offset)
3020#endif /* MAC_USE_SCC_A */
3021
3022#ifdef MAC_USE_SCC_B
3023#ifndef MAC_USE_SCC_A /* Load mac_sccbase only if needed */
3024 movel %pc@(L(mac_sccbase)),%a1
3025#endif /* MAC_USE_SCC_A */
30264: btst #2,%a1@(mac_scc_cha_b_ctrl_offset)
3027 jeq 4b
3028 moveb %d0,%a1@(mac_scc_cha_b_data_offset)
3029#endif /* MAC_USE_SCC_B */
3030
3031#endif /* MAC_SERIAL_DEBUG */
3032
3033 jra L(serial_putc_done)
30345:
3035#endif /* CONFIG_MAC */
3036
3037#ifdef CONFIG_ATARI
3038 is_not_atari(4f)
3039 movel %pc@(L(iobase)),%a1
3040#if defined(USE_PRINTER)
30413: btst #0,%a1@(LSTMFP_GPIP)
3042 jne 3b
3043 moveb #LPSG_IO_B,%a1@(LPSG_SELECT)
3044 moveb %d0,%a1@(LPSG_WRITE)
3045 moveb #LPSG_IO_A,%a1@(LPSG_SELECT)
3046 moveb %a1@(LPSG_READ),%d0
3047 bclr #5,%d0
3048 moveb %d0,%a1@(LPSG_WRITE)
3049 nop
3050 nop
3051 bset #5,%d0
3052 moveb %d0,%a1@(LPSG_WRITE)
3053#elif defined(USE_SCC)
30543: btst #2,%a1@(LSCC_CTRL)
3055 jeq 3b
3056 moveb %d0,%a1@(LSCC_DATA)
3057#elif defined(USE_MFP)
30583: btst #7,%a1@(LMFP_TSR)
3059 jeq 3b
3060 moveb %d0,%a1@(LMFP_UDR)
3061#endif
3062 jra L(serial_putc_done)
30634:
3064#endif /* CONFIG_ATARI */
3065
3066#ifdef CONFIG_MVME147
3067 is_not_mvme147(2f)
30681: btst #2,M147_SCC_CTRL_A
3069 jeq 1b
3070 moveb %d0,M147_SCC_DATA_A
3071 jbra L(serial_putc_done)
30722:
3073#endif
3074
3075#ifdef CONFIG_MVME16x
3076 is_not_mvme16x(2f)
3077 /*
3078 * If the loader gave us a board type then we can use that to
3079 * select an appropriate output routine; otherwise we just use
3080 * the Bug code. If we haev to use the Bug that means the Bug
3081 * workspace has to be valid, which means the Bug has to use
3082 * the SRAM, which is non-standard.
3083 */
3084 moveml %d0-%d7/%a2-%a6,%sp@-
3085 movel vme_brdtype,%d1
3086 jeq 1f | No tag - use the Bug
3087 cmpi #VME_TYPE_MVME162,%d1
3088 jeq 6f
3089 cmpi #VME_TYPE_MVME172,%d1
3090 jne 5f
3091 /* 162/172; it's an SCC */
30926: btst #2,M162_SCC_CTRL_A
3093 nop
3094 nop
3095 nop
3096 jeq 6b
3097 moveb #8,M162_SCC_CTRL_A
3098 nop
3099 nop
3100 nop
3101 moveb %d0,M162_SCC_CTRL_A
3102 jra 3f
31035:
3104 /* 166/167/177; it's a CD2401 */
3105 moveb #0,M167_CYCAR
3106 moveb M167_CYIER,%d2
3107 moveb #0x02,M167_CYIER
31087:
3109 btst #5,M167_PCSCCTICR
3110 jeq 7b
3111 moveb M167_PCTPIACKR,%d1
3112 moveb M167_CYLICR,%d1
3113 jeq 8f
3114 moveb #0x08,M167_CYTEOIR
3115 jra 7b
31168:
3117 moveb %d0,M167_CYTDR
3118 moveb #0,M167_CYTEOIR
3119 moveb %d2,M167_CYIER
3120 jra 3f
31211:
3122 moveb %d0,%sp@-
3123 trap #15
3124 .word 0x0020 /* TRAP 0x020 */
31253:
3126 moveml %sp@+,%d0-%d7/%a2-%a6
3127 jbra L(serial_putc_done)
31282:
3129#endif /* CONFIG_MVME16x */
3130
3131#ifdef CONFIG_BVME6000
3132 is_not_bvme6000(2f)
3133 /*
3134 * The BVME6000 machine has a serial port ...
3135 */
31361: btst #2,BVME_SCC_CTRL_A
3137 jeq 1b
3138 moveb %d0,BVME_SCC_DATA_A
3139 jbra L(serial_putc_done)
31402:
3141#endif
3142
3143#ifdef CONFIG_SUN3X
3144 is_not_sun3x(2f)
3145 movel %d0,-(%sp)
3146 movel 0xFEFE0018,%a1
3147 jbsr (%a1)
3148 addq #4,%sp
3149 jbra L(serial_putc_done)
31502:
3151#endif
3152
3153#ifdef CONFIG_Q40
3154 is_not_q40(2f)
3155 tst.l %pc@(L(q40_do_debug)) /* only debug if requested */
3156 beq 2f
3157 lea %pc@(q40_mem_cptr),%a1
3158 move.l %a1@,%a0
3159 move.b %d0,%a0@
3160 addq.l #4,%a0
3161 move.l %a0,%a1@
3162 jbra L(serial_putc_done)
31632:
3164#endif
3165
3166#ifdef CONFIG_APOLLO
3167 is_not_apollo(2f)
3168 movl %pc@(L(iobase)),%a1
3169 moveb %d0,%a1@(LTHRB0)
31701: moveb %a1@(LSRB0),%d0
3171 andb #0x4,%d0
3172 beq 1b
3173 jbra L(serial_putc_done)
31742:
3175#endif
3176
3177#ifdef CONFIG_HP300
3178 is_not_hp300(3f)
3179 movl %pc@(L(iobase)),%a1
3180 addl %pc@(L(uartbase)),%a1
3181 movel %pc@(L(uart_scode)),%d1 /* Check the scode */
3182 jmi 3f /* Unset? Exit */
3183 cmpi #256,%d1 /* APCI scode? */
3184 jeq 2f
31851: moveb %a1@(DCALSR),%d1 /* Output to DCA */
3186 andb #0x20,%d1
3187 beq 1b
3188 moveb %d0,%a1@(DCADATA)
3189 jbra L(serial_putc_done)
31902: moveb %a1@(APCILSR),%d1 /* Output to APCI */
3191 andb #0x20,%d1
3192 beq 2b
3193 moveb %d0,%a1@(APCIDATA)
3194 jbra L(serial_putc_done)
31953:
3196#endif
3197
3198L(serial_putc_done):
3199func_return serial_putc
3200
3201/*
3202 * Output a string.
3203 */
3204func_start puts,%d0/%a0
3205
3206 movel ARG1,%a0
3207 jra 2f
32081:
3209#ifdef CONSOLE
3210 console_putc %d0
3211#endif
3212#ifdef SERIAL_DEBUG
3213 serial_putc %d0
3214#endif
32152: moveb %a0@+,%d0
3216 jne 1b
3217
3218func_return puts
3219
3220/*
3221 * Output number in hex notation.
3222 */
3223
3224func_start putn,%d0-%d2
3225
3226 putc ' '
3227
3228 movel ARG1,%d0
3229 moveq #7,%d1
32301: roll #4,%d0
3231 move %d0,%d2
3232 andb #0x0f,%d2
3233 addb #'0',%d2
3234 cmpb #'9',%d2
3235 jls 2f
3236 addb #'A'-('9'+1),%d2
32372:
3238#ifdef CONSOLE
3239 console_putc %d2
3240#endif
3241#ifdef SERIAL_DEBUG
3242 serial_putc %d2
3243#endif
3244 dbra %d1,1b
3245
3246func_return putn
3247
3248#ifdef CONFIG_MAC
3249/*
3250 * mac_serial_print
3251 *
3252 * This routine takes its parameters on the stack. It then
3253 * turns around and calls the internal routine. This routine
3254 * is used until the Linux console driver initializes itself.
3255 *
3256 * The calling parameters are:
3257 * void mac_serial_print(const char *str);
3258 *
3259 * This routine does NOT understand variable arguments only
3260 * simple strings!
3261 */
3262ENTRY(mac_serial_print)
3263 moveml %d0/%a0,%sp@-
3264#if 1
3265 move %sr,%sp@-
3266 ori #0x0700,%sr
3267#endif
3268 movel %sp@(10),%a0 /* fetch parameter */
3269 jra 2f
32701: serial_putc %d0
32712: moveb %a0@+,%d0
3272 jne 1b
3273#if 1
3274 move %sp@+,%sr
3275#endif
3276 moveml %sp@+,%d0/%a0
3277 rts
3278#endif /* CONFIG_MAC */
3279
3280#if defined(CONFIG_HP300) || defined(CONFIG_APOLLO)
3281func_start set_leds,%d0/%a0
3282 movel ARG1,%d0
3283#ifdef CONFIG_HP300
3284 is_not_hp300(1f)
3285 movel %pc@(L(iobase)),%a0
3286 moveb %d0,%a0@(0x1ffff)
3287 jra 2f
3288#endif
32891:
3290#ifdef CONFIG_APOLLO
3291 movel %pc@(L(iobase)),%a0
3292 lsll #8,%d0
3293 eorw #0xff00,%d0
3294 moveb %d0,%a0@(LCPUCTRL)
3295#endif
32962:
3297func_return set_leds
3298#endif
3299
3300#ifdef CONSOLE
3301/*
3302 * For continuity, see the data alignment
3303 * to which this structure is tied.
3304 */
3305#define Lconsole_struct_cur_column 0
3306#define Lconsole_struct_cur_row 4
3307#define Lconsole_struct_num_columns 8
3308#define Lconsole_struct_num_rows 12
3309#define Lconsole_struct_left_edge 16
3310#define Lconsole_struct_penguin_putc 20
3311
3312func_start console_init,%a0-%a4/%d0-%d7
3313 /*
3314 * Some of the register usage that follows
3315 * a0 = pointer to boot_info
3316 * a1 = pointer to screen
3317 * a2 = pointer to Lconsole_globals
3318 * d3 = pixel width of screen
3319 * d4 = pixel height of screen
3320 * (d3,d4) ~= (x,y) of a point just below
3321 * and to the right of the screen
3322 * NOT on the screen!
3323 * d5 = number of bytes per scan line
3324 * d6 = number of bytes on the entire screen
3325 */
3326
3327 lea %pc@(L(console_globals)),%a2
3328 movel %pc@(L(mac_videobase)),%a1
3329 movel %pc@(L(mac_rowbytes)),%d5
3330 movel %pc@(L(mac_dimensions)),%d3 /* -> low byte */
3331 movel %d3,%d4
3332 swap %d4 /* -> high byte */
3333 andl #0xffff,%d3 /* d3 = screen width in pixels */
3334 andl #0xffff,%d4 /* d4 = screen height in pixels */
3335
3336 movel %d5,%d6
3337| subl #20,%d6
3338 mulul %d4,%d6 /* scan line bytes x num scan lines */
3339 divul #8,%d6 /* we'll clear 8 bytes at a time */
3340 moveq #-1,%d0 /* Mac_black */
3341 subq #1,%d6
3342
3343L(console_clear_loop):
3344 movel %d0,%a1@+
3345 movel %d0,%a1@+
3346 dbra %d6,L(console_clear_loop)
3347
3348 /* Calculate font size */
3349
3350#if defined(FONT_8x8) && defined(CONFIG_FONT_8x8)
3351 lea %pc@(font_vga_8x8),%a0
3352#elif defined(FONT_8x16) && defined(CONFIG_FONT_8x16)
3353 lea %pc@(font_vga_8x16),%a0
3354#elif defined(FONT_6x11) && defined(CONFIG_FONT_6x11)
3355 lea %pc@(font_vga_6x11),%a0
3356#elif defined(CONFIG_FONT_8x8) /* default */
3357 lea %pc@(font_vga_8x8),%a0
3358#else /* no compiled-in font */
3359 lea 0,%a0
3360#endif
3361
3362 /*
3363 * At this point we make a shift in register usage
3364 * a1 = address of console_font pointer
3365 */
3366 lea %pc@(L(console_font)),%a1
3367 movel %a0,%a1@ /* store pointer to struct fbcon_font_desc in console_font */
3368 tstl %a0
3369 jeq 1f
3370 lea %pc@(L(console_font_data)),%a4
3371 movel %a0@(FONT_DESC_DATA),%d0
3372 subl #L(console_font),%a1
3373 addl %a1,%d0
3374 movel %d0,%a4@
3375
3376 /*
3377 * Calculate global maxs
3378 * Note - we can use either an
3379 * 8 x 16 or 8 x 8 character font
3380 * 6 x 11 also supported
3381 */
3382 /* ASSERT: a0 = contents of Lconsole_font */
3383 movel %d3,%d0 /* screen width in pixels */
3384 divul %a0@(FONT_DESC_WIDTH),%d0 /* d0 = max num chars per row */
3385
3386 movel %d4,%d1 /* screen height in pixels */
3387 divul %a0@(FONT_DESC_HEIGHT),%d1 /* d1 = max num rows */
3388
3389 movel %d0,%a2@(Lconsole_struct_num_columns)
3390 movel %d1,%a2@(Lconsole_struct_num_rows)
3391
3392 /*
3393 * Clear the current row and column
3394 */
3395 clrl %a2@(Lconsole_struct_cur_column)
3396 clrl %a2@(Lconsole_struct_cur_row)
3397 clrl %a2@(Lconsole_struct_left_edge)
3398
3399 /*
3400 * Initialization is complete
3401 */
34021:
3403func_return console_init
3404
3405func_start console_put_stats,%a0/%d7
3406 /*
3407 * Some of the register usage that follows
3408 * a0 = pointer to boot_info
3409 * d7 = value of boot_info fields
3410 */
3411 puts "\nMacLinux\n\n"
3412
3413#ifdef SERIAL_DEBUG
3414 puts " vidaddr:"
3415 putn %pc@(L(mac_videobase)) /* video addr. */
3416
3417 puts "\n _stext:"
3418 lea %pc@(_stext),%a0
3419 putn %a0
3420
3421 puts "\nbootinfo:"
3422 lea %pc@(_end),%a0
3423 putn %a0
3424
3425 puts "\ncpuid:"
3426 putn %pc@(L(cputype))
3427 putc '\n'
3428
3429#ifdef MAC_SERIAL_DEBUG
3430 putn %pc@(L(mac_sccbase))
3431 putc '\n'
3432#endif
3433# if defined(MMU_PRINT)
3434 jbsr mmu_print_machine_cpu_types
3435# endif /* MMU_PRINT */
3436#endif /* SERIAL_DEBUG */
3437
3438func_return console_put_stats
3439
3440#ifdef CONSOLE_PENGUIN
3441func_start console_put_penguin,%a0-%a1/%d0-%d7
3442 /*
3443 * Get 'that_penguin' onto the screen in the upper right corner
3444 * penguin is 64 x 74 pixels, align against right edge of screen
3445 */
3446 lea %pc@(L(mac_dimensions)),%a0
3447 movel %a0@,%d0
3448 andil #0xffff,%d0
3449 subil #64,%d0 /* snug up against the right edge */
3450 clrl %d1 /* start at the top */
3451 movel #73,%d7
3452 lea %pc@(L(that_penguin)),%a1
3453L(console_penguin_row):
3454 movel #31,%d6
3455L(console_penguin_pixel_pair):
3456 moveb %a1@,%d2
3457 lsrb #4,%d2
3458 console_plot_pixel %d0,%d1,%d2
3459 addq #1,%d0
3460 moveb %a1@+,%d2
3461 console_plot_pixel %d0,%d1,%d2
3462 addq #1,%d0
3463 dbra %d6,L(console_penguin_pixel_pair)
3464
3465 subil #64,%d0
3466 addq #1,%d1
3467 dbra %d7,L(console_penguin_row)
3468
3469func_return console_put_penguin
3470
3471/* include penguin bitmap */
3472L(that_penguin):
3473#include "../mac/mac_penguin.S"
3474#endif
3475
3476 /*
3477 * Calculate source and destination addresses
3478 * output a1 = dest
3479 * a2 = source
3480 */
3481
3482func_start console_scroll,%a0-%a4/%d0-%d7
3483 lea %pc@(L(mac_videobase)),%a0
3484 movel %a0@,%a1
3485 movel %a1,%a2
3486 lea %pc@(L(mac_rowbytes)),%a0
3487 movel %a0@,%d5
3488 movel %pc@(L(console_font)),%a0
3489 tstl %a0
3490 jeq 1f
3491 mulul %a0@(FONT_DESC_HEIGHT),%d5 /* account for # scan lines per character */
3492 addal %d5,%a2
3493
3494 /*
3495 * Get dimensions
3496 */
3497 lea %pc@(L(mac_dimensions)),%a0
3498 movel %a0@,%d3
3499 movel %d3,%d4
3500 swap %d4
3501 andl #0xffff,%d3 /* d3 = screen width in pixels */
3502 andl #0xffff,%d4 /* d4 = screen height in pixels */
3503
3504 /*
3505 * Calculate number of bytes to move
3506 */
3507 lea %pc@(L(mac_rowbytes)),%a0
3508 movel %a0@,%d6
3509 movel %pc@(L(console_font)),%a0
3510 subl %a0@(FONT_DESC_HEIGHT),%d4 /* we're not scrolling the top row! */
3511 mulul %d4,%d6 /* scan line bytes x num scan lines */
3512 divul #32,%d6 /* we'll move 8 longs at a time */
3513 subq #1,%d6
3514
3515L(console_scroll_loop):
3516 movel %a2@+,%a1@+
3517 movel %a2@+,%a1@+
3518 movel %a2@+,%a1@+
3519 movel %a2@+,%a1@+
3520 movel %a2@+,%a1@+
3521 movel %a2@+,%a1@+
3522 movel %a2@+,%a1@+
3523 movel %a2@+,%a1@+
3524 dbra %d6,L(console_scroll_loop)
3525
3526 lea %pc@(L(mac_rowbytes)),%a0
3527 movel %a0@,%d6
3528 movel %pc@(L(console_font)),%a0
3529 mulul %a0@(FONT_DESC_HEIGHT),%d6 /* scan line bytes x font height */
3530 divul #32,%d6 /* we'll move 8 words at a time */
3531 subq #1,%d6
3532
3533 moveq #-1,%d0
3534L(console_scroll_clear_loop):
3535 movel %d0,%a1@+
3536 movel %d0,%a1@+
3537 movel %d0,%a1@+
3538 movel %d0,%a1@+
3539 movel %d0,%a1@+
3540 movel %d0,%a1@+
3541 movel %d0,%a1@+
3542 movel %d0,%a1@+
3543 dbra %d6,L(console_scroll_clear_loop)
3544
35451:
3546func_return console_scroll
3547
3548
3549func_start console_putc,%a0/%a1/%d0-%d7
3550
3551 is_not_mac(L(console_exit))
3552 tstl %pc@(L(console_font))
3553 jeq L(console_exit)
3554
3555 /* Output character in d7 on console.
3556 */
3557 movel ARG1,%d7
3558 cmpib #'\n',%d7
3559 jbne 1f
3560
3561 /* A little safe recursion is good for the soul */
3562 console_putc #'\r'
35631:
3564 lea %pc@(L(console_globals)),%a0
3565
3566 cmpib #10,%d7
3567 jne L(console_not_lf)
3568 movel %a0@(Lconsole_struct_cur_row),%d0
3569 addil #1,%d0
3570 movel %d0,%a0@(Lconsole_struct_cur_row)
3571 movel %a0@(Lconsole_struct_num_rows),%d1
3572 cmpl %d1,%d0
3573 jcs 1f
3574 subil #1,%d0
3575 movel %d0,%a0@(Lconsole_struct_cur_row)
3576 console_scroll
35771:
3578 jra L(console_exit)
3579
3580L(console_not_lf):
3581 cmpib #13,%d7
3582 jne L(console_not_cr)
3583 clrl %a0@(Lconsole_struct_cur_column)
3584 jra L(console_exit)
3585
3586L(console_not_cr):
3587 cmpib #1,%d7
3588 jne L(console_not_home)
3589 clrl %a0@(Lconsole_struct_cur_row)
3590 clrl %a0@(Lconsole_struct_cur_column)
3591 jra L(console_exit)
3592
3593/*
3594 * At this point we know that the %d7 character is going to be
3595 * rendered on the screen. Register usage is -
3596 * a0 = pointer to console globals
3597 * a1 = font data
3598 * d0 = cursor column
3599 * d1 = cursor row to draw the character
3600 * d7 = character number
3601 */
3602L(console_not_home):
3603 movel %a0@(Lconsole_struct_cur_column),%d0
3604 addql #1,%a0@(Lconsole_struct_cur_column)
3605 movel %a0@(Lconsole_struct_num_columns),%d1
3606 cmpl %d1,%d0
3607 jcs 1f
3608 console_putc #'\n' /* recursion is OK! */
36091:
3610 movel %a0@(Lconsole_struct_cur_row),%d1
3611
3612 /*
3613 * At this point we make a shift in register usage
3614 * a0 = address of pointer to font data (fbcon_font_desc)
3615 */
3616 movel %pc@(L(console_font)),%a0
3617 movel %pc@(L(console_font_data)),%a1 /* Load fbcon_font_desc.data into a1 */
3618 andl #0x000000ff,%d7
3619 /* ASSERT: a0 = contents of Lconsole_font */
3620 mulul %a0@(FONT_DESC_HEIGHT),%d7 /* d7 = index into font data */
3621 addl %d7,%a1 /* a1 = points to char image */
3622
3623 /*
3624 * At this point we make a shift in register usage
3625 * d0 = pixel coordinate, x
3626 * d1 = pixel coordinate, y
3627 * d2 = (bit 0) 1/0 for white/black (!) pixel on screen
3628 * d3 = font scan line data (8 pixels)
3629 * d6 = count down for the font's pixel width (8)
3630 * d7 = count down for the font's pixel count in height
3631 */
3632 /* ASSERT: a0 = contents of Lconsole_font */
3633 mulul %a0@(FONT_DESC_WIDTH),%d0
3634 mulul %a0@(FONT_DESC_HEIGHT),%d1
3635 movel %a0@(FONT_DESC_HEIGHT),%d7 /* Load fbcon_font_desc.height into d7 */
3636 subq #1,%d7
3637L(console_read_char_scanline):
3638 moveb %a1@+,%d3
3639
3640 /* ASSERT: a0 = contents of Lconsole_font */
3641 movel %a0@(FONT_DESC_WIDTH),%d6 /* Load fbcon_font_desc.width into d6 */
3642 subql #1,%d6
3643
3644L(console_do_font_scanline):
3645 lslb #1,%d3
3646 scsb %d2 /* convert 1 bit into a byte */
3647 console_plot_pixel %d0,%d1,%d2
3648 addq #1,%d0
3649 dbra %d6,L(console_do_font_scanline)
3650
3651 /* ASSERT: a0 = contents of Lconsole_font */
3652 subl %a0@(FONT_DESC_WIDTH),%d0
3653 addq #1,%d1
3654 dbra %d7,L(console_read_char_scanline)
3655
3656L(console_exit):
3657func_return console_putc
3658
3659 /*
3660 * Input:
3661 * d0 = x coordinate
3662 * d1 = y coordinate
3663 * d2 = (bit 0) 1/0 for white/black (!)
3664 * All registers are preserved
3665 */
3666func_start console_plot_pixel,%a0-%a1/%d0-%d4
3667
3668 movel %pc@(L(mac_videobase)),%a1
3669 movel %pc@(L(mac_videodepth)),%d3
3670 movel ARG1,%d0
3671 movel ARG2,%d1
3672 mulul %pc@(L(mac_rowbytes)),%d1
3673 movel ARG3,%d2
3674
3675 /*
3676 * Register usage:
3677 * d0 = x coord becomes byte offset into frame buffer
3678 * d1 = y coord
3679 * d2 = black or white (0/1)
3680 * d3 = video depth
3681 * d4 = temp of x (d0) for many bit depths
3682 */
3683L(test_1bit):
3684 cmpb #1,%d3
3685 jbne L(test_2bit)
3686 movel %d0,%d4 /* we need the low order 3 bits! */
3687 divul #8,%d0
3688 addal %d0,%a1
3689 addal %d1,%a1
3690 andb #7,%d4
3691 eorb #7,%d4 /* reverse the x-coordinate w/ screen-bit # */
3692 andb #1,%d2
3693 jbne L(white_1)
3694 bsetb %d4,%a1@
3695 jbra L(console_plot_pixel_exit)
3696L(white_1):
3697 bclrb %d4,%a1@
3698 jbra L(console_plot_pixel_exit)
3699
3700L(test_2bit):
3701 cmpb #2,%d3
3702 jbne L(test_4bit)
3703 movel %d0,%d4 /* we need the low order 2 bits! */
3704 divul #4,%d0
3705 addal %d0,%a1
3706 addal %d1,%a1
3707 andb #3,%d4
3708 eorb #3,%d4 /* reverse the x-coordinate w/ screen-bit # */
3709 lsll #1,%d4 /* ! */
3710 andb #1,%d2
3711 jbne L(white_2)
3712 bsetb %d4,%a1@
3713 addq #1,%d4
3714 bsetb %d4,%a1@
3715 jbra L(console_plot_pixel_exit)
3716L(white_2):
3717 bclrb %d4,%a1@
3718 addq #1,%d4
3719 bclrb %d4,%a1@
3720 jbra L(console_plot_pixel_exit)
3721
3722L(test_4bit):
3723 cmpb #4,%d3
3724 jbne L(test_8bit)
3725 movel %d0,%d4 /* we need the low order bit! */
3726 divul #2,%d0
3727 addal %d0,%a1
3728 addal %d1,%a1
3729 andb #1,%d4
3730 eorb #1,%d4
3731 lsll #2,%d4 /* ! */
3732 andb #1,%d2
3733 jbne L(white_4)
3734 bsetb %d4,%a1@
3735 addq #1,%d4
3736 bsetb %d4,%a1@
3737 addq #1,%d4
3738 bsetb %d4,%a1@
3739 addq #1,%d4
3740 bsetb %d4,%a1@
3741 jbra L(console_plot_pixel_exit)
3742L(white_4):
3743 bclrb %d4,%a1@
3744 addq #1,%d4
3745 bclrb %d4,%a1@
3746 addq #1,%d4
3747 bclrb %d4,%a1@
3748 addq #1,%d4
3749 bclrb %d4,%a1@
3750 jbra L(console_plot_pixel_exit)
3751
3752L(test_8bit):
3753 cmpb #8,%d3
3754 jbne L(test_16bit)
3755 addal %d0,%a1
3756 addal %d1,%a1
3757 andb #1,%d2
3758 jbne L(white_8)
3759 moveb #0xff,%a1@
3760 jbra L(console_plot_pixel_exit)
3761L(white_8):
3762 clrb %a1@
3763 jbra L(console_plot_pixel_exit)
3764
3765L(test_16bit):
3766 cmpb #16,%d3
3767 jbne L(console_plot_pixel_exit)
3768 addal %d0,%a1
3769 addal %d0,%a1
3770 addal %d1,%a1
3771 andb #1,%d2
3772 jbne L(white_16)
3773 clrw %a1@
3774 jbra L(console_plot_pixel_exit)
3775L(white_16):
3776 movew #0x0fff,%a1@
3777 jbra L(console_plot_pixel_exit)
3778
3779L(console_plot_pixel_exit):
3780func_return console_plot_pixel
3781#endif /* CONSOLE */
3782
3783#if 0
3784/*
3785 * This is some old code lying around. I don't believe
3786 * it's used or important anymore. My guess is it contributed
3787 * to getting to this point, but it's done for now.
3788 * It was still in the 2.1.77 head.S, so it's still here.
3789 * (And still not used!)
3790 */
3791L(showtest):
3792 moveml %a0/%d7,%sp@-
3793 puts "A="
3794 putn %a1
3795
3796 .long 0xf0119f15 | ptestr #5,%a1@,#7,%a0
3797
3798 puts "DA="
3799 putn %a0
3800
3801 puts "D="
3802 putn %a0@
3803
3804 puts "S="
3805 lea %pc@(L(mmu)),%a0
3806 .long 0xf0106200 | pmove %psr,%a0@
3807 clrl %d7
3808 movew %a0@,%d7
3809 putn %d7
3810
3811 putc '\n'
3812 moveml %sp@+,%a0/%d7
3813 rts
3814#endif /* 0 */
3815
3816__INITDATA
3817 .align 4
3818
3819#if defined(CONFIG_ATARI) || defined(CONFIG_AMIGA) || \
3820 defined(CONFIG_HP300) || defined(CONFIG_APOLLO)
3821L(custom):
3822L(iobase):
3823 .long 0
3824#endif
3825
3826#if defined(CONSOLE)
3827L(console_globals):
3828 .long 0 /* cursor column */
3829 .long 0 /* cursor row */
3830 .long 0 /* max num columns */
3831 .long 0 /* max num rows */
3832 .long 0 /* left edge */
3833 .long 0 /* mac putc */
3834L(console_font):
3835 .long 0 /* pointer to console font (struct font_desc) */
3836L(console_font_data):
3837 .long 0 /* pointer to console font data */
3838#endif /* CONSOLE */
3839
3840#if defined(MMU_PRINT)
3841L(mmu_print_data):
3842 .long 0 /* valid flag */
3843 .long 0 /* start logical */
3844 .long 0 /* next logical */
3845 .long 0 /* start physical */
3846 .long 0 /* next physical */
3847#endif /* MMU_PRINT */
3848
3849L(cputype):
3850 .long 0
3851L(mmu_cached_pointer_tables):
3852 .long 0
3853L(mmu_num_pointer_tables):
3854 .long 0
3855L(phys_kernel_start):
3856 .long 0
3857L(kernel_end):
3858 .long 0
3859L(memory_start):
3860 .long 0
3861L(kernel_pgdir_ptr):
3862 .long 0
3863L(temp_mmap_mem):
3864 .long 0
3865
3866#if defined (CONFIG_MVME147)
3867M147_SCC_CTRL_A = 0xfffe3002
3868M147_SCC_DATA_A = 0xfffe3003
3869#endif
3870
3871#if defined (CONFIG_MVME16x)
3872M162_SCC_CTRL_A = 0xfff45005
3873M167_CYCAR = 0xfff450ee
3874M167_CYIER = 0xfff45011
3875M167_CYLICR = 0xfff45026
3876M167_CYTEOIR = 0xfff45085
3877M167_CYTDR = 0xfff450f8
3878M167_PCSCCTICR = 0xfff4201e
3879M167_PCTPIACKR = 0xfff42025
3880#endif
3881
3882#if defined (CONFIG_BVME6000)
3883BVME_SCC_CTRL_A = 0xffb0000b
3884BVME_SCC_DATA_A = 0xffb0000f
3885#endif
3886
3887#if defined(CONFIG_MAC)
3888L(mac_booter_data):
3889 .long 0
3890L(mac_videobase):
3891 .long 0
3892L(mac_videodepth):
3893 .long 0
3894L(mac_dimensions):
3895 .long 0
3896L(mac_rowbytes):
3897 .long 0
3898#ifdef MAC_SERIAL_DEBUG
3899L(mac_sccbase):
3900 .long 0
3901#endif /* MAC_SERIAL_DEBUG */
3902#endif
3903
3904#if defined (CONFIG_APOLLO)
3905LSRB0 = 0x10412
3906LTHRB0 = 0x10416
3907LCPUCTRL = 0x10100
3908#endif
3909
3910#if defined(CONFIG_HP300)
3911DCADATA = 0x11
3912DCALSR = 0x1b
3913APCIDATA = 0x00
3914APCILSR = 0x14
3915L(uartbase):
3916 .long 0
3917L(uart_scode):
3918 .long -1
3919#endif
3920
3921__FINIT
3922 .data
3923 .align 4
3924
3925availmem:
3926 .long 0
3927m68k_pgtable_cachemode:
3928 .long 0
3929m68k_supervisor_cachemode:
3930 .long 0
3931#if defined(CONFIG_MVME16x)
3932mvme_bdid:
3933 .long 0,0,0,0,0,0,0,0
3934#endif
3935#if defined(CONFIG_Q40)
3936q40_mem_cptr:
3937 .long 0
3938L(q40_do_debug):
3939 .long 0
3940#endif
diff --git a/arch/m68k/kernel/ints.c b/arch/m68k/kernel/ints.c
new file mode 100644
index 000000000000..514d323ad536
--- /dev/null
+++ b/arch/m68k/kernel/ints.c
@@ -0,0 +1,281 @@
1/*
2 * linux/arch/m68k/kernel/ints.c -- Linux/m68k general interrupt handling code
3 *
4 * This file is subject to the terms and conditions of the GNU General Public
5 * License. See the file COPYING in the main directory of this archive
6 * for more details.
7 *
8 * 07/03/96: Timer initialization, and thus mach_sched_init(),
9 * removed from request_irq() and moved to init_time().
10 * We should therefore consider renaming our add_isr() and
11 * remove_isr() to request_irq() and free_irq()
12 * respectively, so they are compliant with the other
13 * architectures. /Jes
14 * 11/07/96: Changed all add_/remove_isr() to request_/free_irq() calls.
15 * Removed irq list support, if any machine needs an irq server
16 * it must implement this itself (as it's already done), instead
17 * only default handler are used with mach_default_handler.
18 * request_irq got some flags different from other architectures:
19 * - IRQ_FLG_REPLACE : Replace an existing handler (the default one
20 * can be replaced without this flag)
21 * - IRQ_FLG_LOCK : handler can't be replaced
22 * There are other machine depending flags, see there
23 * If you want to replace a default handler you should know what
24 * you're doing, since it might handle different other irq sources
25 * which must be served /Roman Zippel
26 */
27
28#include <linux/config.h>
29#include <linux/module.h>
30#include <linux/types.h>
31#include <linux/sched.h>
32#include <linux/kernel_stat.h>
33#include <linux/errno.h>
34#include <linux/init.h>
35
36#include <asm/setup.h>
37#include <asm/system.h>
38#include <asm/irq.h>
39#include <asm/traps.h>
40#include <asm/page.h>
41#include <asm/machdep.h>
42
43#ifdef CONFIG_Q40
44#include <asm/q40ints.h>
45#endif
46
47/* table for system interrupt handlers */
48static irq_handler_t irq_list[SYS_IRQS];
49
50static const char *default_names[SYS_IRQS] = {
51 [0] = "spurious int",
52 [1] = "int1 handler",
53 [2] = "int2 handler",
54 [3] = "int3 handler",
55 [4] = "int4 handler",
56 [5] = "int5 handler",
57 [6] = "int6 handler",
58 [7] = "int7 handler"
59};
60
61/* The number of spurious interrupts */
62volatile unsigned int num_spurious;
63
64#define NUM_IRQ_NODES 100
65static irq_node_t nodes[NUM_IRQ_NODES];
66
67static void dummy_enable_irq(unsigned int irq);
68static void dummy_disable_irq(unsigned int irq);
69static int dummy_request_irq(unsigned int irq,
70 irqreturn_t (*handler) (int, void *, struct pt_regs *),
71 unsigned long flags, const char *devname, void *dev_id);
72static void dummy_free_irq(unsigned int irq, void *dev_id);
73
74void (*enable_irq) (unsigned int) = dummy_enable_irq;
75void (*disable_irq) (unsigned int) = dummy_disable_irq;
76
77int (*mach_request_irq) (unsigned int, irqreturn_t (*)(int, void *, struct pt_regs *),
78 unsigned long, const char *, void *) = dummy_request_irq;
79void (*mach_free_irq) (unsigned int, void *) = dummy_free_irq;
80
81void init_irq_proc(void);
82
83/*
84 * void init_IRQ(void)
85 *
86 * Parameters: None
87 *
88 * Returns: Nothing
89 *
90 * This function should be called during kernel startup to initialize
91 * the IRQ handling routines.
92 */
93
94void __init init_IRQ(void)
95{
96 int i;
97
98 for (i = 0; i < SYS_IRQS; i++) {
99 if (mach_default_handler)
100 irq_list[i].handler = (*mach_default_handler)[i];
101 irq_list[i].flags = 0;
102 irq_list[i].dev_id = NULL;
103 irq_list[i].devname = default_names[i];
104 }
105
106 for (i = 0; i < NUM_IRQ_NODES; i++)
107 nodes[i].handler = NULL;
108
109 mach_init_IRQ ();
110}
111
112irq_node_t *new_irq_node(void)
113{
114 irq_node_t *node;
115 short i;
116
117 for (node = nodes, i = NUM_IRQ_NODES-1; i >= 0; node++, i--)
118 if (!node->handler)
119 return node;
120
121 printk ("new_irq_node: out of nodes\n");
122 return NULL;
123}
124
125/*
126 * We will keep these functions until I have convinced Linus to move
127 * the declaration of them from include/linux/sched.h to
128 * include/asm/irq.h.
129 */
130int request_irq(unsigned int irq,
131 irqreturn_t (*handler) (int, void *, struct pt_regs *),
132 unsigned long flags, const char *devname, void *dev_id)
133{
134 return mach_request_irq(irq, handler, flags, devname, dev_id);
135}
136
137EXPORT_SYMBOL(request_irq);
138
139void free_irq(unsigned int irq, void *dev_id)
140{
141 mach_free_irq(irq, dev_id);
142}
143
144EXPORT_SYMBOL(free_irq);
145
146int cpu_request_irq(unsigned int irq,
147 irqreturn_t (*handler)(int, void *, struct pt_regs *),
148 unsigned long flags, const char *devname, void *dev_id)
149{
150 if (irq < IRQ1 || irq > IRQ7) {
151 printk("%s: Incorrect IRQ %d from %s\n",
152 __FUNCTION__, irq, devname);
153 return -ENXIO;
154 }
155
156#if 0
157 if (!(irq_list[irq].flags & IRQ_FLG_STD)) {
158 if (irq_list[irq].flags & IRQ_FLG_LOCK) {
159 printk("%s: IRQ %d from %s is not replaceable\n",
160 __FUNCTION__, irq, irq_list[irq].devname);
161 return -EBUSY;
162 }
163 if (!(flags & IRQ_FLG_REPLACE)) {
164 printk("%s: %s can't replace IRQ %d from %s\n",
165 __FUNCTION__, devname, irq, irq_list[irq].devname);
166 return -EBUSY;
167 }
168 }
169#endif
170
171 irq_list[irq].handler = handler;
172 irq_list[irq].flags = flags;
173 irq_list[irq].dev_id = dev_id;
174 irq_list[irq].devname = devname;
175 return 0;
176}
177
178void cpu_free_irq(unsigned int irq, void *dev_id)
179{
180 if (irq < IRQ1 || irq > IRQ7) {
181 printk("%s: Incorrect IRQ %d\n", __FUNCTION__, irq);
182 return;
183 }
184
185 if (irq_list[irq].dev_id != dev_id)
186 printk("%s: Removing probably wrong IRQ %d from %s\n",
187 __FUNCTION__, irq, irq_list[irq].devname);
188
189 irq_list[irq].handler = (*mach_default_handler)[irq];
190 irq_list[irq].flags = 0;
191 irq_list[irq].dev_id = NULL;
192 irq_list[irq].devname = default_names[irq];
193}
194
195/*
196 * Do we need these probe functions on the m68k?
197 *
198 * ... may be useful with ISA devices
199 */
200unsigned long probe_irq_on (void)
201{
202#ifdef CONFIG_Q40
203 if (MACH_IS_Q40)
204 return q40_probe_irq_on();
205#endif
206 return 0;
207}
208
209EXPORT_SYMBOL(probe_irq_on);
210
211int probe_irq_off (unsigned long irqs)
212{
213#ifdef CONFIG_Q40
214 if (MACH_IS_Q40)
215 return q40_probe_irq_off(irqs);
216#endif
217 return 0;
218}
219
220EXPORT_SYMBOL(probe_irq_off);
221
222static void dummy_enable_irq(unsigned int irq)
223{
224 printk("calling uninitialized enable_irq()\n");
225}
226
227static void dummy_disable_irq(unsigned int irq)
228{
229 printk("calling uninitialized disable_irq()\n");
230}
231
232static int dummy_request_irq(unsigned int irq,
233 irqreturn_t (*handler) (int, void *, struct pt_regs *),
234 unsigned long flags, const char *devname, void *dev_id)
235{
236 printk("calling uninitialized request_irq()\n");
237 return 0;
238}
239
240static void dummy_free_irq(unsigned int irq, void *dev_id)
241{
242 printk("calling uninitialized disable_irq()\n");
243}
244
245asmlinkage void process_int(unsigned long vec, struct pt_regs *fp)
246{
247 if (vec >= VEC_INT1 && vec <= VEC_INT7 && !MACH_IS_BVME6000) {
248 vec -= VEC_SPUR;
249 kstat_cpu(0).irqs[vec]++;
250 irq_list[vec].handler(vec, irq_list[vec].dev_id, fp);
251 } else {
252 if (mach_process_int)
253 mach_process_int(vec, fp);
254 else
255 panic("Can't process interrupt vector %ld\n", vec);
256 return;
257 }
258}
259
260int show_interrupts(struct seq_file *p, void *v)
261{
262 int i = *(loff_t *) v;
263
264 /* autovector interrupts */
265 if (i < SYS_IRQS) {
266 if (mach_default_handler) {
267 seq_printf(p, "auto %2d: %10u ", i,
268 i ? kstat_cpu(0).irqs[i] : num_spurious);
269 seq_puts(p, " ");
270 seq_printf(p, "%s\n", irq_list[i].devname);
271 }
272 } else if (i == SYS_IRQS)
273 mach_get_irq_list(p, v);
274 return 0;
275}
276
277void init_irq_proc(void)
278{
279 /* Insert /proc/irq driver here */
280}
281
diff --git a/arch/m68k/kernel/m68k_ksyms.c b/arch/m68k/kernel/m68k_ksyms.c
new file mode 100644
index 000000000000..fe837e31afbf
--- /dev/null
+++ b/arch/m68k/kernel/m68k_ksyms.c
@@ -0,0 +1,88 @@
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
20asmlinkage long long __ashldi3 (long long, int);
21asmlinkage long long __ashrdi3 (long long, int);
22asmlinkage long long __lshrdi3 (long long, int);
23asmlinkage long long __muldi3 (long long, long long);
24extern char m68k_debug_device[];
25
26extern void dump_thread(struct pt_regs *, struct user *);
27
28/* platform dependent support */
29
30EXPORT_SYMBOL(m68k_machtype);
31EXPORT_SYMBOL(m68k_cputype);
32EXPORT_SYMBOL(m68k_is040or060);
33EXPORT_SYMBOL(m68k_realnum_memory);
34EXPORT_SYMBOL(m68k_memory);
35#ifndef CONFIG_SUN3
36EXPORT_SYMBOL(cache_push);
37EXPORT_SYMBOL(cache_clear);
38#ifndef CONFIG_SINGLE_MEMORY_CHUNK
39EXPORT_SYMBOL(mm_vtop);
40EXPORT_SYMBOL(mm_ptov);
41EXPORT_SYMBOL(mm_end_of_chunk);
42#else
43EXPORT_SYMBOL(m68k_memoffset);
44#endif /* !CONFIG_SINGLE_MEMORY_CHUNK */
45EXPORT_SYMBOL(__ioremap);
46EXPORT_SYMBOL(iounmap);
47EXPORT_SYMBOL(kernel_set_cachemode);
48#endif /* !CONFIG_SUN3 */
49EXPORT_SYMBOL(m68k_debug_device);
50EXPORT_SYMBOL(mach_hwclk);
51EXPORT_SYMBOL(mach_get_ss);
52EXPORT_SYMBOL(mach_get_rtc_pll);
53EXPORT_SYMBOL(mach_set_rtc_pll);
54#ifdef CONFIG_INPUT_M68K_BEEP_MODULE
55EXPORT_SYMBOL(mach_beep);
56#endif
57EXPORT_SYMBOL(dump_fpu);
58EXPORT_SYMBOL(dump_thread);
59EXPORT_SYMBOL(strnlen);
60EXPORT_SYMBOL(strrchr);
61EXPORT_SYMBOL(strstr);
62EXPORT_SYMBOL(strpbrk);
63EXPORT_SYMBOL(enable_irq);
64EXPORT_SYMBOL(disable_irq);
65EXPORT_SYMBOL(kernel_thread);
66#ifdef CONFIG_VME
67EXPORT_SYMBOL(vme_brdtype);
68#endif
69
70/* The following are special because they're not called
71 explicitly (the C compiler generates them). Fortunately,
72 their interface isn't gonna change any time soon now, so
73 it's OK to leave it out of version control. */
74EXPORT_SYMBOL(__ashldi3);
75EXPORT_SYMBOL(__ashrdi3);
76EXPORT_SYMBOL(__lshrdi3);
77EXPORT_SYMBOL(memcpy);
78EXPORT_SYMBOL(memset);
79EXPORT_SYMBOL(memcmp);
80EXPORT_SYMBOL(memscan);
81EXPORT_SYMBOL(__muldi3);
82
83EXPORT_SYMBOL(__down_failed);
84EXPORT_SYMBOL(__down_failed_interruptible);
85EXPORT_SYMBOL(__down_failed_trylock);
86EXPORT_SYMBOL(__up_wakeup);
87
88EXPORT_SYMBOL(get_wchan);
diff --git a/arch/m68k/kernel/module.c b/arch/m68k/kernel/module.c
new file mode 100644
index 000000000000..3b1a2ff61ddc
--- /dev/null
+++ b/arch/m68k/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/m68k/kernel/process.c b/arch/m68k/kernel/process.c
new file mode 100644
index 000000000000..93b043e2a435
--- /dev/null
+++ b/arch/m68k/kernel/process.c
@@ -0,0 +1,405 @@
1/*
2 * linux/arch/m68k/kernel/process.c
3 *
4 * Copyright (C) 1995 Hamish Macdonald
5 *
6 * 68060 fixes by Jesper Skov
7 */
8
9/*
10 * This file handles the architecture-dependent parts of process handling..
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/mm.h>
19#include <linux/smp.h>
20#include <linux/smp_lock.h>
21#include <linux/stddef.h>
22#include <linux/unistd.h>
23#include <linux/ptrace.h>
24#include <linux/slab.h>
25#include <linux/user.h>
26#include <linux/a.out.h>
27#include <linux/reboot.h>
28#include <linux/init_task.h>
29#include <linux/mqueue.h>
30
31#include <asm/uaccess.h>
32#include <asm/system.h>
33#include <asm/traps.h>
34#include <asm/machdep.h>
35#include <asm/setup.h>
36#include <asm/pgtable.h>
37
38/*
39 * Initial task/thread structure. Make this a per-architecture thing,
40 * because different architectures tend to have different
41 * alignment requirements and potentially different initial
42 * setup.
43 */
44static struct fs_struct init_fs = INIT_FS;
45static struct files_struct init_files = INIT_FILES;
46static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
47static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
48struct mm_struct init_mm = INIT_MM(init_mm);
49
50EXPORT_SYMBOL(init_mm);
51
52union thread_union init_thread_union
53__attribute__((section(".data.init_task"), aligned(THREAD_SIZE)))
54 = { INIT_THREAD_INFO(init_task) };
55
56/* initial task structure */
57struct task_struct init_task = INIT_TASK(init_task);
58
59EXPORT_SYMBOL(init_task);
60
61asmlinkage void ret_from_fork(void);
62
63
64/*
65 * Return saved PC from a blocked thread
66 */
67unsigned long thread_saved_pc(struct task_struct *tsk)
68{
69 struct switch_stack *sw = (struct switch_stack *)tsk->thread.ksp;
70 /* Check whether the thread is blocked in resume() */
71 if (in_sched_functions(sw->retpc))
72 return ((unsigned long *)sw->a6)[1];
73 else
74 return sw->retpc;
75}
76
77/*
78 * The idle loop on an m68k..
79 */
80void default_idle(void)
81{
82 if (!need_resched())
83#if defined(MACH_ATARI_ONLY) && !defined(CONFIG_HADES)
84 /* block out HSYNC on the atari (falcon) */
85 __asm__("stop #0x2200" : : : "cc");
86#else
87 __asm__("stop #0x2000" : : : "cc");
88#endif
89}
90
91void (*idle)(void) = default_idle;
92
93/*
94 * The idle thread. There's no useful work to be
95 * done, so just try to conserve power and have a
96 * low exit latency (ie sit in a loop waiting for
97 * somebody to say that they'd like to reschedule)
98 */
99void cpu_idle(void)
100{
101 /* endless idle loop with no priority at all */
102 while (1) {
103 while (!need_resched())
104 idle();
105 schedule();
106 }
107}
108
109void machine_restart(char * __unused)
110{
111 if (mach_reset)
112 mach_reset();
113 for (;;);
114}
115
116EXPORT_SYMBOL(machine_restart);
117
118void machine_halt(void)
119{
120 if (mach_halt)
121 mach_halt();
122 for (;;);
123}
124
125EXPORT_SYMBOL(machine_halt);
126
127void machine_power_off(void)
128{
129 if (mach_power_off)
130 mach_power_off();
131 for (;;);
132}
133
134EXPORT_SYMBOL(machine_power_off);
135
136void show_regs(struct pt_regs * regs)
137{
138 printk("\n");
139 printk("Format %02x Vector: %04x PC: %08lx Status: %04x %s\n",
140 regs->format, regs->vector, regs->pc, regs->sr, print_tainted());
141 printk("ORIG_D0: %08lx D0: %08lx A2: %08lx A1: %08lx\n",
142 regs->orig_d0, regs->d0, regs->a2, regs->a1);
143 printk("A0: %08lx D5: %08lx D4: %08lx\n",
144 regs->a0, regs->d5, regs->d4);
145 printk("D3: %08lx D2: %08lx D1: %08lx\n",
146 regs->d3, regs->d2, regs->d1);
147 if (!(regs->sr & PS_S))
148 printk("USP: %08lx\n", rdusp());
149}
150
151/*
152 * Create a kernel thread
153 */
154int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
155{
156 int pid;
157 mm_segment_t fs;
158
159 fs = get_fs();
160 set_fs (KERNEL_DS);
161
162 {
163 register long retval __asm__ ("d0");
164 register long clone_arg __asm__ ("d1") = flags | CLONE_VM | CLONE_UNTRACED;
165
166 retval = __NR_clone;
167 __asm__ __volatile__
168 ("clrl %%d2\n\t"
169 "trap #0\n\t" /* Linux/m68k system call */
170 "tstl %0\n\t" /* child or parent */
171 "jne 1f\n\t" /* parent - jump */
172 "lea %%sp@(%c7),%6\n\t" /* reload current */
173 "movel %6@,%6\n\t"
174 "movel %3,%%sp@-\n\t" /* push argument */
175 "jsr %4@\n\t" /* call fn */
176 "movel %0,%%d1\n\t" /* pass exit value */
177 "movel %2,%%d0\n\t" /* exit */
178 "trap #0\n"
179 "1:"
180 : "+d" (retval)
181 : "i" (__NR_clone), "i" (__NR_exit),
182 "r" (arg), "a" (fn), "d" (clone_arg), "r" (current),
183 "i" (-THREAD_SIZE)
184 : "d2");
185
186 pid = retval;
187 }
188
189 set_fs (fs);
190 return pid;
191}
192
193void flush_thread(void)
194{
195 unsigned long zero = 0;
196 set_fs(USER_DS);
197 current->thread.fs = __USER_DS;
198 if (!FPU_IS_EMU)
199 asm volatile (".chip 68k/68881\n\t"
200 "frestore %0@\n\t"
201 ".chip 68k" : : "a" (&zero));
202}
203
204/*
205 * "m68k_fork()".. By the time we get here, the
206 * non-volatile registers have also been saved on the
207 * stack. We do some ugly pointer stuff here.. (see
208 * also copy_thread)
209 */
210
211asmlinkage int m68k_fork(struct pt_regs *regs)
212{
213 return do_fork(SIGCHLD, rdusp(), regs, 0, NULL, NULL);
214}
215
216asmlinkage int m68k_vfork(struct pt_regs *regs)
217{
218 return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, rdusp(), regs, 0,
219 NULL, NULL);
220}
221
222asmlinkage int m68k_clone(struct pt_regs *regs)
223{
224 unsigned long clone_flags;
225 unsigned long newsp;
226 int *parent_tidptr, *child_tidptr;
227
228 /* syscall2 puts clone_flags in d1 and usp in d2 */
229 clone_flags = regs->d1;
230 newsp = regs->d2;
231 parent_tidptr = (int *)regs->d3;
232 child_tidptr = (int *)regs->d4;
233 if (!newsp)
234 newsp = rdusp();
235 return do_fork(clone_flags, newsp, regs, 0,
236 parent_tidptr, child_tidptr);
237}
238
239int copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
240 unsigned long unused,
241 struct task_struct * p, struct pt_regs * regs)
242{
243 struct pt_regs * childregs;
244 struct switch_stack * childstack, *stack;
245 unsigned long stack_offset, *retp;
246
247 stack_offset = THREAD_SIZE - sizeof(struct pt_regs);
248 childregs = (struct pt_regs *) ((unsigned long) (p->thread_info) + stack_offset);
249
250 *childregs = *regs;
251 childregs->d0 = 0;
252
253 retp = ((unsigned long *) regs);
254 stack = ((struct switch_stack *) retp) - 1;
255
256 childstack = ((struct switch_stack *) childregs) - 1;
257 *childstack = *stack;
258 childstack->retpc = (unsigned long)ret_from_fork;
259
260 p->thread.usp = usp;
261 p->thread.ksp = (unsigned long)childstack;
262 /*
263 * Must save the current SFC/DFC value, NOT the value when
264 * the parent was last descheduled - RGH 10-08-96
265 */
266 p->thread.fs = get_fs().seg;
267
268 if (!FPU_IS_EMU) {
269 /* Copy the current fpu state */
270 asm volatile ("fsave %0" : : "m" (p->thread.fpstate[0]) : "memory");
271
272 if (!CPU_IS_060 ? p->thread.fpstate[0] : p->thread.fpstate[2])
273 asm volatile ("fmovemx %/fp0-%/fp7,%0\n\t"
274 "fmoveml %/fpiar/%/fpcr/%/fpsr,%1"
275 : : "m" (p->thread.fp[0]), "m" (p->thread.fpcntl[0])
276 : "memory");
277 /* Restore the state in case the fpu was busy */
278 asm volatile ("frestore %0" : : "m" (p->thread.fpstate[0]));
279 }
280
281 return 0;
282}
283
284/* Fill in the fpu structure for a core dump. */
285
286int dump_fpu (struct pt_regs *regs, struct user_m68kfp_struct *fpu)
287{
288 char fpustate[216];
289
290 if (FPU_IS_EMU) {
291 int i;
292
293 memcpy(fpu->fpcntl, current->thread.fpcntl, 12);
294 memcpy(fpu->fpregs, current->thread.fp, 96);
295 /* Convert internal fpu reg representation
296 * into long double format
297 */
298 for (i = 0; i < 24; i += 3)
299 fpu->fpregs[i] = ((fpu->fpregs[i] & 0xffff0000) << 15) |
300 ((fpu->fpregs[i] & 0x0000ffff) << 16);
301 return 1;
302 }
303
304 /* First dump the fpu context to avoid protocol violation. */
305 asm volatile ("fsave %0" :: "m" (fpustate[0]) : "memory");
306 if (!CPU_IS_060 ? !fpustate[0] : !fpustate[2])
307 return 0;
308
309 asm volatile ("fmovem %/fpiar/%/fpcr/%/fpsr,%0"
310 :: "m" (fpu->fpcntl[0])
311 : "memory");
312 asm volatile ("fmovemx %/fp0-%/fp7,%0"
313 :: "m" (fpu->fpregs[0])
314 : "memory");
315 return 1;
316}
317
318/*
319 * fill in the user structure for a core dump..
320 */
321void dump_thread(struct pt_regs * regs, struct user * dump)
322{
323 struct switch_stack *sw;
324
325/* changed the size calculations - should hopefully work better. lbt */
326 dump->magic = CMAGIC;
327 dump->start_code = 0;
328 dump->start_stack = rdusp() & ~(PAGE_SIZE - 1);
329 dump->u_tsize = ((unsigned long) current->mm->end_code) >> PAGE_SHIFT;
330 dump->u_dsize = ((unsigned long) (current->mm->brk +
331 (PAGE_SIZE-1))) >> PAGE_SHIFT;
332 dump->u_dsize -= dump->u_tsize;
333 dump->u_ssize = 0;
334
335 if (dump->start_stack < TASK_SIZE)
336 dump->u_ssize = ((unsigned long) (TASK_SIZE - dump->start_stack)) >> PAGE_SHIFT;
337
338 dump->u_ar0 = (struct user_regs_struct *)((int)&dump->regs - (int)dump);
339 sw = ((struct switch_stack *)regs) - 1;
340 dump->regs.d1 = regs->d1;
341 dump->regs.d2 = regs->d2;
342 dump->regs.d3 = regs->d3;
343 dump->regs.d4 = regs->d4;
344 dump->regs.d5 = regs->d5;
345 dump->regs.d6 = sw->d6;
346 dump->regs.d7 = sw->d7;
347 dump->regs.a0 = regs->a0;
348 dump->regs.a1 = regs->a1;
349 dump->regs.a2 = regs->a2;
350 dump->regs.a3 = sw->a3;
351 dump->regs.a4 = sw->a4;
352 dump->regs.a5 = sw->a5;
353 dump->regs.a6 = sw->a6;
354 dump->regs.d0 = regs->d0;
355 dump->regs.orig_d0 = regs->orig_d0;
356 dump->regs.stkadj = regs->stkadj;
357 dump->regs.sr = regs->sr;
358 dump->regs.pc = regs->pc;
359 dump->regs.fmtvec = (regs->format << 12) | regs->vector;
360 /* dump floating point stuff */
361 dump->u_fpvalid = dump_fpu (regs, &dump->m68kfp);
362}
363
364/*
365 * sys_execve() executes a new program.
366 */
367asmlinkage int sys_execve(char *name, char **argv, char **envp)
368{
369 int error;
370 char * filename;
371 struct pt_regs *regs = (struct pt_regs *) &name;
372
373 lock_kernel();
374 filename = getname(name);
375 error = PTR_ERR(filename);
376 if (IS_ERR(filename))
377 goto out;
378 error = do_execve(filename, argv, envp, regs);
379 putname(filename);
380out:
381 unlock_kernel();
382 return error;
383}
384
385unsigned long get_wchan(struct task_struct *p)
386{
387 unsigned long fp, pc;
388 unsigned long stack_page;
389 int count = 0;
390 if (!p || p == current || p->state == TASK_RUNNING)
391 return 0;
392
393 stack_page = (unsigned long)(p->thread_info);
394 fp = ((struct switch_stack *)p->thread.ksp)->a6;
395 do {
396 if (fp < stack_page+sizeof(struct thread_info) ||
397 fp >= 8184+stack_page)
398 return 0;
399 pc = ((unsigned long *)fp)[1];
400 if (!in_sched_functions(pc))
401 return pc;
402 fp = *(unsigned long *) fp;
403 } while (count++ < 16);
404 return 0;
405}
diff --git a/arch/m68k/kernel/ptrace.c b/arch/m68k/kernel/ptrace.c
new file mode 100644
index 000000000000..0beb53333ba3
--- /dev/null
+++ b/arch/m68k/kernel/ptrace.c
@@ -0,0 +1,393 @@
1/*
2 * linux/arch/m68k/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 [0] = PT_REG(d1),
50 [1] = PT_REG(d2),
51 [2] = PT_REG(d3),
52 [3] = PT_REG(d4),
53 [4] = PT_REG(d5),
54 [5] = SW_REG(d6),
55 [6] = SW_REG(d7),
56 [7] = PT_REG(a0),
57 [8] = PT_REG(a1),
58 [9] = PT_REG(a2),
59 [10] = SW_REG(a3),
60 [11] = SW_REG(a4),
61 [12] = SW_REG(a5),
62 [13] = SW_REG(a6),
63 [14] = PT_REG(d0),
64 [15] = -1,
65 [16] = PT_REG(orig_d0),
66 [17] = PT_REG(sr),
67 [18] = PT_REG(pc),
68};
69
70/*
71 * Get contents of register REGNO in task TASK.
72 */
73static inline long get_reg(struct task_struct *task, int regno)
74{
75 unsigned long *addr;
76
77 if (regno == PT_USP)
78 addr = &task->thread.usp;
79 else if (regno < sizeof(regoff)/sizeof(regoff[0]))
80 addr = (unsigned long *)(task->thread.esp0 + regoff[regno]);
81 else
82 return 0;
83 return *addr;
84}
85
86/*
87 * Write contents of register REGNO in task TASK.
88 */
89static inline int put_reg(struct task_struct *task, int regno,
90 unsigned long data)
91{
92 unsigned long *addr;
93
94 if (regno == PT_USP)
95 addr = &task->thread.usp;
96 else if (regno < sizeof(regoff)/sizeof(regoff[0]))
97 addr = (unsigned long *) (task->thread.esp0 + regoff[regno]);
98 else
99 return -1;
100 *addr = data;
101 return 0;
102}
103
104/*
105 * Called by kernel/ptrace.c when detaching..
106 *
107 * Make sure the single step bit is not set.
108 */
109void ptrace_disable(struct task_struct *child)
110{
111 unsigned long tmp;
112 /* make sure the single step bit is not set. */
113 tmp = get_reg(child, PT_SR) & ~(TRACE_BITS << 16);
114 put_reg(child, PT_SR, tmp);
115 child->thread.work.delayed_trace = 0;
116 child->thread.work.syscall_trace = 0;
117}
118
119asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
120{
121 struct task_struct *child;
122 int ret;
123
124 lock_kernel();
125 ret = -EPERM;
126 if (request == PTRACE_TRACEME) {
127 /* are we already being traced? */
128 if (current->ptrace & PT_PTRACED)
129 goto out;
130 /* set the ptrace bit in the process flags. */
131 current->ptrace |= PT_PTRACED;
132 ret = 0;
133 goto out;
134 }
135 ret = -ESRCH;
136 read_lock(&tasklist_lock);
137 child = find_task_by_pid(pid);
138 if (child)
139 get_task_struct(child);
140 read_unlock(&tasklist_lock);
141 if (!child)
142 goto out;
143
144 ret = -EPERM;
145 if (pid == 1) /* you may not mess with init */
146 goto out_tsk;
147
148 if (request == PTRACE_ATTACH) {
149 ret = ptrace_attach(child);
150 goto out_tsk;
151 }
152
153 ret = ptrace_check_attach(child, request == PTRACE_KILL);
154 if (ret < 0)
155 goto out_tsk;
156
157 switch (request) {
158 /* when I and D space are separate, these will need to be fixed. */
159 case PTRACE_PEEKTEXT: /* read word at location addr. */
160 case PTRACE_PEEKDATA: {
161 unsigned long tmp;
162 int copied;
163
164 copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0);
165 ret = -EIO;
166 if (copied != sizeof(tmp))
167 break;
168 ret = put_user(tmp,(unsigned long *) data);
169 break;
170 }
171
172 /* read the word at location addr in the USER area. */
173 case PTRACE_PEEKUSR: {
174 unsigned long tmp;
175
176 ret = -EIO;
177 if ((addr & 3) || addr < 0 ||
178 addr > sizeof(struct user) - 3)
179 break;
180
181 tmp = 0; /* Default return condition */
182 addr = addr >> 2; /* temporary hack. */
183 ret = -EIO;
184 if (addr < 19) {
185 tmp = get_reg(child, addr);
186 if (addr == PT_SR)
187 tmp >>= 16;
188 } else if (addr >= 21 && addr < 49) {
189 tmp = child->thread.fp[addr - 21];
190#ifdef CONFIG_M68KFPU_EMU
191 /* Convert internal fpu reg representation
192 * into long double format
193 */
194 if (FPU_IS_EMU && (addr < 45) && !(addr % 3))
195 tmp = ((tmp & 0xffff0000) << 15) |
196 ((tmp & 0x0000ffff) << 16);
197#endif
198 } else
199 break;
200 ret = put_user(tmp,(unsigned long *) data);
201 break;
202 }
203
204 /* when I and D space are separate, this will have to be fixed. */
205 case PTRACE_POKETEXT: /* write the word at location addr. */
206 case PTRACE_POKEDATA:
207 ret = 0;
208 if (access_process_vm(child, addr, &data, sizeof(data), 1) == sizeof(data))
209 break;
210 ret = -EIO;
211 break;
212
213 case PTRACE_POKEUSR: /* write the word at location addr in the USER area */
214 ret = -EIO;
215 if ((addr & 3) || addr < 0 ||
216 addr > sizeof(struct user) - 3)
217 break;
218
219 addr = addr >> 2; /* temporary hack. */
220
221 if (addr == PT_SR) {
222 data &= SR_MASK;
223 data <<= 16;
224 data |= get_reg(child, PT_SR) & ~(SR_MASK << 16);
225 }
226 if (addr < 19) {
227 if (put_reg(child, addr, data))
228 break;
229 ret = 0;
230 break;
231 }
232 if (addr >= 21 && addr < 48)
233 {
234#ifdef CONFIG_M68KFPU_EMU
235 /* Convert long double format
236 * into internal fpu reg representation
237 */
238 if (FPU_IS_EMU && (addr < 45) && !(addr % 3)) {
239 data = (unsigned long)data << 15;
240 data = (data & 0xffff0000) |
241 ((data & 0x0000ffff) >> 1);
242 }
243#endif
244 child->thread.fp[addr - 21] = data;
245 ret = 0;
246 }
247 break;
248
249 case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */
250 case PTRACE_CONT: { /* restart after signal. */
251 long tmp;
252
253 ret = -EIO;
254 if ((unsigned long) data > _NSIG)
255 break;
256 if (request == PTRACE_SYSCALL) {
257 child->thread.work.syscall_trace = ~0;
258 } else {
259 child->thread.work.syscall_trace = 0;
260 }
261 child->exit_code = data;
262 /* make sure the single step bit is not set. */
263 tmp = get_reg(child, PT_SR) & ~(TRACE_BITS << 16);
264 put_reg(child, PT_SR, tmp);
265 child->thread.work.delayed_trace = 0;
266 wake_up_process(child);
267 ret = 0;
268 break;
269 }
270
271/*
272 * make the child exit. Best I can do is send it a sigkill.
273 * perhaps it should be put in the status that it wants to
274 * exit.
275 */
276 case PTRACE_KILL: {
277 long tmp;
278
279 ret = 0;
280 if (child->exit_state == EXIT_ZOMBIE) /* already dead */
281 break;
282 child->exit_code = SIGKILL;
283 /* make sure the single step bit is not set. */
284 tmp = get_reg(child, PT_SR) & ~(TRACE_BITS << 16);
285 put_reg(child, PT_SR, tmp);
286 child->thread.work.delayed_trace = 0;
287 wake_up_process(child);
288 break;
289 }
290
291 case PTRACE_SINGLESTEP: { /* set the trap flag. */
292 long tmp;
293
294 ret = -EIO;
295 if ((unsigned long) data > _NSIG)
296 break;
297 child->thread.work.syscall_trace = 0;
298 tmp = get_reg(child, PT_SR) | (TRACE_BITS << 16);
299 put_reg(child, PT_SR, tmp);
300 child->thread.work.delayed_trace = 1;
301
302 child->exit_code = data;
303 /* give it a chance to run. */
304 wake_up_process(child);
305 ret = 0;
306 break;
307 }
308
309 case PTRACE_DETACH: /* detach a process that was attached. */
310 ret = ptrace_detach(child, data);
311 break;
312
313 case PTRACE_GETREGS: { /* Get all gp regs from the child. */
314 int i;
315 unsigned long tmp;
316 for (i = 0; i < 19; i++) {
317 tmp = get_reg(child, i);
318 if (i == PT_SR)
319 tmp >>= 16;
320 if (put_user(tmp, (unsigned long *) data)) {
321 ret = -EFAULT;
322 break;
323 }
324 data += sizeof(long);
325 }
326 ret = 0;
327 break;
328 }
329
330 case PTRACE_SETREGS: { /* Set all gp regs in the child. */
331 int i;
332 unsigned long tmp;
333 for (i = 0; i < 19; i++) {
334 if (get_user(tmp, (unsigned long *) data)) {
335 ret = -EFAULT;
336 break;
337 }
338 if (i == PT_SR) {
339 tmp &= SR_MASK;
340 tmp <<= 16;
341 tmp |= get_reg(child, PT_SR) & ~(SR_MASK << 16);
342 }
343 put_reg(child, i, tmp);
344 data += sizeof(long);
345 }
346 ret = 0;
347 break;
348 }
349
350 case PTRACE_GETFPREGS: { /* Get the child FPU state. */
351 ret = 0;
352 if (copy_to_user((void *)data, &child->thread.fp,
353 sizeof(struct user_m68kfp_struct)))
354 ret = -EFAULT;
355 break;
356 }
357
358 case PTRACE_SETFPREGS: { /* Set the child FPU state. */
359 ret = 0;
360 if (copy_from_user(&child->thread.fp, (void *)data,
361 sizeof(struct user_m68kfp_struct)))
362 ret = -EFAULT;
363 break;
364 }
365
366 default:
367 ret = ptrace_request(child, request, addr, data);
368 break;
369 }
370out_tsk:
371 put_task_struct(child);
372out:
373 unlock_kernel();
374 return ret;
375}
376
377asmlinkage void syscall_trace(void)
378{
379 if (!current->thread.work.delayed_trace &&
380 !current->thread.work.syscall_trace)
381 return;
382 ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
383 ? 0x80 : 0));
384 /*
385 * this isn't the same as continuing with a signal, but it will do
386 * for normal use. strace only continues with a signal if the
387 * stopping signal is not SIGTRAP. -brl
388 */
389 if (current->exit_code) {
390 send_sig(current->exit_code, current, 1);
391 current->exit_code = 0;
392 }
393}
diff --git a/arch/m68k/kernel/semaphore.c b/arch/m68k/kernel/semaphore.c
new file mode 100644
index 000000000000..1ebb79baaa8c
--- /dev/null
+++ b/arch/m68k/kernel/semaphore.c
@@ -0,0 +1,133 @@
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/init.h>
9#include <asm/semaphore-helper.h>
10
11#ifndef CONFIG_RMW_INSNS
12spinlock_t semaphore_wake_lock;
13#endif
14
15/*
16 * Semaphores are implemented using a two-way counter:
17 * The "count" variable is decremented for each process
18 * that tries to sleep, while the "waking" variable is
19 * incremented when the "up()" code goes to wake up waiting
20 * processes.
21 *
22 * Notably, the inline "up()" and "down()" functions can
23 * efficiently test if they need to do any extra work (up
24 * needs to do something only if count was negative before
25 * the increment operation.
26 *
27 * waking_non_zero() (from asm/semaphore.h) must execute
28 * atomically.
29 *
30 * When __up() is called, the count was negative before
31 * incrementing it, and we need to wake up somebody.
32 *
33 * This routine adds one to the count of processes that need to
34 * wake up and exit. ALL waiting processes actually wake up but
35 * only the one that gets to the "waking" field first will gate
36 * through and acquire the semaphore. The others will go back
37 * to sleep.
38 *
39 * Note that these functions are only called when there is
40 * contention on the lock, and as such all this is the
41 * "non-critical" part of the whole semaphore business. The
42 * critical part is the inline stuff in <asm/semaphore.h>
43 * where we want to avoid any extra jumps and calls.
44 */
45void __up(struct semaphore *sem)
46{
47 wake_one_more(sem);
48 wake_up(&sem->wait);
49}
50
51/*
52 * Perform the "down" function. Return zero for semaphore acquired,
53 * return negative for signalled out of the function.
54 *
55 * If called from __down, the return is ignored and the wait loop is
56 * not interruptible. This means that a task waiting on a semaphore
57 * using "down()" cannot be killed until someone does an "up()" on
58 * the semaphore.
59 *
60 * If called from __down_interruptible, the return value gets checked
61 * upon return. If the return value is negative then the task continues
62 * with the negative value in the return register (it can be tested by
63 * the caller).
64 *
65 * Either form may be used in conjunction with "up()".
66 *
67 */
68
69
70#define DOWN_HEAD(task_state) \
71 \
72 \
73 current->state = (task_state); \
74 add_wait_queue(&sem->wait, &wait); \
75 \
76 /* \
77 * Ok, we're set up. sem->count is known to be less than zero \
78 * so we must wait. \
79 * \
80 * We can let go the lock for purposes of waiting. \
81 * We re-acquire it after awaking so as to protect \
82 * all semaphore operations. \
83 * \
84 * If "up()" is called before we call waking_non_zero() then \
85 * we will catch it right away. If it is called later then \
86 * we will have to go through a wakeup cycle to catch it. \
87 * \
88 * Multiple waiters contend for the semaphore lock to see \
89 * who gets to gate through and who has to wait some more. \
90 */ \
91 for (;;) {
92
93#define DOWN_TAIL(task_state) \
94 current->state = (task_state); \
95 } \
96 current->state = TASK_RUNNING; \
97 remove_wait_queue(&sem->wait, &wait);
98
99void __sched __down(struct semaphore * sem)
100{
101 DECLARE_WAITQUEUE(wait, current);
102
103 DOWN_HEAD(TASK_UNINTERRUPTIBLE)
104 if (waking_non_zero(sem))
105 break;
106 schedule();
107 DOWN_TAIL(TASK_UNINTERRUPTIBLE)
108}
109
110int __sched __down_interruptible(struct semaphore * sem)
111{
112 DECLARE_WAITQUEUE(wait, current);
113 int ret = 0;
114
115 DOWN_HEAD(TASK_INTERRUPTIBLE)
116
117 ret = waking_non_zero_interruptible(sem, current);
118 if (ret)
119 {
120 if (ret == 1)
121 /* ret != 0 only if we get interrupted -arca */
122 ret = 0;
123 break;
124 }
125 schedule();
126 DOWN_TAIL(TASK_INTERRUPTIBLE)
127 return ret;
128}
129
130int __down_trylock(struct semaphore * sem)
131{
132 return waking_non_zero_trylock(sem);
133}
diff --git a/arch/m68k/kernel/setup.c b/arch/m68k/kernel/setup.c
new file mode 100644
index 000000000000..d6ca99242e5a
--- /dev/null
+++ b/arch/m68k/kernel/setup.c
@@ -0,0 +1,545 @@
1/*
2 * linux/arch/m68k/kernel/setup.c
3 *
4 * Copyright (C) 1995 Hamish Macdonald
5 */
6
7/*
8 * This file handles the architecture-dependent parts of system setup
9 */
10
11#include <linux/config.h>
12#include <linux/kernel.h>
13#include <linux/mm.h>
14#include <linux/sched.h>
15#include <linux/delay.h>
16#include <linux/interrupt.h>
17#include <linux/fs.h>
18#include <linux/console.h>
19#include <linux/genhd.h>
20#include <linux/errno.h>
21#include <linux/string.h>
22#include <linux/init.h>
23#include <linux/bootmem.h>
24#include <linux/seq_file.h>
25#include <linux/module.h>
26#include <linux/initrd.h>
27
28#include <asm/bootinfo.h>
29#include <asm/setup.h>
30#include <asm/irq.h>
31#include <asm/io.h>
32#include <asm/machdep.h>
33#ifdef CONFIG_AMIGA
34#include <asm/amigahw.h>
35#endif
36#ifdef CONFIG_ATARI
37#include <asm/atarihw.h>
38#include <asm/atari_stram.h>
39#endif
40#ifdef CONFIG_SUN3X
41#include <asm/dvma.h>
42#endif
43
44unsigned long m68k_machtype;
45unsigned long m68k_cputype;
46unsigned long m68k_fputype;
47unsigned long m68k_mmutype;
48#ifdef CONFIG_VME
49unsigned long vme_brdtype;
50#endif
51
52int m68k_is040or060;
53
54extern int end;
55extern unsigned long availmem;
56
57int m68k_num_memory;
58int m68k_realnum_memory;
59unsigned long m68k_memoffset;
60struct mem_info m68k_memory[NUM_MEMINFO];
61
62static struct mem_info m68k_ramdisk;
63
64static char m68k_command_line[CL_SIZE];
65
66char m68k_debug_device[6] = "";
67
68void (*mach_sched_init) (irqreturn_t (*handler)(int, void *, struct pt_regs *)) __initdata = NULL;
69/* machine dependent irq functions */
70void (*mach_init_IRQ) (void) __initdata = NULL;
71irqreturn_t (*(*mach_default_handler)[]) (int, void *, struct pt_regs *);
72void (*mach_get_model) (char *model);
73int (*mach_get_hardware_list) (char *buffer);
74int (*mach_get_irq_list) (struct seq_file *, void *);
75irqreturn_t (*mach_process_int) (int, struct pt_regs *);
76/* machine dependent timer functions */
77unsigned long (*mach_gettimeoffset) (void);
78int (*mach_hwclk) (int, struct rtc_time*);
79int (*mach_set_clock_mmss) (unsigned long);
80unsigned int (*mach_get_ss)(void);
81int (*mach_get_rtc_pll)(struct rtc_pll_info *);
82int (*mach_set_rtc_pll)(struct rtc_pll_info *);
83void (*mach_reset)( void );
84void (*mach_halt)( void );
85void (*mach_power_off)( void );
86long mach_max_dma_address = 0x00ffffff; /* default set to the lower 16MB */
87#if defined(CONFIG_AMIGA_FLOPPY) || defined(CONFIG_ATARI_FLOPPY)
88void (*mach_floppy_setup) (char *, int *) __initdata = NULL;
89#endif
90#ifdef CONFIG_HEARTBEAT
91void (*mach_heartbeat) (int);
92EXPORT_SYMBOL(mach_heartbeat);
93#endif
94#ifdef CONFIG_M68K_L2_CACHE
95void (*mach_l2_flush) (int);
96#endif
97#if defined(CONFIG_INPUT_M68K_BEEP) || defined(CONFIG_INPUT_M68K_BEEP_MODULE)
98void (*mach_beep)(unsigned int, unsigned int);
99#endif
100#if defined(CONFIG_ISA) && defined(MULTI_ISA)
101int isa_type;
102int isa_sex;
103#endif
104
105extern int amiga_parse_bootinfo(const struct bi_record *);
106extern int atari_parse_bootinfo(const struct bi_record *);
107extern int mac_parse_bootinfo(const struct bi_record *);
108extern int q40_parse_bootinfo(const struct bi_record *);
109extern int bvme6000_parse_bootinfo(const struct bi_record *);
110extern int mvme16x_parse_bootinfo(const struct bi_record *);
111extern int mvme147_parse_bootinfo(const struct bi_record *);
112extern int hp300_parse_bootinfo(const struct bi_record *);
113
114extern void config_amiga(void);
115extern void config_atari(void);
116extern void config_mac(void);
117extern void config_sun3(void);
118extern void config_apollo(void);
119extern void config_mvme147(void);
120extern void config_mvme16x(void);
121extern void config_bvme6000(void);
122extern void config_hp300(void);
123extern void config_q40(void);
124extern void config_sun3x(void);
125
126extern void mac_debugging_short (int, short);
127extern void mac_debugging_long (int, long);
128
129#define MASK_256K 0xfffc0000
130
131extern void paging_init(void);
132
133static void __init m68k_parse_bootinfo(const struct bi_record *record)
134{
135 while (record->tag != BI_LAST) {
136 int unknown = 0;
137 const unsigned long *data = record->data;
138 switch (record->tag) {
139 case BI_MACHTYPE:
140 case BI_CPUTYPE:
141 case BI_FPUTYPE:
142 case BI_MMUTYPE:
143 /* Already set up by head.S */
144 break;
145
146 case BI_MEMCHUNK:
147 if (m68k_num_memory < NUM_MEMINFO) {
148 m68k_memory[m68k_num_memory].addr = data[0];
149 m68k_memory[m68k_num_memory].size = data[1];
150 m68k_num_memory++;
151 } else
152 printk("m68k_parse_bootinfo: too many memory chunks\n");
153 break;
154
155 case BI_RAMDISK:
156 m68k_ramdisk.addr = data[0];
157 m68k_ramdisk.size = data[1];
158 break;
159
160 case BI_COMMAND_LINE:
161 strlcpy(m68k_command_line, (const char *)data, sizeof(m68k_command_line));
162 break;
163
164 default:
165 if (MACH_IS_AMIGA)
166 unknown = amiga_parse_bootinfo(record);
167 else if (MACH_IS_ATARI)
168 unknown = atari_parse_bootinfo(record);
169 else if (MACH_IS_MAC)
170 unknown = mac_parse_bootinfo(record);
171 else if (MACH_IS_Q40)
172 unknown = q40_parse_bootinfo(record);
173 else if (MACH_IS_BVME6000)
174 unknown = bvme6000_parse_bootinfo(record);
175 else if (MACH_IS_MVME16x)
176 unknown = mvme16x_parse_bootinfo(record);
177 else if (MACH_IS_MVME147)
178 unknown = mvme147_parse_bootinfo(record);
179 else if (MACH_IS_HP300)
180 unknown = hp300_parse_bootinfo(record);
181 else
182 unknown = 1;
183 }
184 if (unknown)
185 printk("m68k_parse_bootinfo: unknown tag 0x%04x ignored\n",
186 record->tag);
187 record = (struct bi_record *)((unsigned long)record+record->size);
188 }
189
190 m68k_realnum_memory = m68k_num_memory;
191#ifdef CONFIG_SINGLE_MEMORY_CHUNK
192 if (m68k_num_memory > 1) {
193 printk("Ignoring last %i chunks of physical memory\n",
194 (m68k_num_memory - 1));
195 m68k_num_memory = 1;
196 }
197 m68k_memoffset = m68k_memory[0].addr-PAGE_OFFSET;
198#endif
199}
200
201void __init setup_arch(char **cmdline_p)
202{
203 extern int _etext, _edata, _end;
204#ifndef CONFIG_SUN3
205 unsigned long endmem, startmem;
206#endif
207 int i;
208 char *p, *q;
209
210 /* The bootinfo is located right after the kernel bss */
211 m68k_parse_bootinfo((const struct bi_record *)&_end);
212
213 if (CPU_IS_040)
214 m68k_is040or060 = 4;
215 else if (CPU_IS_060)
216 m68k_is040or060 = 6;
217
218 /* FIXME: m68k_fputype is passed in by Penguin booter, which can
219 * be confused by software FPU emulation. BEWARE.
220 * We should really do our own FPU check at startup.
221 * [what do we do with buggy 68LC040s? if we have problems
222 * with them, we should add a test to check_bugs() below] */
223#ifndef CONFIG_M68KFPU_EMU_ONLY
224 /* clear the fpu if we have one */
225 if (m68k_fputype & (FPU_68881|FPU_68882|FPU_68040|FPU_68060)) {
226 volatile int zero = 0;
227 asm __volatile__ ("frestore %0" : : "m" (zero));
228 }
229#endif
230
231 if (CPU_IS_060) {
232 u32 pcr;
233
234 asm (".chip 68060; movec %%pcr,%0; .chip 68k"
235 : "=d" (pcr));
236 if (((pcr >> 8) & 0xff) <= 5) {
237 printk("Enabling workaround for errata I14\n");
238 asm (".chip 68060; movec %0,%%pcr; .chip 68k"
239 : : "d" (pcr | 0x20));
240 }
241 }
242
243 init_mm.start_code = PAGE_OFFSET;
244 init_mm.end_code = (unsigned long) &_etext;
245 init_mm.end_data = (unsigned long) &_edata;
246 init_mm.brk = (unsigned long) &_end;
247
248 *cmdline_p = m68k_command_line;
249 memcpy(saved_command_line, *cmdline_p, CL_SIZE);
250
251 /* Parse the command line for arch-specific options.
252 * For the m68k, this is currently only "debug=xxx" to enable printing
253 * certain kernel messages to some machine-specific device.
254 */
255 for( p = *cmdline_p; p && *p; ) {
256 i = 0;
257 if (!strncmp( p, "debug=", 6 )) {
258 strlcpy( m68k_debug_device, p+6, sizeof(m68k_debug_device) );
259 if ((q = strchr( m68k_debug_device, ' ' ))) *q = 0;
260 i = 1;
261 }
262#ifdef CONFIG_ATARI
263 /* This option must be parsed very early */
264 if (!strncmp( p, "switches=", 9 )) {
265 extern void atari_switches_setup( const char *, int );
266 atari_switches_setup( p+9, (q = strchr( p+9, ' ' )) ?
267 (q - (p+9)) : strlen(p+9) );
268 i = 1;
269 }
270#endif
271
272 if (i) {
273 /* option processed, delete it */
274 if ((q = strchr( p, ' ' )))
275 strcpy( p, q+1 );
276 else
277 *p = 0;
278 } else {
279 if ((p = strchr( p, ' ' ))) ++p;
280 }
281 }
282
283 switch (m68k_machtype) {
284#ifdef CONFIG_AMIGA
285 case MACH_AMIGA:
286 config_amiga();
287 break;
288#endif
289#ifdef CONFIG_ATARI
290 case MACH_ATARI:
291 config_atari();
292 break;
293#endif
294#ifdef CONFIG_MAC
295 case MACH_MAC:
296 config_mac();
297 break;
298#endif
299#ifdef CONFIG_SUN3
300 case MACH_SUN3:
301 config_sun3();
302 break;
303#endif
304#ifdef CONFIG_APOLLO
305 case MACH_APOLLO:
306 config_apollo();
307 break;
308#endif
309#ifdef CONFIG_MVME147
310 case MACH_MVME147:
311 config_mvme147();
312 break;
313#endif
314#ifdef CONFIG_MVME16x
315 case MACH_MVME16x:
316 config_mvme16x();
317 break;
318#endif
319#ifdef CONFIG_BVME6000
320 case MACH_BVME6000:
321 config_bvme6000();
322 break;
323#endif
324#ifdef CONFIG_HP300
325 case MACH_HP300:
326 config_hp300();
327 break;
328#endif
329#ifdef CONFIG_Q40
330 case MACH_Q40:
331 config_q40();
332 break;
333#endif
334#ifdef CONFIG_SUN3X
335 case MACH_SUN3X:
336 config_sun3x();
337 break;
338#endif
339 default:
340 panic ("No configuration setup");
341 }
342
343#ifndef CONFIG_SUN3
344 startmem= m68k_memory[0].addr;
345 endmem = startmem + m68k_memory[0].size;
346 high_memory = (void *)PAGE_OFFSET;
347 for (i = 0; i < m68k_num_memory; i++) {
348 m68k_memory[i].size &= MASK_256K;
349 if (m68k_memory[i].addr < startmem)
350 startmem = m68k_memory[i].addr;
351 if (m68k_memory[i].addr+m68k_memory[i].size > endmem)
352 endmem = m68k_memory[i].addr+m68k_memory[i].size;
353 high_memory += m68k_memory[i].size;
354 }
355
356 availmem += init_bootmem_node(NODE_DATA(0), availmem >> PAGE_SHIFT,
357 startmem >> PAGE_SHIFT, endmem >> PAGE_SHIFT);
358
359 for (i = 0; i < m68k_num_memory; i++)
360 free_bootmem(m68k_memory[i].addr, m68k_memory[i].size);
361
362 reserve_bootmem(m68k_memory[0].addr, availmem - m68k_memory[0].addr);
363
364#ifdef CONFIG_BLK_DEV_INITRD
365 if (m68k_ramdisk.size) {
366 reserve_bootmem(m68k_ramdisk.addr, m68k_ramdisk.size);
367 initrd_start = (unsigned long)phys_to_virt(m68k_ramdisk.addr);
368 initrd_end = initrd_start + m68k_ramdisk.size;
369 printk ("initrd: %08lx - %08lx\n", initrd_start, initrd_end);
370 }
371#endif
372
373#ifdef CONFIG_ATARI
374 if (MACH_IS_ATARI)
375 atari_stram_reserve_pages((void *)availmem);
376#endif
377#ifdef CONFIG_SUN3X
378 if (MACH_IS_SUN3X) {
379 dvma_init();
380 }
381#endif
382
383#endif /* !CONFIG_SUN3 */
384
385 paging_init();
386
387/* set ISA defs early as possible */
388#if defined(CONFIG_ISA) && defined(MULTI_ISA)
389#if defined(CONFIG_Q40)
390 if (MACH_IS_Q40) {
391 isa_type = Q40_ISA;
392 isa_sex = 0;
393 }
394#elif defined(CONFIG_GG2)
395 if (MACH_IS_AMIGA && AMIGAHW_PRESENT(GG2_ISA)){
396 isa_type = GG2_ISA;
397 isa_sex = 0;
398 }
399#elif defined(CONFIG_AMIGA_PCMCIA)
400 if (MACH_IS_AMIGA && AMIGAHW_PRESENT(PCMCIA)){
401 isa_type = AG_ISA;
402 isa_sex = 1;
403 }
404#endif
405#endif
406}
407
408static int show_cpuinfo(struct seq_file *m, void *v)
409{
410 const char *cpu, *mmu, *fpu;
411 unsigned long clockfreq, clockfactor;
412
413#define LOOP_CYCLES_68020 (8)
414#define LOOP_CYCLES_68030 (8)
415#define LOOP_CYCLES_68040 (3)
416#define LOOP_CYCLES_68060 (1)
417
418 if (CPU_IS_020) {
419 cpu = "68020";
420 clockfactor = LOOP_CYCLES_68020;
421 } else if (CPU_IS_030) {
422 cpu = "68030";
423 clockfactor = LOOP_CYCLES_68030;
424 } else if (CPU_IS_040) {
425 cpu = "68040";
426 clockfactor = LOOP_CYCLES_68040;
427 } else if (CPU_IS_060) {
428 cpu = "68060";
429 clockfactor = LOOP_CYCLES_68060;
430 } else {
431 cpu = "680x0";
432 clockfactor = 0;
433 }
434
435#ifdef CONFIG_M68KFPU_EMU_ONLY
436 fpu="none(soft float)";
437#else
438 if (m68k_fputype & FPU_68881)
439 fpu = "68881";
440 else if (m68k_fputype & FPU_68882)
441 fpu = "68882";
442 else if (m68k_fputype & FPU_68040)
443 fpu = "68040";
444 else if (m68k_fputype & FPU_68060)
445 fpu = "68060";
446 else if (m68k_fputype & FPU_SUNFPA)
447 fpu = "Sun FPA";
448 else
449 fpu = "none";
450#endif
451
452 if (m68k_mmutype & MMU_68851)
453 mmu = "68851";
454 else if (m68k_mmutype & MMU_68030)
455 mmu = "68030";
456 else if (m68k_mmutype & MMU_68040)
457 mmu = "68040";
458 else if (m68k_mmutype & MMU_68060)
459 mmu = "68060";
460 else if (m68k_mmutype & MMU_SUN3)
461 mmu = "Sun-3";
462 else if (m68k_mmutype & MMU_APOLLO)
463 mmu = "Apollo";
464 else
465 mmu = "unknown";
466
467 clockfreq = loops_per_jiffy*HZ*clockfactor;
468
469 seq_printf(m, "CPU:\t\t%s\n"
470 "MMU:\t\t%s\n"
471 "FPU:\t\t%s\n"
472 "Clocking:\t%lu.%1luMHz\n"
473 "BogoMips:\t%lu.%02lu\n"
474 "Calibration:\t%lu loops\n",
475 cpu, mmu, fpu,
476 clockfreq/1000000,(clockfreq/100000)%10,
477 loops_per_jiffy/(500000/HZ),(loops_per_jiffy/(5000/HZ))%100,
478 loops_per_jiffy);
479 return 0;
480}
481
482static void *c_start(struct seq_file *m, loff_t *pos)
483{
484 return *pos < 1 ? (void *)1 : NULL;
485}
486static void *c_next(struct seq_file *m, void *v, loff_t *pos)
487{
488 ++*pos;
489 return NULL;
490}
491static void c_stop(struct seq_file *m, void *v)
492{
493}
494struct seq_operations cpuinfo_op = {
495 .start = c_start,
496 .next = c_next,
497 .stop = c_stop,
498 .show = show_cpuinfo,
499};
500
501int get_hardware_list(char *buffer)
502{
503 int len = 0;
504 char model[80];
505 unsigned long mem;
506 int i;
507
508 if (mach_get_model)
509 mach_get_model(model);
510 else
511 strcpy(model, "Unknown m68k");
512
513 len += sprintf(buffer+len, "Model:\t\t%s\n", model);
514 for (mem = 0, i = 0; i < m68k_num_memory; i++)
515 mem += m68k_memory[i].size;
516 len += sprintf(buffer+len, "System Memory:\t%ldK\n", mem>>10);
517
518 if (mach_get_hardware_list)
519 len += mach_get_hardware_list(buffer+len);
520
521 return(len);
522}
523
524
525#if defined(CONFIG_AMIGA_FLOPPY) || defined(CONFIG_ATARI_FLOPPY)
526void __init floppy_setup(char *str, int *ints)
527{
528 if (mach_floppy_setup)
529 mach_floppy_setup (str, ints);
530}
531
532#endif
533
534void check_bugs(void)
535{
536#ifndef CONFIG_M68KFPU_EMU
537 if (m68k_fputype == 0) {
538 printk( KERN_EMERG "*** YOU DO NOT HAVE A FLOATING POINT UNIT, "
539 "WHICH IS REQUIRED BY LINUX/M68K ***\n" );
540 printk( KERN_EMERG "Upgrade your hardware or join the FPU "
541 "emulation project\n" );
542 panic( "no FPU" );
543 }
544#endif /* !CONFIG_M68KFPU_EMU */
545}
diff --git a/arch/m68k/kernel/signal.c b/arch/m68k/kernel/signal.c
new file mode 100644
index 000000000000..9c636a4c238d
--- /dev/null
+++ b/arch/m68k/kernel/signal.c
@@ -0,0 +1,1025 @@
1/*
2 * linux/arch/m68k/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/personality.h>
43#include <linux/tty.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
56const int frame_extra_sizes[16] = {
57 [1] = -1, /* sizeof(((struct frame *)0)->un.fmt1), */
58 [2] = sizeof(((struct frame *)0)->un.fmt2),
59 [3] = sizeof(((struct frame *)0)->un.fmt3),
60 [4] = sizeof(((struct frame *)0)->un.fmt4),
61 [5] = -1, /* sizeof(((struct frame *)0)->un.fmt5), */
62 [6] = -1, /* sizeof(((struct frame *)0)->un.fmt6), */
63 [7] = sizeof(((struct frame *)0)->un.fmt7),
64 [8] = -1, /* sizeof(((struct frame *)0)->un.fmt8), */
65 [9] = sizeof(((struct frame *)0)->un.fmt9),
66 [10] = sizeof(((struct frame *)0)->un.fmta),
67 [11] = sizeof(((struct frame *)0)->un.fmtb),
68 [12] = -1, /* sizeof(((struct frame *)0)->un.fmtc), */
69 [13] = -1, /* sizeof(((struct frame *)0)->un.fmtd), */
70 [14] = -1, /* sizeof(((struct frame *)0)->un.fmte), */
71 [15] = -1, /* sizeof(((struct frame *)0)->un.fmtf), */
72};
73
74/*
75 * Atomically swap in the new signal mask, and wait for a signal.
76 */
77asmlinkage int do_sigsuspend(struct pt_regs *regs)
78{
79 old_sigset_t mask = regs->d3;
80 sigset_t saveset;
81
82 mask &= _BLOCKABLE;
83 saveset = current->blocked;
84 siginitset(&current->blocked, mask);
85 recalc_sigpending();
86
87 regs->d0 = -EINTR;
88 while (1) {
89 current->state = TASK_INTERRUPTIBLE;
90 schedule();
91 if (do_signal(&saveset, regs))
92 return -EINTR;
93 }
94}
95
96asmlinkage int
97do_rt_sigsuspend(struct pt_regs *regs)
98{
99 sigset_t *unewset = (sigset_t *)regs->d1;
100 size_t sigsetsize = (size_t)regs->d2;
101 sigset_t saveset, newset;
102
103 /* XXX: Don't preclude handling different sized sigset_t's. */
104 if (sigsetsize != sizeof(sigset_t))
105 return -EINVAL;
106
107 if (copy_from_user(&newset, unewset, sizeof(newset)))
108 return -EFAULT;
109 sigdelsetmask(&newset, ~_BLOCKABLE);
110
111 saveset = current->blocked;
112 current->blocked = newset;
113 recalc_sigpending();
114
115 regs->d0 = -EINTR;
116 while (1) {
117 current->state = TASK_INTERRUPTIBLE;
118 schedule();
119 if (do_signal(&saveset, regs))
120 return -EINTR;
121 }
122}
123
124asmlinkage int
125sys_sigaction(int sig, const struct old_sigaction *act,
126 struct old_sigaction *oact)
127{
128 struct k_sigaction new_ka, old_ka;
129 int ret;
130
131 if (act) {
132 old_sigset_t mask;
133 if (!access_ok(VERIFY_READ, act, sizeof(*act)) ||
134 __get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
135 __get_user(new_ka.sa.sa_restorer, &act->sa_restorer))
136 return -EFAULT;
137 __get_user(new_ka.sa.sa_flags, &act->sa_flags);
138 __get_user(mask, &act->sa_mask);
139 siginitset(&new_ka.sa.sa_mask, mask);
140 }
141
142 ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
143
144 if (!ret && oact) {
145 if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) ||
146 __put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
147 __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer))
148 return -EFAULT;
149 __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
150 __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
151 }
152
153 return ret;
154}
155
156asmlinkage int
157sys_sigaltstack(const stack_t *uss, stack_t *uoss)
158{
159 return do_sigaltstack(uss, uoss, rdusp());
160}
161
162
163/*
164 * Do a signal return; undo the signal stack.
165 *
166 * Keep the return code on the stack quadword aligned!
167 * That makes the cache flush below easier.
168 */
169
170struct sigframe
171{
172 char *pretcode;
173 int sig;
174 int code;
175 struct sigcontext *psc;
176 char retcode[8];
177 unsigned long extramask[_NSIG_WORDS-1];
178 struct sigcontext sc;
179};
180
181struct rt_sigframe
182{
183 char *pretcode;
184 int sig;
185 struct siginfo *pinfo;
186 void *puc;
187 char retcode[8];
188 struct siginfo info;
189 struct ucontext uc;
190};
191
192
193static unsigned char fpu_version; /* version number of fpu, set by setup_frame */
194
195static inline int restore_fpu_state(struct sigcontext *sc)
196{
197 int err = 1;
198
199 if (FPU_IS_EMU) {
200 /* restore registers */
201 memcpy(current->thread.fpcntl, sc->sc_fpcntl, 12);
202 memcpy(current->thread.fp, sc->sc_fpregs, 24);
203 return 0;
204 }
205
206 if (CPU_IS_060 ? sc->sc_fpstate[2] : sc->sc_fpstate[0]) {
207 /* Verify the frame format. */
208 if (!CPU_IS_060 && (sc->sc_fpstate[0] != fpu_version))
209 goto out;
210 if (CPU_IS_020_OR_030) {
211 if (m68k_fputype & FPU_68881 &&
212 !(sc->sc_fpstate[1] == 0x18 || sc->sc_fpstate[1] == 0xb4))
213 goto out;
214 if (m68k_fputype & FPU_68882 &&
215 !(sc->sc_fpstate[1] == 0x38 || sc->sc_fpstate[1] == 0xd4))
216 goto out;
217 } else if (CPU_IS_040) {
218 if (!(sc->sc_fpstate[1] == 0x00 ||
219 sc->sc_fpstate[1] == 0x28 ||
220 sc->sc_fpstate[1] == 0x60))
221 goto out;
222 } else if (CPU_IS_060) {
223 if (!(sc->sc_fpstate[3] == 0x00 ||
224 sc->sc_fpstate[3] == 0x60 ||
225 sc->sc_fpstate[3] == 0xe0))
226 goto out;
227 } else
228 goto out;
229
230 __asm__ volatile (".chip 68k/68881\n\t"
231 "fmovemx %0,%%fp0-%%fp1\n\t"
232 "fmoveml %1,%%fpcr/%%fpsr/%%fpiar\n\t"
233 ".chip 68k"
234 : /* no outputs */
235 : "m" (*sc->sc_fpregs), "m" (*sc->sc_fpcntl));
236 }
237 __asm__ volatile (".chip 68k/68881\n\t"
238 "frestore %0\n\t"
239 ".chip 68k" : : "m" (*sc->sc_fpstate));
240 err = 0;
241
242out:
243 return err;
244}
245
246#define FPCONTEXT_SIZE 216
247#define uc_fpstate uc_filler[0]
248#define uc_formatvec uc_filler[FPCONTEXT_SIZE/4]
249#define uc_extra uc_filler[FPCONTEXT_SIZE/4+1]
250
251static inline int rt_restore_fpu_state(struct ucontext *uc)
252{
253 unsigned char fpstate[FPCONTEXT_SIZE];
254 int context_size = CPU_IS_060 ? 8 : 0;
255 fpregset_t fpregs;
256 int err = 1;
257
258 if (FPU_IS_EMU) {
259 /* restore fpu control register */
260 if (__copy_from_user(current->thread.fpcntl,
261 uc->uc_mcontext.fpregs.f_fpcntl, 12))
262 goto out;
263 /* restore all other fpu register */
264 if (__copy_from_user(current->thread.fp,
265 uc->uc_mcontext.fpregs.f_fpregs, 96))
266 goto out;
267 return 0;
268 }
269
270 if (__get_user(*(long *)fpstate, (long *)&uc->uc_fpstate))
271 goto out;
272 if (CPU_IS_060 ? fpstate[2] : fpstate[0]) {
273 if (!CPU_IS_060)
274 context_size = fpstate[1];
275 /* Verify the frame format. */
276 if (!CPU_IS_060 && (fpstate[0] != fpu_version))
277 goto out;
278 if (CPU_IS_020_OR_030) {
279 if (m68k_fputype & FPU_68881 &&
280 !(context_size == 0x18 || context_size == 0xb4))
281 goto out;
282 if (m68k_fputype & FPU_68882 &&
283 !(context_size == 0x38 || context_size == 0xd4))
284 goto out;
285 } else if (CPU_IS_040) {
286 if (!(context_size == 0x00 ||
287 context_size == 0x28 ||
288 context_size == 0x60))
289 goto out;
290 } else if (CPU_IS_060) {
291 if (!(fpstate[3] == 0x00 ||
292 fpstate[3] == 0x60 ||
293 fpstate[3] == 0xe0))
294 goto out;
295 } else
296 goto out;
297 if (__copy_from_user(&fpregs, &uc->uc_mcontext.fpregs,
298 sizeof(fpregs)))
299 goto out;
300 __asm__ volatile (".chip 68k/68881\n\t"
301 "fmovemx %0,%%fp0-%%fp7\n\t"
302 "fmoveml %1,%%fpcr/%%fpsr/%%fpiar\n\t"
303 ".chip 68k"
304 : /* no outputs */
305 : "m" (*fpregs.f_fpregs),
306 "m" (*fpregs.f_fpcntl));
307 }
308 if (context_size &&
309 __copy_from_user(fpstate + 4, (long *)&uc->uc_fpstate + 1,
310 context_size))
311 goto out;
312 __asm__ volatile (".chip 68k/68881\n\t"
313 "frestore %0\n\t"
314 ".chip 68k" : : "m" (*fpstate));
315 err = 0;
316
317out:
318 return err;
319}
320
321static inline int
322restore_sigcontext(struct pt_regs *regs, struct sigcontext *usc, void *fp,
323 int *pd0)
324{
325 int fsize, formatvec;
326 struct sigcontext context;
327 int err;
328
329 /* get previous context */
330 if (copy_from_user(&context, usc, sizeof(context)))
331 goto badframe;
332
333 /* restore passed registers */
334 regs->d1 = context.sc_d1;
335 regs->a0 = context.sc_a0;
336 regs->a1 = context.sc_a1;
337 regs->sr = (regs->sr & 0xff00) | (context.sc_sr & 0xff);
338 regs->pc = context.sc_pc;
339 regs->orig_d0 = -1; /* disable syscall checks */
340 wrusp(context.sc_usp);
341 formatvec = context.sc_formatvec;
342 regs->format = formatvec >> 12;
343 regs->vector = formatvec & 0xfff;
344
345 err = restore_fpu_state(&context);
346
347 fsize = frame_extra_sizes[regs->format];
348 if (fsize < 0) {
349 /*
350 * user process trying to return with weird frame format
351 */
352#ifdef DEBUG
353 printk("user process returning with weird frame format\n");
354#endif
355 goto badframe;
356 }
357
358 /* OK. Make room on the supervisor stack for the extra junk,
359 * if necessary.
360 */
361
362 if (fsize) {
363 struct switch_stack *sw = (struct switch_stack *)regs - 1;
364 regs->d0 = context.sc_d0;
365#define frame_offset (sizeof(struct pt_regs)+sizeof(struct switch_stack))
366 __asm__ __volatile__
367 (" movel %0,%/a0\n\t"
368 " subl %1,%/a0\n\t" /* make room on stack */
369 " movel %/a0,%/sp\n\t" /* set stack pointer */
370 /* move switch_stack and pt_regs */
371 "1: movel %0@+,%/a0@+\n\t"
372 " dbra %2,1b\n\t"
373 " lea %/sp@(%c3),%/a0\n\t" /* add offset of fmt */
374 " lsrl #2,%1\n\t"
375 " subql #1,%1\n\t"
376 "2: movesl %4@+,%2\n\t"
377 "3: movel %2,%/a0@+\n\t"
378 " dbra %1,2b\n\t"
379 " bral ret_from_signal\n"
380 "4:\n"
381 ".section __ex_table,\"a\"\n"
382 " .align 4\n"
383 " .long 2b,4b\n"
384 " .long 3b,4b\n"
385 ".previous"
386 : /* no outputs, it doesn't ever return */
387 : "a" (sw), "d" (fsize), "d" (frame_offset/4-1),
388 "n" (frame_offset), "a" (fp)
389 : "a0");
390#undef frame_offset
391 /*
392 * If we ever get here an exception occurred while
393 * building the above stack-frame.
394 */
395 goto badframe;
396 }
397
398 *pd0 = context.sc_d0;
399 return err;
400
401badframe:
402 return 1;
403}
404
405static inline int
406rt_restore_ucontext(struct pt_regs *regs, struct switch_stack *sw,
407 struct ucontext *uc, int *pd0)
408{
409 int fsize, temp;
410 greg_t *gregs = uc->uc_mcontext.gregs;
411 unsigned long usp;
412 int err;
413
414 err = __get_user(temp, &uc->uc_mcontext.version);
415 if (temp != MCONTEXT_VERSION)
416 goto badframe;
417 /* restore passed registers */
418 err |= __get_user(regs->d0, &gregs[0]);
419 err |= __get_user(regs->d1, &gregs[1]);
420 err |= __get_user(regs->d2, &gregs[2]);
421 err |= __get_user(regs->d3, &gregs[3]);
422 err |= __get_user(regs->d4, &gregs[4]);
423 err |= __get_user(regs->d5, &gregs[5]);
424 err |= __get_user(sw->d6, &gregs[6]);
425 err |= __get_user(sw->d7, &gregs[7]);
426 err |= __get_user(regs->a0, &gregs[8]);
427 err |= __get_user(regs->a1, &gregs[9]);
428 err |= __get_user(regs->a2, &gregs[10]);
429 err |= __get_user(sw->a3, &gregs[11]);
430 err |= __get_user(sw->a4, &gregs[12]);
431 err |= __get_user(sw->a5, &gregs[13]);
432 err |= __get_user(sw->a6, &gregs[14]);
433 err |= __get_user(usp, &gregs[15]);
434 wrusp(usp);
435 err |= __get_user(regs->pc, &gregs[16]);
436 err |= __get_user(temp, &gregs[17]);
437 regs->sr = (regs->sr & 0xff00) | (temp & 0xff);
438 regs->orig_d0 = -1; /* disable syscall checks */
439 err |= __get_user(temp, &uc->uc_formatvec);
440 regs->format = temp >> 12;
441 regs->vector = temp & 0xfff;
442
443 err |= rt_restore_fpu_state(uc);
444
445 if (do_sigaltstack(&uc->uc_stack, NULL, usp) == -EFAULT)
446 goto badframe;
447
448 fsize = frame_extra_sizes[regs->format];
449 if (fsize < 0) {
450 /*
451 * user process trying to return with weird frame format
452 */
453#ifdef DEBUG
454 printk("user process returning with weird frame format\n");
455#endif
456 goto badframe;
457 }
458
459 /* OK. Make room on the supervisor stack for the extra junk,
460 * if necessary.
461 */
462
463 if (fsize) {
464#define frame_offset (sizeof(struct pt_regs)+sizeof(struct switch_stack))
465 __asm__ __volatile__
466 (" movel %0,%/a0\n\t"
467 " subl %1,%/a0\n\t" /* make room on stack */
468 " movel %/a0,%/sp\n\t" /* set stack pointer */
469 /* move switch_stack and pt_regs */
470 "1: movel %0@+,%/a0@+\n\t"
471 " dbra %2,1b\n\t"
472 " lea %/sp@(%c3),%/a0\n\t" /* add offset of fmt */
473 " lsrl #2,%1\n\t"
474 " subql #1,%1\n\t"
475 "2: movesl %4@+,%2\n\t"
476 "3: movel %2,%/a0@+\n\t"
477 " dbra %1,2b\n\t"
478 " bral ret_from_signal\n"
479 "4:\n"
480 ".section __ex_table,\"a\"\n"
481 " .align 4\n"
482 " .long 2b,4b\n"
483 " .long 3b,4b\n"
484 ".previous"
485 : /* no outputs, it doesn't ever return */
486 : "a" (sw), "d" (fsize), "d" (frame_offset/4-1),
487 "n" (frame_offset), "a" (&uc->uc_extra)
488 : "a0");
489#undef frame_offset
490 /*
491 * If we ever get here an exception occurred while
492 * building the above stack-frame.
493 */
494 goto badframe;
495 }
496
497 *pd0 = regs->d0;
498 return err;
499
500badframe:
501 return 1;
502}
503
504asmlinkage int do_sigreturn(unsigned long __unused)
505{
506 struct switch_stack *sw = (struct switch_stack *) &__unused;
507 struct pt_regs *regs = (struct pt_regs *) (sw + 1);
508 unsigned long usp = rdusp();
509 struct sigframe *frame = (struct sigframe *)(usp - 4);
510 sigset_t set;
511 int d0;
512
513 if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
514 goto badframe;
515 if (__get_user(set.sig[0], &frame->sc.sc_mask) ||
516 (_NSIG_WORDS > 1 &&
517 __copy_from_user(&set.sig[1], &frame->extramask,
518 sizeof(frame->extramask))))
519 goto badframe;
520
521 sigdelsetmask(&set, ~_BLOCKABLE);
522 current->blocked = set;
523 recalc_sigpending();
524
525 if (restore_sigcontext(regs, &frame->sc, frame + 1, &d0))
526 goto badframe;
527 return d0;
528
529badframe:
530 force_sig(SIGSEGV, current);
531 return 0;
532}
533
534asmlinkage int do_rt_sigreturn(unsigned long __unused)
535{
536 struct switch_stack *sw = (struct switch_stack *) &__unused;
537 struct pt_regs *regs = (struct pt_regs *) (sw + 1);
538 unsigned long usp = rdusp();
539 struct rt_sigframe *frame = (struct rt_sigframe *)(usp - 4);
540 sigset_t set;
541 int d0;
542
543 if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
544 goto badframe;
545 if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
546 goto badframe;
547
548 sigdelsetmask(&set, ~_BLOCKABLE);
549 current->blocked = set;
550 recalc_sigpending();
551
552 if (rt_restore_ucontext(regs, sw, &frame->uc, &d0))
553 goto badframe;
554 return d0;
555
556badframe:
557 force_sig(SIGSEGV, current);
558 return 0;
559}
560
561/*
562 * Set up a signal frame.
563 */
564
565static inline void save_fpu_state(struct sigcontext *sc, struct pt_regs *regs)
566{
567 if (FPU_IS_EMU) {
568 /* save registers */
569 memcpy(sc->sc_fpcntl, current->thread.fpcntl, 12);
570 memcpy(sc->sc_fpregs, current->thread.fp, 24);
571 return;
572 }
573
574 __asm__ volatile (".chip 68k/68881\n\t"
575 "fsave %0\n\t"
576 ".chip 68k"
577 : : "m" (*sc->sc_fpstate) : "memory");
578
579 if (CPU_IS_060 ? sc->sc_fpstate[2] : sc->sc_fpstate[0]) {
580 fpu_version = sc->sc_fpstate[0];
581 if (CPU_IS_020_OR_030 &&
582 regs->vector >= (VEC_FPBRUC * 4) &&
583 regs->vector <= (VEC_FPNAN * 4)) {
584 /* Clear pending exception in 68882 idle frame */
585 if (*(unsigned short *) sc->sc_fpstate == 0x1f38)
586 sc->sc_fpstate[0x38] |= 1 << 3;
587 }
588 __asm__ volatile (".chip 68k/68881\n\t"
589 "fmovemx %%fp0-%%fp1,%0\n\t"
590 "fmoveml %%fpcr/%%fpsr/%%fpiar,%1\n\t"
591 ".chip 68k"
592 : "=m" (*sc->sc_fpregs),
593 "=m" (*sc->sc_fpcntl)
594 : /* no inputs */
595 : "memory");
596 }
597}
598
599static inline int rt_save_fpu_state(struct ucontext *uc, struct pt_regs *regs)
600{
601 unsigned char fpstate[FPCONTEXT_SIZE];
602 int context_size = CPU_IS_060 ? 8 : 0;
603 int err = 0;
604
605 if (FPU_IS_EMU) {
606 /* save fpu control register */
607 err |= copy_to_user(uc->uc_mcontext.fpregs.f_fpcntl,
608 current->thread.fpcntl, 12);
609 /* save all other fpu register */
610 err |= copy_to_user(uc->uc_mcontext.fpregs.f_fpregs,
611 current->thread.fp, 96);
612 return err;
613 }
614
615 __asm__ volatile (".chip 68k/68881\n\t"
616 "fsave %0\n\t"
617 ".chip 68k"
618 : : "m" (*fpstate) : "memory");
619
620 err |= __put_user(*(long *)fpstate, (long *)&uc->uc_fpstate);
621 if (CPU_IS_060 ? fpstate[2] : fpstate[0]) {
622 fpregset_t fpregs;
623 if (!CPU_IS_060)
624 context_size = fpstate[1];
625 fpu_version = fpstate[0];
626 if (CPU_IS_020_OR_030 &&
627 regs->vector >= (VEC_FPBRUC * 4) &&
628 regs->vector <= (VEC_FPNAN * 4)) {
629 /* Clear pending exception in 68882 idle frame */
630 if (*(unsigned short *) fpstate == 0x1f38)
631 fpstate[0x38] |= 1 << 3;
632 }
633 __asm__ volatile (".chip 68k/68881\n\t"
634 "fmovemx %%fp0-%%fp7,%0\n\t"
635 "fmoveml %%fpcr/%%fpsr/%%fpiar,%1\n\t"
636 ".chip 68k"
637 : "=m" (*fpregs.f_fpregs),
638 "=m" (*fpregs.f_fpcntl)
639 : /* no inputs */
640 : "memory");
641 err |= copy_to_user(&uc->uc_mcontext.fpregs, &fpregs,
642 sizeof(fpregs));
643 }
644 if (context_size)
645 err |= copy_to_user((long *)&uc->uc_fpstate + 1, fpstate + 4,
646 context_size);
647 return err;
648}
649
650static void setup_sigcontext(struct sigcontext *sc, struct pt_regs *regs,
651 unsigned long mask)
652{
653 sc->sc_mask = mask;
654 sc->sc_usp = rdusp();
655 sc->sc_d0 = regs->d0;
656 sc->sc_d1 = regs->d1;
657 sc->sc_a0 = regs->a0;
658 sc->sc_a1 = regs->a1;
659 sc->sc_sr = regs->sr;
660 sc->sc_pc = regs->pc;
661 sc->sc_formatvec = regs->format << 12 | regs->vector;
662 save_fpu_state(sc, regs);
663}
664
665static inline int rt_setup_ucontext(struct ucontext *uc, struct pt_regs *regs)
666{
667 struct switch_stack *sw = (struct switch_stack *)regs - 1;
668 greg_t *gregs = uc->uc_mcontext.gregs;
669 int err = 0;
670
671 err |= __put_user(MCONTEXT_VERSION, &uc->uc_mcontext.version);
672 err |= __put_user(regs->d0, &gregs[0]);
673 err |= __put_user(regs->d1, &gregs[1]);
674 err |= __put_user(regs->d2, &gregs[2]);
675 err |= __put_user(regs->d3, &gregs[3]);
676 err |= __put_user(regs->d4, &gregs[4]);
677 err |= __put_user(regs->d5, &gregs[5]);
678 err |= __put_user(sw->d6, &gregs[6]);
679 err |= __put_user(sw->d7, &gregs[7]);
680 err |= __put_user(regs->a0, &gregs[8]);
681 err |= __put_user(regs->a1, &gregs[9]);
682 err |= __put_user(regs->a2, &gregs[10]);
683 err |= __put_user(sw->a3, &gregs[11]);
684 err |= __put_user(sw->a4, &gregs[12]);
685 err |= __put_user(sw->a5, &gregs[13]);
686 err |= __put_user(sw->a6, &gregs[14]);
687 err |= __put_user(rdusp(), &gregs[15]);
688 err |= __put_user(regs->pc, &gregs[16]);
689 err |= __put_user(regs->sr, &gregs[17]);
690 err |= __put_user((regs->format << 12) | regs->vector, &uc->uc_formatvec);
691 err |= rt_save_fpu_state(uc, regs);
692 return err;
693}
694
695static inline void push_cache (unsigned long vaddr)
696{
697 /*
698 * Using the old cache_push_v() was really a big waste.
699 *
700 * What we are trying to do is to flush 8 bytes to ram.
701 * Flushing 2 cache lines of 16 bytes is much cheaper than
702 * flushing 1 or 2 pages, as previously done in
703 * cache_push_v().
704 * Jes
705 */
706 if (CPU_IS_040) {
707 unsigned long temp;
708
709 __asm__ __volatile__ (".chip 68040\n\t"
710 "nop\n\t"
711 "ptestr (%1)\n\t"
712 "movec %%mmusr,%0\n\t"
713 ".chip 68k"
714 : "=r" (temp)
715 : "a" (vaddr));
716
717 temp &= PAGE_MASK;
718 temp |= vaddr & ~PAGE_MASK;
719
720 __asm__ __volatile__ (".chip 68040\n\t"
721 "nop\n\t"
722 "cpushl %%bc,(%0)\n\t"
723 ".chip 68k"
724 : : "a" (temp));
725 }
726 else if (CPU_IS_060) {
727 unsigned long temp;
728 __asm__ __volatile__ (".chip 68060\n\t"
729 "plpar (%0)\n\t"
730 ".chip 68k"
731 : "=a" (temp)
732 : "0" (vaddr));
733 __asm__ __volatile__ (".chip 68060\n\t"
734 "cpushl %%bc,(%0)\n\t"
735 ".chip 68k"
736 : : "a" (temp));
737 }
738 else {
739 /*
740 * 68030/68020 have no writeback cache;
741 * still need to clear icache.
742 * Note that vaddr is guaranteed to be long word aligned.
743 */
744 unsigned long temp;
745 asm volatile ("movec %%cacr,%0" : "=r" (temp));
746 temp += 4;
747 asm volatile ("movec %0,%%caar\n\t"
748 "movec %1,%%cacr"
749 : : "r" (vaddr), "r" (temp));
750 asm volatile ("movec %0,%%caar\n\t"
751 "movec %1,%%cacr"
752 : : "r" (vaddr + 4), "r" (temp));
753 }
754}
755
756static inline void *
757get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size)
758{
759 unsigned long usp;
760
761 /* Default to using normal stack. */
762 usp = rdusp();
763
764 /* This is the X/Open sanctioned signal stack switching. */
765 if (ka->sa.sa_flags & SA_ONSTACK) {
766 if (!on_sig_stack(usp))
767 usp = current->sas_ss_sp + current->sas_ss_size;
768 }
769 return (void *)((usp - frame_size) & -8UL);
770}
771
772static void setup_frame (int sig, struct k_sigaction *ka,
773 sigset_t *set, struct pt_regs *regs)
774{
775 struct sigframe *frame;
776 int fsize = frame_extra_sizes[regs->format];
777 struct sigcontext context;
778 int err = 0;
779
780 if (fsize < 0) {
781#ifdef DEBUG
782 printk ("setup_frame: Unknown frame format %#x\n",
783 regs->format);
784#endif
785 goto give_sigsegv;
786 }
787
788 frame = get_sigframe(ka, regs, sizeof(*frame) + fsize);
789
790 if (fsize) {
791 err |= copy_to_user (frame + 1, regs + 1, fsize);
792 regs->stkadj = fsize;
793 }
794
795 err |= __put_user((current_thread_info()->exec_domain
796 && current_thread_info()->exec_domain->signal_invmap
797 && sig < 32
798 ? current_thread_info()->exec_domain->signal_invmap[sig]
799 : sig),
800 &frame->sig);
801
802 err |= __put_user(regs->vector, &frame->code);
803 err |= __put_user(&frame->sc, &frame->psc);
804
805 if (_NSIG_WORDS > 1)
806 err |= copy_to_user(frame->extramask, &set->sig[1],
807 sizeof(frame->extramask));
808
809 setup_sigcontext(&context, regs, set->sig[0]);
810 err |= copy_to_user (&frame->sc, &context, sizeof(context));
811
812 /* Set up to return from userspace. */
813 err |= __put_user(frame->retcode, &frame->pretcode);
814 /* moveq #,d0; trap #0 */
815 err |= __put_user(0x70004e40 + (__NR_sigreturn << 16),
816 (long *)(frame->retcode));
817
818 if (err)
819 goto give_sigsegv;
820
821 push_cache ((unsigned long) &frame->retcode);
822
823 /* Set up registers for signal handler */
824 wrusp ((unsigned long) frame);
825 regs->pc = (unsigned long) ka->sa.sa_handler;
826
827adjust_stack:
828 /* Prepare to skip over the extra stuff in the exception frame. */
829 if (regs->stkadj) {
830 struct pt_regs *tregs =
831 (struct pt_regs *)((ulong)regs + regs->stkadj);
832#ifdef DEBUG
833 printk("Performing stackadjust=%04x\n", regs->stkadj);
834#endif
835 /* This must be copied with decreasing addresses to
836 handle overlaps. */
837 tregs->vector = 0;
838 tregs->format = 0;
839 tregs->pc = regs->pc;
840 tregs->sr = regs->sr;
841 }
842 return;
843
844give_sigsegv:
845 force_sigsegv(sig, current);
846 goto adjust_stack;
847}
848
849static void setup_rt_frame (int sig, struct k_sigaction *ka, siginfo_t *info,
850 sigset_t *set, struct pt_regs *regs)
851{
852 struct rt_sigframe *frame;
853 int fsize = frame_extra_sizes[regs->format];
854 int err = 0;
855
856 if (fsize < 0) {
857#ifdef DEBUG
858 printk ("setup_frame: Unknown frame format %#x\n",
859 regs->format);
860#endif
861 goto give_sigsegv;
862 }
863
864 frame = get_sigframe(ka, regs, sizeof(*frame));
865
866 if (fsize) {
867 err |= copy_to_user (&frame->uc.uc_extra, regs + 1, fsize);
868 regs->stkadj = fsize;
869 }
870
871 err |= __put_user((current_thread_info()->exec_domain
872 && current_thread_info()->exec_domain->signal_invmap
873 && sig < 32
874 ? current_thread_info()->exec_domain->signal_invmap[sig]
875 : sig),
876 &frame->sig);
877 err |= __put_user(&frame->info, &frame->pinfo);
878 err |= __put_user(&frame->uc, &frame->puc);
879 err |= copy_siginfo_to_user(&frame->info, info);
880
881 /* Create the ucontext. */
882 err |= __put_user(0, &frame->uc.uc_flags);
883 err |= __put_user(0, &frame->uc.uc_link);
884 err |= __put_user((void *)current->sas_ss_sp,
885 &frame->uc.uc_stack.ss_sp);
886 err |= __put_user(sas_ss_flags(rdusp()),
887 &frame->uc.uc_stack.ss_flags);
888 err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
889 err |= rt_setup_ucontext(&frame->uc, regs);
890 err |= copy_to_user (&frame->uc.uc_sigmask, set, sizeof(*set));
891
892 /* Set up to return from userspace. */
893 err |= __put_user(frame->retcode, &frame->pretcode);
894 /* moveq #,d0; notb d0; trap #0 */
895 err |= __put_user(0x70004600 + ((__NR_rt_sigreturn ^ 0xff) << 16),
896 (long *)(frame->retcode + 0));
897 err |= __put_user(0x4e40, (short *)(frame->retcode + 4));
898
899 if (err)
900 goto give_sigsegv;
901
902 push_cache ((unsigned long) &frame->retcode);
903
904 /* Set up registers for signal handler */
905 wrusp ((unsigned long) frame);
906 regs->pc = (unsigned long) ka->sa.sa_handler;
907
908adjust_stack:
909 /* Prepare to skip over the extra stuff in the exception frame. */
910 if (regs->stkadj) {
911 struct pt_regs *tregs =
912 (struct pt_regs *)((ulong)regs + regs->stkadj);
913#ifdef DEBUG
914 printk("Performing stackadjust=%04x\n", regs->stkadj);
915#endif
916 /* This must be copied with decreasing addresses to
917 handle overlaps. */
918 tregs->vector = 0;
919 tregs->format = 0;
920 tregs->pc = regs->pc;
921 tregs->sr = regs->sr;
922 }
923 return;
924
925give_sigsegv:
926 force_sigsegv(sig, current);
927 goto adjust_stack;
928}
929
930static inline void
931handle_restart(struct pt_regs *regs, struct k_sigaction *ka, int has_handler)
932{
933 switch (regs->d0) {
934 case -ERESTARTNOHAND:
935 if (!has_handler)
936 goto do_restart;
937 regs->d0 = -EINTR;
938 break;
939
940 case -ERESTARTSYS:
941 if (has_handler && !(ka->sa.sa_flags & SA_RESTART)) {
942 regs->d0 = -EINTR;
943 break;
944 }
945 /* fallthrough */
946 case -ERESTARTNOINTR:
947 do_restart:
948 regs->d0 = regs->orig_d0;
949 regs->pc -= 2;
950 break;
951 }
952}
953
954void ptrace_signal_deliver(struct pt_regs *regs, void *cookie)
955{
956 if (regs->orig_d0 < 0)
957 return;
958 switch (regs->d0) {
959 case -ERESTARTNOHAND:
960 case -ERESTARTSYS:
961 case -ERESTARTNOINTR:
962 regs->d0 = regs->orig_d0;
963 regs->orig_d0 = -1;
964 regs->pc -= 2;
965 break;
966 }
967}
968
969/*
970 * OK, we're invoking a handler
971 */
972static void
973handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info,
974 sigset_t *oldset, struct pt_regs *regs)
975{
976 /* are we from a system call? */
977 if (regs->orig_d0 >= 0)
978 /* If so, check system call restarting.. */
979 handle_restart(regs, ka, 1);
980
981 /* set up the stack frame */
982 if (ka->sa.sa_flags & SA_SIGINFO)
983 setup_rt_frame(sig, ka, info, oldset, regs);
984 else
985 setup_frame(sig, ka, oldset, regs);
986
987 if (ka->sa.sa_flags & SA_ONESHOT)
988 ka->sa.sa_handler = SIG_DFL;
989
990 sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
991 if (!(ka->sa.sa_flags & SA_NODEFER))
992 sigaddset(&current->blocked,sig);
993 recalc_sigpending();
994}
995
996/*
997 * Note that 'init' is a special process: it doesn't get signals it doesn't
998 * want to handle. Thus you cannot kill init even with a SIGKILL even by
999 * mistake.
1000 */
1001asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs)
1002{
1003 siginfo_t info;
1004 struct k_sigaction ka;
1005 int signr;
1006
1007 current->thread.esp0 = (unsigned long) regs;
1008
1009 if (!oldset)
1010 oldset = &current->blocked;
1011
1012 signr = get_signal_to_deliver(&info, &ka, regs, NULL);
1013 if (signr > 0) {
1014 /* Whee! Actually deliver the signal. */
1015 handle_signal(signr, &ka, &info, oldset, regs);
1016 return 1;
1017 }
1018
1019 /* Did we come from a system call? */
1020 if (regs->orig_d0 >= 0)
1021 /* Restart the system call - no handlers present */
1022 handle_restart(regs, NULL, 0);
1023
1024 return 0;
1025}
diff --git a/arch/m68k/kernel/sun3-head.S b/arch/m68k/kernel/sun3-head.S
new file mode 100644
index 000000000000..bffd69a4a1ab
--- /dev/null
+++ b/arch/m68k/kernel/sun3-head.S
@@ -0,0 +1,104 @@
1#include <linux/linkage.h>
2
3#include <asm/entry.h>
4#include <asm/page.h>
5#include <asm/contregs.h>
6#include <asm/sun3-head.h>
7
8PSL_HIGHIPL = 0x2700
9NBSG = 0x20000
10ICACHE_ONLY = 0x00000009
11CACHES_OFF = 0x00000008 | actually a clear and disable --m
12#define MAS_STACK INT_STACK
13ROOT_TABLE_SIZE = 128
14PAGESIZE = 8192
15SUN3_INVALID_PMEG = 255
16.globl bootup_user_stack
17.globl bootup_kernel_stack
18.globl pg0
19.globl swapper_pg_dir
20.globl kernel_pmd_table
21.globl availmem
22.global m68k_pgtable_cachemode
23.global kpt
24| todo: all these should be in bss!
25swapper_pg_dir: .skip 0x2000
26pg0: .skip 0x2000
27kernel_pmd_table: .skip 0x2000
28
29.globl kernel_pg_dir
30.equ kernel_pg_dir,kernel_pmd_table
31
32 .section .head
33ENTRY(_stext)
34ENTRY(_start)
35
36/* Firstly, disable interrupts and set up function codes. */
37 movew #PSL_HIGHIPL, %sr
38 moveq #FC_CONTROL, %d0
39 movec %d0, %sfc
40 movec %d0, %dfc
41
42/* Make sure we're in context zero. */
43 moveq #0, %d0
44 movsb %d0, AC_CONTEXT
45
46/* map everything the bootloader left us into high memory, clean up the
47 excess later */
48 lea (AC_SEGMAP+0),%a0
49 lea (AC_SEGMAP+KERNBASE),%a1
501:
51 movsb %a0@, %d1
52 movsb %d1, %a1@
53 cmpib #SUN3_INVALID_PMEG, %d1
54 beq 2f
55 addl #NBSG,%a0
56 addl #NBSG,%a1
57 jmp 1b
58
592:
60
61/* Disable caches and jump to high code. */
62 moveq #ICACHE_ONLY,%d0 | Cache disabled until we're ready to enable it
63 movc %d0, %cacr | is this the right value? (yes --m)
64 jmp 1f:l
65
66/* Following code executes at high addresses (0xE000xxx). */
671: lea init_task,%curptr | get initial thread...
68 lea init_thread_union+THREAD_SIZE,%sp | ...and its stack.
69
70/* copy bootinfo records from the loader to _end */
71 lea _end, %a1
72 lea BI_START, %a0
73 /* number of longs to copy */
74 movel %a0@, %d0
751: addl #4, %a0
76 movel %a0@, %a1@
77 addl #4, %a1
78 dbf %d0, 1b
79
80/* Point MSP at an invalid page to trap if it's used. --m */
81 movl #(PAGESIZE),%d0
82 movc %d0,%msp
83 moveq #-1,%d0
84 movsb %d0,(AC_SEGMAP+0x0)
85
86 jbsr sun3_init
87
88 jbsr base_trap_init
89
90 jbsr start_kernel
91 trap #15
92
93 .data
94 .even
95kpt:
96 .long 0
97availmem:
98 .long 0
99| todo: remove next two. --m
100is_medusa:
101 .long 0
102m68k_pgtable_cachemode:
103 .long 0
104
diff --git a/arch/m68k/kernel/sys_m68k.c b/arch/m68k/kernel/sys_m68k.c
new file mode 100644
index 000000000000..2ed7b783f654
--- /dev/null
+++ b/arch/m68k/kernel/sys_m68k.c
@@ -0,0 +1,671 @@
1/*
2 * linux/arch/m68k/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/page.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
115#if 0
116struct mmap_arg_struct64 {
117 __u32 addr;
118 __u32 len;
119 __u32 prot;
120 __u32 flags;
121 __u64 offset; /* 64 bits */
122 __u32 fd;
123};
124
125asmlinkage long sys_mmap64(struct mmap_arg_struct64 *arg)
126{
127 int error = -EFAULT;
128 struct file * file = NULL;
129 struct mmap_arg_struct64 a;
130 unsigned long pgoff;
131
132 if (copy_from_user(&a, arg, sizeof(a)))
133 return -EFAULT;
134
135 if ((long)a.offset & ~PAGE_MASK)
136 return -EINVAL;
137
138 pgoff = a.offset >> PAGE_SHIFT;
139 if ((a.offset >> PAGE_SHIFT) != pgoff)
140 return -EINVAL;
141
142 if (!(a.flags & MAP_ANONYMOUS)) {
143 error = -EBADF;
144 file = fget(a.fd);
145 if (!file)
146 goto out;
147 }
148 a.flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
149
150 down_write(&current->mm->mmap_sem);
151 error = do_mmap_pgoff(file, a.addr, a.len, a.prot, a.flags, pgoff);
152 up_write(&current->mm->mmap_sem);
153 if (file)
154 fput(file);
155out:
156 return error;
157}
158#endif
159
160struct sel_arg_struct {
161 unsigned long n;
162 fd_set *inp, *outp, *exp;
163 struct timeval *tvp;
164};
165
166asmlinkage int old_select(struct sel_arg_struct *arg)
167{
168 struct sel_arg_struct a;
169
170 if (copy_from_user(&a, arg, sizeof(a)))
171 return -EFAULT;
172 /* sys_select() does the appropriate kernel locking */
173 return sys_select(a.n, a.inp, a.outp, a.exp, a.tvp);
174}
175
176/*
177 * sys_ipc() is the de-multiplexer for the SysV IPC calls..
178 *
179 * This is really horribly ugly.
180 */
181asmlinkage int sys_ipc (uint call, int first, int second,
182 int third, void *ptr, long fifth)
183{
184 int version, ret;
185
186 version = call >> 16; /* hack for backward compatibility */
187 call &= 0xffff;
188
189 if (call <= SEMCTL)
190 switch (call) {
191 case SEMOP:
192 return sys_semop (first, (struct sembuf *)ptr, second);
193 case SEMGET:
194 return sys_semget (first, second, third);
195 case SEMCTL: {
196 union semun fourth;
197 if (!ptr)
198 return -EINVAL;
199 if (get_user(fourth.__pad, (void **) ptr))
200 return -EFAULT;
201 return sys_semctl (first, second, third, fourth);
202 }
203 default:
204 return -ENOSYS;
205 }
206 if (call <= MSGCTL)
207 switch (call) {
208 case MSGSND:
209 return sys_msgsnd (first, (struct msgbuf *) ptr,
210 second, third);
211 case MSGRCV:
212 switch (version) {
213 case 0: {
214 struct ipc_kludge tmp;
215 if (!ptr)
216 return -EINVAL;
217 if (copy_from_user (&tmp,
218 (struct ipc_kludge *)ptr,
219 sizeof (tmp)))
220 return -EFAULT;
221 return sys_msgrcv (first, tmp.msgp, second,
222 tmp.msgtyp, third);
223 }
224 default:
225 return sys_msgrcv (first,
226 (struct msgbuf *) ptr,
227 second, fifth, third);
228 }
229 case MSGGET:
230 return sys_msgget ((key_t) first, second);
231 case MSGCTL:
232 return sys_msgctl (first, second,
233 (struct msqid_ds *) ptr);
234 default:
235 return -ENOSYS;
236 }
237 if (call <= SHMCTL)
238 switch (call) {
239 case SHMAT:
240 switch (version) {
241 default: {
242 ulong raddr;
243 ret = do_shmat (first, (char *) ptr,
244 second, &raddr);
245 if (ret)
246 return ret;
247 return put_user (raddr, (ulong *) third);
248 }
249 }
250 case SHMDT:
251 return sys_shmdt ((char *)ptr);
252 case SHMGET:
253 return sys_shmget (first, second, third);
254 case SHMCTL:
255 return sys_shmctl (first, second,
256 (struct shmid_ds *) ptr);
257 default:
258 return -ENOSYS;
259 }
260
261 return -EINVAL;
262}
263
264/* Convert virtual (user) address VADDR to physical address PADDR */
265#define virt_to_phys_040(vaddr) \
266({ \
267 unsigned long _mmusr, _paddr; \
268 \
269 __asm__ __volatile__ (".chip 68040\n\t" \
270 "ptestr (%1)\n\t" \
271 "movec %%mmusr,%0\n\t" \
272 ".chip 68k" \
273 : "=r" (_mmusr) \
274 : "a" (vaddr)); \
275 _paddr = (_mmusr & MMU_R_040) ? (_mmusr & PAGE_MASK) : 0; \
276 _paddr; \
277})
278
279static inline int
280cache_flush_040 (unsigned long addr, int scope, int cache, unsigned long len)
281{
282 unsigned long paddr, i;
283
284 switch (scope)
285 {
286 case FLUSH_SCOPE_ALL:
287 switch (cache)
288 {
289 case FLUSH_CACHE_DATA:
290 /* This nop is needed for some broken versions of the 68040. */
291 __asm__ __volatile__ ("nop\n\t"
292 ".chip 68040\n\t"
293 "cpusha %dc\n\t"
294 ".chip 68k");
295 break;
296 case FLUSH_CACHE_INSN:
297 __asm__ __volatile__ ("nop\n\t"
298 ".chip 68040\n\t"
299 "cpusha %ic\n\t"
300 ".chip 68k");
301 break;
302 default:
303 case FLUSH_CACHE_BOTH:
304 __asm__ __volatile__ ("nop\n\t"
305 ".chip 68040\n\t"
306 "cpusha %bc\n\t"
307 ".chip 68k");
308 break;
309 }
310 break;
311
312 case FLUSH_SCOPE_LINE:
313 /* Find the physical address of the first mapped page in the
314 address range. */
315 if ((paddr = virt_to_phys_040(addr))) {
316 paddr += addr & ~(PAGE_MASK | 15);
317 len = (len + (addr & 15) + 15) >> 4;
318 } else {
319 unsigned long tmp = PAGE_SIZE - (addr & ~PAGE_MASK);
320
321 if (len <= tmp)
322 return 0;
323 addr += tmp;
324 len -= tmp;
325 tmp = PAGE_SIZE;
326 for (;;)
327 {
328 if ((paddr = virt_to_phys_040(addr)))
329 break;
330 if (len <= tmp)
331 return 0;
332 addr += tmp;
333 len -= tmp;
334 }
335 len = (len + 15) >> 4;
336 }
337 i = (PAGE_SIZE - (paddr & ~PAGE_MASK)) >> 4;
338 while (len--)
339 {
340 switch (cache)
341 {
342 case FLUSH_CACHE_DATA:
343 __asm__ __volatile__ ("nop\n\t"
344 ".chip 68040\n\t"
345 "cpushl %%dc,(%0)\n\t"
346 ".chip 68k"
347 : : "a" (paddr));
348 break;
349 case FLUSH_CACHE_INSN:
350 __asm__ __volatile__ ("nop\n\t"
351 ".chip 68040\n\t"
352 "cpushl %%ic,(%0)\n\t"
353 ".chip 68k"
354 : : "a" (paddr));
355 break;
356 default:
357 case FLUSH_CACHE_BOTH:
358 __asm__ __volatile__ ("nop\n\t"
359 ".chip 68040\n\t"
360 "cpushl %%bc,(%0)\n\t"
361 ".chip 68k"
362 : : "a" (paddr));
363 break;
364 }
365 if (!--i && len)
366 {
367 /*
368 * No need to page align here since it is done by
369 * virt_to_phys_040().
370 */
371 addr += PAGE_SIZE;
372 i = PAGE_SIZE / 16;
373 /* Recompute physical address when crossing a page
374 boundary. */
375 for (;;)
376 {
377 if ((paddr = virt_to_phys_040(addr)))
378 break;
379 if (len <= i)
380 return 0;
381 len -= i;
382 addr += PAGE_SIZE;
383 }
384 }
385 else
386 paddr += 16;
387 }
388 break;
389
390 default:
391 case FLUSH_SCOPE_PAGE:
392 len += (addr & ~PAGE_MASK) + (PAGE_SIZE - 1);
393 for (len >>= PAGE_SHIFT; len--; addr += PAGE_SIZE)
394 {
395 if (!(paddr = virt_to_phys_040(addr)))
396 continue;
397 switch (cache)
398 {
399 case FLUSH_CACHE_DATA:
400 __asm__ __volatile__ ("nop\n\t"
401 ".chip 68040\n\t"
402 "cpushp %%dc,(%0)\n\t"
403 ".chip 68k"
404 : : "a" (paddr));
405 break;
406 case FLUSH_CACHE_INSN:
407 __asm__ __volatile__ ("nop\n\t"
408 ".chip 68040\n\t"
409 "cpushp %%ic,(%0)\n\t"
410 ".chip 68k"
411 : : "a" (paddr));
412 break;
413 default:
414 case FLUSH_CACHE_BOTH:
415 __asm__ __volatile__ ("nop\n\t"
416 ".chip 68040\n\t"
417 "cpushp %%bc,(%0)\n\t"
418 ".chip 68k"
419 : : "a" (paddr));
420 break;
421 }
422 }
423 break;
424 }
425 return 0;
426}
427
428#define virt_to_phys_060(vaddr) \
429({ \
430 unsigned long paddr; \
431 __asm__ __volatile__ (".chip 68060\n\t" \
432 "plpar (%0)\n\t" \
433 ".chip 68k" \
434 : "=a" (paddr) \
435 : "0" (vaddr)); \
436 (paddr); /* XXX */ \
437})
438
439static inline int
440cache_flush_060 (unsigned long addr, int scope, int cache, unsigned long len)
441{
442 unsigned long paddr, i;
443
444 /*
445 * 68060 manual says:
446 * cpush %dc : flush DC, remains valid (with our %cacr setup)
447 * cpush %ic : invalidate IC
448 * cpush %bc : flush DC + invalidate IC
449 */
450 switch (scope)
451 {
452 case FLUSH_SCOPE_ALL:
453 switch (cache)
454 {
455 case FLUSH_CACHE_DATA:
456 __asm__ __volatile__ (".chip 68060\n\t"
457 "cpusha %dc\n\t"
458 ".chip 68k");
459 break;
460 case FLUSH_CACHE_INSN:
461 __asm__ __volatile__ (".chip 68060\n\t"
462 "cpusha %ic\n\t"
463 ".chip 68k");
464 break;
465 default:
466 case FLUSH_CACHE_BOTH:
467 __asm__ __volatile__ (".chip 68060\n\t"
468 "cpusha %bc\n\t"
469 ".chip 68k");
470 break;
471 }
472 break;
473
474 case FLUSH_SCOPE_LINE:
475 /* Find the physical address of the first mapped page in the
476 address range. */
477 len += addr & 15;
478 addr &= -16;
479 if (!(paddr = virt_to_phys_060(addr))) {
480 unsigned long tmp = PAGE_SIZE - (addr & ~PAGE_MASK);
481
482 if (len <= tmp)
483 return 0;
484 addr += tmp;
485 len -= tmp;
486 tmp = PAGE_SIZE;
487 for (;;)
488 {
489 if ((paddr = virt_to_phys_060(addr)))
490 break;
491 if (len <= tmp)
492 return 0;
493 addr += tmp;
494 len -= tmp;
495 }
496 }
497 len = (len + 15) >> 4;
498 i = (PAGE_SIZE - (paddr & ~PAGE_MASK)) >> 4;
499 while (len--)
500 {
501 switch (cache)
502 {
503 case FLUSH_CACHE_DATA:
504 __asm__ __volatile__ (".chip 68060\n\t"
505 "cpushl %%dc,(%0)\n\t"
506 ".chip 68k"
507 : : "a" (paddr));
508 break;
509 case FLUSH_CACHE_INSN:
510 __asm__ __volatile__ (".chip 68060\n\t"
511 "cpushl %%ic,(%0)\n\t"
512 ".chip 68k"
513 : : "a" (paddr));
514 break;
515 default:
516 case FLUSH_CACHE_BOTH:
517 __asm__ __volatile__ (".chip 68060\n\t"
518 "cpushl %%bc,(%0)\n\t"
519 ".chip 68k"
520 : : "a" (paddr));
521 break;
522 }
523 if (!--i && len)
524 {
525
526 /*
527 * We just want to jump to the first cache line
528 * in the next page.
529 */
530 addr += PAGE_SIZE;
531 addr &= PAGE_MASK;
532
533 i = PAGE_SIZE / 16;
534 /* Recompute physical address when crossing a page
535 boundary. */
536 for (;;)
537 {
538 if ((paddr = virt_to_phys_060(addr)))
539 break;
540 if (len <= i)
541 return 0;
542 len -= i;
543 addr += PAGE_SIZE;
544 }
545 }
546 else
547 paddr += 16;
548 }
549 break;
550
551 default:
552 case FLUSH_SCOPE_PAGE:
553 len += (addr & ~PAGE_MASK) + (PAGE_SIZE - 1);
554 addr &= PAGE_MASK; /* Workaround for bug in some
555 revisions of the 68060 */
556 for (len >>= PAGE_SHIFT; len--; addr += PAGE_SIZE)
557 {
558 if (!(paddr = virt_to_phys_060(addr)))
559 continue;
560 switch (cache)
561 {
562 case FLUSH_CACHE_DATA:
563 __asm__ __volatile__ (".chip 68060\n\t"
564 "cpushp %%dc,(%0)\n\t"
565 ".chip 68k"
566 : : "a" (paddr));
567 break;
568 case FLUSH_CACHE_INSN:
569 __asm__ __volatile__ (".chip 68060\n\t"
570 "cpushp %%ic,(%0)\n\t"
571 ".chip 68k"
572 : : "a" (paddr));
573 break;
574 default:
575 case FLUSH_CACHE_BOTH:
576 __asm__ __volatile__ (".chip 68060\n\t"
577 "cpushp %%bc,(%0)\n\t"
578 ".chip 68k"
579 : : "a" (paddr));
580 break;
581 }
582 }
583 break;
584 }
585 return 0;
586}
587
588/* sys_cacheflush -- flush (part of) the processor cache. */
589asmlinkage int
590sys_cacheflush (unsigned long addr, int scope, int cache, unsigned long len)
591{
592 struct vm_area_struct *vma;
593 int ret = -EINVAL;
594
595 lock_kernel();
596 if (scope < FLUSH_SCOPE_LINE || scope > FLUSH_SCOPE_ALL ||
597 cache & ~FLUSH_CACHE_BOTH)
598 goto out;
599
600 if (scope == FLUSH_SCOPE_ALL) {
601 /* Only the superuser may explicitly flush the whole cache. */
602 ret = -EPERM;
603 if (!capable(CAP_SYS_ADMIN))
604 goto out;
605 } else {
606 /*
607 * Verify that the specified address region actually belongs
608 * to this process.
609 */
610 vma = find_vma (current->mm, addr);
611 ret = -EINVAL;
612 /* Check for overflow. */
613 if (addr + len < addr)
614 goto out;
615 if (vma == NULL || addr < vma->vm_start || addr + len > vma->vm_end)
616 goto out;
617 }
618
619 if (CPU_IS_020_OR_030) {
620 if (scope == FLUSH_SCOPE_LINE && len < 256) {
621 unsigned long cacr;
622 __asm__ ("movec %%cacr, %0" : "=r" (cacr));
623 if (cache & FLUSH_CACHE_INSN)
624 cacr |= 4;
625 if (cache & FLUSH_CACHE_DATA)
626 cacr |= 0x400;
627 len >>= 2;
628 while (len--) {
629 __asm__ __volatile__ ("movec %1, %%caar\n\t"
630 "movec %0, %%cacr"
631 : /* no outputs */
632 : "r" (cacr), "r" (addr));
633 addr += 4;
634 }
635 } else {
636 /* Flush the whole cache, even if page granularity requested. */
637 unsigned long cacr;
638 __asm__ ("movec %%cacr, %0" : "=r" (cacr));
639 if (cache & FLUSH_CACHE_INSN)
640 cacr |= 8;
641 if (cache & FLUSH_CACHE_DATA)
642 cacr |= 0x800;
643 __asm__ __volatile__ ("movec %0, %%cacr" : : "r" (cacr));
644 }
645 ret = 0;
646 goto out;
647 } else {
648 /*
649 * 040 or 060: don't blindly trust 'scope', someone could
650 * try to flush a few megs of memory.
651 */
652
653 if (len>=3*PAGE_SIZE && scope<FLUSH_SCOPE_PAGE)
654 scope=FLUSH_SCOPE_PAGE;
655 if (len>=10*PAGE_SIZE && scope<FLUSH_SCOPE_ALL)
656 scope=FLUSH_SCOPE_ALL;
657 if (CPU_IS_040) {
658 ret = cache_flush_040 (addr, scope, cache, len);
659 } else if (CPU_IS_060) {
660 ret = cache_flush_060 (addr, scope, cache, len);
661 }
662 }
663out:
664 unlock_kernel();
665 return ret;
666}
667
668asmlinkage int sys_getpagesize(void)
669{
670 return PAGE_SIZE;
671}
diff --git a/arch/m68k/kernel/time.c b/arch/m68k/kernel/time.c
new file mode 100644
index 000000000000..e47e19588525
--- /dev/null
+++ b/arch/m68k/kernel/time.c
@@ -0,0 +1,187 @@
1/*
2 * linux/arch/m68k/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> /* CONFIG_HEARTBEAT */
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/rtc.h>
22
23#include <asm/machdep.h>
24#include <asm/io.h>
25
26#include <linux/time.h>
27#include <linux/timex.h>
28#include <linux/profile.h>
29
30u64 jiffies_64 = INITIAL_JIFFIES;
31
32EXPORT_SYMBOL(jiffies_64);
33
34static inline int set_rtc_mmss(unsigned long nowtime)
35{
36 if (mach_set_clock_mmss)
37 return mach_set_clock_mmss (nowtime);
38 return -1;
39}
40
41/*
42 * timer_interrupt() needs to keep up the real-time clock,
43 * as well as call the "do_timer()" routine every clocktick
44 */
45static irqreturn_t timer_interrupt(int irq, void *dummy, struct pt_regs * regs)
46{
47 do_timer(regs);
48#ifndef CONFIG_SMP
49 update_process_times(user_mode(regs));
50#endif
51 profile_tick(CPU_PROFILING, regs);
52
53#ifdef CONFIG_HEARTBEAT
54 /* use power LED as a heartbeat instead -- much more useful
55 for debugging -- based on the version for PReP by Cort */
56 /* acts like an actual heart beat -- ie thump-thump-pause... */
57 if (mach_heartbeat) {
58 static unsigned cnt = 0, period = 0, dist = 0;
59
60 if (cnt == 0 || cnt == dist)
61 mach_heartbeat( 1 );
62 else if (cnt == 7 || cnt == dist+7)
63 mach_heartbeat( 0 );
64
65 if (++cnt > period) {
66 cnt = 0;
67 /* The hyperbolic function below modifies the heartbeat period
68 * length in dependency of the current (5min) load. It goes
69 * through the points f(0)=126, f(1)=86, f(5)=51,
70 * f(inf)->30. */
71 period = ((672<<FSHIFT)/(5*avenrun[0]+(7<<FSHIFT))) + 30;
72 dist = period / 4;
73 }
74 }
75#endif /* CONFIG_HEARTBEAT */
76 return IRQ_HANDLED;
77}
78
79void time_init(void)
80{
81 struct rtc_time time;
82
83 if (mach_hwclk) {
84 mach_hwclk(0, &time);
85
86 if ((time.tm_year += 1900) < 1970)
87 time.tm_year += 100;
88 xtime.tv_sec = mktime(time.tm_year, time.tm_mon, time.tm_mday,
89 time.tm_hour, time.tm_min, time.tm_sec);
90 xtime.tv_nsec = 0;
91 }
92 wall_to_monotonic.tv_sec = -xtime.tv_sec;
93
94 mach_sched_init(timer_interrupt);
95}
96
97/*
98 * This version of gettimeofday has near microsecond resolution.
99 */
100void do_gettimeofday(struct timeval *tv)
101{
102 unsigned long flags;
103 extern unsigned long wall_jiffies;
104 unsigned long seq;
105 unsigned long usec, sec, lost;
106 unsigned long max_ntp_tick = tick_usec - tickadj;
107
108 do {
109 seq = read_seqbegin_irqsave(&xtime_lock, flags);
110
111 usec = mach_gettimeoffset();
112 lost = jiffies - wall_jiffies;
113
114 /*
115 * If time_adjust is negative then NTP is slowing the clock
116 * so make sure not to go into next possible interval.
117 * Better to lose some accuracy than have time go backwards..
118 */
119 if (unlikely(time_adjust < 0)) {
120 usec = min(usec, max_ntp_tick);
121
122 if (lost)
123 usec += lost * max_ntp_tick;
124 }
125 else if (unlikely(lost))
126 usec += lost * tick_usec;
127
128 sec = xtime.tv_sec;
129 usec += xtime.tv_nsec/1000;
130 } while (read_seqretry_irqrestore(&xtime_lock, seq, flags));
131
132
133 while (usec >= 1000000) {
134 usec -= 1000000;
135 sec++;
136 }
137
138 tv->tv_sec = sec;
139 tv->tv_usec = usec;
140}
141
142EXPORT_SYMBOL(do_gettimeofday);
143
144int do_settimeofday(struct timespec *tv)
145{
146 time_t wtm_sec, sec = tv->tv_sec;
147 long wtm_nsec, nsec = tv->tv_nsec;
148 extern unsigned long wall_jiffies;
149
150 if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC)
151 return -EINVAL;
152
153 write_seqlock_irq(&xtime_lock);
154 /* This is revolting. We need to set the xtime.tv_nsec
155 * correctly. However, the value in this location is
156 * is value at the last tick.
157 * Discover what correction gettimeofday
158 * would have done, and then undo it!
159 */
160 nsec -= 1000 * (mach_gettimeoffset() +
161 (jiffies - wall_jiffies) * (1000000 / HZ));
162
163 wtm_sec = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec);
164 wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec);
165
166 set_normalized_timespec(&xtime, sec, nsec);
167 set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
168
169 time_adjust = 0; /* stop active adjtime() */
170 time_status |= STA_UNSYNC;
171 time_maxerror = NTP_PHASE_LIMIT;
172 time_esterror = NTP_PHASE_LIMIT;
173 write_sequnlock_irq(&xtime_lock);
174 clock_was_set();
175 return 0;
176}
177
178EXPORT_SYMBOL(do_settimeofday);
179
180/*
181 * Scheduler clock - returns current time in ns units.
182 */
183unsigned long long sched_clock(void)
184{
185 return (unsigned long long)jiffies*(1000000000/HZ);
186}
187
diff --git a/arch/m68k/kernel/traps.c b/arch/m68k/kernel/traps.c
new file mode 100644
index 000000000000..deb36e8b04a2
--- /dev/null
+++ b/arch/m68k/kernel/traps.c
@@ -0,0 +1,1227 @@
1/*
2 * linux/arch/m68k/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 * 68040 fixes and writeback by Richard Zidlicky
9 * 68060 fixes by Roman Hodek
10 * 68060 fixes by Jesper Skov
11 *
12 * This file is subject to the terms and conditions of the GNU General Public
13 * License. See the file COPYING in the main directory of this archive
14 * for more details.
15 */
16
17/*
18 * Sets up all exception vectors
19 */
20
21#include <linux/config.h>
22#include <linux/sched.h>
23#include <linux/signal.h>
24#include <linux/kernel.h>
25#include <linux/mm.h>
26#include <linux/module.h>
27#include <linux/a.out.h>
28#include <linux/user.h>
29#include <linux/string.h>
30#include <linux/linkage.h>
31#include <linux/init.h>
32#include <linux/ptrace.h>
33#include <linux/kallsyms.h>
34
35#include <asm/setup.h>
36#include <asm/fpu.h>
37#include <asm/system.h>
38#include <asm/uaccess.h>
39#include <asm/traps.h>
40#include <asm/pgalloc.h>
41#include <asm/machdep.h>
42#include <asm/siginfo.h>
43
44/* assembler routines */
45asmlinkage void system_call(void);
46asmlinkage void buserr(void);
47asmlinkage void trap(void);
48asmlinkage void inthandler(void);
49asmlinkage void nmihandler(void);
50#ifdef CONFIG_M68KFPU_EMU
51asmlinkage void fpu_emu(void);
52#endif
53
54e_vector vectors[256] = {
55 [VEC_BUSERR] = buserr,
56 [VEC_ADDRERR] = trap,
57 [VEC_ILLEGAL] = trap,
58 [VEC_ZERODIV] = trap,
59 [VEC_CHK] = trap,
60 [VEC_TRAP] = trap,
61 [VEC_PRIV] = trap,
62 [VEC_TRACE] = trap,
63 [VEC_LINE10] = trap,
64 [VEC_LINE11] = trap,
65 [VEC_RESV12] = trap,
66 [VEC_COPROC] = trap,
67 [VEC_FORMAT] = trap,
68 [VEC_UNINT] = trap,
69 [VEC_RESV16] = trap,
70 [VEC_RESV17] = trap,
71 [VEC_RESV18] = trap,
72 [VEC_RESV19] = trap,
73 [VEC_RESV20] = trap,
74 [VEC_RESV21] = trap,
75 [VEC_RESV22] = trap,
76 [VEC_RESV23] = trap,
77 [VEC_SPUR] = inthandler,
78 [VEC_INT1] = inthandler,
79 [VEC_INT2] = inthandler,
80 [VEC_INT3] = inthandler,
81 [VEC_INT4] = inthandler,
82 [VEC_INT5] = inthandler,
83 [VEC_INT6] = inthandler,
84 [VEC_INT7] = inthandler,
85 [VEC_SYS] = system_call,
86 [VEC_TRAP1] = trap,
87 [VEC_TRAP2] = trap,
88 [VEC_TRAP3] = trap,
89 [VEC_TRAP4] = trap,
90 [VEC_TRAP5] = trap,
91 [VEC_TRAP6] = trap,
92 [VEC_TRAP7] = trap,
93 [VEC_TRAP8] = trap,
94 [VEC_TRAP9] = trap,
95 [VEC_TRAP10] = trap,
96 [VEC_TRAP11] = trap,
97 [VEC_TRAP12] = trap,
98 [VEC_TRAP13] = trap,
99 [VEC_TRAP14] = trap,
100 [VEC_TRAP15] = trap,
101};
102
103/* nmi handler for the Amiga */
104asm(".text\n"
105 __ALIGN_STR "\n"
106 "nmihandler: rte");
107
108/*
109 * this must be called very early as the kernel might
110 * use some instruction that are emulated on the 060
111 */
112void __init base_trap_init(void)
113{
114 if(MACH_IS_SUN3X) {
115 extern e_vector *sun3x_prom_vbr;
116
117 __asm__ volatile ("movec %%vbr, %0" : "=r" ((void*)sun3x_prom_vbr));
118 }
119
120 /* setup the exception vector table */
121 __asm__ volatile ("movec %0,%%vbr" : : "r" ((void*)vectors));
122
123 if (CPU_IS_060) {
124 /* set up ISP entry points */
125 asmlinkage void unimp_vec(void) asm ("_060_isp_unimp");
126
127 vectors[VEC_UNIMPII] = unimp_vec;
128 }
129}
130
131void __init trap_init (void)
132{
133 int i;
134
135 for (i = 48; i < 64; i++)
136 if (!vectors[i])
137 vectors[i] = trap;
138
139 for (i = 64; i < 256; i++)
140 vectors[i] = inthandler;
141
142#ifdef CONFIG_M68KFPU_EMU
143 if (FPU_IS_EMU)
144 vectors[VEC_LINE11] = fpu_emu;
145#endif
146
147 if (CPU_IS_040 && !FPU_IS_EMU) {
148 /* set up FPSP entry points */
149 asmlinkage void dz_vec(void) asm ("dz");
150 asmlinkage void inex_vec(void) asm ("inex");
151 asmlinkage void ovfl_vec(void) asm ("ovfl");
152 asmlinkage void unfl_vec(void) asm ("unfl");
153 asmlinkage void snan_vec(void) asm ("snan");
154 asmlinkage void operr_vec(void) asm ("operr");
155 asmlinkage void bsun_vec(void) asm ("bsun");
156 asmlinkage void fline_vec(void) asm ("fline");
157 asmlinkage void unsupp_vec(void) asm ("unsupp");
158
159 vectors[VEC_FPDIVZ] = dz_vec;
160 vectors[VEC_FPIR] = inex_vec;
161 vectors[VEC_FPOVER] = ovfl_vec;
162 vectors[VEC_FPUNDER] = unfl_vec;
163 vectors[VEC_FPNAN] = snan_vec;
164 vectors[VEC_FPOE] = operr_vec;
165 vectors[VEC_FPBRUC] = bsun_vec;
166 vectors[VEC_LINE11] = fline_vec;
167 vectors[VEC_FPUNSUP] = unsupp_vec;
168 }
169
170 if (CPU_IS_060 && !FPU_IS_EMU) {
171 /* set up IFPSP entry points */
172 asmlinkage void snan_vec(void) asm ("_060_fpsp_snan");
173 asmlinkage void operr_vec(void) asm ("_060_fpsp_operr");
174 asmlinkage void ovfl_vec(void) asm ("_060_fpsp_ovfl");
175 asmlinkage void unfl_vec(void) asm ("_060_fpsp_unfl");
176 asmlinkage void dz_vec(void) asm ("_060_fpsp_dz");
177 asmlinkage void inex_vec(void) asm ("_060_fpsp_inex");
178 asmlinkage void fline_vec(void) asm ("_060_fpsp_fline");
179 asmlinkage void unsupp_vec(void) asm ("_060_fpsp_unsupp");
180 asmlinkage void effadd_vec(void) asm ("_060_fpsp_effadd");
181
182 vectors[VEC_FPNAN] = snan_vec;
183 vectors[VEC_FPOE] = operr_vec;
184 vectors[VEC_FPOVER] = ovfl_vec;
185 vectors[VEC_FPUNDER] = unfl_vec;
186 vectors[VEC_FPDIVZ] = dz_vec;
187 vectors[VEC_FPIR] = inex_vec;
188 vectors[VEC_LINE11] = fline_vec;
189 vectors[VEC_FPUNSUP] = unsupp_vec;
190 vectors[VEC_UNIMPEA] = effadd_vec;
191 }
192
193 /* if running on an amiga, make the NMI interrupt do nothing */
194 if (MACH_IS_AMIGA) {
195 vectors[VEC_INT7] = nmihandler;
196 }
197}
198
199
200static const char *vec_names[] = {
201 [VEC_RESETSP] = "RESET SP",
202 [VEC_RESETPC] = "RESET PC",
203 [VEC_BUSERR] = "BUS ERROR",
204 [VEC_ADDRERR] = "ADDRESS ERROR",
205 [VEC_ILLEGAL] = "ILLEGAL INSTRUCTION",
206 [VEC_ZERODIV] = "ZERO DIVIDE",
207 [VEC_CHK] = "CHK",
208 [VEC_TRAP] = "TRAPcc",
209 [VEC_PRIV] = "PRIVILEGE VIOLATION",
210 [VEC_TRACE] = "TRACE",
211 [VEC_LINE10] = "LINE 1010",
212 [VEC_LINE11] = "LINE 1111",
213 [VEC_RESV12] = "UNASSIGNED RESERVED 12",
214 [VEC_COPROC] = "COPROCESSOR PROTOCOL VIOLATION",
215 [VEC_FORMAT] = "FORMAT ERROR",
216 [VEC_UNINT] = "UNINITIALIZED INTERRUPT",
217 [VEC_RESV16] = "UNASSIGNED RESERVED 16",
218 [VEC_RESV17] = "UNASSIGNED RESERVED 17",
219 [VEC_RESV18] = "UNASSIGNED RESERVED 18",
220 [VEC_RESV19] = "UNASSIGNED RESERVED 19",
221 [VEC_RESV20] = "UNASSIGNED RESERVED 20",
222 [VEC_RESV21] = "UNASSIGNED RESERVED 21",
223 [VEC_RESV22] = "UNASSIGNED RESERVED 22",
224 [VEC_RESV23] = "UNASSIGNED RESERVED 23",
225 [VEC_SPUR] = "SPURIOUS INTERRUPT",
226 [VEC_INT1] = "LEVEL 1 INT",
227 [VEC_INT2] = "LEVEL 2 INT",
228 [VEC_INT3] = "LEVEL 3 INT",
229 [VEC_INT4] = "LEVEL 4 INT",
230 [VEC_INT5] = "LEVEL 5 INT",
231 [VEC_INT6] = "LEVEL 6 INT",
232 [VEC_INT7] = "LEVEL 7 INT",
233 [VEC_SYS] = "SYSCALL",
234 [VEC_TRAP1] = "TRAP #1",
235 [VEC_TRAP2] = "TRAP #2",
236 [VEC_TRAP3] = "TRAP #3",
237 [VEC_TRAP4] = "TRAP #4",
238 [VEC_TRAP5] = "TRAP #5",
239 [VEC_TRAP6] = "TRAP #6",
240 [VEC_TRAP7] = "TRAP #7",
241 [VEC_TRAP8] = "TRAP #8",
242 [VEC_TRAP9] = "TRAP #9",
243 [VEC_TRAP10] = "TRAP #10",
244 [VEC_TRAP11] = "TRAP #11",
245 [VEC_TRAP12] = "TRAP #12",
246 [VEC_TRAP13] = "TRAP #13",
247 [VEC_TRAP14] = "TRAP #14",
248 [VEC_TRAP15] = "TRAP #15",
249 [VEC_FPBRUC] = "FPCP BSUN",
250 [VEC_FPIR] = "FPCP INEXACT",
251 [VEC_FPDIVZ] = "FPCP DIV BY 0",
252 [VEC_FPUNDER] = "FPCP UNDERFLOW",
253 [VEC_FPOE] = "FPCP OPERAND ERROR",
254 [VEC_FPOVER] = "FPCP OVERFLOW",
255 [VEC_FPNAN] = "FPCP SNAN",
256 [VEC_FPUNSUP] = "FPCP UNSUPPORTED OPERATION",
257 [VEC_MMUCFG] = "MMU CONFIGURATION ERROR",
258 [VEC_MMUILL] = "MMU ILLEGAL OPERATION ERROR",
259 [VEC_MMUACC] = "MMU ACCESS LEVEL VIOLATION ERROR",
260 [VEC_RESV59] = "UNASSIGNED RESERVED 59",
261 [VEC_UNIMPEA] = "UNASSIGNED RESERVED 60",
262 [VEC_UNIMPII] = "UNASSIGNED RESERVED 61",
263 [VEC_RESV62] = "UNASSIGNED RESERVED 62",
264 [VEC_RESV63] = "UNASSIGNED RESERVED 63",
265};
266
267static const char *space_names[] = {
268 [0] = "Space 0",
269 [USER_DATA] = "User Data",
270 [USER_PROGRAM] = "User Program",
271#ifndef CONFIG_SUN3
272 [3] = "Space 3",
273#else
274 [FC_CONTROL] = "Control",
275#endif
276 [4] = "Space 4",
277 [SUPER_DATA] = "Super Data",
278 [SUPER_PROGRAM] = "Super Program",
279 [CPU_SPACE] = "CPU"
280};
281
282void die_if_kernel(char *,struct pt_regs *,int);
283asmlinkage int do_page_fault(struct pt_regs *regs, unsigned long address,
284 unsigned long error_code);
285int send_fault_sig(struct pt_regs *regs);
286
287asmlinkage void trap_c(struct frame *fp);
288
289#if defined (CONFIG_M68060)
290static inline void access_error060 (struct frame *fp)
291{
292 unsigned long fslw = fp->un.fmt4.pc; /* is really FSLW for access error */
293
294#ifdef DEBUG
295 printk("fslw=%#lx, fa=%#lx\n", fslw, fp->un.fmt4.effaddr);
296#endif
297
298 if (fslw & MMU060_BPE) {
299 /* branch prediction error -> clear branch cache */
300 __asm__ __volatile__ ("movec %/cacr,%/d0\n\t"
301 "orl #0x00400000,%/d0\n\t"
302 "movec %/d0,%/cacr"
303 : : : "d0" );
304 /* return if there's no other error */
305 if (!(fslw & MMU060_ERR_BITS) && !(fslw & MMU060_SEE))
306 return;
307 }
308
309 if (fslw & (MMU060_DESC_ERR | MMU060_WP | MMU060_SP)) {
310 unsigned long errorcode;
311 unsigned long addr = fp->un.fmt4.effaddr;
312
313 if (fslw & MMU060_MA)
314 addr = (addr + PAGE_SIZE - 1) & PAGE_MASK;
315
316 errorcode = 1;
317 if (fslw & MMU060_DESC_ERR) {
318 __flush_tlb040_one(addr);
319 errorcode = 0;
320 }
321 if (fslw & MMU060_W)
322 errorcode |= 2;
323#ifdef DEBUG
324 printk("errorcode = %d\n", errorcode );
325#endif
326 do_page_fault(&fp->ptregs, addr, errorcode);
327 } else if (fslw & (MMU060_SEE)){
328 /* Software Emulation Error.
329 * fault during mem_read/mem_write in ifpsp060/os.S
330 */
331 send_fault_sig(&fp->ptregs);
332 } else if (!(fslw & (MMU060_RE|MMU060_WE)) ||
333 send_fault_sig(&fp->ptregs) > 0) {
334 printk("pc=%#lx, fa=%#lx\n", fp->ptregs.pc, fp->un.fmt4.effaddr);
335 printk( "68060 access error, fslw=%lx\n", fslw );
336 trap_c( fp );
337 }
338}
339#endif /* CONFIG_M68060 */
340
341#if defined (CONFIG_M68040)
342static inline unsigned long probe040(int iswrite, unsigned long addr, int wbs)
343{
344 unsigned long mmusr;
345 mm_segment_t old_fs = get_fs();
346
347 set_fs(MAKE_MM_SEG(wbs));
348
349 if (iswrite)
350 asm volatile (".chip 68040; ptestw (%0); .chip 68k" : : "a" (addr));
351 else
352 asm volatile (".chip 68040; ptestr (%0); .chip 68k" : : "a" (addr));
353
354 asm volatile (".chip 68040; movec %%mmusr,%0; .chip 68k" : "=r" (mmusr));
355
356 set_fs(old_fs);
357
358 return mmusr;
359}
360
361static inline int do_040writeback1(unsigned short wbs, unsigned long wba,
362 unsigned long wbd)
363{
364 int res = 0;
365 mm_segment_t old_fs = get_fs();
366
367 /* set_fs can not be moved, otherwise put_user() may oops */
368 set_fs(MAKE_MM_SEG(wbs));
369
370 switch (wbs & WBSIZ_040) {
371 case BA_SIZE_BYTE:
372 res = put_user(wbd & 0xff, (char *)wba);
373 break;
374 case BA_SIZE_WORD:
375 res = put_user(wbd & 0xffff, (short *)wba);
376 break;
377 case BA_SIZE_LONG:
378 res = put_user(wbd, (int *)wba);
379 break;
380 }
381
382 /* set_fs can not be moved, otherwise put_user() may oops */
383 set_fs(old_fs);
384
385
386#ifdef DEBUG
387 printk("do_040writeback1, res=%d\n",res);
388#endif
389
390 return res;
391}
392
393/* after an exception in a writeback the stack frame corresponding
394 * to that exception is discarded, set a few bits in the old frame
395 * to simulate what it should look like
396 */
397static inline void fix_xframe040(struct frame *fp, unsigned long wba, unsigned short wbs)
398{
399 fp->un.fmt7.faddr = wba;
400 fp->un.fmt7.ssw = wbs & 0xff;
401 if (wba != current->thread.faddr)
402 fp->un.fmt7.ssw |= MA_040;
403}
404
405static inline void do_040writebacks(struct frame *fp)
406{
407 int res = 0;
408#if 0
409 if (fp->un.fmt7.wb1s & WBV_040)
410 printk("access_error040: cannot handle 1st writeback. oops.\n");
411#endif
412
413 if ((fp->un.fmt7.wb2s & WBV_040) &&
414 !(fp->un.fmt7.wb2s & WBTT_040)) {
415 res = do_040writeback1(fp->un.fmt7.wb2s, fp->un.fmt7.wb2a,
416 fp->un.fmt7.wb2d);
417 if (res)
418 fix_xframe040(fp, fp->un.fmt7.wb2a, fp->un.fmt7.wb2s);
419 else
420 fp->un.fmt7.wb2s = 0;
421 }
422
423 /* do the 2nd wb only if the first one was successful (except for a kernel wb) */
424 if (fp->un.fmt7.wb3s & WBV_040 && (!res || fp->un.fmt7.wb3s & 4)) {
425 res = do_040writeback1(fp->un.fmt7.wb3s, fp->un.fmt7.wb3a,
426 fp->un.fmt7.wb3d);
427 if (res)
428 {
429 fix_xframe040(fp, fp->un.fmt7.wb3a, fp->un.fmt7.wb3s);
430
431 fp->un.fmt7.wb2s = fp->un.fmt7.wb3s;
432 fp->un.fmt7.wb3s &= (~WBV_040);
433 fp->un.fmt7.wb2a = fp->un.fmt7.wb3a;
434 fp->un.fmt7.wb2d = fp->un.fmt7.wb3d;
435 }
436 else
437 fp->un.fmt7.wb3s = 0;
438 }
439
440 if (res)
441 send_fault_sig(&fp->ptregs);
442}
443
444/*
445 * called from sigreturn(), must ensure userspace code didn't
446 * manipulate exception frame to circumvent protection, then complete
447 * pending writebacks
448 * we just clear TM2 to turn it into an userspace access
449 */
450asmlinkage void berr_040cleanup(struct frame *fp)
451{
452 fp->un.fmt7.wb2s &= ~4;
453 fp->un.fmt7.wb3s &= ~4;
454
455 do_040writebacks(fp);
456}
457
458static inline void access_error040(struct frame *fp)
459{
460 unsigned short ssw = fp->un.fmt7.ssw;
461 unsigned long mmusr;
462
463#ifdef DEBUG
464 printk("ssw=%#x, fa=%#lx\n", ssw, fp->un.fmt7.faddr);
465 printk("wb1s=%#x, wb2s=%#x, wb3s=%#x\n", fp->un.fmt7.wb1s,
466 fp->un.fmt7.wb2s, fp->un.fmt7.wb3s);
467 printk ("wb2a=%lx, wb3a=%lx, wb2d=%lx, wb3d=%lx\n",
468 fp->un.fmt7.wb2a, fp->un.fmt7.wb3a,
469 fp->un.fmt7.wb2d, fp->un.fmt7.wb3d);
470#endif
471
472 if (ssw & ATC_040) {
473 unsigned long addr = fp->un.fmt7.faddr;
474 unsigned long errorcode;
475
476 /*
477 * The MMU status has to be determined AFTER the address
478 * has been corrected if there was a misaligned access (MA).
479 */
480 if (ssw & MA_040)
481 addr = (addr + 7) & -8;
482
483 /* MMU error, get the MMUSR info for this access */
484 mmusr = probe040(!(ssw & RW_040), addr, ssw);
485#ifdef DEBUG
486 printk("mmusr = %lx\n", mmusr);
487#endif
488 errorcode = 1;
489 if (!(mmusr & MMU_R_040)) {
490 /* clear the invalid atc entry */
491 __flush_tlb040_one(addr);
492 errorcode = 0;
493 }
494
495 /* despite what documentation seems to say, RMW
496 * accesses have always both the LK and RW bits set */
497 if (!(ssw & RW_040) || (ssw & LK_040))
498 errorcode |= 2;
499
500 if (do_page_fault(&fp->ptregs, addr, errorcode)) {
501#ifdef DEBUG
502 printk("do_page_fault() !=0 \n");
503#endif
504 if (user_mode(&fp->ptregs)){
505 /* delay writebacks after signal delivery */
506#ifdef DEBUG
507 printk(".. was usermode - return\n");
508#endif
509 return;
510 }
511 /* disable writeback into user space from kernel
512 * (if do_page_fault didn't fix the mapping,
513 * the writeback won't do good)
514 */
515#ifdef DEBUG
516 printk(".. disabling wb2\n");
517#endif
518 if (fp->un.fmt7.wb2a == fp->un.fmt7.faddr)
519 fp->un.fmt7.wb2s &= ~WBV_040;
520 }
521 } else if (send_fault_sig(&fp->ptregs) > 0) {
522 printk("68040 access error, ssw=%x\n", ssw);
523 trap_c(fp);
524 }
525
526 do_040writebacks(fp);
527}
528#endif /* CONFIG_M68040 */
529
530#if defined(CONFIG_SUN3)
531#include <asm/sun3mmu.h>
532
533extern int mmu_emu_handle_fault (unsigned long, int, int);
534
535/* sun3 version of bus_error030 */
536
537static inline void bus_error030 (struct frame *fp)
538{
539 unsigned char buserr_type = sun3_get_buserr ();
540 unsigned long addr, errorcode;
541 unsigned short ssw = fp->un.fmtb.ssw;
542 extern unsigned long _sun3_map_test_start, _sun3_map_test_end;
543
544#ifdef DEBUG
545 if (ssw & (FC | FB))
546 printk ("Instruction fault at %#010lx\n",
547 ssw & FC ?
548 fp->ptregs.format == 0xa ? fp->ptregs.pc + 2 : fp->un.fmtb.baddr - 2
549 :
550 fp->ptregs.format == 0xa ? fp->ptregs.pc + 4 : fp->un.fmtb.baddr);
551 if (ssw & DF)
552 printk ("Data %s fault at %#010lx in %s (pc=%#lx)\n",
553 ssw & RW ? "read" : "write",
554 fp->un.fmtb.daddr,
555 space_names[ssw & DFC], fp->ptregs.pc);
556#endif
557
558 /*
559 * Check if this page should be demand-mapped. This needs to go before
560 * the testing for a bad kernel-space access (demand-mapping applies
561 * to kernel accesses too).
562 */
563
564 if ((ssw & DF)
565 && (buserr_type & (SUN3_BUSERR_PROTERR | SUN3_BUSERR_INVALID))) {
566 if (mmu_emu_handle_fault (fp->un.fmtb.daddr, ssw & RW, 0))
567 return;
568 }
569
570 /* Check for kernel-space pagefault (BAD). */
571 if (fp->ptregs.sr & PS_S) {
572 /* kernel fault must be a data fault to user space */
573 if (! ((ssw & DF) && ((ssw & DFC) == USER_DATA))) {
574 // try checking the kernel mappings before surrender
575 if (mmu_emu_handle_fault (fp->un.fmtb.daddr, ssw & RW, 1))
576 return;
577 /* instruction fault or kernel data fault! */
578 if (ssw & (FC | FB))
579 printk ("Instruction fault at %#010lx\n",
580 fp->ptregs.pc);
581 if (ssw & DF) {
582 /* was this fault incurred testing bus mappings? */
583 if((fp->ptregs.pc >= (unsigned long)&_sun3_map_test_start) &&
584 (fp->ptregs.pc <= (unsigned long)&_sun3_map_test_end)) {
585 send_fault_sig(&fp->ptregs);
586 return;
587 }
588
589 printk ("Data %s fault at %#010lx in %s (pc=%#lx)\n",
590 ssw & RW ? "read" : "write",
591 fp->un.fmtb.daddr,
592 space_names[ssw & DFC], fp->ptregs.pc);
593 }
594 printk ("BAD KERNEL BUSERR\n");
595
596 die_if_kernel("Oops", &fp->ptregs,0);
597 force_sig(SIGKILL, current);
598 return;
599 }
600 } else {
601 /* user fault */
602 if (!(ssw & (FC | FB)) && !(ssw & DF))
603 /* not an instruction fault or data fault! BAD */
604 panic ("USER BUSERR w/o instruction or data fault");
605 }
606
607
608 /* First handle the data fault, if any. */
609 if (ssw & DF) {
610 addr = fp->un.fmtb.daddr;
611
612// errorcode bit 0: 0 -> no page 1 -> protection fault
613// errorcode bit 1: 0 -> read fault 1 -> write fault
614
615// (buserr_type & SUN3_BUSERR_PROTERR) -> protection fault
616// (buserr_type & SUN3_BUSERR_INVALID) -> invalid page fault
617
618 if (buserr_type & SUN3_BUSERR_PROTERR)
619 errorcode = 0x01;
620 else if (buserr_type & SUN3_BUSERR_INVALID)
621 errorcode = 0x00;
622 else {
623#ifdef DEBUG
624 printk ("*** unexpected busfault type=%#04x\n", buserr_type);
625 printk ("invalid %s access at %#lx from pc %#lx\n",
626 !(ssw & RW) ? "write" : "read", addr,
627 fp->ptregs.pc);
628#endif
629 die_if_kernel ("Oops", &fp->ptregs, buserr_type);
630 force_sig (SIGBUS, current);
631 return;
632 }
633
634//todo: wtf is RM bit? --m
635 if (!(ssw & RW) || ssw & RM)
636 errorcode |= 0x02;
637
638 /* Handle page fault. */
639 do_page_fault (&fp->ptregs, addr, errorcode);
640
641 /* Retry the data fault now. */
642 return;
643 }
644
645 /* Now handle the instruction fault. */
646
647 /* Get the fault address. */
648 if (fp->ptregs.format == 0xA)
649 addr = fp->ptregs.pc + 4;
650 else
651 addr = fp->un.fmtb.baddr;
652 if (ssw & FC)
653 addr -= 2;
654
655 if (buserr_type & SUN3_BUSERR_INVALID) {
656 if (!mmu_emu_handle_fault (fp->un.fmtb.daddr, 1, 0))
657 do_page_fault (&fp->ptregs, addr, 0);
658 } else {
659#ifdef DEBUG
660 printk ("protection fault on insn access (segv).\n");
661#endif
662 force_sig (SIGSEGV, current);
663 }
664}
665#else
666#if defined(CPU_M68020_OR_M68030)
667static inline void bus_error030 (struct frame *fp)
668{
669 volatile unsigned short temp;
670 unsigned short mmusr;
671 unsigned long addr, errorcode;
672 unsigned short ssw = fp->un.fmtb.ssw;
673#ifdef DEBUG
674 unsigned long desc;
675
676 printk ("pid = %x ", current->pid);
677 printk ("SSW=%#06x ", ssw);
678
679 if (ssw & (FC | FB))
680 printk ("Instruction fault at %#010lx\n",
681 ssw & FC ?
682 fp->ptregs.format == 0xa ? fp->ptregs.pc + 2 : fp->un.fmtb.baddr - 2
683 :
684 fp->ptregs.format == 0xa ? fp->ptregs.pc + 4 : fp->un.fmtb.baddr);
685 if (ssw & DF)
686 printk ("Data %s fault at %#010lx in %s (pc=%#lx)\n",
687 ssw & RW ? "read" : "write",
688 fp->un.fmtb.daddr,
689 space_names[ssw & DFC], fp->ptregs.pc);
690#endif
691
692 /* ++andreas: If a data fault and an instruction fault happen
693 at the same time map in both pages. */
694
695 /* First handle the data fault, if any. */
696 if (ssw & DF) {
697 addr = fp->un.fmtb.daddr;
698
699#ifdef DEBUG
700 asm volatile ("ptestr %3,%2@,#7,%0\n\t"
701 "pmove %%psr,%1@"
702 : "=a&" (desc)
703 : "a" (&temp), "a" (addr), "d" (ssw));
704#else
705 asm volatile ("ptestr %2,%1@,#7\n\t"
706 "pmove %%psr,%0@"
707 : : "a" (&temp), "a" (addr), "d" (ssw));
708#endif
709 mmusr = temp;
710
711#ifdef DEBUG
712 printk("mmusr is %#x for addr %#lx in task %p\n",
713 mmusr, addr, current);
714 printk("descriptor address is %#lx, contents %#lx\n",
715 __va(desc), *(unsigned long *)__va(desc));
716#endif
717
718 errorcode = (mmusr & MMU_I) ? 0 : 1;
719 if (!(ssw & RW) || (ssw & RM))
720 errorcode |= 2;
721
722 if (mmusr & (MMU_I | MMU_WP)) {
723 if (ssw & 4) {
724 printk("Data %s fault at %#010lx in %s (pc=%#lx)\n",
725 ssw & RW ? "read" : "write",
726 fp->un.fmtb.daddr,
727 space_names[ssw & DFC], fp->ptregs.pc);
728 goto buserr;
729 }
730 /* Don't try to do anything further if an exception was
731 handled. */
732 if (do_page_fault (&fp->ptregs, addr, errorcode) < 0)
733 return;
734 } else if (!(mmusr & MMU_I)) {
735 /* probably a 020 cas fault */
736 if (!(ssw & RM) && send_fault_sig(&fp->ptregs) > 0)
737 printk("unexpected bus error (%#x,%#x)\n", ssw, mmusr);
738 } else if (mmusr & (MMU_B|MMU_L|MMU_S)) {
739 printk("invalid %s access at %#lx from pc %#lx\n",
740 !(ssw & RW) ? "write" : "read", addr,
741 fp->ptregs.pc);
742 die_if_kernel("Oops",&fp->ptregs,mmusr);
743 force_sig(SIGSEGV, current);
744 return;
745 } else {
746#if 0
747 static volatile long tlong;
748#endif
749
750 printk("weird %s access at %#lx from pc %#lx (ssw is %#x)\n",
751 !(ssw & RW) ? "write" : "read", addr,
752 fp->ptregs.pc, ssw);
753 asm volatile ("ptestr #1,%1@,#0\n\t"
754 "pmove %%psr,%0@"
755 : /* no outputs */
756 : "a" (&temp), "a" (addr));
757 mmusr = temp;
758
759 printk ("level 0 mmusr is %#x\n", mmusr);
760#if 0
761 asm volatile ("pmove %%tt0,%0@"
762 : /* no outputs */
763 : "a" (&tlong));
764 printk("tt0 is %#lx, ", tlong);
765 asm volatile ("pmove %%tt1,%0@"
766 : /* no outputs */
767 : "a" (&tlong));
768 printk("tt1 is %#lx\n", tlong);
769#endif
770#ifdef DEBUG
771 printk("Unknown SIGSEGV - 1\n");
772#endif
773 die_if_kernel("Oops",&fp->ptregs,mmusr);
774 force_sig(SIGSEGV, current);
775 return;
776 }
777
778 /* setup an ATC entry for the access about to be retried */
779 if (!(ssw & RW) || (ssw & RM))
780 asm volatile ("ploadw %1,%0@" : /* no outputs */
781 : "a" (addr), "d" (ssw));
782 else
783 asm volatile ("ploadr %1,%0@" : /* no outputs */
784 : "a" (addr), "d" (ssw));
785 }
786
787 /* Now handle the instruction fault. */
788
789 if (!(ssw & (FC|FB)))
790 return;
791
792 if (fp->ptregs.sr & PS_S) {
793 printk("Instruction fault at %#010lx\n",
794 fp->ptregs.pc);
795 buserr:
796 printk ("BAD KERNEL BUSERR\n");
797 die_if_kernel("Oops",&fp->ptregs,0);
798 force_sig(SIGKILL, current);
799 return;
800 }
801
802 /* get the fault address */
803 if (fp->ptregs.format == 10)
804 addr = fp->ptregs.pc + 4;
805 else
806 addr = fp->un.fmtb.baddr;
807 if (ssw & FC)
808 addr -= 2;
809
810 if ((ssw & DF) && ((addr ^ fp->un.fmtb.daddr) & PAGE_MASK) == 0)
811 /* Insn fault on same page as data fault. But we
812 should still create the ATC entry. */
813 goto create_atc_entry;
814
815#ifdef DEBUG
816 asm volatile ("ptestr #1,%2@,#7,%0\n\t"
817 "pmove %%psr,%1@"
818 : "=a&" (desc)
819 : "a" (&temp), "a" (addr));
820#else
821 asm volatile ("ptestr #1,%1@,#7\n\t"
822 "pmove %%psr,%0@"
823 : : "a" (&temp), "a" (addr));
824#endif
825 mmusr = temp;
826
827#ifdef DEBUG
828 printk ("mmusr is %#x for addr %#lx in task %p\n",
829 mmusr, addr, current);
830 printk ("descriptor address is %#lx, contents %#lx\n",
831 __va(desc), *(unsigned long *)__va(desc));
832#endif
833
834 if (mmusr & MMU_I)
835 do_page_fault (&fp->ptregs, addr, 0);
836 else if (mmusr & (MMU_B|MMU_L|MMU_S)) {
837 printk ("invalid insn access at %#lx from pc %#lx\n",
838 addr, fp->ptregs.pc);
839#ifdef DEBUG
840 printk("Unknown SIGSEGV - 2\n");
841#endif
842 die_if_kernel("Oops",&fp->ptregs,mmusr);
843 force_sig(SIGSEGV, current);
844 return;
845 }
846
847create_atc_entry:
848 /* setup an ATC entry for the access about to be retried */
849 asm volatile ("ploadr #2,%0@" : /* no outputs */
850 : "a" (addr));
851}
852#endif /* CPU_M68020_OR_M68030 */
853#endif /* !CONFIG_SUN3 */
854
855asmlinkage void buserr_c(struct frame *fp)
856{
857 /* Only set esp0 if coming from user mode */
858 if (user_mode(&fp->ptregs))
859 current->thread.esp0 = (unsigned long) fp;
860
861#ifdef DEBUG
862 printk ("*** Bus Error *** Format is %x\n", fp->ptregs.format);
863#endif
864
865 switch (fp->ptregs.format) {
866#if defined (CONFIG_M68060)
867 case 4: /* 68060 access error */
868 access_error060 (fp);
869 break;
870#endif
871#if defined (CONFIG_M68040)
872 case 0x7: /* 68040 access error */
873 access_error040 (fp);
874 break;
875#endif
876#if defined (CPU_M68020_OR_M68030)
877 case 0xa:
878 case 0xb:
879 bus_error030 (fp);
880 break;
881#endif
882 default:
883 die_if_kernel("bad frame format",&fp->ptregs,0);
884#ifdef DEBUG
885 printk("Unknown SIGSEGV - 4\n");
886#endif
887 force_sig(SIGSEGV, current);
888 }
889}
890
891
892static int kstack_depth_to_print = 48;
893
894void show_trace(unsigned long *stack)
895{
896 unsigned long *endstack;
897 unsigned long addr;
898 int i;
899
900 printk("Call Trace:");
901 addr = (unsigned long)stack + THREAD_SIZE - 1;
902 endstack = (unsigned long *)(addr & -THREAD_SIZE);
903 i = 0;
904 while (stack + 1 <= endstack) {
905 addr = *stack++;
906 /*
907 * If the address is either in the text segment of the
908 * kernel, or in the region which contains vmalloc'ed
909 * memory, it *may* be the address of a calling
910 * routine; if so, print it so that someone tracing
911 * down the cause of the crash will be able to figure
912 * out the call path that was taken.
913 */
914 if (__kernel_text_address(addr)) {
915#ifndef CONFIG_KALLSYMS
916 if (i % 5 == 0)
917 printk("\n ");
918#endif
919 printk(" [<%08lx>]", addr);
920 print_symbol(" %s\n", addr);
921 i++;
922 }
923 }
924 printk("\n");
925}
926
927void show_registers(struct pt_regs *regs)
928{
929 struct frame *fp = (struct frame *)regs;
930 unsigned long addr;
931 int i;
932
933 addr = (unsigned long)&fp->un;
934 printk("Frame format=%X ", fp->ptregs.format);
935 switch (fp->ptregs.format) {
936 case 0x2:
937 printk("instr addr=%08lx\n", fp->un.fmt2.iaddr);
938 addr += sizeof(fp->un.fmt2);
939 break;
940 case 0x3:
941 printk("eff addr=%08lx\n", fp->un.fmt3.effaddr);
942 addr += sizeof(fp->un.fmt3);
943 break;
944 case 0x4:
945 printk((CPU_IS_060 ? "fault addr=%08lx fslw=%08lx\n"
946 : "eff addr=%08lx pc=%08lx\n"),
947 fp->un.fmt4.effaddr, fp->un.fmt4.pc);
948 addr += sizeof(fp->un.fmt4);
949 break;
950 case 0x7:
951 printk("eff addr=%08lx ssw=%04x faddr=%08lx\n",
952 fp->un.fmt7.effaddr, fp->un.fmt7.ssw, fp->un.fmt7.faddr);
953 printk("wb 1 stat/addr/data: %04x %08lx %08lx\n",
954 fp->un.fmt7.wb1s, fp->un.fmt7.wb1a, fp->un.fmt7.wb1dpd0);
955 printk("wb 2 stat/addr/data: %04x %08lx %08lx\n",
956 fp->un.fmt7.wb2s, fp->un.fmt7.wb2a, fp->un.fmt7.wb2d);
957 printk("wb 3 stat/addr/data: %04x %08lx %08lx\n",
958 fp->un.fmt7.wb3s, fp->un.fmt7.wb3a, fp->un.fmt7.wb3d);
959 printk("push data: %08lx %08lx %08lx %08lx\n",
960 fp->un.fmt7.wb1dpd0, fp->un.fmt7.pd1, fp->un.fmt7.pd2,
961 fp->un.fmt7.pd3);
962 addr += sizeof(fp->un.fmt7);
963 break;
964 case 0x9:
965 printk("instr addr=%08lx\n", fp->un.fmt9.iaddr);
966 addr += sizeof(fp->un.fmt9);
967 break;
968 case 0xa:
969 printk("ssw=%04x isc=%04x isb=%04x daddr=%08lx dobuf=%08lx\n",
970 fp->un.fmta.ssw, fp->un.fmta.isc, fp->un.fmta.isb,
971 fp->un.fmta.daddr, fp->un.fmta.dobuf);
972 addr += sizeof(fp->un.fmta);
973 break;
974 case 0xb:
975 printk("ssw=%04x isc=%04x isb=%04x daddr=%08lx dobuf=%08lx\n",
976 fp->un.fmtb.ssw, fp->un.fmtb.isc, fp->un.fmtb.isb,
977 fp->un.fmtb.daddr, fp->un.fmtb.dobuf);
978 printk("baddr=%08lx dibuf=%08lx ver=%x\n",
979 fp->un.fmtb.baddr, fp->un.fmtb.dibuf, fp->un.fmtb.ver);
980 addr += sizeof(fp->un.fmtb);
981 break;
982 default:
983 printk("\n");
984 }
985 show_stack(NULL, (unsigned long *)addr);
986
987 printk("Code: ");
988 for (i = 0; i < 10; i++)
989 printk("%04x ", 0xffff & ((short *) fp->ptregs.pc)[i]);
990 printk ("\n");
991}
992
993void show_stack(struct task_struct *task, unsigned long *stack)
994{
995 unsigned long *endstack;
996 int i;
997
998 if (!stack) {
999 if (task)
1000 stack = (unsigned long *)task->thread.esp0;
1001 else
1002 stack = (unsigned long *)&stack;
1003 }
1004 endstack = (unsigned long *)(((unsigned long)stack + THREAD_SIZE - 1) & -THREAD_SIZE);
1005
1006 printk("Stack from %08lx:", (unsigned long)stack);
1007 for (i = 0; i < kstack_depth_to_print; i++) {
1008 if (stack + 1 > endstack)
1009 break;
1010 if (i % 8 == 0)
1011 printk("\n ");
1012 printk(" %08lx", *stack++);
1013 }
1014 printk("\n");
1015 show_trace(stack);
1016}
1017
1018/*
1019 * The architecture-independent backtrace generator
1020 */
1021void dump_stack(void)
1022{
1023 unsigned long stack;
1024
1025 show_trace(&stack);
1026}
1027
1028EXPORT_SYMBOL(dump_stack);
1029
1030void bad_super_trap (struct frame *fp)
1031{
1032 console_verbose();
1033 if (fp->ptregs.vector < 4*sizeof(vec_names)/sizeof(vec_names[0]))
1034 printk ("*** %s *** FORMAT=%X\n",
1035 vec_names[(fp->ptregs.vector) >> 2],
1036 fp->ptregs.format);
1037 else
1038 printk ("*** Exception %d *** FORMAT=%X\n",
1039 (fp->ptregs.vector) >> 2,
1040 fp->ptregs.format);
1041 if (fp->ptregs.vector >> 2 == VEC_ADDRERR && CPU_IS_020_OR_030) {
1042 unsigned short ssw = fp->un.fmtb.ssw;
1043
1044 printk ("SSW=%#06x ", ssw);
1045
1046 if (ssw & RC)
1047 printk ("Pipe stage C instruction fault at %#010lx\n",
1048 (fp->ptregs.format) == 0xA ?
1049 fp->ptregs.pc + 2 : fp->un.fmtb.baddr - 2);
1050 if (ssw & RB)
1051 printk ("Pipe stage B instruction fault at %#010lx\n",
1052 (fp->ptregs.format) == 0xA ?
1053 fp->ptregs.pc + 4 : fp->un.fmtb.baddr);
1054 if (ssw & DF)
1055 printk ("Data %s fault at %#010lx in %s (pc=%#lx)\n",
1056 ssw & RW ? "read" : "write",
1057 fp->un.fmtb.daddr, space_names[ssw & DFC],
1058 fp->ptregs.pc);
1059 }
1060 printk ("Current process id is %d\n", current->pid);
1061 die_if_kernel("BAD KERNEL TRAP", &fp->ptregs, 0);
1062}
1063
1064asmlinkage void trap_c(struct frame *fp)
1065{
1066 int sig;
1067 siginfo_t info;
1068
1069 if (fp->ptregs.sr & PS_S) {
1070 if ((fp->ptregs.vector >> 2) == VEC_TRACE) {
1071 /* traced a trapping instruction */
1072 current->ptrace |= PT_DTRACE;
1073 } else
1074 bad_super_trap(fp);
1075 return;
1076 }
1077
1078 /* send the appropriate signal to the user program */
1079 switch ((fp->ptregs.vector) >> 2) {
1080 case VEC_ADDRERR:
1081 info.si_code = BUS_ADRALN;
1082 sig = SIGBUS;
1083 break;
1084 case VEC_ILLEGAL:
1085 case VEC_LINE10:
1086 case VEC_LINE11:
1087 info.si_code = ILL_ILLOPC;
1088 sig = SIGILL;
1089 break;
1090 case VEC_PRIV:
1091 info.si_code = ILL_PRVOPC;
1092 sig = SIGILL;
1093 break;
1094 case VEC_COPROC:
1095 info.si_code = ILL_COPROC;
1096 sig = SIGILL;
1097 break;
1098 case VEC_TRAP1:
1099 case VEC_TRAP2:
1100 case VEC_TRAP3:
1101 case VEC_TRAP4:
1102 case VEC_TRAP5:
1103 case VEC_TRAP6:
1104 case VEC_TRAP7:
1105 case VEC_TRAP8:
1106 case VEC_TRAP9:
1107 case VEC_TRAP10:
1108 case VEC_TRAP11:
1109 case VEC_TRAP12:
1110 case VEC_TRAP13:
1111 case VEC_TRAP14:
1112 info.si_code = ILL_ILLTRP;
1113 sig = SIGILL;
1114 break;
1115 case VEC_FPBRUC:
1116 case VEC_FPOE:
1117 case VEC_FPNAN:
1118 info.si_code = FPE_FLTINV;
1119 sig = SIGFPE;
1120 break;
1121 case VEC_FPIR:
1122 info.si_code = FPE_FLTRES;
1123 sig = SIGFPE;
1124 break;
1125 case VEC_FPDIVZ:
1126 info.si_code = FPE_FLTDIV;
1127 sig = SIGFPE;
1128 break;
1129 case VEC_FPUNDER:
1130 info.si_code = FPE_FLTUND;
1131 sig = SIGFPE;
1132 break;
1133 case VEC_FPOVER:
1134 info.si_code = FPE_FLTOVF;
1135 sig = SIGFPE;
1136 break;
1137 case VEC_ZERODIV:
1138 info.si_code = FPE_INTDIV;
1139 sig = SIGFPE;
1140 break;
1141 case VEC_CHK:
1142 case VEC_TRAP:
1143 info.si_code = FPE_INTOVF;
1144 sig = SIGFPE;
1145 break;
1146 case VEC_TRACE: /* ptrace single step */
1147 info.si_code = TRAP_TRACE;
1148 sig = SIGTRAP;
1149 break;
1150 case VEC_TRAP15: /* breakpoint */
1151 info.si_code = TRAP_BRKPT;
1152 sig = SIGTRAP;
1153 break;
1154 default:
1155 info.si_code = ILL_ILLOPC;
1156 sig = SIGILL;
1157 break;
1158 }
1159 info.si_signo = sig;
1160 info.si_errno = 0;
1161 switch (fp->ptregs.format) {
1162 default:
1163 info.si_addr = (void *) fp->ptregs.pc;
1164 break;
1165 case 2:
1166 info.si_addr = (void *) fp->un.fmt2.iaddr;
1167 break;
1168 case 7:
1169 info.si_addr = (void *) fp->un.fmt7.effaddr;
1170 break;
1171 case 9:
1172 info.si_addr = (void *) fp->un.fmt9.iaddr;
1173 break;
1174 case 10:
1175 info.si_addr = (void *) fp->un.fmta.daddr;
1176 break;
1177 case 11:
1178 info.si_addr = (void *) fp->un.fmtb.daddr;
1179 break;
1180 }
1181 force_sig_info (sig, &info, current);
1182}
1183
1184void die_if_kernel (char *str, struct pt_regs *fp, int nr)
1185{
1186 if (!(fp->sr & PS_S))
1187 return;
1188
1189 console_verbose();
1190 printk("%s: %08x\n",str,nr);
1191 print_modules();
1192 printk("PC: [<%08lx>]",fp->pc);
1193 print_symbol(" %s\n", fp->pc);
1194 printk("\nSR: %04x SP: %p a2: %08lx\n",
1195 fp->sr, fp, fp->a2);
1196 printk("d0: %08lx d1: %08lx d2: %08lx d3: %08lx\n",
1197 fp->d0, fp->d1, fp->d2, fp->d3);
1198 printk("d4: %08lx d5: %08lx a0: %08lx a1: %08lx\n",
1199 fp->d4, fp->d5, fp->a0, fp->a1);
1200
1201 printk("Process %s (pid: %d, stackpage=%08lx)\n",
1202 current->comm, current->pid, PAGE_SIZE+(unsigned long)current);
1203 show_stack(NULL, (unsigned long *)fp);
1204 do_exit(SIGSEGV);
1205}
1206
1207/*
1208 * This function is called if an error occur while accessing
1209 * user-space from the fpsp040 code.
1210 */
1211asmlinkage void fpsp040_die(void)
1212{
1213 do_exit(SIGSEGV);
1214}
1215
1216#ifdef CONFIG_M68KFPU_EMU
1217asmlinkage void fpemu_signal(int signal, int code, void *addr)
1218{
1219 siginfo_t info;
1220
1221 info.si_signo = signal;
1222 info.si_errno = 0;
1223 info.si_code = code;
1224 info.si_addr = addr;
1225 force_sig_info(signal, &info, current);
1226}
1227#endif
diff --git a/arch/m68k/kernel/vmlinux-std.lds b/arch/m68k/kernel/vmlinux-std.lds
new file mode 100644
index 000000000000..e58654f3f8dd
--- /dev/null
+++ b/arch/m68k/kernel/vmlinux-std.lds
@@ -0,0 +1,95 @@
1/* ld script to make m68k Linux kernel */
2
3#include <asm-generic/vmlinux.lds.h>
4
5OUTPUT_FORMAT("elf32-m68k", "elf32-m68k", "elf32-m68k")
6OUTPUT_ARCH(m68k)
7ENTRY(_start)
8jiffies = jiffies_64 + 4;
9SECTIONS
10{
11 . = 0x1000;
12 _text = .; /* Text and read-only data */
13 .text : {
14 *(.text)
15 SCHED_TEXT
16 *(.fixup)
17 *(.gnu.warning)
18 } :text = 0x4e75
19
20 . = ALIGN(16); /* Exception table */
21 __start___ex_table = .;
22 __ex_table : { *(__ex_table) }
23 __stop___ex_table = .;
24
25 RODATA
26
27 _etext = .; /* End of text section */
28
29 .data : { /* Data */
30 *(.data)
31 CONSTRUCTORS
32 }
33
34 .bss : { *(.bss) } /* BSS */
35
36 . = ALIGN(16);
37 .data.cacheline_aligned : { *(.data.cacheline_aligned) } :data
38
39 _edata = .; /* End of data section */
40
41 /* will be freed after init */
42 . = ALIGN(4096); /* Init code and data */
43 __init_begin = .;
44 .init.text : {
45 _sinittext = .;
46 *(.init.text)
47 _einittext = .;
48 }
49 .init.data : { *(.init.data) }
50 . = ALIGN(16);
51 __setup_start = .;
52 .init.setup : { *(.init.setup) }
53 __setup_end = .;
54 __initcall_start = .;
55 .initcall.init : {
56 *(.initcall1.init)
57 *(.initcall2.init)
58 *(.initcall3.init)
59 *(.initcall4.init)
60 *(.initcall5.init)
61 *(.initcall6.init)
62 *(.initcall7.init)
63 }
64 __initcall_end = .;
65 __con_initcall_start = .;
66 .con_initcall.init : { *(.con_initcall.init) }
67 __con_initcall_end = .;
68 SECURITY_INIT
69 . = ALIGN(8192);
70 __initramfs_start = .;
71 .init.ramfs : { *(.init.ramfs) }
72 __initramfs_end = .;
73 . = ALIGN(8192);
74 __init_end = .;
75
76 .data.init_task : { *(.data.init_task) } /* The initial task and kernel stack */
77
78 _end = . ;
79
80 /* Sections to be discarded */
81 /DISCARD/ : {
82 *(.exit.text)
83 *(.exit.data)
84 *(.exitcall.exit)
85 }
86
87 /* Stabs debugging sections. */
88 .stab 0 : { *(.stab) }
89 .stabstr 0 : { *(.stabstr) }
90 .stab.excl 0 : { *(.stab.excl) }
91 .stab.exclstr 0 : { *(.stab.exclstr) }
92 .stab.index 0 : { *(.stab.index) }
93 .stab.indexstr 0 : { *(.stab.indexstr) }
94 .comment 0 : { *(.comment) }
95}
diff --git a/arch/m68k/kernel/vmlinux-sun3.lds b/arch/m68k/kernel/vmlinux-sun3.lds
new file mode 100644
index 000000000000..cc37e8d3c1e2
--- /dev/null
+++ b/arch/m68k/kernel/vmlinux-sun3.lds
@@ -0,0 +1,95 @@
1/* ld script to make m68k Linux kernel */
2
3#include <asm-generic/vmlinux.lds.h>
4
5OUTPUT_FORMAT("elf32-m68k", "elf32-m68k", "elf32-m68k")
6OUTPUT_ARCH(m68k)
7ENTRY(_start)
8jiffies = jiffies_64 + 4;
9SECTIONS
10{
11 . = 0xE004000;
12 _text = .; /* Text and read-only data */
13 .text : {
14 *(.head)
15 *(.text)
16 SCHED_TEXT
17 *(.fixup)
18 *(.gnu.warning)
19 } :text = 0x4e75
20 RODATA
21
22 _etext = .; /* End of text section */
23
24 .data : { /* Data */
25 *(.data)
26 CONSTRUCTORS
27 . = ALIGN(16); /* Exception table */
28 __start___ex_table = .;
29 *(__ex_table)
30 __stop___ex_table = .;
31 } :data
32 /* End of data goes *here* so that freeing init code works properly. */
33 _edata = .;
34
35 /* will be freed after init */
36 . = ALIGN(8192); /* Init code and data */
37__init_begin = .;
38 .init.text : {
39 _sinittext = .;
40 *(.init.text)
41 _einittext = .;
42 }
43 .init.data : { *(.init.data) }
44 . = ALIGN(16);
45 __setup_start = .;
46 .init.setup : { *(.init.setup) }
47 __setup_end = .;
48 __initcall_start = .;
49 .initcall.init : {
50 *(.initcall1.init)
51 *(.initcall2.init)
52 *(.initcall3.init)
53 *(.initcall4.init)
54 *(.initcall5.init)
55 *(.initcall6.init)
56 *(.initcall7.init)
57 }
58 __initcall_end = .;
59 __con_initcall_start = .;
60 .con_initcall.init : { *(.con_initcall.init) }
61 __con_initcall_end = .;
62 SECURITY_INIT
63 . = ALIGN(8192);
64 __initramfs_start = .;
65 .init.ramfs : { *(.init.ramfs) }
66 __initramfs_end = .;
67 . = ALIGN(8192);
68 __init_end = .;
69 .init.task : { *(init_task) }
70
71
72 .bss : { *(.bss) } /* BSS */
73
74 _end = . ;
75
76 /* Sections to be discarded */
77 /DISCARD/ : {
78 *(.exit.text)
79 *(.exit.data)
80 *(.exitcall.exit)
81 }
82
83 .crap : {
84 /* Stabs debugging sections. */
85 *(.stab)
86 *(.stabstr)
87 *(.stab.excl)
88 *(.stab.exclstr)
89 *(.stab.index)
90 *(.stab.indexstr)
91 *(.comment)
92 *(.note)
93 }
94
95}
diff --git a/arch/m68k/kernel/vmlinux.lds.S b/arch/m68k/kernel/vmlinux.lds.S
new file mode 100644
index 000000000000..497b924f3c86
--- /dev/null
+++ b/arch/m68k/kernel/vmlinux.lds.S
@@ -0,0 +1,11 @@
1#include <linux/config.h>
2PHDRS
3{
4 text PT_LOAD FILEHDR PHDRS FLAGS (7);
5 data PT_LOAD FLAGS (7);
6}
7#ifdef CONFIG_SUN3
8#include "vmlinux-sun3.lds"
9#else
10#include "vmlinux-std.lds"
11#endif