summaryrefslogtreecommitdiffstats
path: root/arch/m68k/kernel
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>1997-04-29 21:13:14 +0000
committer <ralf@linux-mips.org>1997-04-29 21:13:14 +0000
commit19c9bba94152148523ba0f7ef7cffe3d45656b11 (patch)
tree40b1cb534496a7f1ca0f5c314a523c69f1fee464 /arch/m68k/kernel
parent7206675c40394c78a90e74812bbdbf8cf3cca1be (diff)
Import of Linux/MIPS 2.1.36
Diffstat (limited to 'arch/m68k/kernel')
-rw-r--r--arch/m68k/kernel/Makefile10
-rw-r--r--arch/m68k/kernel/console.c231
-rw-r--r--arch/m68k/kernel/entry.S160
-rw-r--r--arch/m68k/kernel/head.S306
-rw-r--r--arch/m68k/kernel/ints.c86
-rw-r--r--arch/m68k/kernel/ksyms.c89
-rw-r--r--arch/m68k/kernel/m68k_ksyms.c57
-rw-r--r--arch/m68k/kernel/process.c54
-rw-r--r--arch/m68k/kernel/ptrace.c105
-rw-r--r--arch/m68k/kernel/setup.c208
-rw-r--r--arch/m68k/kernel/signal.c41
-rw-r--r--arch/m68k/kernel/sys_m68k.c347
-rw-r--r--arch/m68k/kernel/traps.c107
13 files changed, 1071 insertions, 730 deletions
diff --git a/arch/m68k/kernel/Makefile b/arch/m68k/kernel/Makefile
index 339e1b5db..67d87c1b9 100644
--- a/arch/m68k/kernel/Makefile
+++ b/arch/m68k/kernel/Makefile
@@ -13,7 +13,15 @@
all: kernel.o head.o
O_TARGET := kernel.o
O_OBJS := entry.o process.o traps.o ints.o signal.o ptrace.o \
- setup.o bios32.o sys_m68k.o console.o time.o ksyms.o
+ setup.o bios32.o sys_m68k.o time.o
+ifdef CONFIG_VT
+O_OBJS += console.o
+endif
+OX_OBJS := m68k_ksyms.o
+
+ifdef CONFIG_KGDB
+O_OBJS += kgdb.o
+endif
head.o: head.S
diff --git a/arch/m68k/kernel/console.c b/arch/m68k/kernel/console.c
index cac94e7d4..468ae0b59 100644
--- a/arch/m68k/kernel/console.c
+++ b/arch/m68k/kernel/console.c
@@ -20,7 +20,7 @@
* 'unsigned long con_init(unsigned long)'
* 'int con_open(struct tty_struct *tty, struct file * filp)'
* 'void con_write(struct tty_struct * tty)'
- * 'void console_print(const char * b)'
+ * 'void vt_console_print(const char * b)'
* 'void update_screen(int new_console)'
*
* 'void do_blank_screen(int)'
@@ -103,11 +103,13 @@
* interrupt, as we use trap-gates. Hopefully all is well.
*/
+#include <linux/config.h>
#include <linux/sched.h>
#include <linux/timer.h>
#include <linux/interrupt.h>
#include <linux/tty.h>
#include <linux/tty_flip.h>
+#include <linux/console.h>
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/errno.h>
@@ -127,6 +129,7 @@
#include "../../../drivers/char/vt_kern.h"
#include "../../../drivers/char/consolemap.h"
#include "../../../drivers/char/selection.h"
+#include "../../../drivers/char/console_struct.h"
#ifndef MIN
@@ -146,12 +149,13 @@ static void gotoxy(int currcons, int new_x, int new_y);
static void save_cur(int currcons);
static void blank_screen(void);
static void unblank_screen(void);
+static int con_open(struct tty_struct *, struct file *);
extern void change_console(unsigned int);
static inline void set_cursor(int currcons);
static void reset_terminal(int currcons, int do_clear);
extern void reset_vc(unsigned int new_console);
extern void vt_init(void);
-extern void register_console(void (*proc)(const char *));
+static void set_vesa_blanking(unsigned long arg);
extern void vesa_blank(void);
extern void vesa_unblank(void);
extern void compute_shiftstate(void);
@@ -170,6 +174,7 @@ int video_mode_512ch = 0; /* 512-character mode */
static unsigned short console_charmask = 0x0ff;
static unsigned short *vc_scrbuf[MAX_NR_CONSOLES];
+struct vc vc_cons [MAX_NR_CONSOLES];
/* used by kbd_bh - set by keyboard_interrupt */
int do_poke_blanked_console = 0;
@@ -178,13 +183,17 @@ static int blankinterval = 10*60*HZ;
static int vesa_off_interval = 0;
static int vesa_blank_mode = 0; /* 0:none 1:suspendV 2:suspendH 3:powerdown */
-static struct vc {
- struct vc_data *d;
+/*
+ * fg_console is the current virtual console,
+ * last_console is the last used one,
+ * want_console is the console we want to switch to,
+ * kmsg_redirect is the console for kernel messages,
+ */
+int fg_console = 0;
+int last_console = 0;
+int want_console = -1;
+int kmsg_redirect = 0;
- /* might add scrmem, vt_struct, kbd at some time,
- to have everything in one place - the disadvantage
- would be that vc_cons etc can no longer be static */
-} vc_cons [MAX_NR_CONSOLES];
struct consw *conswitchp;
#define cols (vc_cons[currcons].d->vc_cols)
@@ -259,8 +268,6 @@ struct consw *conswitchp;
#define vtnewvt (vt_cons[currcons]->vt_newvt)
#endif
-#define structsize (sizeof(struct vc_data) + sizeof(struct vt_struct))
-
int vc_cons_allocated(unsigned int i)
{
return (i < MAX_NR_CONSOLES && vc_cons[i].d);
@@ -610,8 +617,7 @@ void scrollback(int l)
return;
}
-static void scrup(int currcons, unsigned int t, unsigned int b,
- int nr)
+static void scrup(int currcons, unsigned int t, unsigned int b, int nr)
{
unsigned short *p;
int i;
@@ -625,10 +631,10 @@ static void scrup(int currcons, unsigned int t, unsigned int b,
p = video_mem_start + (b - nr) * cols;
for (i = nr * cols; i > 0; i--)
- *p++ = video_erase_char;
+ *p++ = video_erase_char;
if (currcons != fg_console)
- return;
+ return;
/*
* Arno:
* Scrolling has now been moved to amicon.c where it should have
@@ -801,8 +807,8 @@ static void csi_X(int currcons, int vpar) /* erase the following vpar positions
if (!vpar)
vpar++;
- start=pos;
- count=(vpar > cols-x) ? (cols-x) : vpar;
+ start = pos;
+ count = (vpar > cols-x) ? (cols-x) : vpar;
if (currcons == fg_console)
sw->con_clear(vc_cons[currcons].d,y,x,1,count);
@@ -970,7 +976,7 @@ static void respond_string(const char * p, struct tty_struct * tty)
tty_schedule_flip(tty);
}
-static void cursor_report(int currcons, struct tty_struct * tty)
+static inline void cursor_report(int currcons, struct tty_struct * tty)
{
char buf[40];
@@ -997,7 +1003,7 @@ void mouse_report(struct tty_struct * tty, int butt, int mrx, int mry)
respond_string(buf, tty);
}
-/* invoked via ioctl(TIOCLINUX) */
+/* invoked via ioctl(TIOCLINUX) and through set_selection */
int mouse_reporting(void)
{
int currcons = fg_console;
@@ -1005,6 +1011,56 @@ int mouse_reporting(void)
return report_mouse;
}
+int tioclinux(struct tty_struct *tty, unsigned long arg)
+{
+ char type, data;
+
+ if (tty->driver.type != TTY_DRIVER_TYPE_CONSOLE)
+ return -EINVAL;
+ if (current->tty != tty && !suser())
+ return -EPERM;
+ if (get_user(type, (char *)arg))
+ return -EFAULT;
+ switch (type)
+ {
+ case 2:
+ return set_selection(arg, tty, 1);
+ case 3:
+ return paste_selection(tty);
+ case 4:
+ do_unblank_screen();
+ return 0;
+ case 5:
+ return sel_loadlut(arg);
+ case 6:
+
+ /*
+ * Make it possible to react to Shift+Mousebutton.
+ * Note that 'shift_state' is an undocumented
+ * kernel-internal variable; programs not closely
+ * related to the kernel should not use this.
+ */
+ data = shift_state;
+ return put_user(data, (char *) arg);
+ case 7:
+ data = mouse_reporting();
+ return put_user(data, (char *) arg);
+ case 10:
+ set_vesa_blanking(arg);
+ return 0;
+ case 11: /* set kmsg redirect */
+ if (!suser())
+ return -EPERM;
+ if (get_user(data, (char *)arg+1))
+ return -EFAULT;
+ kmsg_redirect = data;
+ return 0;
+ case 12: /* get fg_console */
+ return fg_console;
+ }
+ return -EINVAL;
+}
+
static inline unsigned short *screenpos(int currcons, int offset, int viewed)
{
unsigned short *p = (unsigned short *)(origin + offset);
@@ -1242,18 +1298,18 @@ static void setterm_command(int currcons)
}
}
-static void insert_char(int currcons)
+static inline void insert_char(int currcons)
{
int i;
unsigned short *p = pos;
for (i = cols - x - 2; i >= 0; i--)
- p[i + 1] = p[i];
+ p[i + 1] = p[i];
*pos = video_erase_char;
need_wrap = 0;
if (currcons != fg_console)
- return;
+ return;
/* Arno:
* Move the remainder of the line (-1 character) one spot to the right
@@ -1277,19 +1333,19 @@ static void csi_at(int currcons, unsigned int nr)
p = pos + cols - x - nr;
while (--p >= pos)
- p[nr] = *p;
+ p[nr] = *p;
for (i = 0; i < nr; i++)
- *++p = video_erase_char;
+ *++p = video_erase_char;
need_wrap = 0;
if (currcons != fg_console)
- return;
+ return;
sw->con_bmove (vc_cons[currcons].d, y, x, y, x + nr,
1, cols - x - nr);
while (nr--)
- sw->con_putc (vc_cons[currcons].d, video_erase_char & 0x00ff,
- y, x + nr);
+ sw->con_putc (vc_cons[currcons].d,
+ video_erase_char & 0x00ff, y, x + nr);
}
static void csi_L(int currcons, unsigned int nr)
@@ -1584,9 +1640,9 @@ static int do_con_write(struct tty_struct * tty, int from_user,
*/
/* Only use this for the foreground console,
- where we really draw the chars */
+ where we really draw the chars */
- if (count > 2 &&
+ if (count > 2 &&
!decim && !utf && currcons == fg_console) {
static char putcs_buf[256];
char *p = putcs_buf;
@@ -1599,13 +1655,11 @@ static int do_con_write(struct tty_struct * tty, int from_user,
if (nextx == cols) {
sw->con_putc(vc_cons[currcons].d,
*putcs_buf, y, x);
- pos--;
+ ((unsigned short *)pos)--;
need_wrap = decawm;
continue;
}
- /* TAB TAB TAB - Arghh!!!! */
-
while (count)
{
enable_bh(CONSOLE_BH);
@@ -2068,12 +2122,13 @@ void poke_blanked_console(void)
/* DPC: New version of console_print using putcs */
-void console_print(const char * b)
+#ifdef CONFIG_VT_CONSOLE
+void vt_console_print(const char * b, unsigned int count)
{
int currcons = fg_console;
unsigned char c;
const char *start = b;
- ushort count = 0;
+ ushort cnt = 0;
ushort myx = x;
static int printing = 0;
@@ -2086,7 +2141,7 @@ void console_print(const char * b)
if (!vc_cons_allocated(currcons)) {
/* impossible */
- printk("console_print: tty %d not allocated ??\n", currcons+1);
+ printk("vt_console_print: tty %d not allocated ??\n", currcons+1);
printing = 0;
return;
}
@@ -2096,52 +2151,51 @@ void console_print(const char * b)
/* Contrived structure to try to emulate original need_wrap behaviour
* Problems caused when we have need_wrap set on '\n' character */
-
- while ((c = *(b++)) != 0) {
- if (c == 10 || c == 13 || c == 8 || need_wrap) {
- if ((count = b - start - 1) > 0) {
- sw->con_putcs(vc_cons[currcons].d, start, count ,
- y, x);
- x += count;
- if (need_wrap)
- x--;
- }
-
- if (c == 8) { /* backspace */
- bs(currcons);
- start = b;
- myx = x;
- continue;
+
+ while (count-- > 0) {
+ c = *(b++);
+ if (c == 10 || c == 13 || c == 8 || need_wrap) {
+ if ((cnt = b - start - 1) > 0) {
+ sw->con_putcs(vc_cons[currcons].d,
+ start, cnt, y, x);
+ x += cnt;
+ if (need_wrap)
+ x--;
+ }
+
+ if (c == 8) { /* backspace */
+ bs(currcons);
+ start = b;
+ myx = x;
+ continue;
+ }
+ if (c != 13)
+ lf(currcons);
+ cr(currcons);
+
+ if (c == 10 || c == 13) {
+ start = b; myx = x; continue;
+ }
+
+ start = b-1; myx = x;
+ }
+
+ *pos = c | (attr << 8);
+ if (myx == cols - 1) {
+ need_wrap = 1;
+ continue;
}
- if (c != 13)
- lf(currcons);
- cr(currcons);
-
- if (c == 10 || c == 13) {
- start = b; myx = x; continue;
- }
-
- start = b-1; myx = x;
- }
-
- *pos = c | (attr << 8);
- if (myx == cols - 1) {
- need_wrap = 1;
- continue;
- }
- pos++;
- myx++;
+ pos++;
+ myx++;
}
- if ((count = b - start -1) > 0) {
- sw->con_putcs(vc_cons[currcons].d, start, count ,
- y, x);
- x += count;
- if (x == cols)
- {
- x--;
- need_wrap = 1;
- }
+ if ((cnt = b - start) > 0) {
+ sw->con_putcs(vc_cons[currcons].d, start, cnt, y, x);
+ x += cnt;
+ if (x == cols){
+ x--;
+ need_wrap = 1;
+ }
}
set_cursor(currcons);
@@ -2149,6 +2203,18 @@ void console_print(const char * b)
printing = 0;
}
+static int vt_console_device(void)
+{
+ return MKDEV(TTY_MAJOR, fg_console + 1);
+}
+
+extern void keyboard_wait_for_keypress(void);
+
+struct console vt_console_driver = {
+ vt_console_print, do_unblank_screen,
+ keyboard_wait_for_keypress, vt_console_device
+};
+#endif
/*
* con_throttle and con_unthrottle are only used for
@@ -2219,7 +2285,7 @@ static void console_bh(void)
*/
unsigned long con_init(unsigned long kmem_start)
{
- char *display_desc = "????";
+ const char *display_desc = "????";
unsigned int currcons = 0;
extern int serial_debug;
@@ -2293,14 +2359,15 @@ unsigned long con_init(unsigned long kmem_start)
printable = 1;
/* If "serdebug" cmd line option was present, don't register for printk */
+#ifdef CONFIG_VT_CONSOLE
if (!serial_debug)
- register_console(console_print);
+ register_console(&vt_console_driver);
printk("Console: %s %s %ldx%ld, %d virtual console%s (max %d)\n",
can_do_color ? "colour":"mono",
display_desc,
cols,rows,
MIN_NR_CONSOLES, (MIN_NR_CONSOLES == 1) ? "" : "s", MAX_NR_CONSOLES);
-
+#endif
init_bh(CONSOLE_BH, console_bh);
return kmem_start;
}
@@ -2466,7 +2533,7 @@ static void unblank_screen(void)
/*
* Allocate the console screen memory.
*/
-int con_open(struct tty_struct *tty, struct file * filp)
+static int con_open(struct tty_struct *tty, struct file * filp)
{
unsigned int currcons;
int i;
@@ -2603,7 +2670,7 @@ int con_adjust_height(unsigned long fontheight)
return -EINVAL;
}
-void set_vesa_blanking(int arg)
+static void set_vesa_blanking(unsigned long arg)
{
char *argp = (char *)arg + 1;
unsigned int mode;
diff --git a/arch/m68k/kernel/entry.S b/arch/m68k/kernel/entry.S
index 603afe9ab..2cb35e67f 100644
--- a/arch/m68k/kernel/entry.S
+++ b/arch/m68k/kernel/entry.S
@@ -52,6 +52,10 @@
#include <linux/linkage.h>
#include <asm/setup.h>
#include <asm/segment.h>
+#ifdef CONFIG_KGDB
+#include <asm/kgdb.h>
+.globl SYMBOL_NAME(kgdb_registers)
+#endif
LENOSYS = 38
@@ -66,7 +70,7 @@ LTASK_BLOCKED = 16
LTASK_FLAGS = 20
/* the following macro is used when enabling interrupts */
-#if defined(CONFIG_ATARI_ONLY)
+#if defined(MACH_ATARI_ONLY)
/* block out HSYNC on the atari */
#define ALLOWINT 0xfbff
#define MAX_NOINT_IPL 3
@@ -87,11 +91,23 @@ LFORMATVEC = 0x2E
* regs are a2-a6 and d6-d7 preserved by C code
* the kernel doesn't mess with usp unless it needs to
*/
+#ifndef CONFIG_KGDB
#define SAVE_ALL \
clrl %sp@-; /* stk_adj */ \
movel %d0,%sp@-; /* orig d0 */ \
movel %d0,%sp@-; /* d0 */ \
moveml %d1-%d5/%a0-%a1,%sp@-
+#else
+/* Need to save the "missing" registers for kgdb...
+ */
+#define SAVE_ALL \
+ clrl %sp@-; /* stk_adj */ \
+ movel %d0,%sp@-; /* orig d0 */ \
+ movel %d0,%sp@-; /* d0 */ \
+ moveml %d1-%d5/%a0-%a1,%sp@-; \
+ moveml %d6-%d7,SYMBOL_NAME(kgdb_registers)+GDBOFFA_D6; \
+ moveml %a2-%a6,SYMBOL_NAME(kgdb_registers)+GDBOFFA_A2
+#endif
#define RESTORE_ALL \
moveml %sp@+,%a0-%a1/%d1-%d5; \
@@ -148,37 +164,18 @@ ENTRY(reschedule)
pea SYMBOL_NAME(ret_from_exception)
jmp SYMBOL_NAME(schedule)
-ENTRY(system_call)
- SAVE_ALL
- movel #-LENOSYS,LD0(%sp) | default return value in d0
- | original D0 is in orig_d0
- movel %d0,%d2
-
- | save top of frame
- pea %sp@
- jbsr SYMBOL_NAME(set_esp0)
- addql #4,%sp
-
- cmpl #NR_syscalls,%d2
- jcc SYMBOL_NAME(ret_from_exception)
- lea SYMBOL_NAME(sys_call_table),%a0
- movel %a0@(%d2:l:4),%d3
- jeq SYMBOL_NAME(ret_from_exception)
- movel SYMBOL_NAME(current_set),%a0
- btst #5,%a0@(LTASK_FLAGS+3) | PF_TRACESYS
- bnes 1f
- movel %d3,%a0
- jbsr %a0@
- movel %d0,%sp@(LD0) | save the return value
+badsys:
+ movel #-LENOSYS,LD0(%sp)
jra SYMBOL_NAME(ret_from_exception)
-1:
+
+do_trace:
+ movel #-LENOSYS,LD0(%sp) | needed for strace
subql #4,%sp
SAVE_SWITCH_STACK
jbsr SYMBOL_NAME(syscall_trace)
RESTORE_SWITCH_STACK
addql #4,%sp
- movel %d3,%a0
- jbsr %a0@
+ jbsr @(SYMBOL_NAME(sys_call_table),%d2:l:4)@(0)
movel %d0,%sp@(LD0) | save the return value
subql #4,%sp | dummy return address
SAVE_SWITCH_STACK
@@ -187,6 +184,24 @@ ENTRY(system_call)
SYMBOL_NAME_LABEL(ret_from_signal)
RESTORE_SWITCH_STACK
addql #4,%sp
+ jra SYMBOL_NAME(ret_from_exception)
+
+ENTRY(system_call)
+ SAVE_ALL
+ movel %d0,%d2
+
+ | save top of frame
+ pea %sp@
+ jbsr SYMBOL_NAME(set_esp0)
+ addql #4,%sp
+
+ cmpl #NR_syscalls,%d2
+ jcc badsys
+ movel SYMBOL_NAME(current_set),%a0
+ btst #5,%a0@(LTASK_FLAGS+3) | PF_TRACESYS
+ jne do_trace
+ jbsr @(SYMBOL_NAME(sys_call_table),%d2:l:4)@(0)
+ movel %d0,%sp@(LD0) | save the return value
SYMBOL_NAME_LABEL(ret_from_exception)
btst #5,%sp@(LSR) | check if returning to kernel
@@ -197,17 +212,8 @@ SYMBOL_NAME_LABEL(ret_from_exception)
cmpl #SYMBOL_NAME(task),%a0 | task[0] cannot have signals
jeq 2f
bclr #5,%a0@(LTASK_FLAGS+1) | check for delayed trace
- jeq 1f
- bclr #7,%sp@(LSR) | clear trace bit in SR
- pea 1 | send SIGTRAP
- movel %a0,%sp@-
- pea 5
- jbsr SYMBOL_NAME(send_sig)
- addql #8,%sp
- addql #4,%sp
- movel SYMBOL_NAME(current_set),%a0
-
-1:
+ jne do_delayed_trace
+5:
tstl %a0@(LTASK_STATE) | state
jne SYMBOL_NAME(reschedule)
tstl %a0@(LTASK_COUNTER) | counter
@@ -234,6 +240,17 @@ Lsignal_return:
addql #4,%sp
RESTORE_ALL
+do_delayed_trace:
+ bclr #7,%sp@(LSR) | clear trace bit in SR
+ pea 1 | send SIGTRAP
+ movel %a0,%sp@-
+ pea 5
+ jbsr SYMBOL_NAME(send_sig)
+ addql #8,%sp
+ addql #4,%sp
+ movel SYMBOL_NAME(current_set),%a0
+ jra 5b
+
/*
** This is the main interrupt handler, responsible for calling process_int()
*/
@@ -243,7 +260,7 @@ SYMBOL_NAME_LABEL(inthandler)
movel %d0,%sp@(LORIG_D0) | a -1 in the ORIG_D0 field
| signifies that the stack frame
| is NOT for syscall
- addql #1,SYMBOL_NAME(intr_count)
+ addql #1,SYMBOL_NAME(local_irq_count)
| put exception # in d0
bfextu %sp@(LFORMATVEC){#4,#10},%d0
@@ -254,27 +271,26 @@ SYMBOL_NAME_LABEL(inthandler)
SYMBOL_NAME_LABEL(ret_from_interrupt)
/* check if we need to do software interrupts */
-1:
- movel SYMBOL_NAME(intr_count),%d1
+ movel SYMBOL_NAME(local_irq_count),%d1
subql #1,%d1
jne 4f
- bfextu %sp@(LSR){#5,#3},%d0 | Check for nested interrupt.
+#if 0
+ bfextu %sp@(LSR){#5,#3},%d0 | Check for nested interrupt.
#if MAX_NOINT_IPL > 0
cmpiw #MAX_NOINT_IPL,%d0
#endif
jhi 4f
-2:
+#endif
movel SYMBOL_NAME(bh_active),%d0
andl SYMBOL_NAME(bh_mask),%d0
- jne 3f
+ jeq 3f
- clrl SYMBOL_NAME(intr_count) | deliver signals, reschedule etc..
- jra SYMBOL_NAME(ret_from_exception)
-3:
jbsr SYMBOL_NAME(do_bottom_half)
- jbra 2b
+3:
+ clrl SYMBOL_NAME(local_irq_count)
+ jra SYMBOL_NAME(ret_from_exception)
4:
- movel %d1,SYMBOL_NAME(intr_count)
+ movel %d1,SYMBOL_NAME(local_irq_count)
RESTORE_ALL
@@ -338,8 +354,10 @@ SYMBOL_NAME_LABEL(resume)
/* save sr */
movew %sr,%a0@(LTSS_SR)
+#if 0
/* disable interrupts */
oriw #0x0700,%sr
+#endif
/* save fs (sfc,%dfc) (may be pointing to kernel memory) */
movec %sfc,%d0
@@ -360,18 +378,18 @@ SYMBOL_NAME_LABEL(resume)
fsave %a0@(LTSS_FPCTXT+27*4)
#if defined(CONFIG_M68060)
-#if !defined(CONFIG_M68060_ONLY)
- btst #3,SYMBOL_NAME(boot_info)+BI_cputype+3
+#if !defined(CPU_M68060_ONLY)
+ btst #3,SYMBOL_NAME(m68k_cputype)+3
beqs 1f
#endif
/* The 060 FPU keeps status in bits 15-8 of the first longword */
tstb %a0@(LTSS_FPCTXT+27*4+2)
jeq 3f
-#if !defined(CONFIG_M68060_ONLY)
+#if !defined(CPU_M68060_ONLY)
jra 2f
#endif
#endif /* CONFIG_M68060 */
-#if !defined(CONFIG_M68060_ONLY)
+#if !defined(CPU_M68060_ONLY)
1: tstb %a0@(LTSS_FPCTXT+27*4)
jeq 3f
#endif
@@ -387,12 +405,12 @@ SYMBOL_NAME_LABEL(resume)
tstb %d2
jne 4f
-#if defined(CONFIG_M68020_OR_M68030) && defined(CONFIG_M68040_OR_M68060)
+#if defined(CPU_M68020_OR_M68030) && defined(CPU_M68040_OR_M68060)
/* 68040 or 68060 ? */
tstl SYMBOL_NAME(m68k_is040or060)
bnes 1f
#endif
-#if defined(CONFIG_M68020_OR_M68030)
+#if defined(CPU_M68020_OR_M68030)
/*
* switch address space
*/
@@ -406,49 +424,51 @@ SYMBOL_NAME_LABEL(resume)
pmove %a1@(LTSS_CRP),%crp
#endif
-#if defined(CONFIG_M68020_OR_M68030) && defined(CONFIG_M68040_OR_M68060)
+#if defined(CPU_M68020_OR_M68030) && defined(CPU_M68040_OR_M68060)
jra 2f /* skip m68040 stuff */
1:
#endif
-#if defined(CONFIG_M68040_OR_M68060)
+#if defined(CPU_M68040_OR_M68060)
/*
* switch address space
*/
+ .chip 68040
/* flush address translation cache (user entries) */
- .word 0xf510 /* pflushan */
+ pflushan
/* switch the root pointer */
movel %a1@(LTSS_CRP+4),%d0
- .long 0x4e7b0806 /* movec d0,urp */
+ movec %d0,%urp
#if defined (CONFIG_M68060)
/* is it a '060 ? */
- btst #3,SYMBOL_NAME(boot_info)+BI_cputype+3
+ btst #3,SYMBOL_NAME(m68k_cputype)+3
beqs 2f
/* clear user entries in the branch cache */
movec %cacr,%d0
orl #0x00200000,%d0
movec %d0,%cacr
#endif /* CONFIG_M68060 */
-#endif /* CONFIG_M68040_OR_M68060 */
+ .chip 68k
+#endif /* CPU_M68040_OR_M68060 */
2:
4:
/* restore floating point context */
#if defined(CONFIG_M68060)
-#if !defined(CONFIG_M68060_ONLY)
- btst #3,SYMBOL_NAME(boot_info)+BI_cputype+3
+#if !defined(CPU_M68060_ONLY)
+ btst #3,SYMBOL_NAME(m68k_cputype)+3
beqs 1f
#endif
/* The 060 FPU keeps status in bits 15-8 of the first longword */
tstb %a1@(LTSS_FPCTXT+27*4+2)
jeq 3f
-#if !defined(CONFIG_M68060_ONLY)
+#if !defined(CPU_M68060_ONLY)
jra 2f
#endif
#endif /* CONFIG_M68060 */
-#if !defined(CONFIG_M68060_ONLY)
+#if !defined(CPU_M68060_ONLY)
1: tstb %a1@(LTSS_FPCTXT+27*4)
jeq 3f
#endif
@@ -592,7 +612,7 @@ SYMBOL_NAME_LABEL(sys_call_table)
.long SYMBOL_NAME(sys_ni_syscall) /* iopl for i386 */ /* 110 */
.long SYMBOL_NAME(sys_vhangup)
.long SYMBOL_NAME(sys_idle)
- .long SYMBOL_NAME(sys_ni_syscall) /* vm86 for i386 */
+ .long SYMBOL_NAME(sys_ni_syscall) /* vm86old for i386 */
.long SYMBOL_NAME(sys_wait4)
.long SYMBOL_NAME(sys_swapoff) /* 115 */
.long SYMBOL_NAME(sys_sysinfo)
@@ -644,5 +664,11 @@ SYMBOL_NAME_LABEL(sys_call_table)
.long SYMBOL_NAME(sys_nanosleep)
.long SYMBOL_NAME(sys_mremap)
.long SYMBOL_NAME(sys_setresuid)
- .long SYMBOL_NAME(sys_getresuid)
- .space (NR_syscalls-165)*4
+ .long SYMBOL_NAME(sys_getresuid) /* 165 */
+ .long SYMBOL_NAME(sys_ni_syscall) /* for vm86 */
+ .long SYMBOL_NAME(sys_query_module)
+ .long SYMBOL_NAME(sys_poll)
+ .long SYMBOL_NAME(sys_nfsservctl)
+ .rept NR_syscalls-(.-SYMBOL_NAME(sys_call_table))/4
+ .long SYMBOL_NAME(sys_ni_syscall)
+ .endr
diff --git a/arch/m68k/kernel/head.S b/arch/m68k/kernel/head.S
index 3dab4b2eb..c2b72aa2d 100644
--- a/arch/m68k/kernel/head.S
+++ b/arch/m68k/kernel/head.S
@@ -67,11 +67,13 @@
#include <linux/config.h>
#include <linux/linkage.h>
+#include <asm/bootinfo.h>
#include <asm/setup.h>
#include <asm/pgtable.h>
.globl SYMBOL_NAME(kernel_pg_dir), SYMBOL_NAME(kpt)
.globl SYMBOL_NAME(availmem), SYMBOL_NAME(is_medusa)
+.globl SYMBOL_NAME(is_hades)
.globl SYMBOL_NAME(m68k_pgtable_cachemode)
.globl SYMBOL_NAME(kernel_pmd_table), SYMBOL_NAME(swapper_pg_dir)
@@ -178,21 +180,29 @@ ENTRY(_start)
lea %pc@(SYMBOL_NAME(_stext):w),%sp
/*
- * Copy bootinfo from position after BSS to final resting place
- */
- lea %pc@(SYMBOL_NAME(_end)),%a0
- lea %pc@(SYMBOL_NAME(boot_info)),%a1
- movel %pc@(SYMBOL_NAME(bisize)),%d0
- subql #1,%d0
-1: moveb %a0@+,%a1@+
- dbra %d0,1b
-
-/*
* Record the CPU and machine type.
*/
- lea %pc@(SYMBOL_NAME(boot_info)),%a0
- movel %a0@(BI_machtype),%d4
- movel %a0@(BI_cputype),%d0
+
+ movew #BI_MACHTYPE,%d0
+ jbsr Lget_bi_record
+ movel %a0@,%d4
+ lea %pc@(SYMBOL_NAME(m68k_machtype)),%a0
+ movel %d4,%a0@
+ movew #BI_FPUTYPE,%d0
+ jbsr Lget_bi_record
+ movel %a0@,%d0
+ lea %pc@(SYMBOL_NAME(m68k_fputype)),%a0
+ movel %d0,%a0@
+ movew #BI_MMUTYPE,%d0
+ jbsr Lget_bi_record
+ movel %a0@,%d0
+ lea %pc@(SYMBOL_NAME(m68k_mmutype)),%a0
+ movel %d0,%a0@
+ movew #BI_CPUTYPE,%d0
+ jbsr Lget_bi_record
+ movel %a0@,%d0
+ lea %pc@(SYMBOL_NAME(m68k_cputype)),%a0
+ movel %d0,%a0@
btst #CPUB_68060,%d0
jeq 1f
@@ -226,18 +236,68 @@ ENTRY(_start)
#endif
/*
+ If running on an Atari, determine the I/O base of the
+ serial port and test if we are running on a Medusa or Hades.
+ This test is necessary here, because on the Hades the serial
+ port is only accessible in the high I/O memory area.
+
+ The test whether it is a Medusa is done by writing to the byte at
+ phys. 0x0. This should result in a bus error on all other machines.
+
+ ...should, but doesn't. The Afterburner040 for the Falcon has the
+ same behaviour (0x0..0x7 are no ROM shadow). So we have to do
+ another test to distinguish Medusa and AB040. This is a
+ read attempt for 0x00ff82fe phys. that should bus error on a Falcon
+ (+AB040), but is in the range where the Medusa always asserts DTACK.
+
+ The test for the Hades is done by reading address 0xb0000000. This
+ should give a bus error on the Medusa.
+ */
+
+#ifdef CONFIG_ATARI
+ is_not_atari(Lnotypetest)
+
+ moveq #0,%d3 /* base addr for others: 0x00000000 */
+ moveq #0,%d2 /* no Hades */
+ movec %d3,%vbr
+ lea %pc@(Ltest_berr),%a0
+ movel %a0,0x8
+ movel %sp,%a0
+ moveb 0x0,%d1
+ clrb 0x0
+ nop
+ moveb %d1,0x0
+ nop
+ tstb 0x00ff82fe
+ nop
+ movel #0xff000000,%d3 /* Medusa base addr: 0xff000000 */
+ tstb 0xb0000000
+ nop
+ movel #0xff000000,%d2 /* Computer is a Hades */
+ moveq #0,%d3
+Ltest_berr:
+ movel %a0,%sp
+ lea %pc@(SYMBOL_NAME(is_hades)),%a0
+ movel %d2,%a0@
+ lea %pc@(SYMBOL_NAME(is_medusa)),%a0
+ movel %d3,%a0@
+Lnotypetest:
+#endif
+
+/*
* Initialize serial port
*/
+
jbsr Lserial_init
putr()
putc('A')
/*
- * Get address at end of kernel code/data/bss and
- * mask off at a page boundary.
+ * Get address at end of bootinfo and mask off at a page boundary.
*/
- lea %pc@(SYMBOL_NAME(_end)),%a0
+ moveq #0,%d0
+ jbsr Lget_bi_record
addw #PAGESIZE-1,%a0
movel %a0,%d0
andl #-PAGESIZE,%d0
@@ -250,10 +310,6 @@ ENTRY(_start)
*/
lea %pc@(SYMBOL_NAME(_stext)-PAGESIZE:w),%a0
movel %a0,%d5
-#ifdef HACKER_KERNEL
- lea %pc@(Lkernel_start),%a0
- movel %d5,%a0@
-#endif
/*
* initialize the kernel root table.
@@ -486,35 +542,16 @@ Lnotami:
For the Medusa it is better to map the I/O region transparently
(i.e. 0xffxxxxxx -> 0xffxxxxxx), because some I/O registers are
- accessible only in the high area. The test whether it is a Medusa
- is done by writing to the byte at phys. 0x0. This should result
- in a bus error on all other machines.
+ accessible only in the high area.
- ...should, but doesn't. The Afterburner040 for the Falcon has the
- same behaviour (0x0..0x7 are no ROM shadow). So we have to do
- another test to distinguish Medusa and AB040. This is a
- read attempt for 0x00ff82fe phys. that should bus error on a Falcon
- (+AB040), but is in the range where the Medusa always asserts DTACK.
+ On the Hades all I/O registers are only accessible in the high
+ area.
*/
- moveq #0,%d3 /* base addr for others: 0x00000000 */
- movec %d3,%vbr
- lea %pc@(Ltest_berr),%a0
- movel %a0,0x8
- movel %sp,%a0
- moveb 0x0,%d1
- clrb 0x0
- nop
- moveb %d1,0x0
- nop
- tstb 0x00ff82fe
- nop
- movel #0xff000000,%d3 /* Medusa base addr: 0xff000000 */
-Ltest_berr:
- movel %a0,%sp
- lea %pc@(SYMBOL_NAME(is_medusa)),%a0
- movel %d3,%a0@
-
+ movel %pc@(is_medusa),%d3
+ bne 1f
+ movel %pc@(is_hades),%d3
+1:
/* Let the root table point to the new pointer table */
lea %a4@(PTR_TABLE_SIZE<<2),%a4
movel %a4,%a0
@@ -637,45 +674,47 @@ Lmapphys:
/* no limit, 4byte descriptors */
movel #0x80000002,%a3@
movel %a5,%a3@(4)
- .long 0xf0134800 /* pmove %a3@,%srp */
- .long 0xf0134c00 /* pmove %a3@,%crp */
- .long 0xf0002400 /* pflusha */
+ pmove %a3@,%srp
+ pmove %a3@,%crp
+ pflusha
/*
* enable,super root enable,4096 byte pages,7 bit root index,
* 7 bit pointer index, 6 bit page table index.
*/
movel #0x82c07760,%a3@
- .long 0xf0134000 /* pmove %a3@,%tc (enable the MMU) */
+ pmove %a3@,%tc /* enable the MMU */
tstl %d0
jne 1f
jmp %pc@(2f+0x80000000)
1: jmp 2f:w
2: movel %d2,%a5@(%d0:w)
- .long 0xf0002400 /* pflusha */
+ pflusha
jmp LdoneMMUenable:w
Lamimmu68040:
+ .chip 68040
lea 2f:w,%a0
movel %d5,%d0
andl #0xff000000,%d0
jne 1f
lea %pc@(2f+0x80000000),%a0
1: orw #TTR_ENABLE+TTR_KERNELMODE+_PAGE_NOCACHE_S,%d0
- .long 0x4e7b0004 /* movec %d0,%itt0 */
- .long 0x4e7bd806 /* movec %a5,%urp */
- .long 0x4e7bd807 /* movec %a5,%srp */
- .word 0xf518 /* pflusha */
+ movec %d0,%itt0
+ movec %a5,%urp
+ movec %a5,%srp
+ pflusha
movel #TC_ENABLE+TC_PAGE4K,%d0
/*
* this value is also ok for the 68060, we don`t use the cache
* mode/protection defaults
*/
- .long 0x4e7b0003 /* movec %d0,%tc (enable the MMU) */
+ movec %d0,%tc /* enable the MMU */
jmp %a0@
2: moveq #0,%d0
- .long 0x4e7b0004 /* movec %d0,%itt0 */
+ movec %d0,%itt0
jmp LdoneMMUenable:w
+ .chip 68k
Lmapphysnotamiga:
#endif
@@ -696,6 +735,7 @@ Lmapphysnotamiga:
is_040_or_060(Latarimmu68040)
+ .chip 68030
lea %pc@(Lmmu),%a3
movel %d5,%d0
jne 1f
@@ -706,7 +746,7 @@ Lmapphysnotamiga:
jeq 2f
orw #TTR_ENABLE+TTR_CI+TTR_RWM+TTR_FCB2+TTR_FCM1+TTR_FCM0,%d0
movel %d0,%a3@
- .long 0xf0130800 /* pmove %a3@,%tt0 */
+ pmove %a3@,%tt0
jra 3f
/* tt0 doesn't work if physical and virtual address of kernel is in
* the same 16M area (Falcon with Magnum/FX, kernel in alternate ram)
@@ -729,23 +769,25 @@ Lmapphysnotamiga:
/* no limit, 4byte descriptors */
3: movel #0x80000002,%a3@
movel %a5,%a3@(4)
- .long 0xf0134800 /* pmove %a3@,%srp */
- .long 0xf0134c00 /* pmove %a3@,%crp */
- .long 0xf0002400 /* pflusha */
+ pmove %a3@,%srp
+ pmove %a3@,%crp
+ pflusha
/*
* enable,super root enable,4096 byte pages,7 bit root index,
* 7 bit pointer index, 6 bit page table index.
*/
movel #0x82c07760,%a3@
- .long 0xf0134000 /* pmove %a3@,%tc (enable the MMU) */
+ pmove %a3@,%tc /* enable the MMU */
jmp %a0@
4: clrl %a3@
- .long 0xf0130800 /* pmove %a3@,%tt0 */
+ pmove %a3@,%tt0
jra LdoneMMUenable
5: movel %d2,%a1@
jra LdoneMMUenable
+ .chip 68k
Latarimmu68040:
+ .chip 68040
movel %d5,%d0
jne 1f
lea LdoneMMUenable:w,%a0
@@ -753,22 +795,22 @@ Latarimmu68040:
1: lea 3f:w,%a0
andl #0xff000000,%d0 /* logical address base */
orw #TTR_ENABLE+TTR_KERNELMODE+_PAGE_NOCACHE_S,%d0
- .long 0x4e7b0004 /* movec %d0,%itt0 */
+ movec %d0,%itt0
2: nop
- .word 0xf518 /* pflusha */
- .long 0x4e7bd807 /* movec %a5,%srp */
- .long 0x4e7bd806 /* movec %a5,%urp */
+ pflusha
+ movec %a5,%srp
+ movec %a5,%urp
movel #TC_ENABLE+TC_PAGE4K,%d0
/*
* this value is also ok for the 68060, we don`t use the cache
* mode/protection defaults
*/
- .long 0x4e7b0003 /* movec %d0,%tc (enable the MMU) */
+ movec %d0,%tc /* enable the MMU */
jmp %a0@
3: moveq #0,%d0
- .long 0x4e7b0004 /* movec %d0,%itt0 */
- tstl %a1
+ movec %d0,%itt0
jra LdoneMMUenable
+ .chip 68k
Lmapphysnotatari:
#endif
@@ -830,7 +872,9 @@ LdoneMMUenable:
jra 1f
Lcache680460:
- .word 0xf4f8 /* cpusha %bc */
+ .chip 68040
+ cpusha %bc
+ .chip 68k
is_060(Lcache68060)
@@ -840,12 +884,14 @@ Lcache680460:
jra 1f
Lcache68060:
+ .chip 68060
movel #CC6_ENABLE_D+CC6_ENABLE_I+CC6_ENABLE_SB+CC6_PUSH_DPI+CC6_ENABLE_B+CC6_CLRA_B,%d0
/* MMU stuff works in copyback mode now, so enable the cache */
movec %d0,%cacr
/* enable superscalar dispatch in PCR */
moveq #1,%d0
- .long 0x4e7b0808 /* movec d0,pcr */
+ movec %d0,%pcr
+ .chip 68k
1:
/*
@@ -859,43 +905,26 @@ Lcache68060:
jbsr SYMBOL_NAME(start_kernel)
/*
- * switch off mmu and exit
+ * Find a tag record in the bootinfo structure
+ * The bootinfo structure is located right after the kernel bss
+ * Returns: d0: size (-1 if not found)
+ * a0: data pointer (end-of-records if not found)
*/
-
-#ifdef HACKER_KERNEL
-ENTRY(kernel_exit)
- lea 2f:w,%a0
- movel %pc@(Lkernel_start),%a0
- lea %a0@(2f:w),%a1
- movel %a1,%d0
- andl #0xff000000,%d0
- jne 1f
- jmp %a0@(1f+0x80000000)
-1: orw #TTR_ENABLE+TTR_KERNELMODE+_PAGE_NOCACHE_S,%d0
- .long 0x4e7b0004 /* movec %d0,%itt0 */
- jmp %a1@
+Lget_bi_record:
+ lea %pc@(SYMBOL_NAME(_end)),%a0
+1: tstw %a0@(BIR_tag)
+ jeq 3f
+ cmpw %a0@(BIR_tag),%d0
+ jeq 2f
+ addw %a0@(BIR_size),%a0
+ jra 1b
2: moveq #0,%d0
- .long 0x4e7b0003 /* movec %d0,%tc (disable the MMU) */
- .word 0xf518 /* pflusha */
- .long 0x4e7b0004 /* movec %d0,%itt0 */
- movec %d0,%cacr
- .word 0xf4f8 /* cpusha %bc */
-
- lea %pc@(SYMBOL_NAME(boot_info)),%a0
- jmp %a0@(BI_amiga_exit_func:w)@(0:w)
-#endif
-
-/*
- * Serial port output support.
- */
-LSERPER = 0xdff032
-LSERDAT = 0xdff030
-LSERDATR = 0xdff018
-LNTSC_PERIOD = 371
-LPAL_PERIOD = 368
-LNTSC_ECLOCK = 7159090
-LSERIAL_CNTRL = 0xbfd000
-LSERIAL_DTR = 7
+ movew %a0@(BIR_size),%d0
+ lea %a0@(BIR_data),%a0
+ rts
+3: moveq #-1,%d0
+ lea %a0@(BIR_size),%a0
+ rts
/*
* Debug output support
@@ -953,8 +982,18 @@ LMFP_UDR = 0xfffa2f
#endif
/*
+ * Serial port output support.
+ */
+LSERPER = 0xdff032
+LSERDAT = 0xdff030
+LSERDATR = 0xdff018
+LSERIAL_CNTRL = 0xbfd000
+LSERIAL_DTR = 7
+
+/*
* Initialize serial port hardware for 9600/8/1
* a0 thrashed
+ * Amiga d0 trashed
* Atari d0 trashed (a1 in case of SCC)
*/
.even
@@ -962,31 +1001,30 @@ Lserial_init:
#ifdef CONFIG_AMIGA
cmpil #MACH_AMIGA,%d4
jne 1f
- lea %pc@(SYMBOL_NAME(boot_info)),%a0
bclr #LSERIAL_DTR,LSERIAL_CNTRL
- movew #LNTSC_PERIOD,LSERPER
- cmpl #LNTSC_ECLOCK,%a0@(BI_amiga_eclock)
- jeq 9f
- movew #LPAL_PERIOD,LSERPER
+ movew #BI_AMIGA_SERPER,%d0
+ jbsr Lget_bi_record
+ movew %a0@,LSERPER
jra 9f
1:
#endif
#ifdef CONFIG_ATARI
cmpil #MACH_ATARI,%d4
jne 4f
+ movel %pc@(Liobase),%a1
#ifdef USE_PRINTER
- bclr #0,LSTMFP_IERB
- bclr #0,LSTMFP_DDR
- moveb #LPSG_CONTROL,LPSG_SELECT
- moveb #0xff,LPSG_WRITE
- moveb #LPSG_IO_B,LPSG_SELECT
- clrb LPSG_WRITE
- moveb #LPSG_IO_A,LPSG_SELECT
- moveb LPSG_READ,%d0
+ bclr #0,%a1@(LSTMFP_IERB)
+ bclr #0,%a1@(LSTMFP_DDR)
+ moveb #LPSG_CONTROL,%a1@(LPSG_SELECT)
+ moveb #0xff,%a1@(LPSG_WRITE)
+ moveb #LPSG_IO_B,%a1@(LPSG_SELECT)
+ clrb %a1@(LPSG_WRITE)
+ moveb #LPSG_IO_A,%a1@(LPSG_SELECT)
+ moveb %a1@(LPSG_READ),%d0
bset #5,%d0
- moveb %d0,LPSG_WRITE
+ moveb %d0,%a1@(LPSG_WRITE)
#elif defined(USE_SCC)
- lea LSCC_CTRL_B,%a0
+ lea %a1@(LSCC_CTRL_B),%a0
lea %pc@(scc_initable:w),%a1
2: moveb %a1@+,%d0
jmi 3f
@@ -995,12 +1033,12 @@ Lserial_init:
jra 2b
3: clrb %a0@
#elif defined(USE_MFP)
- bclr #1,LMFP_TSR
- moveb #0x88,LMFP_UCR
- andb #0x70,LMFP_TDCDR
- moveb #2,LMFP_TDDR
- orb #1,LMFP_TDCDR
- bset #1,LMFP_TSR
+ bclr #1,%a1@(LMFP_TSR)
+ moveb #0x88,%a1@(LMFP_UCR)
+ andb #0x70,%a1@(LMFP_TDCDR)
+ moveb #2,%a1@(LMFP_TDDR)
+ orb #1,%a1@(LMFP_TDCDR)
+ bset #1,%a1@(LMFP_TSR)
#endif
4:
#endif
@@ -1073,8 +1111,6 @@ Lserial_puts:
/*
* Output number in d7 in hex notation on serial port.
- * d0-d2 trashed.
- * d7 trashed.
*/
Lserial_putnum:
@@ -1103,7 +1139,7 @@ Lshowtest:
putc('=')
putn(%a1)
- .long 0xf0119f15 | ptestr #5,%a1@,#7,%a0
+ ptestr #5,%a1@,#7,%a0
putc('D')
putc('A')
@@ -1117,7 +1153,7 @@ Lshowtest:
putc('S')
putc('=')
lea %pc@(Lmmu),%a0
- .long 0xf0106200 | pmove %psr,%a0@
+ pmove %psr,%a0@
clrl %d7
movew %a0@,%d7
jbsr Lserial_putnum
@@ -1128,10 +1164,6 @@ Lshowtest:
.data
.even
-#ifdef HACKER_KERNEL
-Lkernel_start:
- .long 0
-#endif
Lcustom:
Liobase:
.long 0
@@ -1142,5 +1174,7 @@ SYMBOL_NAME_LABEL(availmem)
.long 0
SYMBOL_NAME_LABEL(is_medusa)
.long 0
+SYMBOL_NAME_LABEL(is_hades)
+ .long 0
SYMBOL_NAME_LABEL(m68k_pgtable_cachemode)
.long 0
diff --git a/arch/m68k/kernel/ints.c b/arch/m68k/kernel/ints.c
index 8656b2979..f49c38cd3 100644
--- a/arch/m68k/kernel/ints.c
+++ b/arch/m68k/kernel/ints.c
@@ -50,6 +50,24 @@ volatile unsigned int num_spurious;
#define NUM_IRQ_NODES 100
static irq_node_t nodes[NUM_IRQ_NODES];
+unsigned int local_irq_count[NR_CPUS];
+
+int __m68k_bh_counter;
+
+static void dummy_enable_irq(unsigned int irq);
+static void dummy_disable_irq(unsigned int irq);
+static int dummy_request_irq(unsigned int irq,
+ void (*handler) (int, void *, struct pt_regs *),
+ unsigned long flags, const char *devname, void *dev_id);
+static void dummy_free_irq(unsigned int irq, void *dev_id);
+
+void (*enable_irq) (unsigned int) = dummy_enable_irq;
+void (*disable_irq) (unsigned int) = dummy_disable_irq;
+
+int (*mach_request_irq) (unsigned int, void (*)(int, void *, struct pt_regs *),
+ unsigned long, const char *, void *) = dummy_request_irq;
+void (*mach_free_irq) (unsigned int, void *) = dummy_free_irq;
+
/*
* void init_IRQ(void)
*
@@ -92,14 +110,30 @@ irq_node_t *new_irq_node(void)
return NULL;
}
-int request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *),
- unsigned long flags, const char *devname, void *dev_id)
+/*
+ * We will keep these functions until I have convinced Linus to move
+ * the declaration of them from include/linux/sched.h to
+ * include/asm/irq.h.
+ */
+int request_irq(unsigned int irq,
+ void (*handler) (int, void *, struct pt_regs *),
+ unsigned long flags, const char *devname, void *dev_id)
{
- if (irq & IRQ_MACHSPEC)
- return mach_request_irq(IRQ_IDX(irq), handler, flags, devname, dev_id);
+ return mach_request_irq(irq, handler, flags, devname, dev_id);
+}
+
+void free_irq(unsigned int irq, void *dev_id)
+{
+ mach_free_irq(irq, dev_id);
+}
+int sys_request_irq(unsigned int irq,
+ void (*handler)(int, void *, struct pt_regs *),
+ unsigned long flags, const char *devname, void *dev_id)
+{
if (irq < IRQ1 || irq > IRQ7) {
- printk("%s: Incorrect IRQ %d from %s\n", __FUNCTION__, irq, devname);
+ printk("%s: Incorrect IRQ %d from %s\n",
+ __FUNCTION__, irq, devname);
return -ENXIO;
}
@@ -109,7 +143,7 @@ int request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *)
__FUNCTION__, irq, irq_list[irq].devname);
return -EBUSY;
}
- if (flags & IRQ_FLG_REPLACE) {
+ if (!(flags & IRQ_FLG_REPLACE)) {
printk("%s: %s can't replace IRQ %d from %s\n",
__FUNCTION__, devname, irq, irq_list[irq].devname);
return -EBUSY;
@@ -122,13 +156,8 @@ int request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *)
return 0;
}
-void free_irq(unsigned int irq, void *dev_id)
+void sys_free_irq(unsigned int irq, void *dev_id)
{
- if (irq & IRQ_MACHSPEC) {
- mach_free_irq(IRQ_IDX(irq), dev_id);
- return;
- }
-
if (irq < IRQ1 || irq > IRQ7) {
printk("%s: Incorrect IRQ %d\n", __FUNCTION__, irq);
return;
@@ -157,31 +186,42 @@ int probe_irq_off (unsigned long irqs)
return 0;
}
-void enable_irq(unsigned int irq)
+static void dummy_enable_irq(unsigned int irq)
+{
+ printk("calling uninitialized enable_irq()\n");
+}
+
+static void dummy_disable_irq(unsigned int irq)
+{
+ printk("calling uninitialized disable_irq()\n");
+}
+
+static int dummy_request_irq(unsigned int irq,
+ void (*handler) (int, void *, struct pt_regs *),
+ unsigned long flags, const char *devname, void *dev_id)
{
- if ((irq & IRQ_MACHSPEC) && mach_enable_irq)
- mach_enable_irq(IRQ_IDX(irq));
+ printk("calling uninitialized request_irq()\n");
+ return 0;
}
-void disable_irq(unsigned int irq)
+static void dummy_free_irq(unsigned int irq, void *dev_id)
{
- if ((irq & IRQ_MACHSPEC) && mach_disable_irq)
- mach_disable_irq(IRQ_IDX(irq));
+ printk("calling uninitialized disable_irq()\n");
}
asmlinkage void process_int(unsigned long vec, struct pt_regs *fp)
{
- if (vec < VEC_INT1 || vec > VEC_INT7) {
+ if (vec >= VEC_INT1 && vec <= VEC_INT7) {
+ vec -= VEC_SPUR;
+ kstat.interrupts[vec]++;
+ irq_list[vec].handler(vec, irq_list[vec].dev_id, fp);
+ } else {
if (mach_process_int)
mach_process_int(vec, fp);
else
panic("Can't process interrupt vector %ld\n", vec);
return;
}
-
- vec -= VEC_SPUR;
- kstat.interrupts[vec]++;
- irq_list[vec].handler(vec, irq_list[vec].dev_id, fp);
}
int get_irq_list(char *buf)
diff --git a/arch/m68k/kernel/ksyms.c b/arch/m68k/kernel/ksyms.c
deleted file mode 100644
index bf067c782..000000000
--- a/arch/m68k/kernel/ksyms.c
+++ /dev/null
@@ -1,89 +0,0 @@
-#include <linux/config.h>
-#include <linux/module.h>
-#include <linux/linkage.h>
-#include <linux/sched.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/user.h>
-#include <linux/elfcore.h>
-
-#include <asm/setup.h>
-#include <asm/pgtable.h>
-#include <asm/irq.h>
-#include <asm/semaphore.h>
-
-asmlinkage long long __ashrdi3 (long long, int);
-extern char m68k_debug_device[];
-
-#ifdef CONFIG_ATARI
-extern void mach_atari_syms_export (void);
-#endif
-#ifdef CONFIG_AMIGA
-extern void mach_amiga_syms_export (void);
-#endif
-#ifdef CONFIG_MAC
-extern void mach_mac_syms_export (void);
-#endif
-
-extern void dump_thread(struct pt_regs *, struct user *);
-extern int dump_fpu(elf_fpregset_t *);
-
-static struct symbol_table arch_symbol_table = {
-#include <linux/symtab_begin.h>
- /* platform dependent support */
-
- X(memcmp),
- X(boot_info),
- X(m68k_is040or060),
- X(cache_push),
- X(cache_push_v),
- X(cache_clear),
- X(mm_vtop),
- X(mm_ptov),
- X(mm_end_of_chunk),
- X(m68k_debug_device),
- X(request_irq),
- X(free_irq),
- X(dump_fpu),
- X(dump_thread),
- X(strnlen),
- X(strrchr),
-
- /* The following are special because they're not called
- explicitly (the C compiler generates them). Fortunately,
- their interface isn't gonna change any time soon now, so
- it's OK to leave it out of version control. */
- XNOVERS(__ashrdi3),
- XNOVERS(memcpy),
- XNOVERS(memset),
-
- XNOVERS(__down_failed),
- XNOVERS(__up_wakeup),
-
-#include <linux/symtab_end.h>
-};
-
-void arch_syms_export(void)
-{
- register_symtab(&arch_symbol_table);
-
- switch (boot_info.machtype) {
-#ifdef CONFIG_ATARI
- case MACH_ATARI:
- mach_atari_syms_export();
- break;
-#endif
-#ifdef CONFIG_AMIGA
- case MACH_AMIGA:
- mach_amiga_syms_export();
- break;
-#endif
-#ifdef CONFIG_MAC
- case MACH_MAC:
- mach_mac_syms_export();
- break;
-#endif
- default:
- break;
- }
-}
diff --git a/arch/m68k/kernel/m68k_ksyms.c b/arch/m68k/kernel/m68k_ksyms.c
new file mode 100644
index 000000000..3138d99df
--- /dev/null
+++ b/arch/m68k/kernel/m68k_ksyms.c
@@ -0,0 +1,57 @@
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/linkage.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/user.h>
+#include <linux/elfcore.h>
+
+#include <asm/setup.h>
+#include <asm/machdep.h>
+#include <asm/pgtable.h>
+#include <asm/irq.h>
+#include <asm/semaphore.h>
+#include <asm/checksum.h>
+#include <asm/hardirq.h>
+
+asmlinkage long long __ashrdi3 (long long, int);
+extern char m68k_debug_device[];
+
+extern void dump_thread(struct pt_regs *, struct user *);
+extern int dump_fpu(elf_fpregset_t *);
+
+/* platform dependent support */
+
+EXPORT_SYMBOL(memcmp);
+EXPORT_SYMBOL(m68k_machtype);
+EXPORT_SYMBOL(m68k_cputype);
+EXPORT_SYMBOL(m68k_is040or060);
+EXPORT_SYMBOL(cache_push);
+EXPORT_SYMBOL(cache_push_v);
+EXPORT_SYMBOL(cache_clear);
+EXPORT_SYMBOL(mm_vtop);
+EXPORT_SYMBOL(mm_ptov);
+EXPORT_SYMBOL(mm_end_of_chunk);
+EXPORT_SYMBOL(m68k_debug_device);
+EXPORT_SYMBOL(dump_fpu);
+EXPORT_SYMBOL(dump_thread);
+EXPORT_SYMBOL(strnlen);
+EXPORT_SYMBOL(strrchr);
+EXPORT_SYMBOL(strstr);
+EXPORT_SYMBOL(local_irq_count);
+
+/* Networking helper routines. */
+EXPORT_SYMBOL(csum_partial_copy);
+
+/* The following are special because they're not called
+ explicitly (the C compiler generates them). Fortunately,
+ their interface isn't gonna change any time soon now, so
+ it's OK to leave it out of version control. */
+EXPORT_SYMBOL_NOVERS(__ashrdi3);
+EXPORT_SYMBOL_NOVERS(memcpy);
+EXPORT_SYMBOL_NOVERS(memset);
+
+EXPORT_SYMBOL_NOVERS(__down_failed);
+EXPORT_SYMBOL_NOVERS(__down_failed_interruptible);
+EXPORT_SYMBOL_NOVERS(__up_wakeup);
diff --git a/arch/m68k/kernel/process.c b/arch/m68k/kernel/process.c
index cc9664b5f..5422831a8 100644
--- a/arch/m68k/kernel/process.c
+++ b/arch/m68k/kernel/process.c
@@ -14,12 +14,15 @@
#include <linux/sched.h>
#include <linux/kernel.h>
#include <linux/mm.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
#include <linux/stddef.h>
#include <linux/unistd.h>
#include <linux/ptrace.h>
#include <linux/malloc.h>
#include <linux/user.h>
#include <linux/a.out.h>
+#include <linux/reboot.h>
#include <asm/uaccess.h>
#include <asm/system.h>
@@ -34,21 +37,40 @@ asmlinkage void ret_from_exception(void);
*/
asmlinkage int sys_idle(void)
{
+ int ret = -EPERM;
+
+ lock_kernel();
if (current->pid != 0)
- return -EPERM;
+ goto out;
/* endless idle loop with no priority at all */
+ current->priority = -100;
current->counter = -100;
for (;;)
schedule();
+ ret = 0;
+out:
+ unlock_kernel();
+ return ret;
}
-void hard_reset_now(void)
+void machine_restart(char * __unused)
{
if (mach_reset)
mach_reset();
}
+void machine_halt(void)
+{
+}
+
+void machine_power_off(void)
+{
+#if defined(CONFIG_APM) && defined(CONFIG_APM_POWER_OFF)
+ apm_set_power_state(APM_STATE_OFF);
+#endif
+}
+
void show_regs(struct pt_regs * regs)
{
printk("\n");
@@ -86,27 +108,36 @@ void flush_thread(void)
asmlinkage int m68k_fork(struct pt_regs *regs)
{
- return do_fork(SIGCHLD, rdusp(), regs);
+ int ret;
+
+ lock_kernel();
+ ret = do_fork(SIGCHLD, rdusp(), regs);
+ unlock_kernel();
+ return ret;
}
asmlinkage int m68k_clone(struct pt_regs *regs)
{
unsigned long clone_flags;
unsigned long newsp;
+ int ret;
+ lock_kernel();
/* syscall2 puts clone_flags in d1 and usp in d2 */
clone_flags = regs->d1;
newsp = regs->d2;
if (!newsp)
newsp = rdusp();
- return do_fork(clone_flags, newsp, regs);
+ ret = do_fork(clone_flags, newsp, regs);
+ unlock_kernel();
+ return ret;
}
void release_thread(struct task_struct *dead_task)
{
}
-void copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
+int copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
struct task_struct * p, struct pt_regs * regs)
{
struct pt_regs * childregs;
@@ -145,11 +176,13 @@ void copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
: "memory");
/* Restore the state in case the fpu was busy */
asm volatile ("frestore %0" : : "m" (p->tss.fpstate[0]));
+
+ return 0;
}
/* Fill in the fpu structure for a core dump. */
-int dump_fpu (struct user_m68kfp_struct *fpu)
+int dump_fpu (struct pt_regs *regs, struct user_m68kfp_struct *fpu)
{
char fpustate[216];
@@ -187,7 +220,7 @@ void dump_thread(struct pt_regs * regs, struct user * dump)
if (dump->start_stack < TASK_SIZE)
dump->u_ssize = ((unsigned long) (TASK_SIZE - dump->start_stack)) >> PAGE_SHIFT;
- dump->u_ar0 = (struct pt_regs *)(((int)(&dump->regs)) -((int)(dump)));
+ dump->u_ar0 = (struct user_regs_struct *)((int)&dump->regs - (int)dump);
sw = ((struct switch_stack *)regs) - 1;
dump->regs.d1 = regs->d1;
dump->regs.d2 = regs->d2;
@@ -210,7 +243,7 @@ void dump_thread(struct pt_regs * regs, struct user * dump)
dump->regs.pc = regs->pc;
dump->regs.fmtvec = (regs->format << 12) | regs->vector;
/* dump floating point stuff */
- dump->u_fpvalid = dump_fpu (&dump->m68kfp);
+ dump->u_fpvalid = dump_fpu (regs, &dump->m68kfp);
}
/*
@@ -222,10 +255,13 @@ asmlinkage int sys_execve(char *name, char **argv, char **envp)
char * filename;
struct pt_regs *regs = (struct pt_regs *) &name;
+ lock_kernel();
error = getname(name, &filename);
if (error)
- return error;
+ goto out;
error = do_execve(filename, argv, envp, regs);
putname(filename);
+out:
+ unlock_kernel();
return error;
}
diff --git a/arch/m68k/kernel/ptrace.c b/arch/m68k/kernel/ptrace.c
index dc48a2ec5..70e341b31 100644
--- a/arch/m68k/kernel/ptrace.c
+++ b/arch/m68k/kernel/ptrace.c
@@ -14,6 +14,8 @@
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/mm.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
#include <linux/errno.h>
#include <linux/ptrace.h>
#include <linux/user.h>
@@ -322,25 +324,28 @@ static int write_long(struct task_struct * tsk, unsigned long addr,
asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
{
struct task_struct *child;
- struct user * dummy;
-
- dummy = NULL;
+ int ret;
+ lock_kernel();
+ ret = -EPERM;
if (request == PTRACE_TRACEME) {
/* are we already being traced? */
if (current->flags & PF_PTRACED)
- return -EPERM;
+ goto out;
/* set the ptrace bit in the process flags. */
current->flags |= PF_PTRACED;
- return 0;
+ ret = 0;
+ goto out;
}
if (pid == 1) /* you may not mess with init */
- return -EPERM;
+ goto out;
+ ret = -ESRCH;
if (!(child = get_task(pid)))
- return -ESRCH;
+ goto out;
+ ret = -EPERM;
if (request == PTRACE_ATTACH) {
if (child == current)
- return -EPERM;
+ goto out;
if ((!child->dumpable ||
(current->uid != child->euid) ||
(current->uid != child->suid) ||
@@ -348,10 +353,10 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
(current->gid != child->egid) ||
(current->gid != child->sgid) ||
(current->gid != child->gid)) && !suser())
- return -EPERM;
+ goto out;
/* the same process cannot be attached many times */
if (child->flags & PF_PTRACED)
- return -EPERM;
+ goto out;
child->flags |= PF_PTRACED;
if (child->p_pptr != current) {
REMOVE_LINKS(child);
@@ -359,39 +364,42 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
SET_LINKS(child);
}
send_sig(SIGSTOP, child, 1);
- return 0;
+ ret = 0;
+ goto out;
}
+ ret = -ESRCH;
if (!(child->flags & PF_PTRACED))
- return -ESRCH;
+ goto out;
if (child->state != TASK_STOPPED) {
if (request != PTRACE_KILL)
- return -ESRCH;
+ goto out;
}
if (child->p_pptr != current)
- return -ESRCH;
+ goto out;
switch (request) {
/* when I and D space are separate, these will need to be fixed. */
case PTRACE_PEEKTEXT: /* read word at location addr. */
case PTRACE_PEEKDATA: {
unsigned long tmp;
- int res;
- res = read_long(child, addr, &tmp);
- if (res < 0)
- return res;
- return put_user(tmp, (unsigned long *) data);
+ ret = read_long(child, addr, &tmp);
+ if (ret >= 0)
+ ret = put_user(tmp, (unsigned long *) data);
+ goto out;
}
/* read the word at location addr in the USER area. */
case PTRACE_PEEKUSR: {
unsigned long tmp;
+ ret = -EIO;
if ((addr & 3) || addr < 0 || addr >= sizeof(struct user))
- return -EIO;
+ goto out;
tmp = 0; /* Default return condition */
addr = addr >> 2; /* temporary hack. */
+ ret = -EIO;
if (addr < 19) {
tmp = get_reg(child, addr);
if (addr == PT_SR)
@@ -400,23 +408,26 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
else if (addr >= 21 && addr < 49)
tmp = child->tss.fp[addr - 21];
else
- return -EIO;
- return put_user(tmp,(unsigned long *) data);
+ goto out;
+ ret = put_user(tmp,(unsigned long *) data);
+ goto out;
}
/* when I and D space are separate, this will have to be fixed. */
case PTRACE_POKETEXT: /* write the word at location addr. */
case PTRACE_POKEDATA:
- return write_long(child,addr,data);
+ ret = write_long(child,addr,data);
+ goto out;
case PTRACE_POKEUSR: /* write the word at location addr in the USER area */
+ ret = -EIO;
if ((addr & 3) || addr < 0 || addr >= sizeof(struct user))
- return -EIO;
+ goto out;
addr = addr >> 2; /* temporary hack. */
if (addr == PT_ORIG_D0)
- return -EIO;
+ goto out;
if (addr == PT_SR) {
data &= SR_MASK;
data <<= 16;
@@ -424,22 +435,24 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
}
if (addr < 19) {
if (put_reg(child, addr, data))
- return -EIO;
- return 0;
+ goto out;
+ ret = 0;
+ goto out;
}
if (addr >= 21 && addr < 48)
{
child->tss.fp[addr - 21] = data;
- return 0;
+ ret = 0;
}
- return -EIO;
+ goto out;
case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */
case PTRACE_CONT: { /* restart after signal. */
long tmp;
+ ret = -EIO;
if ((unsigned long) data >= NSIG)
- return -EIO;
+ goto out;
if (request == PTRACE_SYSCALL)
child->flags |= PF_TRACESYS;
else
@@ -449,7 +462,8 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
/* make sure the single step bit is not set. */
tmp = get_reg(child, PT_SR) & ~(TRACE_BITS << 16);
put_reg(child, PT_SR, tmp);
- return 0;
+ ret = 0;
+ goto out;
}
/*
@@ -460,21 +474,23 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
case PTRACE_KILL: {
long tmp;
+ ret = 0;
if (child->state == TASK_ZOMBIE) /* already dead */
- return 0;
+ goto out;
wake_up_process(child);
child->exit_code = SIGKILL;
/* make sure the single step bit is not set. */
tmp = get_reg(child, PT_SR) & ~(TRACE_BITS << 16);
put_reg(child, PT_SR, tmp);
- return 0;
+ goto out;
}
case PTRACE_SINGLESTEP: { /* set the trap flag. */
long tmp;
+ ret = -EIO;
if ((unsigned long) data >= NSIG)
- return -EIO;
+ goto out;
child->flags &= ~PF_TRACESYS;
tmp = get_reg(child, PT_SR) | (TRACE_BITS << 16);
put_reg(child, PT_SR, tmp);
@@ -482,14 +498,16 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
wake_up_process(child);
child->exit_code = data;
/* give it a chance to run. */
- return 0;
+ ret = 0;
+ goto out;
}
case PTRACE_DETACH: { /* detach a process that was attached. */
long tmp;
+ ret = -EIO;
if ((unsigned long) data >= NSIG)
- return -EIO;
+ goto out;
child->flags &= ~(PF_PTRACED|PF_TRACESYS);
wake_up_process(child);
child->exit_code = data;
@@ -499,19 +517,25 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
/* make sure the single step bit is not set. */
tmp = get_reg(child, PT_SR) & ~(TRACE_BITS << 16);
put_reg(child, PT_SR, tmp);
- return 0;
+ ret = 0;
+ goto out;
}
default:
- return -EIO;
+ ret = -EIO;
+ goto out;
}
+out:
+ unlock_kernel();
+ return ret;
}
asmlinkage void syscall_trace(void)
{
+ lock_kernel();
if ((current->flags & (PF_PTRACED|PF_TRACESYS))
!= (PF_PTRACED|PF_TRACESYS))
- return;
+ goto out;
current->exit_code = SIGTRAP;
current->state = TASK_STOPPED;
notify_parent(current);
@@ -524,5 +548,6 @@ asmlinkage void syscall_trace(void)
if (current->exit_code)
current->signal |= (1 << (current->exit_code - 1));
current->exit_code = 0;
- return;
+out:
+ unlock_kernel();
}
diff --git a/arch/m68k/kernel/setup.c b/arch/m68k/kernel/setup.c
index 58987d1cc..dfd91d0d4 100644
--- a/arch/m68k/kernel/setup.c
+++ b/arch/m68k/kernel/setup.c
@@ -19,19 +19,26 @@
#include <linux/errno.h>
#include <linux/string.h>
+#include <asm/bootinfo.h>
#include <asm/setup.h>
#include <asm/irq.h>
#include <asm/machdep.h>
-#include <asm/amigatypes.h>
+#ifdef CONFIG_AMIGA
#include <asm/amigahw.h>
+#endif
+#ifdef CONFIG_ATARI
+#include <asm/atarihw.h>
+#endif
#ifdef CONFIG_BLK_DEV_INITRD
#include <linux/blk.h>
#include <asm/pgtable.h>
#endif
-struct bootinfo boot_info = {0,};
-int bisize = sizeof boot_info;
+u_long m68k_machtype;
+u_long m68k_cputype;
+u_long m68k_fputype;
+u_long m68k_mmutype;
int m68k_is040or060 = 0;
@@ -40,12 +47,13 @@ char m68k_debug_device[6] = "";
extern int end;
extern unsigned long availmem;
-char saved_command_line[CL_SIZE];
+int m68k_num_memory = 0;
+struct mem_info m68k_memory[NUM_MEMINFO];
-/* setup some dummy routines */
-static void dummy_waitbut(void)
-{
-}
+static struct mem_info m68k_ramdisk = { 0, 0 };
+
+static char m68k_command_line[CL_SIZE];
+char saved_command_line[CL_SIZE];
void (*mach_sched_init) (void (*handler)(int, void *, struct pt_regs *));
/* machine dependent keyboard functions */
@@ -55,11 +63,8 @@ void (*mach_kbd_leds) (unsigned int) = NULL;
/* machine dependent irq functions */
void (*mach_init_IRQ) (void);
void (*(*mach_default_handler)[]) (int, void *, struct pt_regs *) = NULL;
-int (*mach_request_irq) (unsigned int, void (*)(int, void *, struct pt_regs *),
- unsigned long, const char *, void *);
-int (*mach_free_irq) (unsigned int, void *);
-void (*mach_enable_irq) (unsigned int) = NULL;
-void (*mach_disable_irq) (unsigned int) = NULL;
+void (*mach_get_model) (char *model) = NULL;
+int (*mach_get_hardware_list) (char *buffer) = NULL;
int (*mach_get_irq_list) (char *) = NULL;
void (*mach_process_int) (int, struct pt_regs *) = NULL;
/* machine dependent timer functions */
@@ -67,12 +72,9 @@ unsigned long (*mach_gettimeoffset) (void);
void (*mach_gettod) (int*, int*, int*, int*, int*, int*);
int (*mach_hwclk) (int, struct hwclk_time*) = NULL;
int (*mach_set_clock_mmss) (unsigned long) = NULL;
-void (*mach_mksound)( unsigned int count, unsigned int ticks );
void (*mach_reset)( void );
-void (*waitbut)(void) = dummy_waitbut;
struct fb_info *(*mach_fb_init)(long *);
long mach_max_dma_address = 0x00ffffff; /* default set to the lower 16MB */
-void (*mach_debug_init)(void);
void (*mach_video_setup) (char *, int *);
#ifdef CONFIG_BLK_DEV_FD
int (*mach_floppy_init) (void) = NULL;
@@ -80,39 +82,75 @@ void (*mach_floppy_setup) (char *, int *) = NULL;
void (*mach_floppy_eject) (void) = NULL;
#endif
+extern int amiga_parse_bootinfo(const struct bi_record *);
+extern int atari_parse_bootinfo(const struct bi_record *);
+
extern void config_amiga(void);
extern void config_atari(void);
extern void config_mac(void);
extern void config_sun3(void);
+extern void config_apollo(void);
-extern void register_console(void (*proc)(const char *));
-extern void ami_serial_print (const char *str);
-extern void ata_serial_print (const char *str);
+#define MASK_256K 0xfffc0000
-extern void (*kd_mksound)(unsigned int, unsigned int);
-extern void amiga_get_model(char *model);
-extern void atari_get_model(char *model);
-extern void mac_get_model(char *model);
-extern int amiga_get_hardware_list(char *buffer);
-extern int atari_get_hardware_list(char *buffer);
-extern int mac_get_hardware_list(char *buffer);
+static void m68k_parse_bootinfo(const struct bi_record *record)
+{
+ while (record->tag != BI_LAST) {
+ int unknown = 0;
+ const u_long *data = record->data;
+ switch (record->tag) {
+ case BI_MACHTYPE:
+ case BI_CPUTYPE:
+ case BI_FPUTYPE:
+ case BI_MMUTYPE:
+ /* Already set up by head.S */
+ break;
-#define MASK_256K 0xfffc0000
+ case BI_MEMCHUNK:
+ if (m68k_num_memory < NUM_MEMINFO) {
+ m68k_memory[m68k_num_memory].addr = data[0];
+ m68k_memory[m68k_num_memory].size = data[1];
+ m68k_num_memory++;
+ } else
+ printk("m68k_parse_bootinfo: too many memory chunks\n");
+ break;
-void setup_arch(char **cmdline_p,
- unsigned long * memory_start_p, unsigned long * memory_end_p)
+ case BI_RAMDISK:
+ m68k_ramdisk.addr = data[0];
+ m68k_ramdisk.size = data[1];
+ break;
+
+ case BI_COMMAND_LINE:
+ strncpy(m68k_command_line, (const char *)data, CL_SIZE);
+ m68k_command_line[CL_SIZE-1] = '\0';
+ break;
+
+ default:
+ if (MACH_IS_AMIGA)
+ unknown = amiga_parse_bootinfo(record);
+ else if (MACH_IS_ATARI)
+ unknown = atari_parse_bootinfo(record);
+ else
+ unknown = 1;
+ }
+ if (unknown)
+ printk("m68k_parse_bootinfo: unknown tag 0x%04x ignored\n",
+ record->tag);
+ record = (struct bi_record *)((u_long)record+record->size);
+ }
+}
+
+void setup_arch(char **cmdline_p, unsigned long * memory_start_p,
+ unsigned long * memory_end_p)
{
unsigned long memory_start, memory_end;
extern int _etext, _edata, _end;
int i;
char *p, *q;
- if (MACH_IS_AMIGA)
- register_console(ami_serial_print);
-
- if (MACH_IS_ATARI)
- register_console(ata_serial_print);
+ /* The bootinfo is located right after the kernel bss */
+ m68k_parse_bootinfo((const struct bi_record *)&_end);
if (CPU_IS_040)
m68k_is040or060 = 4;
@@ -120,7 +158,7 @@ void setup_arch(char **cmdline_p,
m68k_is040or060 = 6;
/* clear the fpu if we have one */
- if (boot_info.cputype & (FPU_68881|FPU_68882|FPU_68040|FPU_68060)) {
+ if (m68k_fputype & (FPU_68881|FPU_68882|FPU_68040|FPU_68060)) {
volatile int zero = 0;
asm __volatile__ ("frestore %0" : : "m" (zero));
}
@@ -128,15 +166,15 @@ void setup_arch(char **cmdline_p,
memory_start = availmem;
memory_end = 0;
- for (i = 0; i < boot_info.num_memory; i++)
- memory_end += boot_info.memory[i].size & MASK_256K;
+ for (i = 0; i < m68k_num_memory; i++)
+ memory_end += m68k_memory[i].size & MASK_256K;
init_task.mm->start_code = 0;
init_task.mm->end_code = (unsigned long) &_etext;
init_task.mm->end_data = (unsigned long) &_edata;
init_task.mm->brk = (unsigned long) &_end;
- *cmdline_p = boot_info.command_line;
+ *cmdline_p = m68k_command_line;
memcpy(saved_command_line, *cmdline_p, CL_SIZE);
/* Parse the command line for arch-specific options.
@@ -166,7 +204,7 @@ void setup_arch(char **cmdline_p,
*memory_start_p = memory_start;
*memory_end_p = memory_end;
- switch (boot_info.machtype) {
+ switch (m68k_machtype) {
#ifdef CONFIG_AMIGA
case MACH_AMIGA:
config_amiga();
@@ -187,21 +225,26 @@ void setup_arch(char **cmdline_p,
config_sun3();
break;
#endif
+#ifdef CONFIG_APOLLO
+ case MACH_APOLLO:
+ config_apollo();
+ break;
+#endif
default:
panic ("No configuration setup");
}
#ifdef CONFIG_BLK_DEV_INITRD
- if (boot_info.ramdisk_size) {
- initrd_start = PTOV (boot_info.ramdisk_addr);
- initrd_end = initrd_start + boot_info.ramdisk_size * 1024;
+ if (m68k_ramdisk.size) {
+ initrd_start = PTOV (m68k_ramdisk.addr);
+ initrd_end = initrd_start + m68k_ramdisk.size;
}
#endif
}
int get_cpuinfo(char * buffer)
{
- char *cpu, *mmu, *fpu;
+ const char *cpu, *mmu, *fpu;
u_long clockfreq, clockfactor;
#define LOOP_CYCLES_68020 (8)
@@ -211,33 +254,49 @@ int get_cpuinfo(char * buffer)
if (CPU_IS_020) {
cpu = "68020";
- mmu = "68851";
clockfactor = LOOP_CYCLES_68020;
} else if (CPU_IS_030) {
- cpu = mmu = "68030";
+ cpu = "68030";
clockfactor = LOOP_CYCLES_68030;
} else if (CPU_IS_040) {
- cpu = mmu = "68040";
+ cpu = "68040";
clockfactor = LOOP_CYCLES_68040;
} else if (CPU_IS_060) {
- cpu = mmu = "68060";
+ cpu = "68060";
clockfactor = LOOP_CYCLES_68060;
} else {
- cpu = mmu = "680x0";
+ cpu = "680x0";
clockfactor = 0;
}
- if (boot_info.cputype & FPU_68881)
+ if (m68k_fputype & FPU_68881)
fpu = "68881";
- else if (boot_info.cputype & FPU_68882)
+ else if (m68k_fputype & FPU_68882)
fpu = "68882";
- else if (boot_info.cputype & FPU_68040)
+ else if (m68k_fputype & FPU_68040)
fpu = "68040";
- else if (boot_info.cputype & FPU_68060)
+ else if (m68k_fputype & FPU_68060)
fpu = "68060";
+ else if (m68k_fputype & FPU_SUNFPA)
+ fpu = "Sun FPA";
else
fpu = "none";
+ if (m68k_mmutype & MMU_68851)
+ mmu = "68851";
+ else if (m68k_mmutype & MMU_68030)
+ mmu = "68030";
+ else if (m68k_mmutype & MMU_68040)
+ mmu = "68040";
+ else if (m68k_mmutype & MMU_68060)
+ mmu = "68060";
+ else if (m68k_mmutype & MMU_SUN3)
+ mmu = "Sun-3";
+ else if (m68k_mmutype & MMU_APOLLO)
+ mmu = "Apollo";
+ else
+ mmu = "unknown";
+
clockfreq = loops_per_sec*clockfactor;
return(sprintf(buffer, "CPU:\t\t%s\n"
@@ -260,48 +319,19 @@ int get_hardware_list(char *buffer)
u_long mem;
int i;
- switch (boot_info.machtype) {
-#ifdef CONFIG_AMIGA
- case MACH_AMIGA:
- amiga_get_model(model);
- break;
-#endif
-#ifdef CONFIG_ATARI
- case MACH_ATARI:
- atari_get_model(model);
- break;
-#endif
-#ifdef CONFIG_MAC
- case MACH_MAC:
- mac_get_model(model);
- break;
-#endif
- default:
- strcpy(model, "Unknown m68k");
- } /* boot_info.machtype */
+ if (mach_get_model)
+ mach_get_model(model);
+ else
+ strcpy(model, "Unknown m68k");
len += sprintf(buffer+len, "Model:\t\t%s\n", model);
len += get_cpuinfo(buffer+len);
- for (mem = 0, i = 0; i < boot_info.num_memory; i++)
- mem += boot_info.memory[i].size;
+ for (mem = 0, i = 0; i < m68k_num_memory; i++)
+ mem += m68k_memory[i].size;
len += sprintf(buffer+len, "System Memory:\t%ldK\n", mem>>10);
- switch (boot_info.machtype) {
-#ifdef CONFIG_AMIGA
- case MACH_AMIGA:
- len += amiga_get_hardware_list(buffer+len);
- break;
-#endif
-#ifdef CONFIG_ATARI
- case MACH_ATARI:
- len += atari_get_hardware_list(buffer+len);
- break;
-#endif
-#ifdef CONFIG_MAC
- case MACH_MAC:
- break;
-#endif
- } /* boot_info.machtype */
+ if (mach_get_hardware_list)
+ len += mach_get_hardware_list(buffer+len);
return(len);
}
diff --git a/arch/m68k/kernel/signal.c b/arch/m68k/kernel/signal.c
index 0d2a372f9..c60e82b0b 100644
--- a/arch/m68k/kernel/signal.c
+++ b/arch/m68k/kernel/signal.c
@@ -127,26 +127,26 @@ asmlinkage int do_sigreturn(unsigned long __unused)
/* Verify the frame format. */
if (!CPU_IS_060 && (context.sc_fpstate[0] != fpu_version))
goto badframe;
- if (boot_info.cputype & FPU_68881)
+ if (m68k_fputype & FPU_68881)
{
if (context.sc_fpstate[1] != 0x18
&& context.sc_fpstate[1] != 0xb4)
goto badframe;
}
- else if (boot_info.cputype & FPU_68882)
+ else if (m68k_fputype & FPU_68882)
{
if (context.sc_fpstate[1] != 0x38
&& context.sc_fpstate[1] != 0xd4)
goto badframe;
}
- else if (boot_info.cputype & FPU_68040)
+ else if (m68k_fputype & FPU_68040)
{
if (!(context.sc_fpstate[1] == 0x00 ||
context.sc_fpstate[1] == 0x28 ||
context.sc_fpstate[1] == 0x60))
goto badframe;
}
- else if (boot_info.cputype & FPU_68060)
+ else if (m68k_fputype & FPU_68060)
{
if (!(context.sc_fpstate[3] == 0x00 ||
context.sc_fpstate[3] == 0x60 ||
@@ -174,7 +174,7 @@ asmlinkage int do_sigreturn(unsigned long __unused)
if (context.sc_usp != fp+fsize)
current->flags &= ~PF_ONSIGSTK;
-
+
/* OK. Make room on the supervisor stack for the extra junk,
* if necessary.
*/
@@ -200,7 +200,7 @@ asmlinkage int do_sigreturn(unsigned long __unused)
" .align 4\n"
" .long 2b,4b\n"
" .long 3b,4b\n"
- ".text"
+ ".previous"
: /* no outputs, it doesn't ever return */
: "a" (sw), "d" (fsize), "d" (frame_offset/4-1),
"n" (frame_offset), "a" (fp)
@@ -261,8 +261,8 @@ badframe:
#define UFRAME_SIZE(fs) (sizeof(struct sigcontext)/4 + 6 + fs/4)
-static void setup_frame (struct sigaction * sa, struct pt_regs *regs,
- int signr, unsigned long oldmask)
+static inline void setup_frame (struct sigaction * sa, struct pt_regs *regs,
+ int signr, unsigned long oldmask)
{
struct sigcontext context;
unsigned long *frame, *tframe;
@@ -291,20 +291,23 @@ static void setup_frame (struct sigaction * sa, struct pt_regs *regs,
tframe = frame;
/* return address points to code on stack */
- put_user((ulong)(frame+4), tframe); tframe++;
+
+ if(put_user((ulong)(frame+4), tframe))
+ do_exit(SIGSEGV);
+ tframe++;
if (current->exec_domain && current->exec_domain->signal_invmap)
- put_user(current->exec_domain->signal_invmap[signr], tframe);
+ __put_user(current->exec_domain->signal_invmap[signr], tframe);
else
- put_user(signr, tframe);
+ __put_user(signr, tframe);
tframe++;
- put_user(regs->vector, tframe); tframe++;
+ __put_user(regs->vector, tframe); tframe++;
/* "scp" parameter. points to sigcontext */
- put_user((ulong)(frame+6), tframe); tframe++;
+ __put_user((ulong)(frame+6), tframe); tframe++;
/* set up the return code... */
- put_user(0xdefc0014,tframe); tframe++; /* addaw #20,sp */
- put_user(0x70774e40,tframe); tframe++; /* moveq #119,d0; trap #0 */
+ __put_user(0xdefc0014,tframe); tframe++; /* addaw #20,sp */
+ __put_user(0x70774e40,tframe); tframe++; /* moveq #119,d0; trap #0 */
/* Flush caches so the instructions will be correctly executed. (MA) */
cache_push_v ((unsigned long)frame, (int)tframe - (int)frame);
@@ -360,9 +363,9 @@ static void setup_frame (struct sigaction * sa, struct pt_regs *regs,
/*
* OK, we're invoking a handler
- */
-static void handle_signal(unsigned long signr, struct sigaction *sa,
- unsigned long oldmask, struct pt_regs *regs)
+ */
+static inline void handle_signal(unsigned long signr, struct sigaction *sa,
+ unsigned long oldmask, struct pt_regs *regs)
{
/* are we from a system call? */
if (regs->orig_d0 >= 0) {
@@ -482,7 +485,7 @@ asmlinkage int do_signal(unsigned long oldmask, struct pt_regs *regs)
continue;
current->state = TASK_STOPPED;
current->exit_code = signr;
- if (!(current->p_pptr->sig->action[SIGCHLD-1].sa_flags &
+ if (!(current->p_pptr->sig->action[SIGCHLD-1].sa_flags &
SA_NOCLDSTOP))
notify_parent(current);
schedule();
diff --git a/arch/m68k/kernel/sys_m68k.c b/arch/m68k/kernel/sys_m68k.c
index d187e3d57..5acfd1cbd 100644
--- a/arch/m68k/kernel/sys_m68k.c
+++ b/arch/m68k/kernel/sys_m68k.c
@@ -9,6 +9,8 @@
#include <linux/errno.h>
#include <linux/sched.h>
#include <linux/mm.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
#include <linux/sem.h>
#include <linux/msg.h>
#include <linux/shm.h>
@@ -31,15 +33,14 @@ asmlinkage int sys_pipe(unsigned long * fildes)
int fd[2];
int error;
- error = verify_area(VERIFY_WRITE,fildes,8);
- if (error)
- return error;
+ lock_kernel();
error = do_pipe(fd);
- if (error)
- return error;
- put_user(fd[0],0+fildes);
- put_user(fd[1],1+fildes);
- return 0;
+ if (!error) {
+ if (copy_to_user(fildes, fd, 2*sizeof(int)))
+ error = -EFAULT;
+ }
+ unlock_kernel();
+ return error;
}
/*
@@ -64,16 +65,20 @@ asmlinkage int old_mmap(struct mmap_arg_struct *arg)
struct file * file = NULL;
struct mmap_arg_struct a;
- error = verify_area(VERIFY_READ, arg, sizeof(*arg));
- if (error)
- return error;
- copy_from_user(&a, arg, sizeof(a));
+ lock_kernel();
+ error = -EFAULT;
+ if (copy_from_user(&a, arg, sizeof(a)))
+ goto out;
+
if (!(a.flags & MAP_ANONYMOUS)) {
+ error = -EBADF;
if (a.fd >= NR_OPEN || !(file = current->files->fd[a.fd]))
- return -EBADF;
+ goto out;
}
a.flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
error = do_mmap(file, a.addr, a.len, a.prot, a.flags, a.offset);
+out:
+ unlock_kernel();
return error;
}
@@ -92,6 +97,7 @@ asmlinkage int old_select(struct sel_arg_struct *arg)
if (copy_from_user(&a, arg, sizeof(a)))
return -EFAULT;
+ /* sys_select() does the appropriate kernel locking */
return sys_select(a.n, a.inp, a.outp, a.exp, a.tvp);
}
@@ -102,7 +108,7 @@ asmlinkage int old_select(struct sel_arg_struct *arg)
*/
asmlinkage int sys_ipc (uint call, int first, int second, int third, void *ptr, long fifth)
{
- int version;
+ int version, ret;
version = call >> 16; /* hack for backward compatibility */
call &= 0xffff;
@@ -110,46 +116,57 @@ asmlinkage int sys_ipc (uint call, int first, int second, int third, void *ptr,
if (call <= SEMCTL)
switch (call) {
case SEMOP:
- return sys_semop (first, (struct sembuf *)ptr, second);
+ ret = sys_semop (first, (struct sembuf *)ptr, second);
+ goto out;
case SEMGET:
- return sys_semget (first, second, third);
+ ret = sys_semget (first, second, third);
+ goto out;
case SEMCTL: {
union semun fourth;
- int err;
+ ret = -EINVAL;
if (!ptr)
- return -EINVAL;
- if ((err = verify_area (VERIFY_READ, ptr, sizeof(long))))
- return err;
- get_user(fourth.__pad, (void **)ptr);
- return sys_semctl (first, second, third, fourth);
+ goto out;
+ if ((ret = get_user(fourth.__pad, (void **) ptr)))
+ goto out;
+ ret = sys_semctl (first, second, third, fourth);
+ goto out;
}
default:
- return -EINVAL;
+ ret = -EINVAL;
+ goto out;
}
if (call <= MSGCTL)
switch (call) {
case MSGSND:
- return sys_msgsnd (first, (struct msgbuf *) ptr,
- second, third);
+ ret = sys_msgsnd (first, (struct msgbuf *) ptr,
+ second, third);
+ goto out;
case MSGRCV:
switch (version) {
case 0: {
struct ipc_kludge tmp;
+ ret = -EINVAL;
if (!ptr)
- return -EINVAL;
+ goto out;
+ ret = -EFAULT;
if (copy_from_user (&tmp, ptr, sizeof (tmp)))
- return -EFAULT;
- return sys_msgrcv (first, tmp.msgp, second, tmp.msgtyp, third);
+ goto out;
+ ret = sys_msgrcv (first, tmp.msgp, second, tmp.msgtyp, third);
+ goto out;
}
case 1: default:
- return sys_msgrcv (first, (struct msgbuf *) ptr, second, fifth, third);
+ ret = sys_msgrcv (first, (struct msgbuf *) ptr, second, fifth, third);
+ goto out;
}
case MSGGET:
- return sys_msgget ((key_t) first, second);
+ ret = sys_msgget ((key_t) first, second);
+ goto out;
case MSGCTL:
- return sys_msgctl (first, second, (struct msqid_ds *) ptr);
+ ret = sys_msgctl (first, second, (struct msqid_ds *) ptr);
+ goto out;
default:
- return -EINVAL;
+ ret = -EINVAL;
+ goto out;
}
if (call <= SHMCTL)
switch (call) {
@@ -157,30 +174,30 @@ asmlinkage int sys_ipc (uint call, int first, int second, int third, void *ptr,
switch (version) {
case 0: default: {
ulong raddr;
- int err;
- if ((err = verify_area(VERIFY_WRITE, (ulong*) third, sizeof(ulong))))
- return err;
- err = sys_shmat (first, (char *) ptr, second, &raddr);
- if (err)
- return err;
- put_user (raddr, (ulong *) third);
- return 0;
- }
- case 1: /* iBCS2 emulator entry point */
- if (get_fs() != get_ds())
- return -EINVAL;
- return sys_shmat (first, (char *) ptr, second, (ulong *) third);
+ ret = sys_shmat (first, (char *) ptr, second, &raddr);
+ if (ret)
+ goto out;
+ ret = put_user (raddr, (ulong *) third);
+ goto out;
+ }
}
case SHMDT:
- return sys_shmdt ((char *)ptr);
+ ret = sys_shmdt ((char *)ptr);
+ goto out;
case SHMGET:
- return sys_shmget (first, second, third);
+ ret = sys_shmget (first, second, third);
+ goto out;
case SHMCTL:
- return sys_shmctl (first, second, (struct shmid_ds *) ptr);
+ ret = sys_shmctl (first, second, (struct shmid_ds *) ptr);
+ goto out;
default:
- return -EINVAL;
+ ret = -EINVAL;
+ goto out;
}
- return -EINVAL;
+ ret = -EINVAL;
+out:
+ unlock_kernel();
+ return ret;
}
asmlinkage int sys_ioperm(unsigned long from, unsigned long num, int on)
@@ -192,15 +209,14 @@ asmlinkage int sys_ioperm(unsigned long from, unsigned long num, int on)
in VALID whether the virtual address is actually mapped. */
#define virt_to_phys_040(vaddr, paddr, valid) \
{ \
- register unsigned long _tmp1 __asm__ ("a0") = (vaddr); \
- register unsigned long _tmp2 __asm__ ("d0"); \
unsigned long _mmusr; \
\
- __asm__ __volatile__ (".word 0xf568 /* ptestr (%1) */\n\t" \
- ".long 0x4e7a0805 /* movec %%mmusr,%0 */" \
- : "=d" (_tmp2) \
- : "a" (_tmp1)); \
- _mmusr = _tmp2; \
+ __asm__ __volatile__ (".chip 68040\n\t" \
+ "ptestr (%1)\n\t" \
+ "movec %%mmusr,%0\n\t" \
+ ".chip 68k" \
+ : "=r" (_mmusr) \
+ : "a" (vaddr)); \
if (!(_mmusr & MMU_R_040)) \
(valid) = 0; \
else \
@@ -224,16 +240,22 @@ cache_flush_040 (unsigned long addr, int scope, int cache, unsigned long len)
case FLUSH_CACHE_DATA:
/* This nop is needed for some broken versions of the 68040. */
__asm__ __volatile__ ("nop\n\t"
- ".word 0xf478 /* cpusha %%dc */");
+ ".chip 68040\n\t"
+ "cpusha %dc\n\t"
+ ".chip 68k");
break;
case FLUSH_CACHE_INSN:
__asm__ __volatile__ ("nop\n\t"
- ".word 0xf4b8 /* cpusha %%ic */");
+ ".chip 68040\n\t"
+ "cpusha %ic\n\t"
+ ".chip 68k");
break;
default:
case FLUSH_CACHE_BOTH:
__asm__ __volatile__ ("nop\n\t"
- ".word 0xf4f8 /* cpusha %%bc */");
+ ".chip 68040\n\t"
+ "cpusha %bc\n\t"
+ ".chip 68k");
break;
}
break;
@@ -254,23 +276,28 @@ cache_flush_040 (unsigned long addr, int scope, int cache, unsigned long len)
}
while (len--)
{
- register unsigned long tmp __asm__ ("a0") = paddr;
switch (cache)
{
case FLUSH_CACHE_DATA:
__asm__ __volatile__ ("nop\n\t"
- ".word 0xf468 /* cpushl %%dc,(%0) */"
- : : "a" (tmp));
+ ".chip 68040\n\t"
+ "cpushl %%dc,(%0)\n\t"
+ ".chip 68k"
+ : : "a" (paddr));
break;
case FLUSH_CACHE_INSN:
__asm__ __volatile__ ("nop\n\t"
- ".word 0xf4a8 /* cpushl %%ic,(%0) */"
- : : "a" (tmp));
+ ".chip 68040\n\t"
+ "cpushl %%ic,(%0)\n\t"
+ ".chip 68k"
+ : : "a" (paddr));
break;
default:
case FLUSH_CACHE_BOTH:
__asm__ __volatile__ ("nop\n\t"
- ".word 0xf4e8 /* cpushl %%bc,(%0) */"
+ ".chip 68040\n\t"
+ "cpushl %%bc,(%0)\n\t"
+ ".chip 68k"
: : "a" (paddr));
break;
}
@@ -302,28 +329,32 @@ cache_flush_040 (unsigned long addr, int scope, int cache, unsigned long len)
case FLUSH_SCOPE_PAGE:
for (len >>= PAGE_SHIFT; len--; addr += PAGE_SIZE)
{
- register unsigned long tmp __asm__ ("a0");
virt_to_phys_040 (addr, paddr, valid);
if (!valid)
continue;
- tmp = paddr;
switch (cache)
{
case FLUSH_CACHE_DATA:
__asm__ __volatile__ ("nop\n\t"
- ".word 0xf470 /* cpushp %%dc,(%0) */"
- : : "a" (tmp));
+ ".chip 68040\n\t"
+ "cpushp %%dc,(%0)\n\t"
+ ".chip 68k"
+ : : "a" (paddr));
break;
case FLUSH_CACHE_INSN:
__asm__ __volatile__ ("nop\n\t"
- ".word 0xf4b0 /* cpushp %%ic,(%0) */"
- : : "a" (tmp));
+ ".chip 68040\n\t"
+ "cpushp %%ic,(%0)\n\t"
+ ".chip 68k"
+ : : "a" (paddr));
break;
default:
case FLUSH_CACHE_BOTH:
__asm__ __volatile__ ("nop\n\t"
- ".word 0xf4f0 /* cpushp %%bc,(%0) */"
- : : "a" (tmp));
+ ".chip 68040\n\t"
+ "cpushp %%bc,(%0)\n\t"
+ ".chip 68k"
+ : : "a" (paddr));
break;
}
}
@@ -334,13 +365,12 @@ cache_flush_040 (unsigned long addr, int scope, int cache, unsigned long len)
#define virt_to_phys_060(vaddr, paddr, valid) \
{ \
- register unsigned long _tmp __asm__ ("a0") = (vaddr); \
- \
- __asm__ __volatile__ (".word 0xf5c8 /* plpar (%1) */" \
- : "=a" (_tmp) \
- : "0" (_tmp)); \
+ __asm__ __volatile__ (".chip 68060\n\t" \
+ "plpar (%0)\n\t" \
+ ".chip 68k" \
+ : "=a" (paddr) \
+ : "0" (vaddr)); \
(valid) = 1; /* XXX */ \
- (paddr) = _tmp; \
}
static inline int
@@ -355,17 +385,23 @@ cache_flush_060 (unsigned long addr, int scope, int cache, unsigned long len)
switch (cache)
{
case FLUSH_CACHE_DATA:
- __asm__ __volatile__ (".word 0xf478 /* cpusha %%dc */\n\t"
- ".word 0xf458 /* cinva %%dc */");
+ __asm__ __volatile__ (".chip 68060\n\t"
+ "cpusha %dc\n\t"
+ "cinva %dc\n\t"
+ ".chip 68k");
break;
case FLUSH_CACHE_INSN:
- __asm__ __volatile__ (".word 0xf4b8 /* cpusha %%ic */\n\t"
- ".word 0xf498 /* cinva %%ic */");
+ __asm__ __volatile__ (".chip 68060\n\t"
+ "cpusha %ic\n\t"
+ "cinva %ic\n\t"
+ ".chip 68k");
break;
default:
case FLUSH_CACHE_BOTH:
- __asm__ __volatile__ (".word 0xf4f8 /* cpusha %%bc */\n\t"
- ".word 0xf4d8 /* cinva %%bc */");
+ __asm__ __volatile__ (".chip 68060\n\t"
+ "cpusha %bc\n\t"
+ "cinva %bc\n\t"
+ ".chip 68k");
break;
}
break;
@@ -386,23 +422,28 @@ cache_flush_060 (unsigned long addr, int scope, int cache, unsigned long len)
}
while (len--)
{
- register unsigned long tmp __asm__ ("a0") = paddr;
switch (cache)
{
case FLUSH_CACHE_DATA:
- __asm__ __volatile__ (".word 0xf468 /* cpushl %%dc,(%0) */\n\t"
- ".word 0xf448 /* cinv %%dc,(%0) */"
- : : "a" (tmp));
+ __asm__ __volatile__ (".chip 68060\n\t"
+ "cpushl %%dc,(%0)\n\t"
+ "cinvl %%dc,(%0)\n\t"
+ ".chip 68k"
+ : : "a" (paddr));
break;
case FLUSH_CACHE_INSN:
- __asm__ __volatile__ (".word 0xf4a8 /* cpushl %%ic,(%0) */\n\t"
- ".word 0xf488 /* cinv %%ic,(%0) */"
- : : "a" (tmp));
+ __asm__ __volatile__ (".chip 68060\n\t"
+ "cpushl %%ic,(%0)\n\t"
+ "cinvl %%ic,(%0)\n\t"
+ ".chip 68k"
+ : : "a" (paddr));
break;
default:
case FLUSH_CACHE_BOTH:
- __asm__ __volatile__ (".word 0xf4e8 /* cpushl %%bc,(%0) */\n\t"
- ".word 0xf4c8 /* cinv %%bc,(%0) */"
+ __asm__ __volatile__ (".chip 68060\n\t"
+ "cpushl %%bc,(%0)\n\t"
+ "cinvl %%bc,(%0)\n\t"
+ ".chip 68k"
: : "a" (paddr));
break;
}
@@ -434,28 +475,32 @@ cache_flush_060 (unsigned long addr, int scope, int cache, unsigned long len)
case FLUSH_SCOPE_PAGE:
for (len >>= PAGE_SHIFT; len--; addr += PAGE_SIZE)
{
- register unsigned long tmp __asm__ ("a0");
virt_to_phys_060 (addr, paddr, valid);
if (!valid)
continue;
- tmp = paddr;
switch (cache)
{
case FLUSH_CACHE_DATA:
- __asm__ __volatile__ (".word 0xf470 /* cpushp %%dc,(%0) */\n\t"
- ".word 0xf450 /* cinv %%dc,(%0) */"
- : : "a" (tmp));
+ __asm__ __volatile__ (".chip 68060\n\t"
+ "cpushp %%dc,(%0)\n\t"
+ "cinvp %%dc,(%0)\n\t"
+ ".chip 68k"
+ : : "a" (paddr));
break;
case FLUSH_CACHE_INSN:
- __asm__ __volatile__ (".word 0xf4b0 /* cpushp %%ic,(%0) */\n\t"
- ".word 0xf490 /* cinv %%ic,(%0) */"
- : : "a" (tmp));
+ __asm__ __volatile__ (".chip 68060\n\t"
+ "cpushp %%ic,(%0)\n\t"
+ "cinvp %%ic,(%0)\n\t"
+ ".chip 68k"
+ : : "a" (paddr));
break;
default:
case FLUSH_CACHE_BOTH:
- __asm__ __volatile__ (".word 0xf4f0 /* cpushp %%bc,(%0) */\n\t"
- ".word 0xf4d0 /* cinv %%bc,(%0) */"
- : : "a" (tmp));
+ __asm__ __volatile__ (".chip 68060\n\t"
+ "cpushp %%bc,(%0)\n\t"
+ "cinvp %%bc,(%0)\n\t"
+ ".chip 68k"
+ : : "a" (paddr));
break;
}
}
@@ -468,41 +513,63 @@ cache_flush_060 (unsigned long addr, int scope, int cache, unsigned long len)
asmlinkage int
sys_cacheflush (unsigned long addr, int scope, int cache, unsigned long len)
{
- struct vm_area_struct *vma;
+ struct vm_area_struct *vma;
+ int ret = -EINVAL;
- if (scope < FLUSH_SCOPE_LINE || scope > FLUSH_SCOPE_ALL
- || cache & ~FLUSH_CACHE_BOTH)
- return -EINVAL;
+ lock_kernel();
+ if (scope < FLUSH_SCOPE_LINE || scope > FLUSH_SCOPE_ALL ||
+ cache & ~FLUSH_CACHE_BOTH)
+ goto out;
- if (scope == FLUSH_SCOPE_ALL)
- {
- /* Only the superuser may flush the whole cache. */
- if (!suser ())
- return -EPERM;
- }
- else
- {
- /* Verify that the specified address region actually belongs to
- this process. */
- vma = find_vma (current->mm, addr);
- if (vma == NULL || addr < vma->vm_start || addr + len > vma->vm_end)
- return -EINVAL;
- }
+ if (scope == FLUSH_SCOPE_ALL) {
+ /* Only the superuser may flush the whole cache. */
+ ret = -EPERM;
+ if (!suser ())
+ goto out;
+ } else {
+ /* Verify that the specified address region actually belongs to
+ * this process.
+ */
+ vma = find_vma (current->mm, addr);
+ ret = -EINVAL;
+ if (vma == NULL || addr < vma->vm_start || addr + len > vma->vm_end)
+ goto out;
+ }
- if (CPU_IS_020_OR_030) {
- /* Always flush the whole cache, everything else would not be
- worth the hassle. */
- __asm__ __volatile__
- ("movec %%cacr, %%d0\n\t"
- "or %0, %%d0\n\t"
- "movec %%d0, %%cacr"
- : /* no outputs */
- : "di" ((cache & FLUSH_CACHE_INSN ? 8 : 0)
- | (cache & FLUSH_CACHE_DATA ? 0x800 : 0))
- : "d0");
- return 0;
- } else if (CPU_IS_040)
- return cache_flush_040 (addr, scope, cache, len);
- else if (CPU_IS_060)
- return cache_flush_060 (addr, scope, cache, len);
+ if (CPU_IS_020_OR_030) {
+ if (scope == FLUSH_SCOPE_LINE) {
+ unsigned long cacr;
+ __asm__ ("movec %%cacr, %0" : "=r" (cacr));
+ if (cache & FLUSH_CACHE_INSN)
+ cacr |= 4;
+ if (cache & FLUSH_CACHE_DATA)
+ cacr |= 0x400;
+ len >>= 4;
+ while (len--) {
+ __asm__ __volatile__ ("movec %1, %%caar\n\t"
+ "movec %0, %%cacr"
+ : /* no outputs */
+ : "r" (cacr), "r" (addr));
+ addr += 16;
+ }
+ } else {
+ /* Flush the whole cache, even if page granularity requested. */
+ unsigned long cacr;
+ __asm__ ("movec %%cacr, %0" : "=r" (cacr));
+ if (cache & FLUSH_CACHE_INSN)
+ cacr |= 8;
+ if (cache & FLUSH_CACHE_DATA)
+ cacr |= 0x800;
+ __asm__ __volatile__ ("movec %0, %%cacr" : : "r" (cacr));
+ }
+ ret = 0;
+ goto out;
+ } else if (CPU_IS_040) {
+ ret = cache_flush_040 (addr, scope, cache, len);
+ } else if (CPU_IS_060) {
+ ret = cache_flush_060 (addr, scope, cache, len);
+ }
+out:
+ unlock_kernel();
+ return ret;
}
diff --git a/arch/m68k/kernel/traps.c b/arch/m68k/kernel/traps.c
index 39625f3b6..1cc547907 100644
--- a/arch/m68k/kernel/traps.c
+++ b/arch/m68k/kernel/traps.c
@@ -29,11 +29,15 @@
#include <linux/linkage.h>
#include <asm/setup.h>
+#include <asm/fpu.h>
#include <asm/system.h>
#include <asm/uaccess.h>
#include <asm/traps.h>
#include <asm/pgtable.h>
#include <asm/machdep.h>
+#ifdef CONFIG_KGDB
+#include <asm/kgdb.h>
+#endif
/* assembler routines */
asmlinkage void system_call(void);
@@ -140,10 +144,9 @@ static inline void console_verbose(void)
{
extern int console_loglevel;
console_loglevel = 15;
- mach_debug_init();
}
-char *vec_names[] = {
+static char *vec_names[] = {
"RESET SP", "RESET PC", "BUS ERROR", "ADDRESS ERROR",
"ILLEGAL INSTRUCTION", "ZERO DIVIDE", "CHK", "TRAPcc",
"PRIVILEGE VIOLATION", "TRACE", "LINE 1010", "LINE 1111",
@@ -162,17 +165,17 @@ char *vec_names[] = {
"FPCP BSUN", "FPCP INEXACT", "FPCP DIV BY 0", "FPCP UNDERFLOW",
"FPCP OPERAND ERROR", "FPCP OVERFLOW", "FPCP SNAN",
"FPCP UNSUPPORTED OPERATION",
- "MMU CONFIGUATION ERROR"
+ "MMU CONFIGURATION ERROR"
};
-char *space_names[] = {
+static char *space_names[] = {
"Space 0", "User Data", "User Program", "Space 3",
"Space 4", "Super Data", "Super Program", "CPU"
};
-extern void die_if_kernel(char *,struct pt_regs *,int);
+void die_if_kernel(char *,struct pt_regs *,int);
asmlinkage int do_page_fault(struct pt_regs *regs, unsigned long address,
unsigned long error_code);
@@ -184,7 +187,7 @@ static inline void access_error060 (struct frame *fp)
unsigned long fslw = fp->un.fmt4.pc; /* is really FSLW for access error */
#ifdef DEBUG
- printk("fslw=%#lx, fa=%#lx\n", ssw, fp->un.fmt4.effaddr);
+ printk("fslw=%#lx, fa=%#lx\n", fslw, fp->un.fmt4.effaddr);
#endif
if (fslw & MMU060_BPE) {
@@ -194,7 +197,7 @@ static inline void access_error060 (struct frame *fp)
"movec %/d0,%/cacr"
: : : "d0" );
/* return if there's no other error */
- if (!(fslw & MMU060_ERR_BITS))
+ if ((!(fslw & MMU060_ERR_BITS)) && !(fslw & MMU060_SEE))
return;
}
@@ -209,8 +212,13 @@ static inline void access_error060 (struct frame *fp)
if (fslw & MMU060_MA)
addr = PAGE_ALIGN(addr);
do_page_fault(&fp->ptregs, addr, errorcode);
- }
- else {
+ } else if (fslw & (MMU060_SEE)){
+ /* Software Emulation Error. Probably an instruction
+ * using an unsupported addressing mode
+ */
+ send_sig (SIGSEGV, current, 1);
+ } else {
+ printk("pc=%#lx, fa=%#lx\n", fp->ptregs.pc, fp->un.fmt4.effaddr);
printk( "68060 access error, fslw=%lx\n", fslw );
trap_c( fp );
}
@@ -218,7 +226,7 @@ static inline void access_error060 (struct frame *fp)
#endif /* CONFIG_M68060 */
#if defined (CONFIG_M68040)
-static unsigned long probe040 (int iswrite, int fc, unsigned long addr)
+static inline unsigned long probe040 (int iswrite, int fc, unsigned long addr)
{
unsigned long mmusr;
unsigned long fs = get_fs();
@@ -227,28 +235,26 @@ static unsigned long probe040 (int iswrite, int fc, unsigned long addr)
if (iswrite)
/* write */
- asm volatile ("movel %1,%/a0\n\t"
- ".word 0xf548\n\t" /* ptestw (a0) */
- ".long 0x4e7a8805\n\t" /* movec mmusr,a0 */
- "movel %/a0,%0"
- : "=g" (mmusr)
- : "g" (addr)
- : "a0");
+ asm volatile (".chip 68040\n\t"
+ "ptestw (%1)\n\t"
+ "movec %%mmusr,%0\n\t"
+ ".chip 68k"
+ : "=r" (mmusr)
+ : "a" (addr));
else
- asm volatile ("movel %1,%/a0\n\t"
- ".word 0xf568\n\t" /* ptestr (a0) */
- ".long 0x4e7a8805\n\t" /* movec mmusr,a0 */
- "movel %/a0,%0"
- : "=g" (mmusr)
- : "g" (addr)
- : "a0");
+ asm volatile (".chip 68040\n\t"
+ "ptestr (%1)\n\t"
+ "movec %%mmusr,%0\n\t"
+ ".chip 68k"
+ : "=r" (mmusr)
+ : "a" (addr));
set_fs (fs);
return mmusr;
}
-static void do_040writeback (unsigned short ssw,
+static inline void do_040writeback (unsigned short ssw,
unsigned short wbs,
unsigned long wba,
unsigned long wbd,
@@ -313,11 +319,9 @@ static inline void access_error040 (struct frame *fp)
/* MMU error, get the MMUSR info for this access */
mmusr = probe040 (!(ssw & RW_040), ssw & TM_040, addr);
- /*
#ifdef DEBUG
printk("mmusr = %lx\n", mmusr);
#endif
-*/
errorcode = ((mmusr & MMU_R_040) ? 1 : 0) |
((ssw & RW_040) ? 0 : 2);
do_page_fault (&fp->ptregs, addr, errorcode);
@@ -353,7 +357,7 @@ static inline void access_error040 (struct frame *fp)
}
#endif /* CONFIG_M68040 */
-#if defined(CONFIG_M68020_OR_M68030)
+#if defined(CPU_M68020_OR_M68030)
static inline void bus_error030 (struct frame *fp)
{
volatile unsigned short temp;
@@ -605,7 +609,7 @@ static inline void bus_error030 (struct frame *fp)
printk ("level 0 mmusr is %#x\n", mmusr);
#ifdef DEBUG
- if (boot_info.cputype & CPU_68030) {
+ if (m68k_cputype & CPU_68030) {
asm volatile ("pmove %/tt0,%0@"
: /* no outputs */
: "a" (&tlong));
@@ -632,7 +636,7 @@ create_atc_entry:
asm volatile ("ploadr #2,%0@" : /* no outputs */
: "a" (addr));
}
-#endif /* CONFIG_M68020_OR_M68030 */
+#endif /* CPU_M68020_OR_M68030 */
asmlinkage void buserr_c(struct frame *fp)
{
@@ -655,7 +659,7 @@ asmlinkage void buserr_c(struct frame *fp)
access_error040 (fp);
break;
#endif
-#if defined (CONFIG_M68020_OR_M68030)
+#if defined (CPU_M68020_OR_M68030)
case 0xa:
case 0xb:
bus_error030 (fp);
@@ -679,6 +683,11 @@ int kstack_depth_to_print = 48;
static void dump_stack(struct frame *fp)
{
+#ifdef CONFIG_KGDB
+ /* This will never return to here, if kgdb has been initialized. And if
+ * it returns from there, then to where the error happened... */
+ enter_kgdb( &fp->ptregs );
+#else
unsigned long *stack, *endstack, addr, module_start, module_end;
extern char _start, _etext;
int i;
@@ -776,10 +785,15 @@ static void dump_stack(struct frame *fp)
for (i = 0; i < 10; i++)
printk("%04x ", 0xffff & ((short *) fp->ptregs.pc)[i]);
printk ("\n");
+#endif
}
void bad_super_trap (struct frame *fp)
{
+#ifdef CONFIG_KGDB
+ /* Save the register dump if we'll enter kgdb anyways */
+ if (!kgdb_initialized) {
+#endif
console_verbose();
if (fp->ptregs.vector < 4*sizeof(vec_names)/sizeof(vec_names[0]))
printk ("*** %s *** FORMAT=%X\n",
@@ -809,6 +823,9 @@ void bad_super_trap (struct frame *fp)
fp->ptregs.pc);
}
printk ("Current process id is %d\n", current->pid);
+#ifdef CONFIG_KGDB
+ }
+#endif
die_if_kernel("BAD KERNEL TRAP", &fp->ptregs, 0);
}
@@ -867,14 +884,18 @@ asmlinkage void trap_c(struct frame *fp)
case VEC_FPOVER:
case VEC_FPNAN:
{
- unsigned char fstate[216];
+ unsigned char fstate[FPSTATESIZE];
- __asm__ __volatile__ ("fsave %0@" : : "a" (fstate) : "memory");
+ __asm__ __volatile__ (".chip 68k/68881\n\t"
+ "fsave %0@\n\t"
+ ".chip 68k" : : "a" (fstate) : "memory");
/* Set the exception pending bit in the 68882 idle frame */
if (*(unsigned short *) fstate == 0x1f38)
{
fstate[fstate[1]] |= 1 << 3;
- __asm__ __volatile__ ("frestore %0@" : : "a" (fstate));
+ __asm__ __volatile__ (".chip 68k/68881\n\t"
+ "frestore %0@\n\t"
+ ".chip 68k" : : "a" (fstate));
}
}
/* fall through */
@@ -905,9 +926,13 @@ void die_if_kernel (char *str, struct pt_regs *fp, int nr)
if (!(fp->sr & PS_S))
return;
+#ifdef CONFIG_KGDB
+ /* Save the register dump if we'll enter kgdb anyways */
+ if (!kgdb_initialized) {
+#endif
console_verbose();
printk("%s: %08x\n",str,nr);
- printk("PC: %08lx\nSR: %04x SP: %p\n", fp->pc, fp->sr, fp);
+ printk("PC: [<%08lx>]\nSR: %04x SP: %p\n", fp->pc, fp->sr, fp);
printk("d0: %08lx d1: %08lx d2: %08lx d3: %08lx\n",
fp->d0, fp->d1, fp->d2, fp->d3);
printk("d4: %08lx d5: %08lx a0: %08lx a1: %08lx\n",
@@ -917,6 +942,18 @@ void die_if_kernel (char *str, struct pt_regs *fp, int nr)
printk("Corrupted stack page\n");
printk("Process %s (pid: %d, stackpage=%08lx)\n",
current->comm, current->pid, current->kernel_stack_page);
+#ifdef CONFIG_KGDB
+ }
+#endif
dump_stack((struct frame *)fp);
do_exit(SIGSEGV);
}
+
+/*
+ * This function is called if an error occur while accessing
+ * user-space from the fpsp040 code.
+ */
+asmlinkage void fpsp040_die(void)
+{
+ do_exit(SIGSEGV);
+}