aboutsummaryrefslogtreecommitdiff
path: root/arch/mips/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'arch/mips/kernel')
-rw-r--r--arch/mips/kernel/Makefile3
-rw-r--r--arch/mips/kernel/apm.c2
-rw-r--r--arch/mips/kernel/binfmt_elfn32.c1
-rw-r--r--arch/mips/kernel/binfmt_elfo32.c1
-rw-r--r--arch/mips/kernel/cpu-probe.c19
-rw-r--r--arch/mips/kernel/dma-no-isa.c28
-rw-r--r--arch/mips/kernel/genex.S63
-rw-r--r--arch/mips/kernel/head.S5
-rw-r--r--arch/mips/kernel/i8259.c179
-rw-r--r--arch/mips/kernel/irixelf.c10
-rw-r--r--arch/mips/kernel/irq-msc01.c47
-rw-r--r--arch/mips/kernel/irq-mv6434x.c64
-rw-r--r--arch/mips/kernel/irq-rm7000.c61
-rw-r--r--arch/mips/kernel/irq-rm9000.c55
-rw-r--r--arch/mips/kernel/irq.c34
-rw-r--r--arch/mips/kernel/irq_cpu.c90
-rw-r--r--arch/mips/kernel/kspd.c6
-rw-r--r--arch/mips/kernel/linux32.c586
-rw-r--r--arch/mips/kernel/machine_kexec.c85
-rw-r--r--arch/mips/kernel/mips_ksyms.c2
-rw-r--r--arch/mips/kernel/module.c15
-rw-r--r--arch/mips/kernel/relocate_kernel.S80
-rw-r--r--arch/mips/kernel/reset.c2
-rw-r--r--arch/mips/kernel/rtlx.c6
-rw-r--r--arch/mips/kernel/scall32-o32.S2
-rw-r--r--arch/mips/kernel/scall64-64.S2
-rw-r--r--arch/mips/kernel/scall64-n32.S16
-rw-r--r--arch/mips/kernel/scall64-o32.S2
-rw-r--r--arch/mips/kernel/setup.c87
-rw-r--r--arch/mips/kernel/signal_n32.c1
-rw-r--r--arch/mips/kernel/smp-mt.c2
-rw-r--r--arch/mips/kernel/smp.c8
-rw-r--r--arch/mips/kernel/smtc.c1
-rw-r--r--arch/mips/kernel/sysirix.c10
-rw-r--r--arch/mips/kernel/time.c66
-rw-r--r--arch/mips/kernel/traps.c72
-rw-r--r--arch/mips/kernel/vmlinux.lds.S2
-rw-r--r--arch/mips/kernel/vpe.c2
38 files changed, 589 insertions, 1128 deletions
diff --git a/arch/mips/kernel/Makefile b/arch/mips/kernel/Makefile
index 6bfbbed0897..bbbb8d7cb89 100644
--- a/arch/mips/kernel/Makefile
+++ b/arch/mips/kernel/Makefile
@@ -45,7 +45,6 @@ obj-$(CONFIG_MIPS_APSP_KSPD) += kspd.o
obj-$(CONFIG_MIPS_VPE_LOADER) += vpe.o
obj-$(CONFIG_MIPS_VPE_APSP_API) += rtlx.o
-obj-$(CONFIG_NO_ISA) += dma-no-isa.o
obj-$(CONFIG_I8259) += i8259.o
obj-$(CONFIG_IRQ_CPU) += irq_cpu.o
obj-$(CONFIG_IRQ_CPU_RM7K) += irq-rm7000.o
@@ -67,6 +66,8 @@ obj-$(CONFIG_64BIT) += cpu-bugs64.o
obj-$(CONFIG_I8253) += i8253.o
+obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o
+
CFLAGS_cpu-bugs64.o = $(shell if $(CC) $(CFLAGS) -Wa,-mdaddi -c -o /dev/null -xc /dev/null >/dev/null 2>&1; then echo "-DHAVE_AS_SET_DADDI"; fi)
EXTRA_AFLAGS := $(CFLAGS)
diff --git a/arch/mips/kernel/apm.c b/arch/mips/kernel/apm.c
index 528e731049c..ba16d07588c 100644
--- a/arch/mips/kernel/apm.c
+++ b/arch/mips/kernel/apm.c
@@ -356,7 +356,7 @@ static int apm_open(struct inode * inode, struct file * filp)
{
struct apm_user *as;
- as = (struct apm_user *)kzalloc(sizeof(*as), GFP_KERNEL);
+ as = kzalloc(sizeof(*as), GFP_KERNEL);
if (as) {
/*
* XXX - this is a tiny bit broken, when we consider BSD
diff --git a/arch/mips/kernel/binfmt_elfn32.c b/arch/mips/kernel/binfmt_elfn32.c
index 4a9f1ecefaf..9b34238d41c 100644
--- a/arch/mips/kernel/binfmt_elfn32.c
+++ b/arch/mips/kernel/binfmt_elfn32.c
@@ -90,7 +90,6 @@ struct elf_prpsinfo32
char pr_psargs[ELF_PRARGSZ]; /* initial part of arg list */
};
-#define elf_addr_t u32
#define elf_caddr_t u32
#define init_elf_binfmt init_elfn32_binfmt
diff --git a/arch/mips/kernel/binfmt_elfo32.c b/arch/mips/kernel/binfmt_elfo32.c
index e3181377989..993f7ec70f3 100644
--- a/arch/mips/kernel/binfmt_elfo32.c
+++ b/arch/mips/kernel/binfmt_elfo32.c
@@ -92,7 +92,6 @@ struct elf_prpsinfo32
char pr_psargs[ELF_PRARGSZ]; /* initial part of arg list */
};
-#define elf_addr_t u32
#define elf_caddr_t u32
#define init_elf_binfmt init_elf32_binfmt
diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c
index 8485af340ee..442839e9578 100644
--- a/arch/mips/kernel/cpu-probe.c
+++ b/arch/mips/kernel/cpu-probe.c
@@ -110,9 +110,8 @@ static inline void check_wait(void)
{
struct cpuinfo_mips *c = &current_cpu_data;
- printk("Checking for 'wait' instruction... ");
if (nowait) {
- printk (" disabled.\n");
+ printk("Wait instruction disabled.\n");
return;
}
@@ -120,11 +119,9 @@ static inline void check_wait(void)
case CPU_R3081:
case CPU_R3081E:
cpu_wait = r3081_wait;
- printk(" available.\n");
break;
case CPU_TX3927:
cpu_wait = r39xx_wait;
- printk(" available.\n");
break;
case CPU_R4200:
/* case CPU_R4300: */
@@ -146,33 +143,23 @@ static inline void check_wait(void)
case CPU_74K:
case CPU_PR4450:
cpu_wait = r4k_wait;
- printk(" available.\n");
break;
case CPU_TX49XX:
cpu_wait = r4k_wait_irqoff;
- printk(" available.\n");
break;
case CPU_AU1000:
case CPU_AU1100:
case CPU_AU1500:
case CPU_AU1550:
case CPU_AU1200:
- if (allow_au1k_wait) {
+ if (allow_au1k_wait)
cpu_wait = au1k_wait;
- printk(" available.\n");
- } else
- printk(" unavailable.\n");
break;
case CPU_RM9000:
- if ((c->processor_id & 0x00ff) >= 0x40) {
+ if ((c->processor_id & 0x00ff) >= 0x40)
cpu_wait = r4k_wait;
- printk(" available.\n");
- } else {
- printk(" unavailable.\n");
- }
break;
default:
- printk(" unavailable.\n");
break;
}
}
diff --git a/arch/mips/kernel/dma-no-isa.c b/arch/mips/kernel/dma-no-isa.c
deleted file mode 100644
index 6df8b07741e..00000000000
--- a/arch/mips/kernel/dma-no-isa.c
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * 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.
- *
- * Copyright (C) 2004 by Ralf Baechle
- *
- * Dummy ISA DMA functions for systems that don't have ISA but share drivers
- * with ISA such as legacy free PCI.
- */
-#include <linux/errno.h>
-#include <linux/module.h>
-#include <linux/spinlock.h>
-
-DEFINE_SPINLOCK(dma_spin_lock);
-
-int request_dma(unsigned int dmanr, const char * device_id)
-{
- return -EINVAL;
-}
-
-void free_dma(unsigned int dmanr)
-{
-}
-
-EXPORT_SYMBOL(dma_spin_lock);
-EXPORT_SYMBOL(request_dma);
-EXPORT_SYMBOL(free_dma);
diff --git a/arch/mips/kernel/genex.S b/arch/mips/kernel/genex.S
index 5baca16993d..aacd4a005c5 100644
--- a/arch/mips/kernel/genex.S
+++ b/arch/mips/kernel/genex.S
@@ -19,6 +19,7 @@
#include <asm/mipsregs.h>
#include <asm/stackframe.h>
#include <asm/war.h>
+#include <asm/page.h>
#define PANIC_PIC(msg) \
.set push; \
@@ -378,6 +379,68 @@ NESTED(nmi_handler, PT_SIZE, sp)
BUILD_HANDLER dsp dsp sti silent /* #26 */
BUILD_HANDLER reserved reserved sti verbose /* others */
+ .align 5
+ LEAF(handle_ri_rdhwr_vivt)
+#ifdef CONFIG_MIPS_MT_SMTC
+ PANIC_PIC("handle_ri_rdhwr_vivt called")
+#else
+ .set push
+ .set noat
+ .set noreorder
+ /* check if TLB contains a entry for EPC */
+ MFC0 k1, CP0_ENTRYHI
+ andi k1, 0xff /* ASID_MASK */
+ MFC0 k0, CP0_EPC
+ PTR_SRL k0, PAGE_SHIFT + 1
+ PTR_SLL k0, PAGE_SHIFT + 1
+ or k1, k0
+ MTC0 k1, CP0_ENTRYHI
+ mtc0_tlbw_hazard
+ tlbp
+ tlb_probe_hazard
+ mfc0 k1, CP0_INDEX
+ .set pop
+ bltz k1, handle_ri /* slow path */
+ /* fall thru */
+#endif
+ END(handle_ri_rdhwr_vivt)
+
+ LEAF(handle_ri_rdhwr)
+ .set push
+ .set noat
+ .set noreorder
+ /* 0x7c03e83b: rdhwr v1,$29 */
+ MFC0 k1, CP0_EPC
+ lui k0, 0x7c03
+ lw k1, (k1)
+ ori k0, 0xe83b
+ .set reorder
+ bne k0, k1, handle_ri /* if not ours */
+ /* The insn is rdhwr. No need to check CAUSE.BD here. */
+ get_saved_sp /* k1 := current_thread_info */
+ .set noreorder
+ MFC0 k0, CP0_EPC
+#if defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_TX39XX)
+ ori k1, _THREAD_MASK
+ xori k1, _THREAD_MASK
+ LONG_L v1, TI_TP_VALUE(k1)
+ LONG_ADDIU k0, 4
+ jr k0
+ rfe
+#else
+ LONG_ADDIU k0, 4 /* stall on $k0 */
+ MTC0 k0, CP0_EPC
+ /* I hope three instructions between MTC0 and ERET are enough... */
+ ori k1, _THREAD_MASK
+ xori k1, _THREAD_MASK
+ LONG_L v1, TI_TP_VALUE(k1)
+ .set mips3
+ eret
+ .set mips0
+#endif
+ .set pop
+ END(handle_ri_rdhwr)
+
#ifdef CONFIG_64BIT
/* A temporary overflow handler used by check_daddi(). */
diff --git a/arch/mips/kernel/head.S b/arch/mips/kernel/head.S
index ddc1b71c937..9a7811d13db 100644
--- a/arch/mips/kernel/head.S
+++ b/arch/mips/kernel/head.S
@@ -138,7 +138,7 @@
EXPORT(stext) # used for profiling
EXPORT(_stext)
-#if defined(CONFIG_QEMU) || defined(CONFIG_MIPS_SIM)
+#ifdef CONFIG_MIPS_SIM
/*
* Give us a fighting chance of running if execution beings at the
* kernel load address. This is needed because this platform does
@@ -250,6 +250,9 @@ NESTED(smp_bootstrap, 16, sp)
*/
page swapper_pg_dir, _PGD_ORDER
#ifdef CONFIG_64BIT
+#if defined(CONFIG_MODULES) && !defined(CONFIG_BUILD_ELF64)
+ page module_pg_dir, _PGD_ORDER
+#endif
page invalid_pmd_table, _PMD_ORDER
#endif
page invalid_pte_table, _PTE_ORDER
diff --git a/arch/mips/kernel/i8259.c b/arch/mips/kernel/i8259.c
index 48e3418c217..b59a676c6d0 100644
--- a/arch/mips/kernel/i8259.c
+++ b/arch/mips/kernel/i8259.c
@@ -19,9 +19,6 @@
#include <asm/i8259.h>
#include <asm/io.h>
-void enable_8259A_irq(unsigned int irq);
-void disable_8259A_irq(unsigned int irq);
-
/*
* This is the 'legacy' 8259A Programmable Interrupt Controller,
* present in the majority of PC/AT boxes.
@@ -31,34 +28,16 @@ void disable_8259A_irq(unsigned int irq);
* moves to arch independent land
*/
+static int i8259A_auto_eoi;
DEFINE_SPINLOCK(i8259A_lock);
-
-static void end_8259A_irq (unsigned int irq)
-{
- if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)) &&
- irq_desc[irq].action)
- enable_8259A_irq(irq);
-}
-
-#define shutdown_8259A_irq disable_8259A_irq
-
+/* some platforms call this... */
void mask_and_ack_8259A(unsigned int);
-static unsigned int startup_8259A_irq(unsigned int irq)
-{
- enable_8259A_irq(irq);
-
- return 0; /* never anything pending */
-}
-
-static struct irq_chip i8259A_irq_type = {
- .typename = "XT-PIC",
- .startup = startup_8259A_irq,
- .shutdown = shutdown_8259A_irq,
- .enable = enable_8259A_irq,
- .disable = disable_8259A_irq,
- .ack = mask_and_ack_8259A,
- .end = end_8259A_irq,
+static struct irq_chip i8259A_chip = {
+ .name = "XT-PIC",
+ .mask = disable_8259A_irq,
+ .unmask = enable_8259A_irq,
+ .mask_ack = mask_and_ack_8259A,
};
/*
@@ -70,8 +49,8 @@ static struct irq_chip i8259A_irq_type = {
*/
static unsigned int cached_irq_mask = 0xffff;
-#define cached_21 (cached_irq_mask)
-#define cached_A1 (cached_irq_mask >> 8)
+#define cached_master_mask (cached_irq_mask)
+#define cached_slave_mask (cached_irq_mask >> 8)
void disable_8259A_irq(unsigned int irq)
{
@@ -81,9 +60,9 @@ void disable_8259A_irq(unsigned int irq)
spin_lock_irqsave(&i8259A_lock, flags);
cached_irq_mask |= mask;
if (irq & 8)
- outb(cached_A1,0xA1);
+ outb(cached_slave_mask, PIC_SLAVE_IMR);
else
- outb(cached_21,0x21);
+ outb(cached_master_mask, PIC_MASTER_IMR);
spin_unlock_irqrestore(&i8259A_lock, flags);
}
@@ -95,9 +74,9 @@ void enable_8259A_irq(unsigned int irq)
spin_lock_irqsave(&i8259A_lock, flags);
cached_irq_mask &= mask;
if (irq & 8)
- outb(cached_A1,0xA1);
+ outb(cached_slave_mask, PIC_SLAVE_IMR);
else
- outb(cached_21,0x21);
+ outb(cached_master_mask, PIC_MASTER_IMR);
spin_unlock_irqrestore(&i8259A_lock, flags);
}
@@ -109,9 +88,9 @@ int i8259A_irq_pending(unsigned int irq)
spin_lock_irqsave(&i8259A_lock, flags);
if (irq < 8)
- ret = inb(0x20) & mask;
+ ret = inb(PIC_MASTER_CMD) & mask;
else
- ret = inb(0xA0) & (mask >> 8);
+ ret = inb(PIC_SLAVE_CMD) & (mask >> 8);
spin_unlock_irqrestore(&i8259A_lock, flags);
return ret;
@@ -120,7 +99,7 @@ int i8259A_irq_pending(unsigned int irq)
void make_8259A_irq(unsigned int irq)
{
disable_irq_nosync(irq);
- irq_desc[irq].chip = &i8259A_irq_type;
+ set_irq_chip_and_handler(irq, &i8259A_chip, handle_level_irq);
enable_irq(irq);
}
@@ -136,14 +115,14 @@ static inline int i8259A_irq_real(unsigned int irq)
int irqmask = 1 << irq;
if (irq < 8) {
- outb(0x0B,0x20); /* ISR register */
- value = inb(0x20) & irqmask;
- outb(0x0A,0x20); /* back to the IRR register */
+ outb(0x0B,PIC_MASTER_CMD); /* ISR register */
+ value = inb(PIC_MASTER_CMD) & irqmask;
+ outb(0x0A,PIC_MASTER_CMD); /* back to the IRR register */
return value;
}
- outb(0x0B,0xA0); /* ISR register */
- value = inb(0xA0) & (irqmask >> 8);
- outb(0x0A,0xA0); /* back to the IRR register */
+ outb(0x0B,PIC_SLAVE_CMD); /* ISR register */
+ value = inb(PIC_SLAVE_CMD) & (irqmask >> 8);
+ outb(0x0A,PIC_SLAVE_CMD); /* back to the IRR register */
return value;
}
@@ -160,17 +139,19 @@ void mask_and_ack_8259A(unsigned int irq)
spin_lock_irqsave(&i8259A_lock, flags);
/*
- * Lightweight spurious IRQ detection. We do not want to overdo
- * spurious IRQ handling - it's usually a sign of hardware problems, so
- * we only do the checks we can do without slowing down good hardware
- * nnecesserily.
+ * Lightweight spurious IRQ detection. We do not want
+ * to overdo spurious IRQ handling - it's usually a sign
+ * of hardware problems, so we only do the checks we can
+ * do without slowing down good hardware unnecessarily.
*
- * Note that IRQ7 and IRQ15 (the two spurious IRQs usually resulting
- * rom the 8259A-1|2 PICs) occur even if the IRQ is masked in the 8259A.
- * Thus we can check spurious 8259A IRQs without doing the quite slow
- * i8259A_irq_real() call for every IRQ. This does not cover 100% of
- * spurious interrupts, but should be enough to warn the user that
- * there is something bad going on ...
+ * Note that IRQ7 and IRQ15 (the two spurious IRQs
+ * usually resulting from the 8259A-1|2 PICs) occur
+ * even if the IRQ is masked in the 8259A. Thus we
+ * can check spurious 8259A IRQs without doing the
+ * quite slow i8259A_irq_real() call for every IRQ.
+ * This does not cover 100% of spurious interrupts,
+ * but should be enough to warn the user that there
+ * is something bad going on ...
*/
if (cached_irq_mask & irqmask)
goto spurious_8259A_irq;
@@ -178,14 +159,14 @@ void mask_and_ack_8259A(unsigned int irq)
handle_real_irq:
if (irq & 8) {
- inb(0xA1); /* DUMMY - (do we need this?) */
- outb(cached_A1,0xA1);
- outb(0x60+(irq&7),0xA0);/* 'Specific EOI' to slave */
- outb(0x62,0x20); /* 'Specific EOI' to master-IRQ2 */
+ inb(PIC_SLAVE_IMR); /* DUMMY - (do we need this?) */
+ outb(cached_slave_mask, PIC_SLAVE_IMR);
+ outb(0x60+(irq&7),PIC_SLAVE_CMD);/* 'Specific EOI' to slave */
+ outb(0x60+PIC_CASCADE_IR,PIC_MASTER_CMD); /* 'Specific EOI' to master-IRQ2 */
} else {
- inb(0x21); /* DUMMY - (do we need this?) */
- outb(cached_21,0x21);
- outb(0x60+irq,0x20); /* 'Specific EOI' to master */
+ inb(PIC_MASTER_IMR); /* DUMMY - (do we need this?) */
+ outb(cached_master_mask, PIC_MASTER_IMR);
+ outb(0x60+irq,PIC_MASTER_CMD); /* 'Specific EOI to master */
}
#ifdef CONFIG_MIPS_MT_SMTC
if (irq_hwmask[irq] & ST0_IM)
@@ -206,7 +187,7 @@ spurious_8259A_irq:
goto handle_real_irq;
{
- static int spurious_irq_mask = 0;
+ static int spurious_irq_mask;
/*
* At this point we can be sure the IRQ is spurious,
* lets ACK and report it. [once per IRQ]
@@ -227,13 +208,25 @@ spurious_8259A_irq:
static int i8259A_resume(struct sys_device *dev)
{
- init_8259A(0);
+ init_8259A(i8259A_auto_eoi);
+ return 0;
+}
+
+static int i8259A_shutdown(struct sys_device *dev)
+{
+ /* Put the i8259A into a quiescent state that
+ * the kernel initialization code can get it
+ * out of.
+ */
+ outb(0xff, PIC_MASTER_IMR); /* mask all of 8259A-1 */
+ outb(0xff, PIC_SLAVE_IMR); /* mask all of 8259A-1 */
return 0;
}
static struct sysdev_class i8259_sysdev_class = {
set_kset_name("i8259"),
.resume = i8259A_resume,
+ .shutdown = i8259A_shutdown,
};
static struct sys_device device_i8259A = {
@@ -255,41 +248,41 @@ void __init init_8259A(int auto_eoi)
{
unsigned long flags;
+ i8259A_auto_eoi = auto_eoi;
+
spin_lock_irqsave(&i8259A_lock, flags);
- outb(0xff, 0x21); /* mask all of 8259A-1 */
- outb(0xff, 0xA1); /* mask all of 8259A-2 */
+ outb(0xff, PIC_MASTER_IMR); /* mask all of 8259A-1 */
+ outb(0xff, PIC_SLAVE_IMR); /* mask all of 8259A-2 */
/*
* outb_p - this has to work on a wide range of PC hardware.
*/
- outb_p(0x11, 0x20); /* ICW1: select 8259A-1 init */
- outb_p(0x00, 0x21); /* ICW2: 8259A-1 IR0-7 mapped to 0x00-0x07 */
- outb_p(0x04, 0x21); /* 8259A-1 (the master) has a slave on IR2 */
- if (auto_eoi)
- outb_p(0x03, 0x21); /* master does Auto EOI */
- else
- outb_p(0x01, 0x21); /* master expects normal EOI */
-
- outb_p(0x11, 0xA0); /* ICW1: select 8259A-2 init */
- outb_p(0x08, 0xA1); /* ICW2: 8259A-2 IR0-7 mapped to 0x08-0x0f */
- outb_p(0x02, 0xA1); /* 8259A-2 is a slave on master's IR2 */
- outb_p(0x01, 0xA1); /* (slave's support for AEOI in flat mode
- is to be investigated) */
-
+ outb_p(0x11, PIC_MASTER_CMD); /* ICW1: select 8259A-1 init */
+ outb_p(I8259A_IRQ_BASE + 0, PIC_MASTER_IMR); /* ICW2: 8259A-1 IR0 mapped to I8259A_IRQ_BASE + 0x00 */
+ outb_p(1U << PIC_CASCADE_IR, PIC_MASTER_IMR); /* 8259A-1 (the master) has a slave on IR2 */
+ if (auto_eoi) /* master does Auto EOI */
+ outb_p(MASTER_ICW4_DEFAULT | PIC_ICW4_AEOI, PIC_MASTER_IMR);
+ else /* master expects normal EOI */
+ outb_p(MASTER_ICW4_DEFAULT, PIC_MASTER_IMR);
+
+ outb_p(0x11, PIC_SLAVE_CMD); /* ICW1: select 8259A-2 init */
+ outb_p(I8259A_IRQ_BASE + 8, PIC_SLAVE_IMR); /* ICW2: 8259A-2 IR0 mapped to I8259A_IRQ_BASE + 0x08 */
+ outb_p(PIC_CASCADE_IR, PIC_SLAVE_IMR); /* 8259A-2 is a slave on master's IR2 */
+ outb_p(SLAVE_ICW4_DEFAULT, PIC_SLAVE_IMR); /* (slave's support for AEOI in flat mode is to be investigated) */
if (auto_eoi)
/*
- * in AEOI mode we just have to mask the interrupt
+ * In AEOI mode we just have to mask the interrupt
* when acking.
*/
- i8259A_irq_type.ack = disable_8259A_irq;
+ i8259A_chip.mask_ack = disable_8259A_irq;
else
- i8259A_irq_type.ack = mask_and_ack_8259A;
+ i8259A_chip.mask_ack = mask_and_ack_8259A;
udelay(100); /* wait for 8259A to initialize */
- outb(cached_21, 0x21); /* restore master IRQ mask */
- outb(cached_A1, 0xA1); /* restore slave IRQ mask */
+ outb(cached_master_mask, PIC_MASTER_IMR); /* restore master IRQ mask */
+ outb(cached_slave_mask, PIC_SLAVE_IMR); /* restore slave IRQ mask */
spin_unlock_irqrestore(&i8259A_lock, flags);
}
@@ -302,11 +295,17 @@ static struct irqaction irq2 = {
};
static struct resource pic1_io_resource = {
- .name = "pic1", .start = 0x20, .end = 0x21, .flags = IORESOURCE_BUSY
+ .name = "pic1",
+ .start = PIC_MASTER_CMD,
+ .end = PIC_MASTER_IMR,
+ .flags = IORESOURCE_BUSY
};
static struct resource pic2_io_resource = {
- .name = "pic2", .start = 0xa0, .end = 0xa1, .flags = IORESOURCE_BUSY
+ .name = "pic2",
+ .start = PIC_SLAVE_CMD,
+ .end = PIC_SLAVE_IMR,
+ .flags = IORESOURCE_BUSY
};
/*
@@ -323,12 +322,8 @@ void __init init_i8259_irqs (void)
init_8259A(0);
- for (i = 0; i < 16; i++) {
- irq_desc[i].status = IRQ_DISABLED;
- irq_desc[i].action = NULL;
- irq_desc[i].depth = 1;
- irq_desc[i].chip = &i8259A_irq_type;
- }
+ for (i = 0; i < 16; i++)
+ set_irq_chip_and_handler(i, &i8259A_chip, handle_level_irq);
- setup_irq(2, &irq2);
+ setup_irq(PIC_CASCADE_IR, &irq2);
}
diff --git a/arch/mips/kernel/irixelf.c b/arch/mips/kernel/irixelf.c
index ab12c8f0151..37cad5de515 100644
--- a/arch/mips/kernel/irixelf.c
+++ b/arch/mips/kernel/irixelf.c
@@ -52,10 +52,6 @@ static struct linux_binfmt irix_format = {
irix_core_dump, PAGE_SIZE
};
-#ifndef elf_addr_t
-#define elf_addr_t unsigned long
-#endif
-
#ifdef DEBUG
/* Debugging routines. */
static char *get_elf_p_type(Elf32_Word p_type)
@@ -1013,7 +1009,7 @@ static int notesize(struct memelfnote *en)
int sz;
sz = sizeof(struct elf_note);
- sz += roundup(strlen(en->name), 4);
+ sz += roundup(strlen(en->name) + 1, 4);
sz += roundup(en->datasz, 4);
return sz;
@@ -1032,7 +1028,7 @@ static int writenote(struct memelfnote *men, struct file *file)
{
struct elf_note en;
- en.n_namesz = strlen(men->name);
+ en.n_namesz = strlen(men->name) + 1;
en.n_descsz = men->datasz;
en.n_type = men->type;
@@ -1149,7 +1145,7 @@ static int irix_core_dump(long signr, struct pt_regs * regs, struct file *file)
psinfo.pr_pid = prstatus.pr_pid = current->pid;
psinfo.pr_ppid = prstatus.pr_ppid = current->parent->pid;
psinfo.pr_pgrp = prstatus.pr_pgrp = process_group(current);
- psinfo.pr_sid = prstatus.pr_sid = current->signal->session;
+ psinfo.pr_sid = prstatus.pr_sid = process_session(current);
if (current->pid == current->tgid) {
/*
* This is the record for the group leader. Add in the
diff --git a/arch/mips/kernel/irq-msc01.c b/arch/mips/kernel/irq-msc01.c
index 650a80ca374..bcaad669608 100644
--- a/arch/mips/kernel/irq-msc01.c
+++ b/arch/mips/kernel/irq-msc01.c
@@ -45,31 +45,6 @@ static inline void unmask_msc_irq(unsigned int irq)
}
/*
- * Enables the IRQ on SOC-it
- */
-static void enable_msc_irq(unsigned int irq)
-{
- unmask_msc_irq(irq);
-}
-
-/*
- * Initialize the IRQ on SOC-it
- */
-static unsigned int startup_msc_irq(unsigned int irq)
-{
- unmask_msc_irq(irq);
- return 0;
-}
-
-/*
- * Disables the IRQ on SOC-it
- */
-static void disable_msc_irq(unsigned int irq)
-{
- mask_msc_irq(irq);
-}
-
-/*
* Masks and ACKs an IRQ
*/
static void level_mask_and_ack_msc_irq(unsigned int irq)
@@ -136,25 +111,23 @@ msc_bind_eic_interrupt (unsigned int irq, unsigned int set)
(irq<<MSC01_IC_RAMW_ADDR_SHF) | (set<<MSC01_IC_RAMW_DATA_SHF));
}
-#define shutdown_msc_irq disable_msc_irq
-
struct irq_chip msc_levelirq_type = {
.typename = "SOC-it-Level",
- .startup = startup_msc_irq,
- .shutdown = shutdown_msc_irq,
- .enable = enable_msc_irq,
- .disable = disable_msc_irq,
.ack = level_mask_and_ack_msc_irq,
+ .mask = mask_msc_irq,
+ .mask_ack = level_mask_and_ack_msc_irq,
+ .unmask = unmask_msc_irq,
+ .eoi = unmask_msc_irq,
.end = end_msc_irq,
};
struct irq_chip msc_edgeirq_type = {
.typename = "SOC-it-Edge",
- .startup =startup_msc_irq,
- .shutdown = shutdown_msc_irq,
- .enable = enable_msc_irq,
- .disable = disable_msc_irq,
.ack = edge_mask_and_ack_msc_irq,
+ .mask = mask_msc_irq,
+ .mask_ack = edge_mask_and_ack_msc_irq,
+ .unmask = unmask_msc_irq,
+ .eoi = unmask_msc_irq,
.end = end_msc_irq,
};
@@ -175,14 +148,14 @@ void __init init_msc_irqs(unsigned int base, msc_irqmap_t *imp, int nirq)
switch (imp->im_type) {
case MSC01_IRQ_EDGE:
- irq_desc[base+n].chip = &msc_edgeirq_type;
+ set_irq_chip(base+n, &msc_edgeirq_type);
if (cpu_has_veic)
MSCIC_WRITE(MSC01_IC_SUP+n*8, MSC01_IC_SUP_EDGE_BIT);
else
MSCIC_WRITE(MSC01_IC_SUP+n*8, MSC01_IC_SUP_EDGE_BIT | imp->im_lvl);
break;
case MSC01_IRQ_LEVEL:
- irq_desc[base+n].chip = &msc_levelirq_type;
+ set_irq_chip(base+n, &msc_levelirq_type);
if (cpu_has_veic)
MSCIC_WRITE(MSC01_IC_SUP+n*8, 0);
else
diff --git a/arch/mips/kernel/irq-mv6434x.c b/arch/mips/kernel/irq-mv6434x.c
index 37d106202b8..efbd219845b 100644
--- a/arch/mips/kernel/irq-mv6434x.c
+++ b/arch/mips/kernel/irq-mv6434x.c
@@ -67,48 +67,6 @@ static inline void unmask_mv64340_irq(unsigned int irq)
}
/*
- * Enables the IRQ on Marvell Chip
- */
-static void enable_mv64340_irq(unsigned int irq)
-{
- unmask_mv64340_irq(irq);
-}
-
-/*
- * Initialize the IRQ on Marvell Chip
- */
-static unsigned int startup_mv64340_irq(unsigned int irq)
-{
- unmask_mv64340_irq(irq);
- return 0;
-}
-
-/*
- * Disables the IRQ on Marvell Chip
- */
-static void disable_mv64340_irq(unsigned int irq)
-{
- mask_mv64340_irq(irq);
-}
-
-/*
- * Masks and ACKs an IRQ
- */
-static void mask_and_ack_mv64340_irq(unsigned int irq)
-{
- mask_mv64340_irq(irq);
-}
-
-/*
- * End IRQ processing
- */
-static void end_mv64340_irq(unsigned int irq)
-{
- if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
- unmask_mv64340_irq(irq);
-}
-
-/*
* Interrupt handler for interrupts coming from the Marvell chip.
* It could be built in ethernet ports etc...
*/
@@ -133,29 +91,21 @@ void ll_mv64340_irq(void)
do_IRQ(ls1bit32(irq_src_high) + irq_base + 32);
}
-#define shutdown_mv64340_irq disable_mv64340_irq
-
struct irq_chip mv64340_irq_type = {
.typename = "MV-64340",
- .startup = startup_mv64340_irq,
- .shutdown = shutdown_mv64340_irq,
- .enable = enable_mv64340_irq,
- .disable = disable_mv64340_irq,
- .ack = mask_and_ack_mv64340_irq,
- .end = end_mv64340_irq,
+ .ack = mask_mv64340_irq,
+ .mask = mask_mv64340_irq,
+ .mask_ack = mask_mv64340_irq,
+ .unmask = unmask_mv64340_irq,
};
void __init mv64340_irq_init(unsigned int base)
{
int i;
- /* Reset irq handlers pointers to NULL */
- for (i = base; i < base + 64; i++) {
- irq_desc[i].status = IRQ_DISABLED;
- irq_desc[i].action = 0;
- irq_desc[i].depth = 2;
- irq_desc[i].chip = &mv64340_irq_type;
- }
+ for (i = base; i < base + 64; i++)
+ set_irq_chip_and_handler(i, &mv64340_irq_type,
+ handle_level_irq);
irq_base = base;
}
diff --git a/arch/mips/kernel/irq-rm7000.c b/arch/mips/kernel/irq-rm7000.c
index 6b54c7109e2..123324ba8c1 100644
--- a/arch/mips/kernel/irq-rm7000.c
+++ b/arch/mips/kernel/irq-rm7000.c
@@ -29,56 +29,12 @@ static inline void mask_rm7k_irq(unsigned int irq)
clear_c0_intcontrol(0x100 << (irq - irq_base));
}
-static inline void rm7k_cpu_irq_enable(unsigned int irq)
-{
- unsigned long flags;
-
- local_irq_save(flags);
- unmask_rm7k_irq(irq);
- local_irq_restore(flags);
-}
-
-static void rm7k_cpu_irq_disable(unsigned int irq)
-{
- unsigned long flags;
-
- local_irq_save(flags);
- mask_rm7k_irq(irq);
- local_irq_restore(flags);
-}
-
-static unsigned int rm7k_cpu_irq_startup(unsigned int irq)
-{
- rm7k_cpu_irq_enable(irq);
-
- return 0;
-}
-
-#define rm7k_cpu_irq_shutdown rm7k_cpu_irq_disable
-
-/*
- * While we ack the interrupt interrupts are disabled and thus we don't need
- * to deal with concurrency issues. Same for rm7k_cpu_irq_end.
- */
-static void rm7k_cpu_irq_ack(unsigned int irq)
-{
- mask_rm7k_irq(irq);
-}
-
-static void rm7k_cpu_irq_end(unsigned int irq)
-{
- if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
- unmask_rm7k_irq(irq);
-}
-
static struct irq_chip rm7k_irq_controller = {
.typename = "RM7000",
- .startup = rm7k_cpu_irq_startup,
- .shutdown = rm7k_cpu_irq_shutdown,
- .enable = rm7k_cpu_irq_enable,
- .disable = rm7k_cpu_irq_disable,
- .ack = rm7k_cpu_irq_ack,
- .end = rm7k_cpu_irq_end,
+ .ack = mask_rm7k_irq,
+ .mask = mask_rm7k_irq,
+ .mask_ack = mask_rm7k_irq,
+ .unmask = unmask_rm7k_irq,
};
void __init rm7k_cpu_irq_init(int base)
@@ -87,12 +43,9 @@ void __init rm7k_cpu_irq_init(int base)
clear_c0_intcontrol(0x00000f00); /* Mask all */
- for (i = base; i < base + 4; i++) {
- irq_desc[i].status = IRQ_DISABLED;
- irq_desc[i].action = NULL;
- irq_desc[i].depth = 1;
- irq_desc[i].chip = &rm7k_irq_controller;
- }
+ for (i = base; i < base + 4; i++)
+ set_irq_chip_and_handler(i, &rm7k_irq_controller,
+ handle_level_irq);
irq_base = base;
}
diff --git a/arch/mips/kernel/irq-rm9000.c b/arch/mips/kernel/irq-rm9000.c
index 62f011ba97a..0e6f4c5349d 100644
--- a/arch/mips/kernel/irq-rm9000.c
+++ b/arch/mips/kernel/irq-rm9000.c
@@ -48,15 +48,6 @@ static void rm9k_cpu_irq_disable(unsigned int irq)
local_irq_restore(flags);
}
-static unsigned int rm9k_cpu_irq_startup(unsigned int irq)
-{
- rm9k_cpu_irq_enable(irq);
-
- return 0;
-}
-
-#define rm9k_cpu_irq_shutdown rm9k_cpu_irq_disable
-
/*
* Performance counter interrupts are global on all processors.
*/
@@ -89,40 +80,22 @@ static void rm9k_perfcounter_irq_shutdown(unsigned int irq)
on_each_cpu(local_rm9k_perfcounter_irq_shutdown, (void *) irq, 0, 1);
}
-
-/*
- * While we ack the interrupt interrupts are disabled and thus we don't need
- * to deal with concurrency issues. Same for rm9k_cpu_irq_end.
- */
-static void rm9k_cpu_irq_ack(unsigned int irq)
-{
- mask_rm9k_irq(irq);
-}
-
-static void rm9k_cpu_irq_end(unsigned int irq)
-{
- if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
- unmask_rm9k_irq(irq);
-}
-
static struct irq_chip rm9k_irq_controller = {
.typename = "RM9000",
- .startup = rm9k_cpu_irq_startup,
- .shutdown = rm9k_cpu_irq_shutdown,
- .enable = rm9k_cpu_irq_enable,
- .disable = rm9k_cpu_irq_disable,
- .ack = rm9k_cpu_irq_ack,
- .end = rm9k_cpu_irq_end,
+ .ack = mask_rm9k_irq,
+ .mask = mask_rm9k_irq,
+ .mask_ack = mask_rm9k_irq,
+ .unmask = unmask_rm9k_irq,
};
static struct irq_chip rm9k_perfcounter_irq = {
.typename = "RM9000",
.startup = rm9k_perfcounter_irq_startup,
.shutdown = rm9k_perfcounter_irq_shutdown,
- .enable = rm9k_cpu_irq_enable,
- .disable = rm9k_cpu_irq_disable,
- .ack = rm9k_cpu_irq_ack,
- .end = rm9k_cpu_irq_end,
+ .ack = mask_rm9k_irq,
+ .mask = mask_rm9k_irq,
+ .mask_ack = mask_rm9k_irq,
+ .unmask = unmask_rm9k_irq,
};
unsigned int rm9000_perfcount_irq;
@@ -135,15 +108,13 @@ void __init rm9k_cpu_irq_init(int base)
clear_c0_intcontrol(0x0000f000); /* Mask all */
- for (i = base; i < base + 4; i++) {
- irq_desc[i].status = IRQ_DISABLED;
- irq_desc[i].action = NULL;
- irq_desc[i].depth = 1;
- irq_desc[i].chip = &rm9k_irq_controller;
- }
+ for (i = base; i < base + 4; i++)
+ set_irq_chip_and_handler(i, &rm9k_irq_controller,
+ handle_level_irq);
rm9000_perfcount_irq = base + 1;
- irq_desc[rm9000_perfcount_irq].chip = &rm9k_perfcounter_irq;
+ set_irq_chip_and_handler(rm9000_perfcount_irq, &rm9k_perfcounter_irq,
+ handle_level_irq);
irq_base = base;
}
diff --git a/arch/mips/kernel/irq.c b/arch/mips/kernel/irq.c
index 9b0e49d63d7..2fe4c868a80 100644
--- a/arch/mips/kernel/irq.c
+++ b/arch/mips/kernel/irq.c
@@ -88,25 +88,6 @@ atomic_t irq_err_count;
unsigned long irq_hwmask[NR_IRQS];
#endif /* CONFIG_MIPS_MT_SMTC */
-#undef do_IRQ
-
-/*
- * do_IRQ handles all normal device IRQ's (the special
- * SMP cross-CPU interrupts have their own specific
- * handlers).
- */
-asmlinkage unsigned int do_IRQ(unsigned int irq)
-{
- irq_enter();
-
- __DO_IRQ_SMTC_HOOK();
- __do_IRQ(irq);
-
- irq_exit();
-
- return 1;
-}
-
/*
* Generic, controller-independent functions:
*/
@@ -136,7 +117,7 @@ int show_interrupts(struct seq_file *p, void *v)
for_each_online_cpu(j)
seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]);
#endif
- seq_printf(p, " %14s", irq_desc[i].chip->typename);
+ seq_printf(p, " %14s", irq_desc[i].chip->name);
seq_printf(p, " %s", action->name);
for (action=action->next; action; action = action->next)
@@ -172,19 +153,6 @@ __setup("nokgdb", nokgdb);
void __init init_IRQ(void)
{
- int i;
-
- for (i = 0; i < NR_IRQS; i++) {
- irq_desc[i].status = IRQ_DISABLED;
- irq_desc[i].action = NULL;
- irq_desc[i].depth = 1;
- irq_desc[i].chip = &no_irq_chip;
- spin_lock_init(&irq_desc[i].lock);
-#ifdef CONFIG_MIPS_MT_SMTC
- irq_hwmask[i] = 0;
-#endif /* CONFIG_MIPS_MT_SMTC */
- }
-
arch_init_irq();
#ifdef CONFIG_KGDB
diff --git a/arch/mips/kernel/irq_cpu.c b/arch/mips/kernel/irq_cpu.c
index 9bb21c7f214..fcc86b96ccf 100644
--- a/arch/mips/kernel/irq_cpu.c
+++ b/arch/mips/kernel/irq_cpu.c
@@ -50,58 +50,13 @@ static inline void mask_mips_irq(unsigned int irq)
irq_disable_hazard();
}
-static inline void mips_cpu_irq_enable(unsigned int irq)
-{
- unsigned long flags;
-
- local_irq_save(flags);
- unmask_mips_irq(irq);
- back_to_back_c0_hazard();
- local_irq_restore(flags);
-}
-
-static void mips_cpu_irq_disable(unsigned int irq)
-{
- unsigned long flags;
-
- local_irq_save(flags);
- mask_mips_irq(irq);
- back_to_back_c0_hazard();
- local_irq_restore(flags);
-}
-
-static unsigned int mips_cpu_irq_startup(unsigned int irq)
-{
- mips_cpu_irq_enable(irq);
-
- return 0;
-}
-
-#define mips_cpu_irq_shutdown mips_cpu_irq_disable
-
-/*
- * While we ack the interrupt interrupts are disabled and thus we don't need
- * to deal with concurrency issues. Same for mips_cpu_irq_end.
- */
-static void mips_cpu_irq_ack(unsigned int irq)
-{
- mask_mips_irq(irq);
-}
-
-static void mips_cpu_irq_end(unsigned int irq)
-{
- if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
- unmask_mips_irq(irq);
-}
-
static struct irq_chip mips_cpu_irq_controller = {
.typename = "MIPS",
- .startup = mips_cpu_irq_startup,
- .shutdown = mips_cpu_irq_shutdown,
- .enable = mips_cpu_irq_enable,
- .disable = mips_cpu_irq_disable,
- .ack = mips_cpu_irq_ack,
- .end = mips_cpu_irq_end,
+ .ack = mask_mips_irq,
+ .mask = mask_mips_irq,
+ .mask_ack = mask_mips_irq,
+ .unmask = unmask_mips_irq,
+ .eoi = unmask_mips_irq,
};
/*
@@ -110,8 +65,6 @@ static struct irq_chip mips_cpu_irq_controller = {
#define unmask_mips_mt_irq unmask_mips_irq
#define mask_mips_mt_irq mask_mips_irq
-#define mips_mt_cpu_irq_enable mips_cpu_irq_enable
-#define mips_mt_cpu_irq_disable mips_cpu_irq_disable
static unsigned int mips_mt_cpu_irq_startup(unsigned int irq)
{
@@ -119,13 +72,11 @@ static unsigned int mips_mt_cpu_irq_startup(unsigned int irq)
clear_c0_cause(0x100 << (irq - mips_cpu_irq_base));
evpe(vpflags);
- mips_mt_cpu_irq_enable(irq);
+ unmask_mips_mt_irq(irq);
return 0;
}
-#define mips_mt_cpu_irq_shutdown mips_mt_cpu_irq_disable
-
/*
* While we ack the interrupt interrupts are disabled and thus we don't need
* to deal with concurrency issues. Same for mips_cpu_irq_end.
@@ -138,16 +89,14 @@ static void mips_mt_cpu_irq_ack(unsigned int irq)
mask_mips_mt_irq(irq);
}
-#define mips_mt_cpu_irq_end mips_cpu_irq_end
-
static struct irq_chip mips_mt_cpu_irq_controller = {
.typename = "MIPS",
.startup = mips_mt_cpu_irq_startup,
- .shutdown = mips_mt_cpu_irq_shutdown,
- .enable = mips_mt_cpu_irq_enable,
- .disable = mips_mt_cpu_irq_disable,
.ack = mips_mt_cpu_irq_ack,
- .end = mips_mt_cpu_irq_end,
+ .mask = mask_mips_mt_irq,
+ .mask_ack = mips_mt_cpu_irq_ack,
+ .unmask = unmask_mips_mt_irq,
+ .eoi = unmask_mips_mt_irq,
};
void __init mips_cpu_irq_init(int irq_base)
@@ -163,19 +112,12 @@ void __init mips_cpu_irq_init(int irq_base)
* leave them uninitialized for other processors.
*/
if (cpu_has_mipsmt)
- for (i = irq_base; i < irq_base + 2; i++) {
- irq_desc[i].status = IRQ_DISABLED;
- irq_desc[i].action = NULL;
- irq_desc[i].depth = 1;
- irq_desc[i].chip = &mips_mt_cpu_irq_controller;
- }
-
- for (i = irq_base + 2; i < irq_base + 8; i++) {
- irq_desc[i].status = IRQ_DISABLED;
- irq_desc[i].action = NULL;
- irq_desc[i].depth = 1;
- irq_desc[i].chip = &mips_cpu_irq_controller;
- }
+ for (i = irq_base; i < irq_base + 2; i++)
+ set_irq_chip(i, &mips_mt_cpu_irq_controller);
+
+ for (i = irq_base + 2; i < irq_base + 8; i++)
+ set_irq_chip_and_handler(i, &mips_cpu_irq_controller,
+ handle_level_irq);
mips_cpu_irq_base = irq_base;
}
diff --git a/arch/mips/kernel/kspd.c b/arch/mips/kernel/kspd.c
index f06a144c788..5929f883e46 100644
--- a/arch/mips/kernel/kspd.c
+++ b/arch/mips/kernel/kspd.c
@@ -301,7 +301,7 @@ static void sp_cleanup(void)
for (;;) {
unsigned long set;
i = j * __NFDBITS;
- if (i >= fdt->max_fdset || i >= fdt->max_fds)
+ if (i >= fdt->max_fds)
break;
set = fdt->open_fds->fds_bits[j++];
while (set) {
@@ -319,7 +319,7 @@ static void sp_cleanup(void)
static int channel_open = 0;
/* the work handler */
-static void sp_work(void *data)
+static void sp_work(struct work_struct *unused)
{
if (!channel_open) {
if( rtlx_open(RTLX_CHANNEL_SYSIO, 1) != 0) {
@@ -354,7 +354,7 @@ static void startwork(int vpe)
return;
}
- INIT_WORK(&work, sp_work, NULL);
+ INIT_WORK(&work, sp_work);
queue_work(workqueue, &work);
} else
queue_work(workqueue, &work);
diff --git a/arch/mips/kernel/linux32.c b/arch/mips/kernel/linux32.c
index 7a3ebbeba1f..de3fae260ff 100644
--- a/arch/mips/kernel/linux32.c
+++ b/arch/mips/kernel/linux32.c
@@ -382,531 +382,6 @@ asmlinkage int sys32_sched_rr_get_interval(compat_pid_t pid,
return ret;
}
-struct msgbuf32 { s32 mtype; char mtext[1]; };
-
-struct ipc_perm32
-{
- key_t key;
- __compat_uid_t uid;
- __compat_gid_t gid;
- __compat_uid_t cuid;
- __compat_gid_t cgid;
- compat_mode_t mode;
- unsigned short seq;
-};
-
-struct ipc64_perm32 {
- key_t key;
- __compat_uid_t uid;
- __compat_gid_t gid;
- __compat_uid_t cuid;
- __compat_gid_t cgid;
- compat_mode_t mode;
- unsigned short seq;
- unsigned short __pad1;
- unsigned int __unused1;
- unsigned int __unused2;
-};
-
-struct semid_ds32 {
- struct ipc_perm32 sem_perm; /* permissions .. see ipc.h */
- compat_time_t sem_otime; /* last semop time */
- compat_time_t sem_ctime; /* last change time */
- u32 sem_base; /* ptr to first semaphore in array */
- u32 sem_pending; /* pending operations to be processed */
- u32 sem_pending_last; /* last pending operation */
- u32 undo; /* undo requests on this array */
- unsigned short sem_nsems; /* no. of semaphores in array */
-};
-
-struct semid64_ds32 {
- struct ipc64_perm32 sem_perm;
- compat_time_t sem_otime;
- compat_time_t sem_ctime;
- unsigned int sem_nsems;
- unsigned int __unused1;
- unsigned int __unused2;
-};
-
-struct msqid_ds32
-{
- struct ipc_perm32 msg_perm;
- u32 msg_first;
- u32 msg_last;
- compat_time_t msg_stime;
- compat_time_t msg_rtime;
- compat_time_t msg_ctime;
- u32 wwait;
- u32 rwait;
- unsigned short msg_cbytes;
- unsigned short msg_qnum;
- unsigned short msg_qbytes;
- compat_ipc_pid_t msg_lspid;
- compat_ipc_pid_t msg_lrpid;
-};
-
-struct msqid64_ds32 {
- struct ipc64_perm32 msg_perm;
- compat_time_t msg_stime;
- unsigned int __unused1;
- compat_time_t msg_rtime;
- unsigned int __unused2;
- compat_time_t msg_ctime;
- unsigned int __unused3;
- unsigned int msg_cbytes;
- unsigned int msg_qnum;
- unsigned int msg_qbytes;
- compat_pid_t msg_lspid;
- compat_pid_t msg_lrpid;
- unsigned int __unused4;
- unsigned int __unused5;
-};
-
-struct shmid_ds32 {
- struct ipc_perm32 shm_perm;
- int shm_segsz;
- compat_time_t shm_atime;
- compat_time_t shm_dtime;
- compat_time_t shm_ctime;
- compat_ipc_pid_t shm_cpid;
- compat_ipc_pid_t shm_lpid;
- unsigned short shm_nattch;
-};
-
-struct shmid64_ds32 {
- struct ipc64_perm32 shm_perm;
- compat_size_t shm_segsz;
- compat_time_t shm_atime;
- compat_time_t shm_dtime;
- compat_time_t shm_ctime;
- compat_pid_t shm_cpid;
- compat_pid_t shm_lpid;
- unsigned int shm_nattch;
- unsigned int __unused1;
- unsigned int __unused2;
-};
-
-struct ipc_kludge32 {
- u32 msgp;
- s32 msgtyp;
-};
-
-static int
-do_sys32_semctl(int first, int second, int third, void __user *uptr)
-{
- union semun fourth;
- u32 pad;
- int err, err2;
- struct semid64_ds s;
- mm_segment_t old_fs;
-
- if (!uptr)
- return -EINVAL;
- err = -EFAULT;
- if (get_user (pad, (u32 __user *)uptr))
- return err;
- if ((third & ~IPC_64) == SETVAL)
- fourth.val = (int)pad;
- else
- fourth.__pad = (void __user *)A(pad);
- switch (third & ~IPC_64) {
- case IPC_INFO:
- case IPC_RMID:
- case IPC_SET:
- case SEM_INFO:
- case GETVAL:
- case GETPID:
- case GETNCNT:
- case GETZCNT:
- case GETALL:
- case SETVAL:
- case SETALL:
- err = sys_semctl (first, second, third, fourth);
- break;
-
- case IPC_STAT:
- case SEM_STAT:
- fourth.__pad = (struct semid64_ds __user *)&s;
- old_fs = get_fs();
- set_fs(KERNEL_DS);
- err = sys_semctl(first, second, third | IPC_64, fourth);
- set_fs(old_fs);
-
- if (third & IPC_64) {
- struct semid64_ds32 __user *usp64 = (struct semid64_ds32 __user *) A(pad);
-
- if (!access_ok(VERIFY_WRITE, usp64, sizeof(*usp64))) {
- err = -EFAULT;
- break;
- }
- err2 = __put_user(s.sem_perm.key, &usp64->sem_perm.key);
- err2 |= __put_user(s.sem_perm.uid, &usp64->sem_perm.uid);
- err2 |= __put_user(s.sem_perm.gid, &usp64->sem_perm.gid);
- err2 |= __put_user(s.sem_perm.cuid, &usp64->sem_perm.cuid);
- err2 |= __put_user(s.sem_perm.cgid, &usp64->sem_perm.cgid);
- err2 |= __put_user(s.sem_perm.mode, &usp64->sem_perm.mode);
- err2 |= __put_user(s.sem_perm.seq, &usp64->sem_perm.seq);
- err2 |= __put_user(s.sem_otime, &usp64->sem_otime);
- err2 |= __put_user(s.sem_ctime, &usp64->sem_ctime);
- err2 |= __put_user(s.sem_nsems, &usp64->sem_nsems);
- } else {
- struct semid_ds32 __user *usp32 = (struct semid_ds32 __user *) A(pad);
-
- if (!access_ok(VERIFY_WRITE, usp32, sizeof(*usp32))) {
- err = -EFAULT;
- break;
- }
- err2 = __put_user(s.sem_perm.key, &usp32->sem_perm.key);
- err2 |= __put_user(s.sem_perm.uid, &usp32->sem_perm.uid);
- err2 |= __put_user(s.sem_perm.gid, &usp32->sem_perm.gid);
- err2 |= __put_user(s.sem_perm.cuid, &usp32->sem_perm.cuid);
- err2 |= __put_user(s.sem_perm.cgid, &usp32->sem_perm.cgid);
- err2 |= __put_user(s.sem_perm.mode, &usp32->sem_perm.mode);
- err2 |= __put_user(s.sem_perm.seq, &usp32->sem_perm.seq);
- err2 |= __put_user(s.sem_otime, &usp32->sem_otime);
- err2 |= __put_user(s.sem_ctime, &usp32->sem_ctime);
- err2 |= __put_user(s.sem_nsems, &usp32->sem_nsems);
- }
- if (err2)
- err = -EFAULT;
- break;
-
- default:
- err = - EINVAL;
- break;
- }
-
- return err;
-}
-
-static int
-do_sys32_msgsnd (int first, int second, int third, void __user *uptr)
-{
- struct msgbuf32 __user *up = (struct msgbuf32 __user *)uptr;
- struct msgbuf *p;
- mm_segment_t old_fs;
- int err;
-
- if (second < 0)
- return -EINVAL;
- p = kmalloc (second + sizeof (struct msgbuf)
- + 4, GFP_USER);
- if (!p)
- return -ENOMEM;
- err = get_user (p->mtype, &up->mtype);
- if (err)
- goto out;
- err |= __copy_from_user (p->mtext, &up->mtext, second);
- if (err)
- goto out;
- old_fs = get_fs ();
- set_fs (KERNEL_DS);
- err = sys_msgsnd (first, (struct msgbuf __user *)p, second, third);
- set_fs (old_fs);
-out:
- kfree (p);
-
- return err;
-}
-
-static int
-do_sys32_msgrcv (int first, int second, int msgtyp, int third,
- int version, void __user *uptr)
-{
- struct msgbuf32 __user *up;
- struct msgbuf *p;
- mm_segment_t old_fs;
- int err;
-
- if (!version) {
- struct ipc_kludge32 __user *uipck = (struct ipc_kludge32 __user *)uptr;
- struct ipc_kludge32 ipck;
-
- err = -EINVAL;
- if (!uptr)
- goto out;
- err = -EFAULT;
- if (copy_from_user (&ipck, uipck, sizeof (struct ipc_kludge32)))
- goto out;
- uptr = (void __user *)AA(ipck.msgp);
- msgtyp = ipck.msgtyp;
- }
-
- if (second < 0)
- return -EINVAL;
- err = -ENOMEM;
- p = kmalloc (second + sizeof (struct msgbuf) + 4, GFP_USER);
- if (!p)
- goto out;
- old_fs = get_fs ();
- set_fs (KERNEL_DS);
- err = sys_msgrcv (first, (struct msgbuf __user *)p, second + 4, msgtyp, third);
- set_fs (old_fs);
- if (err < 0)
- goto free_then_out;
- up = (struct msgbuf32 __user *)uptr;
- if (put_user (p->mtype, &up->mtype) ||
- __copy_to_user (&up->mtext, p->mtext, err))
- err = -EFAULT;
-free_then_out:
- kfree (p);
-out:
- return err;
-}
-
-static int
-do_sys32_msgctl (int first, int second, void __user *uptr)
-{
- int err = -EINVAL, err2;
- struct msqid64_ds m;
- struct msqid_ds32 __user *up32 = (struct msqid_ds32 __user *)uptr;
- struct msqid64_ds32 __user *up64 = (struct msqid64_ds32 __user *)uptr;
- mm_segment_t old_fs;
-
- switch (second & ~IPC_64) {
- case IPC_INFO:
- case IPC_RMID:
- case MSG_INFO:
- err = sys_msgctl (first, second, (struct msqid_ds __user *)uptr);
- break;
-
- case IPC_SET:
- if (second & IPC_64) {
- if (!access_ok(VERIFY_READ, up64, sizeof(*up64))) {
- err = -EFAULT;
- break;
- }
- err = __get_user(m.msg_perm.uid, &up64->msg_perm.uid);
- err |= __get_user(m.msg_perm.gid, &up64->msg_perm.gid);
- err |= __get_user(m.msg_perm.mode, &up64->msg_perm.mode);
- err |= __get_user(m.msg_qbytes, &up64->msg_qbytes);
- } else {
- if (!access_ok(VERIFY_READ, up32, sizeof(*up32))) {
- err = -EFAULT;
- break;
- }
- err = __get_user(m.msg_perm.uid, &up32->msg_perm.uid);
- err |= __get_user(m.msg_perm.gid, &up32->msg_perm.gid);
- err |= __get_user(m.msg_perm.mode, &up32->msg_perm.mode);
- err |= __get_user(m.msg_qbytes, &up32->msg_qbytes);
- }
- if (err)
- break;
- old_fs = get_fs();
- set_fs(KERNEL_DS);
- err = sys_msgctl(first, second | IPC_64, (struct msqid_ds __user *)&m);
- set_fs(old_fs);
- break;
-
- case IPC_STAT:
- case MSG_STAT:
- old_fs = get_fs();
- set_fs(KERNEL_DS);
- err = sys_msgctl(first, second | IPC_64, (struct msqid_ds __user *)&m);
- set_fs(old_fs);
- if (second & IPC_64) {
- if (!access_ok(VERIFY_WRITE, up64, sizeof(*up64))) {
- err = -EFAULT;
- break;
- }
- err2 = __put_user(m.msg_perm.key, &up64->msg_perm.key);
- err2 |= __put_user(m.msg_perm.uid, &up64->msg_perm.uid);
- err2 |= __put_user(m.msg_perm.gid, &up64->msg_perm.gid);
- err2 |= __put_user(m.msg_perm.cuid, &up64->msg_perm.cuid);
- err2 |= __put_user(m.msg_perm.cgid, &up64->msg_perm.cgid);
- err2 |= __put_user(m.msg_perm.mode, &up64->msg_perm.mode);
- err2 |= __put_user(m.msg_perm.seq, &up64->msg_perm.seq);
- err2 |= __put_user(m.msg_stime, &up64->msg_stime);
- err2 |= __put_user(m.msg_rtime, &up64->msg_rtime);
- err2 |= __put_user(m.msg_ctime, &up64->msg_ctime);
- err2 |= __put_user(m.msg_cbytes, &up64->msg_cbytes);
- err2 |= __put_user(m.msg_qnum, &up64->msg_qnum);
- err2 |= __put_user(m.msg_qbytes, &up64->msg_qbytes);
- err2 |= __put_user(m.msg_lspid, &up64->msg_lspid);
- err2 |= __put_user(m.msg_lrpid, &up64->msg_lrpid);
- if (err2)
- err = -EFAULT;
- } else {
- if (!access_ok(VERIFY_WRITE, up32, sizeof(*up32))) {
- err = -EFAULT;
- break;
- }
- err2 = __put_user(m.msg_perm.key, &up32->msg_perm.key);
- err2 |= __put_user(m.msg_perm.uid, &up32->msg_perm.uid);
- err2 |= __put_user(m.msg_perm.gid, &up32->msg_perm.gid);
- err2 |= __put_user(m.msg_perm.cuid, &up32->msg_perm.cuid);
- err2 |= __put_user(m.msg_perm.cgid, &up32->msg_perm.cgid);
- err2 |= __put_user(m.msg_perm.mode, &up32->msg_perm.mode);
- err2 |= __put_user(m.msg_perm.seq, &up32->msg_perm.seq);
- err2 |= __put_user(m.msg_stime, &up32->msg_stime);
- err2 |= __put_user(m.msg_rtime, &up32->msg_rtime);
- err2 |= __put_user(m.msg_ctime, &up32->msg_ctime);
- err2 |= __put_user(m.msg_cbytes, &up32->msg_cbytes);
- err2 |= __put_user(m.msg_qnum, &up32->msg_qnum);
- err2 |= __put_user(m.msg_qbytes, &up32->msg_qbytes);
- err2 |= __put_user(m.msg_lspid, &up32->msg_lspid);
- err2 |= __put_user(m.msg_lrpid, &up32->msg_lrpid);
- if (err2)
- err = -EFAULT;
- }
- break;
- }
-
- return err;
-}
-
-static int
-do_sys32_shmat (int first, int second, int third, int version, void __user *uptr)
-{
- unsigned long raddr;
- u32 __user *uaddr = (u32 __user *)A((u32)third);
- int err = -EINVAL;
-
- if (version == 1)
- return err;
- err = do_shmat (first, uptr, second, &raddr);
- if (err)
- return err;
- err = put_user (raddr, uaddr);
- return err;
-}
-
-struct shm_info32 {
- int used_ids;
- u32 shm_tot, shm_rss, shm_swp;
- u32 swap_attempts, swap_successes;
-};
-
-static int
-do_sys32_shmctl (int first, int second, void __user *uptr)
-{
- struct shmid64_ds32 __user *up64 = (struct shmid64_ds32 __user *)uptr;
- struct shmid_ds32 __user *up32 = (struct shmid_ds32 __user *)uptr;
- struct shm_info32 __user *uip = (struct shm_info32 __user *)uptr;
- int err = -EFAULT, err2;
- struct shmid64_ds s64;
- mm_segment_t old_fs;
- struct shm_info si;
- struct shmid_ds s;
-
- switch (second & ~IPC_64) {
- case IPC_INFO:
- second = IPC_INFO; /* So that we don't have to translate it */
- case IPC_RMID:
- case SHM_LOCK:
- case SHM_UNLOCK:
- err = sys_shmctl(first, second, (struct shmid_ds __user *)uptr);
- break;
- case IPC_SET:
- if (second & IPC_64) {
- err = get_user(s.shm_perm.uid, &up64->shm_perm.uid);
- err |= get_user(s.shm_perm.gid, &up64->shm_perm.gid);
- err |= get_user(s.shm_perm.mode, &up64->shm_perm.mode);
- } else {
- err = get_user(s.shm_perm.uid, &up32->shm_perm.uid);
- err |= get_user(s.shm_perm.gid, &up32->shm_perm.gid);
- err |= get_user(s.shm_perm.mode, &up32->shm_perm.mode);
- }
- if (err)
- break;
- old_fs = get_fs();
- set_fs(KERNEL_DS);
- err = sys_shmctl(first, second & ~IPC_64, (struct shmid_ds __user *)&s);
- set_fs(old_fs);
- break;
-
- case IPC_STAT:
- case SHM_STAT:
- old_fs = get_fs();
- set_fs(KERNEL_DS);
- err = sys_shmctl(first, second | IPC_64, (void __user *) &s64);
- set_fs(old_fs);
- if (err < 0)
- break;
- if (second & IPC_64) {
- if (!access_ok(VERIFY_WRITE, up64, sizeof(*up64))) {
- err = -EFAULT;
- break;
- }
- err2 = __put_user(s64.shm_perm.key, &up64->shm_perm.key);
- err2 |= __put_user(s64.shm_perm.uid, &up64->shm_perm.uid);
- err2 |= __put_user(s64.shm_perm.gid, &up64->shm_perm.gid);
- err2 |= __put_user(s64.shm_perm.cuid, &up64->shm_perm.cuid);
- err2 |= __put_user(s64.shm_perm.cgid, &up64->shm_perm.cgid);
- err2 |= __put_user(s64.shm_perm.mode, &up64->shm_perm.mode);
- err2 |= __put_user(s64.shm_perm.seq, &up64->shm_perm.seq);
- err2 |= __put_user(s64.shm_atime, &up64->shm_atime);
- err2 |= __put_user(s64.shm_dtime, &up64->shm_dtime);
- err2 |= __put_user(s64.shm_ctime, &up64->shm_ctime);
- err2 |= __put_user(s64.shm_segsz, &up64->shm_segsz);
- err2 |= __put_user(s64.shm_nattch, &up64->shm_nattch);
- err2 |= __put_user(s64.shm_cpid, &up64->shm_cpid);
- err2 |= __put_user(s64.shm_lpid, &up64->shm_lpid);
- } else {
- if (!access_ok(VERIFY_WRITE, up32, sizeof(*up32))) {
- err = -EFAULT;
- break;
- }
- err2 = __put_user(s64.shm_perm.key, &up32->shm_perm.key);
- err2 |= __put_user(s64.shm_perm.uid, &up32->shm_perm.uid);
- err2 |= __put_user(s64.shm_perm.gid, &up32->shm_perm.gid);
- err2 |= __put_user(s64.shm_perm.cuid, &up32->shm_perm.cuid);
- err2 |= __put_user(s64.shm_perm.cgid, &up32->shm_perm.cgid);
- err2 |= __put_user(s64.shm_perm.mode, &up32->shm_perm.mode);
- err2 |= __put_user(s64.shm_perm.seq, &up32->shm_perm.seq);
- err2 |= __put_user(s64.shm_atime, &up32->shm_atime);
- err2 |= __put_user(s64.shm_dtime, &up32->shm_dtime);
- err2 |= __put_user(s64.shm_ctime, &up32->shm_ctime);
- err2 |= __put_user(s64.shm_segsz, &up32->shm_segsz);
- err2 |= __put_user(s64.shm_nattch, &up32->shm_nattch);
- err2 |= __put_user(s64.shm_cpid, &up32->shm_cpid);
- err2 |= __put_user(s64.shm_lpid, &up32->shm_lpid);
- }
- if (err2)
- err = -EFAULT;
- break;
-
- case SHM_INFO:
- old_fs = get_fs();
- set_fs(KERNEL_DS);
- err = sys_shmctl(first, second, (void __user *)&si);
- set_fs(old_fs);
- if (err < 0)
- break;
- err2 = put_user(si.used_ids, &uip->used_ids);
- err2 |= __put_user(si.shm_tot, &uip->shm_tot);
- err2 |= __put_user(si.shm_rss, &uip->shm_rss);
- err2 |= __put_user(si.shm_swp, &uip->shm_swp);
- err2 |= __put_user(si.swap_attempts, &uip->swap_attempts);
- err2 |= __put_user (si.swap_successes, &uip->swap_successes);
- if (err2)
- err = -EFAULT;
- break;
-
- default:
- err = -EINVAL;
- break;
- }
-
- return err;
-}
-
-static int sys32_semtimedop(int semid, struct sembuf __user *tsems, int nsems,
- const struct compat_timespec __user *timeout32)
-{
- struct compat_timespec t32;
- struct timespec __user *t64 = compat_alloc_user_space(sizeof(*t64));
-
- if (copy_from_user(&t32, timeout32, sizeof(t32)))
- return -EFAULT;
-
- if (put_user(t32.tv_sec, &t64->tv_sec) ||
- put_user(t32.tv_nsec, &t64->tv_nsec))
- return -EFAULT;
-
- return sys_semtimedop(semid, tsems, nsems, t64);
-}
-
asmlinkage long
sys32_ipc (u32 call, int first, int second, int third, u32 ptr, u32 fifth)
{
@@ -918,48 +393,43 @@ sys32_ipc (u32 call, int first, int second, int third, u32 ptr, u32 fifth)
switch (call) {
case SEMOP:
/* struct sembuf is the same on 32 and 64bit :)) */
- err = sys_semtimedop (first, (struct sembuf __user *)AA(ptr), second,
- NULL);
+ err = sys_semtimedop(first, compat_ptr(ptr), second, NULL);
break;
case SEMTIMEDOP:
- err = sys32_semtimedop (first, (struct sembuf __user *)AA(ptr), second,
- (const struct compat_timespec __user *)AA(fifth));
+ err = compat_sys_semtimedop(first, compat_ptr(ptr), second,
+ compat_ptr(fifth));
break;
case SEMGET:
- err = sys_semget (first, second, third);
+ err = sys_semget(first, second, third);
break;
case SEMCTL:
- err = do_sys32_semctl (first, second, third,
- (void __user *)AA(ptr));
+ err = compat_sys_semctl(first, second, third, compat_ptr(ptr));
break;
-
case MSGSND:
- err = do_sys32_msgsnd (first, second, third,
- (void __user *)AA(ptr));
+ err = compat_sys_msgsnd(first, second, third, compat_ptr(ptr));
break;
case MSGRCV:
- err = do_sys32_msgrcv (first, second, fifth, third,
- version, (void __user *)AA(ptr));
+ err = compat_sys_msgrcv(first, second, fifth, third,
+ version, compat_ptr(ptr));
break;
case MSGGET:
- err = sys_msgget ((key_t) first, second);
+ err = sys_msgget((key_t) first, second);
break;
case MSGCTL:
- err = do_sys32_msgctl (first, second, (void __user *)AA(ptr));
+ err = compat_sys_msgctl(first, second, compat_ptr(ptr));
break;
-
case SHMAT:
- err = do_sys32_shmat (first, second, third,
- version, (void __user *)AA(ptr));
+ err = compat_sys_shmat(first, second, third, version,
+ compat_ptr(ptr));
break;
case SHMDT:
- err = sys_shmdt ((char __user *)A(ptr));
+ err = sys_shmdt(compat_ptr(ptr));
break;
case SHMGET:
- err = sys_shmget (first, (unsigned)second, third);
+ err = sys_shmget(first, (unsigned)second, third);
break;
case SHMCTL:
- err = do_sys32_shmctl (first, second, (void __user *)AA(ptr));
+ err = compat_sys_shmctl(first, second, compat_ptr(ptr));
break;
default:
err = -EINVAL;
@@ -969,18 +439,28 @@ sys32_ipc (u32 call, int first, int second, int third, u32 ptr, u32 fifth)
return err;
}
-asmlinkage long sys32_shmat(int shmid, char __user *shmaddr,
- int shmflg, int32_t __user *addr)
+#ifdef CONFIG_MIPS32_N32
+asmlinkage long sysn32_semctl(int semid, int semnum, int cmd, u32 arg)
{
- unsigned long raddr;
- int err;
+ /* compat_sys_semctl expects a pointer to union semun */
+ u32 __user *uptr = compat_alloc_user_space(sizeof(u32));
+ if (put_user(arg, uptr))
+ return -EFAULT;
+ return compat_sys_semctl(semid, semnum, cmd, uptr);
+}
- err = do_shmat(shmid, shmaddr, shmflg, &raddr);
- if (err)
- return err;
+asmlinkage long sysn32_msgsnd(int msqid, u32 msgp, unsigned msgsz, int msgflg)
+{
+ return compat_sys_msgsnd(msqid, msgsz, msgflg, compat_ptr(msgp));
+}
- return put_user(raddr, addr);
+asmlinkage long sysn32_msgrcv(int msqid, u32 msgp, size_t msgsz, int msgtyp,
+ int msgflg)
+{
+ return compat_sys_msgrcv(msqid, msgsz, msgtyp, msgflg, IPC_64,
+ compat_ptr(msgp));
}
+#endif
struct sysctl_args32
{
diff --git a/arch/mips/kernel/machine_kexec.c b/arch/mips/kernel/machine_kexec.c
new file mode 100644
index 00000000000..e0ad754c7ed
--- /dev/null
+++ b/arch/mips/kernel/machine_kexec.c
@@ -0,0 +1,85 @@
+/*
+ * machine_kexec.c for kexec
+ * Created by <nschichan@corp.free.fr> on Thu Oct 12 15:15:06 2006
+ *
+ * This source code is licensed under the GNU General Public License,
+ * Version 2. See the file COPYING for more details.
+ */
+
+#include <linux/kexec.h>
+#include <linux/mm.h>
+#include <linux/delay.h>
+
+#include <asm/cacheflush.h>
+#include <asm/page.h>
+
+const extern unsigned char relocate_new_kernel[];
+const extern unsigned int relocate_new_kernel_size;
+
+extern unsigned long kexec_start_address;
+extern unsigned long kexec_indirection_page;
+
+int
+machine_kexec_prepare(struct kimage *kimage)
+{
+ return 0;
+}
+
+void
+machine_kexec_cleanup(struct kimage *kimage)
+{
+}
+
+void
+machine_shutdown(void)
+{
+}
+
+void
+machine_crash_shutdown(struct pt_regs *regs)
+{
+}
+
+void
+machine_kexec(struct kimage *image)
+{
+ unsigned long reboot_code_buffer;
+ unsigned long entry;
+ unsigned long *ptr;
+
+ reboot_code_buffer =
+ (unsigned long)page_address(image->control_code_page);
+
+ kexec_start_address = image->start;
+ kexec_indirection_page = phys_to_virt(image->head & PAGE_MASK);
+
+ memcpy((void*)reboot_code_buffer, relocate_new_kernel,
+ relocate_new_kernel_size);
+
+ /*
+ * The generic kexec code builds a page list with physical
+ * addresses. they are directly accessible through KSEG0 (or
+ * CKSEG0 or XPHYS if on 64bit system), hence the
+ * pys_to_virt() call.
+ */
+ for (ptr = &image->head; (entry = *ptr) && !(entry &IND_DONE);
+ ptr = (entry & IND_INDIRECTION) ?
+ phys_to_virt(entry & PAGE_MASK) : ptr + 1) {
+ if (*ptr & IND_SOURCE || *ptr & IND_INDIRECTION ||
+ *ptr & IND_DESTINATION)
+ *ptr = phys_to_virt(*ptr);
+ }
+
+ /*
+ * we do not want to be bothered.
+ */
+ local_irq_disable();
+
+ flush_icache_range(reboot_code_buffer,
+ reboot_code_buffer + KEXEC_CONTROL_CODE_SIZE);
+
+ printk("Will call new kernel at %08x\n", image->start);
+ printk("Bye ...\n");
+ flush_cache_all();
+ ((void (*)(void))reboot_code_buffer)();
+}
diff --git a/arch/mips/kernel/mips_ksyms.c b/arch/mips/kernel/mips_ksyms.c
index f44a01357ad..2ef857c3ee5 100644
--- a/arch/mips/kernel/mips_ksyms.c
+++ b/arch/mips/kernel/mips_ksyms.c
@@ -46,5 +46,7 @@ EXPORT_SYMBOL(__strnlen_user_nocheck_asm);
EXPORT_SYMBOL(__strnlen_user_asm);
EXPORT_SYMBOL(csum_partial);
+EXPORT_SYMBOL(csum_partial_copy_nocheck);
+EXPORT_SYMBOL(__csum_partial_copy_user);
EXPORT_SYMBOL(invalid_pte_table);
diff --git a/arch/mips/kernel/module.c b/arch/mips/kernel/module.c
index d7bf0215bc1..cb0801437b6 100644
--- a/arch/mips/kernel/module.c
+++ b/arch/mips/kernel/module.c
@@ -29,6 +29,7 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/spinlock.h>
+#include <asm/pgtable.h> /* MODULE_START */
struct mips_hi16 {
struct mips_hi16 *next;
@@ -43,9 +44,23 @@ static DEFINE_SPINLOCK(dbe_lock);
void *module_alloc(unsigned long size)
{
+#ifdef MODULE_START
+ struct vm_struct *area;
+
+ size = PAGE_ALIGN(size);
+ if (!size)
+ return NULL;
+
+ area = __get_vm_area(size, VM_ALLOC, MODULE_START, MODULE_END);
+ if (!area)
+ return NULL;
+
+ return __vmalloc_area(area, GFP_KERNEL, PAGE_KERNEL);
+#else
if (size == 0)
return NULL;
return vmalloc(size);
+#endif
}
/* Free memory returned from module_alloc */
diff --git a/arch/mips/kernel/relocate_kernel.S b/arch/mips/kernel/relocate_kernel.S
new file mode 100644
index 00000000000..a3f0d00c133
--- /dev/null
+++ b/arch/mips/kernel/relocate_kernel.S
@@ -0,0 +1,80 @@
+/*
+ * relocate_kernel.S for kexec
+ * Created by <nschichan@corp.free.fr> on Thu Oct 12 17:49:57 2006
+ *
+ * This source code is licensed under the GNU General Public License,
+ * Version 2. See the file COPYING for more details.
+ */
+
+#include <asm/asm.h>
+#include <asm/asmmacro.h>
+#include <asm/regdef.h>
+#include <asm/page.h>
+#include <asm/mipsregs.h>
+#include <asm/stackframe.h>
+#include <asm/addrspace.h>
+
+ .globl relocate_new_kernel
+relocate_new_kernel:
+
+ PTR_L s0, kexec_indirection_page
+ PTR_L s1, kexec_start_address
+
+process_entry:
+ PTR_L s2, (s0)
+ PTR_ADD s0, s0, SZREG
+
+ /* destination page */
+ and s3, s2, 0x1
+ beq s3, zero, 1f
+ and s4, s2, ~0x1 /* store destination addr in s4 */
+ move a0, s4
+ b process_entry
+
+1:
+ /* indirection page, update s0 */
+ and s3, s2, 0x2
+ beq s3, zero, 1f
+ and s0, s2, ~0x2
+ b process_entry
+
+1:
+ /* done page */
+ and s3, s2, 0x4
+ beq s3, zero, 1f
+ b done
+1:
+ /* source page */
+ and s3, s2, 0x8
+ beq s3, zero, process_entry
+ and s2, s2, ~0x8
+ li s6, (1 << PAGE_SHIFT) / SZREG
+
+copy_word:
+ /* copy page word by word */
+ REG_L s5, (s2)
+ REG_S s5, (s4)
+ INT_ADD s4, s4, SZREG
+ INT_ADD s2, s2, SZREG
+ INT_SUB s6, s6, 1
+ beq s6, zero, process_entry
+ b copy_word
+ b process_entry
+
+done:
+ /* jump to kexec_start_address */
+ j s1
+
+ .globl kexec_start_address
+kexec_start_address:
+ .long 0x0
+
+ .globl kexec_indirection_page
+kexec_indirection_page:
+ .long 0x0
+
+relocate_new_kernel_end:
+
+ .globl relocate_new_kernel_size
+relocate_new_kernel_size:
+ .long relocate_new_kernel_end - relocate_new_kernel
diff --git a/arch/mips/kernel/reset.c b/arch/mips/kernel/reset.c
index 621037db229..060563a712b 100644
--- a/arch/mips/kernel/reset.c
+++ b/arch/mips/kernel/reset.c
@@ -23,6 +23,8 @@ void (*_machine_restart)(char *command);
void (*_machine_halt)(void);
void (*pm_power_off)(void);
+EXPORT_SYMBOL(pm_power_off);
+
void machine_restart(char *command)
{
if (_machine_restart)
diff --git a/arch/mips/kernel/rtlx.c b/arch/mips/kernel/rtlx.c
index 8c8c8324f77..5a99e3e0c96 100644
--- a/arch/mips/kernel/rtlx.c
+++ b/arch/mips/kernel/rtlx.c
@@ -415,7 +415,7 @@ static unsigned int file_poll(struct file *file, poll_table * wait)
int minor;
unsigned int mask = 0;
- minor = iminor(file->f_dentry->d_inode);
+ minor = iminor(file->f_path.dentry->d_inode);
poll_wait(file, &channel_wqs[minor].rt_queue, wait);
poll_wait(file, &channel_wqs[minor].lx_queue, wait);
@@ -437,7 +437,7 @@ static unsigned int file_poll(struct file *file, poll_table * wait)
static ssize_t file_read(struct file *file, char __user * buffer, size_t count,
loff_t * ppos)
{
- int minor = iminor(file->f_dentry->d_inode);
+ int minor = iminor(file->f_path.dentry->d_inode);
/* data available? */
if (!rtlx_read_poll(minor, (file->f_flags & O_NONBLOCK) ? 0 : 1)) {
@@ -454,7 +454,7 @@ static ssize_t file_write(struct file *file, const char __user * buffer,
struct rtlx_channel *rt;
DECLARE_WAITQUEUE(wait, current);
- minor = iminor(file->f_dentry->d_inode);
+ minor = iminor(file->f_path.dentry->d_inode);
rt = &rtlx->channel[minor];
/* any space left... */
diff --git a/arch/mips/kernel/scall32-o32.S b/arch/mips/kernel/scall32-o32.S
index a95f37de080..7c0b3936ba4 100644
--- a/arch/mips/kernel/scall32-o32.S
+++ b/arch/mips/kernel/scall32-o32.S
@@ -653,7 +653,7 @@ einval: li v0, -EINVAL
sys sys_move_pages 6
sys sys_set_robust_list 2
sys sys_get_robust_list 3 /* 4310 */
- sys sys_ni_syscall 0
+ sys sys_kexec_load 4
sys sys_getcpu 3
sys sys_epoll_pwait 6
.endm
diff --git a/arch/mips/kernel/scall64-64.S b/arch/mips/kernel/scall64-64.S
index 8fb0f60f657..e569b846e9a 100644
--- a/arch/mips/kernel/scall64-64.S
+++ b/arch/mips/kernel/scall64-64.S
@@ -468,6 +468,6 @@ sys_call_table:
PTR sys_move_pages
PTR sys_set_robust_list
PTR sys_get_robust_list
- PTR sys_ni_syscall /* 5270 */
+ PTR sys_kexec_load /* 5270 */
PTR sys_getcpu
PTR sys_epoll_pwait
diff --git a/arch/mips/kernel/scall64-n32.S b/arch/mips/kernel/scall64-n32.S
index 0da5ca2040f..a7bff2a5472 100644
--- a/arch/mips/kernel/scall64-n32.S
+++ b/arch/mips/kernel/scall64-n32.S
@@ -149,8 +149,8 @@ EXPORT(sysn32_call_table)
PTR sys_mincore
PTR sys_madvise
PTR sys_shmget
- PTR sys32_shmat
- PTR sys_shmctl /* 6030 */
+ PTR sys_shmat
+ PTR compat_sys_shmctl /* 6030 */
PTR sys_dup
PTR sys_dup2
PTR sys_pause
@@ -184,12 +184,12 @@ EXPORT(sysn32_call_table)
PTR sys32_newuname
PTR sys_semget
PTR sys_semop
- PTR sys_semctl
+ PTR sysn32_semctl
PTR sys_shmdt /* 6065 */
PTR sys_msgget
- PTR sys_msgsnd
- PTR sys_msgrcv
- PTR sys_msgctl
+ PTR sysn32_msgsnd
+ PTR sysn32_msgrcv
+ PTR compat_sys_msgctl
PTR compat_sys_fcntl /* 6070 */
PTR sys_flock
PTR sys_fsync
@@ -335,7 +335,7 @@ EXPORT(sysn32_call_table)
PTR compat_sys_fcntl64
PTR sys_set_tid_address
PTR sys_restart_syscall
- PTR sys_semtimedop /* 6215 */
+ PTR compat_sys_semtimedop /* 6215 */
PTR sys_fadvise64_64
PTR compat_sys_statfs64
PTR compat_sys_fstatfs64
@@ -394,6 +394,6 @@ EXPORT(sysn32_call_table)
PTR sys_move_pages
PTR compat_sys_set_robust_list
PTR compat_sys_get_robust_list
- PTR sys_ni_syscall
+ PTR compat_sys_kexec_load
PTR sys_getcpu
PTR sys_epoll_pwait
diff --git a/arch/mips/kernel/scall64-o32.S b/arch/mips/kernel/scall64-o32.S
index b9d00cae8b5..e91379c1be1 100644
--- a/arch/mips/kernel/scall64-o32.S
+++ b/arch/mips/kernel/scall64-o32.S
@@ -516,7 +516,7 @@ sys_call_table:
PTR compat_sys_move_pages
PTR compat_sys_set_robust_list
PTR compat_sys_get_robust_list /* 4310 */
- PTR sys_ni_syscall
+ PTR compat_sys_kexec_load
PTR sys_getcpu
PTR sys_epoll_pwait
.size sys_call_table,.-sys_call_table
diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c
index 8f6e89697cc..89440a0d852 100644
--- a/arch/mips/kernel/setup.c
+++ b/arch/mips/kernel/setup.c
@@ -145,13 +145,12 @@ static int __init rd_start_early(char *p)
unsigned long start = memparse(p, &p);
#ifdef CONFIG_64BIT
- /* HACK: Guess if the sign extension was forgotten */
- if (start > 0x0000000080000000 && start < 0x00000000ffffffff)
- start |= 0xffffffff00000000UL;
+ /* Guess if the sign extension was forgotten by bootloader */
+ if (start < XKPHYS)
+ start = (int)start;
#endif
initrd_start = start;
initrd_end += start;
-
return 0;
}
early_param("rd_start", rd_start_early);
@@ -159,41 +158,64 @@ early_param("rd_start", rd_start_early);
static int __init rd_size_early(char *p)
{
initrd_end += memparse(p, &p);
-
return 0;
}
early_param("rd_size", rd_size_early);
+/* it returns the next free pfn after initrd */
static unsigned long __init init_initrd(void)
{
- unsigned long tmp, end, size;
+ unsigned long end;
u32 *initrd_header;
- ROOT_DEV = Root_RAM0;
-
/*
* Board specific code or command line parser should have
* already set up initrd_start and initrd_end. In these cases
* perfom sanity checks and use them if all looks good.
*/
- size = initrd_end - initrd_start;
- if (initrd_end == 0 || size == 0) {
- initrd_start = 0;
- initrd_end = 0;
- } else
- return initrd_end;
-
- end = (unsigned long)&_end;
- tmp = PAGE_ALIGN(end) - sizeof(u32) * 2;
- if (tmp < end)
- tmp += PAGE_SIZE;
-
- initrd_header = (u32 *)tmp;
- if (initrd_header[0] == 0x494E5244) {
- initrd_start = (unsigned long)&initrd_header[2];
- initrd_end = initrd_start + initrd_header[1];
+ if (initrd_start && initrd_end > initrd_start)
+ goto sanitize;
+
+ /*
+ * See if initrd has been added to the kernel image by
+ * arch/mips/boot/addinitrd.c. In that case a header is
+ * prepended to initrd and is made up by 8 bytes. The fisrt
+ * word is a magic number and the second one is the size of
+ * initrd. Initrd start must be page aligned in any cases.
+ */
+ initrd_header = __va(PAGE_ALIGN(__pa_symbol(&_end) + 8)) - 8;
+ if (initrd_header[0] != 0x494E5244)
+ goto disable;
+ initrd_start = (unsigned long)(initrd_header + 2);
+ initrd_end = initrd_start + initrd_header[1];
+
+sanitize:
+ if (initrd_start & ~PAGE_MASK) {
+ printk(KERN_ERR "initrd start must be page aligned\n");
+ goto disable;
}
- return initrd_end;
+ if (initrd_start < PAGE_OFFSET) {
+ printk(KERN_ERR "initrd start < PAGE_OFFSET\n");
+ goto disable;
+ }
+
+ /*
+ * Sanitize initrd addresses. For example firmware
+ * can't guess if they need to pass them through
+ * 64-bits values if the kernel has been built in pure
+ * 32-bit. We need also to switch from KSEG0 to XKPHYS
+ * addresses now, so the code can now safely use __pa().
+ */
+ end = __pa(initrd_end);
+ initrd_end = (unsigned long)__va(end);
+ initrd_start = (unsigned long)__va(__pa(initrd_start));
+
+ ROOT_DEV = Root_RAM0;
+ return PFN_UP(end);
+disable:
+ initrd_start = 0;
+ initrd_end = 0;
+ return 0;
}
static void __init finalize_initrd(void)
@@ -204,12 +226,12 @@ static void __init finalize_initrd(void)
printk(KERN_INFO "Initrd not found or empty");
goto disable;
}
- if (CPHYSADDR(initrd_end) > PFN_PHYS(max_low_pfn)) {
+ if (__pa(initrd_end) > PFN_PHYS(max_low_pfn)) {
printk("Initrd extends beyond end of memory");
goto disable;
}
- reserve_bootmem(CPHYSADDR(initrd_start), size);
+ reserve_bootmem(__pa(initrd_start), size);
initrd_below_start_ok = 1;
printk(KERN_INFO "Initial ramdisk at: 0x%lx (%lu bytes)\n",
@@ -259,8 +281,7 @@ static void __init bootmem_init(void)
* not selected. Once that done we can determine the low bound
* of usable memory.
*/
- reserved_end = init_initrd();
- reserved_end = PFN_UP(CPHYSADDR(max(reserved_end, (unsigned long)&_end)));
+ reserved_end = max(init_initrd(), PFN_UP(__pa_symbol(&_end)));
/*
* Find the highest page frame number we have available.
@@ -432,10 +453,10 @@ static void __init resource_init(void)
if (UNCAC_BASE != IO_BASE)
return;
- code_resource.start = virt_to_phys(&_text);
- code_resource.end = virt_to_phys(&_etext) - 1;
- data_resource.start = virt_to_phys(&_etext);
- data_resource.end = virt_to_phys(&_edata) - 1;
+ code_resource.start = __pa_symbol(&_text);
+ code_resource.end = __pa_symbol(&_etext) - 1;
+ data_resource.start = __pa_symbol(&_etext);
+ data_resource.end = __pa_symbol(&_edata) - 1;
/*
* Request address space for all standard RAM.
diff --git a/arch/mips/kernel/signal_n32.c b/arch/mips/kernel/signal_n32.c
index 477c5334ec1..a67c18555ed 100644
--- a/arch/mips/kernel/signal_n32.c
+++ b/arch/mips/kernel/signal_n32.c
@@ -17,7 +17,6 @@
*/
#include <linux/cache.h>
#include <linux/sched.h>
-#include <linux/sched.h>
#include <linux/mm.h>
#include <linux/smp.h>
#include <linux/smp_lock.h>
diff --git a/arch/mips/kernel/smp-mt.c b/arch/mips/kernel/smp-mt.c
index 2ac19a6cbf6..1ee689c0e0c 100644
--- a/arch/mips/kernel/smp-mt.c
+++ b/arch/mips/kernel/smp-mt.c
@@ -278,7 +278,9 @@ void __init plat_prepare_cpus(unsigned int max_cpus)
/* need to mark IPI's as IRQ_PER_CPU */
irq_desc[cpu_ipi_resched_irq].status |= IRQ_PER_CPU;
+ set_irq_handler(cpu_ipi_resched_irq, handle_percpu_irq);
irq_desc[cpu_ipi_call_irq].status |= IRQ_PER_CPU;
+ set_irq_handler(cpu_ipi_call_irq, handle_percpu_irq);
}
/*
diff --git a/arch/mips/kernel/smp.c b/arch/mips/kernel/smp.c
index 49db516789e..0555fc554f6 100644
--- a/arch/mips/kernel/smp.c
+++ b/arch/mips/kernel/smp.c
@@ -172,7 +172,7 @@ int smp_call_function (void (*func) (void *info), void *info, int retry,
spin_lock(&smp_call_lock);
call_data = &data;
- mb();
+ smp_mb();
/* Send a message to all other CPUs and wait for them to respond */
for_each_online_cpu(i)
@@ -204,7 +204,7 @@ void smp_call_function_interrupt(void)
* Notify initiating CPU that I've grabbed the data and am
* about to execute the function.
*/
- mb();
+ smp_mb();
atomic_inc(&call_data->started);
/*
@@ -215,7 +215,7 @@ void smp_call_function_interrupt(void)
irq_exit();
if (wait) {
- mb();
+ smp_mb();
atomic_inc(&call_data->finished);
}
}
@@ -271,7 +271,7 @@ void __devinit smp_prepare_boot_cpu(void)
* and keep control until "cpu_online(cpu)" is set. Note: cpu is
* physical, not logical.
*/
-int __devinit __cpu_up(unsigned int cpu)
+int __cpuinit __cpu_up(unsigned int cpu)
{
struct task_struct *idle;
diff --git a/arch/mips/kernel/smtc.c b/arch/mips/kernel/smtc.c
index 3b78caf112f..802febed7df 100644
--- a/arch/mips/kernel/smtc.c
+++ b/arch/mips/kernel/smtc.c
@@ -1009,6 +1009,7 @@ void setup_cross_vpe_interrupts(void)
setup_irq_smtc(cpu_ipi_irq, &irq_ipi, (0x100 << MIPS_CPU_IPI_IRQ));
irq_desc[cpu_ipi_irq].status |= IRQ_PER_CPU;
+ set_irq_handler(cpu_ipi_irq, handle_percpu_irq);
}
/*
diff --git a/arch/mips/kernel/sysirix.c b/arch/mips/kernel/sysirix.c
index 93c74fefff7..6c2406a93f2 100644
--- a/arch/mips/kernel/sysirix.c
+++ b/arch/mips/kernel/sysirix.c
@@ -732,7 +732,7 @@ asmlinkage int irix_fstatfs(unsigned int fd, struct irix_statfs __user *buf)
goto out;
}
- error = vfs_statfs(file->f_dentry, &kbuf);
+ error = vfs_statfs(file->f_path.dentry, &kbuf);
if (error)
goto out_f;
@@ -1041,7 +1041,7 @@ asmlinkage unsigned long irix_mmap32(unsigned long addr, size_t len, int prot,
unsigned long old_pos;
long max_size = offset + len;
- if (max_size > file->f_dentry->d_inode->i_size) {
+ if (max_size > file->f_path.dentry->d_inode->i_size) {
old_pos = sys_lseek (fd, max_size - 1, 0);
sys_write (fd, (void __user *) "", 1);
sys_lseek (fd, old_pos, 0);
@@ -1406,7 +1406,7 @@ asmlinkage int irix_fstatvfs(int fd, struct irix_statvfs __user *buf)
error = -EBADF;
goto out;
}
- error = vfs_statfs(file->f_dentry, &kbuf);
+ error = vfs_statfs(file->f_path.dentry, &kbuf);
if (error)
goto out_f;
@@ -1526,7 +1526,7 @@ asmlinkage int irix_mmap64(struct pt_regs *regs)
unsigned long old_pos;
long max_size = off2 + len;
- if (max_size > file->f_dentry->d_inode->i_size) {
+ if (max_size > file->f_path.dentry->d_inode->i_size) {
old_pos = sys_lseek (fd, max_size - 1, 0);
sys_write (fd, (void __user *) "", 1);
sys_lseek (fd, old_pos, 0);
@@ -1658,7 +1658,7 @@ asmlinkage int irix_fstatvfs64(int fd, struct irix_statvfs __user *buf)
error = -EBADF;
goto out;
}
- error = vfs_statfs(file->f_dentry, &kbuf);
+ error = vfs_statfs(file->f_path.dentry, &kbuf);
if (error)
goto out_f;
diff --git a/arch/mips/kernel/time.c b/arch/mips/kernel/time.c
index e535f86efa2..8aa544f73a5 100644
--- a/arch/mips/kernel/time.c
+++ b/arch/mips/kernel/time.c
@@ -11,7 +11,6 @@
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*/
-#include <linux/clocksource.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/init.h>
@@ -83,17 +82,11 @@ static void null_timer_ack(void) { /* nothing */ }
/*
* Null high precision timer functions for systems lacking one.
*/
-static unsigned int null_hpt_read(void)
+static cycle_t null_hpt_read(void)
{
return 0;
}
-static void __init null_hpt_init(void)
-{
- /* nothing */
-}
-
-
/*
* Timer ack for an R4k-compatible timer of a known frequency.
*/
@@ -101,10 +94,8 @@ static void c0_timer_ack(void)
{
unsigned int count;
-#ifndef CONFIG_SOC_PNX8550 /* pnx8550 resets to zero */
/* Ack this timer interrupt and set the next one. */
expirelo += cycles_per_jiffy;
-#endif
write_c0_compare(expirelo);
/* Check to see if we have missed any timer interrupts. */
@@ -118,7 +109,7 @@ static void c0_timer_ack(void)
/*
* High precision timer functions for a R4k-compatible timer.
*/
-static unsigned int c0_hpt_read(void)
+static cycle_t c0_hpt_read(void)
{
return read_c0_count();
}
@@ -132,9 +123,6 @@ static void __init c0_hpt_timer_init(void)
int (*mips_timer_state)(void);
void (*mips_timer_ack)(void);
-unsigned int (*mips_hpt_read)(void);
-void (*mips_hpt_init)(void) __initdata = null_hpt_init;
-unsigned int mips_hpt_mask = 0xffffffff;
/* last time when xtime and rtc are sync'ed up */
static long last_rtc_update;
@@ -276,8 +264,7 @@ static struct irqaction timer_irqaction = {
static unsigned int __init calibrate_hpt(void)
{
- u64 frequency;
- u32 hpt_start, hpt_end, hpt_count, hz;
+ cycle_t frequency, hpt_start, hpt_end, hpt_count, hz;
const int loops = HZ / 10;
int log_2_loops = 0;
@@ -303,28 +290,23 @@ static unsigned int __init calibrate_hpt(void)
* during the calculated number of periods between timer
* interrupts.
*/
- hpt_start = mips_hpt_read();
+ hpt_start = clocksource_mips.read();
do {
while (mips_timer_state());
while (!mips_timer_state());
} while (--i);
- hpt_end = mips_hpt_read();
+ hpt_end = clocksource_mips.read();
- hpt_count = (hpt_end - hpt_start) & mips_hpt_mask;
+ hpt_count = (hpt_end - hpt_start) & clocksource_mips.mask;
hz = HZ;
- frequency = (u64)hpt_count * (u64)hz;
+ frequency = hpt_count * hz;
return frequency >> log_2_loops;
}
-static cycle_t read_mips_hpt(void)
-{
- return (cycle_t)mips_hpt_read();
-}
-
-static struct clocksource clocksource_mips = {
+struct clocksource clocksource_mips = {
.name = "MIPS",
- .read = read_mips_hpt,
+ .mask = 0xffffffff,
.is_continuous = 1,
};
@@ -333,7 +315,7 @@ static void __init init_mips_clocksource(void)
u64 temp;
u32 shift;
- if (!mips_hpt_frequency || mips_hpt_read == null_hpt_read)
+ if (!mips_hpt_frequency || clocksource_mips.read == null_hpt_read)
return;
/* Calclate a somewhat reasonable rating value */
@@ -347,7 +329,6 @@ static void __init init_mips_clocksource(void)
}
clocksource_mips.shift = shift;
clocksource_mips.mult = (u32)temp;
- clocksource_mips.mask = mips_hpt_mask;
clocksource_register(&clocksource_mips);
}
@@ -367,32 +348,36 @@ void __init time_init(void)
-xtime.tv_sec, -xtime.tv_nsec);
/* Choose appropriate high precision timer routines. */
- if (!cpu_has_counter && !mips_hpt_read)
+ if (!cpu_has_counter && !clocksource_mips.read)
/* No high precision timer -- sorry. */
- mips_hpt_read = null_hpt_read;
+ clocksource_mips.read = null_hpt_read;
else if (!mips_hpt_frequency && !mips_timer_state) {
/* A high precision timer of unknown frequency. */
- if (!mips_hpt_read)
+ if (!clocksource_mips.read)
/* No external high precision timer -- use R4k. */
- mips_hpt_read = c0_hpt_read;
+ clocksource_mips.read = c0_hpt_read;
} else {
/* We know counter frequency. Or we can get it. */
- if (!mips_hpt_read) {
+ if (!clocksource_mips.read) {
/* No external high precision timer -- use R4k. */
- mips_hpt_read = c0_hpt_read;
+ clocksource_mips.read = c0_hpt_read;
if (!mips_timer_state) {
/* No external timer interrupt -- use R4k. */
- mips_hpt_init = c0_hpt_timer_init;
mips_timer_ack = c0_timer_ack;
+ /* Calculate cache parameters. */
+ cycles_per_jiffy =
+ (mips_hpt_frequency + HZ / 2) / HZ;
+ /*
+ * This sets up the high precision
+ * timer for the first interrupt.
+ */
+ c0_hpt_timer_init();
}
}
if (!mips_hpt_frequency)
mips_hpt_frequency = calibrate_hpt();
- /* Calculate cache parameters. */
- cycles_per_jiffy = (mips_hpt_frequency + HZ / 2) / HZ;
-
/* Report the high precision timer rate for a reference. */
printk("Using %u.%03u MHz high precision timer.\n",
((mips_hpt_frequency + 500) / 1000) / 1000,
@@ -403,9 +388,6 @@ void __init time_init(void)
/* No timer interrupt ack (e.g. i8254). */
mips_timer_ack = null_timer_ack;
- /* This sets up the high precision timer for the first interrupt. */
- mips_hpt_init();
-
/*
* Call board specific timer interrupt setup.
*
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
index 9fda1b8be3a..2a932cada24 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -54,6 +54,8 @@ extern asmlinkage void handle_dbe(void);
extern asmlinkage void handle_sys(void);
extern asmlinkage void handle_bp(void);
extern asmlinkage void handle_ri(void);
+extern asmlinkage void handle_ri_rdhwr_vivt(void);
+extern asmlinkage void handle_ri_rdhwr(void);
extern asmlinkage void handle_cpu(void);
extern asmlinkage void handle_ov(void);
extern asmlinkage void handle_tr(void);
@@ -397,19 +399,6 @@ asmlinkage void do_be(struct pt_regs *regs)
force_sig(SIGBUS, current);
}
-static inline int get_insn_opcode(struct pt_regs *regs, unsigned int *opcode)
-{
- unsigned int __user *epc;
-
- epc = (unsigned int __user *) regs->cp0_epc +
- ((regs->cp0_cause & CAUSEF_BD) != 0);
- if (!get_user(*opcode, epc))
- return 0;
-
- force_sig(SIGSEGV, current);
- return 1;
-}
-
/*
* ll/sc emulation
*/
@@ -544,8 +533,8 @@ static inline int simulate_llsc(struct pt_regs *regs)
{
unsigned int opcode;
- if (unlikely(get_insn_opcode(regs, &opcode)))
- return -EFAULT;
+ if (get_user(opcode, (unsigned int __user *) exception_epc(regs)))
+ goto out_sigsegv;
if ((opcode & OPCODE) == LL) {
simulate_ll(regs, opcode);
@@ -557,6 +546,10 @@ static inline int simulate_llsc(struct pt_regs *regs)
}
return -EFAULT; /* Strange things going on ... */
+
+out_sigsegv:
+ force_sig(SIGSEGV, current);
+ return -EFAULT;
}
/*
@@ -569,8 +562,8 @@ static inline int simulate_rdhwr(struct pt_regs *regs)
struct thread_info *ti = task_thread_info(current);
unsigned int opcode;
- if (unlikely(get_insn_opcode(regs, &opcode)))
- return -EFAULT;
+ if (get_user(opcode, (unsigned int __user *) exception_epc(regs)))
+ goto out_sigsegv;
if (unlikely(compute_return_epc(regs)))
return -EFAULT;
@@ -589,6 +582,10 @@ static inline int simulate_rdhwr(struct pt_regs *regs)
/* Not ours. */
return -EFAULT;
+
+out_sigsegv:
+ force_sig(SIGSEGV, current);
+ return -EFAULT;
}
asmlinkage void do_ov(struct pt_regs *regs)
@@ -672,10 +669,8 @@ asmlinkage void do_bp(struct pt_regs *regs)
unsigned int opcode, bcode;
siginfo_t info;
- die_if_kernel("Break instruction in kernel code", regs);
-
- if (get_insn_opcode(regs, &opcode))
- return;
+ if (get_user(opcode, (unsigned int __user *) exception_epc(regs)))
+ goto out_sigsegv;
/*
* There is the ancient bug in the MIPS assemblers that the break
@@ -696,6 +691,7 @@ asmlinkage void do_bp(struct pt_regs *regs)
switch (bcode) {
case BRK_OVERFLOW << 10:
case BRK_DIVZERO << 10:
+ die_if_kernel("Break instruction in kernel code", regs);
if (bcode == (BRK_DIVZERO << 10))
info.si_code = FPE_INTDIV;
else
@@ -705,9 +701,16 @@ asmlinkage void do_bp(struct pt_regs *regs)
info.si_addr = (void __user *) regs->cp0_epc;
force_sig_info(SIGFPE, &info, current);
break;
+ case BRK_BUG:
+ die("Kernel bug detected", regs);
+ break;
default:
+ die_if_kernel("Break instruction in kernel code", regs);
force_sig(SIGTRAP, current);
}
+
+out_sigsegv:
+ force_sig(SIGSEGV, current);
}
asmlinkage void do_tr(struct pt_regs *regs)
@@ -715,10 +718,8 @@ asmlinkage void do_tr(struct pt_regs *regs)
unsigned int opcode, tcode = 0;
siginfo_t info;
- die_if_kernel("Trap instruction in kernel code", regs);
-
- if (get_insn_opcode(regs, &opcode))
- return;
+ if (get_user(opcode, (unsigned int __user *) exception_epc(regs)))
+ goto out_sigsegv;
/* Immediate versions don't provide a code. */
if (!(opcode & OPCODE))
@@ -733,6 +734,7 @@ asmlinkage void do_tr(struct pt_regs *regs)
switch (tcode) {
case BRK_OVERFLOW:
case BRK_DIVZERO:
+ die_if_kernel("Trap instruction in kernel code", regs);
if (tcode == BRK_DIVZERO)
info.si_code = FPE_INTDIV;
else
@@ -742,9 +744,16 @@ asmlinkage void do_tr(struct pt_regs *regs)
info.si_addr = (void __user *) regs->cp0_epc;
force_sig_info(SIGFPE, &info, current);
break;
+ case BRK_BUG:
+ die("Kernel bug detected", regs);
+ break;
default:
+ die_if_kernel("Trap instruction in kernel code", regs);
force_sig(SIGTRAP, current);
}
+
+out_sigsegv:
+ force_sig(SIGSEGV, current);
}
asmlinkage void do_ri(struct pt_regs *regs)
@@ -1423,6 +1432,15 @@ void __init set_uncached_handler (unsigned long offset, void *addr, unsigned lon
memcpy((void *)(uncached_ebase + offset), addr, size);
}
+static int __initdata rdhwr_noopt;
+static int __init set_rdhwr_noopt(char *str)
+{
+ rdhwr_noopt = 1;
+ return 1;
+}
+
+__setup("rdhwr_noopt", set_rdhwr_noopt);
+
void __init trap_init(void)
{
extern char except_vec3_generic, except_vec3_r4000;
@@ -1502,7 +1520,9 @@ void __init trap_init(void)
set_except_vector(8, handle_sys);
set_except_vector(9, handle_bp);
- set_except_vector(10, handle_ri);
+ set_except_vector(10, rdhwr_noopt ? handle_ri :
+ (cpu_has_vtag_icache ?
+ handle_ri_rdhwr_vivt : handle_ri_rdhwr));
set_except_vector(11, handle_cpu);
set_except_vector(12, handle_ov);
set_except_vector(13, handle_tr);
diff --git a/arch/mips/kernel/vmlinux.lds.S b/arch/mips/kernel/vmlinux.lds.S
index 79f0317d84a..cecff24cc97 100644
--- a/arch/mips/kernel/vmlinux.lds.S
+++ b/arch/mips/kernel/vmlinux.lds.S
@@ -112,6 +112,7 @@ SECTIONS
/* .exit.text is discarded at runtime, not link time, to deal with
references from .rodata */
.exit.text : { *(.exit.text) }
+ .exit.data : { *(.exit.data) }
. = ALIGN(_PAGE_SIZE);
__initramfs_start = .;
.init.ramfs : { *(.init.ramfs) }
@@ -139,7 +140,6 @@ SECTIONS
/* Sections to be discarded */
/DISCARD/ : {
- *(.exit.data)
*(.exitcall.exit)
/* ABI crap starts here */
diff --git a/arch/mips/kernel/vpe.c b/arch/mips/kernel/vpe.c
index 51ddd216689..666bef484dc 100644
--- a/arch/mips/kernel/vpe.c
+++ b/arch/mips/kernel/vpe.c
@@ -1179,7 +1179,7 @@ static ssize_t vpe_write(struct file *file, const char __user * buffer,
size_t ret = count;
struct vpe *v;
- minor = iminor(file->f_dentry->d_inode);
+ minor = iminor(file->f_path.dentry->d_inode);
if ((v = get_vpe(minor)) == NULL)
return -ENODEV;