summaryrefslogtreecommitdiffstats
path: root/arch/m68k/kernel
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>1999-10-09 00:00:47 +0000
committerRalf Baechle <ralf@linux-mips.org>1999-10-09 00:00:47 +0000
commitd6434e1042f3b0a6dfe1b1f615af369486f9b1fa (patch)
treee2be02f33984c48ec019c654051d27964e42c441 /arch/m68k/kernel
parent609d1e803baf519487233b765eb487f9ec227a18 (diff)
Merge with 2.3.19.
Diffstat (limited to 'arch/m68k/kernel')
-rw-r--r--arch/m68k/kernel/Makefile11
-rw-r--r--arch/m68k/kernel/bios32.c20
-rw-r--r--arch/m68k/kernel/entry.S163
-rw-r--r--arch/m68k/kernel/head.S8
-rw-r--r--arch/m68k/kernel/ints.c12
-rw-r--r--arch/m68k/kernel/kgdb.c168
-rw-r--r--arch/m68k/kernel/m68k_defs.c37
-rw-r--r--arch/m68k/kernel/m68k_defs.h36
-rw-r--r--arch/m68k/kernel/m68k_ksyms.c9
-rw-r--r--arch/m68k/kernel/process.c129
-rw-r--r--arch/m68k/kernel/ptrace.c42
-rw-r--r--arch/m68k/kernel/semaphore.c129
-rw-r--r--arch/m68k/kernel/setup.c54
-rw-r--r--arch/m68k/kernel/signal.c104
-rw-r--r--arch/m68k/kernel/sun3-head.S102
-rw-r--r--arch/m68k/kernel/traps.c283
16 files changed, 965 insertions, 342 deletions
diff --git a/arch/m68k/kernel/Makefile b/arch/m68k/kernel/Makefile
index 280a5b450..146fcb69b 100644
--- a/arch/m68k/kernel/Makefile
+++ b/arch/m68k/kernel/Makefile
@@ -10,11 +10,16 @@
.S.o:
$(CC) -D__ASSEMBLY__ -traditional -c $< -o $*.o
+ifndef CONFIG_SUN3
all: head.o kernel.o
+else
+all: sun3-head.o kernel.o
+endif
+
O_TARGET := kernel.o
O_OBJS := entry.o process.o traps.o ints.o signal.o ptrace.o \
- setup.o sys_m68k.o time.o
-OX_OBJS := m68k_ksyms.o
+ sys_m68k.o time.o semaphore.o
+OX_OBJS := setup.o m68k_ksyms.o
ifdef CONFIG_KGDB
O_OBJS += kgdb.o
@@ -26,6 +31,8 @@ endif
head.o: head.S m68k_defs.h
+sun3-head.o: sun3-head.S m68k_defs.h
+
m68k_defs.h: m68k_defs.c m68k_defs.head
rm -f m68k_defs.d
SUNPRO_DEPENDENCIES="m68k_defs.d m68k_defs.h" \
diff --git a/arch/m68k/kernel/bios32.c b/arch/m68k/kernel/bios32.c
index b1322261a..55b762bbd 100644
--- a/arch/m68k/kernel/bios32.c
+++ b/arch/m68k/kernel/bios32.c
@@ -240,7 +240,7 @@ static unsigned int mem_base = FIRST_MEM_ADDR; /* Skip first 32M. */
* accesses.
*/
-__initfunc(static void disable_dev(struct pci_dev *dev))
+static void __init disable_dev(struct pci_dev *dev)
{
struct pci_bus *bus;
unsigned short cmd;
@@ -263,8 +263,8 @@ __initfunc(static void disable_dev(struct pci_dev *dev))
#define MAX(val1, val2) ( ((val1) > (val2)) ? val1 : val2)
-__initfunc(static void layout_dev(struct pci_dev *dev, unsigned long pci_mem_base,
- unsigned long pci_io_base))
+static void __init layout_dev(struct pci_dev *dev, unsigned long pci_mem_base,
+ unsigned long pci_io_base)
{
struct pci_bus *bus;
unsigned short cmd;
@@ -400,8 +400,8 @@ __initfunc(static void layout_dev(struct pci_dev *dev, unsigned long pci_mem_bas
bus->number, PCI_SLOT(dev->devfn), dev->vendor, dev->device, dev->class));
}
-__initfunc(static void layout_bus(struct pci_bus *bus, unsigned long pci_mem_base,
- unsigned long pci_io_base))
+static void __init layout_bus(struct pci_bus *bus, unsigned long pci_mem_base,
+ unsigned long pci_io_base)
{
struct pci_dev *dev;
@@ -512,7 +512,7 @@ int pcibios_present(void)
return 0;
}
-__initfunc(void pcibios_init(void))
+void __init pcibios_init(void)
{
printk("Linux/m68k PCI BIOS32 revision %x.%02x\n", MAJOR_REV, MINOR_REV);
@@ -531,7 +531,7 @@ __initfunc(void pcibios_init(void))
* of the PCI cards.
*/
-__initfunc(static inline void hades_fixup(void))
+static inline void __init hades_fixup(void)
{
char irq_tab[4] = {
IRQ_TT_MFP_IO0, /* Slot 0. */
@@ -560,7 +560,7 @@ __initfunc(static inline void hades_fixup(void))
}
}
-__initfunc(void pcibios_fixup(void))
+void __init pcibios_fixup(void)
{
#if PCI_MODIFY
unsigned long orig_mem_base, orig_io_base;
@@ -587,11 +587,11 @@ __initfunc(void pcibios_fixup(void))
hades_fixup();
}
-__initfunc(void pcibios_fixup_bus(struct pci_bus *bus))
+void __init pcibios_fixup_bus(struct pci_bus *bus)
{
}
-__initfunc(char *pcibios_setup(char *str))
+char * __init pcibios_setup(char *str)
{
return str;
}
diff --git a/arch/m68k/kernel/entry.S b/arch/m68k/kernel/entry.S
index 61482c3a8..21acaa218 100644
--- a/arch/m68k/kernel/entry.S
+++ b/arch/m68k/kernel/entry.S
@@ -67,11 +67,21 @@ ENTRY(trap)
ENTRY(reschedule)
| save top of frame
- movel %sp,%curptr@(TASK_TSS+TSS_ESP0)
+ movel %sp,%curptr@(TASK_THREAD+THREAD_ESP0)
pea SYMBOL_NAME(ret_from_exception)
jmp SYMBOL_NAME(schedule)
+ | After a fork we jump here directly from resume,
+ | so that %d1 contains the previous task
+ | Theoretically only needed on SMP, but let's watch
+ | what happens in schedule_tail() in future...
+ENTRY(ret_from_fork)
+ movel %d1,%sp@-
+ jsr SYMBOL_NAME(schedule_tail)
+ addql #4,%sp
+ jra SYMBOL_NAME(ret_from_exception)
+
badsys:
movel #-ENOSYS,PT_D0(%sp)
jra SYMBOL_NAME(ret_from_exception)
@@ -100,7 +110,7 @@ ENTRY(system_call)
GET_CURRENT(%d0)
| save top of frame
- movel %sp,%curptr@(TASK_TSS+TSS_ESP0)
+ movel %sp,%curptr@(TASK_THREAD+THREAD_ESP0)
cmpl #NR_syscalls,%d2
jcc badsys
@@ -118,8 +128,10 @@ SYMBOL_NAME_LABEL(ret_from_exception)
andw #ALLOWINT,%sr
tstl %curptr@(TASK_NEEDRESCHED)
jne SYMBOL_NAME(reschedule)
+#if 0
cmpl #SYMBOL_NAME(task),%curptr | task[0] cannot have signals
jeq 2f
+#endif
| check for delayed trace
bclr #PF_DTRACE_BIT,%curptr@(TASK_FLAGS+PF_DTRACE_OFF)
jne do_delayed_trace
@@ -152,6 +164,36 @@ do_delayed_trace:
addql #4,%sp
jra 5b
+
+#if 0
+#if CONFIG_AMIGA
+SYMBOL_NAME_LABEL(ami_inthandler)
+ addql #1,SYMBOL_NAME(local_irq_count)
+ SAVE_ALL_INT
+ GET_CURRENT(%d0)
+
+ bfextu %sp@(PT_VECTOR){#4,#12},%d0
+ movel %d0,%a0
+ addql #1,%a0@(SYMBOL_NAME(kstat)+STAT_IRQ-VECOFF(VEC_SPUR))
+ movel %a0@(SYMBOL_NAME(autoirq_list)-VECOFF(VEC_SPUR)),%a0
+
+| amiga vector int handler get the req mask instead of irq vector
+ lea CUSTOMBASE,%a1
+ movew %a1@(C_INTREQR),%d0
+ andw %a1@(C_INTENAR),%d0
+
+| prepare stack (push frame pointer, dev_id & req mask)
+ pea %sp@
+ movel %a0@(IRQ_DEVID),%sp@-
+ movel %d0,%sp@-
+ pea %pc@(SYMBOL_NAME(ret_from_interrupt):w)
+ jbra @(IRQ_HANDLER,%a0)@(0)
+
+ENTRY(nmi_handler)
+ rte
+#endif
+#endif
+
/*
** This is the main interrupt handler, responsible for calling process_int()
*/
@@ -171,7 +213,7 @@ SYMBOL_NAME_LABEL(inthandler)
jbeq 1f
jbsr SYMBOL_NAME(floppy_hardint)
jbra 3f
-1:
+1:
#endif
jbsr SYMBOL_NAME(process_int)| process the IRQ
3: addql #8,%sp | pop parameters off stack
@@ -179,7 +221,7 @@ SYMBOL_NAME_LABEL(inthandler)
SYMBOL_NAME_LABEL(ret_from_interrupt)
subql #1,SYMBOL_NAME(local_irq_count)
jeq 1f
-2:
+2:
RESTORE_ALL
1:
#if 1
@@ -265,25 +307,30 @@ SYMBOL_NAME_LABEL(resume)
*/
/* save sr */
- movew %sr,%a0@(TASK_TSS+TSS_SR)
+ movew %sr,%a0@(TASK_THREAD+THREAD_SR)
/* save fs (sfc,%dfc) (may be pointing to kernel memory) */
movec %sfc,%d0
- movew %d0,%a0@(TASK_TSS+TSS_FS)
+ movew %d0,%a0@(TASK_THREAD+THREAD_FS)
/* save usp */
/* it is better to use a movel here instead of a movew 8*) */
movec %usp,%d0
- movel %d0,%a0@(TASK_TSS+TSS_USP)
+ movel %d0,%a0@(TASK_THREAD+THREAD_USP)
/* save non-scratch registers on stack */
SAVE_SWITCH_STACK
/* save current kernel stack pointer */
- movel %sp,%a0@(TASK_TSS+TSS_KSP)
+ movel %sp,%a0@(TASK_THREAD+THREAD_KSP)
/* save floating point context */
- fsave %a0@(TASK_TSS+TSS_FPSTATE)
+#ifndef CONFIG_M68KFPU_EMU_ONLY
+#ifdef CONFIG_M68KFPU_EMU
+ tstl SYMBOL_NAME(m68k_fputype)
+ jeq 3f
+#endif
+ fsave %a0@(TASK_THREAD+THREAD_FPSTATE)
#if defined(CONFIG_M68060)
#if !defined(CPU_M68060_ONLY)
@@ -291,127 +338,71 @@ SYMBOL_NAME_LABEL(resume)
beqs 1f
#endif
/* The 060 FPU keeps status in bits 15-8 of the first longword */
- tstb %a0@(TASK_TSS+TSS_FPSTATE+2)
+ tstb %a0@(TASK_THREAD+THREAD_FPSTATE+2)
jeq 3f
#if !defined(CPU_M68060_ONLY)
jra 2f
#endif
#endif /* CONFIG_M68060 */
#if !defined(CPU_M68060_ONLY)
-1: tstb %a0@(TASK_TSS+TSS_FPSTATE)
+1: tstb %a0@(TASK_THREAD+THREAD_FPSTATE)
jeq 3f
#endif
-2: fmovemx %fp0-%fp7,%a0@(TASK_TSS+TSS_FPREG)
- fmoveml %fpcr/%fpsr/%fpiar,%a0@(TASK_TSS+TSS_FPCNTL)
+2: fmovemx %fp0-%fp7,%a0@(TASK_THREAD+THREAD_FPREG)
+ fmoveml %fpcr/%fpsr/%fpiar,%a0@(TASK_THREAD+THREAD_FPCNTL)
3:
+#endif /* CONFIG_M68KFPU_EMU_ONLY */
/* Return previous task in %d1 */
movel %curptr,%d1
/* switch to new task (a1 contains new task) */
movel %a1,%curptr
- /* Skip address space switching if they are the same. */
- movel %a0@(TASK_MM),%d0
- cmpl %a1@(TASK_MM),%d0
+ /* restore floating point context */
+#ifndef CONFIG_M68KFPU_EMU_ONLY
+#ifdef CONFIG_M68KFPU_EMU
+ tstl SYMBOL_NAME(m68k_fputype)
jeq 4f
-
-#if defined(CPU_M68020_OR_M68030) && defined(CPU_M68040_OR_M68060)
- /* 68040 or 68060 ? */
- tstl SYMBOL_NAME(m68k_is040or060)
- bnes 1f
#endif
-#if defined(CPU_M68020_OR_M68030)
- /*
- * switch address space
- */
-
- /* flush MC68030/MC68020 caches (they are virtually addressed) */
- movec %cacr,%d0
- oriw #LFLUSH_I_AND_D,%d0
- movec %d0,%cacr
-
- /* switch the root pointer */
-#ifdef CPU_M68030_ONLY
- .chip 68030
- pmovefd %a1@(TASK_TSS+TSS_CRP),%crp
- .chip 68k
- pflush #0,#4
-#else
- pmove %a1@(TASK_TSS+TSS_CRP),%crp
-#endif
-#endif
-
-#if defined(CPU_M68020_OR_M68030) && defined(CPU_M68040_OR_M68060)
- jra 2f /* skip m68040 stuff */
-1:
-#endif
-#if defined(CPU_M68040_OR_M68060)
- /*
- * switch address space
- */
- .chip 68040
-
- /* flush address translation cache (user entries) */
- pflushan
-
- /* switch the root pointer */
- movel %a1@(TASK_TSS+TSS_CRP+4),%d0
- movec %d0,%urp
-
-#if defined (CONFIG_M68060)
- /* is it a '060 ? */
-#if !defined(CPU_M68060_ONLY)
- btst #3,SYMBOL_NAME(m68k_cputype)+3
- beqs 2f
-#endif
- /* clear user entries in the branch cache */
- movec %cacr,%d0
- orl #0x00200000,%d0
- movec %d0,%cacr
-#endif /* CONFIG_M68060 */
- .chip 68k
-#endif /* CPU_M68040_OR_M68060 */
-2:
-4:
- /* restore floating point context */
-
#if defined(CONFIG_M68060)
#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@(TASK_TSS+TSS_FPSTATE+2)
+ tstb %a1@(TASK_THREAD+THREAD_FPSTATE+2)
jeq 3f
#if !defined(CPU_M68060_ONLY)
jra 2f
#endif
#endif /* CONFIG_M68060 */
#if !defined(CPU_M68060_ONLY)
-1: tstb %a1@(TASK_TSS+TSS_FPSTATE)
+1: tstb %a1@(TASK_THREAD+THREAD_FPSTATE)
jeq 3f
#endif
-2: fmovemx %a1@(TASK_TSS+TSS_FPREG),%fp0-%fp7
- fmoveml %a1@(TASK_TSS+TSS_FPCNTL),%fpcr/%fpsr/%fpiar
-3: frestore %a1@(TASK_TSS+TSS_FPSTATE)
+2: fmovemx %a1@(TASK_THREAD+THREAD_FPREG),%fp0-%fp7
+ fmoveml %a1@(TASK_THREAD+THREAD_FPCNTL),%fpcr/%fpsr/%fpiar
+3: frestore %a1@(TASK_THREAD+THREAD_FPSTATE)
+4:
+#endif /* CONFIG_M68KFPU_EMU_ONLY */
/* restore the kernel stack pointer */
- movel %a1@(TASK_TSS+TSS_KSP),%sp
+ movel %a1@(TASK_THREAD+THREAD_KSP),%sp
/* restore non-scratch registers */
RESTORE_SWITCH_STACK
/* restore user stack pointer */
- movel %a1@(TASK_TSS+TSS_USP),%a0
+ movel %a1@(TASK_THREAD+THREAD_USP),%a0
movel %a0,%usp
/* restore fs (sfc,%dfc) */
- movew %a1@(TASK_TSS+TSS_FS),%a0
+ movew %a1@(TASK_THREAD+THREAD_FS),%a0
movec %a0,%sfc
movec %a0,%dfc
/* restore status register */
- movew %a1@(TASK_TSS+TSS_SR),%sr
+ movew %a1@(TASK_THREAD+THREAD_SR),%sr
rts
@@ -530,7 +521,7 @@ SYMBOL_NAME_LABEL(sys_call_table)
.long SYMBOL_NAME(sys_ni_syscall)
.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) /* obsolete idle() syscall */
.long SYMBOL_NAME(sys_ni_syscall) /* vm86old for i386 */
.long SYMBOL_NAME(sys_wait4)
.long SYMBOL_NAME(sys_swapoff) /* 115 */
diff --git a/arch/m68k/kernel/head.S b/arch/m68k/kernel/head.S
index 361b10cb6..49285b86d 100644
--- a/arch/m68k/kernel/head.S
+++ b/arch/m68k/kernel/head.S
@@ -503,10 +503,18 @@ func_define putn,1
.macro puts string
#if defined(CONSOLE) || defined(SERIAL_DEBUG)
+/* The __INITDATA stuff is a no-op when ftrace or kgdb are turned on */
+#if defined(CONFIG_FTRACE) || defined(CONFIG_KGDB)
+ bra 1f
+#endif
__INITDATA
.Lstr\@:
.string "\string"
__FINIT
+#if defined(CONFIG_FTRACE) || defined(CONFIG_KGDB)
+ .align 2
+1:
+#endif
pea %pc@(.Lstr\@)
func_call puts
addql #4,%sp
diff --git a/arch/m68k/kernel/ints.c b/arch/m68k/kernel/ints.c
index 31931a920..9dc6427e6 100644
--- a/arch/m68k/kernel/ints.c
+++ b/arch/m68k/kernel/ints.c
@@ -86,14 +86,14 @@ void (*mach_free_irq) (unsigned int, void *) = dummy_free_irq;
* the IRQ handling routines.
*/
-__initfunc(void init_IRQ(void))
+void __init init_IRQ(void)
{
int i;
for (i = 0; i < SYS_IRQS; i++) {
if (mach_default_handler)
irq_list[i].handler = (*mach_default_handler)[i];
- irq_list[i].flags = IRQ_FLG_STD;
+ irq_list[i].flags = 0;
irq_list[i].dev_id = NULL;
irq_list[i].devname = default_names[i];
}
@@ -144,6 +144,7 @@ int sys_request_irq(unsigned int irq,
return -ENXIO;
}
+#if 0
if (!(irq_list[irq].flags & IRQ_FLG_STD)) {
if (irq_list[irq].flags & IRQ_FLG_LOCK) {
printk("%s: IRQ %d from %s is not replaceable\n",
@@ -156,6 +157,8 @@ int sys_request_irq(unsigned int irq,
return -EBUSY;
}
}
+#endif
+
irq_list[irq].handler = handler;
irq_list[irq].flags = flags;
irq_list[irq].dev_id = dev_id;
@@ -175,7 +178,7 @@ void sys_free_irq(unsigned int irq, void *dev_id)
__FUNCTION__, irq, irq_list[irq].devname);
irq_list[irq].handler = (*mach_default_handler)[irq];
- irq_list[irq].flags = IRQ_FLG_STD;
+ irq_list[irq].flags = 0;
irq_list[irq].dev_id = NULL;
irq_list[irq].devname = default_names[irq];
}
@@ -250,9 +253,6 @@ int get_irq_list(char *buf)
for (i = 0; i < SYS_IRQS; i++) {
len += sprintf(buf+len, "auto %2d: %10u ", i,
i ? kstat.irqs[0][i] : num_spurious);
- if (irq_list[i].flags & IRQ_FLG_LOCK)
- len += sprintf(buf+len, "L ");
- else
len += sprintf(buf+len, " ");
len += sprintf(buf+len, "%s\n", irq_list[i].devname);
}
diff --git a/arch/m68k/kernel/kgdb.c b/arch/m68k/kernel/kgdb.c
index cdbd250cd..be75defdb 100644
--- a/arch/m68k/kernel/kgdb.c
+++ b/arch/m68k/kernel/kgdb.c
@@ -189,6 +189,11 @@
#include <asm/amigahw.h>
#include <asm/amigaints.h>
#endif
+#ifdef CONFIG_MAC
+#include <linux/tty.h>
+#include <asm/bootinfo.h>
+#include <asm/macints.h>
+#endif
#undef DEBUG
@@ -239,6 +244,15 @@ static unsigned char atari_scc_intr( void );
extern int amiga_ser_out( unsigned char c );
extern unsigned char amiga_ser_in( void );
#endif
+#ifdef CONFIG_MAC
+static unsigned char mac_scca_in( void );
+static unsigned char mac_scca_out( unsigned char c );
+static unsigned char mac_scca_intr( void );
+static unsigned char mac_sccb_in( void );
+static unsigned char mac_sccb_out( unsigned char c);
+static unsigned char mac_sccb_intr( void );
+extern void mac_init_scc_port( int cflag, int port );
+#endif
/************************* End of Prototypes **************************/
@@ -668,6 +682,31 @@ void kgdb_init(void)
}
#endif
+#ifdef CONFIG_MAC
+ if (MACH_IS_MAC) {
+ if (!strcmp( m68k_debug_device, "ser" ) ||
+ !strcmp( m68k_debug_device, "ser1" )) {
+ mac_init_scc_port( B9600|CS8, 0 );
+ serial_in = mac_scca_in;
+ serial_out = mac_scca_out;
+ serial_intr = mac_scca_intr;
+ } else if (!strcmp( m68k_debug_device, "ser2" )) {
+ mac_init_scc_port( B9600|CS8, 1 );
+ serial_in = mac_sccb_in;
+ serial_out = mac_sccb_out;
+ serial_intr = mac_sccb_intr;
+ }
+ }
+ if (!serial_in || !serial_out) {
+ if (*m68k_debug_device)
+ printk( "kgdb_init failed: no valid serial device!\n" );
+ else
+ printk( "kgdb not enabled\n" );
+ return;
+ }
+ request_irq(4, kgdb_intr, IRQ_TYPE_FAST, "kgdb", NULL);
+#endif
+
#ifdef CONFIG_ATARI
if (!serial_in || !serial_out) {
if (*m68k_debug_device)
@@ -781,8 +820,15 @@ __asm__
/* copy format/vector word */
" movew %a0@("FRAMEOFF_VECTOR"),%a1@("GDBOFF_VECTOR")\n"
/* save FPU regs */
+#ifndef CONFIG_M68KFPU_EMU_ONLY
+#ifdef CONFIG_M68KFPU_EMU
+ " tstl "SYMBOL_NAME_STR(m68k_fputype)"\n"
+ " jeq 1f\n"
+#endif
" fmovemx %fp0-%fp7,%a1@("GDBOFF_FP0")\n"
" fmoveml %fpcr/%fpsr/%fpiar,%a1@("GDBOFF_FPCTL")\n"
+ "1:\n"
+#endif /* CONFIG_M68KFPU_EMU_ONLY */
/* set stack to CPU frame */
" addl #"FRAMEOFF_SR",%a0\n"
@@ -801,8 +847,15 @@ __asm__
/* after return, first restore FPU registers */
" movel #"SYMBOL_NAME_STR(kgdb_registers)",%a0\n" /* source */
+#ifndef CONFIG_M68KFPU_EMU_ONLY
+#ifdef CONFIG_M68KFPU_EMU
+ " tstl "SYMBOL_NAME_STR(m68k_fputype)"\n"
+ " jeq 1f\n"
+#endif
" fmovemx %a0@("GDBOFF_FP0"),%fp0-%fp7\n"
" fmoveml %a0@("GDBOFF_FPCTL"),%fpcr/%fpsr/%fpiar\n"
+ "1:\n"
+#endif /* CONFIG_M68KFPU_EMU_ONLY */
/* set new stack pointer */
" movel %a0@("GDBOFF_A7"),%sp\n"
" clrw %sp@-\n" /* fake format $0 frame */
@@ -849,8 +902,15 @@ __asm__
/* fake format 0 and vector 1 (translated to SIGINT) */
" movew #4,%a1@("GDBOFF_VECTOR")\n"
/* save FPU regs */
+#ifndef CONFIG_M68KFPU_EMU_ONLY
+#ifdef CONFIG_M68KFPU_EMU
+ " tstl "SYMBOL_NAME_STR(m68k_fputype)"\n"
+ " jeq 1f\n"
+#endif
" fmovemx %fp0-%fp7,%a1@("GDBOFF_FP0")\n"
" fmoveml %fpcr/%fpsr/%fpiar,%a1@("GDBOFF_FPCTL")\n"
+ "1:\n"
+#endif /* CONFIG_M68KFPU_EMU_ONLY */
/* pop off the CPU stack frame */
" addql #8,%sp\n"
" movel %sp,%a1@("GDBOFF_A7")\n" /* save a7 now */
@@ -1192,3 +1252,111 @@ static unsigned char atari_scc_intr( void )
}
#endif
+
+/* -------------------- Macintosh serial I/O -------------------- */
+
+#ifdef CONFIG_MAC
+
+struct SCC
+ {
+ u_char cha_b_ctrl;
+ u_char char_dummy1;
+ u_char cha_a_ctrl;
+ u_char char_dummy2;
+ u_char cha_b_data;
+ u_char char_dummy3;
+ u_char cha_a_data;
+ };
+
+#define scc (*((volatile struct SCC*)mac_bi_data.sccbase))
+
+#define uSEC 1
+#define LONG_DELAY() \
+ do { \
+ int i; \
+ for( i = 60*uSEC; i > 0; --i ) \
+ barrier(); \
+ } while(0)
+
+static unsigned char mac_sccb_out (unsigned char c)
+{
+ int i;
+ do {
+ LONG_DELAY();
+ } while (!(scc.cha_b_ctrl & 0x04)); /* wait for tx buf empty */
+ for( i = uSEC; i > 0; --i )
+ barrier();
+ scc.cha_b_data = c;
+}
+
+static unsigned char mac_scca_out (unsigned char c)
+{
+ int i;
+ do {
+ LONG_DELAY();
+ } while (!(scc.cha_a_ctrl & 0x04)); /* wait for tx buf empty */
+ for( i = uSEC; i > 0; --i )
+ barrier();
+ scc.cha_a_data = c;
+}
+
+static unsigned char mac_sccb_in( void )
+{
+ do {
+ LONG_DELAY();
+ } while( !(scc.cha_b_ctrl & 0x01) ); /* wait for rx buf filled */
+ LONG_DELAY();
+ return( scc.cha_b_data );
+}
+
+static unsigned char mac_scca_in( void )
+
+{
+ do {
+ LONG_DELAY();
+ } while( !(scc.cha_a_ctrl & 0x01) ); /* wait for rx buf filled */
+ LONG_DELAY();
+ return( scc.cha_a_data );
+}
+
+static unsigned char mac_sccb_intr( void )
+
+{ unsigned char c, stat;
+
+ LONG_DELAY();
+ scc.cha_b_ctrl = 1; /* RR1 */
+ LONG_DELAY();
+ stat = scc.cha_b_ctrl;
+ LONG_DELAY();
+ c = scc.cha_b_data;
+ LONG_DELAY();
+ if (stat & 0x30) {
+ scc.cha_b_ctrl = 0x30; /* error reset for overrun and parity */
+ LONG_DELAY();
+ }
+ scc.cha_b_ctrl = 0x38; /* reset highest IUS */
+ LONG_DELAY();
+ return( c );
+}
+
+static unsigned char mac_scca_intr( void )
+
+{ unsigned char c, stat;
+
+ LONG_DELAY();
+ scc.cha_a_ctrl = 1; /* RR1 */
+ LONG_DELAY();
+ stat = scc.cha_a_ctrl;
+ LONG_DELAY();
+ c = scc.cha_a_data;
+ LONG_DELAY();
+ if (stat & 0x30) {
+ scc.cha_a_ctrl = 0x30; /* error reset for overrun and parity */
+ LONG_DELAY();
+ }
+ scc.cha_a_ctrl = 0x38; /* reset highest IUS */
+ LONG_DELAY();
+ return( c );
+}
+
+#endif
diff --git a/arch/m68k/kernel/m68k_defs.c b/arch/m68k/kernel/m68k_defs.c
index e2e6715e7..47cffcfa9 100644
--- a/arch/m68k/kernel/m68k_defs.c
+++ b/arch/m68k/kernel/m68k_defs.c
@@ -26,25 +26,34 @@ int main(void)
DEFINE(TASK_FLAGS, offsetof(struct task_struct, flags));
DEFINE(TASK_SIGPENDING, offsetof(struct task_struct, sigpending));
DEFINE(TASK_NEEDRESCHED, offsetof(struct task_struct, need_resched));
- DEFINE(TASK_TSS, offsetof(struct task_struct, tss));
+ DEFINE(TASK_THREAD, offsetof(struct task_struct, thread));
DEFINE(TASK_MM, offsetof(struct task_struct, mm));
+ DEFINE(TASK_ACTIVE_MM, offsetof(struct task_struct, active_mm));
/* offsets into the thread struct */
- DEFINE(TSS_KSP, offsetof(struct thread_struct, ksp));
- DEFINE(TSS_USP, offsetof(struct thread_struct, usp));
- DEFINE(TSS_SR, offsetof(struct thread_struct, sr));
- DEFINE(TSS_FS, offsetof(struct thread_struct, fs));
- DEFINE(TSS_CRP, offsetof(struct thread_struct, crp));
- DEFINE(TSS_ESP0, offsetof(struct thread_struct, esp0));
- DEFINE(TSS_FPREG, offsetof(struct thread_struct, fp));
- DEFINE(TSS_FPCNTL, offsetof(struct thread_struct, fpcntl));
- DEFINE(TSS_FPSTATE, offsetof(struct thread_struct, fpstate));
+ DEFINE(THREAD_KSP, offsetof(struct thread_struct, ksp));
+ DEFINE(THREAD_USP, offsetof(struct thread_struct, usp));
+ DEFINE(THREAD_SR, offsetof(struct thread_struct, sr));
+ DEFINE(THREAD_FS, offsetof(struct thread_struct, fs));
+ DEFINE(THREAD_CRP, offsetof(struct thread_struct, crp));
+ DEFINE(THREAD_ESP0, offsetof(struct thread_struct, esp0));
+ DEFINE(THREAD_FPREG, offsetof(struct thread_struct, fp));
+ DEFINE(THREAD_FPCNTL, offsetof(struct thread_struct, fpcntl));
+ DEFINE(THREAD_FPSTATE, offsetof(struct thread_struct, fpstate));
/* offsets into the pt_regs */
DEFINE(PT_D0, offsetof(struct pt_regs, d0));
DEFINE(PT_ORIG_D0, offsetof(struct pt_regs, orig_d0));
+ DEFINE(PT_D1, offsetof(struct pt_regs, d1));
+ DEFINE(PT_D2, offsetof(struct pt_regs, d2));
+ DEFINE(PT_D3, offsetof(struct pt_regs, d3));
+ DEFINE(PT_D4, offsetof(struct pt_regs, d4));
+ DEFINE(PT_D5, offsetof(struct pt_regs, d5));
+ DEFINE(PT_A0, offsetof(struct pt_regs, a0));
+ DEFINE(PT_A1, offsetof(struct pt_regs, a1));
+ DEFINE(PT_A2, offsetof(struct pt_regs, a2));
+ DEFINE(PT_PC, offsetof(struct pt_regs, pc));
DEFINE(PT_SR, offsetof(struct pt_regs, sr));
-
/* bitfields are a bit difficult */
DEFINE(PT_VECTOR, offsetof(struct pt_regs, pc) + 4);
@@ -69,6 +78,12 @@ int main(void)
DEFINE(FBCON_FONT_DESC_DATA, offsetof(struct fbcon_font_desc, data));
DEFINE(FBCON_FONT_DESC_PREF, offsetof(struct fbcon_font_desc, pref));
+ /* signal defines */
+ DEFINE(SIGSEGV, SIGSEGV);
+ DEFINE(SEGV_MAPERR, SEGV_MAPERR);
+ DEFINE(SIGTRAP, SIGTRAP);
+ DEFINE(TRAP_TRACE, TRAP_TRACE);
+
/* offsets into the custom struct */
DEFINE(CUSTOMBASE, &custom);
DEFINE(C_INTENAR, offsetof(struct CUSTOM, intenar));
diff --git a/arch/m68k/kernel/m68k_defs.h b/arch/m68k/kernel/m68k_defs.h
index 4926a6dad..374e56e27 100644
--- a/arch/m68k/kernel/m68k_defs.h
+++ b/arch/m68k/kernel/m68k_defs.h
@@ -7,19 +7,29 @@
#define TASK_FLAGS 4
#define TASK_SIGPENDING 8
#define TASK_NEEDRESCHED 20
-#define TASK_TSS 470
-#define TASK_MM 622
-#define TSS_KSP 0
-#define TSS_USP 4
-#define TSS_SR 8
-#define TSS_FS 10
-#define TSS_CRP 12
-#define TSS_ESP0 20
-#define TSS_FPREG 24
-#define TSS_FPCNTL 120
-#define TSS_FPSTATE 132
+#define TASK_THREAD 482
+#define TASK_MM 634
+#define TASK_ACTIVE_MM 638
+#define THREAD_KSP 0
+#define THREAD_USP 4
+#define THREAD_SR 8
+#define THREAD_FS 10
+#define THREAD_CRP 12
+#define THREAD_ESP0 20
+#define THREAD_FPREG 24
+#define THREAD_FPCNTL 120
+#define THREAD_FPSTATE 132
#define PT_D0 32
#define PT_ORIG_D0 36
+#define PT_D1 0
+#define PT_D2 4
+#define PT_D3 8
+#define PT_D4 12
+#define PT_D5 16
+#define PT_A0 20
+#define PT_A1 24
+#define PT_A2 28
+#define PT_PC 46
#define PT_SR 44
#define PT_VECTOR 50
#define IRQ_HANDLER 0
@@ -35,6 +45,10 @@
#define FBCON_FONT_DESC_HEIGHT 12
#define FBCON_FONT_DESC_DATA 16
#define FBCON_FONT_DESC_PREF 20
+#define SIGSEGV 11
+#define SEGV_MAPERR 1
+#define SIGTRAP 5
+#define TRAP_TRACE 2
#define CUSTOMBASE -2132807680
#define C_INTENAR 28
#define C_INTREQR 30
diff --git a/arch/m68k/kernel/m68k_ksyms.c b/arch/m68k/kernel/m68k_ksyms.c
index 5aae5953c..64af7cf7c 100644
--- a/arch/m68k/kernel/m68k_ksyms.c
+++ b/arch/m68k/kernel/m68k_ksyms.c
@@ -38,11 +38,14 @@ EXPORT_SYMBOL(mm_vtop);
EXPORT_SYMBOL(mm_ptov);
EXPORT_SYMBOL(mm_end_of_chunk);
#endif
-EXPORT_SYMBOL(mm_vtop_fallback);
EXPORT_SYMBOL(m68k_realnum_memory);
EXPORT_SYMBOL(m68k_memory);
+#ifndef CONFIG_SUN3
+EXPORT_SYMBOL(mm_vtop_fallback);
EXPORT_SYMBOL(__ioremap);
EXPORT_SYMBOL(iounmap);
+EXPORT_SYMBOL(kernel_set_cachemode);
+#endif
EXPORT_SYMBOL(m68k_debug_device);
EXPORT_SYMBOL(dump_fpu);
EXPORT_SYMBOL(dump_thread);
@@ -53,10 +56,7 @@ EXPORT_SYMBOL(local_irq_count);
EXPORT_SYMBOL(local_bh_count);
EXPORT_SYMBOL(enable_irq);
EXPORT_SYMBOL(disable_irq);
-EXPORT_SYMBOL(kernel_set_cachemode);
EXPORT_SYMBOL(kernel_thread);
-EXPORT_SYMBOL(register_serial);
-EXPORT_SYMBOL(unregister_serial);
/* Networking helper routines. */
EXPORT_SYMBOL(csum_partial_copy);
@@ -69,6 +69,7 @@ EXPORT_SYMBOL_NOVERS(__ashrdi3);
EXPORT_SYMBOL_NOVERS(memcpy);
EXPORT_SYMBOL_NOVERS(memset);
EXPORT_SYMBOL_NOVERS(memcmp);
+EXPORT_SYMBOL_NOVERS(memscan);
EXPORT_SYMBOL_NOVERS(__down_failed);
EXPORT_SYMBOL_NOVERS(__down_failed_interruptible);
diff --git a/arch/m68k/kernel/process.c b/arch/m68k/kernel/process.c
index 97f3bd151..ba94860f6 100644
--- a/arch/m68k/kernel/process.c
+++ b/arch/m68k/kernel/process.c
@@ -40,49 +40,64 @@
*/
static struct vm_area_struct init_mmap = INIT_MMAP;
static struct fs_struct init_fs = INIT_FS;
-static struct file * init_fd_array[NR_OPEN] = { NULL, };
static struct files_struct init_files = INIT_FILES;
static struct signal_struct init_signals = INIT_SIGNALS;
-struct mm_struct init_mm = INIT_MM;
+struct mm_struct init_mm = INIT_MM(init_mm);
union task_union init_task_union
- __attribute__((section("init_task"), aligned(2*PAGE_SIZE)))
- = { task: INIT_TASK };
+__attribute__((section("init_task"), aligned(KTHREAD_SIZE)))
+ = { task: INIT_TASK(init_task_union.task) };
+
+asmlinkage void ret_from_fork(void);
-asmlinkage void ret_from_exception(void);
/*
* The idle loop on an m68k..
*/
-asmlinkage int sys_idle(void)
+static void default_idle(void)
{
- if (current->pid != 0)
- return -EPERM;
-
- /* endless idle loop with no priority at all */
- current->priority = 0;
- current->counter = -100;
- for (;;) {
+ while(1) {
if (!current->need_resched)
-#if defined(CONFIG_ATARI) && !defined(CONFIG_AMIGA) && !defined(CONFIG_MAC)
+#if defined(MACH_ATARI_ONLY) && !defined(CONFIG_HADES)
/* block out HSYNC on the atari (falcon) */
__asm__("stop #0x2200" : : : "cc");
-#else /* portable version */
+#else
__asm__("stop #0x2000" : : : "cc");
-#endif /* machine compilation types */
+#endif
schedule();
check_pgt_cache();
}
}
+void (*idle)(void) = default_idle;
+
+/*
+ * The idle thread. There's no useful work to be
+ * done, so just try to conserve power and have a
+ * low exit latency (ie sit in a loop waiting for
+ * somebody to say that they'd like to reschedule)
+ */
+void cpu_idle(void)
+{
+ /* endless idle loop with no priority at all */
+ init_idle();
+ current->priority = 0;
+ current->counter = -100;
+ idle();
+}
+
void machine_restart(char * __unused)
{
if (mach_reset)
mach_reset();
+ for (;;);
}
void machine_halt(void)
{
+ if (mach_halt)
+ mach_halt();
+ for (;;);
}
void machine_power_off(void)
@@ -90,6 +105,10 @@ void machine_power_off(void)
#if defined(CONFIG_APM) && defined(CONFIG_APM_POWER_OFF)
apm_set_power_state(APM_STATE_OFF);
#endif
+
+ if (mach_power_off)
+ mach_power_off();
+ for (;;);
}
void show_regs(struct pt_regs * regs)
@@ -127,7 +146,7 @@ int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
"trap #0\n\t" /* Linux/m68k system call */
"tstl %0\n\t" /* child or parent */
"jne 1f\n\t" /* parent - jump */
- "lea %%sp@(-8192),%6\n\t" /* reload current */
+ "lea %%sp@(%c7),%6\n\t" /* reload current */
"movel %3,%%sp@-\n\t" /* push argument */
"jsr %4@\n\t" /* call fn */
"movel %0,%%d1\n\t" /* pass exit value */
@@ -136,7 +155,8 @@ int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
"1:"
: "=d" (retval)
: "0" (__NR_clone), "i" (__NR_exit),
- "r" (arg), "a" (fn), "d" (clone_arg), "r" (current)
+ "r" (arg), "a" (fn), "d" (clone_arg), "r" (current),
+ "i" (-KTHREAD_SIZE)
: "d0", "d2");
pid = retval;
}
@@ -149,10 +169,11 @@ void flush_thread(void)
{
unsigned long zero = 0;
set_fs(USER_DS);
- current->tss.fs = __USER_DS;
- asm volatile (".chip 68k/68881\n\t"
- "frestore %0@\n\t"
- ".chip 68k" : : "a" (&zero));
+ current->thread.fs = __USER_DS;
+ if (!FPU_IS_EMU)
+ asm volatile (".chip 68k/68881\n\t"
+ "frestore %0@\n\t"
+ ".chip 68k" : : "a" (&zero));
}
/*
@@ -192,7 +213,7 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
struct switch_stack * childstack, *stack;
unsigned long stack_offset, *retp;
- stack_offset = 2*PAGE_SIZE - sizeof(struct pt_regs);
+ stack_offset = KTHREAD_SIZE - sizeof(struct pt_regs);
childregs = (struct pt_regs *) ((unsigned long) p + stack_offset);
*childregs = *regs;
@@ -203,26 +224,28 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
childstack = ((struct switch_stack *) childregs) - 1;
*childstack = *stack;
- childstack->retpc = (unsigned long) ret_from_exception;
+ childstack->retpc = (unsigned long)ret_from_fork;
- p->tss.usp = usp;
- p->tss.ksp = (unsigned long)childstack;
+ p->thread.usp = usp;
+ p->thread.ksp = (unsigned long)childstack;
/*
* Must save the current SFC/DFC value, NOT the value when
* the parent was last descheduled - RGH 10-08-96
*/
- p->tss.fs = get_fs().seg;
-
- /* Copy the current fpu state */
- asm volatile ("fsave %0" : : "m" (p->tss.fpstate[0]) : "memory");
-
- if (!CPU_IS_060 ? p->tss.fpstate[0] : p->tss.fpstate[2])
- asm volatile ("fmovemx %/fp0-%/fp7,%0\n\t"
- "fmoveml %/fpiar/%/fpcr/%/fpsr,%1"
- : : "m" (p->tss.fp[0]), "m" (p->tss.fpcntl[0])
- : "memory");
- /* Restore the state in case the fpu was busy */
- asm volatile ("frestore %0" : : "m" (p->tss.fpstate[0]));
+ p->thread.fs = get_fs().seg;
+
+ if (!FPU_IS_EMU) {
+ /* Copy the current fpu state */
+ asm volatile ("fsave %0" : : "m" (p->thread.fpstate[0]) : "memory");
+
+ if (!CPU_IS_060 ? p->thread.fpstate[0] : p->thread.fpstate[2])
+ asm volatile ("fmovemx %/fp0-%/fp7,%0\n\t"
+ "fmoveml %/fpiar/%/fpcr/%/fpsr,%1"
+ : : "m" (p->thread.fp[0]), "m" (p->thread.fpcntl[0])
+ : "memory");
+ /* Restore the state in case the fpu was busy */
+ asm volatile ("frestore %0" : : "m" (p->thread.fpstate[0]));
+ }
return 0;
}
@@ -231,20 +254,34 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
int dump_fpu (struct pt_regs *regs, struct user_m68kfp_struct *fpu)
{
- char fpustate[216];
+ char fpustate[216];
+
+ if (FPU_IS_EMU) {
+ int i;
+
+ memcpy(fpu->fpcntl, current->thread.fpcntl, 12);
+ memcpy(fpu->fpregs, current->thread.fp, 96);
+ /* Convert internal fpu reg representation
+ * into long double format
+ */
+ for (i = 0; i < 24; i += 3)
+ fpu->fpregs[i] = ((fpu->fpregs[i] & 0xffff0000) << 15) |
+ ((fpu->fpregs[i] & 0x0000ffff) << 16);
+ return 1;
+ }
- /* First dump the fpu context to avoid protocol violation. */
- asm volatile ("fsave %0" :: "m" (fpustate[0]) : "memory");
- if (!CPU_IS_060 ? !fpustate[0] : !fpustate[2])
- return 0;
+ /* First dump the fpu context to avoid protocol violation. */
+ asm volatile ("fsave %0" :: "m" (fpustate[0]) : "memory");
+ if (!CPU_IS_060 ? !fpustate[0] : !fpustate[2])
+ return 0;
- asm volatile ("fmovem %/fpiar/%/fpcr/%/fpsr,%0"
+ asm volatile ("fmovem %/fpiar/%/fpcr/%/fpsr,%0"
:: "m" (fpu->fpcntl[0])
: "memory");
- asm volatile ("fmovemx %/fp0-%/fp7,%0"
+ asm volatile ("fmovemx %/fp0-%/fp7,%0"
:: "m" (fpu->fpregs[0])
: "memory");
- return 1;
+ return 1;
}
/*
diff --git a/arch/m68k/kernel/ptrace.c b/arch/m68k/kernel/ptrace.c
index 86e225362..7db64849d 100644
--- a/arch/m68k/kernel/ptrace.c
+++ b/arch/m68k/kernel/ptrace.c
@@ -18,6 +18,7 @@
#include <linux/errno.h>
#include <linux/ptrace.h>
#include <linux/user.h>
+#include <linux/config.h>
#include <asm/uaccess.h>
#include <asm/page.h>
@@ -37,7 +38,7 @@
/* sets the trace bits. */
#define TRACE_BITS 0x8000
-/* Find the stack offset for a register, relative to tss.esp0. */
+/* Find the stack offset for a register, relative to thread.esp0. */
#define PT_REG(reg) ((long)&((struct pt_regs *)0)->reg)
#define SW_REG(reg) ((long)&((struct switch_stack *)0)->reg \
- sizeof(struct switch_stack))
@@ -60,9 +61,9 @@ static inline long get_reg(struct task_struct *task, int regno)
unsigned long *addr;
if (regno == PT_USP)
- addr = &task->tss.usp;
+ addr = &task->thread.usp;
else if (regno < sizeof(regoff)/sizeof(regoff[0]))
- addr = (unsigned long *)(task->tss.esp0 + regoff[regno]);
+ addr = (unsigned long *)(task->thread.esp0 + regoff[regno]);
else
return 0;
return *addr;
@@ -77,9 +78,9 @@ static inline int put_reg(struct task_struct *task, int regno,
unsigned long *addr;
if (regno == PT_USP)
- addr = &task->tss.usp;
+ addr = &task->thread.usp;
else if (regno < sizeof(regoff)/sizeof(regoff[0]))
- addr = (unsigned long *) (task->tss.esp0 + regoff[regno]);
+ addr = (unsigned long *) (task->thread.esp0 + regoff[regno]);
else
return -1;
*addr = data;
@@ -384,10 +385,17 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
tmp = get_reg(child, addr);
if (addr == PT_SR)
tmp >>= 16;
- }
- else if (addr >= 21 && addr < 49)
- tmp = child->tss.fp[addr - 21];
- else
+ } else if (addr >= 21 && addr < 49) {
+ tmp = child->thread.fp[addr - 21];
+#ifdef CONFIG_M68KFPU_EMU
+ /* Convert internal fpu reg representation
+ * into long double format
+ */
+ if (FPU_IS_EMU && (addr < 45) && !(addr % 3))
+ tmp = ((tmp & 0xffff0000) << 15) |
+ ((tmp & 0x0000ffff) << 16);
+#endif
+ } else
goto out;
ret = put_user(tmp,(unsigned long *) data);
goto out;
@@ -423,7 +431,17 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
}
if (addr >= 21 && addr < 48)
{
- child->tss.fp[addr - 21] = data;
+#ifdef CONFIG_M68KFPU_EMU
+ /* Convert long double format
+ * into internal fpu reg representation
+ */
+ if (FPU_IS_EMU && (addr < 45) && !(addr % 3)) {
+ data = (unsigned long)data << 15;
+ data = (data & 0xffff0000) |
+ ((data & 0x0000ffff) >> 1);
+ }
+#endif
+ child->thread.fp[addr - 21] = data;
ret = 0;
}
goto out;
@@ -544,7 +562,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
case PTRACE_GETFPREGS: { /* Get the child FPU state. */
ret = 0;
- if (copy_to_user((void *)data, &child->tss.fp,
+ if (copy_to_user((void *)data, &child->thread.fp,
sizeof(struct user_m68kfp_struct)))
ret = -EFAULT;
goto out;
@@ -552,7 +570,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
case PTRACE_SETFPREGS: { /* Set the child FPU state. */
ret = 0;
- if (copy_from_user(&child->tss.fp, (void *)data,
+ if (copy_from_user(&child->thread.fp, (void *)data,
sizeof(struct user_m68kfp_struct)))
ret = -EFAULT;
goto out;
diff --git a/arch/m68k/kernel/semaphore.c b/arch/m68k/kernel/semaphore.c
new file mode 100644
index 000000000..d62b355e1
--- /dev/null
+++ b/arch/m68k/kernel/semaphore.c
@@ -0,0 +1,129 @@
+/*
+ * Generic semaphore code. Buyer beware. Do your own
+ * specific changes in <asm/semaphore-helper.h>
+ */
+
+#include <linux/sched.h>
+#include <asm/semaphore-helper.h>
+
+/*
+ * Semaphores are implemented using a two-way counter:
+ * The "count" variable is decremented for each process
+ * that tries to sleep, while the "waking" variable is
+ * incremented when the "up()" code goes to wake up waiting
+ * processes.
+ *
+ * Notably, the inline "up()" and "down()" functions can
+ * efficiently test if they need to do any extra work (up
+ * needs to do something only if count was negative before
+ * the increment operation.
+ *
+ * waking_non_zero() (from asm/semaphore.h) must execute
+ * atomically.
+ *
+ * When __up() is called, the count was negative before
+ * incrementing it, and we need to wake up somebody.
+ *
+ * This routine adds one to the count of processes that need to
+ * wake up and exit. ALL waiting processes actually wake up but
+ * only the one that gets to the "waking" field first will gate
+ * through and acquire the semaphore. The others will go back
+ * to sleep.
+ *
+ * Note that these functions are only called when there is
+ * contention on the lock, and as such all this is the
+ * "non-critical" part of the whole semaphore business. The
+ * critical part is the inline stuff in <asm/semaphore.h>
+ * where we want to avoid any extra jumps and calls.
+ */
+void __up(struct semaphore *sem)
+{
+ wake_one_more(sem);
+ wake_up(&sem->wait);
+}
+
+/*
+ * Perform the "down" function. Return zero for semaphore acquired,
+ * return negative for signalled out of the function.
+ *
+ * If called from __down, the return is ignored and the wait loop is
+ * not interruptible. This means that a task waiting on a semaphore
+ * using "down()" cannot be killed until someone does an "up()" on
+ * the semaphore.
+ *
+ * If called from __down_interruptible, the return value gets checked
+ * upon return. If the return value is negative then the task continues
+ * with the negative value in the return register (it can be tested by
+ * the caller).
+ *
+ * Either form may be used in conjunction with "up()".
+ *
+ */
+
+#define DOWN_VAR \
+ struct task_struct *tsk = current; \
+ wait_queue_t wait; \
+ init_waitqueue_entry(&wait, tsk);
+
+#define DOWN_HEAD(task_state) \
+ \
+ \
+ tsk->state = (task_state); \
+ add_wait_queue(&sem->wait, &wait); \
+ \
+ /* \
+ * Ok, we're set up. sem->count is known to be less than zero \
+ * so we must wait. \
+ * \
+ * We can let go the lock for purposes of waiting. \
+ * We re-acquire it after awaking so as to protect \
+ * all semaphore operations. \
+ * \
+ * If "up()" is called before we call waking_non_zero() then \
+ * we will catch it right away. If it is called later then \
+ * we will have to go through a wakeup cycle to catch it. \
+ * \
+ * Multiple waiters contend for the semaphore lock to see \
+ * who gets to gate through and who has to wait some more. \
+ */ \
+ for (;;) {
+
+#define DOWN_TAIL(task_state) \
+ tsk->state = (task_state); \
+ } \
+ tsk->state = TASK_RUNNING; \
+ remove_wait_queue(&sem->wait, &wait);
+
+void __down(struct semaphore * sem)
+{
+ DOWN_VAR
+ DOWN_HEAD(TASK_UNINTERRUPTIBLE)
+ if (waking_non_zero(sem))
+ break;
+ schedule();
+ DOWN_TAIL(TASK_UNINTERRUPTIBLE)
+}
+
+int __down_interruptible(struct semaphore * sem)
+{
+ int ret = 0;
+ DOWN_VAR
+ DOWN_HEAD(TASK_INTERRUPTIBLE)
+
+ ret = waking_non_zero_interruptible(sem, tsk);
+ if (ret)
+ {
+ if (ret == 1)
+ /* ret != 0 only if we get interrupted -arca */
+ ret = 0;
+ break;
+ }
+ schedule();
+ DOWN_TAIL(TASK_INTERRUPTIBLE)
+ return ret;
+}
+
+int __down_trylock(struct semaphore * sem)
+{
+ return waking_non_zero_trylock(sem);
+}
diff --git a/arch/m68k/kernel/setup.c b/arch/m68k/kernel/setup.c
index 39dcd9c15..adafc9879 100644
--- a/arch/m68k/kernel/setup.c
+++ b/arch/m68k/kernel/setup.c
@@ -19,6 +19,7 @@
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/init.h>
+#include <linux/module.h>
#include <asm/bootinfo.h>
#include <asm/setup.h>
@@ -76,6 +77,8 @@ 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_reset)( void );
+void (*mach_halt)( void ) = NULL;
+void (*mach_power_off)( void ) = NULL;
long mach_max_dma_address = 0x00ffffff; /* default set to the lower 16MB */
#if defined(CONFIG_AMIGA_FLOPPY) || defined(CONFIG_ATARI_FLOPPY) || defined(CONFIG_BLK_DEV_FD)
void (*mach_floppy_setup) (char *, int *) __initdata = NULL;
@@ -100,6 +103,9 @@ long m68k_serial_console_init(long, long );
#ifdef CONFIG_HEARTBEAT
void (*mach_heartbeat) (int) = NULL;
#endif
+#ifdef CONFIG_M68K_L2_CACHE
+void (*mach_l2_flush) (int) = NULL;
+#endif
extern void base_trap_init(void);
@@ -118,7 +124,7 @@ extern int q40_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_sun3(unsigned long *, unsigned long *);
extern void config_apollo(void);
extern void config_mvme147(void);
extern void config_mvme16x(void);
@@ -127,10 +133,12 @@ extern void config_hp300(void);
extern void config_q40(void);
extern void config_sun3x(void);
-#define MASK_256K 0xfffc0000
+extern void mac_debugging_short (int, short);
+extern void mac_debugging_long (int, long);
+#define MASK_256K 0xfffc0000
-__initfunc(static void m68k_parse_bootinfo(const struct bi_record *record))
+static void __init m68k_parse_bootinfo(const struct bi_record *record)
{
while (record->tag != BI_LAST) {
int unknown = 0;
@@ -190,8 +198,8 @@ __initfunc(static void m68k_parse_bootinfo(const struct bi_record *record))
#endif
}
-__initfunc(void setup_arch(char **cmdline_p, unsigned long * memory_start_p,
- unsigned long * memory_end_p))
+void __init setup_arch(char **cmdline_p, unsigned long * memory_start_p,
+ unsigned long * memory_end_p)
{
extern int _etext, _edata, _end;
int i;
@@ -205,18 +213,27 @@ __initfunc(void setup_arch(char **cmdline_p, unsigned long * memory_start_p,
else if (CPU_IS_060)
m68k_is040or060 = 6;
+#ifndef CONFIG_SUN3
base_trap_init();
+#endif
+ /* FIXME: m68k_fputype is passed in by Penguin booter, which can
+ * be confused by software FPU emulation. BEWARE.
+ * We should really do our own FPU check at startup.
+ * [what do we do with buggy 68LC040s? if we have problems
+ * with them, we should add a test to check_bugs() below] */
+#ifndef CONFIG_M68KFPU_EMU_ONLY
/* clear the fpu if we have one */
if (m68k_fputype & (FPU_68881|FPU_68882|FPU_68040|FPU_68060)) {
volatile int zero = 0;
asm __volatile__ ("frestore %0" : : "m" (zero));
}
+#endif
- init_task.mm->start_code = PAGE_OFFSET;
- init_task.mm->end_code = (unsigned long) &_etext;
- init_task.mm->end_data = (unsigned long) &_edata;
- init_task.mm->brk = (unsigned long) &_end;
+ init_mm.start_code = PAGE_OFFSET;
+ init_mm.end_code = (unsigned long) &_etext;
+ init_mm.end_data = (unsigned long) &_edata;
+ init_mm.brk = (unsigned long) &_end;
*cmdline_p = m68k_command_line;
memcpy(saved_command_line, *cmdline_p, CL_SIZE);
@@ -272,7 +289,7 @@ __initfunc(void setup_arch(char **cmdline_p, unsigned long * memory_start_p,
#endif
#ifdef CONFIG_SUN3
case MACH_SUN3:
- config_sun3();
+ config_sun3(memory_start_p, memory_end_p);
break;
#endif
#ifdef CONFIG_APOLLO
@@ -321,10 +338,12 @@ __initfunc(void setup_arch(char **cmdline_p, unsigned long * memory_start_p,
}
#endif
+#ifndef CONFIG_SUN3
*memory_start_p = availmem;
*memory_end_p = 0;
for (i = 0; i < m68k_num_memory; i++)
*memory_end_p += m68k_memory[i].size & MASK_256K;
+#endif
}
int get_cpuinfo(char * buffer)
@@ -354,6 +373,9 @@ int get_cpuinfo(char * buffer)
clockfactor = 0;
}
+#ifdef CONFIG_M68KFPU_EMU_ONLY
+ fpu="none(soft float)";
+#else
if (m68k_fputype & FPU_68881)
fpu = "68881";
else if (m68k_fputype & FPU_68882)
@@ -366,6 +388,7 @@ int get_cpuinfo(char * buffer)
fpu = "Sun FPA";
else
fpu = "none";
+#endif
if (m68k_mmutype & MMU_68851)
mmu = "68851";
@@ -452,6 +475,9 @@ void unregister_serial(int i)
m68k_unregister_serial(i);
#endif
}
+EXPORT_SYMBOL(register_serial);
+EXPORT_SYMBOL(unregister_serial);
+
#ifdef CONFIG_SERIAL_CONSOLE
long serial_console_init(long kmem_start, long kmem_end)
{
@@ -461,13 +487,15 @@ long serial_console_init(long kmem_start, long kmem_end)
#endif
#if defined(M68K_SERIAL) && defined(CONFIG_SERIAL_CONSOLE)
return m68k_serial_console_init(kmem_start, kmem_end);
+#else
+ return kmem_start;
#endif
}
#endif
#endif
#if defined(CONFIG_AMIGA_FLOPPY) || defined(CONFIG_ATARI_FLOPPY) || defined(CONFIG_BLK_DEV_FD)
-__initfunc(void floppy_setup(char *str, int *ints))
+void __init floppy_setup(char *str, int *ints)
{
if (mach_floppy_setup)
mach_floppy_setup (str, ints);
@@ -481,7 +509,7 @@ void floppy_eject(void)
#endif
/* for "kbd-reset" cmdline param */
-__initfunc(void kbd_reset_setup(char *str, int *ints))
+void __init kbd_reset_setup(char *str, int *ints)
{
}
@@ -496,7 +524,7 @@ void arch_gettod(int *year, int *mon, int *day, int *hour,
void check_bugs(void)
{
-#ifndef CONFIG_FPU_EMU
+#ifndef CONFIG_M68KFPU_EMU
if (m68k_fputype == 0) {
printk( KERN_EMERG "*** YOU DO NOT HAVE A FLOATING POINT UNIT, "
"WHICH IS REQUIRED BY LINUX/M68K ***\n" );
diff --git a/arch/m68k/kernel/signal.c b/arch/m68k/kernel/signal.c
index a2b9ce1d4..f35dd94c5 100644
--- a/arch/m68k/kernel/signal.c
+++ b/arch/m68k/kernel/signal.c
@@ -14,6 +14,10 @@
* 68060 fixes by Jesper Skov
*
* 1997-12-01 Modified for POSIX.1b signals by Andreas Schwab
+ *
+ * mathemu support by Roman Zippel
+ * (Note: fpstate in the signal context is completly ignored for the emulator
+ * and the internal floating point format is put on stack)
*/
/*
@@ -156,6 +160,9 @@ sys_sigaltstack(const stack_t *uss, stack_t *uoss)
/*
* Do a signal return; undo the signal stack.
+ *
+ * Keep the return code on the stack quadword aligned!
+ * That makes the cache flush below easier.
*/
struct sigframe
@@ -175,9 +182,9 @@ struct rt_sigframe
int sig;
struct siginfo *pinfo;
void *puc;
+ char retcode[8];
struct siginfo info;
struct ucontext uc;
- char retcode[8];
};
@@ -187,6 +194,13 @@ static inline int restore_fpu_state(struct sigcontext *sc)
{
int err = 1;
+ if (FPU_IS_EMU) {
+ /* restore registers */
+ memcpy(current->thread.fpcntl, sc->sc_fpcntl, 12);
+ memcpy(current->thread.fp, sc->sc_fpregs, 24);
+ return 0;
+ }
+
if (CPU_IS_060 ? sc->sc_fpstate[2] : sc->sc_fpstate[0]) {
/* Verify the frame format. */
if (!CPU_IS_060 && (sc->sc_fpstate[0] != fpu_version))
@@ -239,6 +253,18 @@ static inline int rt_restore_fpu_state(struct ucontext *uc)
fpregset_t fpregs;
int err = 1;
+ if (FPU_IS_EMU) {
+ /* restore fpu control register */
+ if (__copy_from_user(current->thread.fpcntl,
+ &uc->uc_mcontext.fpregs.f_pcr, 12))
+ goto out;
+ /* restore all other fpu register */
+ if (__copy_from_user(current->thread.fp,
+ uc->uc_mcontext.fpregs.f_fpregs, 96))
+ goto out;
+ return 0;
+ }
+
if (__get_user(*(long *)fpstate, (long *)&uc->uc_fpstate))
goto out;
if (CPU_IS_060 ? fpstate[2] : fpstate[0]) {
@@ -478,7 +504,7 @@ asmlinkage int do_sigreturn(unsigned long __unused)
struct switch_stack *sw = (struct switch_stack *) &__unused;
struct pt_regs *regs = (struct pt_regs *) (sw + 1);
unsigned long usp = rdusp();
- struct sigframe *frame = (struct sigframe *)(usp - 24);
+ struct sigframe *frame = (struct sigframe *)(usp - 4);
sigset_t set;
int d0;
@@ -536,6 +562,13 @@ badframe:
static inline void save_fpu_state(struct sigcontext *sc, struct pt_regs *regs)
{
+ if (FPU_IS_EMU) {
+ /* save registers */
+ memcpy(sc->sc_fpcntl, current->thread.fpcntl, 12);
+ memcpy(sc->sc_fpregs, current->thread.fp, 24);
+ return;
+ }
+
__asm__ volatile (".chip 68k/68881\n\t"
"fsave %0\n\t"
".chip 68k"
@@ -567,6 +600,16 @@ static inline int rt_save_fpu_state(struct ucontext *uc, struct pt_regs *regs)
int context_size = CPU_IS_060 ? 8 : 0;
int err = 0;
+ if (FPU_IS_EMU) {
+ /* save fpu control register */
+ err |= copy_to_user(&uc->uc_mcontext.fpregs.f_pcr,
+ current->thread.fpcntl, 12);
+ /* save all other fpu register */
+ err |= copy_to_user(uc->uc_mcontext.fpregs.f_fpregs,
+ current->thread.fp, 96);
+ return err;
+ }
+
__asm__ volatile (".chip 68k/68881\n\t"
"fsave %0\n\t"
".chip 68k"
@@ -677,25 +720,6 @@ static inline void push_cache (unsigned long vaddr)
"cpushl %%bc,(%0)\n\t"
".chip 68k"
: : "a" (temp));
- if (((vaddr + 8) ^ vaddr) & ~15) {
- if (((vaddr + 8) ^ vaddr) & PAGE_MASK)
- __asm__ __volatile__ (".chip 68040\n\t"
- "nop\n\t"
- "ptestr (%1)\n\t"
- "movec %%mmusr,%0\n\t"
- ".chip 68k"
- : "=r" (temp)
- : "a" (vaddr + 8));
-
- temp &= PAGE_MASK;
- temp |= (vaddr + 8) & ~PAGE_MASK;
-
- __asm__ __volatile__ (".chip 68040\n\t"
- "nop\n\t"
- "cpushl %%bc,(%0)\n\t"
- ".chip 68k"
- : : "a" (temp));
- }
}
else if (CPU_IS_060) {
unsigned long temp;
@@ -708,18 +732,6 @@ static inline void push_cache (unsigned long vaddr)
"cpushl %%bc,(%0)\n\t"
".chip 68k"
: : "a" (temp));
- if (((vaddr + 8) ^ vaddr) & ~15) {
- if (((vaddr + 8) ^ vaddr) & PAGE_MASK)
- __asm__ __volatile__ (".chip 68060\n\t"
- "plpar (%0)\n\t"
- ".chip 68k"
- : "=a" (temp)
- : "0" (vaddr + 8));
- __asm__ __volatile__ (".chip 68060\n\t"
- "cpushl %%bc,(%0)\n\t"
- ".chip 68k"
- : : "a" (temp));
- }
}
else {
/*
@@ -797,11 +809,9 @@ static void setup_frame (int sig, struct k_sigaction *ka,
/* Set up to return from userspace. */
err |= __put_user(frame->retcode, &frame->pretcode);
- /* addaw #20,sp */
- err |= __put_user(0xdefc0014, (long *)(frame->retcode + 0));
/* moveq #,d0; trap #0 */
err |= __put_user(0x70004e40 + (__NR_sigreturn << 16),
- (long *)(frame->retcode + 4));
+ (long *)(frame->retcode));
if (err)
goto give_sigsegv;
@@ -881,10 +891,10 @@ static void setup_rt_frame (int sig, struct k_sigaction *ka, siginfo_t *info,
/* Set up to return from userspace. */
err |= __put_user(frame->retcode, &frame->pretcode);
- /* movel #,d0; trap #0 */
- err |= __put_user(0x203c, (short *)(frame->retcode + 0));
- err |= __put_user(__NR_rt_sigreturn, (long *)(frame->retcode + 2));
- err |= __put_user(0x4e40, (short *)(frame->retcode + 6));
+ /* moveq #,d0; notb d0; trap #0 */
+ err |= __put_user(0x70004600 + ((__NR_rt_sigreturn ^ 0xff) << 16),
+ (long *)(frame->retcode + 0));
+ err |= __put_user(0x4e40, (short *)(frame->retcode + 4));
if (err)
goto give_sigsegv;
@@ -964,11 +974,10 @@ handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info,
if (ka->sa.sa_flags & SA_ONESHOT)
ka->sa.sa_handler = SIG_DFL;
- if (!(ka->sa.sa_flags & SA_NODEFER)) {
- sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
+ sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
+ if (!(ka->sa.sa_flags & SA_NODEFER))
sigaddset(&current->blocked,sig);
- recalc_sigpending(current);
- }
+ recalc_sigpending(current);
}
/*
@@ -985,7 +994,7 @@ asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs)
siginfo_t info;
struct k_sigaction *ka;
- current->tss.esp0 = (unsigned long) regs;
+ current->thread.esp0 = (unsigned long) regs;
if (!oldset)
oldset = &current->blocked;
@@ -1084,14 +1093,13 @@ asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs)
case SIGQUIT: case SIGILL: case SIGTRAP:
case SIGIOT: case SIGFPE: case SIGSEGV:
- if (current->binfmt
- && current->binfmt->core_dump
- && current->binfmt->core_dump(signr, regs))
+ if (do_coredump(signr, regs))
exit_code |= 0x80;
/* FALLTHRU */
default:
sigaddset(&current->signal, signr);
+ recalc_sigpending(current);
current->flags |= PF_SIGNALED;
do_exit(exit_code);
/* NOTREACHED */
diff --git a/arch/m68k/kernel/sun3-head.S b/arch/m68k/kernel/sun3-head.S
new file mode 100644
index 000000000..fa17d83a9
--- /dev/null
+++ b/arch/m68k/kernel/sun3-head.S
@@ -0,0 +1,102 @@
+#include <linux/config.h>
+#include <linux/linkage.h>
+
+#include <asm/page.h>
+#include <asm/contregs.h>
+#include <asm/sun3-head.h>
+
+PSL_HIGHIPL = 0x2700
+NBSG = 0x20000
+ICACHE_ONLY = 0x00000009
+CACHES_OFF = 0x00000008 | actually a clear and disable --m
+#define MAS_STACK INT_STACK
+ROOT_TABLE_SIZE = 128
+PAGESIZE = 8192
+
+.globl SYMBOL_NAME(bootup_user_stack)
+.globl SYMBOL_NAME(bootup_kernel_stack)
+.globl SYMBOL_NAME(pg0)
+.globl SYMBOL_NAME(empty_bad_page)
+.globl SYMBOL_NAME(empty_bad_page_table)
+.globl SYMBOL_NAME(empty_zero_page)
+.globl SYMBOL_NAME(swapper_pg_dir)
+.globl SYMBOL_NAME(kernel_pmd_table)
+.global SYMBOL_NAME(m68k_pgtable_cachemode)
+.global SYMBOL_NAME(kpt)
+| todo: all these should be in bss!
+SYMBOL_NAME(swapper_pg_dir): .skip 0x2000
+SYMBOL_NAME(pg0): .skip 0x2000
+SYMBOL_NAME(empty_bad_page): .skip 0x2000
+SYMBOL_NAME(empty_bad_page_table): .skip 0x2000
+SYMBOL_NAME(kernel_pmd_table): .skip 0x2000
+SYMBOL_NAME(empty_zero_page): .skip 0x2000
+
+.globl SYMBOL_NAME(kernel_pg_dir)
+.equ SYMBOL_NAME(kernel_pg_dir),SYMBOL_NAME(kernel_pmd_table)
+
+ .section .head
+ENTRY(_stext)
+ENTRY(_start)
+
+/* Firstly, disable interrupts and set up function codes. */
+ movew #PSL_HIGHIPL, %sr
+ moveq #FC_CONTROL, %d0
+ movec %d0, %sfc
+ movec %d0, %dfc
+
+/* Make sure we're in context zero. */
+ moveq #0, %d0
+ movsb %d0, AC_CONTEXT
+
+/* Copy mappings for first megabyte of RAM to address 0xE000000. */
+ lea (AC_SEGMAP+0),%a0
+ lea (AC_SEGMAP+KERNBASE),%a1
+ moveq #(0x140000/NBSG-1),%d0
+1: movsb %a0@,%d1
+ movsb %d1,%a1@
+ addl #NBSG,%a0
+ addl #NBSG,%a1
+ dbf %d0,1b
+
+/* Disable caches and jump to high code. */
+ moveq #ICACHE_ONLY,%d0 | Cache disabled until we're ready to enable it
+ movc %d0, %cacr | is this the right value? (yes --m)
+ jmp 1f:l
+
+/* Following code executes at high addresses (0xE000xxx). */
+1: lea SYMBOL_NAME(init_task_union),%a2 | get initial thread...
+ lea %a2@(KTHREAD_SIZE),%sp | ...and its stack.
+
+/* copy bootinfo records from the loader to _end */
+ lea SYMBOL_NAME(_end), %a1
+ lea BI_START, %a0
+ /* number of longs to copy */
+ movel %a0@, %d0
+1: addl #4, %a0
+ movel %a0@, %a1@
+ addl #4, %a1
+ dbf %d0, 1b
+
+/* Point MSP at an invalid page to trap if it's used. --m */
+ movl #(PAGESIZE),%d0
+ movc %d0,%msp
+ moveq #-1,%d0
+ movsb %d0,(AC_SEGMAP+0x0)
+
+ jbsr SYMBOL_NAME(sun3_init)
+
+ jbsr SYMBOL_NAME(start_kernel)
+ trap #15
+
+ .data
+ .even
+SYMBOL_NAME_LABEL(kpt)
+ .long 0
+SYMBOL_NAME_LABEL(availmem)
+ .long 0
+| todo: remove next two. --m
+SYMBOL_NAME_LABEL(is_medusa)
+ .long 0
+SYMBOL_NAME_LABEL(m68k_pgtable_cachemode)
+ .long 0
+
diff --git a/arch/m68k/kernel/traps.c b/arch/m68k/kernel/traps.c
index 1f07014b2..e3a9e560b 100644
--- a/arch/m68k/kernel/traps.c
+++ b/arch/m68k/kernel/traps.c
@@ -47,6 +47,9 @@ asmlinkage void buserr(void);
asmlinkage void trap(void);
asmlinkage void inthandler(void);
asmlinkage void nmihandler(void);
+#ifdef CONFIG_M68KFPU_EMU
+asmlinkage void fpu_emu(void);
+#endif
e_vector vectors[256] = {
0, 0, buserr, trap, trap, trap, trap, trap,
@@ -65,12 +68,21 @@ asm(".text\n"
__ALIGN_STR "\n"
SYMBOL_NAME_STR(nmihandler) ": rte");
-__initfunc(void base_trap_init(void))
+void __init base_trap_init(void)
{
+#ifdef CONFIG_SUN3
+ /* Keep the keyboard interrupt working with PROM for debugging. --m */
+ e_vector *old_vbr;
+ __asm__ volatile ("movec %%vbr,%1\n\t"
+ "movec %0,%%vbr"
+ : "=&r" (old_vbr) : "r" ((void*)vectors));
+ vectors[0x1E] = old_vbr[0x1E]; /* Copy int6 vector. */
+#else
/* setup the exception vector table */
__asm__ volatile ("movec %0,%%vbr" : : "r" ((void*)vectors));
+#endif
- if (CPU_IS_040) {
+ if (CPU_IS_040 && !FPU_IS_EMU) {
/* set up FPSP entry points */
asmlinkage void dz_vec(void) asm ("dz");
asmlinkage void inex_vec(void) asm ("inex");
@@ -93,6 +105,12 @@ __initfunc(void base_trap_init(void))
vectors[VEC_FPUNSUP] = unsupp_vec;
}
if (CPU_IS_060) {
+ /* set up ISP entry points */
+ asmlinkage void unimp_vec(void) asm ("_060_isp_unimp");
+
+ vectors[VEC_UNIMPII] = unimp_vec;
+ }
+ if (CPU_IS_060 && !FPU_IS_EMU) {
/* set up IFPSP entry points */
asmlinkage void snan_vec(void) asm ("_060_fpsp_snan");
asmlinkage void operr_vec(void) asm ("_060_fpsp_operr");
@@ -104,8 +122,6 @@ __initfunc(void base_trap_init(void))
asmlinkage void unsupp_vec(void) asm ("_060_fpsp_unsupp");
asmlinkage void effadd_vec(void) asm ("_060_fpsp_effadd");
- asmlinkage void unimp_vec(void) asm ("_060_isp_unimp");
-
vectors[VEC_FPNAN] = snan_vec;
vectors[VEC_FPOE] = operr_vec;
vectors[VEC_FPOVER] = ovfl_vec;
@@ -115,14 +131,10 @@ __initfunc(void base_trap_init(void))
vectors[VEC_LINE11] = fline_vec;
vectors[VEC_FPUNSUP] = unsupp_vec;
vectors[VEC_UNIMPEA] = effadd_vec;
-
- /* set up ISP entry points */
-
- vectors[VEC_UNIMPII] = unimp_vec;
}
}
-__initfunc(void trap_init (void))
+void __init trap_init (void)
{
int i;
@@ -133,16 +145,19 @@ __initfunc(void trap_init (void))
for (i = 64; i < 256; i++)
vectors[i] = inthandler;
+#ifdef CONFIG_M68KFPU_EMU
+ if (FPU_IS_EMU)
+ vectors[VEC_LINE11] = fpu_emu;
+#endif
+
/* if running on an amiga, make the NMI interrupt do nothing */
if (MACH_IS_AMIGA) {
vectors[VEC_INT7] = nmihandler;
}
-}
-
-void set_evector(int vecnum, void (*handler)(void))
-{
- if (vecnum >= 0 && vecnum <= 256)
- vectors[vecnum] = handler;
+#ifdef CONFIG_SUN3
+ /* Moved from setup_arch() */
+ base_trap_init();
+#endif
}
@@ -152,6 +167,7 @@ static inline void console_verbose(void)
console_loglevel = 15;
}
+
static char *vec_names[] = {
"RESET SP", "RESET PC", "BUS ERROR", "ADDRESS ERROR",
"ILLEGAL INSTRUCTION", "ZERO DIVIDE", "CHK", "TRAPcc",
@@ -174,12 +190,17 @@ static char *vec_names[] = {
"MMU CONFIGURATION ERROR"
};
+#ifndef CONFIG_SUN3
static char *space_names[] = {
"Space 0", "User Data", "User Program", "Space 3",
"Space 4", "Super Data", "Super Program", "CPU"
};
-
-
+#else
+static char *space_names[] = {
+ "Space 0", "User Data", "User Program", "Control",
+ "Space 4", "Super Data", "Super Program", "CPU"
+ };
+#endif
void die_if_kernel(char *,struct pt_regs *,int);
asmlinkage int do_page_fault(struct pt_regs *regs, unsigned long address,
@@ -330,6 +351,17 @@ static inline void access_error040 (struct frame *fp)
#endif
errorcode = ((mmusr & MMU_R_040) ? 1 : 0) |
((ssw & RW_040) ? 0 : 2);
+#ifdef CONFIG_FTRACE
+ {
+ unsigned long flags;
+
+ save_flags(flags);
+ cli();
+ do_ftrace(0xfa000000 | errorcode);
+ do_ftrace(mmusr);
+ restore_flags(flags);
+ }
+#endif
do_page_fault (&fp->ptregs, addr, errorcode);
} else {
printk ("68040 access error, ssw=%x\n", ssw);
@@ -363,6 +395,132 @@ static inline void access_error040 (struct frame *fp)
}
#endif /* CONFIG_M68040 */
+#if defined(CONFIG_SUN3)
+#include <asm/sun3mmu.h>
+
+extern int mmu_emu_handle_fault (unsigned long, int, int);
+
+/* sun3 version of bus_error030 */
+
+extern inline void bus_error030 (struct frame *fp)
+{
+ unsigned char buserr_type = sun3_get_buserr ();
+ unsigned long addr, errorcode;
+ unsigned short ssw = fp->un.fmtb.ssw;
+
+#if DEBUG
+ if (ssw & (FC | FB))
+ printk ("Instruction fault at %#010lx\n",
+ ssw & FC ?
+ fp->ptregs.format == 0xa ? fp->ptregs.pc + 2 : fp->un.fmtb.baddr - 2
+ :
+ fp->ptregs.format == 0xa ? fp->ptregs.pc + 4 : fp->un.fmtb.baddr);
+ if (ssw & DF)
+ printk ("Data %s fault at %#010lx in %s (pc=%#lx)\n",
+ ssw & RW ? "read" : "write",
+ fp->un.fmtb.daddr,
+ space_names[ssw & DFC], fp->ptregs.pc);
+#endif
+
+ /*
+ * Check if this page should be demand-mapped. This needs to go before
+ * the testing for a bad kernel-space access (demand-mapping applies
+ * to kernel accesses too).
+ */
+
+ if ((ssw & DF)
+ && (buserr_type & (SUN3_BUSERR_PROTERR | SUN3_BUSERR_INVALID))) {
+ if (mmu_emu_handle_fault (fp->un.fmtb.daddr, ssw & RW, 0))
+ return;
+ }
+
+ /* Check for kernel-space pagefault (BAD). */
+ if (fp->ptregs.sr & PS_S) {
+ /* kernel fault must be a data fault to user space */
+ if (! ((ssw & DF) && ((ssw & DFC) == USER_DATA))) {
+ // try checking the kernel mappings before surrender
+ if (mmu_emu_handle_fault (fp->un.fmtb.daddr, ssw & RW, 1))
+ return;
+ /* instruction fault or kernel data fault! */
+ if (ssw & (FC | FB))
+ printk ("Instruction fault at %#010lx\n",
+ fp->ptregs.pc);
+ if (ssw & DF) {
+ printk ("Data %s fault at %#010lx in %s (pc=%#lx)\n",
+ ssw & RW ? "read" : "write",
+ fp->un.fmtb.daddr,
+ space_names[ssw & DFC], fp->ptregs.pc);
+ }
+ printk ("BAD KERNEL BUSERR\n");
+
+ die_if_kernel("Oops", &fp->ptregs,0);
+ force_sig(SIGKILL, current);
+ return;
+ }
+ } else {
+ /* user fault */
+ if (!(ssw & (FC | FB)) && !(ssw & DF))
+ /* not an instruction fault or data fault! BAD */
+ panic ("USER BUSERR w/o instruction or data fault");
+ }
+
+
+ /* First handle the data fault, if any. */
+ if (ssw & DF) {
+ addr = fp->un.fmtb.daddr;
+
+// errorcode bit 0: 0 -> no page 1 -> protection fault
+// errorcode bit 1: 0 -> read fault 1 -> write fault
+
+// (buserr_type & SUN3_BUSERR_PROTERR) -> protection fault
+// (buserr_type & SUN3_BUSERR_INVALID) -> invalid page fault
+
+ if (buserr_type & SUN3_BUSERR_PROTERR)
+ errorcode = 0x01;
+ else if (buserr_type & SUN3_BUSERR_INVALID)
+ errorcode = 0x00;
+ else {
+ printk ("*** unexpected busfault type=%#04x\n", buserr_type);
+ printk ("invalid %s access at %#lx from pc %#lx\n",
+ !(ssw & RW) ? "write" : "read", addr,
+ fp->ptregs.pc);
+ die_if_kernel ("Oops", &fp->ptregs, buserr_type);
+ force_sig (SIGSEGV, current);
+ return;
+ }
+
+//todo: wtf is RM bit? --m
+ if (!(ssw & RW) || ssw & RM)
+ errorcode |= 0x02;
+
+ /* Handle page fault. */
+ do_page_fault (&fp->ptregs, addr, errorcode);
+
+ /* Retry the data fault now. */
+ return;
+ }
+
+ /* Now handle the instruction fault. */
+
+ /* Get the fault address. */
+ if (fp->ptregs.format == 0xA)
+ addr = fp->ptregs.pc + 4;
+ else
+ addr = fp->un.fmtb.baddr;
+ if (ssw & FC)
+ addr -= 2;
+
+ if (buserr_type & SUN3_BUSERR_INVALID) {
+ if (!mmu_emu_handle_fault (fp->un.fmtb.daddr, 1, 0))
+ do_page_fault (&fp->ptregs, addr, 0);
+ } else {
+#ifdef DEBUG
+ printk ("protection fault on insn access (segv).\n");
+#endif
+ force_sig (SIGSEGV, current);
+ }
+}
+#else
#if defined(CPU_M68020_OR_M68030)
static inline void bus_error030 (struct frame *fp)
{
@@ -507,44 +665,6 @@ static inline void bus_error030 (struct frame *fp)
else
asm volatile ("ploadr %1,%0@" : /* no outputs */
: "a" (addr), "d" (ssw));
-
-#if 0
- /* If this was a data fault due to an invalid page and a
- prefetch is pending on the same page, simulate it (but
- only if the page is now valid). Otherwise we'll get an
- weird insn access. */
- if ((ssw & RB) && (mmusr & MMU_I))
- {
- unsigned long iaddr;
-
- if ((fp->ptregs.format) == 0xB)
- iaddr = fp->un.fmtb.baddr;
- else
- iaddr = fp->ptregs.pc + 4;
- if (((addr ^ iaddr) & PAGE_MASK) == 0)
- {
- /* We only need to check the ATC as the entry has
- already been set up above. */
- asm volatile ("ptestr #1,%1@,#0\n\t"
- "pmove %/psr,%0@"
- : : "a" (&temp), "a" (iaddr));
- mmusr = temp;
-#ifdef DEBUG
- printk ("prefetch iaddr=%#lx ssw=%#x mmusr=%#x\n",
- iaddr, ssw, mmusr);
-#endif
- if (!(mmusr & MMU_I))
- {
- unsigned short insn;
- asm volatile ("movesw %1@,%0"
- : "=r" (insn)
- : "a" (iaddr));
- fp->un.fmtb.isb = insn;
- fp->un.fmtb.ssw &= ~RB;
- }
- }
- }
-#endif
}
/* Now handle the instruction fault. */
@@ -598,43 +718,6 @@ static inline void bus_error030 (struct frame *fp)
die_if_kernel("Oops",&fp->ptregs,mmusr);
force_sig(SIGSEGV, current);
return;
- } else {
-#if 0 /* stale ATC entry?? Ignore it */
-
-#ifdef DEBUG
- static volatile long tlong;
-#endif
-
- printk ("weird insn access at %#lx from pc %#lx (ssw is %#x)\n",
- addr, fp->ptregs.pc, ssw);
- asm volatile ("ptestr #1,%1@,#0\n\t"
- "pmove %/psr,%0@"
- : /* no outputs */
- : "a" (&temp), "a" (addr));
- mmusr = temp;
-
- printk ("level 0 mmusr is %#x\n", mmusr);
-#ifdef DEBUG
- if (m68k_cputype & CPU_68030) {
- asm volatile ("pmove %/tt0,%0@"
- : /* no outputs */
- : "a" (&tlong));
- printk ("tt0 is %#lx, ", tlong);
- asm volatile ("pmove %/tt1,%0@"
- : /* no outputs */
- : "a" (&tlong));
- printk ("tt1 is %#lx\n", tlong);
- }
-
-#endif
-
-#if DEBUG
- printk("Unknown SIGSEGV - 3\n");
-#endif
- die_if_kernel("Oops",&fp->ptregs,mmusr);
- force_sig(SIGSEGV, current);
- return;
-#endif
}
create_atc_entry:
@@ -643,12 +726,13 @@ create_atc_entry:
: "a" (addr));
}
#endif /* CPU_M68020_OR_M68030 */
+#endif /* !CONFIG_SUN3 */
asmlinkage void buserr_c(struct frame *fp)
{
/* Only set esp0 if coming from user mode */
if (user_mode(&fp->ptregs))
- current->tss.esp0 = (unsigned long) fp;
+ current->thread.esp0 = (unsigned long) fp;
#if DEBUG
printk ("*** Bus Error *** Format is %x\n", fp->ptregs.format);
@@ -990,3 +1074,16 @@ asmlinkage void fpsp040_die(void)
{
do_exit(SIGSEGV);
}
+
+#ifdef CONFIG_M68KFPU_EMU
+asmlinkage void fpemu_signal(int signal, int code, void *addr)
+{
+ siginfo_t info;
+
+ info.si_signo = signal;
+ info.si_errno = 0;
+ info.si_code = code;
+ info.si_addr = addr;
+ force_sig_info(signal, &info, current);
+}
+#endif