aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'arch/mips/kernel')
-rw-r--r--arch/mips/kernel/Makefile10
-rw-r--r--arch/mips/kernel/cevt-gic.c105
-rw-r--r--arch/mips/kernel/cevt-r4k.c6
-rw-r--r--arch/mips/kernel/cpu-probe.c71
-rw-r--r--arch/mips/kernel/crash_dump.c4
-rw-r--r--arch/mips/kernel/csrc-gic.c40
-rw-r--r--arch/mips/kernel/elf.c191
-rw-r--r--arch/mips/kernel/i8259.c24
-rw-r--r--arch/mips/kernel/irq-gic.c402
-rw-r--r--arch/mips/kernel/irq_cpu.c48
-rw-r--r--arch/mips/kernel/mips-cm.c12
-rw-r--r--arch/mips/kernel/mips-cpc.c4
-rw-r--r--arch/mips/kernel/mips_ksyms.c4
-rw-r--r--arch/mips/kernel/perf_event_mipsxx.c30
-rw-r--r--arch/mips/kernel/process.c54
-rw-r--r--arch/mips/kernel/prom.c18
-rw-r--r--arch/mips/kernel/setup.c14
-rw-r--r--arch/mips/kernel/signal.c2
-rw-r--r--arch/mips/kernel/smp-bmips.c114
-rw-r--r--arch/mips/kernel/smp-cmp.c2
-rw-r--r--arch/mips/kernel/smp-cps.c6
-rw-r--r--arch/mips/kernel/smp-gic.c2
-rw-r--r--arch/mips/kernel/smp-mt.c6
-rw-r--r--arch/mips/kernel/syscall.c2
-rw-r--r--arch/mips/kernel/traps.c66
-rw-r--r--arch/mips/kernel/vdso.c15
26 files changed, 551 insertions, 701 deletions
diff --git a/arch/mips/kernel/Makefile b/arch/mips/kernel/Makefile
index 008a2fed0584..92987d1bbe5f 100644
--- a/arch/mips/kernel/Makefile
+++ b/arch/mips/kernel/Makefile
@@ -4,9 +4,10 @@
4 4
5extra-y := head.o vmlinux.lds 5extra-y := head.o vmlinux.lds
6 6
7obj-y += cpu-probe.o branch.o entry.o genex.o idle.o irq.o process.o \ 7obj-y += cpu-probe.o branch.o elf.o entry.o genex.o idle.o irq.o \
8 prom.o ptrace.o reset.o setup.o signal.o syscall.o \ 8 process.o prom.o ptrace.o reset.o setup.o signal.o \
9 time.o topology.o traps.o unaligned.o watch.o vdso.o 9 syscall.o time.o topology.o traps.o unaligned.o watch.o \
10 vdso.o
10 11
11ifdef CONFIG_FUNCTION_TRACER 12ifdef CONFIG_FUNCTION_TRACER
12CFLAGS_REMOVE_ftrace.o = -pg 13CFLAGS_REMOVE_ftrace.o = -pg
@@ -18,12 +19,10 @@ endif
18obj-$(CONFIG_CEVT_BCM1480) += cevt-bcm1480.o 19obj-$(CONFIG_CEVT_BCM1480) += cevt-bcm1480.o
19obj-$(CONFIG_CEVT_R4K) += cevt-r4k.o 20obj-$(CONFIG_CEVT_R4K) += cevt-r4k.o
20obj-$(CONFIG_CEVT_DS1287) += cevt-ds1287.o 21obj-$(CONFIG_CEVT_DS1287) += cevt-ds1287.o
21obj-$(CONFIG_CEVT_GIC) += cevt-gic.o
22obj-$(CONFIG_CEVT_GT641XX) += cevt-gt641xx.o 22obj-$(CONFIG_CEVT_GT641XX) += cevt-gt641xx.o
23obj-$(CONFIG_CEVT_SB1250) += cevt-sb1250.o 23obj-$(CONFIG_CEVT_SB1250) += cevt-sb1250.o
24obj-$(CONFIG_CEVT_TXX9) += cevt-txx9.o 24obj-$(CONFIG_CEVT_TXX9) += cevt-txx9.o
25obj-$(CONFIG_CSRC_BCM1480) += csrc-bcm1480.o 25obj-$(CONFIG_CSRC_BCM1480) += csrc-bcm1480.o
26obj-$(CONFIG_CSRC_GIC) += csrc-gic.o
27obj-$(CONFIG_CSRC_IOASIC) += csrc-ioasic.o 26obj-$(CONFIG_CSRC_IOASIC) += csrc-ioasic.o
28obj-$(CONFIG_CSRC_R4K) += csrc-r4k.o 27obj-$(CONFIG_CSRC_R4K) += csrc-r4k.o
29obj-$(CONFIG_CSRC_SB1250) += csrc-sb1250.o 28obj-$(CONFIG_CSRC_SB1250) += csrc-sb1250.o
@@ -68,7 +67,6 @@ obj-$(CONFIG_IRQ_CPU_RM7K) += irq-rm7000.o
68obj-$(CONFIG_MIPS_MSC) += irq-msc01.o 67obj-$(CONFIG_MIPS_MSC) += irq-msc01.o
69obj-$(CONFIG_IRQ_TXX9) += irq_txx9.o 68obj-$(CONFIG_IRQ_TXX9) += irq_txx9.o
70obj-$(CONFIG_IRQ_GT641XX) += irq-gt641xx.o 69obj-$(CONFIG_IRQ_GT641XX) += irq-gt641xx.o
71obj-$(CONFIG_IRQ_GIC) += irq-gic.o
72 70
73obj-$(CONFIG_KPROBES) += kprobes.o 71obj-$(CONFIG_KPROBES) += kprobes.o
74obj-$(CONFIG_32BIT) += scall32-o32.o 72obj-$(CONFIG_32BIT) += scall32-o32.o
diff --git a/arch/mips/kernel/cevt-gic.c b/arch/mips/kernel/cevt-gic.c
deleted file mode 100644
index 6093716980b9..000000000000
--- a/arch/mips/kernel/cevt-gic.c
+++ /dev/null
@@ -1,105 +0,0 @@
1/*
2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
4 * for more details.
5 *
6 * Copyright (C) 2013 Imagination Technologies Ltd.
7 */
8#include <linux/clockchips.h>
9#include <linux/interrupt.h>
10#include <linux/percpu.h>
11#include <linux/smp.h>
12#include <linux/irq.h>
13
14#include <asm/time.h>
15#include <asm/gic.h>
16#include <asm/mips-boards/maltaint.h>
17
18DEFINE_PER_CPU(struct clock_event_device, gic_clockevent_device);
19int gic_timer_irq_installed;
20
21
22static int gic_next_event(unsigned long delta, struct clock_event_device *evt)
23{
24 u64 cnt;
25 int res;
26
27 cnt = gic_read_count();
28 cnt += (u64)delta;
29 gic_write_cpu_compare(cnt, cpumask_first(evt->cpumask));
30 res = ((int)(gic_read_count() - cnt) >= 0) ? -ETIME : 0;
31 return res;
32}
33
34void gic_set_clock_mode(enum clock_event_mode mode,
35 struct clock_event_device *evt)
36{
37 /* Nothing to do ... */
38}
39
40irqreturn_t gic_compare_interrupt(int irq, void *dev_id)
41{
42 struct clock_event_device *cd;
43 int cpu = smp_processor_id();
44
45 gic_write_compare(gic_read_compare());
46 cd = &per_cpu(gic_clockevent_device, cpu);
47 cd->event_handler(cd);
48 return IRQ_HANDLED;
49}
50
51struct irqaction gic_compare_irqaction = {
52 .handler = gic_compare_interrupt,
53 .flags = IRQF_PERCPU | IRQF_TIMER,
54 .name = "timer",
55};
56
57
58void gic_event_handler(struct clock_event_device *dev)
59{
60}
61
62int gic_clockevent_init(void)
63{
64 unsigned int cpu = smp_processor_id();
65 struct clock_event_device *cd;
66 unsigned int irq;
67
68 if (!cpu_has_counter || !gic_frequency)
69 return -ENXIO;
70
71 irq = MIPS_GIC_IRQ_BASE;
72
73 cd = &per_cpu(gic_clockevent_device, cpu);
74
75 cd->name = "MIPS GIC";
76 cd->features = CLOCK_EVT_FEAT_ONESHOT |
77 CLOCK_EVT_FEAT_C3STOP;
78
79 clockevent_set_clock(cd, gic_frequency);
80
81 /* Calculate the min / max delta */
82 cd->max_delta_ns = clockevent_delta2ns(0x7fffffff, cd);
83 cd->min_delta_ns = clockevent_delta2ns(0x300, cd);
84
85 cd->rating = 300;
86 cd->irq = irq;
87 cd->cpumask = cpumask_of(cpu);
88 cd->set_next_event = gic_next_event;
89 cd->set_mode = gic_set_clock_mode;
90 cd->event_handler = gic_event_handler;
91
92 clockevents_register_device(cd);
93
94 GICWRITE(GIC_REG(VPE_LOCAL, GIC_VPE_COMPARE_MAP), 0x80000002);
95 GICWRITE(GIC_REG(VPE_LOCAL, GIC_VPE_SMASK), GIC_VPE_SMASK_CMP_MSK);
96
97 if (gic_timer_irq_installed)
98 return 0;
99
100 gic_timer_irq_installed = 1;
101
102 setup_irq(irq, &gic_compare_irqaction);
103 irq_set_handler(irq, handle_percpu_irq);
104 return 0;
105}
diff --git a/arch/mips/kernel/cevt-r4k.c b/arch/mips/kernel/cevt-r4k.c
index bc127e22fdab..6acaad0480af 100644
--- a/arch/mips/kernel/cevt-r4k.c
+++ b/arch/mips/kernel/cevt-r4k.c
@@ -11,10 +11,10 @@
11#include <linux/percpu.h> 11#include <linux/percpu.h>
12#include <linux/smp.h> 12#include <linux/smp.h>
13#include <linux/irq.h> 13#include <linux/irq.h>
14#include <linux/irqchip/mips-gic.h>
14 15
15#include <asm/time.h> 16#include <asm/time.h>
16#include <asm/cevt-r4k.h> 17#include <asm/cevt-r4k.h>
17#include <asm/gic.h>
18 18
19static int mips_next_event(unsigned long delta, 19static int mips_next_event(unsigned long delta,
20 struct clock_event_device *evt) 20 struct clock_event_device *evt)
@@ -85,8 +85,8 @@ void mips_event_handler(struct clock_event_device *dev)
85 */ 85 */
86static int c0_compare_int_pending(void) 86static int c0_compare_int_pending(void)
87{ 87{
88#ifdef CONFIG_IRQ_GIC 88#ifdef CONFIG_MIPS_GIC
89 if (cpu_has_veic) 89 if (gic_present)
90 return gic_get_timer_pending(); 90 return gic_get_timer_pending();
91#endif 91#endif
92 return (read_c0_cause() >> cp0_compare_irq_shift) & (1ul << CAUSEB_IP); 92 return (read_c0_cause() >> cp0_compare_irq_shift) & (1ul << CAUSEB_IP);
diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c
index dc49cf30c2db..5342674842f5 100644
--- a/arch/mips/kernel/cpu-probe.c
+++ b/arch/mips/kernel/cpu-probe.c
@@ -69,6 +69,63 @@ static int __init htw_disable(char *s)
69 69
70__setup("nohtw", htw_disable); 70__setup("nohtw", htw_disable);
71 71
72static int mips_ftlb_disabled;
73static int mips_has_ftlb_configured;
74
75static void set_ftlb_enable(struct cpuinfo_mips *c, int enable);
76
77static int __init ftlb_disable(char *s)
78{
79 unsigned int config4, mmuextdef;
80
81 /*
82 * If the core hasn't done any FTLB configuration, there is nothing
83 * for us to do here.
84 */
85 if (!mips_has_ftlb_configured)
86 return 1;
87
88 /* Disable it in the boot cpu */
89 set_ftlb_enable(&cpu_data[0], 0);
90
91 back_to_back_c0_hazard();
92
93 config4 = read_c0_config4();
94
95 /* Check that FTLB has been disabled */
96 mmuextdef = config4 & MIPS_CONF4_MMUEXTDEF;
97 /* MMUSIZEEXT == VTLB ON, FTLB OFF */
98 if (mmuextdef == MIPS_CONF4_MMUEXTDEF_FTLBSIZEEXT) {
99 /* This should never happen */
100 pr_warn("FTLB could not be disabled!\n");
101 return 1;
102 }
103
104 mips_ftlb_disabled = 1;
105 mips_has_ftlb_configured = 0;
106
107 /*
108 * noftlb is mainly used for debug purposes so print
109 * an informative message instead of using pr_debug()
110 */
111 pr_info("FTLB has been disabled\n");
112
113 /*
114 * Some of these bits are duplicated in the decode_config4.
115 * MIPS_CONF4_MMUEXTDEF_MMUSIZEEXT is the only possible case
116 * once FTLB has been disabled so undo what decode_config4 did.
117 */
118 cpu_data[0].tlbsize -= cpu_data[0].tlbsizeftlbways *
119 cpu_data[0].tlbsizeftlbsets;
120 cpu_data[0].tlbsizeftlbsets = 0;
121 cpu_data[0].tlbsizeftlbways = 0;
122
123 return 1;
124}
125
126__setup("noftlb", ftlb_disable);
127
128
72static inline void check_errata(void) 129static inline void check_errata(void)
73{ 130{
74 struct cpuinfo_mips *c = &current_cpu_data; 131 struct cpuinfo_mips *c = &current_cpu_data;
@@ -140,7 +197,7 @@ static inline unsigned long cpu_get_fpu_id(void)
140 */ 197 */
141static inline int __cpu_has_fpu(void) 198static inline int __cpu_has_fpu(void)
142{ 199{
143 return ((cpu_get_fpu_id() & FPIR_IMP_MASK) != FPIR_IMP_NONE); 200 return (cpu_get_fpu_id() & FPIR_IMP_MASK) != FPIR_IMP_NONE;
144} 201}
145 202
146static inline unsigned long cpu_get_msa_id(void) 203static inline unsigned long cpu_get_msa_id(void)
@@ -399,6 +456,8 @@ static inline unsigned int decode_config4(struct cpuinfo_mips *c)
399 ftlb_page = MIPS_CONF4_VFTLBPAGESIZE; 456 ftlb_page = MIPS_CONF4_VFTLBPAGESIZE;
400 /* fall through */ 457 /* fall through */
401 case MIPS_CONF4_MMUEXTDEF_FTLBSIZEEXT: 458 case MIPS_CONF4_MMUEXTDEF_FTLBSIZEEXT:
459 if (mips_ftlb_disabled)
460 break;
402 newcf4 = (config4 & ~ftlb_page) | 461 newcf4 = (config4 & ~ftlb_page) |
403 (page_size_ftlb(mmuextdef) << 462 (page_size_ftlb(mmuextdef) <<
404 MIPS_CONF4_FTLBPAGESIZE_SHIFT); 463 MIPS_CONF4_FTLBPAGESIZE_SHIFT);
@@ -418,6 +477,7 @@ static inline unsigned int decode_config4(struct cpuinfo_mips *c)
418 c->tlbsizeftlbways = ((config4 & MIPS_CONF4_FTLBWAYS) >> 477 c->tlbsizeftlbways = ((config4 & MIPS_CONF4_FTLBWAYS) >>
419 MIPS_CONF4_FTLBWAYS_SHIFT) + 2; 478 MIPS_CONF4_FTLBWAYS_SHIFT) + 2;
420 c->tlbsize += c->tlbsizeftlbways * c->tlbsizeftlbsets; 479 c->tlbsize += c->tlbsizeftlbways * c->tlbsizeftlbsets;
480 mips_has_ftlb_configured = 1;
421 break; 481 break;
422 } 482 }
423 } 483 }
@@ -432,7 +492,7 @@ static inline unsigned int decode_config5(struct cpuinfo_mips *c)
432 unsigned int config5; 492 unsigned int config5;
433 493
434 config5 = read_c0_config5(); 494 config5 = read_c0_config5();
435 config5 &= ~MIPS_CONF5_UFR; 495 config5 &= ~(MIPS_CONF5_UFR | MIPS_CONF5_UFE);
436 write_c0_config5(config5); 496 write_c0_config5(config5);
437 497
438 if (config5 & MIPS_CONF5_EVA) 498 if (config5 & MIPS_CONF5_EVA)
@@ -453,8 +513,8 @@ static void decode_configs(struct cpuinfo_mips *c)
453 513
454 c->scache.flags = MIPS_CACHE_NOT_PRESENT; 514 c->scache.flags = MIPS_CACHE_NOT_PRESENT;
455 515
456 /* Enable FTLB if present */ 516 /* Enable FTLB if present and not disabled */
457 set_ftlb_enable(c, 1); 517 set_ftlb_enable(c, !mips_ftlb_disabled);
458 518
459 ok = decode_config0(c); /* Read Config registers. */ 519 ok = decode_config0(c); /* Read Config registers. */
460 BUG_ON(!ok); /* Arch spec violation! */ 520 BUG_ON(!ok); /* Arch spec violation! */
@@ -1058,6 +1118,7 @@ static inline void cpu_probe_broadcom(struct cpuinfo_mips *c, unsigned int cpu)
1058 break; 1118 break;
1059 } 1119 }
1060 case PRID_IMP_BMIPS5000: 1120 case PRID_IMP_BMIPS5000:
1121 case PRID_IMP_BMIPS5200:
1061 c->cputype = CPU_BMIPS5000; 1122 c->cputype = CPU_BMIPS5000;
1062 __cpu_name[cpu] = "Broadcom BMIPS5000"; 1123 __cpu_name[cpu] = "Broadcom BMIPS5000";
1063 set_elf_platform(cpu, "bmips5000"); 1124 set_elf_platform(cpu, "bmips5000");
@@ -1288,6 +1349,8 @@ void cpu_probe(void)
1288 MIPS_CPU_ISA_M64R1 | MIPS_CPU_ISA_M64R2)) { 1349 MIPS_CPU_ISA_M64R1 | MIPS_CPU_ISA_M64R2)) {
1289 if (c->fpu_id & MIPS_FPIR_3D) 1350 if (c->fpu_id & MIPS_FPIR_3D)
1290 c->ases |= MIPS_ASE_MIPS3D; 1351 c->ases |= MIPS_ASE_MIPS3D;
1352 if (c->fpu_id & MIPS_FPIR_FREP)
1353 c->options |= MIPS_CPU_FRE;
1291 } 1354 }
1292 } 1355 }
1293 1356
diff --git a/arch/mips/kernel/crash_dump.c b/arch/mips/kernel/crash_dump.c
index f291cf99b03a..6fe7790e5868 100644
--- a/arch/mips/kernel/crash_dump.c
+++ b/arch/mips/kernel/crash_dump.c
@@ -38,7 +38,7 @@ ssize_t copy_oldmem_page(unsigned long pfn, char *buf,
38 kunmap_atomic(vaddr); 38 kunmap_atomic(vaddr);
39 } else { 39 } else {
40 if (!kdump_buf_page) { 40 if (!kdump_buf_page) {
41 pr_warning("Kdump: Kdump buffer page not allocated\n"); 41 pr_warn("Kdump: Kdump buffer page not allocated\n");
42 42
43 return -EFAULT; 43 return -EFAULT;
44 } 44 }
@@ -57,7 +57,7 @@ static int __init kdump_buf_page_init(void)
57 57
58 kdump_buf_page = kmalloc(PAGE_SIZE, GFP_KERNEL); 58 kdump_buf_page = kmalloc(PAGE_SIZE, GFP_KERNEL);
59 if (!kdump_buf_page) { 59 if (!kdump_buf_page) {
60 pr_warning("Kdump: Failed to allocate kdump buffer page\n"); 60 pr_warn("Kdump: Failed to allocate kdump buffer page\n");
61 ret = -ENOMEM; 61 ret = -ENOMEM;
62 } 62 }
63 63
diff --git a/arch/mips/kernel/csrc-gic.c b/arch/mips/kernel/csrc-gic.c
deleted file mode 100644
index e02620901117..000000000000
--- a/arch/mips/kernel/csrc-gic.c
+++ /dev/null
@@ -1,40 +0,0 @@
1/*
2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
4 * for more details.
5 *
6 * Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved.
7 */
8#include <linux/init.h>
9#include <linux/time.h>
10
11#include <asm/gic.h>
12
13static cycle_t gic_hpt_read(struct clocksource *cs)
14{
15 return gic_read_count();
16}
17
18static struct clocksource gic_clocksource = {
19 .name = "GIC",
20 .read = gic_hpt_read,
21 .flags = CLOCK_SOURCE_IS_CONTINUOUS,
22};
23
24void __init gic_clocksource_init(unsigned int frequency)
25{
26 unsigned int config, bits;
27
28 /* Calculate the clocksource mask. */
29 GICREAD(GIC_REG(SHARED, GIC_SH_CONFIG), config);
30 bits = 32 + ((config & GIC_SH_CONFIG_COUNTBITS_MSK) >>
31 (GIC_SH_CONFIG_COUNTBITS_SHF - 2));
32
33 /* Set clocksource mask. */
34 gic_clocksource.mask = CLOCKSOURCE_MASK(bits);
35
36 /* Calculate a somewhat reasonable rating value. */
37 gic_clocksource.rating = 200 + frequency / 10000000;
38
39 clocksource_register_hz(&gic_clocksource, frequency);
40}
diff --git a/arch/mips/kernel/elf.c b/arch/mips/kernel/elf.c
new file mode 100644
index 000000000000..c92b15df6893
--- /dev/null
+++ b/arch/mips/kernel/elf.c
@@ -0,0 +1,191 @@
1/*
2 * Copyright (C) 2014 Imagination Technologies
3 * Author: Paul Burton <paul.burton@imgtec.com>
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version.
9 */
10
11#include <linux/elf.h>
12#include <linux/sched.h>
13
14enum {
15 FP_ERROR = -1,
16 FP_DOUBLE_64A = -2,
17};
18
19int arch_elf_pt_proc(void *_ehdr, void *_phdr, struct file *elf,
20 bool is_interp, struct arch_elf_state *state)
21{
22 struct elfhdr *ehdr = _ehdr;
23 struct elf_phdr *phdr = _phdr;
24 struct mips_elf_abiflags_v0 abiflags;
25 int ret;
26
27 if (config_enabled(CONFIG_64BIT) &&
28 (ehdr->e_ident[EI_CLASS] != ELFCLASS32))
29 return 0;
30 if (phdr->p_type != PT_MIPS_ABIFLAGS)
31 return 0;
32 if (phdr->p_filesz < sizeof(abiflags))
33 return -EINVAL;
34
35 ret = kernel_read(elf, phdr->p_offset, (char *)&abiflags,
36 sizeof(abiflags));
37 if (ret < 0)
38 return ret;
39 if (ret != sizeof(abiflags))
40 return -EIO;
41
42 /* Record the required FP ABIs for use by mips_check_elf */
43 if (is_interp)
44 state->interp_fp_abi = abiflags.fp_abi;
45 else
46 state->fp_abi = abiflags.fp_abi;
47
48 return 0;
49}
50
51static inline unsigned get_fp_abi(struct elfhdr *ehdr, int in_abi)
52{
53 /* If the ABI requirement is provided, simply return that */
54 if (in_abi != -1)
55 return in_abi;
56
57 /* If the EF_MIPS_FP64 flag was set, return MIPS_ABI_FP_64 */
58 if (ehdr->e_flags & EF_MIPS_FP64)
59 return MIPS_ABI_FP_64;
60
61 /* Default to MIPS_ABI_FP_DOUBLE */
62 return MIPS_ABI_FP_DOUBLE;
63}
64
65int arch_check_elf(void *_ehdr, bool has_interpreter,
66 struct arch_elf_state *state)
67{
68 struct elfhdr *ehdr = _ehdr;
69 unsigned fp_abi, interp_fp_abi, abi0, abi1;
70
71 /* Ignore non-O32 binaries */
72 if (config_enabled(CONFIG_64BIT) &&
73 (ehdr->e_ident[EI_CLASS] != ELFCLASS32))
74 return 0;
75
76 fp_abi = get_fp_abi(ehdr, state->fp_abi);
77
78 if (has_interpreter) {
79 interp_fp_abi = get_fp_abi(ehdr, state->interp_fp_abi);
80
81 abi0 = min(fp_abi, interp_fp_abi);
82 abi1 = max(fp_abi, interp_fp_abi);
83 } else {
84 abi0 = abi1 = fp_abi;
85 }
86
87 state->overall_abi = FP_ERROR;
88
89 if (abi0 == abi1) {
90 state->overall_abi = abi0;
91 } else if (abi0 == MIPS_ABI_FP_ANY) {
92 state->overall_abi = abi1;
93 } else if (abi0 == MIPS_ABI_FP_DOUBLE) {
94 switch (abi1) {
95 case MIPS_ABI_FP_XX:
96 state->overall_abi = MIPS_ABI_FP_DOUBLE;
97 break;
98
99 case MIPS_ABI_FP_64A:
100 state->overall_abi = FP_DOUBLE_64A;
101 break;
102 }
103 } else if (abi0 == MIPS_ABI_FP_SINGLE ||
104 abi0 == MIPS_ABI_FP_SOFT) {
105 /* Cannot link with other ABIs */
106 } else if (abi0 == MIPS_ABI_FP_OLD_64) {
107 switch (abi1) {
108 case MIPS_ABI_FP_XX:
109 case MIPS_ABI_FP_64:
110 case MIPS_ABI_FP_64A:
111 state->overall_abi = MIPS_ABI_FP_64;
112 break;
113 }
114 } else if (abi0 == MIPS_ABI_FP_XX ||
115 abi0 == MIPS_ABI_FP_64 ||
116 abi0 == MIPS_ABI_FP_64A) {
117 state->overall_abi = MIPS_ABI_FP_64;
118 }
119
120 switch (state->overall_abi) {
121 case MIPS_ABI_FP_64:
122 case MIPS_ABI_FP_64A:
123 case FP_DOUBLE_64A:
124 if (!config_enabled(CONFIG_MIPS_O32_FP64_SUPPORT))
125 return -ELIBBAD;
126 break;
127
128 case FP_ERROR:
129 return -ELIBBAD;
130 }
131
132 return 0;
133}
134
135void mips_set_personality_fp(struct arch_elf_state *state)
136{
137 if (config_enabled(CONFIG_FP32XX_HYBRID_FPRS)) {
138 /*
139 * Use hybrid FPRs for all code which can correctly execute
140 * with that mode.
141 */
142 switch (state->overall_abi) {
143 case MIPS_ABI_FP_DOUBLE:
144 case MIPS_ABI_FP_SINGLE:
145 case MIPS_ABI_FP_SOFT:
146 case MIPS_ABI_FP_XX:
147 case MIPS_ABI_FP_ANY:
148 /* FR=1, FRE=1 */
149 clear_thread_flag(TIF_32BIT_FPREGS);
150 set_thread_flag(TIF_HYBRID_FPREGS);
151 return;
152 }
153 }
154
155 switch (state->overall_abi) {
156 case MIPS_ABI_FP_DOUBLE:
157 case MIPS_ABI_FP_SINGLE:
158 case MIPS_ABI_FP_SOFT:
159 /* FR=0 */
160 set_thread_flag(TIF_32BIT_FPREGS);
161 clear_thread_flag(TIF_HYBRID_FPREGS);
162 break;
163
164 case FP_DOUBLE_64A:
165 /* FR=1, FRE=1 */
166 clear_thread_flag(TIF_32BIT_FPREGS);
167 set_thread_flag(TIF_HYBRID_FPREGS);
168 break;
169
170 case MIPS_ABI_FP_64:
171 case MIPS_ABI_FP_64A:
172 /* FR=1, FRE=0 */
173 clear_thread_flag(TIF_32BIT_FPREGS);
174 clear_thread_flag(TIF_HYBRID_FPREGS);
175 break;
176
177 case MIPS_ABI_FP_XX:
178 case MIPS_ABI_FP_ANY:
179 if (!config_enabled(CONFIG_MIPS_O32_FP64_SUPPORT))
180 set_thread_flag(TIF_32BIT_FPREGS);
181 else
182 clear_thread_flag(TIF_32BIT_FPREGS);
183
184 clear_thread_flag(TIF_HYBRID_FPREGS);
185 break;
186
187 default:
188 case FP_ERROR:
189 BUG();
190 }
191}
diff --git a/arch/mips/kernel/i8259.c b/arch/mips/kernel/i8259.c
index 50b364897dda..a74ec3ae557c 100644
--- a/arch/mips/kernel/i8259.c
+++ b/arch/mips/kernel/i8259.c
@@ -12,6 +12,7 @@
12#include <linux/init.h> 12#include <linux/init.h>
13#include <linux/ioport.h> 13#include <linux/ioport.h>
14#include <linux/interrupt.h> 14#include <linux/interrupt.h>
15#include <linux/irqdomain.h>
15#include <linux/kernel.h> 16#include <linux/kernel.h>
16#include <linux/spinlock.h> 17#include <linux/spinlock.h>
17#include <linux/syscore_ops.h> 18#include <linux/syscore_ops.h>
@@ -308,6 +309,19 @@ static struct resource pic2_io_resource = {
308 .flags = IORESOURCE_BUSY 309 .flags = IORESOURCE_BUSY
309}; 310};
310 311
312static int i8259A_irq_domain_map(struct irq_domain *d, unsigned int virq,
313 irq_hw_number_t hw)
314{
315 irq_set_chip_and_handler(virq, &i8259A_chip, handle_level_irq);
316 irq_set_probe(virq);
317 return 0;
318}
319
320static struct irq_domain_ops i8259A_ops = {
321 .map = i8259A_irq_domain_map,
322 .xlate = irq_domain_xlate_onecell,
323};
324
311/* 325/*
312 * On systems with i8259-style interrupt controllers we assume for 326 * On systems with i8259-style interrupt controllers we assume for
313 * driver compatibility reasons interrupts 0 - 15 to be the i8259 327 * driver compatibility reasons interrupts 0 - 15 to be the i8259
@@ -315,17 +329,17 @@ static struct resource pic2_io_resource = {
315 */ 329 */
316void __init init_i8259_irqs(void) 330void __init init_i8259_irqs(void)
317{ 331{
318 int i; 332 struct irq_domain *domain;
319 333
320 insert_resource(&ioport_resource, &pic1_io_resource); 334 insert_resource(&ioport_resource, &pic1_io_resource);
321 insert_resource(&ioport_resource, &pic2_io_resource); 335 insert_resource(&ioport_resource, &pic2_io_resource);
322 336
323 init_8259A(0); 337 init_8259A(0);
324 338
325 for (i = I8259A_IRQ_BASE; i < I8259A_IRQ_BASE + 16; i++) { 339 domain = irq_domain_add_legacy(NULL, 16, I8259A_IRQ_BASE, 0,
326 irq_set_chip_and_handler(i, &i8259A_chip, handle_level_irq); 340 &i8259A_ops, NULL);
327 irq_set_probe(i); 341 if (!domain)
328 } 342 panic("Failed to add i8259 IRQ domain");
329 343
330 setup_irq(I8259A_IRQ_BASE + PIC_CASCADE_IR, &irq2); 344 setup_irq(I8259A_IRQ_BASE + PIC_CASCADE_IR, &irq2);
331} 345}
diff --git a/arch/mips/kernel/irq-gic.c b/arch/mips/kernel/irq-gic.c
deleted file mode 100644
index 9e9d8b9a5b97..000000000000
--- a/arch/mips/kernel/irq-gic.c
+++ /dev/null
@@ -1,402 +0,0 @@
1/*
2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
4 * for more details.
5 *
6 * Copyright (C) 2008 Ralf Baechle (ralf@linux-mips.org)
7 * Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved.
8 */
9#include <linux/bitmap.h>
10#include <linux/init.h>
11#include <linux/smp.h>
12#include <linux/irq.h>
13#include <linux/clocksource.h>
14
15#include <asm/io.h>
16#include <asm/gic.h>
17#include <asm/setup.h>
18#include <asm/traps.h>
19#include <linux/hardirq.h>
20#include <asm-generic/bitops/find.h>
21
22unsigned int gic_frequency;
23unsigned int gic_present;
24unsigned long _gic_base;
25unsigned int gic_irq_base;
26unsigned int gic_irq_flags[GIC_NUM_INTRS];
27
28/* The index into this array is the vector # of the interrupt. */
29struct gic_shared_intr_map gic_shared_intr_map[GIC_NUM_INTRS];
30
31struct gic_pcpu_mask {
32 DECLARE_BITMAP(pcpu_mask, GIC_NUM_INTRS);
33};
34
35struct gic_pending_regs {
36 DECLARE_BITMAP(pending, GIC_NUM_INTRS);
37};
38
39struct gic_intrmask_regs {
40 DECLARE_BITMAP(intrmask, GIC_NUM_INTRS);
41};
42
43static struct gic_pcpu_mask pcpu_masks[NR_CPUS];
44static struct gic_pending_regs pending_regs[NR_CPUS];
45static struct gic_intrmask_regs intrmask_regs[NR_CPUS];
46
47#if defined(CONFIG_CSRC_GIC) || defined(CONFIG_CEVT_GIC)
48cycle_t gic_read_count(void)
49{
50 unsigned int hi, hi2, lo;
51
52 do {
53 GICREAD(GIC_REG(SHARED, GIC_SH_COUNTER_63_32), hi);
54 GICREAD(GIC_REG(SHARED, GIC_SH_COUNTER_31_00), lo);
55 GICREAD(GIC_REG(SHARED, GIC_SH_COUNTER_63_32), hi2);
56 } while (hi2 != hi);
57
58 return (((cycle_t) hi) << 32) + lo;
59}
60
61void gic_write_compare(cycle_t cnt)
62{
63 GICWRITE(GIC_REG(VPE_LOCAL, GIC_VPE_COMPARE_HI),
64 (int)(cnt >> 32));
65 GICWRITE(GIC_REG(VPE_LOCAL, GIC_VPE_COMPARE_LO),
66 (int)(cnt & 0xffffffff));
67}
68
69void gic_write_cpu_compare(cycle_t cnt, int cpu)
70{
71 unsigned long flags;
72
73 local_irq_save(flags);
74
75 GICWRITE(GIC_REG(VPE_LOCAL, GIC_VPE_OTHER_ADDR), cpu);
76 GICWRITE(GIC_REG(VPE_OTHER, GIC_VPE_COMPARE_HI),
77 (int)(cnt >> 32));
78 GICWRITE(GIC_REG(VPE_OTHER, GIC_VPE_COMPARE_LO),
79 (int)(cnt & 0xffffffff));
80
81 local_irq_restore(flags);
82}
83
84cycle_t gic_read_compare(void)
85{
86 unsigned int hi, lo;
87
88 GICREAD(GIC_REG(VPE_LOCAL, GIC_VPE_COMPARE_HI), hi);
89 GICREAD(GIC_REG(VPE_LOCAL, GIC_VPE_COMPARE_LO), lo);
90
91 return (((cycle_t) hi) << 32) + lo;
92}
93#endif
94
95unsigned int gic_get_timer_pending(void)
96{
97 unsigned int vpe_pending;
98
99 GICWRITE(GIC_REG(VPE_LOCAL, GIC_VPE_OTHER_ADDR), 0);
100 GICREAD(GIC_REG(VPE_OTHER, GIC_VPE_PEND), vpe_pending);
101 return (vpe_pending & GIC_VPE_PEND_TIMER_MSK);
102}
103
104void gic_bind_eic_interrupt(int irq, int set)
105{
106 /* Convert irq vector # to hw int # */
107 irq -= GIC_PIN_TO_VEC_OFFSET;
108
109 /* Set irq to use shadow set */
110 GICWRITE(GIC_REG_ADDR(VPE_LOCAL, GIC_VPE_EIC_SS(irq)), set);
111}
112
113void gic_send_ipi(unsigned int intr)
114{
115 GICWRITE(GIC_REG(SHARED, GIC_SH_WEDGE), 0x80000000 | intr);
116}
117
118static void gic_eic_irq_dispatch(void)
119{
120 unsigned int cause = read_c0_cause();
121 int irq;
122
123 irq = (cause & ST0_IM) >> STATUSB_IP2;
124 if (irq == 0)
125 irq = -1;
126
127 if (irq >= 0)
128 do_IRQ(gic_irq_base + irq);
129 else
130 spurious_interrupt();
131}
132
133static void __init vpe_local_setup(unsigned int numvpes)
134{
135 unsigned long timer_intr = GIC_INT_TMR;
136 unsigned long perf_intr = GIC_INT_PERFCTR;
137 unsigned int vpe_ctl;
138 int i;
139
140 if (cpu_has_veic) {
141 /*
142 * GIC timer interrupt -> CPU HW Int X (vector X+2) ->
143 * map to pin X+2-1 (since GIC adds 1)
144 */
145 timer_intr += (GIC_CPU_TO_VEC_OFFSET - GIC_PIN_TO_VEC_OFFSET);
146 /*
147 * GIC perfcnt interrupt -> CPU HW Int X (vector X+2) ->
148 * map to pin X+2-1 (since GIC adds 1)
149 */
150 perf_intr += (GIC_CPU_TO_VEC_OFFSET - GIC_PIN_TO_VEC_OFFSET);
151 }
152
153 /*
154 * Setup the default performance counter timer interrupts
155 * for all VPEs
156 */
157 for (i = 0; i < numvpes; i++) {
158 GICWRITE(GIC_REG(VPE_LOCAL, GIC_VPE_OTHER_ADDR), i);
159
160 /* Are Interrupts locally routable? */
161 GICREAD(GIC_REG(VPE_OTHER, GIC_VPE_CTL), vpe_ctl);
162 if (vpe_ctl & GIC_VPE_CTL_TIMER_RTBL_MSK)
163 GICWRITE(GIC_REG(VPE_OTHER, GIC_VPE_TIMER_MAP),
164 GIC_MAP_TO_PIN_MSK | timer_intr);
165 if (cpu_has_veic) {
166 set_vi_handler(timer_intr + GIC_PIN_TO_VEC_OFFSET,
167 gic_eic_irq_dispatch);
168 gic_shared_intr_map[timer_intr + GIC_PIN_TO_VEC_OFFSET].local_intr_mask |= GIC_VPE_RMASK_TIMER_MSK;
169 }
170
171 if (vpe_ctl & GIC_VPE_CTL_PERFCNT_RTBL_MSK)
172 GICWRITE(GIC_REG(VPE_OTHER, GIC_VPE_PERFCTR_MAP),
173 GIC_MAP_TO_PIN_MSK | perf_intr);
174 if (cpu_has_veic) {
175 set_vi_handler(perf_intr + GIC_PIN_TO_VEC_OFFSET, gic_eic_irq_dispatch);
176 gic_shared_intr_map[perf_intr + GIC_PIN_TO_VEC_OFFSET].local_intr_mask |= GIC_VPE_RMASK_PERFCNT_MSK;
177 }
178 }
179}
180
181unsigned int gic_compare_int(void)
182{
183 unsigned int pending;
184
185 GICREAD(GIC_REG(VPE_LOCAL, GIC_VPE_PEND), pending);
186 if (pending & GIC_VPE_PEND_CMP_MSK)
187 return 1;
188 else
189 return 0;
190}
191
192void gic_get_int_mask(unsigned long *dst, const unsigned long *src)
193{
194 unsigned int i;
195 unsigned long *pending, *intrmask, *pcpu_mask;
196 unsigned long *pending_abs, *intrmask_abs;
197
198 /* Get per-cpu bitmaps */
199 pending = pending_regs[smp_processor_id()].pending;
200 intrmask = intrmask_regs[smp_processor_id()].intrmask;
201 pcpu_mask = pcpu_masks[smp_processor_id()].pcpu_mask;
202
203 pending_abs = (unsigned long *) GIC_REG_ABS_ADDR(SHARED,
204 GIC_SH_PEND_31_0_OFS);
205 intrmask_abs = (unsigned long *) GIC_REG_ABS_ADDR(SHARED,
206 GIC_SH_MASK_31_0_OFS);
207
208 for (i = 0; i < BITS_TO_LONGS(GIC_NUM_INTRS); i++) {
209 GICREAD(*pending_abs, pending[i]);
210 GICREAD(*intrmask_abs, intrmask[i]);
211 pending_abs++;
212 intrmask_abs++;
213 }
214
215 bitmap_and(pending, pending, intrmask, GIC_NUM_INTRS);
216 bitmap_and(pending, pending, pcpu_mask, GIC_NUM_INTRS);
217 bitmap_and(dst, src, pending, GIC_NUM_INTRS);
218}
219
220unsigned int gic_get_int(void)
221{
222 DECLARE_BITMAP(interrupts, GIC_NUM_INTRS);
223
224 bitmap_fill(interrupts, GIC_NUM_INTRS);
225 gic_get_int_mask(interrupts, interrupts);
226
227 return find_first_bit(interrupts, GIC_NUM_INTRS);
228}
229
230static void gic_mask_irq(struct irq_data *d)
231{
232 GIC_CLR_INTR_MASK(d->irq - gic_irq_base);
233}
234
235static void gic_unmask_irq(struct irq_data *d)
236{
237 GIC_SET_INTR_MASK(d->irq - gic_irq_base);
238}
239
240#ifdef CONFIG_SMP
241static DEFINE_SPINLOCK(gic_lock);
242
243static int gic_set_affinity(struct irq_data *d, const struct cpumask *cpumask,
244 bool force)
245{
246 unsigned int irq = (d->irq - gic_irq_base);
247 cpumask_t tmp = CPU_MASK_NONE;
248 unsigned long flags;
249 int i;
250
251 cpumask_and(&tmp, cpumask, cpu_online_mask);
252 if (cpus_empty(tmp))
253 return -1;
254
255 /* Assumption : cpumask refers to a single CPU */
256 spin_lock_irqsave(&gic_lock, flags);
257
258 /* Re-route this IRQ */
259 GIC_SH_MAP_TO_VPE_SMASK(irq, first_cpu(tmp));
260
261 /* Update the pcpu_masks */
262 for (i = 0; i < NR_CPUS; i++)
263 clear_bit(irq, pcpu_masks[i].pcpu_mask);
264 set_bit(irq, pcpu_masks[first_cpu(tmp)].pcpu_mask);
265
266 cpumask_copy(d->affinity, cpumask);
267 spin_unlock_irqrestore(&gic_lock, flags);
268
269 return IRQ_SET_MASK_OK_NOCOPY;
270}
271#endif
272
273static struct irq_chip gic_irq_controller = {
274 .name = "MIPS GIC",
275 .irq_ack = gic_irq_ack,
276 .irq_mask = gic_mask_irq,
277 .irq_mask_ack = gic_mask_irq,
278 .irq_unmask = gic_unmask_irq,
279 .irq_eoi = gic_finish_irq,
280#ifdef CONFIG_SMP
281 .irq_set_affinity = gic_set_affinity,
282#endif
283};
284
285static void __init gic_setup_intr(unsigned int intr, unsigned int cpu,
286 unsigned int pin, unsigned int polarity, unsigned int trigtype,
287 unsigned int flags)
288{
289 struct gic_shared_intr_map *map_ptr;
290
291 /* Setup Intr to Pin mapping */
292 if (pin & GIC_MAP_TO_NMI_MSK) {
293 int i;
294
295 GICWRITE(GIC_REG_ADDR(SHARED, GIC_SH_MAP_TO_PIN(intr)), pin);
296 /* FIXME: hack to route NMI to all cpu's */
297 for (i = 0; i < NR_CPUS; i += 32) {
298 GICWRITE(GIC_REG_ADDR(SHARED,
299 GIC_SH_MAP_TO_VPE_REG_OFF(intr, i)),
300 0xffffffff);
301 }
302 } else {
303 GICWRITE(GIC_REG_ADDR(SHARED, GIC_SH_MAP_TO_PIN(intr)),
304 GIC_MAP_TO_PIN_MSK | pin);
305 /* Setup Intr to CPU mapping */
306 GIC_SH_MAP_TO_VPE_SMASK(intr, cpu);
307 if (cpu_has_veic) {
308 set_vi_handler(pin + GIC_PIN_TO_VEC_OFFSET,
309 gic_eic_irq_dispatch);
310 map_ptr = &gic_shared_intr_map[pin + GIC_PIN_TO_VEC_OFFSET];
311 if (map_ptr->num_shared_intr >= GIC_MAX_SHARED_INTR)
312 BUG();
313 map_ptr->intr_list[map_ptr->num_shared_intr++] = intr;
314 }
315 }
316
317 /* Setup Intr Polarity */
318 GIC_SET_POLARITY(intr, polarity);
319
320 /* Setup Intr Trigger Type */
321 GIC_SET_TRIGGER(intr, trigtype);
322
323 /* Init Intr Masks */
324 GIC_CLR_INTR_MASK(intr);
325
326 /* Initialise per-cpu Interrupt software masks */
327 set_bit(intr, pcpu_masks[cpu].pcpu_mask);
328
329 if ((flags & GIC_FLAG_TRANSPARENT) && (cpu_has_veic == 0))
330 GIC_SET_INTR_MASK(intr);
331 if (trigtype == GIC_TRIG_EDGE)
332 gic_irq_flags[intr] |= GIC_TRIG_EDGE;
333}
334
335static void __init gic_basic_init(int numintrs, int numvpes,
336 struct gic_intr_map *intrmap, int mapsize)
337{
338 unsigned int i, cpu;
339 unsigned int pin_offset = 0;
340
341 board_bind_eic_interrupt = &gic_bind_eic_interrupt;
342
343 /* Setup defaults */
344 for (i = 0; i < numintrs; i++) {
345 GIC_SET_POLARITY(i, GIC_POL_POS);
346 GIC_SET_TRIGGER(i, GIC_TRIG_LEVEL);
347 GIC_CLR_INTR_MASK(i);
348 if (i < GIC_NUM_INTRS) {
349 gic_irq_flags[i] = 0;
350 gic_shared_intr_map[i].num_shared_intr = 0;
351 gic_shared_intr_map[i].local_intr_mask = 0;
352 }
353 }
354
355 /*
356 * In EIC mode, the HW_INT# is offset by (2-1). Need to subtract
357 * one because the GIC will add one (since 0=no intr).
358 */
359 if (cpu_has_veic)
360 pin_offset = (GIC_CPU_TO_VEC_OFFSET - GIC_PIN_TO_VEC_OFFSET);
361
362 /* Setup specifics */
363 for (i = 0; i < mapsize; i++) {
364 cpu = intrmap[i].cpunum;
365 if (cpu == GIC_UNUSED)
366 continue;
367 gic_setup_intr(i,
368 intrmap[i].cpunum,
369 intrmap[i].pin + pin_offset,
370 intrmap[i].polarity,
371 intrmap[i].trigtype,
372 intrmap[i].flags);
373 }
374
375 vpe_local_setup(numvpes);
376}
377
378void __init gic_init(unsigned long gic_base_addr,
379 unsigned long gic_addrspace_size,
380 struct gic_intr_map *intr_map, unsigned int intr_map_size,
381 unsigned int irqbase)
382{
383 unsigned int gicconfig;
384 int numvpes, numintrs;
385
386 _gic_base = (unsigned long) ioremap_nocache(gic_base_addr,
387 gic_addrspace_size);
388 gic_irq_base = irqbase;
389
390 GICREAD(GIC_REG(SHARED, GIC_SH_CONFIG), gicconfig);
391 numintrs = (gicconfig & GIC_SH_CONFIG_NUMINTRS_MSK) >>
392 GIC_SH_CONFIG_NUMINTRS_SHF;
393 numintrs = ((numintrs + 1) * 8);
394
395 numvpes = (gicconfig & GIC_SH_CONFIG_NUMVPES_MSK) >>
396 GIC_SH_CONFIG_NUMVPES_SHF;
397 numvpes = numvpes + 1;
398
399 gic_basic_init(numintrs, numvpes, intr_map, intr_map_size);
400
401 gic_platform_init(numintrs, &gic_irq_controller);
402}
diff --git a/arch/mips/kernel/irq_cpu.c b/arch/mips/kernel/irq_cpu.c
index e498f2b3646a..590c2c980fd3 100644
--- a/arch/mips/kernel/irq_cpu.c
+++ b/arch/mips/kernel/irq_cpu.c
@@ -36,6 +36,7 @@
36#include <asm/irq_cpu.h> 36#include <asm/irq_cpu.h>
37#include <asm/mipsregs.h> 37#include <asm/mipsregs.h>
38#include <asm/mipsmtregs.h> 38#include <asm/mipsmtregs.h>
39#include <asm/setup.h>
39 40
40static inline void unmask_mips_irq(struct irq_data *d) 41static inline void unmask_mips_irq(struct irq_data *d)
41{ 42{
@@ -94,28 +95,24 @@ static struct irq_chip mips_mt_cpu_irq_controller = {
94 .irq_eoi = unmask_mips_irq, 95 .irq_eoi = unmask_mips_irq,
95}; 96};
96 97
97void __init mips_cpu_irq_init(void) 98asmlinkage void __weak plat_irq_dispatch(void)
98{ 99{
99 int irq_base = MIPS_CPU_IRQ_BASE; 100 unsigned long pending = read_c0_cause() & read_c0_status() & ST0_IM;
100 int i; 101 int irq;
101 102
102 /* Mask interrupts. */ 103 if (!pending) {
103 clear_c0_status(ST0_IM); 104 spurious_interrupt();
104 clear_c0_cause(CAUSEF_IP); 105 return;
105 106 }
106 /* Software interrupts are used for MT/CMT IPI */
107 for (i = irq_base; i < irq_base + 2; i++)
108 irq_set_chip_and_handler(i, cpu_has_mipsmt ?
109 &mips_mt_cpu_irq_controller :
110 &mips_cpu_irq_controller,
111 handle_percpu_irq);
112 107
113 for (i = irq_base + 2; i < irq_base + 8; i++) 108 pending >>= CAUSEB_IP;
114 irq_set_chip_and_handler(i, &mips_cpu_irq_controller, 109 while (pending) {
115 handle_percpu_irq); 110 irq = fls(pending) - 1;
111 do_IRQ(MIPS_CPU_IRQ_BASE + irq);
112 pending &= ~BIT(irq);
113 }
116} 114}
117 115
118#ifdef CONFIG_IRQ_DOMAIN
119static int mips_cpu_intc_map(struct irq_domain *d, unsigned int irq, 116static int mips_cpu_intc_map(struct irq_domain *d, unsigned int irq,
120 irq_hw_number_t hw) 117 irq_hw_number_t hw)
121{ 118{
@@ -128,6 +125,9 @@ static int mips_cpu_intc_map(struct irq_domain *d, unsigned int irq,
128 chip = &mips_cpu_irq_controller; 125 chip = &mips_cpu_irq_controller;
129 } 126 }
130 127
128 if (cpu_has_vint)
129 set_vi_handler(hw, plat_irq_dispatch);
130
131 irq_set_chip_and_handler(irq, chip, handle_percpu_irq); 131 irq_set_chip_and_handler(irq, chip, handle_percpu_irq);
132 132
133 return 0; 133 return 0;
@@ -138,8 +138,7 @@ static const struct irq_domain_ops mips_cpu_intc_irq_domain_ops = {
138 .xlate = irq_domain_xlate_onecell, 138 .xlate = irq_domain_xlate_onecell,
139}; 139};
140 140
141int __init mips_cpu_intc_init(struct device_node *of_node, 141static void __init __mips_cpu_irq_init(struct device_node *of_node)
142 struct device_node *parent)
143{ 142{
144 struct irq_domain *domain; 143 struct irq_domain *domain;
145 144
@@ -151,7 +150,16 @@ int __init mips_cpu_intc_init(struct device_node *of_node,
151 &mips_cpu_intc_irq_domain_ops, NULL); 150 &mips_cpu_intc_irq_domain_ops, NULL);
152 if (!domain) 151 if (!domain)
153 panic("Failed to add irqdomain for MIPS CPU"); 152 panic("Failed to add irqdomain for MIPS CPU");
153}
154 154
155void __init mips_cpu_irq_init(void)
156{
157 __mips_cpu_irq_init(NULL);
158}
159
160int __init mips_cpu_irq_of_init(struct device_node *of_node,
161 struct device_node *parent)
162{
163 __mips_cpu_irq_init(of_node);
155 return 0; 164 return 0;
156} 165}
157#endif /* CONFIG_IRQ_DOMAIN */
diff --git a/arch/mips/kernel/mips-cm.c b/arch/mips/kernel/mips-cm.c
index f76f7a08412d..85bbe9b96759 100644
--- a/arch/mips/kernel/mips-cm.c
+++ b/arch/mips/kernel/mips-cm.c
@@ -16,7 +16,7 @@
16void __iomem *mips_cm_base; 16void __iomem *mips_cm_base;
17void __iomem *mips_cm_l2sync_base; 17void __iomem *mips_cm_l2sync_base;
18 18
19phys_t __mips_cm_phys_base(void) 19phys_addr_t __mips_cm_phys_base(void)
20{ 20{
21 u32 config3 = read_c0_config3(); 21 u32 config3 = read_c0_config3();
22 u32 cmgcr; 22 u32 cmgcr;
@@ -30,10 +30,10 @@ phys_t __mips_cm_phys_base(void)
30 return (cmgcr & MIPS_CMGCRF_BASE) << (36 - 32); 30 return (cmgcr & MIPS_CMGCRF_BASE) << (36 - 32);
31} 31}
32 32
33phys_t mips_cm_phys_base(void) 33phys_addr_t mips_cm_phys_base(void)
34 __attribute__((weak, alias("__mips_cm_phys_base"))); 34 __attribute__((weak, alias("__mips_cm_phys_base")));
35 35
36phys_t __mips_cm_l2sync_phys_base(void) 36phys_addr_t __mips_cm_l2sync_phys_base(void)
37{ 37{
38 u32 base_reg; 38 u32 base_reg;
39 39
@@ -49,13 +49,13 @@ phys_t __mips_cm_l2sync_phys_base(void)
49 return mips_cm_phys_base() + MIPS_CM_GCR_SIZE; 49 return mips_cm_phys_base() + MIPS_CM_GCR_SIZE;
50} 50}
51 51
52phys_t mips_cm_l2sync_phys_base(void) 52phys_addr_t mips_cm_l2sync_phys_base(void)
53 __attribute__((weak, alias("__mips_cm_l2sync_phys_base"))); 53 __attribute__((weak, alias("__mips_cm_l2sync_phys_base")));
54 54
55static void mips_cm_probe_l2sync(void) 55static void mips_cm_probe_l2sync(void)
56{ 56{
57 unsigned major_rev; 57 unsigned major_rev;
58 phys_t addr; 58 phys_addr_t addr;
59 59
60 /* L2-only sync was introduced with CM major revision 6 */ 60 /* L2-only sync was introduced with CM major revision 6 */
61 major_rev = (read_gcr_rev() & CM_GCR_REV_MAJOR_MSK) >> 61 major_rev = (read_gcr_rev() & CM_GCR_REV_MAJOR_MSK) >>
@@ -78,7 +78,7 @@ static void mips_cm_probe_l2sync(void)
78 78
79int mips_cm_probe(void) 79int mips_cm_probe(void)
80{ 80{
81 phys_t addr; 81 phys_addr_t addr;
82 u32 base_reg; 82 u32 base_reg;
83 83
84 addr = mips_cm_phys_base(); 84 addr = mips_cm_phys_base();
diff --git a/arch/mips/kernel/mips-cpc.c b/arch/mips/kernel/mips-cpc.c
index ba473608a347..11964501c4b0 100644
--- a/arch/mips/kernel/mips-cpc.c
+++ b/arch/mips/kernel/mips-cpc.c
@@ -21,7 +21,7 @@ static DEFINE_PER_CPU_ALIGNED(spinlock_t, cpc_core_lock);
21 21
22static DEFINE_PER_CPU_ALIGNED(unsigned long, cpc_core_lock_flags); 22static DEFINE_PER_CPU_ALIGNED(unsigned long, cpc_core_lock_flags);
23 23
24phys_t __weak mips_cpc_phys_base(void) 24phys_addr_t __weak mips_cpc_phys_base(void)
25{ 25{
26 u32 cpc_base; 26 u32 cpc_base;
27 27
@@ -44,7 +44,7 @@ phys_t __weak mips_cpc_phys_base(void)
44 44
45int mips_cpc_probe(void) 45int mips_cpc_probe(void)
46{ 46{
47 phys_t addr; 47 phys_addr_t addr;
48 unsigned cpu; 48 unsigned cpu;
49 49
50 for_each_possible_cpu(cpu) 50 for_each_possible_cpu(cpu)
diff --git a/arch/mips/kernel/mips_ksyms.c b/arch/mips/kernel/mips_ksyms.c
index 2607c3a4ff7e..17eaf0cf760c 100644
--- a/arch/mips/kernel/mips_ksyms.c
+++ b/arch/mips/kernel/mips_ksyms.c
@@ -24,9 +24,7 @@ extern long __strncpy_from_user_nocheck_asm(char *__to,
24 const char *__from, long __len); 24 const char *__from, long __len);
25extern long __strncpy_from_user_asm(char *__to, const char *__from, 25extern long __strncpy_from_user_asm(char *__to, const char *__from,
26 long __len); 26 long __len);
27extern long __strlen_kernel_nocheck_asm(const char *s);
28extern long __strlen_kernel_asm(const char *s); 27extern long __strlen_kernel_asm(const char *s);
29extern long __strlen_user_nocheck_asm(const char *s);
30extern long __strlen_user_asm(const char *s); 28extern long __strlen_user_asm(const char *s);
31extern long __strnlen_kernel_nocheck_asm(const char *s); 29extern long __strnlen_kernel_nocheck_asm(const char *s);
32extern long __strnlen_kernel_asm(const char *s); 30extern long __strnlen_kernel_asm(const char *s);
@@ -62,9 +60,7 @@ EXPORT_SYMBOL(__strncpy_from_kernel_nocheck_asm);
62EXPORT_SYMBOL(__strncpy_from_kernel_asm); 60EXPORT_SYMBOL(__strncpy_from_kernel_asm);
63EXPORT_SYMBOL(__strncpy_from_user_nocheck_asm); 61EXPORT_SYMBOL(__strncpy_from_user_nocheck_asm);
64EXPORT_SYMBOL(__strncpy_from_user_asm); 62EXPORT_SYMBOL(__strncpy_from_user_asm);
65EXPORT_SYMBOL(__strlen_kernel_nocheck_asm);
66EXPORT_SYMBOL(__strlen_kernel_asm); 63EXPORT_SYMBOL(__strlen_kernel_asm);
67EXPORT_SYMBOL(__strlen_user_nocheck_asm);
68EXPORT_SYMBOL(__strlen_user_asm); 64EXPORT_SYMBOL(__strlen_user_asm);
69EXPORT_SYMBOL(__strnlen_kernel_nocheck_asm); 65EXPORT_SYMBOL(__strnlen_kernel_nocheck_asm);
70EXPORT_SYMBOL(__strnlen_kernel_asm); 66EXPORT_SYMBOL(__strnlen_kernel_asm);
diff --git a/arch/mips/kernel/perf_event_mipsxx.c b/arch/mips/kernel/perf_event_mipsxx.c
index a8f9cdc6f8b0..9466184d0039 100644
--- a/arch/mips/kernel/perf_event_mipsxx.c
+++ b/arch/mips/kernel/perf_event_mipsxx.c
@@ -561,8 +561,8 @@ static int mipspmu_get_irq(void)
561 IRQF_PERCPU | IRQF_NOBALANCING | IRQF_NO_THREAD, 561 IRQF_PERCPU | IRQF_NOBALANCING | IRQF_NO_THREAD,
562 "mips_perf_pmu", NULL); 562 "mips_perf_pmu", NULL);
563 if (err) { 563 if (err) {
564 pr_warning("Unable to request IRQ%d for MIPS " 564 pr_warn("Unable to request IRQ%d for MIPS performance counters!\n",
565 "performance counters!\n", mipspmu.irq); 565 mipspmu.irq);
566 } 566 }
567 } else if (cp0_perfcount_irq < 0) { 567 } else if (cp0_perfcount_irq < 0) {
568 /* 568 /*
@@ -572,8 +572,7 @@ static int mipspmu_get_irq(void)
572 perf_irq = mipsxx_pmu_handle_shared_irq; 572 perf_irq = mipsxx_pmu_handle_shared_irq;
573 err = 0; 573 err = 0;
574 } else { 574 } else {
575 pr_warning("The platform hasn't properly defined its " 575 pr_warn("The platform hasn't properly defined its interrupt controller\n");
576 "interrupt controller.\n");
577 err = -ENOENT; 576 err = -ENOENT;
578 } 577 }
579 578
@@ -1614,22 +1613,13 @@ init_hw_perf_events(void)
1614 counters = counters_total_to_per_cpu(counters); 1613 counters = counters_total_to_per_cpu(counters);
1615#endif 1614#endif
1616 1615
1617#ifdef MSC01E_INT_BASE 1616 if (get_c0_perfcount_int)
1618 if (cpu_has_veic) { 1617 irq = get_c0_perfcount_int();
1619 /* 1618 else if ((cp0_perfcount_irq >= 0) &&
1620 * Using platform specific interrupt controller defines. 1619 (cp0_compare_irq != cp0_perfcount_irq))
1621 */ 1620 irq = MIPS_CPU_IRQ_BASE + cp0_perfcount_irq;
1622 irq = MSC01E_INT_BASE + MSC01E_INT_PERFCTR; 1621 else
1623 } else { 1622 irq = -1;
1624#endif
1625 if ((cp0_perfcount_irq >= 0) &&
1626 (cp0_compare_irq != cp0_perfcount_irq))
1627 irq = MIPS_CPU_IRQ_BASE + cp0_perfcount_irq;
1628 else
1629 irq = -1;
1630#ifdef MSC01E_INT_BASE
1631 }
1632#endif
1633 1623
1634 mipspmu.map_raw_event = mipsxx_pmu_map_raw_event; 1624 mipspmu.map_raw_event = mipsxx_pmu_map_raw_event;
1635 1625
diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c
index 636b0745d7c7..eb76434828e8 100644
--- a/arch/mips/kernel/process.c
+++ b/arch/mips/kernel/process.c
@@ -42,6 +42,7 @@
42#include <asm/isadep.h> 42#include <asm/isadep.h>
43#include <asm/inst.h> 43#include <asm/inst.h>
44#include <asm/stacktrace.h> 44#include <asm/stacktrace.h>
45#include <asm/irq_regs.h>
45 46
46#ifdef CONFIG_HOTPLUG_CPU 47#ifdef CONFIG_HOTPLUG_CPU
47void arch_cpu_idle_dead(void) 48void arch_cpu_idle_dead(void)
@@ -187,21 +188,21 @@ static inline int is_ra_save_ins(union mips_instruction *ip)
187 */ 188 */
188 if (mm_insn_16bit(ip->halfword[0])) { 189 if (mm_insn_16bit(ip->halfword[0])) {
189 mmi.word = (ip->halfword[0] << 16); 190 mmi.word = (ip->halfword[0] << 16);
190 return ((mmi.mm16_r5_format.opcode == mm_swsp16_op && 191 return (mmi.mm16_r5_format.opcode == mm_swsp16_op &&
191 mmi.mm16_r5_format.rt == 31) || 192 mmi.mm16_r5_format.rt == 31) ||
192 (mmi.mm16_m_format.opcode == mm_pool16c_op && 193 (mmi.mm16_m_format.opcode == mm_pool16c_op &&
193 mmi.mm16_m_format.func == mm_swm16_op)); 194 mmi.mm16_m_format.func == mm_swm16_op);
194 } 195 }
195 else { 196 else {
196 mmi.halfword[0] = ip->halfword[1]; 197 mmi.halfword[0] = ip->halfword[1];
197 mmi.halfword[1] = ip->halfword[0]; 198 mmi.halfword[1] = ip->halfword[0];
198 return ((mmi.mm_m_format.opcode == mm_pool32b_op && 199 return (mmi.mm_m_format.opcode == mm_pool32b_op &&
199 mmi.mm_m_format.rd > 9 && 200 mmi.mm_m_format.rd > 9 &&
200 mmi.mm_m_format.base == 29 && 201 mmi.mm_m_format.base == 29 &&
201 mmi.mm_m_format.func == mm_swm32_func) || 202 mmi.mm_m_format.func == mm_swm32_func) ||
202 (mmi.i_format.opcode == mm_sw32_op && 203 (mmi.i_format.opcode == mm_sw32_op &&
203 mmi.i_format.rs == 29 && 204 mmi.i_format.rs == 29 &&
204 mmi.i_format.rt == 31)); 205 mmi.i_format.rt == 31);
205 } 206 }
206#else 207#else
207 /* sw / sd $ra, offset($sp) */ 208 /* sw / sd $ra, offset($sp) */
@@ -233,7 +234,7 @@ static inline int is_jump_ins(union mips_instruction *ip)
233 if (ip->r_format.opcode != mm_pool32a_op || 234 if (ip->r_format.opcode != mm_pool32a_op ||
234 ip->r_format.func != mm_pool32axf_op) 235 ip->r_format.func != mm_pool32axf_op)
235 return 0; 236 return 0;
236 return (((ip->u_format.uimmediate >> 6) & mm_jalr_op) == mm_jalr_op); 237 return ((ip->u_format.uimmediate >> 6) & mm_jalr_op) == mm_jalr_op;
237#else 238#else
238 if (ip->j_format.opcode == j_op) 239 if (ip->j_format.opcode == j_op)
239 return 1; 240 return 1;
@@ -260,13 +261,13 @@ static inline int is_sp_move_ins(union mips_instruction *ip)
260 union mips_instruction mmi; 261 union mips_instruction mmi;
261 262
262 mmi.word = (ip->halfword[0] << 16); 263 mmi.word = (ip->halfword[0] << 16);
263 return ((mmi.mm16_r3_format.opcode == mm_pool16d_op && 264 return (mmi.mm16_r3_format.opcode == mm_pool16d_op &&
264 mmi.mm16_r3_format.simmediate && mm_addiusp_func) || 265 mmi.mm16_r3_format.simmediate && mm_addiusp_func) ||
265 (mmi.mm16_r5_format.opcode == mm_pool16d_op && 266 (mmi.mm16_r5_format.opcode == mm_pool16d_op &&
266 mmi.mm16_r5_format.rt == 29)); 267 mmi.mm16_r5_format.rt == 29);
267 } 268 }
268 return (ip->mm_i_format.opcode == mm_addiu32_op && 269 return ip->mm_i_format.opcode == mm_addiu32_op &&
269 ip->mm_i_format.rt == 29 && ip->mm_i_format.rs == 29); 270 ip->mm_i_format.rt == 29 && ip->mm_i_format.rs == 29;
270#else 271#else
271 /* addiu/daddiu sp,sp,-imm */ 272 /* addiu/daddiu sp,sp,-imm */
272 if (ip->i_format.rs != 29 || ip->i_format.rt != 29) 273 if (ip->i_format.rs != 29 || ip->i_format.rt != 29)
@@ -532,3 +533,20 @@ unsigned long arch_align_stack(unsigned long sp)
532 533
533 return sp & ALMASK; 534 return sp & ALMASK;
534} 535}
536
537static void arch_dump_stack(void *info)
538{
539 struct pt_regs *regs;
540
541 regs = get_irq_regs();
542
543 if (regs)
544 show_regs(regs);
545
546 dump_stack();
547}
548
549void arch_trigger_all_cpu_backtrace(bool include_self)
550{
551 smp_call_function(arch_dump_stack, NULL, 1);
552}
diff --git a/arch/mips/kernel/prom.c b/arch/mips/kernel/prom.c
index 5d39bb85bf35..452d4350ce42 100644
--- a/arch/mips/kernel/prom.c
+++ b/arch/mips/kernel/prom.c
@@ -16,6 +16,7 @@
16#include <linux/debugfs.h> 16#include <linux/debugfs.h>
17#include <linux/of.h> 17#include <linux/of.h>
18#include <linux/of_fdt.h> 18#include <linux/of_fdt.h>
19#include <linux/of_platform.h>
19 20
20#include <asm/page.h> 21#include <asm/page.h>
21#include <asm/prom.h> 22#include <asm/prom.h>
@@ -54,4 +55,21 @@ void __init __dt_setup_arch(void *bph)
54 55
55 mips_set_machine_name(of_flat_dt_get_machine_name()); 56 mips_set_machine_name(of_flat_dt_get_machine_name());
56} 57}
58
59int __init __dt_register_buses(const char *bus0, const char *bus1)
60{
61 static struct of_device_id of_ids[3];
62
63 if (!of_have_populated_dt())
64 panic("device tree not present");
65
66 strlcpy(of_ids[0].compatible, bus0, sizeof(of_ids[0].compatible));
67 strlcpy(of_ids[1].compatible, bus1, sizeof(of_ids[1].compatible));
68
69 if (of_platform_populate(NULL, of_ids, NULL, NULL))
70 panic("failed to populate DT");
71
72 return 0;
73}
74
57#endif 75#endif
diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c
index f3b635f86c39..058929041368 100644
--- a/arch/mips/kernel/setup.c
+++ b/arch/mips/kernel/setup.c
@@ -82,14 +82,14 @@ static struct resource data_resource = { .name = "Kernel data", };
82 82
83static void *detect_magic __initdata = detect_memory_region; 83static void *detect_magic __initdata = detect_memory_region;
84 84
85void __init add_memory_region(phys_t start, phys_t size, long type) 85void __init add_memory_region(phys_addr_t start, phys_addr_t size, long type)
86{ 86{
87 int x = boot_mem_map.nr_map; 87 int x = boot_mem_map.nr_map;
88 int i; 88 int i;
89 89
90 /* Sanity check */ 90 /* Sanity check */
91 if (start + size < start) { 91 if (start + size < start) {
92 pr_warning("Trying to add an invalid memory region, skipped\n"); 92 pr_warn("Trying to add an invalid memory region, skipped\n");
93 return; 93 return;
94 } 94 }
95 95
@@ -127,10 +127,10 @@ void __init add_memory_region(phys_t start, phys_t size, long type)
127 boot_mem_map.nr_map++; 127 boot_mem_map.nr_map++;
128} 128}
129 129
130void __init detect_memory_region(phys_t start, phys_t sz_min, phys_t sz_max) 130void __init detect_memory_region(phys_addr_t start, phys_addr_t sz_min, phys_addr_t sz_max)
131{ 131{
132 void *dm = &detect_magic; 132 void *dm = &detect_magic;
133 phys_t size; 133 phys_addr_t size;
134 134
135 for (size = sz_min; size < sz_max; size <<= 1) { 135 for (size = sz_min; size < sz_max; size <<= 1) {
136 if (!memcmp(dm, dm + size, sizeof(detect_magic))) 136 if (!memcmp(dm, dm + size, sizeof(detect_magic)))
@@ -493,7 +493,7 @@ static int usermem __initdata;
493 493
494static int __init early_parse_mem(char *p) 494static int __init early_parse_mem(char *p)
495{ 495{
496 phys_t start, size; 496 phys_addr_t start, size;
497 497
498 /* 498 /*
499 * If a user specifies memory size, we 499 * If a user specifies memory size, we
@@ -545,9 +545,9 @@ static int __init early_parse_elfcorehdr(char *p)
545early_param("elfcorehdr", early_parse_elfcorehdr); 545early_param("elfcorehdr", early_parse_elfcorehdr);
546#endif 546#endif
547 547
548static void __init arch_mem_addpart(phys_t mem, phys_t end, int type) 548static void __init arch_mem_addpart(phys_addr_t mem, phys_addr_t end, int type)
549{ 549{
550 phys_t size; 550 phys_addr_t size;
551 int i; 551 int i;
552 552
553 size = end - mem; 553 size = end - mem;
diff --git a/arch/mips/kernel/signal.c b/arch/mips/kernel/signal.c
index 16f1e4f2bf3c..545bf11bd2ed 100644
--- a/arch/mips/kernel/signal.c
+++ b/arch/mips/kernel/signal.c
@@ -530,7 +530,7 @@ static void handle_signal(struct ksignal *ksig, struct pt_regs *regs)
530 struct mips_abi *abi = current->thread.abi; 530 struct mips_abi *abi = current->thread.abi;
531#ifdef CONFIG_CPU_MICROMIPS 531#ifdef CONFIG_CPU_MICROMIPS
532 void *vdso; 532 void *vdso;
533 unsigned int tmp = (unsigned int)current->mm->context.vdso; 533 unsigned long tmp = (unsigned long)current->mm->context.vdso;
534 534
535 set_isa16_mode(tmp); 535 set_isa16_mode(tmp);
536 vdso = (void *)tmp; 536 vdso = (void *)tmp;
diff --git a/arch/mips/kernel/smp-bmips.c b/arch/mips/kernel/smp-bmips.c
index 06bb5ed6d80a..b8bd9340c9c7 100644
--- a/arch/mips/kernel/smp-bmips.c
+++ b/arch/mips/kernel/smp-bmips.c
@@ -35,6 +35,7 @@
35#include <asm/bmips.h> 35#include <asm/bmips.h>
36#include <asm/traps.h> 36#include <asm/traps.h>
37#include <asm/barrier.h> 37#include <asm/barrier.h>
38#include <asm/cpu-features.h>
38 39
39static int __maybe_unused max_cpus = 1; 40static int __maybe_unused max_cpus = 1;
40 41
@@ -42,6 +43,12 @@ static int __maybe_unused max_cpus = 1;
42int bmips_smp_enabled = 1; 43int bmips_smp_enabled = 1;
43int bmips_cpu_offset; 44int bmips_cpu_offset;
44cpumask_t bmips_booted_mask; 45cpumask_t bmips_booted_mask;
46unsigned long bmips_tp1_irqs = IE_IRQ1;
47
48#define RESET_FROM_KSEG0 0x80080800
49#define RESET_FROM_KSEG1 0xa0080800
50
51static void bmips_set_reset_vec(int cpu, u32 val);
45 52
46#ifdef CONFIG_SMP 53#ifdef CONFIG_SMP
47 54
@@ -194,6 +201,9 @@ static void bmips_boot_secondary(int cpu, struct task_struct *idle)
194 pr_info("SMP: Booting CPU%d...\n", cpu); 201 pr_info("SMP: Booting CPU%d...\n", cpu);
195 202
196 if (cpumask_test_cpu(cpu, &bmips_booted_mask)) { 203 if (cpumask_test_cpu(cpu, &bmips_booted_mask)) {
204 /* kseg1 might not exist if this CPU enabled XKS01 */
205 bmips_set_reset_vec(cpu, RESET_FROM_KSEG0);
206
197 switch (current_cpu_type()) { 207 switch (current_cpu_type()) {
198 case CPU_BMIPS4350: 208 case CPU_BMIPS4350:
199 case CPU_BMIPS4380: 209 case CPU_BMIPS4380:
@@ -203,8 +213,9 @@ static void bmips_boot_secondary(int cpu, struct task_struct *idle)
203 bmips5000_send_ipi_single(cpu, 0); 213 bmips5000_send_ipi_single(cpu, 0);
204 break; 214 break;
205 } 215 }
206 } 216 } else {
207 else { 217 bmips_set_reset_vec(cpu, RESET_FROM_KSEG1);
218
208 switch (current_cpu_type()) { 219 switch (current_cpu_type()) {
209 case CPU_BMIPS4350: 220 case CPU_BMIPS4350:
210 case CPU_BMIPS4380: 221 case CPU_BMIPS4380:
@@ -213,17 +224,7 @@ static void bmips_boot_secondary(int cpu, struct task_struct *idle)
213 set_c0_brcm_cmt_ctrl(0x01); 224 set_c0_brcm_cmt_ctrl(0x01);
214 break; 225 break;
215 case CPU_BMIPS5000: 226 case CPU_BMIPS5000:
216 if (cpu & 0x01) 227 write_c0_brcm_action(ACTION_BOOT_THREAD(cpu));
217 write_c0_brcm_action(ACTION_BOOT_THREAD(cpu));
218 else {
219 /*
220 * core N thread 0 was already booted; just
221 * pulse the NMI line
222 */
223 bmips_write_zscm_reg(0x210, 0xc0000000);
224 udelay(10);
225 bmips_write_zscm_reg(0x210, 0x00);
226 }
227 break; 228 break;
228 } 229 }
229 cpumask_set_cpu(cpu, &bmips_booted_mask); 230 cpumask_set_cpu(cpu, &bmips_booted_mask);
@@ -235,31 +236,12 @@ static void bmips_boot_secondary(int cpu, struct task_struct *idle)
235 */ 236 */
236static void bmips_init_secondary(void) 237static void bmips_init_secondary(void)
237{ 238{
238 /* move NMI vector to kseg0, in case XKS01 is enabled */
239
240 void __iomem *cbr;
241 unsigned long old_vec;
242 unsigned long relo_vector;
243 int boot_cpu;
244
245 switch (current_cpu_type()) { 239 switch (current_cpu_type()) {
246 case CPU_BMIPS4350: 240 case CPU_BMIPS4350:
247 case CPU_BMIPS4380: 241 case CPU_BMIPS4380:
248 cbr = BMIPS_GET_CBR();
249
250 boot_cpu = !!(read_c0_brcm_cmt_local() & (1 << 31));
251 relo_vector = boot_cpu ? BMIPS_RELO_VECTOR_CONTROL_0 :
252 BMIPS_RELO_VECTOR_CONTROL_1;
253
254 old_vec = __raw_readl(cbr + relo_vector);
255 __raw_writel(old_vec & ~0x20000000, cbr + relo_vector);
256
257 clear_c0_cause(smp_processor_id() ? C_SW1 : C_SW0); 242 clear_c0_cause(smp_processor_id() ? C_SW1 : C_SW0);
258 break; 243 break;
259 case CPU_BMIPS5000: 244 case CPU_BMIPS5000:
260 write_c0_brcm_bootvec(read_c0_brcm_bootvec() &
261 (smp_processor_id() & 0x01 ? ~0x20000000 : ~0x2000));
262
263 write_c0_brcm_action(ACTION_CLR_IPI(smp_processor_id(), 0)); 245 write_c0_brcm_action(ACTION_CLR_IPI(smp_processor_id(), 0));
264 break; 246 break;
265 } 247 }
@@ -276,7 +258,7 @@ static void bmips_smp_finish(void)
276 write_c0_compare(read_c0_count() + mips_hpt_frequency / HZ); 258 write_c0_compare(read_c0_count() + mips_hpt_frequency / HZ);
277 259
278 irq_enable_hazard(); 260 irq_enable_hazard();
279 set_c0_status(IE_SW0 | IE_SW1 | IE_IRQ1 | IE_IRQ5 | ST0_IE); 261 set_c0_status(IE_SW0 | IE_SW1 | bmips_tp1_irqs | IE_IRQ5 | ST0_IE);
280 irq_enable_hazard(); 262 irq_enable_hazard();
281} 263}
282 264
@@ -381,6 +363,7 @@ static int bmips_cpu_disable(void)
381 363
382 set_cpu_online(cpu, false); 364 set_cpu_online(cpu, false);
383 cpu_clear(cpu, cpu_callin_map); 365 cpu_clear(cpu, cpu_callin_map);
366 clear_c0_status(IE_IRQ5);
384 367
385 local_flush_tlb_all(); 368 local_flush_tlb_all();
386 local_flush_icache_range(0, ~0); 369 local_flush_icache_range(0, ~0);
@@ -405,7 +388,8 @@ void __ref play_dead(void)
405 * IRQ handlers; this clears ST0_IE and returns immediately. 388 * IRQ handlers; this clears ST0_IE and returns immediately.
406 */ 389 */
407 clear_c0_cause(CAUSEF_IV | C_SW0 | C_SW1); 390 clear_c0_cause(CAUSEF_IV | C_SW0 | C_SW1);
408 change_c0_status(IE_IRQ5 | IE_IRQ1 | IE_SW0 | IE_SW1 | ST0_IE | ST0_BEV, 391 change_c0_status(
392 IE_IRQ5 | bmips_tp1_irqs | IE_SW0 | IE_SW1 | ST0_IE | ST0_BEV,
409 IE_SW0 | IE_SW1 | ST0_IE | ST0_BEV); 393 IE_SW0 | IE_SW1 | ST0_IE | ST0_BEV);
410 irq_disable_hazard(); 394 irq_disable_hazard();
411 395
@@ -473,10 +457,61 @@ static inline void bmips_nmi_handler_setup(void)
473 &bmips_smp_int_vec_end); 457 &bmips_smp_int_vec_end);
474} 458}
475 459
460struct reset_vec_info {
461 int cpu;
462 u32 val;
463};
464
465static void bmips_set_reset_vec_remote(void *vinfo)
466{
467 struct reset_vec_info *info = vinfo;
468 int shift = info->cpu & 0x01 ? 16 : 0;
469 u32 mask = ~(0xffff << shift), val = info->val >> 16;
470
471 preempt_disable();
472 if (smp_processor_id() > 0) {
473 smp_call_function_single(0, &bmips_set_reset_vec_remote,
474 info, 1);
475 } else {
476 if (info->cpu & 0x02) {
477 /* BMIPS5200 "should" use mask/shift, but it's buggy */
478 bmips_write_zscm_reg(0xa0, (val << 16) | val);
479 bmips_read_zscm_reg(0xa0);
480 } else {
481 write_c0_brcm_bootvec((read_c0_brcm_bootvec() & mask) |
482 (val << shift));
483 }
484 }
485 preempt_enable();
486}
487
488static void bmips_set_reset_vec(int cpu, u32 val)
489{
490 struct reset_vec_info info;
491
492 if (current_cpu_type() == CPU_BMIPS5000) {
493 /* this needs to run from CPU0 (which is always online) */
494 info.cpu = cpu;
495 info.val = val;
496 bmips_set_reset_vec_remote(&info);
497 } else {
498 void __iomem *cbr = BMIPS_GET_CBR();
499
500 if (cpu == 0)
501 __raw_writel(val, cbr + BMIPS_RELO_VECTOR_CONTROL_0);
502 else {
503 if (current_cpu_type() != CPU_BMIPS4380)
504 return;
505 __raw_writel(val, cbr + BMIPS_RELO_VECTOR_CONTROL_1);
506 }
507 }
508 __sync();
509 back_to_back_c0_hazard();
510}
511
476void bmips_ebase_setup(void) 512void bmips_ebase_setup(void)
477{ 513{
478 unsigned long new_ebase = ebase; 514 unsigned long new_ebase = ebase;
479 void __iomem __maybe_unused *cbr;
480 515
481 BUG_ON(ebase != CKSEG0); 516 BUG_ON(ebase != CKSEG0);
482 517
@@ -496,15 +531,14 @@ void bmips_ebase_setup(void)
496 &bmips_smp_int_vec, 0x80); 531 &bmips_smp_int_vec, 0x80);
497 __sync(); 532 __sync();
498 return; 533 return;
534 case CPU_BMIPS3300:
499 case CPU_BMIPS4380: 535 case CPU_BMIPS4380:
500 /* 536 /*
501 * 0x8000_0000: reset/NMI (initially in kseg1) 537 * 0x8000_0000: reset/NMI (initially in kseg1)
502 * 0x8000_0400: normal vectors 538 * 0x8000_0400: normal vectors
503 */ 539 */
504 new_ebase = 0x80000400; 540 new_ebase = 0x80000400;
505 cbr = BMIPS_GET_CBR(); 541 bmips_set_reset_vec(0, RESET_FROM_KSEG0);
506 __raw_writel(0x80080800, cbr + BMIPS_RELO_VECTOR_CONTROL_0);
507 __raw_writel(0xa0080800, cbr + BMIPS_RELO_VECTOR_CONTROL_1);
508 break; 542 break;
509 case CPU_BMIPS5000: 543 case CPU_BMIPS5000:
510 /* 544 /*
@@ -512,10 +546,8 @@ void bmips_ebase_setup(void)
512 * 0x8000_1000: normal vectors 546 * 0x8000_1000: normal vectors
513 */ 547 */
514 new_ebase = 0x80001000; 548 new_ebase = 0x80001000;
515 write_c0_brcm_bootvec(0xa0088008); 549 bmips_set_reset_vec(0, RESET_FROM_KSEG0);
516 write_c0_ebase(new_ebase); 550 write_c0_ebase(new_ebase);
517 if (max_cpus > 2)
518 bmips_write_zscm_reg(0xa0, 0xa008a008);
519 break; 551 break;
520 default: 552 default:
521 return; 553 return;
diff --git a/arch/mips/kernel/smp-cmp.c b/arch/mips/kernel/smp-cmp.c
index fc8a51553426..1e0a93c5a3e7 100644
--- a/arch/mips/kernel/smp-cmp.c
+++ b/arch/mips/kernel/smp-cmp.c
@@ -24,6 +24,7 @@
24#include <linux/cpumask.h> 24#include <linux/cpumask.h>
25#include <linux/interrupt.h> 25#include <linux/interrupt.h>
26#include <linux/compiler.h> 26#include <linux/compiler.h>
27#include <linux/irqchip/mips-gic.h>
27 28
28#include <linux/atomic.h> 29#include <linux/atomic.h>
29#include <asm/cacheflush.h> 30#include <asm/cacheflush.h>
@@ -37,7 +38,6 @@
37#include <asm/mipsmtregs.h> 38#include <asm/mipsmtregs.h>
38#include <asm/mips_mt.h> 39#include <asm/mips_mt.h>
39#include <asm/amon.h> 40#include <asm/amon.h>
40#include <asm/gic.h>
41 41
42static void cmp_init_secondary(void) 42static void cmp_init_secondary(void)
43{ 43{
diff --git a/arch/mips/kernel/smp-cps.c b/arch/mips/kernel/smp-cps.c
index e6e16a1d4add..bed7590e475f 100644
--- a/arch/mips/kernel/smp-cps.c
+++ b/arch/mips/kernel/smp-cps.c
@@ -9,13 +9,13 @@
9 */ 9 */
10 10
11#include <linux/io.h> 11#include <linux/io.h>
12#include <linux/irqchip/mips-gic.h>
12#include <linux/sched.h> 13#include <linux/sched.h>
13#include <linux/slab.h> 14#include <linux/slab.h>
14#include <linux/smp.h> 15#include <linux/smp.h>
15#include <linux/types.h> 16#include <linux/types.h>
16 17
17#include <asm/bcache.h> 18#include <asm/bcache.h>
18#include <asm/gic.h>
19#include <asm/mips-cm.h> 19#include <asm/mips-cm.h>
20#include <asm/mips-cpc.h> 20#include <asm/mips-cpc.h>
21#include <asm/mips_mt.h> 21#include <asm/mips_mt.h>
@@ -273,8 +273,8 @@ static void cps_init_secondary(void)
273 if (cpu_has_mipsmt) 273 if (cpu_has_mipsmt)
274 dmt(); 274 dmt();
275 275
276 change_c0_status(ST0_IM, STATUSF_IP3 | STATUSF_IP4 | 276 change_c0_status(ST0_IM, STATUSF_IP2 | STATUSF_IP3 | STATUSF_IP4 |
277 STATUSF_IP6 | STATUSF_IP7); 277 STATUSF_IP5 | STATUSF_IP6 | STATUSF_IP7);
278} 278}
279 279
280static void cps_smp_finish(void) 280static void cps_smp_finish(void)
diff --git a/arch/mips/kernel/smp-gic.c b/arch/mips/kernel/smp-gic.c
index 3b21a96d1ccb..5f0ab5bcd01e 100644
--- a/arch/mips/kernel/smp-gic.c
+++ b/arch/mips/kernel/smp-gic.c
@@ -12,9 +12,9 @@
12 * option) any later version. 12 * option) any later version.
13 */ 13 */
14 14
15#include <linux/irqchip/mips-gic.h>
15#include <linux/printk.h> 16#include <linux/printk.h>
16 17
17#include <asm/gic.h>
18#include <asm/mips-cpc.h> 18#include <asm/mips-cpc.h>
19#include <asm/smp-ops.h> 19#include <asm/smp-ops.h>
20 20
diff --git a/arch/mips/kernel/smp-mt.c b/arch/mips/kernel/smp-mt.c
index 21f23add04f4..ad86951b73bd 100644
--- a/arch/mips/kernel/smp-mt.c
+++ b/arch/mips/kernel/smp-mt.c
@@ -21,6 +21,7 @@
21#include <linux/sched.h> 21#include <linux/sched.h>
22#include <linux/cpumask.h> 22#include <linux/cpumask.h>
23#include <linux/interrupt.h> 23#include <linux/interrupt.h>
24#include <linux/irqchip/mips-gic.h>
24#include <linux/compiler.h> 25#include <linux/compiler.h>
25#include <linux/smp.h> 26#include <linux/smp.h>
26 27
@@ -34,7 +35,6 @@
34#include <asm/mipsregs.h> 35#include <asm/mipsregs.h>
35#include <asm/mipsmtregs.h> 36#include <asm/mipsmtregs.h>
36#include <asm/mips_mt.h> 37#include <asm/mips_mt.h>
37#include <asm/gic.h>
38 38
39static void __init smvp_copy_vpe_config(void) 39static void __init smvp_copy_vpe_config(void)
40{ 40{
@@ -119,7 +119,7 @@ static void vsmp_send_ipi_single(int cpu, unsigned int action)
119 unsigned long flags; 119 unsigned long flags;
120 int vpflags; 120 int vpflags;
121 121
122#ifdef CONFIG_IRQ_GIC 122#ifdef CONFIG_MIPS_GIC
123 if (gic_present) { 123 if (gic_present) {
124 gic_send_ipi_single(cpu, action); 124 gic_send_ipi_single(cpu, action);
125 return; 125 return;
@@ -158,7 +158,7 @@ static void vsmp_send_ipi_mask(const struct cpumask *mask, unsigned int action)
158 158
159static void vsmp_init_secondary(void) 159static void vsmp_init_secondary(void)
160{ 160{
161#ifdef CONFIG_IRQ_GIC 161#ifdef CONFIG_MIPS_GIC
162 /* This is Malta specific: IPI,performance and timer interrupts */ 162 /* This is Malta specific: IPI,performance and timer interrupts */
163 if (gic_present) 163 if (gic_present)
164 change_c0_status(ST0_IM, STATUSF_IP3 | STATUSF_IP4 | 164 change_c0_status(ST0_IM, STATUSF_IP3 | STATUSF_IP4 |
diff --git a/arch/mips/kernel/syscall.c b/arch/mips/kernel/syscall.c
index 4a4f9dda5658..604b558809c4 100644
--- a/arch/mips/kernel/syscall.c
+++ b/arch/mips/kernel/syscall.c
@@ -117,6 +117,7 @@ static inline int mips_atomic_set(unsigned long addr, unsigned long new)
117 "2: sc %[tmp], (%[addr]) \n" 117 "2: sc %[tmp], (%[addr]) \n"
118 " beqzl %[tmp], 1b \n" 118 " beqzl %[tmp], 1b \n"
119 "3: \n" 119 "3: \n"
120 " .insn \n"
120 " .section .fixup,\"ax\" \n" 121 " .section .fixup,\"ax\" \n"
121 "4: li %[err], %[efault] \n" 122 "4: li %[err], %[efault] \n"
122 " j 3b \n" 123 " j 3b \n"
@@ -142,6 +143,7 @@ static inline int mips_atomic_set(unsigned long addr, unsigned long new)
142 "2: sc %[tmp], (%[addr]) \n" 143 "2: sc %[tmp], (%[addr]) \n"
143 " bnez %[tmp], 4f \n" 144 " bnez %[tmp], 4f \n"
144 "3: \n" 145 "3: \n"
146 " .insn \n"
145 " .subsection 2 \n" 147 " .subsection 2 \n"
146 "4: b 1b \n" 148 "4: b 1b \n"
147 " .previous \n" 149 " .previous \n"
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
index 22b19c275044..ad3d2031c327 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -724,6 +724,50 @@ int process_fpemu_return(int sig, void __user *fault_addr)
724 } 724 }
725} 725}
726 726
727static int simulate_fp(struct pt_regs *regs, unsigned int opcode,
728 unsigned long old_epc, unsigned long old_ra)
729{
730 union mips_instruction inst = { .word = opcode };
731 void __user *fault_addr = NULL;
732 int sig;
733
734 /* If it's obviously not an FP instruction, skip it */
735 switch (inst.i_format.opcode) {
736 case cop1_op:
737 case cop1x_op:
738 case lwc1_op:
739 case ldc1_op:
740 case swc1_op:
741 case sdc1_op:
742 break;
743
744 default:
745 return -1;
746 }
747
748 /*
749 * do_ri skipped over the instruction via compute_return_epc, undo
750 * that for the FPU emulator.
751 */
752 regs->cp0_epc = old_epc;
753 regs->regs[31] = old_ra;
754
755 /* Save the FP context to struct thread_struct */
756 lose_fpu(1);
757
758 /* Run the emulator */
759 sig = fpu_emulator_cop1Handler(regs, &current->thread.fpu, 1,
760 &fault_addr);
761
762 /* If something went wrong, signal */
763 process_fpemu_return(sig, fault_addr);
764
765 /* Restore the hardware register state */
766 own_fpu(1);
767
768 return 0;
769}
770
727/* 771/*
728 * XXX Delayed fp exceptions when doing a lazy ctx switch XXX 772 * XXX Delayed fp exceptions when doing a lazy ctx switch XXX
729 */ 773 */
@@ -1016,6 +1060,9 @@ asmlinkage void do_ri(struct pt_regs *regs)
1016 1060
1017 if (status < 0) 1061 if (status < 0)
1018 status = simulate_sync(regs, opcode); 1062 status = simulate_sync(regs, opcode);
1063
1064 if (status < 0)
1065 status = simulate_fp(regs, opcode, old_epc, old31);
1019 } 1066 }
1020 1067
1021 if (status < 0) 1068 if (status < 0)
@@ -1380,12 +1427,19 @@ asmlinkage void do_mcheck(struct pt_regs *regs)
1380 show_regs(regs); 1427 show_regs(regs);
1381 1428
1382 if (multi_match) { 1429 if (multi_match) {
1383 printk("Index : %0x\n", read_c0_index()); 1430 pr_err("Index : %0x\n", read_c0_index());
1384 printk("Pagemask: %0x\n", read_c0_pagemask()); 1431 pr_err("Pagemask: %0x\n", read_c0_pagemask());
1385 printk("EntryHi : %0*lx\n", field, read_c0_entryhi()); 1432 pr_err("EntryHi : %0*lx\n", field, read_c0_entryhi());
1386 printk("EntryLo0: %0*lx\n", field, read_c0_entrylo0()); 1433 pr_err("EntryLo0: %0*lx\n", field, read_c0_entrylo0());
1387 printk("EntryLo1: %0*lx\n", field, read_c0_entrylo1()); 1434 pr_err("EntryLo1: %0*lx\n", field, read_c0_entrylo1());
1388 printk("\n"); 1435 pr_err("Wired : %0x\n", read_c0_wired());
1436 pr_err("Pagegrain: %0x\n", read_c0_pagegrain());
1437 if (cpu_has_htw) {
1438 pr_err("PWField : %0*lx\n", field, read_c0_pwfield());
1439 pr_err("PWSize : %0*lx\n", field, read_c0_pwsize());
1440 pr_err("PWCtl : %0x\n", read_c0_pwctl());
1441 }
1442 pr_err("\n");
1389 dump_tlb_all(); 1443 dump_tlb_all();
1390 } 1444 }
1391 1445
diff --git a/arch/mips/kernel/vdso.c b/arch/mips/kernel/vdso.c
index 0f1af58b036a..ed2a278722a9 100644
--- a/arch/mips/kernel/vdso.c
+++ b/arch/mips/kernel/vdso.c
@@ -16,9 +16,11 @@
16#include <linux/elf.h> 16#include <linux/elf.h>
17#include <linux/vmalloc.h> 17#include <linux/vmalloc.h>
18#include <linux/unistd.h> 18#include <linux/unistd.h>
19#include <linux/random.h>
19 20
20#include <asm/vdso.h> 21#include <asm/vdso.h>
21#include <asm/uasm.h> 22#include <asm/uasm.h>
23#include <asm/processor.h>
22 24
23/* 25/*
24 * Including <asm/unistd.h> would give use the 64-bit syscall numbers ... 26 * Including <asm/unistd.h> would give use the 64-bit syscall numbers ...
@@ -67,7 +69,18 @@ subsys_initcall(init_vdso);
67 69
68static unsigned long vdso_addr(unsigned long start) 70static unsigned long vdso_addr(unsigned long start)
69{ 71{
70 return STACK_TOP; 72 unsigned long offset = 0UL;
73
74 if (current->flags & PF_RANDOMIZE) {
75 offset = get_random_int();
76 offset <<= PAGE_SHIFT;
77 if (TASK_IS_32BIT_ADDR)
78 offset &= 0xfffffful;
79 else
80 offset &= 0xffffffful;
81 }
82
83 return STACK_TOP + offset;
71} 84}
72 85
73int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp) 86int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)