diff options
author | Ralf Baechle <ralf@linux-mips.org> | 1997-04-29 21:13:14 +0000 |
---|---|---|
committer | <ralf@linux-mips.org> | 1997-04-29 21:13:14 +0000 |
commit | 19c9bba94152148523ba0f7ef7cffe3d45656b11 (patch) | |
tree | 40b1cb534496a7f1ca0f5c314a523c69f1fee464 /arch/m68k/kernel | |
parent | 7206675c40394c78a90e74812bbdbf8cf3cca1be (diff) |
Import of Linux/MIPS 2.1.36
Diffstat (limited to 'arch/m68k/kernel')
-rw-r--r-- | arch/m68k/kernel/Makefile | 10 | ||||
-rw-r--r-- | arch/m68k/kernel/console.c | 231 | ||||
-rw-r--r-- | arch/m68k/kernel/entry.S | 160 | ||||
-rw-r--r-- | arch/m68k/kernel/head.S | 306 | ||||
-rw-r--r-- | arch/m68k/kernel/ints.c | 86 | ||||
-rw-r--r-- | arch/m68k/kernel/ksyms.c | 89 | ||||
-rw-r--r-- | arch/m68k/kernel/m68k_ksyms.c | 57 | ||||
-rw-r--r-- | arch/m68k/kernel/process.c | 54 | ||||
-rw-r--r-- | arch/m68k/kernel/ptrace.c | 105 | ||||
-rw-r--r-- | arch/m68k/kernel/setup.c | 208 | ||||
-rw-r--r-- | arch/m68k/kernel/signal.c | 41 | ||||
-rw-r--r-- | arch/m68k/kernel/sys_m68k.c | 347 | ||||
-rw-r--r-- | arch/m68k/kernel/traps.c | 107 |
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); +} |