diff options
Diffstat (limited to 'arch/mips/kernel')
-rw-r--r-- | arch/mips/kernel/Makefile | 1 | ||||
-rw-r--r-- | arch/mips/kernel/branch.c | 9 | ||||
-rw-r--r-- | arch/mips/kernel/entry.S | 77 | ||||
-rw-r--r-- | arch/mips/kernel/fpe.c | 2 | ||||
-rw-r--r-- | arch/mips/kernel/gdb-low.S | 2 | ||||
-rw-r--r-- | arch/mips/kernel/head.S | 70 | ||||
-rw-r--r-- | arch/mips/kernel/irixelf.c | 9 | ||||
-rw-r--r-- | arch/mips/kernel/irixsig.c | 2 | ||||
-rw-r--r-- | arch/mips/kernel/irq.c | 81 | ||||
-rw-r--r-- | arch/mips/kernel/mips_ksyms.c | 14 | ||||
-rw-r--r-- | arch/mips/kernel/pci.c | 44 | ||||
-rw-r--r-- | arch/mips/kernel/proc.c | 28 | ||||
-rw-r--r-- | arch/mips/kernel/process.c | 4 | ||||
-rw-r--r-- | arch/mips/kernel/r2300_fpu.S | 8 | ||||
-rw-r--r-- | arch/mips/kernel/r4k_fpu.S | 153 | ||||
-rw-r--r-- | arch/mips/kernel/r4k_misc.S | 2 | ||||
-rw-r--r-- | arch/mips/kernel/r6000_fpu.S | 22 | ||||
-rw-r--r-- | arch/mips/kernel/setup.c | 8 | ||||
-rw-r--r-- | arch/mips/kernel/signal.c | 4 | ||||
-rw-r--r-- | arch/mips/kernel/syscall.c | 12 | ||||
-rw-r--r-- | arch/mips/kernel/syscalls.h | 6 | ||||
-rw-r--r-- | arch/mips/kernel/sysmips.c | 2 | ||||
-rw-r--r-- | arch/mips/kernel/time.c | 9 | ||||
-rw-r--r-- | arch/mips/kernel/traps.c | 60 | ||||
-rw-r--r-- | arch/mips/kernel/unaligned.c | 21 |
25 files changed, 318 insertions, 332 deletions
diff --git a/arch/mips/kernel/Makefile b/arch/mips/kernel/Makefile index 69cd54975..2b398d00b 100644 --- a/arch/mips/kernel/Makefile +++ b/arch/mips/kernel/Makefile @@ -16,7 +16,6 @@ O_OBJS := branch.o process.o signal.o entry.o traps.o ptrace.o vm86.o \ ioport.o pci.o reset.o setup.o syscall.o sysmips.o ipc.o \ r4k_switch.o r4k_misc.o r4k_scall.o r4k_fpu.o r2300_switch.o \ r2300_misc.o r2300_scall.o r2300_fpu.o r6000_fpu.o unaligned.o - OX_OBJS := mips_ksyms.o ifdef CONFIG_MIPS_FPE_MODULE diff --git a/arch/mips/kernel/branch.c b/arch/mips/kernel/branch.c index b9d138a32..4ca20214d 100644 --- a/arch/mips/kernel/branch.c +++ b/arch/mips/kernel/branch.c @@ -16,8 +16,7 @@ #include <asm/uaccess.h> /* - * Compute the return address and do emulate branch and instruction - * simulation, if required. + * Compute the return address and do emulate branch simulation, if required. */ int __compute_return_epc(struct pt_regs *regs) { @@ -162,14 +161,12 @@ int __compute_return_epc(struct pt_regs *regs) /* * And now the FPA/cp1 branch instructions. - * - * FIXME: This will silently fail for MIPS IV cop1 branches with - * the cc field != 0. */ case cop1_op: asm ("cfc1\t%0,$31":"=r" (fcr31)); bit = (insn.i_format.rt >> 2); - bit += bit ? 24 : 23; + bit += (bit != 0); + bit += 23; switch (insn.i_format.rt) { case 0: /* bc1f */ case 2: /* bc1fl */ diff --git a/arch/mips/kernel/entry.S b/arch/mips/kernel/entry.S index c955b964e..2e286da80 100644 --- a/arch/mips/kernel/entry.S +++ b/arch/mips/kernel/entry.S @@ -7,7 +7,7 @@ * * Copyright (C) 1994, 1995 by Ralf Baechle * - * $Id: entry.S,v 1.2 1997/08/11 04:21:31 ralf Exp $ + * $Id: entry.S,v 1.4 1997/09/20 19:20:13 root Exp $ */ /* @@ -50,6 +50,7 @@ reschedule: jal schedule nop EXPORT(ret_from_sys_call) +EXPORT(ret_from_irq) lw t0,bh_mask lw t1,bh_active # unused delay slot and t0,t1 @@ -75,64 +76,15 @@ EXPORT(ret_from_sys_call) jal do_signal move a1,sp - .set noat -EXPORT(return) +EXPORT(return) .set noat RESTORE_ALL eret .set at /* - * Beware: interrupt, fast_interrupt and bad_interrupt have unusual - * calling conventions to speedup the mess. - * - * a0 - interrupt number - * s2 - destroyed - * return values: - * v0 - return routine + * Common spurious interrupt handler. */ .text - .set at - .align 5 -NESTED(interrupt, PT_SIZE, sp) - move s2,ra - mfc0 t0,CP0_STATUS # enable IRQs - ori t0,0x1f - xori t0,0x1e - mtc0 t0,CP0_STATUS - - jal do_IRQ - move a1,sp - - mfc0 t0,CP0_STATUS # disable IRQs - ori t0,1 - xori t0,1 - mtc0 t0,CP0_STATUS - .set reorder - la v0,ret_from_sys_call - jr s2 - .set noreorder - END(interrupt) - - .align 5 -NESTED(fast_interrupt, PT_SIZE, sp) - move s2,ra - jal do_fast_IRQ - nop - - .set reorder - la v0,return - jr s2 - .set noreorder - END(fast_interrupt) - - /* - * Don't return & unblock the pic - */ -LEAF(bad_interrupt) - j return - END(bad_interrupt) - - .text .align 5 LEAF(spurious_interrupt) /* @@ -141,10 +93,8 @@ LEAF(spurious_interrupt) */ lui t1,%hi(spurious_count) lw t0,%lo(spurious_count)(t1) - la v0,return addiu t0,1 - - jr ra + j ret_from_irq sw t0,%lo(spurious_count)(t1) END(spurious_interrupt) @@ -164,7 +114,7 @@ LEAF(spurious_interrupt) REG_S t0,PT_BVADDR(sp); #define __BUILD_silent(exception) -#define fmt "Got %s at %016Lx.\n" +#define fmt "Got %s at %08lx.\n" #define __BUILD_verbose(exception) \ la a1,8f; \ @@ -215,21 +165,6 @@ EXPORT(exception_count_##exception); \ BUILD_HANDLER(reserved,reserved,none,verbose) /* others */ /* - * Exception handler table with 32 entries. - * This might be extended to handle software exceptions - */ - .bss - .align PTRLOG -EXPORT(exception_handlers) - .fill 32,PTRSIZE,0 - -/* - * Interrupt handler table with 32 entries. - */ -EXPORT(IRQ_vectors) - .fill 32,PTRSIZE,0 - -/* * Table of syscalls */ .data diff --git a/arch/mips/kernel/fpe.c b/arch/mips/kernel/fpe.c index 46ff43bb4..ee47f016f 100644 --- a/arch/mips/kernel/fpe.c +++ b/arch/mips/kernel/fpe.c @@ -6,7 +6,7 @@ * * Copyright (C) 1997 Ralf Baechle * - * $Id:$ + * $Id: fpe.c,v 1.1 1997/08/11 04:17:18 ralf Exp $ */ #include <linux/kernel.h> #include <linux/module.h> diff --git a/arch/mips/kernel/gdb-low.S b/arch/mips/kernel/gdb-low.S index bd7ef94fb..a379c5c5b 100644 --- a/arch/mips/kernel/gdb-low.S +++ b/arch/mips/kernel/gdb-low.S @@ -4,6 +4,8 @@ * gdb-low.S contains the low-level trap handler for the GDB stub. * * Copyright (C) 1995 Andreas Busse + * + * $Id:$ */ #include <linux/sys.h> diff --git a/arch/mips/kernel/head.S b/arch/mips/kernel/head.S index 3251c89d9..d6e82febf 100644 --- a/arch/mips/kernel/head.S +++ b/arch/mips/kernel/head.S @@ -7,6 +7,8 @@ * Further modifications by David S. Miller * * Head.S contains the MIPS exception handler and startup code. + * + * $Id: head.S,v 1.10 1997/11/13 12:55:29 ralf Exp $ */ #include <linux/config.h> #include <linux/tasks.h> @@ -27,8 +29,10 @@ /* * Reserved space for exception handlers. * Necessary for machines which link their kernels at KSEG0. + * FIXME: We could overwrite some of the useless handlers + * with those actually being used. */ - .fill 512 + .fill 520 /* * This is space for the interrupt handlers. * After trap_init() they are located at virtual address KSEG0. @@ -93,6 +97,34 @@ eret END(except_vec0_r4600) + /* TLB refill, EXL == 0, R4xx0, non-R4600 version */ + .set noreorder + .set noat + LEAF(except_vec0_nevada) + .set mips3 + mfc0 k0, CP0_BADVADDR # Get faulting address + _GET_CURRENT(k1) # get current task ptr + srl k0, k0, 22 # get pgd only bits + lw k1, THREAD_PGDIR(k1) # get task pg_dir + sll k0, k0, 2 + addu k1, k1, k0 # add in pgd offset + lw k1, (k1) + mfc0 k0, CP0_CONTEXT # get context reg + srl k0, k0, 1 # get pte offset + and k0, k0, 0xff8 + addu k1, k1, k0 # add in offset + lw k0, 0(k1) # get even pte + lw k1, 4(k1) # get odd pte + srl k0, k0, 6 # convert to entrylo0 + mtc0 k0, CP0_ENTRYLO0 # load it + srl k1, k1, 6 # convert to entrylo1 + mtc0 k1, CP0_ENTRYLO1 # load it + tlbwr # write random tlb entry + nop + nop + eret # return from trap + END(except_vec0_nevada) + /* TLB refill, EXL == 0, R4[40]00/R5000 badvaddr hwbug version */ LEAF(except_vec0_r45k_bvahwbug) .set mips3 @@ -109,6 +141,7 @@ addu k1, k1, k0 lw k0, 0(k1) lw k1, 4(k1) + nop /* XXX */ tlbp srl k0, k0, 6 mtc0 k0, CP0_ENTRYLO0 @@ -139,6 +172,7 @@ addu k1, k1, k0 lw k0, 0(k1) lw k1, 4(k1) + nop /* XXX */ tlbp srl k0, k0, 6 mtc0 k0, CP0_ENTRYLO0 @@ -199,6 +233,7 @@ addu k1, k1, k0 lw k0, 0(k1) lw k1, 4(k1) + nop /* XXX */ tlbp srl k0, k0, 6 mtc0 zero, CP0_ENTRYLO0 @@ -309,6 +344,17 @@ END(except_vec3_generic) .set at + /* + * Special interrupt vector for embedded MIPS. This is a + * dedicated interrupt vector which reduces interrupt processing + * overhead. The jump instruction will be inserted here at + * initialization time. This handler may only be 8 bytes in size! + */ + NESTED(except_vec4, 0, sp) +1: j 1b /* Dummy, will be replaced */ + nop + END(except_vec4) + /* * Kernel entry point */ @@ -357,13 +403,10 @@ probe_done: #ifndef CONFIG_SGI /* Clear BSS first so that there are no surprises... */ la t0, _edata - la t1, (_end - 4) - sw zero, (t0) -1: - addiu t0, 4 + la t1, _end +1: addiu t0, 1 bne t0, t1, 1b - sw zero, (t0) - nop + sb zero, -1(t0) #endif /* * Determine the mmu/cache attached to this machine, @@ -400,8 +443,9 @@ probe_done: /* * Stack for kernel and init */ -9: la sp, init_task_union+(KERNEL_STACK_SIZE-4*SZREG) - sw sp, kernelsp +9: la t0, init_task_union+KERNEL_STACK_SIZE-32 + sw t0, kernelsp + subu sp, t0, 4*SZREG /* Disable coprocessors */ mfc0 t0, CP0_STATUS @@ -604,6 +648,14 @@ LEAF(wire_mappings_r3000) b probe_done sw t2, (t3) 1: + li t2, PRID_IMP_NEVADA + bne t1, t2, 1f + nop + + li t2, CPU_NEVADA + b probe_done + sw t2, (t3) +1: li t2, CPU_UNKNOWN sw t2, (t3) diff --git a/arch/mips/kernel/irixelf.c b/arch/mips/kernel/irixelf.c index 26ae60b9e..a7c7bb7df 100644 --- a/arch/mips/kernel/irixelf.c +++ b/arch/mips/kernel/irixelf.c @@ -6,7 +6,6 @@ * * Based upon work which is: * Copyright 1993, 1994: Eric Youngdale (ericy@cais.com). - * */ #include <linux/module.h> @@ -228,6 +227,7 @@ unsigned long * create_irix_tables(char * p, int argc, int envc, return sp; } + /* This is much more generalized than the library routine read function, * so we keep this separate. Technically the library read function * is only provided so that we can read a.out libraries that have @@ -679,7 +679,7 @@ static inline int do_load_irix_binary(struct linux_binprm * bprm, start_code = 0xffffffff; end_code = 0; end_data = 0; - + retval = look_for_irix_interpreter(&elf_interpreter, &interpreter_dentry, &interp_elf_ex, elf_phdata, bprm, @@ -754,7 +754,6 @@ static inline int do_load_irix_binary(struct linux_binprm * bprm, } } - set_fs(old_fs); kfree(elf_phdata); @@ -861,7 +860,7 @@ static inline int do_load_irix_library(int fd) /* Seek to the beginning of the file. */ if (file->f_op->llseek) { - if ((error = file->f_op->llseek(inode, file, 0, 0)) != 0) + if ((error = file->f_op->llseek(file, 0, 0)) != 0) return -ENOEXEC; } else file->f_pos = 0; @@ -1028,7 +1027,7 @@ static int dump_write(struct file *file, const void *addr, int nr) static int dump_seek(struct file *file, off_t off) { if (file->f_op->llseek) { - if (file->f_op->llseek(file->f_dentry->d_inode, file, off, 0) != off) + if (file->f_op->llseek(file, off, 0) != off) return 0; } else file->f_pos = off; diff --git a/arch/mips/kernel/irixsig.c b/arch/mips/kernel/irixsig.c index a40178f36..c84a391a7 100644 --- a/arch/mips/kernel/irixsig.c +++ b/arch/mips/kernel/irixsig.c @@ -1,4 +1,4 @@ -/* $Id: irixsig.c,v 1.3 1997/07/29 03:04:27 ralf Exp $ +/* $Id: irixsig.c,v 1.4 1997/08/05 09:43:10 ralf Exp $ * irixsig.c: WHEEE, IRIX signals! YOW, am I compatable or what?!?! * * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) diff --git a/arch/mips/kernel/irq.c b/arch/mips/kernel/irq.c index 81ac4846d..2f29b0ca5 100644 --- a/arch/mips/kernel/irq.c +++ b/arch/mips/kernel/irq.c @@ -4,7 +4,7 @@ * Copyright (C) 1992 Linus Torvalds * Copyright (C) 1994, 1995, 1996, 1997 Ralf Baechle * - * $Id: irq.c,v 1.4 1997/09/12 01:30:22 ralf Exp $ + * $Id: irq.c,v 1.7 1997/09/26 11:51:33 ralf Exp $ */ #include <linux/errno.h> #include <linux/init.h> @@ -86,8 +86,6 @@ void enable_irq(unsigned int irq_nr) * fast ones, then the bad ones. */ extern void interrupt(void); -extern void fast_interrupt(void); -extern void bad_interrupt(void); static struct irqaction *irq_action[32] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, @@ -130,48 +128,45 @@ atomic_t __mips_bh_counter; */ asmlinkage void do_IRQ(int irq, struct pt_regs * regs) { - struct irqaction * action = *(irq + irq_action); - int do_random, cpu = smp_processor_id(); + struct irqaction *action; + int do_random, cpu; + cpu = smp_processor_id(); irq_enter(cpu, irq); kstat.interrupts[irq]++; - /* slow interrupts run with interrupts enabled */ - sti(); - action = *(irq + irq_action); - do_random = 0; - while (action) { - do_random |= action->flags; - action->handler(irq, action->dev_id, regs); - action = action->next; - } - if (do_random & SA_SAMPLE_RANDOM) - add_interrupt_randomness(irq); - irq_exit(cpu, irq); -} + /* + * mask and ack quickly, we don't want the irq controller + * thinking we're snobs just because some other CPU has + * disabled global interrupts (we have already done the + * INT_ACK cycles, it's too late to try to pretend to the + * controller that we aren't taking the interrupt). + * + * Commented out because we've already done this in the + * machinespecific part of the handler. It's reasonable to + * do this here in a highlevel language though because that way + * we could get rid of a good part of duplicated code ... + */ + /* mask_and_ack_irq(irq); */ -/* - * do_fast_IRQ handles IRQ's that don't need the fancy interrupt return - * stuff - the handler is also running with interrupts disabled unless - * it explicitly enables them later. - */ -asmlinkage void do_fast_IRQ(int irq) -{ - struct irqaction * action; - int do_random, cpu = smp_processor_id(); - - irq_enter(cpu, irq); - kstat.interrupts[irq]++; action = *(irq + irq_action); - do_random = 0; - while (action) { - do_random |= action->flags; - action->handler(irq, action->dev_id, NULL); - action = action->next; + if (action) { + if (!(action->flags & SA_INTERRUPT)) + __sti(); + action = *(irq + irq_action); + do_random = 0; + do { + do_random |= action->flags; + action->handler(irq, action->dev_id, regs); + action = action->next; + } while (action); + if (do_random & SA_SAMPLE_RANDOM) + add_interrupt_randomness(irq); + __cli(); } - if (do_random & SA_SAMPLE_RANDOM) - add_interrupt_randomness(irq); irq_exit(cpu, irq); + + /* unmasking and bottom half handling is done magically for us. */ } /* @@ -211,10 +206,6 @@ int setup_x86_irq(int irq, struct irqaction * new) *p = new; if (!shared) { - if (new->flags & SA_INTERRUPT) - set_int_vector(irq,fast_interrupt); - else - set_int_vector(irq,interrupt); unmask_irq(irq); } restore_flags(flags); @@ -269,10 +260,8 @@ void free_irq(unsigned int irq, void *dev_id) /* Found it - now free it */ save_and_cli(flags); *p = action->next; - if (!irq[irq_action]) { + if (!irq[irq_action]) mask_irq(irq); - set_int_vector(irq, bad_interrupt); - } restore_flags(flags); kfree(action); return; @@ -321,9 +310,5 @@ int probe_irq_off (unsigned long irqs) __initfunc(void init_IRQ(void)) { - int i; - - for (i = 0; i < 32 ; i++) - set_int_vector(i, bad_interrupt); irq_setup(); } diff --git a/arch/mips/kernel/mips_ksyms.c b/arch/mips/kernel/mips_ksyms.c index 83712649c..3e8fc275d 100644 --- a/arch/mips/kernel/mips_ksyms.c +++ b/arch/mips/kernel/mips_ksyms.c @@ -7,7 +7,7 @@ * * Copyright (C) 1996, 1997 by Ralf Baechle * - * $Id: mips_ksyms.c,v 1.2 1997/07/29 03:58:54 ralf Exp $ + * $Id: mips_ksyms.c,v 1.4 1997/08/11 04:17:18 ralf Exp $ */ #include <linux/config.h> #include <linux/module.h> @@ -62,11 +62,21 @@ EXPORT_SYMBOL(csum_partial_copy); */ EXPORT_SYMBOL(flush_page_to_ram); EXPORT_SYMBOL(fd_cacheflush); +EXPORT_SYMBOL(flush_cache_all); /* * Base address of ports for Intel style I/O. */ -EXPORT_SYMBOL(port_base); +EXPORT_SYMBOL(mips_io_port_base); + +/* + * Architecture specific stuff. + */ +#ifdef CONFIG_MIPS_JAZZ +EXPORT_SYMBOL(vdma_alloc); +EXPORT_SYMBOL(vdma_free); +EXPORT_SYMBOL(vdma_log2phys); +#endif #ifdef CONFIG_SGI EXPORT_SYMBOL(hpc3c0); diff --git a/arch/mips/kernel/pci.c b/arch/mips/kernel/pci.c index 25ea56fdd..6f7374fd2 100644 --- a/arch/mips/kernel/pci.c +++ b/arch/mips/kernel/pci.c @@ -13,7 +13,9 @@ #include <linux/types.h> #include <asm/pci.h> -#ifndef CONFIG_PCI +#ifdef CONFIG_PCI + +struct pci_ops *pci_ops; /* * BIOS32 replacement. @@ -24,15 +26,13 @@ __initfunc(unsigned long pcibios_init(unsigned long memory_start, return memory_start; } -#else /* defined(CONFIG_PCI) */ - /* * Following the generic parts of the MIPS BIOS32 code. */ int pcibios_present (void) { - return _pcibios_init != NULL; + return pci_ops != NULL; } /* @@ -87,68 +87,46 @@ int pcibios_find_class (unsigned int class_code, unsigned short index, * each PCI chipset configuration. We just run the hook to the machine * specific implementation. */ -unsigned long (*_pcibios_init)(unsigned long memory_start, unsigned long memory_end); -__initfunc(unsigned long pcibios_init(unsigned long memory_start, - unsigned long memory_end)) -{ - return _pcibios_init ? _pcibios_init(memory_start, memory_end) - : memory_start; -} - -unsigned long (*_pcibios_fixup) (unsigned long memory_start, - unsigned long memory_end); unsigned long pcibios_fixup (unsigned long memory_start, unsigned long memory_end) { - return _pcibios_fixup(memory_start, memory_end); + return pci_ops->pcibios_fixup(memory_start, memory_end); } -int (*_pcibios_read_config_byte) (unsigned char bus, unsigned char dev_fn, - unsigned char where, unsigned char *val); int pcibios_read_config_byte (unsigned char bus, unsigned char dev_fn, unsigned char where, unsigned char *val) { - return _pcibios_read_config_byte(bus, dev_fn, where, val); + return pci_ops->pcibios_read_config_byte(bus, dev_fn, where, val); } -int (*_pcibios_read_config_word) (unsigned char bus, unsigned char dev_fn, - unsigned char where, unsigned short *val); int pcibios_read_config_word (unsigned char bus, unsigned char dev_fn, unsigned char where, unsigned short *val) { - return _pcibios_read_config_word(bus, dev_fn, where, val); + return pci_ops->pcibios_read_config_word(bus, dev_fn, where, val); } -int (*_pcibios_read_config_dword) (unsigned char bus, unsigned char dev_fn, - unsigned char where, unsigned int *val); int pcibios_read_config_dword (unsigned char bus, unsigned char dev_fn, unsigned char where, unsigned int *val) { - return _pcibios_read_config_dword(bus, dev_fn, where, val); + return pci_ops->pcibios_read_config_dword(bus, dev_fn, where, val); } -int (*_pcibios_write_config_byte) (unsigned char bus, unsigned char dev_fn, - unsigned char where, unsigned char val); int pcibios_write_config_byte (unsigned char bus, unsigned char dev_fn, unsigned char where, unsigned char val) { - return _pcibios_write_config_byte(bus, dev_fn, where, val); + return pci_ops->pcibios_write_config_byte(bus, dev_fn, where, val); } -int (*_pcibios_write_config_word) (unsigned char bus, unsigned char dev_fn, - unsigned char where, unsigned short val); int pcibios_write_config_word (unsigned char bus, unsigned char dev_fn, unsigned char where, unsigned short val) { - return _pcibios_write_config_word(bus, dev_fn, where, val); + return pci_ops->pcibios_write_config_word(bus, dev_fn, where, val); } -int (*_pcibios_write_config_dword) (unsigned char bus, unsigned char dev_fn, - unsigned char where, unsigned int val); int pcibios_write_config_dword (unsigned char bus, unsigned char dev_fn, unsigned char where, unsigned int val) { - return _pcibios_write_config_dword(bus, dev_fn, where, val); + return pci_ops->pcibios_write_config_dword(bus, dev_fn, where, val); } #endif /* defined(CONFIG_PCI) */ diff --git a/arch/mips/kernel/proc.c b/arch/mips/kernel/proc.c index 0e2803dd3..2c454c019 100644 --- a/arch/mips/kernel/proc.c +++ b/arch/mips/kernel/proc.c @@ -5,11 +5,12 @@ */ #include <linux/delay.h> #include <linux/kernel.h> +#include <linux/sched.h> #include <asm/bootinfo.h> #include <asm/mipsregs.h> +#include <asm/processor.h> +#include <asm/watch.h> -unsigned long dflushes = 0; -unsigned long iflushes = 0; unsigned long unaligned_instructions; /* @@ -27,8 +28,15 @@ int get_cpuinfo(char *buffer) const char *mach_dec_names[] = GROUP_DEC_NAMES; const char *mach_arc_names[] = GROUP_ARC_NAMES; const char *mach_sni_rm_names[] = GROUP_SNI_RM_NAMES; - const char **mach_group_to_name[] = { mach_unknown_names, mach_jazz_names, - mach_dec_names, mach_arc_names, mach_sni_rm_names}; + const char *mach_acn_names[] = GROUP_ACN_NAMES; + const char *mach_sgi_names[] = GROUP_SGI_NAMES; + const char **mach_group_to_name[] = { mach_unknown_names, + mach_jazz_names, + mach_dec_names, + mach_arc_names, + mach_sni_rm_names, + mach_acn_names, + mach_sgi_names }; unsigned int version = read_32bit_cp0_register(CP0_PRID); int len; @@ -51,12 +59,16 @@ int get_cpuinfo(char *buffer) #if defined (__MIPSEL__) len += sprintf(buffer + len, "byteorder\t\t: little endian\n"); #endif - len += sprintf(buffer + len, "D-cache flushes\t\t: %lu\n", - dflushes); - len += sprintf(buffer + len, "I-cache flushes\t\t: %lu\n", - iflushes); len += sprintf(buffer + len, "unaligned accesses\t: %lu\n", unaligned_instructions); + len += sprintf(buffer + len, "wait instruction\t: %s\n", + wait_available ? "yes" : "no"); + len += sprintf(buffer + len, "microsecond timers\t: %s\n", + cyclecounter_available ? "yes" : "no"); + len += sprintf(buffer + len, "extra interrupt vector\t: %s\n", + dedicated_iv_available ? "yes" : "no"); + len += sprintf(buffer + len, "hardware watchpoint\t: %s\n", + watch_available ? "yes" : "no"); return len; } diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c index 3ffb9b258..6d28d6e98 100644 --- a/arch/mips/kernel/process.c +++ b/arch/mips/kernel/process.c @@ -70,10 +70,10 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long usp, struct pt_regs * childregs; long childksp; - childksp = (unsigned long)p + KERNEL_STACK_SIZE - 8; + childksp = (unsigned long)p + KERNEL_STACK_SIZE - 32; /* set up new TSS. */ - childregs = ((struct pt_regs *) ((unsigned long)p + KERNEL_STACK_SIZE)) - 1; + childregs = (struct pt_regs *) childksp - 1; *childregs = *regs; childregs->regs[7] = 0; /* Clear error flag */ if(current->personality == PER_LINUX) { diff --git a/arch/mips/kernel/r2300_fpu.S b/arch/mips/kernel/r2300_fpu.S index fc4e04617..6c699c74d 100644 --- a/arch/mips/kernel/r2300_fpu.S +++ b/arch/mips/kernel/r2300_fpu.S @@ -10,7 +10,7 @@ * Multi-arch abstraction and asm macros for easier reading: * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) * - * $Id: r2300_fpu.S,v 1.2 1997/06/25 14:44:51 ralf Exp $ + * $Id: r2300_fpu.S,v 1.3 1997/12/01 16:54:20 ralf Exp $ */ #include <asm/asm.h> #include <asm/fpregdef.h> @@ -30,7 +30,7 @@ nop cfc1 t0,fcr31 - /* Store the 16 odd double precision registers */ + /* Store the 32 single precision registers */ swc1 $f0,(SC_FPREGS+0)(a0) swc1 $f1,(SC_FPREGS+8)(a0) swc1 $f2,(SC_FPREGS+16)(a0) @@ -76,7 +76,8 @@ .set macro END(r2300_save_fp_context) -/* Restore fpu state: +/* + * Restore fpu state: * - fp gp registers * - cp1 status/control register * @@ -91,7 +92,6 @@ bgez t0,1f nop - bgez t0,1f lw t0,SC_FPC_CSR(a0) /* Restore the 16 odd double precision registers only * when enabled in the cp0 status register. diff --git a/arch/mips/kernel/r4k_fpu.S b/arch/mips/kernel/r4k_fpu.S index c5c519f4e..72638d462 100644 --- a/arch/mips/kernel/r4k_fpu.S +++ b/arch/mips/kernel/r4k_fpu.S @@ -10,7 +10,7 @@ * Multi-arch abstraction and asm macros for easier reading: * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) * - * $Id: r4k_fpu.S,v 1.2 1997/06/25 14:44:52 ralf Exp $ + * $Id: r4k_fpu.S,v 1.3 1997/12/01 16:56:06 ralf Exp $ */ #include <asm/asm.h> #include <asm/fpregdef.h> @@ -21,7 +21,7 @@ .set noreorder .set mips3 /* Save floating point context */ - LEAF(r4k_save_fp_context) +LEAF(r4k_save_fp_context) mfc0 t1,CP0_STATUS sll t2,t1,2 bgez t2,2f @@ -31,41 +31,41 @@ bgez t2,1f nop /* Store the 16 odd double precision registers */ - swc1 $f1,(SC_FPREGS+8)(a0) - swc1 $f3,(SC_FPREGS+24)(a0) - swc1 $f5,(SC_FPREGS+40)(a0) - swc1 $f7,(SC_FPREGS+56)(a0) - swc1 $f9,(SC_FPREGS+72)(a0) - swc1 $f11,(SC_FPREGS+88)(a0) - swc1 $f13,(SC_FPREGS+104)(a0) - swc1 $f15,(SC_FPREGS+120)(a0) - swc1 $f17,(SC_FPREGS+136)(a0) - swc1 $f19,(SC_FPREGS+152)(a0) - swc1 $f21,(SC_FPREGS+168)(a0) - swc1 $f23,(SC_FPREGS+184)(a0) - swc1 $f25,(SC_FPREGS+200)(a0) - swc1 $f27,(SC_FPREGS+216)(a0) - swc1 $f29,(SC_FPREGS+232)(a0) - swc1 $f31,(SC_FPREGS+248)(a0) + sdc1 $f1,(SC_FPREGS+8)(a0) + sdc1 $f3,(SC_FPREGS+24)(a0) + sdc1 $f5,(SC_FPREGS+40)(a0) + sdc1 $f7,(SC_FPREGS+56)(a0) + sdc1 $f9,(SC_FPREGS+72)(a0) + sdc1 $f11,(SC_FPREGS+88)(a0) + sdc1 $f13,(SC_FPREGS+104)(a0) + sdc1 $f15,(SC_FPREGS+120)(a0) + sdc1 $f17,(SC_FPREGS+136)(a0) + sdc1 $f19,(SC_FPREGS+152)(a0) + sdc1 $f21,(SC_FPREGS+168)(a0) + sdc1 $f23,(SC_FPREGS+184)(a0) + sdc1 $f25,(SC_FPREGS+200)(a0) + sdc1 $f27,(SC_FPREGS+216)(a0) + sdc1 $f29,(SC_FPREGS+232)(a0) + sdc1 $f31,(SC_FPREGS+248)(a0) /* Store the 16 even double precision registers */ 1: - swc1 $f0,(SC_FPREGS+0)(a0) - swc1 $f2,(SC_FPREGS+16)(a0) - swc1 $f4,(SC_FPREGS+32)(a0) - swc1 $f6,(SC_FPREGS+48)(a0) - swc1 $f8,(SC_FPREGS+64)(a0) - swc1 $f10,(SC_FPREGS+80)(a0) - swc1 $f12,(SC_FPREGS+96)(a0) - swc1 $f14,(SC_FPREGS+112)(a0) - swc1 $f16,(SC_FPREGS+128)(a0) - swc1 $f18,(SC_FPREGS+144)(a0) - swc1 $f20,(SC_FPREGS+160)(a0) - swc1 $f22,(SC_FPREGS+176)(a0) - swc1 $f24,(SC_FPREGS+192)(a0) - swc1 $f26,(SC_FPREGS+208)(a0) - swc1 $f28,(SC_FPREGS+224)(a0) - swc1 $f30,(SC_FPREGS+240)(a0) + sdc1 $f0,(SC_FPREGS+0)(a0) + sdc1 $f2,(SC_FPREGS+16)(a0) + sdc1 $f4,(SC_FPREGS+32)(a0) + sdc1 $f6,(SC_FPREGS+48)(a0) + sdc1 $f8,(SC_FPREGS+64)(a0) + sdc1 $f10,(SC_FPREGS+80)(a0) + sdc1 $f12,(SC_FPREGS+96)(a0) + sdc1 $f14,(SC_FPREGS+112)(a0) + sdc1 $f16,(SC_FPREGS+128)(a0) + sdc1 $f18,(SC_FPREGS+144)(a0) + sdc1 $f20,(SC_FPREGS+160)(a0) + sdc1 $f22,(SC_FPREGS+176)(a0) + sdc1 $f24,(SC_FPREGS+192)(a0) + sdc1 $f26,(SC_FPREGS+208)(a0) + sdc1 $f28,(SC_FPREGS+224)(a0) + sdc1 $f30,(SC_FPREGS+240)(a0) sw t1,SC_FPC_CSR(a0) cfc1 t0,$0 # implementation/version @@ -80,7 +80,8 @@ .set macro END(r4k_save_fp_context) -/* Restore fpu state: +/* + * Restore fpu state: * - fp gp registers * - cp1 status/control register * @@ -88,7 +89,7 @@ * frame on the current content of c0_status, not on the content of the * stack frame which might have been changed by the user. */ - LEAF(r4k_restore_fp_context) +LEAF(r4k_restore_fp_context) mfc0 t1,CP0_STATUS sll t0,t1,2 bgez t0,2f @@ -99,52 +100,46 @@ /* Restore the 16 odd double precision registers only * when enabled in the cp0 status register. */ - lwc1 $f1,(SC_FPREGS+8)(a0) - lwc1 $f3,(SC_FPREGS+24)(a0) - lwc1 $f5,(SC_FPREGS+40)(a0) - lwc1 $f7,(SC_FPREGS+56)(a0) - lwc1 $f9,(SC_FPREGS+72)(a0) - lwc1 $f11,(SC_FPREGS+88)(a0) - lwc1 $f13,(SC_FPREGS+104)(a0) - lwc1 $f15,(SC_FPREGS+120)(a0) - lwc1 $f17,(SC_FPREGS+136)(a0) - lwc1 $f19,(SC_FPREGS+152)(a0) - lwc1 $f21,(SC_FPREGS+168)(a0) - lwc1 $f23,(SC_FPREGS+184)(a0) - lwc1 $f25,(SC_FPREGS+200)(a0) - lwc1 $f27,(SC_FPREGS+216)(a0) - lwc1 $f29,(SC_FPREGS+232)(a0) - lwc1 $f31,(SC_FPREGS+248)(a0) + ldc1 $f1,(SC_FPREGS+8)(a0) + ldc1 $f3,(SC_FPREGS+24)(a0) + ldc1 $f5,(SC_FPREGS+40)(a0) + ldc1 $f7,(SC_FPREGS+56)(a0) + ldc1 $f9,(SC_FPREGS+72)(a0) + ldc1 $f11,(SC_FPREGS+88)(a0) + ldc1 $f13,(SC_FPREGS+104)(a0) + ldc1 $f15,(SC_FPREGS+120)(a0) + ldc1 $f17,(SC_FPREGS+136)(a0) + ldc1 $f19,(SC_FPREGS+152)(a0) + ldc1 $f21,(SC_FPREGS+168)(a0) + ldc1 $f23,(SC_FPREGS+184)(a0) + ldc1 $f25,(SC_FPREGS+200)(a0) + ldc1 $f27,(SC_FPREGS+216)(a0) + ldc1 $f29,(SC_FPREGS+232)(a0) + ldc1 $f31,(SC_FPREGS+248)(a0) - /* Restore the 16 even double precision registers + /* + * Restore the 16 even double precision registers * when cp1 was enabled in the cp0 status register. */ -1: - lwc1 $f0,(SC_FPREGS+0)(a0) - lwc1 $f2,(SC_FPREGS+16)(a0) - lwc1 $f4,(SC_FPREGS+32)(a0) - lwc1 $f6,(SC_FPREGS+48)(a0) - lwc1 $f8,(SC_FPREGS+64)(a0) - lwc1 $f10,(SC_FPREGS+80)(a0) - lwc1 $f12,(SC_FPREGS+96)(a0) - lwc1 $f14,(SC_FPREGS+112)(a0) - lwc1 $f16,(SC_FPREGS+128)(a0) - lwc1 $f18,(SC_FPREGS+144)(a0) - lwc1 $f20,(SC_FPREGS+160)(a0) - lwc1 $f22,(SC_FPREGS+176)(a0) - lwc1 $f24,(SC_FPREGS+192)(a0) - lwc1 $f26,(SC_FPREGS+208)(a0) - lwc1 $f28,(SC_FPREGS+224)(a0) - lwc1 $f30,(SC_FPREGS+240)(a0) - ctc1 t0,fcr31 - +1: ldc1 $f0,(SC_FPREGS+0)(a0) + ldc1 $f2,(SC_FPREGS+16)(a0) + ldc1 $f4,(SC_FPREGS+32)(a0) + ldc1 $f6,(SC_FPREGS+48)(a0) + ldc1 $f8,(SC_FPREGS+64)(a0) + ldc1 $f10,(SC_FPREGS+80)(a0) + ldc1 $f12,(SC_FPREGS+96)(a0) + ldc1 $f14,(SC_FPREGS+112)(a0) + ldc1 $f16,(SC_FPREGS+128)(a0) + ldc1 $f18,(SC_FPREGS+144)(a0) + ldc1 $f20,(SC_FPREGS+160)(a0) + ldc1 $f22,(SC_FPREGS+176)(a0) + ldc1 $f24,(SC_FPREGS+192)(a0) + ldc1 $f26,(SC_FPREGS+208)(a0) + ldc1 $f28,(SC_FPREGS+224)(a0) + ldc1 $f30,(SC_FPREGS+240)(a0) jr ra - .set nomacro - nop - .set macro -2: - jr ra - .set nomacro + ctc1 t0,fcr31 + +2: jr ra nop - .set macro END(r4k_restore_fp_context) diff --git a/arch/mips/kernel/r4k_misc.S b/arch/mips/kernel/r4k_misc.S index 090b3109f..2e0223260 100644 --- a/arch/mips/kernel/r4k_misc.S +++ b/arch/mips/kernel/r4k_misc.S @@ -6,7 +6,7 @@ * Multi-cpu abstraction and reworking: * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) * - * $Id: r4k_misc.S,v 1.2 1997/06/09 06:20:52 ralf Exp $ + * $Id: r4k_misc.S,v 1.3 1997/09/07 04:51:07 ralf Exp $ */ #include <asm/asm.h> #include <asm/current.h> diff --git a/arch/mips/kernel/r6000_fpu.S b/arch/mips/kernel/r6000_fpu.S index 66d4fa848..db471fa96 100644 --- a/arch/mips/kernel/r6000_fpu.S +++ b/arch/mips/kernel/r6000_fpu.S @@ -10,7 +10,7 @@ * Multi-arch abstraction and asm macros for easier reading: * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) * - * $Id: r6000_fpu.S,v 1.2 1997/06/25 14:44:52 ralf Exp $ + * $Id: r6000_fpu.S,v 1.3 1997/12/01 16:56:56 ralf Exp $ */ #include <asm/asm.h> #include <asm/fpregdef.h> @@ -44,18 +44,10 @@ sdc1 $f26,(SC_FPREGS+208)(a0) sdc1 $f28,(SC_FPREGS+224)(a0) sdc1 $f30,(SC_FPREGS+240)(a0) - sw t0,SC_FPC_CSR(a0) - cfc1 t0,$0 # implementation/version - - jr ra - .set nomacro - sw t0,SC_FPC_EIR(a0) - .set macro -1: jr ra - .set nomacro + sw t0,SC_FPC_CSR(a0) +1: jr ra nop - .set macro END(r6000_save_fp_context) /* Restore fpu state: @@ -89,14 +81,8 @@ ldc1 $f26,(SC_FPREGS+208)(a0) ldc1 $f28,(SC_FPREGS+224)(a0) ldc1 $f30,(SC_FPREGS+240)(a0) - jr ra - .set nomacro ctc1 t0,fcr31 - .set macro -1: - jr ra - .set nomacro +1: jr ra nop - .set macro END(r6000_restore_fp_context) diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c index 3ebf269f5..a1932d117 100644 --- a/arch/mips/kernel/setup.c +++ b/arch/mips/kernel/setup.c @@ -5,7 +5,7 @@ * Copyright (C) 1995, 1996 Ralf Baechle * Copyright (C) 1996 Stoned Elipot * - * $Id:$ + * $Id: setup.c,v 1.4 1997/09/07 04:55:42 ralf Exp $ */ #include <linux/config.h> #include <linux/errno.h> @@ -122,6 +122,12 @@ static char command_line[CL_SIZE] = { 0, }; void (*irq_setup)(void); /* + * mips_io_port_base is the begin of the address space to which x86 style + * I/O ports are mapped. + */ +unsigned long mips_io_port_base; + +/* * isa_slot_offset is the address where E(ISA) busaddress 0 is is mapped * for the processor. */ diff --git a/arch/mips/kernel/signal.c b/arch/mips/kernel/signal.c index 4ff1a98b4..481a34147 100644 --- a/arch/mips/kernel/signal.c +++ b/arch/mips/kernel/signal.c @@ -4,7 +4,7 @@ * Copyright (C) 1991, 1992 Linus Torvalds * Copyright (C) 1994, 1995, 1996 Ralf Baechle * - * $Id: signal.c,v 1.5 1997/09/12 01:30:24 ralf Exp $ + * $Id: signal.c,v 1.8 1997/12/01 16:26:34 ralf Exp $ */ #include <linux/config.h> #include <linux/sched.h> @@ -174,7 +174,7 @@ static void setup_frame(struct sigaction * sa, struct pt_regs *regs, * Set up the return code ... * * .set noreorder - * addiu sp,24 + * addiu sp,0x20 * li v0,__NR_sigreturn * syscall * .set reorder diff --git a/arch/mips/kernel/syscall.c b/arch/mips/kernel/syscall.c index 0a190e3ab..ffcf176e4 100644 --- a/arch/mips/kernel/syscall.c +++ b/arch/mips/kernel/syscall.c @@ -10,6 +10,8 @@ * TODO: Implement the compatibility syscalls. * Don't waste that much memory for empty entries in the syscall * table. + * + * $Id: syscall.c,v 1.4 1997/09/18 07:57:30 root Exp $ */ #undef CONF_PRINT_SYSCALLS #undef CONF_DEBUG_IRIX @@ -84,15 +86,17 @@ asmlinkage int sys_idle(void) current->counter = -100; for (;;) { /* - * R4[236]00 have wait, R4[04]00 don't. + * R4[36]00 have wait, R4[04]00 don't. * FIXME: We should save power by reducing the clock where - * possible. Should help alot for battery powered - * R4200/4300i systems. + * possible. Thiss will cut down the power consuption + * of R4200 systems to about 1/16th of normal, the + * same for logic clocked with the processor generated + * clocks. */ if (wait_available && !need_resched) __asm__(".set\tmips3\n\t" "wait\n\t" - ".set\tmips0\n\t"); + ".set\tmips0"); run_task_queue(&tq_scheduler); schedule(); } diff --git a/arch/mips/kernel/syscalls.h b/arch/mips/kernel/syscalls.h index 3232af01c..159931b4b 100644 --- a/arch/mips/kernel/syscalls.h +++ b/arch/mips/kernel/syscalls.h @@ -5,9 +5,9 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 1995, 1996, 1997 by Ralf Baechle + * Copyright (C) 1995, 1996 by Ralf Baechle * - * $Id: syscalls.h,v 1.6 1997/08/06 19:15:08 miguel Exp $ + * $Id: syscalls.h,v 1.5 1997/09/11 01:57:38 ralf Exp $ */ /* @@ -210,5 +210,3 @@ SYS(sys_poll, 3) SYS(sys_nfsservctl, 3) SYS(sys_setresgid, 3) /* 4190 */ SYS(sys_getresgid, 3) -SYS(sys_setresgid, 3) /* 4190 */ -SYS(sys_getresgid, 3) diff --git a/arch/mips/kernel/sysmips.c b/arch/mips/kernel/sysmips.c index e73598345..62f8687c0 100644 --- a/arch/mips/kernel/sysmips.c +++ b/arch/mips/kernel/sysmips.c @@ -7,7 +7,7 @@ * * Copyright (C) 1995, 1996, 1997 by Ralf Baechle * - * $Id: sysmips.c,v 1.2 1997/07/01 08:59:08 ralf Exp $ + * $Id: sysmips.c,v 1.3 1997/07/18 06:26:02 ralf Exp $ */ #include <linux/errno.h> #include <linux/linkage.h> diff --git a/arch/mips/kernel/time.c b/arch/mips/kernel/time.c index 886b9b35e..f2cbabd86 100644 --- a/arch/mips/kernel/time.c +++ b/arch/mips/kernel/time.c @@ -6,7 +6,7 @@ * This file contains the time handling details for PC-style clocks as * found in some MIPS systems. * - * $Id: time.c,v 1.2 1997/07/01 08:59:08 ralf Exp $ + * $Id: time.c,v 1.5 1997/11/12 12:12:12 ralf Exp $ */ #include <linux/errno.h> #include <linux/init.h> @@ -39,7 +39,6 @@ extern volatile unsigned long lost_ticks; /* Cycle counter value at the previous timer interrupt.. */ static unsigned int timerhi = 0, timerlo = 0; -static char cyclecounter_available = 1; /* * On MIPS only R4000 and better have a cycle counter. @@ -397,7 +396,7 @@ static inline unsigned long mktime(unsigned int year, unsigned int mon, )*60 + sec; /* finally seconds */ } -static char cyclecounter_available; +char cyclecounter_available; static inline void init_cycle_counter(void) { @@ -437,7 +436,9 @@ static inline void init_cycle_counter(void) } } -static struct irqaction irq0 = { timer_interrupt, 0, 0, "timer", NULL, NULL}; +struct irqaction irq0 = { timer_interrupt, SA_INTERRUPT, 0, + "timer", NULL, NULL}; + void (*board_time_init)(struct irqaction *irq); diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c index 99ebc3aeb..fc0dd091c 100644 --- a/arch/mips/kernel/traps.c +++ b/arch/mips/kernel/traps.c @@ -8,7 +8,7 @@ * Copyright 1994, 1995, 1996, 1997 by Ralf Baechle * Modified for R3000 by Paul M. Antoine, 1995, 1996 * - * $Id: traps.c,v 1.3 1997/09/17 07:22:12 ralf Exp $ + * $Id: traps.c,v 1.7 1997/12/01 16:33:28 ralf Exp $ */ #include <linux/config.h> #include <linux/init.h> @@ -72,7 +72,8 @@ extern asmlinkage void handle_reserved(void); static char *cpu_names[] = CPU_NAMES; -unsigned int watch_available = 0; +char watch_available = 0; +char dedicated_iv_available = 0; void (*ibe_board_handler)(struct pt_regs *regs); void (*dbe_board_handler)(struct pt_regs *regs); @@ -175,7 +176,7 @@ void die_if_kernel(const char * str, struct pt_regs * regs, long err) return; #endif #if (_MIPS_ISA == _MIPS_ISA_MIPS3) || (_MIPS_ISA == _MIPS_ISA_MIPS4) - if (!(regs->cp0_status & 0x18)) + if (regs->cp0_status & ST0_KSU == KSU_USER) return; #endif console_verbose(); @@ -189,8 +190,6 @@ static void default_be_board_handler(struct pt_regs *regs) /* * Assume it would be too dangerous to continue ... */ - printk ("BE HANDLER\n"); - show_regs (regs); force_sig(SIGBUS, current); } @@ -427,6 +426,40 @@ static inline void watch_init(unsigned long cputype) } } +/* + * Some MIPS CPUs have a dedicated interrupt vector which reduces the + * interrupt processing overhead. Use it where available. + * FIXME: more CPUs than just the Nevada have this feature. + */ +static inline void setup_dedicated_int(void) +{ + extern void except_vec4(void); + switch(mips_cputype) { + case CPU_NEVADA: + memcpy((void *)(KSEG0 + 0x200), except_vec4, 8); + set_cp0_cause(CAUSEF_IV, CAUSEF_IV); + dedicated_iv_available = 1; + } +} + +unsigned long exception_handlers[32]; + +/* + * As a side effect of the way this is implemented we're limited + * to interrupt handlers in the address range from + * KSEG0 <= x < KSEG0 + 256mb on the Nevada. Oh well ... + */ +void set_except_vector(int n, void *addr) +{ + unsigned handler = (unsigned long) addr; + exception_handlers[n] = handler; + if (n == 0 && dedicated_iv_available) { + *(volatile u32 *)(KSEG0+0x200) = 0x08000000 | + (0x03ffffff & (handler >> 2)); + flush_icache_range(KSEG0+0x200, KSEG0 + 0x204); + } +} + typedef asmlinkage int (*syscall_t)(void *a0,...); asmlinkage int (*do_syscalls)(struct pt_regs *regs, syscall_t fun, int narg); extern asmlinkage int r4k_do_syscalls(struct pt_regs *regs, @@ -449,7 +482,8 @@ extern asmlinkage void r2300_resume(void *tsk); __initfunc(void trap_init(void)) { - extern char except_vec0_r4000, except_vec0_r4600, except_vec0_r2300; + extern char except_vec0_nevada, except_vec0_r4000; + extern char except_vec0_r4600, except_vec0_r2300; extern char except_vec1_generic, except_vec2_generic; extern char except_vec3_generic, except_vec3_r4000; unsigned long i; @@ -471,9 +505,11 @@ __initfunc(void trap_init(void)) set_except_vector(i, handle_reserved); /* - * Only some CPUs have the watch exception. + * Only some CPUs have the watch exceptions or a dedicated + * interrupt vector. */ watch_init(mips_cputype); + setup_dedicated_int(); /* * Handling the following exceptions depends mostly of the cpu type @@ -509,10 +545,12 @@ __initfunc(void trap_init(void)) case CPU_R4600: case CPU_R5000: case CPU_NEVADA: - if(mips_cputype != CPU_R4600) - memcpy((void *)KSEG0, &except_vec0_r4000, 0x80); - else + if(mips_cputype == CPU_NEVADA) { + memcpy((void *)KSEG0, &except_vec0_nevada, 0x80); + } else if (mips_cputype == CPU_R4600) memcpy((void *)KSEG0, &except_vec0_r4600, 0x80); + else + memcpy((void *)KSEG0, &except_vec0_r4000, 0x80); /* * The idea is that this special r4000 general exception @@ -611,5 +649,5 @@ __initfunc(void trap_init(void)) default: panic("Unknown CPU type"); } - flush_cache_all(); + flush_icache_range(KSEG0, KSEG0 + 0x200); } diff --git a/arch/mips/kernel/unaligned.c b/arch/mips/kernel/unaligned.c index 696244b6c..ea81ba7db 100644 --- a/arch/mips/kernel/unaligned.c +++ b/arch/mips/kernel/unaligned.c @@ -407,11 +407,11 @@ do_ade(struct pt_regs *regs) { register_t pc = regs->cp0_epc; register_t badvaddr __attribute__ ((unused)) = regs->cp0_badvaddr; - char *adels; + char adels; lock_kernel(); adels = (((regs->cp0_cause & CAUSEF_EXCCODE) >> - CAUSEB_EXCCODE) == 4) ? "adel" : "ades"; + CAUSEB_EXCCODE) == 4) ? 'l' : 's'; #ifdef CONF_NO_UNALIGNED_KERNEL_ACCESS /* @@ -420,13 +420,8 @@ do_ade(struct pt_regs *regs) */ if (kernel_address(badvaddr) && !user_mode(regs)) { show_regs(regs); -#ifdef __mips64 - panic("Caught %s exception in kernel mode accessing %016Lx.", - adels, badvaddr); -#else - panic("Caught %s exception in kernel mode accessing %08lx.", - adels, badvaddr); -#endif + panic("Caught adel%c exception in kernel mode accessing %08lx.", + adels, badvaddr); } #endif /* CONF_NO_UNALIGNED_KERNEL_ACCESS */ @@ -435,15 +430,9 @@ do_ade(struct pt_regs *regs) register_t logpc = pc; if (regs->cp0_cause & CAUSEF_BD) logpc += 4; -#ifdef __mips64 - printk(KERN_DEBUG - "Caught %s in '%s' at 0x%016Lx accessing 0x%016Lx.\n", - adels, current->comm, logpc, regs->cp0_badvaddr); -#else printk(KERN_DEBUG - "Caught %s in '%s' at 0x%08lx accessing 0x%08lx.\n", + "Caught adel%c in '%s' at 0x%08lx accessing 0x%08lx.\n", adels, current->comm, logpc, regs->cp0_badvaddr); -#endif } #endif /* CONF_LOG_UNALIGNED_ACCESSES */ |