diff options
Diffstat (limited to 'arch/mips/kernel')
-rw-r--r-- | arch/mips/kernel/Makefile | 1 | ||||
-rw-r--r-- | arch/mips/kernel/asm-offsets.c | 4 | ||||
-rw-r--r-- | arch/mips/kernel/cpu-bugs64.c | 2 | ||||
-rw-r--r-- | arch/mips/kernel/irixsig.c | 2 | ||||
-rw-r--r-- | arch/mips/kernel/irq_txx9.c | 192 | ||||
-rw-r--r-- | arch/mips/kernel/machine_kexec.c | 5 | ||||
-rw-r--r-- | arch/mips/kernel/mips-mt.c | 7 | ||||
-rw-r--r-- | arch/mips/kernel/smp-mt.c | 6 | ||||
-rw-r--r-- | arch/mips/kernel/smtc.c | 2 | ||||
-rw-r--r-- | arch/mips/kernel/traps.c | 31 | ||||
-rw-r--r-- | arch/mips/kernel/vmlinux.lds.S | 7 |
11 files changed, 231 insertions, 28 deletions
diff --git a/arch/mips/kernel/Makefile b/arch/mips/kernel/Makefile index 07344cb3759..2fd96d95a39 100644 --- a/arch/mips/kernel/Makefile +++ b/arch/mips/kernel/Makefile @@ -50,6 +50,7 @@ obj-$(CONFIG_IRQ_CPU) += irq_cpu.o obj-$(CONFIG_IRQ_CPU_RM7K) += irq-rm7000.o obj-$(CONFIG_IRQ_CPU_RM9K) += irq-rm9000.o obj-$(CONFIG_MIPS_BOARDS_GEN) += irq-msc01.o +obj-$(CONFIG_IRQ_TXX9) += irq_txx9.o obj-$(CONFIG_32BIT) += scall32-o32.o obj-$(CONFIG_64BIT) += scall64-64.o diff --git a/arch/mips/kernel/asm-offsets.c b/arch/mips/kernel/asm-offsets.c index 013327286c2..ca136298acd 100644 --- a/arch/mips/kernel/asm-offsets.c +++ b/arch/mips/kernel/asm-offsets.c @@ -232,6 +232,10 @@ void output_mm_defines(void) constant("#define _PMD_T_LOG2 ", PMD_T_LOG2); constant("#define _PTE_T_LOG2 ", PTE_T_LOG2); linefeed; + constant("#define _PGD_ORDER ", PGD_ORDER); + constant("#define _PMD_ORDER ", PMD_ORDER); + constant("#define _PTE_ORDER ", PTE_ORDER); + linefeed; constant("#define _PMD_SHIFT ", PMD_SHIFT); constant("#define _PGDIR_SHIFT ", PGDIR_SHIFT); linefeed; diff --git a/arch/mips/kernel/cpu-bugs64.c b/arch/mips/kernel/cpu-bugs64.c index c09337b947b..ac04f0adc40 100644 --- a/arch/mips/kernel/cpu-bugs64.c +++ b/arch/mips/kernel/cpu-bugs64.c @@ -29,7 +29,7 @@ static inline void align_mod(const int align, const int mod) ".endr\n\t" ".set pop" : - : "n" (align), "n" (mod)); + : "rn" (align), "rn" (mod)); } static inline void mult_sh_align_mod(long *v1, long *v2, long *w, diff --git a/arch/mips/kernel/irixsig.c b/arch/mips/kernel/irixsig.c index 6980deb6dce..28b2a8f0091 100644 --- a/arch/mips/kernel/irixsig.c +++ b/arch/mips/kernel/irixsig.c @@ -725,7 +725,7 @@ asmlinkage int irix_getcontext(struct pt_regs *regs) current->comm, current->pid, ctx); #endif - if (!access_ok(VERIFY_WRITE, ctx, sizeof(*ctx))); + if (!access_ok(VERIFY_WRITE, ctx, sizeof(*ctx))) return -EFAULT; error = __put_user(current->thread.irix_oldctx, &ctx->link); diff --git a/arch/mips/kernel/irq_txx9.c b/arch/mips/kernel/irq_txx9.c new file mode 100644 index 00000000000..a4d1462c27f --- /dev/null +++ b/arch/mips/kernel/irq_txx9.c @@ -0,0 +1,192 @@ +/* + * linux/arch/mips/kernel/irq_txx9.c + * + * Based on linux/arch/mips/jmr3927/rbhma3100/irq.c, + * linux/arch/mips/tx4927/common/tx4927_irq.c, + * linux/arch/mips/tx4938/common/irq.c + * + * Copyright 2001, 2003-2005 MontaVista Software Inc. + * Author: MontaVista Software, Inc. + * ahennessy@mvista.com + * source@mvista.com + * Copyright (C) 2000-2001 Toshiba Corporation + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ +#include <linux/init.h> +#include <linux/interrupt.h> +#include <linux/types.h> +#include <asm/txx9irq.h> + +struct txx9_irc_reg { + u32 cer; + u32 cr[2]; + u32 unused0; + u32 ilr[8]; + u32 unused1[4]; + u32 imr; + u32 unused2[7]; + u32 scr; + u32 unused3[7]; + u32 ssr; + u32 unused4[7]; + u32 csr; +}; + +/* IRCER : Int. Control Enable */ +#define TXx9_IRCER_ICE 0x00000001 + +/* IRCR : Int. Control */ +#define TXx9_IRCR_LOW 0x00000000 +#define TXx9_IRCR_HIGH 0x00000001 +#define TXx9_IRCR_DOWN 0x00000002 +#define TXx9_IRCR_UP 0x00000003 +#define TXx9_IRCR_EDGE(cr) ((cr) & 0x00000002) + +/* IRSCR : Int. Status Control */ +#define TXx9_IRSCR_EIClrE 0x00000100 +#define TXx9_IRSCR_EIClr_MASK 0x0000000f + +/* IRCSR : Int. Current Status */ +#define TXx9_IRCSR_IF 0x00010000 +#define TXx9_IRCSR_ILV_MASK 0x00000700 +#define TXx9_IRCSR_IVL_MASK 0x0000001f + +#define irc_dlevel 0 +#define irc_elevel 1 + +static struct txx9_irc_reg __iomem *txx9_ircptr __read_mostly; + +static struct { + unsigned char level; + unsigned char mode; +} txx9irq[TXx9_MAX_IR] __read_mostly; + +static void txx9_irq_unmask(unsigned int irq) +{ + unsigned int irq_nr = irq - TXX9_IRQ_BASE; + u32 __iomem *ilrp = &txx9_ircptr->ilr[(irq_nr % 16 ) / 2]; + int ofs = irq_nr / 16 * 16 + (irq_nr & 1) * 8; + + __raw_writel((__raw_readl(ilrp) & ~(0xff << ofs)) + | (txx9irq[irq_nr].level << ofs), + ilrp); +#ifdef CONFIG_CPU_TX39XX + /* update IRCSR */ + __raw_writel(0, &txx9_ircptr->imr); + __raw_writel(irc_elevel, &txx9_ircptr->imr); +#endif +} + +static inline void txx9_irq_mask(unsigned int irq) +{ + unsigned int irq_nr = irq - TXX9_IRQ_BASE; + u32 __iomem *ilrp = &txx9_ircptr->ilr[(irq_nr % 16) / 2]; + int ofs = irq_nr / 16 * 16 + (irq_nr & 1) * 8; + + __raw_writel((__raw_readl(ilrp) & ~(0xff << ofs)) + | (irc_dlevel << ofs), + ilrp); +#ifdef CONFIG_CPU_TX39XX + /* update IRCSR */ + __raw_writel(0, &txx9_ircptr->imr); + __raw_writel(irc_elevel, &txx9_ircptr->imr); + /* flush write buffer */ + __raw_readl(&txx9_ircptr->ssr); +#else + mmiowb(); +#endif +} + +static void txx9_irq_mask_ack(unsigned int irq) +{ + unsigned int irq_nr = irq - TXX9_IRQ_BASE; + + txx9_irq_mask(irq); + /* clear edge detection */ + if (unlikely(TXx9_IRCR_EDGE(txx9irq[irq_nr].mode))) + __raw_writel(TXx9_IRSCR_EIClrE | irq_nr, &txx9_ircptr->scr); +} + +static int txx9_irq_set_type(unsigned int irq, unsigned int flow_type) +{ + unsigned int irq_nr = irq - TXX9_IRQ_BASE; + u32 cr; + u32 __iomem *crp; + int ofs; + int mode; + + if (flow_type & IRQF_TRIGGER_PROBE) + return 0; + switch (flow_type & IRQF_TRIGGER_MASK) { + case IRQF_TRIGGER_RISING: mode = TXx9_IRCR_UP; break; + case IRQF_TRIGGER_FALLING: mode = TXx9_IRCR_DOWN; break; + case IRQF_TRIGGER_HIGH: mode = TXx9_IRCR_HIGH; break; + case IRQF_TRIGGER_LOW: mode = TXx9_IRCR_LOW; break; + default: + return -EINVAL; + } + crp = &txx9_ircptr->cr[(unsigned int)irq_nr / 8]; + cr = __raw_readl(crp); + ofs = (irq_nr & (8 - 1)) * 2; + cr &= ~(0x3 << ofs); + cr |= (mode & 0x3) << ofs; + __raw_writel(cr, crp); + txx9irq[irq_nr].mode = mode; + return 0; +} + +static struct irq_chip txx9_irq_chip = { + .name = "TXX9", + .ack = txx9_irq_mask_ack, + .mask = txx9_irq_mask, + .mask_ack = txx9_irq_mask_ack, + .unmask = txx9_irq_unmask, + .set_type = txx9_irq_set_type, +}; + +void __init txx9_irq_init(unsigned long baseaddr) +{ + int i; + + txx9_ircptr = ioremap(baseaddr, sizeof(struct txx9_irc_reg)); + for (i = 0; i < TXx9_MAX_IR; i++) { + txx9irq[i].level = 4; /* middle level */ + txx9irq[i].mode = TXx9_IRCR_LOW; + set_irq_chip_and_handler(TXX9_IRQ_BASE + i, + &txx9_irq_chip, handle_level_irq); + } + + /* mask all IRC interrupts */ + __raw_writel(0, &txx9_ircptr->imr); + for (i = 0; i < 8; i++) + __raw_writel(0, &txx9_ircptr->ilr[i]); + /* setup IRC interrupt mode (Low Active) */ + for (i = 0; i < 2; i++) + __raw_writel(0, &txx9_ircptr->cr[i]); + /* enable interrupt control */ + __raw_writel(TXx9_IRCER_ICE, &txx9_ircptr->cer); + __raw_writel(irc_elevel, &txx9_ircptr->imr); +} + +int __init txx9_irq_set_pri(int irc_irq, int new_pri) +{ + int old_pri; + + if ((unsigned int)irc_irq >= TXx9_MAX_IR) + return 0; + old_pri = txx9irq[irc_irq].level; + txx9irq[irc_irq].level = new_pri; + return old_pri; +} + +int txx9_irq(void) +{ + u32 csr = __raw_readl(&txx9_ircptr->csr); + + if (likely(!(csr & TXx9_IRCSR_IF))) + return TXX9_IRQ_BASE + (csr & (TXx9_MAX_IR - 1)); + return -1; +} diff --git a/arch/mips/kernel/machine_kexec.c b/arch/mips/kernel/machine_kexec.c index 22960d67cf0..85beb9b0b2d 100644 --- a/arch/mips/kernel/machine_kexec.c +++ b/arch/mips/kernel/machine_kexec.c @@ -78,11 +78,8 @@ machine_kexec(struct kimage *image) */ local_irq_disable(); - flush_icache_range(reboot_code_buffer, - reboot_code_buffer + KEXEC_CONTROL_CODE_SIZE); - printk("Will call new kernel at %08lx\n", image->start); printk("Bye ...\n"); - flush_cache_all(); + __flush_cache_all(); ((noretfun_t) reboot_code_buffer)(); } diff --git a/arch/mips/kernel/mips-mt.c b/arch/mips/kernel/mips-mt.c index 7169a4db37b..56750b02ab4 100644 --- a/arch/mips/kernel/mips-mt.c +++ b/arch/mips/kernel/mips-mt.c @@ -4,6 +4,7 @@ */ #include <linux/device.h> +#include <linux/kallsyms.h> #include <linux/kernel.h> #include <linux/sched.h> #include <linux/module.h> @@ -84,8 +85,9 @@ void mips_mt_regdump(unsigned long mvpctl) read_vpe_c0_vpeconf0()); printk(" VPE%d.Status : %08lx\n", i, read_vpe_c0_status()); - printk(" VPE%d.EPC : %08lx\n", + printk(" VPE%d.EPC : %08lx ", i, read_vpe_c0_epc()); + print_symbol("%s\n", read_vpe_c0_epc()); printk(" VPE%d.Cause : %08lx\n", i, read_vpe_c0_cause()); printk(" VPE%d.Config7 : %08lx\n", @@ -110,7 +112,8 @@ void mips_mt_regdump(unsigned long mvpctl) } printk(" TCStatus : %08lx\n", tcstatval); printk(" TCBind : %08lx\n", read_tc_c0_tcbind()); - printk(" TCRestart : %08lx\n", read_tc_c0_tcrestart()); + printk(" TCRestart : %08lx ", read_tc_c0_tcrestart()); + print_symbol("%s\n", read_tc_c0_tcrestart()); printk(" TCHalt : %08lx\n", haltval); printk(" TCContext : %08lx\n", read_tc_c0_tccontext()); if (!haltval) diff --git a/arch/mips/kernel/smp-mt.c b/arch/mips/kernel/smp-mt.c index 19b30d6f172..05dcce41632 100644 --- a/arch/mips/kernel/smp-mt.c +++ b/arch/mips/kernel/smp-mt.c @@ -287,7 +287,7 @@ void __init plat_prepare_cpus(unsigned int max_cpus) * (unsigned long)idle->thread_info the gp * assumes a 1:1 mapping of TC => VPE */ -void prom_boot_secondary(int cpu, struct task_struct *idle) +void __cpuinit prom_boot_secondary(int cpu, struct task_struct *idle) { struct thread_info *gp = task_thread_info(idle); dvpe(); @@ -321,7 +321,7 @@ void prom_boot_secondary(int cpu, struct task_struct *idle) evpe(EVPE_ENABLE); } -void prom_init_secondary(void) +void __cpuinit prom_init_secondary(void) { /* Enable per-cpu interrupts */ @@ -330,7 +330,7 @@ void prom_init_secondary(void) (STATUSF_IP0 | STATUSF_IP1 | STATUSF_IP6 | STATUSF_IP7)); } -void prom_smp_finish(void) +void __cpuinit prom_smp_finish(void) { write_c0_compare(read_c0_count() + (8* mips_hpt_frequency/HZ)); diff --git a/arch/mips/kernel/smtc.c b/arch/mips/kernel/smtc.c index 16aa5d37117..43826c16101 100644 --- a/arch/mips/kernel/smtc.c +++ b/arch/mips/kernel/smtc.c @@ -28,8 +28,6 @@ * This file should be built into the kernel only if CONFIG_MIPS_MT_SMTC is set. */ -#define MIPS_CPU_IPI_IRQ 1 - #define LOCK_MT_PRA() \ local_irq_save(flags); \ mtflags = dmt() diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c index c8e291c8305..6379003f9d8 100644 --- a/arch/mips/kernel/traps.c +++ b/arch/mips/kernel/traps.c @@ -606,6 +606,8 @@ asmlinkage void do_ov(struct pt_regs *regs) */ asmlinkage void do_fpe(struct pt_regs *regs, unsigned long fcr31) { + siginfo_t info; + die_if_kernel("FP exception in kernel code", regs); if (fcr31 & FPU_CSR_UNI_X) { @@ -641,9 +643,22 @@ asmlinkage void do_fpe(struct pt_regs *regs, unsigned long fcr31) force_sig(sig, current); return; - } - - force_sig(SIGFPE, current); + } else if (fcr31 & FPU_CSR_INV_X) + info.si_code = FPE_FLTINV; + else if (fcr31 & FPU_CSR_DIV_X) + info.si_code = FPE_FLTDIV; + else if (fcr31 & FPU_CSR_OVF_X) + info.si_code = FPE_FLTOVF; + else if (fcr31 & FPU_CSR_UDF_X) + info.si_code = FPE_FLTUND; + else if (fcr31 & FPU_CSR_INE_X) + info.si_code = FPE_FLTRES; + else + info.si_code = __SI_FAULT; + info.si_signo = SIGFPE; + info.si_errno = 0; + info.si_addr = (void __user *) regs->cp0_epc; + force_sig_info(SIGFPE, &info, current); } asmlinkage void do_bp(struct pt_regs *regs) @@ -1035,19 +1050,11 @@ void ejtag_exception_handler(struct pt_regs *regs) /* * NMI exception handler. */ -void nmi_exception_handler(struct pt_regs *regs) +NORET_TYPE void ATTRIB_NORET nmi_exception_handler(struct pt_regs *regs) { -#ifdef CONFIG_MIPS_MT_SMTC - unsigned long dvpret = dvpe(); - bust_spinlocks(1); - printk("NMI taken!!!!\n"); - mips_mt_regdump(dvpret); -#else bust_spinlocks(1); printk("NMI taken!!!!\n"); -#endif /* CONFIG_MIPS_MT_SMTC */ die("NMI", regs); - while(1) ; } #define VECTORSPACING 0x100 /* for EI/VI mode */ diff --git a/arch/mips/kernel/vmlinux.lds.S b/arch/mips/kernel/vmlinux.lds.S index bc9bae2a73f..60bbaecde18 100644 --- a/arch/mips/kernel/vmlinux.lds.S +++ b/arch/mips/kernel/vmlinux.lds.S @@ -142,15 +142,16 @@ SECTIONS *(.exitcall.exit) /* ABI crap starts here */ - *(.comment) *(.MIPS.options) - *(.note) *(.options) *(.pdr) *(.reginfo) - *(.mdebug*) } + /* These mark the ABI of the kernel for debuggers. */ + .mdebug.abi32 : { KEEP(*(.mdebug.abi32)) } + .mdebug.abi64 : { KEEP(*(.mdebug.abi64)) } + /* This is the MIPS specific mdebug section. */ .mdebug : { *(.mdebug) } |