aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'arch/mips/kernel')
-rw-r--r--arch/mips/kernel/Makefile17
-rw-r--r--arch/mips/kernel/asm-offsets.c4
-rw-r--r--arch/mips/kernel/cevt-gt641xx.c10
-rw-r--r--arch/mips/kernel/cevt-r4k.c2
-rw-r--r--arch/mips/kernel/cpu-probe.c43
-rw-r--r--arch/mips/kernel/cpufreq/Kconfig41
-rw-r--r--arch/mips/kernel/cpufreq/Makefile5
-rw-r--r--arch/mips/kernel/cpufreq/loongson2_clock.c170
-rw-r--r--arch/mips/kernel/cpufreq/loongson2_cpufreq.c227
-rw-r--r--arch/mips/kernel/csrc-powertv.c180
-rw-r--r--arch/mips/kernel/ftrace.c275
-rw-r--r--arch/mips/kernel/i8259.c22
-rw-r--r--arch/mips/kernel/irq-gt641xx.c18
-rw-r--r--arch/mips/kernel/irq.c35
-rw-r--r--arch/mips/kernel/kspd.c1
-rw-r--r--arch/mips/kernel/linux32.c99
-rw-r--r--arch/mips/kernel/mcount.S189
-rw-r--r--arch/mips/kernel/mips_ksyms.c5
-rw-r--r--arch/mips/kernel/octeon_switch.S1
-rw-r--r--arch/mips/kernel/process.c8
-rw-r--r--arch/mips/kernel/ptrace.c30
-rw-r--r--arch/mips/kernel/rtlx.c2
-rw-r--r--arch/mips/kernel/scall32-o32.S1
-rw-r--r--arch/mips/kernel/scall64-64.S1
-rw-r--r--arch/mips/kernel/scall64-n32.S7
-rw-r--r--arch/mips/kernel/scall64-o32.S5
-rw-r--r--arch/mips/kernel/setup.c44
-rw-r--r--arch/mips/kernel/signal-common.h5
-rw-r--r--arch/mips/kernel/signal.c130
-rw-r--r--arch/mips/kernel/signal32.c79
-rw-r--r--arch/mips/kernel/signal_n32.c26
-rw-r--r--arch/mips/kernel/smp.c3
-rw-r--r--arch/mips/kernel/smtc.c26
-rw-r--r--arch/mips/kernel/spinlock_test.c141
-rw-r--r--arch/mips/kernel/syscall.c170
-rw-r--r--arch/mips/kernel/time.c33
-rw-r--r--arch/mips/kernel/traps.c184
-rw-r--r--arch/mips/kernel/unaligned.c25
-rw-r--r--arch/mips/kernel/vdso.c112
-rw-r--r--arch/mips/kernel/vmlinux.lds.S1
-rw-r--r--arch/mips/kernel/vpe.c1
41 files changed, 1728 insertions, 650 deletions
diff --git a/arch/mips/kernel/Makefile b/arch/mips/kernel/Makefile
index eecd2a9f155c..7a6ac501cbb5 100644
--- a/arch/mips/kernel/Makefile
+++ b/arch/mips/kernel/Makefile
@@ -2,13 +2,16 @@
2# Makefile for the Linux/MIPS kernel. 2# Makefile for the Linux/MIPS kernel.
3# 3#
4 4
5CPPFLAGS_vmlinux.lds := $(KBUILD_CFLAGS)
6
7extra-y := head.o init_task.o vmlinux.lds 5extra-y := head.o init_task.o vmlinux.lds
8 6
9obj-y += cpu-probe.o branch.o entry.o genex.o irq.o process.o \ 7obj-y += cpu-probe.o branch.o entry.o genex.o irq.o process.o \
10 ptrace.o reset.o setup.o signal.o syscall.o \ 8 ptrace.o reset.o setup.o signal.o syscall.o \
11 time.o topology.o traps.o unaligned.o watch.o 9 time.o topology.o traps.o unaligned.o watch.o vdso.o
10
11ifdef CONFIG_FUNCTION_TRACER
12CFLAGS_REMOVE_ftrace.o = -pg
13CFLAGS_REMOVE_early_printk.o = -pg
14endif
12 15
13obj-$(CONFIG_CEVT_BCM1480) += cevt-bcm1480.o 16obj-$(CONFIG_CEVT_BCM1480) += cevt-bcm1480.o
14obj-$(CONFIG_CEVT_R4K_LIB) += cevt-r4k.o 17obj-$(CONFIG_CEVT_R4K_LIB) += cevt-r4k.o
@@ -19,6 +22,7 @@ obj-$(CONFIG_CEVT_SB1250) += cevt-sb1250.o
19obj-$(CONFIG_CEVT_TXX9) += cevt-txx9.o 22obj-$(CONFIG_CEVT_TXX9) += cevt-txx9.o
20obj-$(CONFIG_CSRC_BCM1480) += csrc-bcm1480.o 23obj-$(CONFIG_CSRC_BCM1480) += csrc-bcm1480.o
21obj-$(CONFIG_CSRC_IOASIC) += csrc-ioasic.o 24obj-$(CONFIG_CSRC_IOASIC) += csrc-ioasic.o
25obj-$(CONFIG_CSRC_POWERTV) += csrc-powertv.o
22obj-$(CONFIG_CSRC_R4K_LIB) += csrc-r4k.o 26obj-$(CONFIG_CSRC_R4K_LIB) += csrc-r4k.o
23obj-$(CONFIG_CSRC_SB1250) += csrc-sb1250.o 27obj-$(CONFIG_CSRC_SB1250) += csrc-sb1250.o
24obj-$(CONFIG_SYNC_R4K) += sync-r4k.o 28obj-$(CONFIG_SYNC_R4K) += sync-r4k.o
@@ -26,6 +30,8 @@ obj-$(CONFIG_SYNC_R4K) += sync-r4k.o
26obj-$(CONFIG_STACKTRACE) += stacktrace.o 30obj-$(CONFIG_STACKTRACE) += stacktrace.o
27obj-$(CONFIG_MODULES) += mips_ksyms.o module.o 31obj-$(CONFIG_MODULES) += mips_ksyms.o module.o
28 32
33obj-$(CONFIG_FUNCTION_TRACER) += mcount.o ftrace.o
34
29obj-$(CONFIG_CPU_LOONGSON2) += r4k_fpu.o r4k_switch.o 35obj-$(CONFIG_CPU_LOONGSON2) += r4k_fpu.o r4k_switch.o
30obj-$(CONFIG_CPU_MIPS32) += r4k_fpu.o r4k_switch.o 36obj-$(CONFIG_CPU_MIPS32) += r4k_fpu.o r4k_switch.o
31obj-$(CONFIG_CPU_MIPS64) += r4k_fpu.o r4k_switch.o 37obj-$(CONFIG_CPU_MIPS64) += r4k_fpu.o r4k_switch.o
@@ -87,9 +93,14 @@ obj-$(CONFIG_GPIO_TXX9) += gpio_txx9.o
87 93
88obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o 94obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o
89obj-$(CONFIG_EARLY_PRINTK) += early_printk.o 95obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
96obj-$(CONFIG_SPINLOCK_TEST) += spinlock_test.o
90 97
91CFLAGS_cpu-bugs64.o = $(shell if $(CC) $(KBUILD_CFLAGS) -Wa,-mdaddi -c -o /dev/null -xc /dev/null >/dev/null 2>&1; then echo "-DHAVE_AS_SET_DADDI"; fi) 98CFLAGS_cpu-bugs64.o = $(shell if $(CC) $(KBUILD_CFLAGS) -Wa,-mdaddi -c -o /dev/null -xc /dev/null >/dev/null 2>&1; then echo "-DHAVE_AS_SET_DADDI"; fi)
92 99
93obj-$(CONFIG_HAVE_STD_PC_SERIAL_PORT) += 8250-platform.o 100obj-$(CONFIG_HAVE_STD_PC_SERIAL_PORT) += 8250-platform.o
94 101
102obj-$(CONFIG_MIPS_CPUFREQ) += cpufreq/
103
95EXTRA_CFLAGS += -Werror 104EXTRA_CFLAGS += -Werror
105
106CPPFLAGS_vmlinux.lds := $(KBUILD_CFLAGS)
diff --git a/arch/mips/kernel/asm-offsets.c b/arch/mips/kernel/asm-offsets.c
index 2c1e1d02338b..ca6c83218caa 100644
--- a/arch/mips/kernel/asm-offsets.c
+++ b/arch/mips/kernel/asm-offsets.c
@@ -188,11 +188,15 @@ void output_mm_defines(void)
188 DEFINE(_PTE_T_SIZE, sizeof(pte_t)); 188 DEFINE(_PTE_T_SIZE, sizeof(pte_t));
189 BLANK(); 189 BLANK();
190 DEFINE(_PGD_T_LOG2, PGD_T_LOG2); 190 DEFINE(_PGD_T_LOG2, PGD_T_LOG2);
191#ifndef __PAGETABLE_PMD_FOLDED
191 DEFINE(_PMD_T_LOG2, PMD_T_LOG2); 192 DEFINE(_PMD_T_LOG2, PMD_T_LOG2);
193#endif
192 DEFINE(_PTE_T_LOG2, PTE_T_LOG2); 194 DEFINE(_PTE_T_LOG2, PTE_T_LOG2);
193 BLANK(); 195 BLANK();
194 DEFINE(_PGD_ORDER, PGD_ORDER); 196 DEFINE(_PGD_ORDER, PGD_ORDER);
197#ifndef __PAGETABLE_PMD_FOLDED
195 DEFINE(_PMD_ORDER, PMD_ORDER); 198 DEFINE(_PMD_ORDER, PMD_ORDER);
199#endif
196 DEFINE(_PTE_ORDER, PTE_ORDER); 200 DEFINE(_PTE_ORDER, PTE_ORDER);
197 BLANK(); 201 BLANK();
198 DEFINE(_PMD_SHIFT, PMD_SHIFT); 202 DEFINE(_PMD_SHIFT, PMD_SHIFT);
diff --git a/arch/mips/kernel/cevt-gt641xx.c b/arch/mips/kernel/cevt-gt641xx.c
index f5d265eb6eae..392ef3756c56 100644
--- a/arch/mips/kernel/cevt-gt641xx.c
+++ b/arch/mips/kernel/cevt-gt641xx.c
@@ -25,7 +25,7 @@
25#include <asm/gt64120.h> 25#include <asm/gt64120.h>
26#include <asm/time.h> 26#include <asm/time.h>
27 27
28static DEFINE_SPINLOCK(gt641xx_timer_lock); 28static DEFINE_RAW_SPINLOCK(gt641xx_timer_lock);
29static unsigned int gt641xx_base_clock; 29static unsigned int gt641xx_base_clock;
30 30
31void gt641xx_set_base_clock(unsigned int clock) 31void gt641xx_set_base_clock(unsigned int clock)
@@ -49,7 +49,7 @@ static int gt641xx_timer0_set_next_event(unsigned long delta,
49{ 49{
50 u32 ctrl; 50 u32 ctrl;
51 51
52 spin_lock(&gt641xx_timer_lock); 52 raw_spin_lock(&gt641xx_timer_lock);
53 53
54 ctrl = GT_READ(GT_TC_CONTROL_OFS); 54 ctrl = GT_READ(GT_TC_CONTROL_OFS);
55 ctrl &= ~(GT_TC_CONTROL_ENTC0_MSK | GT_TC_CONTROL_SELTC0_MSK); 55 ctrl &= ~(GT_TC_CONTROL_ENTC0_MSK | GT_TC_CONTROL_SELTC0_MSK);
@@ -58,7 +58,7 @@ static int gt641xx_timer0_set_next_event(unsigned long delta,
58 GT_WRITE(GT_TC0_OFS, delta); 58 GT_WRITE(GT_TC0_OFS, delta);
59 GT_WRITE(GT_TC_CONTROL_OFS, ctrl); 59 GT_WRITE(GT_TC_CONTROL_OFS, ctrl);
60 60
61 spin_unlock(&gt641xx_timer_lock); 61 raw_spin_unlock(&gt641xx_timer_lock);
62 62
63 return 0; 63 return 0;
64} 64}
@@ -68,7 +68,7 @@ static void gt641xx_timer0_set_mode(enum clock_event_mode mode,
68{ 68{
69 u32 ctrl; 69 u32 ctrl;
70 70
71 spin_lock(&gt641xx_timer_lock); 71 raw_spin_lock(&gt641xx_timer_lock);
72 72
73 ctrl = GT_READ(GT_TC_CONTROL_OFS); 73 ctrl = GT_READ(GT_TC_CONTROL_OFS);
74 ctrl &= ~(GT_TC_CONTROL_ENTC0_MSK | GT_TC_CONTROL_SELTC0_MSK); 74 ctrl &= ~(GT_TC_CONTROL_ENTC0_MSK | GT_TC_CONTROL_SELTC0_MSK);
@@ -86,7 +86,7 @@ static void gt641xx_timer0_set_mode(enum clock_event_mode mode,
86 86
87 GT_WRITE(GT_TC_CONTROL_OFS, ctrl); 87 GT_WRITE(GT_TC_CONTROL_OFS, ctrl);
88 88
89 spin_unlock(&gt641xx_timer_lock); 89 raw_spin_unlock(&gt641xx_timer_lock);
90} 90}
91 91
92static void gt641xx_timer0_event_handler(struct clock_event_device *dev) 92static void gt641xx_timer0_event_handler(struct clock_event_device *dev)
diff --git a/arch/mips/kernel/cevt-r4k.c b/arch/mips/kernel/cevt-r4k.c
index b469ad05d520..0b2450ceb13f 100644
--- a/arch/mips/kernel/cevt-r4k.c
+++ b/arch/mips/kernel/cevt-r4k.c
@@ -97,7 +97,7 @@ void mips_event_handler(struct clock_event_device *dev)
97 */ 97 */
98static int c0_compare_int_pending(void) 98static int c0_compare_int_pending(void)
99{ 99{
100 return (read_c0_cause() >> cp0_compare_irq) & 0x100; 100 return (read_c0_cause() >> cp0_compare_irq_shift) & (1ul << CAUSEB_IP);
101} 101}
102 102
103/* 103/*
diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c
index 7a51866068a4..be5bb16be4e0 100644
--- a/arch/mips/kernel/cpu-probe.c
+++ b/arch/mips/kernel/cpu-probe.c
@@ -16,6 +16,7 @@
16#include <linux/ptrace.h> 16#include <linux/ptrace.h>
17#include <linux/smp.h> 17#include <linux/smp.h>
18#include <linux/stddef.h> 18#include <linux/stddef.h>
19#include <linux/module.h>
19 20
20#include <asm/bugs.h> 21#include <asm/bugs.h>
21#include <asm/cpu.h> 22#include <asm/cpu.h>
@@ -32,6 +33,7 @@
32 * the CPU very much. 33 * the CPU very much.
33 */ 34 */
34void (*cpu_wait)(void); 35void (*cpu_wait)(void);
36EXPORT_SYMBOL(cpu_wait);
35 37
36static void r3081_wait(void) 38static void r3081_wait(void)
37{ 39{
@@ -160,6 +162,7 @@ void __init check_wait(void)
160 case CPU_BCM6348: 162 case CPU_BCM6348:
161 case CPU_BCM6358: 163 case CPU_BCM6358:
162 case CPU_CAVIUM_OCTEON: 164 case CPU_CAVIUM_OCTEON:
165 case CPU_CAVIUM_OCTEON_PLUS:
163 cpu_wait = r4k_wait; 166 cpu_wait = r4k_wait;
164 break; 167 break;
165 168
@@ -282,6 +285,15 @@ static inline int __cpu_has_fpu(void)
282 return ((cpu_get_fpu_id() & 0xff00) != FPIR_IMP_NONE); 285 return ((cpu_get_fpu_id() & 0xff00) != FPIR_IMP_NONE);
283} 286}
284 287
288static inline void cpu_probe_vmbits(struct cpuinfo_mips *c)
289{
290#ifdef __NEED_VMBITS_PROBE
291 write_c0_entryhi(0x3fffffffffffe000ULL);
292 back_to_back_c0_hazard();
293 c->vmbits = fls64(read_c0_entryhi() & 0x3fffffffffffe000ULL);
294#endif
295}
296
285#define R4K_OPTS (MIPS_CPU_TLB | MIPS_CPU_4KEX | MIPS_CPU_4K_CACHE \ 297#define R4K_OPTS (MIPS_CPU_TLB | MIPS_CPU_4KEX | MIPS_CPU_4K_CACHE \
286 | MIPS_CPU_COUNTER) 298 | MIPS_CPU_COUNTER)
287 299
@@ -689,6 +701,19 @@ static inline unsigned int decode_config3(struct cpuinfo_mips *c)
689 return config3 & MIPS_CONF_M; 701 return config3 & MIPS_CONF_M;
690} 702}
691 703
704static inline unsigned int decode_config4(struct cpuinfo_mips *c)
705{
706 unsigned int config4;
707
708 config4 = read_c0_config4();
709
710 if ((config4 & MIPS_CONF4_MMUEXTDEF) == MIPS_CONF4_MMUEXTDEF_MMUSIZEEXT
711 && cpu_has_tlb)
712 c->tlbsize += (config4 & MIPS_CONF4_MMUSIZEEXT) * 0x40;
713
714 return config4 & MIPS_CONF_M;
715}
716
692static void __cpuinit decode_configs(struct cpuinfo_mips *c) 717static void __cpuinit decode_configs(struct cpuinfo_mips *c)
693{ 718{
694 int ok; 719 int ok;
@@ -707,6 +732,8 @@ static void __cpuinit decode_configs(struct cpuinfo_mips *c)
707 ok = decode_config2(c); 732 ok = decode_config2(c);
708 if (ok) 733 if (ok)
709 ok = decode_config3(c); 734 ok = decode_config3(c);
735 if (ok)
736 ok = decode_config4(c);
710 737
711 mips_probe_watch_registers(c); 738 mips_probe_watch_registers(c);
712} 739}
@@ -720,9 +747,6 @@ static inline void cpu_probe_mips(struct cpuinfo_mips *c, unsigned int cpu)
720 __cpu_name[cpu] = "MIPS 4Kc"; 747 __cpu_name[cpu] = "MIPS 4Kc";
721 break; 748 break;
722 case PRID_IMP_4KEC: 749 case PRID_IMP_4KEC:
723 c->cputype = CPU_4KEC;
724 __cpu_name[cpu] = "MIPS 4KEc";
725 break;
726 case PRID_IMP_4KECR2: 750 case PRID_IMP_4KECR2:
727 c->cputype = CPU_4KEC; 751 c->cputype = CPU_4KEC;
728 __cpu_name[cpu] = "MIPS 4KEc"; 752 __cpu_name[cpu] = "MIPS 4KEc";
@@ -888,12 +912,18 @@ static inline void cpu_probe_cavium(struct cpuinfo_mips *c, unsigned int cpu)
888 case PRID_IMP_CAVIUM_CN38XX: 912 case PRID_IMP_CAVIUM_CN38XX:
889 case PRID_IMP_CAVIUM_CN31XX: 913 case PRID_IMP_CAVIUM_CN31XX:
890 case PRID_IMP_CAVIUM_CN30XX: 914 case PRID_IMP_CAVIUM_CN30XX:
915 c->cputype = CPU_CAVIUM_OCTEON;
916 __cpu_name[cpu] = "Cavium Octeon";
917 goto platform;
891 case PRID_IMP_CAVIUM_CN58XX: 918 case PRID_IMP_CAVIUM_CN58XX:
892 case PRID_IMP_CAVIUM_CN56XX: 919 case PRID_IMP_CAVIUM_CN56XX:
893 case PRID_IMP_CAVIUM_CN50XX: 920 case PRID_IMP_CAVIUM_CN50XX:
894 case PRID_IMP_CAVIUM_CN52XX: 921 case PRID_IMP_CAVIUM_CN52XX:
895 c->cputype = CPU_CAVIUM_OCTEON; 922 c->cputype = CPU_CAVIUM_OCTEON_PLUS;
896 __cpu_name[cpu] = "Cavium Octeon"; 923 __cpu_name[cpu] = "Cavium Octeon+";
924platform:
925 if (cpu == 0)
926 __elf_platform = "octeon";
897 break; 927 break;
898 default: 928 default:
899 printk(KERN_INFO "Unknown Octeon chip!\n"); 929 printk(KERN_INFO "Unknown Octeon chip!\n");
@@ -903,6 +933,7 @@ static inline void cpu_probe_cavium(struct cpuinfo_mips *c, unsigned int cpu)
903} 933}
904 934
905const char *__cpu_name[NR_CPUS]; 935const char *__cpu_name[NR_CPUS];
936const char *__elf_platform;
906 937
907__cpuinit void cpu_probe(void) 938__cpuinit void cpu_probe(void)
908{ 939{
@@ -967,6 +998,8 @@ __cpuinit void cpu_probe(void)
967 c->srsets = ((read_c0_srsctl() >> 26) & 0x0f) + 1; 998 c->srsets = ((read_c0_srsctl() >> 26) & 0x0f) + 1;
968 else 999 else
969 c->srsets = 1; 1000 c->srsets = 1;
1001
1002 cpu_probe_vmbits(c);
970} 1003}
971 1004
972__cpuinit void cpu_report(void) 1005__cpuinit void cpu_report(void)
diff --git a/arch/mips/kernel/cpufreq/Kconfig b/arch/mips/kernel/cpufreq/Kconfig
new file mode 100644
index 000000000000..58c601eee6fd
--- /dev/null
+++ b/arch/mips/kernel/cpufreq/Kconfig
@@ -0,0 +1,41 @@
1#
2# CPU Frequency scaling
3#
4
5config MIPS_EXTERNAL_TIMER
6 bool
7
8config MIPS_CPUFREQ
9 bool
10 default y
11 depends on CPU_SUPPORTS_CPUFREQ && MIPS_EXTERNAL_TIMER
12
13if MIPS_CPUFREQ
14
15menu "CPU Frequency scaling"
16
17source "drivers/cpufreq/Kconfig"
18
19if CPU_FREQ
20
21comment "CPUFreq processor drivers"
22
23config LOONGSON2_CPUFREQ
24 tristate "Loongson2 CPUFreq Driver"
25 select CPU_FREQ_TABLE
26 depends on MIPS_CPUFREQ
27 help
28 This option adds a CPUFreq driver for loongson processors which
29 support software configurable cpu frequency.
30
31 Loongson2F and it's successors support this feature.
32
33 For details, take a look at <file:Documentation/cpu-freq/>.
34
35 If in doubt, say N.
36
37endif # CPU_FREQ
38
39endmenu
40
41endif # MIPS_CPUFREQ
diff --git a/arch/mips/kernel/cpufreq/Makefile b/arch/mips/kernel/cpufreq/Makefile
new file mode 100644
index 000000000000..c3479a432efe
--- /dev/null
+++ b/arch/mips/kernel/cpufreq/Makefile
@@ -0,0 +1,5 @@
1#
2# Makefile for the Linux/MIPS cpufreq.
3#
4
5obj-$(CONFIG_LOONGSON2_CPUFREQ) += loongson2_cpufreq.o loongson2_clock.o
diff --git a/arch/mips/kernel/cpufreq/loongson2_clock.c b/arch/mips/kernel/cpufreq/loongson2_clock.c
new file mode 100644
index 000000000000..cefc6e259baf
--- /dev/null
+++ b/arch/mips/kernel/cpufreq/loongson2_clock.c
@@ -0,0 +1,170 @@
1/*
2 * Copyright (C) 2006 - 2008 Lemote Inc. & Insititute of Computing Technology
3 * Author: Yanhua, yanh@lemote.com
4 *
5 * This file is subject to the terms and conditions of the GNU General Public
6 * License. See the file "COPYING" in the main directory of this archive
7 * for more details.
8 */
9
10#include <linux/cpufreq.h>
11#include <linux/platform_device.h>
12
13#include <asm/clock.h>
14
15#include <loongson.h>
16
17static LIST_HEAD(clock_list);
18static DEFINE_SPINLOCK(clock_lock);
19static DEFINE_MUTEX(clock_list_sem);
20
21/* Minimum CLK support */
22enum {
23 DC_ZERO, DC_25PT = 2, DC_37PT, DC_50PT, DC_62PT, DC_75PT,
24 DC_87PT, DC_DISABLE, DC_RESV
25};
26
27struct cpufreq_frequency_table loongson2_clockmod_table[] = {
28 {DC_RESV, CPUFREQ_ENTRY_INVALID},
29 {DC_ZERO, CPUFREQ_ENTRY_INVALID},
30 {DC_25PT, 0},
31 {DC_37PT, 0},
32 {DC_50PT, 0},
33 {DC_62PT, 0},
34 {DC_75PT, 0},
35 {DC_87PT, 0},
36 {DC_DISABLE, 0},
37 {DC_RESV, CPUFREQ_TABLE_END},
38};
39EXPORT_SYMBOL_GPL(loongson2_clockmod_table);
40
41static struct clk cpu_clk = {
42 .name = "cpu_clk",
43 .flags = CLK_ALWAYS_ENABLED | CLK_RATE_PROPAGATES,
44 .rate = 800000000,
45};
46
47struct clk *clk_get(struct device *dev, const char *id)
48{
49 return &cpu_clk;
50}
51EXPORT_SYMBOL(clk_get);
52
53static void propagate_rate(struct clk *clk)
54{
55 struct clk *clkp;
56
57 list_for_each_entry(clkp, &clock_list, node) {
58 if (likely(clkp->parent != clk))
59 continue;
60 if (likely(clkp->ops && clkp->ops->recalc))
61 clkp->ops->recalc(clkp);
62 if (unlikely(clkp->flags & CLK_RATE_PROPAGATES))
63 propagate_rate(clkp);
64 }
65}
66
67int clk_enable(struct clk *clk)
68{
69 return 0;
70}
71EXPORT_SYMBOL(clk_enable);
72
73void clk_disable(struct clk *clk)
74{
75}
76EXPORT_SYMBOL(clk_disable);
77
78unsigned long clk_get_rate(struct clk *clk)
79{
80 return (unsigned long)clk->rate;
81}
82EXPORT_SYMBOL(clk_get_rate);
83
84void clk_put(struct clk *clk)
85{
86}
87EXPORT_SYMBOL(clk_put);
88
89int clk_set_rate(struct clk *clk, unsigned long rate)
90{
91 return clk_set_rate_ex(clk, rate, 0);
92}
93EXPORT_SYMBOL_GPL(clk_set_rate);
94
95int clk_set_rate_ex(struct clk *clk, unsigned long rate, int algo_id)
96{
97 int ret = 0;
98 int regval;
99 int i;
100
101 if (likely(clk->ops && clk->ops->set_rate)) {
102 unsigned long flags;
103
104 spin_lock_irqsave(&clock_lock, flags);
105 ret = clk->ops->set_rate(clk, rate, algo_id);
106 spin_unlock_irqrestore(&clock_lock, flags);
107 }
108
109 if (unlikely(clk->flags & CLK_RATE_PROPAGATES))
110 propagate_rate(clk);
111
112 for (i = 0; loongson2_clockmod_table[i].frequency != CPUFREQ_TABLE_END;
113 i++) {
114 if (loongson2_clockmod_table[i].frequency ==
115 CPUFREQ_ENTRY_INVALID)
116 continue;
117 if (rate == loongson2_clockmod_table[i].frequency)
118 break;
119 }
120 if (rate != loongson2_clockmod_table[i].frequency)
121 return -ENOTSUPP;
122
123 clk->rate = rate;
124
125 regval = LOONGSON_CHIPCFG0;
126 regval = (regval & ~0x7) | (loongson2_clockmod_table[i].index - 1);
127 LOONGSON_CHIPCFG0 = regval;
128
129 return ret;
130}
131EXPORT_SYMBOL_GPL(clk_set_rate_ex);
132
133long clk_round_rate(struct clk *clk, unsigned long rate)
134{
135 if (likely(clk->ops && clk->ops->round_rate)) {
136 unsigned long flags, rounded;
137
138 spin_lock_irqsave(&clock_lock, flags);
139 rounded = clk->ops->round_rate(clk, rate);
140 spin_unlock_irqrestore(&clock_lock, flags);
141
142 return rounded;
143 }
144
145 return rate;
146}
147EXPORT_SYMBOL_GPL(clk_round_rate);
148
149/*
150 * This is the simple version of Loongson-2 wait, Maybe we need do this in
151 * interrupt disabled content
152 */
153
154DEFINE_SPINLOCK(loongson2_wait_lock);
155void loongson2_cpu_wait(void)
156{
157 u32 cpu_freq;
158 unsigned long flags;
159
160 spin_lock_irqsave(&loongson2_wait_lock, flags);
161 cpu_freq = LOONGSON_CHIPCFG0;
162 LOONGSON_CHIPCFG0 &= ~0x7; /* Put CPU into wait mode */
163 LOONGSON_CHIPCFG0 = cpu_freq; /* Restore CPU state */
164 spin_unlock_irqrestore(&loongson2_wait_lock, flags);
165}
166EXPORT_SYMBOL_GPL(loongson2_cpu_wait);
167
168MODULE_AUTHOR("Yanhua <yanh@lemote.com>");
169MODULE_DESCRIPTION("cpufreq driver for Loongson 2F");
170MODULE_LICENSE("GPL");
diff --git a/arch/mips/kernel/cpufreq/loongson2_cpufreq.c b/arch/mips/kernel/cpufreq/loongson2_cpufreq.c
new file mode 100644
index 000000000000..2f6a0b147ab8
--- /dev/null
+++ b/arch/mips/kernel/cpufreq/loongson2_cpufreq.c
@@ -0,0 +1,227 @@
1/*
2 * Cpufreq driver for the loongson-2 processors
3 *
4 * The 2E revision of loongson processor not support this feature.
5 *
6 * Copyright (C) 2006 - 2008 Lemote Inc. & Insititute of Computing Technology
7 * Author: Yanhua, yanh@lemote.com
8 *
9 * This file is subject to the terms and conditions of the GNU General Public
10 * License. See the file "COPYING" in the main directory of this archive
11 * for more details.
12 */
13#include <linux/cpufreq.h>
14#include <linux/module.h>
15#include <linux/err.h>
16#include <linux/sched.h> /* set_cpus_allowed() */
17#include <linux/delay.h>
18#include <linux/platform_device.h>
19
20#include <asm/clock.h>
21
22#include <loongson.h>
23
24static uint nowait;
25
26static struct clk *cpuclk;
27
28static void (*saved_cpu_wait) (void);
29
30static int loongson2_cpu_freq_notifier(struct notifier_block *nb,
31 unsigned long val, void *data);
32
33static struct notifier_block loongson2_cpufreq_notifier_block = {
34 .notifier_call = loongson2_cpu_freq_notifier
35};
36
37static int loongson2_cpu_freq_notifier(struct notifier_block *nb,
38 unsigned long val, void *data)
39{
40 if (val == CPUFREQ_POSTCHANGE)
41 current_cpu_data.udelay_val = loops_per_jiffy;
42
43 return 0;
44}
45
46static unsigned int loongson2_cpufreq_get(unsigned int cpu)
47{
48 return clk_get_rate(cpuclk);
49}
50
51/*
52 * Here we notify other drivers of the proposed change and the final change.
53 */
54static int loongson2_cpufreq_target(struct cpufreq_policy *policy,
55 unsigned int target_freq,
56 unsigned int relation)
57{
58 unsigned int cpu = policy->cpu;
59 unsigned int newstate = 0;
60 cpumask_t cpus_allowed;
61 struct cpufreq_freqs freqs;
62 unsigned int freq;
63
64 if (!cpu_online(cpu))
65 return -ENODEV;
66
67 cpus_allowed = current->cpus_allowed;
68 set_cpus_allowed(current, cpumask_of_cpu(cpu));
69
70 if (cpufreq_frequency_table_target
71 (policy, &loongson2_clockmod_table[0], target_freq, relation,
72 &newstate))
73 return -EINVAL;
74
75 freq =
76 ((cpu_clock_freq / 1000) *
77 loongson2_clockmod_table[newstate].index) / 8;
78 if (freq < policy->min || freq > policy->max)
79 return -EINVAL;
80
81 pr_debug("cpufreq: requested frequency %u Hz\n", target_freq * 1000);
82
83 freqs.cpu = cpu;
84 freqs.old = loongson2_cpufreq_get(cpu);
85 freqs.new = freq;
86 freqs.flags = 0;
87
88 if (freqs.new == freqs.old)
89 return 0;
90
91 /* notifiers */
92 cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
93
94 set_cpus_allowed(current, cpus_allowed);
95
96 /* setting the cpu frequency */
97 clk_set_rate(cpuclk, freq);
98
99 /* notifiers */
100 cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
101
102 pr_debug("cpufreq: set frequency %u kHz\n", freq);
103
104 return 0;
105}
106
107static int loongson2_cpufreq_cpu_init(struct cpufreq_policy *policy)
108{
109 int i;
110
111 if (!cpu_online(policy->cpu))
112 return -ENODEV;
113
114 cpuclk = clk_get(NULL, "cpu_clk");
115 if (IS_ERR(cpuclk)) {
116 printk(KERN_ERR "cpufreq: couldn't get CPU clk\n");
117 return PTR_ERR(cpuclk);
118 }
119
120 cpuclk->rate = cpu_clock_freq / 1000;
121 if (!cpuclk->rate)
122 return -EINVAL;
123
124 /* clock table init */
125 for (i = 2;
126 (loongson2_clockmod_table[i].frequency != CPUFREQ_TABLE_END);
127 i++)
128 loongson2_clockmod_table[i].frequency = (cpuclk->rate * i) / 8;
129
130 policy->cur = loongson2_cpufreq_get(policy->cpu);
131
132 cpufreq_frequency_table_get_attr(&loongson2_clockmod_table[0],
133 policy->cpu);
134
135 return cpufreq_frequency_table_cpuinfo(policy,
136 &loongson2_clockmod_table[0]);
137}
138
139static int loongson2_cpufreq_verify(struct cpufreq_policy *policy)
140{
141 return cpufreq_frequency_table_verify(policy,
142 &loongson2_clockmod_table[0]);
143}
144
145static int loongson2_cpufreq_exit(struct cpufreq_policy *policy)
146{
147 clk_put(cpuclk);
148 return 0;
149}
150
151static struct freq_attr *loongson2_table_attr[] = {
152 &cpufreq_freq_attr_scaling_available_freqs,
153 NULL,
154};
155
156static struct cpufreq_driver loongson2_cpufreq_driver = {
157 .owner = THIS_MODULE,
158 .name = "loongson2",
159 .init = loongson2_cpufreq_cpu_init,
160 .verify = loongson2_cpufreq_verify,
161 .target = loongson2_cpufreq_target,
162 .get = loongson2_cpufreq_get,
163 .exit = loongson2_cpufreq_exit,
164 .attr = loongson2_table_attr,
165};
166
167static struct platform_device_id platform_device_ids[] = {
168 {
169 .name = "loongson2_cpufreq",
170 },
171 {}
172};
173
174MODULE_DEVICE_TABLE(platform, platform_device_ids);
175
176static struct platform_driver platform_driver = {
177 .driver = {
178 .name = "loongson2_cpufreq",
179 .owner = THIS_MODULE,
180 },
181 .id_table = platform_device_ids,
182};
183
184static int __init cpufreq_init(void)
185{
186 int ret;
187
188 /* Register platform stuff */
189 ret = platform_driver_register(&platform_driver);
190 if (ret)
191 return ret;
192
193 pr_info("cpufreq: Loongson-2F CPU frequency driver.\n");
194
195 cpufreq_register_notifier(&loongson2_cpufreq_notifier_block,
196 CPUFREQ_TRANSITION_NOTIFIER);
197
198 ret = cpufreq_register_driver(&loongson2_cpufreq_driver);
199
200 if (!ret && !nowait) {
201 saved_cpu_wait = cpu_wait;
202 cpu_wait = loongson2_cpu_wait;
203 }
204
205 return ret;
206}
207
208static void __exit cpufreq_exit(void)
209{
210 if (!nowait && saved_cpu_wait)
211 cpu_wait = saved_cpu_wait;
212 cpufreq_unregister_driver(&loongson2_cpufreq_driver);
213 cpufreq_unregister_notifier(&loongson2_cpufreq_notifier_block,
214 CPUFREQ_TRANSITION_NOTIFIER);
215
216 platform_driver_unregister(&platform_driver);
217}
218
219module_init(cpufreq_init);
220module_exit(cpufreq_exit);
221
222module_param(nowait, uint, 0644);
223MODULE_PARM_DESC(nowait, "Disable Loongson-2F specific wait");
224
225MODULE_AUTHOR("Yanhua <yanh@lemote.com>");
226MODULE_DESCRIPTION("cpufreq driver for Loongson2F");
227MODULE_LICENSE("GPL");
diff --git a/arch/mips/kernel/csrc-powertv.c b/arch/mips/kernel/csrc-powertv.c
new file mode 100644
index 000000000000..a27c16c8690e
--- /dev/null
+++ b/arch/mips/kernel/csrc-powertv.c
@@ -0,0 +1,180 @@
1/*
2 * Copyright (C) 2008 Scientific-Atlanta, Inc.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17 */
18/*
19 * The file comes from kernel/csrc-r4k.c
20 */
21#include <linux/clocksource.h>
22#include <linux/init.h>
23
24#include <asm/time.h> /* Not included in linux/time.h */
25
26#include <asm/mach-powertv/asic_regs.h>
27#include "powertv-clock.h"
28
29/* MIPS PLL Register Definitions */
30#define PLL_GET_M(x) (((x) >> 8) & 0x000000FF)
31#define PLL_GET_N(x) (((x) >> 16) & 0x000000FF)
32#define PLL_GET_P(x) (((x) >> 24) & 0x00000007)
33
34/*
35 * returns: Clock frequency in kHz
36 */
37unsigned int __init mips_get_pll_freq(void)
38{
39 unsigned int pll_reg, m, n, p;
40 unsigned int fin = 54000; /* Base frequency in kHz */
41 unsigned int fout;
42
43 /* Read PLL register setting */
44 pll_reg = asic_read(mips_pll_setup);
45 m = PLL_GET_M(pll_reg);
46 n = PLL_GET_N(pll_reg);
47 p = PLL_GET_P(pll_reg);
48 pr_info("MIPS PLL Register:0x%x M=%d N=%d P=%d\n", pll_reg, m, n, p);
49
50 /* Calculate clock frequency = (2 * N * 54MHz) / (M * (2**P)) */
51 fout = ((2 * n * fin) / (m * (0x01 << p)));
52
53 pr_info("MIPS Clock Freq=%d kHz\n", fout);
54
55 return fout;
56}
57
58static cycle_t c0_hpt_read(struct clocksource *cs)
59{
60 return read_c0_count();
61}
62
63static struct clocksource clocksource_mips = {
64 .name = "powertv-counter",
65 .read = c0_hpt_read,
66 .mask = CLOCKSOURCE_MASK(32),
67 .flags = CLOCK_SOURCE_IS_CONTINUOUS,
68};
69
70static void __init powertv_c0_hpt_clocksource_init(void)
71{
72 unsigned int pll_freq = mips_get_pll_freq();
73
74 pr_info("CPU frequency %d.%02d MHz\n", pll_freq / 1000,
75 (pll_freq % 1000) * 100 / 1000);
76
77 mips_hpt_frequency = pll_freq / 2 * 1000;
78
79 clocksource_mips.rating = 200 + mips_hpt_frequency / 10000000;
80
81 clocksource_set_clock(&clocksource_mips, mips_hpt_frequency);
82
83 clocksource_register(&clocksource_mips);
84}
85
86/**
87 * struct tim_c - free running counter
88 * @hi: High 16 bits of the counter
89 * @lo: Low 32 bits of the counter
90 *
91 * Lays out the structure of the free running counter in memory. This counter
92 * increments at a rate of 27 MHz/8 on all platforms.
93 */
94struct tim_c {
95 unsigned int hi;
96 unsigned int lo;
97};
98
99static struct tim_c *tim_c;
100
101static cycle_t tim_c_read(struct clocksource *cs)
102{
103 unsigned int hi;
104 unsigned int next_hi;
105 unsigned int lo;
106
107 hi = readl(&tim_c->hi);
108
109 for (;;) {
110 lo = readl(&tim_c->lo);
111 next_hi = readl(&tim_c->hi);
112 if (next_hi == hi)
113 break;
114 hi = next_hi;
115 }
116
117pr_crit("%s: read %llx\n", __func__, ((u64) hi << 32) | lo);
118 return ((u64) hi << 32) | lo;
119}
120
121#define TIM_C_SIZE 48 /* # bits in the timer */
122
123static struct clocksource clocksource_tim_c = {
124 .name = "powertv-tim_c",
125 .read = tim_c_read,
126 .mask = CLOCKSOURCE_MASK(TIM_C_SIZE),
127 .flags = CLOCK_SOURCE_IS_CONTINUOUS,
128};
129
130/**
131 * powertv_tim_c_clocksource_init - set up a clock source for the TIM_C clock
132 *
133 * The hard part here is coming up with a constant k and shift s such that
134 * the 48-bit TIM_C value multiplied by k doesn't overflow and that value,
135 * when shifted right by s, yields the corresponding number of nanoseconds.
136 * We know that TIM_C counts at 27 MHz/8, so each cycle corresponds to
137 * 1 / (27,000,000/8) seconds. Multiply that by a billion and you get the
138 * number of nanoseconds. Since the TIM_C value has 48 bits and the math is
139 * done in 64 bits, avoiding an overflow means that k must be less than
140 * 64 - 48 = 16 bits.
141 */
142static void __init powertv_tim_c_clocksource_init(void)
143{
144 int prescale;
145 unsigned long dividend;
146 unsigned long k;
147 int s;
148 const int max_k_bits = (64 - 48) - 1;
149 const unsigned long billion = 1000000000;
150 const unsigned long counts_per_second = 27000000 / 8;
151
152 prescale = BITS_PER_LONG - ilog2(billion) - 1;
153 dividend = billion << prescale;
154 k = dividend / counts_per_second;
155 s = ilog2(k) - max_k_bits;
156
157 if (s < 0)
158 s = prescale;
159
160 else {
161 k >>= s;
162 s += prescale;
163 }
164
165 clocksource_tim_c.mult = k;
166 clocksource_tim_c.shift = s;
167 clocksource_tim_c.rating = 200;
168
169 clocksource_register(&clocksource_tim_c);
170 tim_c = (struct tim_c *) asic_reg_addr(tim_ch);
171}
172
173/**
174 powertv_clocksource_init - initialize all clocksources
175 */
176void __init powertv_clocksource_init(void)
177{
178 powertv_c0_hpt_clocksource_init();
179 powertv_tim_c_clocksource_init();
180}
diff --git a/arch/mips/kernel/ftrace.c b/arch/mips/kernel/ftrace.c
new file mode 100644
index 000000000000..e9e64e0ff7aa
--- /dev/null
+++ b/arch/mips/kernel/ftrace.c
@@ -0,0 +1,275 @@
1/*
2 * Code for replacing ftrace calls with jumps.
3 *
4 * Copyright (C) 2007-2008 Steven Rostedt <srostedt@redhat.com>
5 * Copyright (C) 2009 DSLab, Lanzhou University, China
6 * Author: Wu Zhangjin <wuzhangjin@gmail.com>
7 *
8 * Thanks goes to Steven Rostedt for writing the original x86 version.
9 */
10
11#include <linux/uaccess.h>
12#include <linux/init.h>
13#include <linux/ftrace.h>
14
15#include <asm/cacheflush.h>
16#include <asm/asm.h>
17#include <asm/asm-offsets.h>
18
19#ifdef CONFIG_DYNAMIC_FTRACE
20
21#define JAL 0x0c000000 /* jump & link: ip --> ra, jump to target */
22#define ADDR_MASK 0x03ffffff /* op_code|addr : 31...26|25 ....0 */
23#define jump_insn_encode(op_code, addr) \
24 ((unsigned int)((op_code) | (((addr) >> 2) & ADDR_MASK)))
25
26static unsigned int ftrace_nop = 0x00000000;
27
28static int ftrace_modify_code(unsigned long ip, unsigned int new_code)
29{
30 int faulted;
31
32 /* *(unsigned int *)ip = new_code; */
33 safe_store_code(new_code, ip, faulted);
34
35 if (unlikely(faulted))
36 return -EFAULT;
37
38 flush_icache_range(ip, ip + 8);
39
40 return 0;
41}
42
43static int lui_v1;
44static int jal_mcount;
45
46int ftrace_make_nop(struct module *mod,
47 struct dyn_ftrace *rec, unsigned long addr)
48{
49 unsigned int new;
50 int faulted;
51 unsigned long ip = rec->ip;
52
53 /* We have compiled module with -mlong-calls, but compiled the kernel
54 * without it, we need to cope with them respectively. */
55 if (ip & 0x40000000) {
56 /* record it for ftrace_make_call */
57 if (lui_v1 == 0) {
58 /* lui_v1 = *(unsigned int *)ip; */
59 safe_load_code(lui_v1, ip, faulted);
60
61 if (unlikely(faulted))
62 return -EFAULT;
63 }
64
65 /* lui v1, hi_16bit_of_mcount --> b 1f (0x10000004)
66 * addiu v1, v1, low_16bit_of_mcount
67 * move at, ra
68 * jalr v1
69 * nop
70 * 1f: (ip + 12)
71 */
72 new = 0x10000004;
73 } else {
74 /* record/calculate it for ftrace_make_call */
75 if (jal_mcount == 0) {
76 /* We can record it directly like this:
77 * jal_mcount = *(unsigned int *)ip;
78 * Herein, jump over the first two nop instructions */
79 jal_mcount = jump_insn_encode(JAL, (MCOUNT_ADDR + 8));
80 }
81
82 /* move at, ra
83 * jalr v1 --> nop
84 */
85 new = ftrace_nop;
86 }
87 return ftrace_modify_code(ip, new);
88}
89
90static int modified; /* initialized as 0 by default */
91
92int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
93{
94 unsigned int new;
95 unsigned long ip = rec->ip;
96
97 /* We just need to remove the "b ftrace_stub" at the fist time! */
98 if (modified == 0) {
99 modified = 1;
100 ftrace_modify_code(addr, ftrace_nop);
101 }
102 /* ip, module: 0xc0000000, kernel: 0x80000000 */
103 new = (ip & 0x40000000) ? lui_v1 : jal_mcount;
104
105 return ftrace_modify_code(ip, new);
106}
107
108#define FTRACE_CALL_IP ((unsigned long)(&ftrace_call))
109
110int ftrace_update_ftrace_func(ftrace_func_t func)
111{
112 unsigned int new;
113
114 new = jump_insn_encode(JAL, (unsigned long)func);
115
116 return ftrace_modify_code(FTRACE_CALL_IP, new);
117}
118
119int __init ftrace_dyn_arch_init(void *data)
120{
121 /* The return code is retured via data */
122 *(unsigned long *)data = 0;
123
124 return 0;
125}
126#endif /* CONFIG_DYNAMIC_FTRACE */
127
128#ifdef CONFIG_FUNCTION_GRAPH_TRACER
129
130#ifdef CONFIG_DYNAMIC_FTRACE
131
132extern void ftrace_graph_call(void);
133#define JMP 0x08000000 /* jump to target directly */
134#define CALL_FTRACE_GRAPH_CALLER \
135 jump_insn_encode(JMP, (unsigned long)(&ftrace_graph_caller))
136#define FTRACE_GRAPH_CALL_IP ((unsigned long)(&ftrace_graph_call))
137
138int ftrace_enable_ftrace_graph_caller(void)
139{
140 return ftrace_modify_code(FTRACE_GRAPH_CALL_IP,
141 CALL_FTRACE_GRAPH_CALLER);
142}
143
144int ftrace_disable_ftrace_graph_caller(void)
145{
146 return ftrace_modify_code(FTRACE_GRAPH_CALL_IP, ftrace_nop);
147}
148
149#endif /* !CONFIG_DYNAMIC_FTRACE */
150
151#ifndef KBUILD_MCOUNT_RA_ADDRESS
152#define S_RA_SP (0xafbf << 16) /* s{d,w} ra, offset(sp) */
153#define S_R_SP (0xafb0 << 16) /* s{d,w} R, offset(sp) */
154#define OFFSET_MASK 0xffff /* stack offset range: 0 ~ PT_SIZE */
155
156unsigned long ftrace_get_parent_addr(unsigned long self_addr,
157 unsigned long parent,
158 unsigned long parent_addr,
159 unsigned long fp)
160{
161 unsigned long sp, ip, ra;
162 unsigned int code;
163 int faulted;
164
165 /* in module or kernel? */
166 if (self_addr & 0x40000000) {
167 /* module: move to the instruction "lui v1, HI_16BIT_OF_MCOUNT" */
168 ip = self_addr - 20;
169 } else {
170 /* kernel: move to the instruction "move ra, at" */
171 ip = self_addr - 12;
172 }
173
174 /* search the text until finding the non-store instruction or "s{d,w}
175 * ra, offset(sp)" instruction */
176 do {
177 ip -= 4;
178
179 /* get the code at "ip": code = *(unsigned int *)ip; */
180 safe_load_code(code, ip, faulted);
181
182 if (unlikely(faulted))
183 return 0;
184
185 /* If we hit the non-store instruction before finding where the
186 * ra is stored, then this is a leaf function and it does not
187 * store the ra on the stack. */
188 if ((code & S_R_SP) != S_R_SP)
189 return parent_addr;
190
191 } while (((code & S_RA_SP) != S_RA_SP));
192
193 sp = fp + (code & OFFSET_MASK);
194
195 /* ra = *(unsigned long *)sp; */
196 safe_load_stack(ra, sp, faulted);
197 if (unlikely(faulted))
198 return 0;
199
200 if (ra == parent)
201 return sp;
202 return 0;
203}
204
205#endif
206
207/*
208 * Hook the return address and push it in the stack of return addrs
209 * in current thread info.
210 */
211void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr,
212 unsigned long fp)
213{
214 unsigned long old;
215 struct ftrace_graph_ent trace;
216 unsigned long return_hooker = (unsigned long)
217 &return_to_handler;
218 int faulted;
219
220 if (unlikely(atomic_read(&current->tracing_graph_pause)))
221 return;
222
223 /* "parent" is the stack address saved the return address of the caller
224 * of _mcount.
225 *
226 * if the gcc < 4.5, a leaf function does not save the return address
227 * in the stack address, so, we "emulate" one in _mcount's stack space,
228 * and hijack it directly, but for a non-leaf function, it save the
229 * return address to the its own stack space, we can not hijack it
230 * directly, but need to find the real stack address,
231 * ftrace_get_parent_addr() does it!
232 *
233 * if gcc>= 4.5, with the new -mmcount-ra-address option, for a
234 * non-leaf function, the location of the return address will be saved
235 * to $12 for us, and for a leaf function, only put a zero into $12. we
236 * do it in ftrace_graph_caller of mcount.S.
237 */
238
239 /* old = *parent; */
240 safe_load_stack(old, parent, faulted);
241 if (unlikely(faulted))
242 goto out;
243#ifndef KBUILD_MCOUNT_RA_ADDRESS
244 parent = (unsigned long *)ftrace_get_parent_addr(self_addr, old,
245 (unsigned long)parent,
246 fp);
247 /* If fails when getting the stack address of the non-leaf function's
248 * ra, stop function graph tracer and return */
249 if (parent == 0)
250 goto out;
251#endif
252 /* *parent = return_hooker; */
253 safe_store_stack(return_hooker, parent, faulted);
254 if (unlikely(faulted))
255 goto out;
256
257 if (ftrace_push_return_trace(old, self_addr, &trace.depth, fp) ==
258 -EBUSY) {
259 *parent = old;
260 return;
261 }
262
263 trace.func = self_addr;
264
265 /* Only trace if the calling function expects to */
266 if (!ftrace_graph_entry(&trace)) {
267 current->curr_ret_stack--;
268 *parent = old;
269 }
270 return;
271out:
272 ftrace_graph_stop();
273 WARN_ON(1);
274}
275#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
diff --git a/arch/mips/kernel/i8259.c b/arch/mips/kernel/i8259.c
index 01c0885a8061..27799113332c 100644
--- a/arch/mips/kernel/i8259.c
+++ b/arch/mips/kernel/i8259.c
@@ -29,7 +29,7 @@
29 */ 29 */
30 30
31static int i8259A_auto_eoi = -1; 31static int i8259A_auto_eoi = -1;
32DEFINE_SPINLOCK(i8259A_lock); 32DEFINE_RAW_SPINLOCK(i8259A_lock);
33static void disable_8259A_irq(unsigned int irq); 33static void disable_8259A_irq(unsigned int irq);
34static void enable_8259A_irq(unsigned int irq); 34static void enable_8259A_irq(unsigned int irq);
35static void mask_and_ack_8259A(unsigned int irq); 35static void mask_and_ack_8259A(unsigned int irq);
@@ -65,13 +65,13 @@ static void disable_8259A_irq(unsigned int irq)
65 65
66 irq -= I8259A_IRQ_BASE; 66 irq -= I8259A_IRQ_BASE;
67 mask = 1 << irq; 67 mask = 1 << irq;
68 spin_lock_irqsave(&i8259A_lock, flags); 68 raw_spin_lock_irqsave(&i8259A_lock, flags);
69 cached_irq_mask |= mask; 69 cached_irq_mask |= mask;
70 if (irq & 8) 70 if (irq & 8)
71 outb(cached_slave_mask, PIC_SLAVE_IMR); 71 outb(cached_slave_mask, PIC_SLAVE_IMR);
72 else 72 else
73 outb(cached_master_mask, PIC_MASTER_IMR); 73 outb(cached_master_mask, PIC_MASTER_IMR);
74 spin_unlock_irqrestore(&i8259A_lock, flags); 74 raw_spin_unlock_irqrestore(&i8259A_lock, flags);
75} 75}
76 76
77static void enable_8259A_irq(unsigned int irq) 77static void enable_8259A_irq(unsigned int irq)
@@ -81,13 +81,13 @@ static void enable_8259A_irq(unsigned int irq)
81 81
82 irq -= I8259A_IRQ_BASE; 82 irq -= I8259A_IRQ_BASE;
83 mask = ~(1 << irq); 83 mask = ~(1 << irq);
84 spin_lock_irqsave(&i8259A_lock, flags); 84 raw_spin_lock_irqsave(&i8259A_lock, flags);
85 cached_irq_mask &= mask; 85 cached_irq_mask &= mask;
86 if (irq & 8) 86 if (irq & 8)
87 outb(cached_slave_mask, PIC_SLAVE_IMR); 87 outb(cached_slave_mask, PIC_SLAVE_IMR);
88 else 88 else
89 outb(cached_master_mask, PIC_MASTER_IMR); 89 outb(cached_master_mask, PIC_MASTER_IMR);
90 spin_unlock_irqrestore(&i8259A_lock, flags); 90 raw_spin_unlock_irqrestore(&i8259A_lock, flags);
91} 91}
92 92
93int i8259A_irq_pending(unsigned int irq) 93int i8259A_irq_pending(unsigned int irq)
@@ -98,12 +98,12 @@ int i8259A_irq_pending(unsigned int irq)
98 98
99 irq -= I8259A_IRQ_BASE; 99 irq -= I8259A_IRQ_BASE;
100 mask = 1 << irq; 100 mask = 1 << irq;
101 spin_lock_irqsave(&i8259A_lock, flags); 101 raw_spin_lock_irqsave(&i8259A_lock, flags);
102 if (irq < 8) 102 if (irq < 8)
103 ret = inb(PIC_MASTER_CMD) & mask; 103 ret = inb(PIC_MASTER_CMD) & mask;
104 else 104 else
105 ret = inb(PIC_SLAVE_CMD) & (mask >> 8); 105 ret = inb(PIC_SLAVE_CMD) & (mask >> 8);
106 spin_unlock_irqrestore(&i8259A_lock, flags); 106 raw_spin_unlock_irqrestore(&i8259A_lock, flags);
107 107
108 return ret; 108 return ret;
109} 109}
@@ -151,7 +151,7 @@ static void mask_and_ack_8259A(unsigned int irq)
151 151
152 irq -= I8259A_IRQ_BASE; 152 irq -= I8259A_IRQ_BASE;
153 irqmask = 1 << irq; 153 irqmask = 1 << irq;
154 spin_lock_irqsave(&i8259A_lock, flags); 154 raw_spin_lock_irqsave(&i8259A_lock, flags);
155 /* 155 /*
156 * Lightweight spurious IRQ detection. We do not want 156 * Lightweight spurious IRQ detection. We do not want
157 * to overdo spurious IRQ handling - it's usually a sign 157 * to overdo spurious IRQ handling - it's usually a sign
@@ -183,7 +183,7 @@ handle_real_irq:
183 outb(0x60+irq, PIC_MASTER_CMD); /* 'Specific EOI to master */ 183 outb(0x60+irq, PIC_MASTER_CMD); /* 'Specific EOI to master */
184 } 184 }
185 smtc_im_ack_irq(irq); 185 smtc_im_ack_irq(irq);
186 spin_unlock_irqrestore(&i8259A_lock, flags); 186 raw_spin_unlock_irqrestore(&i8259A_lock, flags);
187 return; 187 return;
188 188
189spurious_8259A_irq: 189spurious_8259A_irq:
@@ -264,7 +264,7 @@ static void init_8259A(int auto_eoi)
264 264
265 i8259A_auto_eoi = auto_eoi; 265 i8259A_auto_eoi = auto_eoi;
266 266
267 spin_lock_irqsave(&i8259A_lock, flags); 267 raw_spin_lock_irqsave(&i8259A_lock, flags);
268 268
269 outb(0xff, PIC_MASTER_IMR); /* mask all of 8259A-1 */ 269 outb(0xff, PIC_MASTER_IMR); /* mask all of 8259A-1 */
270 outb(0xff, PIC_SLAVE_IMR); /* mask all of 8259A-2 */ 270 outb(0xff, PIC_SLAVE_IMR); /* mask all of 8259A-2 */
@@ -298,7 +298,7 @@ static void init_8259A(int auto_eoi)
298 outb(cached_master_mask, PIC_MASTER_IMR); /* restore master IRQ mask */ 298 outb(cached_master_mask, PIC_MASTER_IMR); /* restore master IRQ mask */
299 outb(cached_slave_mask, PIC_SLAVE_IMR); /* restore slave IRQ mask */ 299 outb(cached_slave_mask, PIC_SLAVE_IMR); /* restore slave IRQ mask */
300 300
301 spin_unlock_irqrestore(&i8259A_lock, flags); 301 raw_spin_unlock_irqrestore(&i8259A_lock, flags);
302} 302}
303 303
304/* 304/*
diff --git a/arch/mips/kernel/irq-gt641xx.c b/arch/mips/kernel/irq-gt641xx.c
index ebcc5f7ad9c2..42ef81461bfc 100644
--- a/arch/mips/kernel/irq-gt641xx.c
+++ b/arch/mips/kernel/irq-gt641xx.c
@@ -27,18 +27,18 @@
27 27
28#define GT641XX_IRQ_TO_BIT(irq) (1U << (irq - GT641XX_IRQ_BASE)) 28#define GT641XX_IRQ_TO_BIT(irq) (1U << (irq - GT641XX_IRQ_BASE))
29 29
30static DEFINE_SPINLOCK(gt641xx_irq_lock); 30static DEFINE_RAW_SPINLOCK(gt641xx_irq_lock);
31 31
32static void ack_gt641xx_irq(unsigned int irq) 32static void ack_gt641xx_irq(unsigned int irq)
33{ 33{
34 unsigned long flags; 34 unsigned long flags;
35 u32 cause; 35 u32 cause;
36 36
37 spin_lock_irqsave(&gt641xx_irq_lock, flags); 37 raw_spin_lock_irqsave(&gt641xx_irq_lock, flags);
38 cause = GT_READ(GT_INTRCAUSE_OFS); 38 cause = GT_READ(GT_INTRCAUSE_OFS);
39 cause &= ~GT641XX_IRQ_TO_BIT(irq); 39 cause &= ~GT641XX_IRQ_TO_BIT(irq);
40 GT_WRITE(GT_INTRCAUSE_OFS, cause); 40 GT_WRITE(GT_INTRCAUSE_OFS, cause);
41 spin_unlock_irqrestore(&gt641xx_irq_lock, flags); 41 raw_spin_unlock_irqrestore(&gt641xx_irq_lock, flags);
42} 42}
43 43
44static void mask_gt641xx_irq(unsigned int irq) 44static void mask_gt641xx_irq(unsigned int irq)
@@ -46,11 +46,11 @@ static void mask_gt641xx_irq(unsigned int irq)
46 unsigned long flags; 46 unsigned long flags;
47 u32 mask; 47 u32 mask;
48 48
49 spin_lock_irqsave(&gt641xx_irq_lock, flags); 49 raw_spin_lock_irqsave(&gt641xx_irq_lock, flags);
50 mask = GT_READ(GT_INTRMASK_OFS); 50 mask = GT_READ(GT_INTRMASK_OFS);
51 mask &= ~GT641XX_IRQ_TO_BIT(irq); 51 mask &= ~GT641XX_IRQ_TO_BIT(irq);
52 GT_WRITE(GT_INTRMASK_OFS, mask); 52 GT_WRITE(GT_INTRMASK_OFS, mask);
53 spin_unlock_irqrestore(&gt641xx_irq_lock, flags); 53 raw_spin_unlock_irqrestore(&gt641xx_irq_lock, flags);
54} 54}
55 55
56static void mask_ack_gt641xx_irq(unsigned int irq) 56static void mask_ack_gt641xx_irq(unsigned int irq)
@@ -58,7 +58,7 @@ static void mask_ack_gt641xx_irq(unsigned int irq)
58 unsigned long flags; 58 unsigned long flags;
59 u32 cause, mask; 59 u32 cause, mask;
60 60
61 spin_lock_irqsave(&gt641xx_irq_lock, flags); 61 raw_spin_lock_irqsave(&gt641xx_irq_lock, flags);
62 mask = GT_READ(GT_INTRMASK_OFS); 62 mask = GT_READ(GT_INTRMASK_OFS);
63 mask &= ~GT641XX_IRQ_TO_BIT(irq); 63 mask &= ~GT641XX_IRQ_TO_BIT(irq);
64 GT_WRITE(GT_INTRMASK_OFS, mask); 64 GT_WRITE(GT_INTRMASK_OFS, mask);
@@ -66,7 +66,7 @@ static void mask_ack_gt641xx_irq(unsigned int irq)
66 cause = GT_READ(GT_INTRCAUSE_OFS); 66 cause = GT_READ(GT_INTRCAUSE_OFS);
67 cause &= ~GT641XX_IRQ_TO_BIT(irq); 67 cause &= ~GT641XX_IRQ_TO_BIT(irq);
68 GT_WRITE(GT_INTRCAUSE_OFS, cause); 68 GT_WRITE(GT_INTRCAUSE_OFS, cause);
69 spin_unlock_irqrestore(&gt641xx_irq_lock, flags); 69 raw_spin_unlock_irqrestore(&gt641xx_irq_lock, flags);
70} 70}
71 71
72static void unmask_gt641xx_irq(unsigned int irq) 72static void unmask_gt641xx_irq(unsigned int irq)
@@ -74,11 +74,11 @@ static void unmask_gt641xx_irq(unsigned int irq)
74 unsigned long flags; 74 unsigned long flags;
75 u32 mask; 75 u32 mask;
76 76
77 spin_lock_irqsave(&gt641xx_irq_lock, flags); 77 raw_spin_lock_irqsave(&gt641xx_irq_lock, flags);
78 mask = GT_READ(GT_INTRMASK_OFS); 78 mask = GT_READ(GT_INTRMASK_OFS);
79 mask |= GT641XX_IRQ_TO_BIT(irq); 79 mask |= GT641XX_IRQ_TO_BIT(irq);
80 GT_WRITE(GT_INTRMASK_OFS, mask); 80 GT_WRITE(GT_INTRMASK_OFS, mask);
81 spin_unlock_irqrestore(&gt641xx_irq_lock, flags); 81 raw_spin_unlock_irqrestore(&gt641xx_irq_lock, flags);
82} 82}
83 83
84static struct irq_chip gt641xx_irq_chip = { 84static struct irq_chip gt641xx_irq_chip = {
diff --git a/arch/mips/kernel/irq.c b/arch/mips/kernel/irq.c
index 7b845ba9dff4..c6345f579a8a 100644
--- a/arch/mips/kernel/irq.c
+++ b/arch/mips/kernel/irq.c
@@ -15,13 +15,13 @@
15#include <linux/kernel_stat.h> 15#include <linux/kernel_stat.h>
16#include <linux/module.h> 16#include <linux/module.h>
17#include <linux/proc_fs.h> 17#include <linux/proc_fs.h>
18#include <linux/slab.h>
19#include <linux/mm.h> 18#include <linux/mm.h>
20#include <linux/random.h> 19#include <linux/random.h>
21#include <linux/sched.h> 20#include <linux/sched.h>
22#include <linux/seq_file.h> 21#include <linux/seq_file.h>
23#include <linux/kallsyms.h> 22#include <linux/kallsyms.h>
24#include <linux/kgdb.h> 23#include <linux/kgdb.h>
24#include <linux/ftrace.h>
25 25
26#include <asm/atomic.h> 26#include <asm/atomic.h>
27#include <asm/system.h> 27#include <asm/system.h>
@@ -99,7 +99,7 @@ int show_interrupts(struct seq_file *p, void *v)
99 } 99 }
100 100
101 if (i < NR_IRQS) { 101 if (i < NR_IRQS) {
102 spin_lock_irqsave(&irq_desc[i].lock, flags); 102 raw_spin_lock_irqsave(&irq_desc[i].lock, flags);
103 action = irq_desc[i].action; 103 action = irq_desc[i].action;
104 if (!action) 104 if (!action)
105 goto skip; 105 goto skip;
@@ -118,7 +118,7 @@ int show_interrupts(struct seq_file *p, void *v)
118 118
119 seq_putc(p, '\n'); 119 seq_putc(p, '\n');
120skip: 120skip:
121 spin_unlock_irqrestore(&irq_desc[i].lock, flags); 121 raw_spin_unlock_irqrestore(&irq_desc[i].lock, flags);
122 } else if (i == NR_IRQS) { 122 } else if (i == NR_IRQS) {
123 seq_putc(p, '\n'); 123 seq_putc(p, '\n');
124 seq_printf(p, "ERR: %10u\n", atomic_read(&irq_err_count)); 124 seq_printf(p, "ERR: %10u\n", atomic_read(&irq_err_count));
@@ -150,3 +150,32 @@ void __init init_IRQ(void)
150 kgdb_early_setup = 1; 150 kgdb_early_setup = 1;
151#endif 151#endif
152} 152}
153
154/*
155 * do_IRQ handles all normal device IRQ's (the special
156 * SMP cross-CPU interrupts have their own specific
157 * handlers).
158 */
159void __irq_entry do_IRQ(unsigned int irq)
160{
161 irq_enter();
162 __DO_IRQ_SMTC_HOOK(irq);
163 generic_handle_irq(irq);
164 irq_exit();
165}
166
167#ifdef CONFIG_MIPS_MT_SMTC_IRQAFF
168/*
169 * To avoid inefficient and in some cases pathological re-checking of
170 * IRQ affinity, we have this variant that skips the affinity check.
171 */
172
173void __irq_entry do_IRQ_no_affinity(unsigned int irq)
174{
175 irq_enter();
176 __NO_AFFINITY_IRQ_SMTC_HOOK(irq);
177 generic_handle_irq(irq);
178 irq_exit();
179}
180
181#endif /* CONFIG_MIPS_MT_SMTC_IRQAFF */
diff --git a/arch/mips/kernel/kspd.c b/arch/mips/kernel/kspd.c
index ad4e017ed2f3..80e2ba694bab 100644
--- a/arch/mips/kernel/kspd.c
+++ b/arch/mips/kernel/kspd.c
@@ -82,6 +82,7 @@ static int sp_stopping;
82#define MTSP_O_SHLOCK 0x0010 82#define MTSP_O_SHLOCK 0x0010
83#define MTSP_O_EXLOCK 0x0020 83#define MTSP_O_EXLOCK 0x0020
84#define MTSP_O_ASYNC 0x0040 84#define MTSP_O_ASYNC 0x0040
85/* XXX: check which of these is actually O_SYNC vs O_DSYNC */
85#define MTSP_O_FSYNC O_SYNC 86#define MTSP_O_FSYNC O_SYNC
86#define MTSP_O_NOFOLLOW 0x0100 87#define MTSP_O_NOFOLLOW 0x0100
87#define MTSP_O_SYNC 0x0080 88#define MTSP_O_SYNC 0x0080
diff --git a/arch/mips/kernel/linux32.c b/arch/mips/kernel/linux32.c
index b77fefaff9da..c2dab140dc98 100644
--- a/arch/mips/kernel/linux32.c
+++ b/arch/mips/kernel/linux32.c
@@ -9,14 +9,12 @@
9#include <linux/mm.h> 9#include <linux/mm.h>
10#include <linux/errno.h> 10#include <linux/errno.h>
11#include <linux/file.h> 11#include <linux/file.h>
12#include <linux/smp_lock.h>
13#include <linux/highuid.h> 12#include <linux/highuid.h>
14#include <linux/resource.h> 13#include <linux/resource.h>
15#include <linux/highmem.h> 14#include <linux/highmem.h>
16#include <linux/time.h> 15#include <linux/time.h>
17#include <linux/times.h> 16#include <linux/times.h>
18#include <linux/poll.h> 17#include <linux/poll.h>
19#include <linux/slab.h>
20#include <linux/skbuff.h> 18#include <linux/skbuff.h>
21#include <linux/filter.h> 19#include <linux/filter.h>
22#include <linux/shm.h> 20#include <linux/shm.h>
@@ -35,6 +33,7 @@
35#include <linux/compat.h> 33#include <linux/compat.h>
36#include <linux/vfs.h> 34#include <linux/vfs.h>
37#include <linux/ipc.h> 35#include <linux/ipc.h>
36#include <linux/slab.h>
38 37
39#include <net/sock.h> 38#include <net/sock.h>
40#include <net/scm.h> 39#include <net/scm.h>
@@ -67,28 +66,13 @@ SYSCALL_DEFINE6(32_mmap2, unsigned long, addr, unsigned long, len,
67 unsigned long, prot, unsigned long, flags, unsigned long, fd, 66 unsigned long, prot, unsigned long, flags, unsigned long, fd,
68 unsigned long, pgoff) 67 unsigned long, pgoff)
69{ 68{
70 struct file * file = NULL;
71 unsigned long error; 69 unsigned long error;
72 70
73 error = -EINVAL; 71 error = -EINVAL;
74 if (pgoff & (~PAGE_MASK >> 12)) 72 if (pgoff & (~PAGE_MASK >> 12))
75 goto out; 73 goto out;
76 pgoff >>= PAGE_SHIFT-12; 74 error = sys_mmap_pgoff(addr, len, prot, flags, fd,
77 75 pgoff >> (PAGE_SHIFT-12));
78 if (!(flags & MAP_ANONYMOUS)) {
79 error = -EBADF;
80 file = fget(fd);
81 if (!file)
82 goto out;
83 }
84 flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
85
86 down_write(&current->mm->mmap_sem);
87 error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
88 up_write(&current->mm->mmap_sem);
89 if (file)
90 fput(file);
91
92out: 76out:
93 return error; 77 return error;
94} 78}
@@ -265,83 +249,6 @@ SYSCALL_DEFINE5(n32_msgrcv, int, msqid, u32, msgp, size_t, msgsz,
265} 249}
266#endif 250#endif
267 251
268struct sysctl_args32
269{
270 compat_caddr_t name;
271 int nlen;
272 compat_caddr_t oldval;
273 compat_caddr_t oldlenp;
274 compat_caddr_t newval;
275 compat_size_t newlen;
276 unsigned int __unused[4];
277};
278
279#ifdef CONFIG_SYSCTL_SYSCALL
280
281SYSCALL_DEFINE1(32_sysctl, struct sysctl_args32 __user *, args)
282{
283 struct sysctl_args32 tmp;
284 int error;
285 size_t oldlen;
286 size_t __user *oldlenp = NULL;
287 unsigned long addr = (((unsigned long)&args->__unused[0]) + 7) & ~7;
288
289 if (copy_from_user(&tmp, args, sizeof(tmp)))
290 return -EFAULT;
291
292 if (tmp.oldval && tmp.oldlenp) {
293 /* Duh, this is ugly and might not work if sysctl_args
294 is in read-only memory, but do_sysctl does indirectly
295 a lot of uaccess in both directions and we'd have to
296 basically copy the whole sysctl.c here, and
297 glibc's __sysctl uses rw memory for the structure
298 anyway. */
299 if (get_user(oldlen, (u32 __user *)A(tmp.oldlenp)) ||
300 put_user(oldlen, (size_t __user *)addr))
301 return -EFAULT;
302 oldlenp = (size_t __user *)addr;
303 }
304
305 lock_kernel();
306 error = do_sysctl((int __user *)A(tmp.name), tmp.nlen, (void __user *)A(tmp.oldval),
307 oldlenp, (void __user *)A(tmp.newval), tmp.newlen);
308 unlock_kernel();
309 if (oldlenp) {
310 if (!error) {
311 if (get_user(oldlen, (size_t __user *)addr) ||
312 put_user(oldlen, (u32 __user *)A(tmp.oldlenp)))
313 error = -EFAULT;
314 }
315 copy_to_user(args->__unused, tmp.__unused, sizeof(tmp.__unused));
316 }
317 return error;
318}
319
320#else
321
322SYSCALL_DEFINE1(32_sysctl, struct sysctl_args32 __user *, args)
323{
324 return -ENOSYS;
325}
326
327#endif /* CONFIG_SYSCTL_SYSCALL */
328
329SYSCALL_DEFINE1(32_newuname, struct new_utsname __user *, name)
330{
331 int ret = 0;
332
333 down_read(&uts_sem);
334 if (copy_to_user(name, utsname(), sizeof *name))
335 ret = -EFAULT;
336 up_read(&uts_sem);
337
338 if (current->personality == PER_LINUX32 && !ret)
339 if (copy_to_user(name->machine, "mips\0\0\0", 8))
340 ret = -EFAULT;
341
342 return ret;
343}
344
345SYSCALL_DEFINE1(32_personality, unsigned long, personality) 252SYSCALL_DEFINE1(32_personality, unsigned long, personality)
346{ 253{
347 int ret; 254 int ret;
diff --git a/arch/mips/kernel/mcount.S b/arch/mips/kernel/mcount.S
new file mode 100644
index 000000000000..6851fc97a511
--- /dev/null
+++ b/arch/mips/kernel/mcount.S
@@ -0,0 +1,189 @@
1/*
2 * MIPS specific _mcount support
3 *
4 * This file is subject to the terms and conditions of the GNU General Public
5 * License. See the file "COPYING" in the main directory of this archive for
6 * more details.
7 *
8 * Copyright (C) 2009 Lemote Inc. & DSLab, Lanzhou University, China
9 * Author: Wu Zhangjin <wuzhangjin@gmail.com>
10 */
11
12#include <asm/regdef.h>
13#include <asm/stackframe.h>
14#include <asm/ftrace.h>
15
16 .text
17 .set noreorder
18 .set noat
19
20 .macro MCOUNT_SAVE_REGS
21 PTR_SUBU sp, PT_SIZE
22 PTR_S ra, PT_R31(sp)
23 PTR_S AT, PT_R1(sp)
24 PTR_S a0, PT_R4(sp)
25 PTR_S a1, PT_R5(sp)
26 PTR_S a2, PT_R6(sp)
27 PTR_S a3, PT_R7(sp)
28#ifdef CONFIG_64BIT
29 PTR_S a4, PT_R8(sp)
30 PTR_S a5, PT_R9(sp)
31 PTR_S a6, PT_R10(sp)
32 PTR_S a7, PT_R11(sp)
33#endif
34 .endm
35
36 .macro MCOUNT_RESTORE_REGS
37 PTR_L ra, PT_R31(sp)
38 PTR_L AT, PT_R1(sp)
39 PTR_L a0, PT_R4(sp)
40 PTR_L a1, PT_R5(sp)
41 PTR_L a2, PT_R6(sp)
42 PTR_L a3, PT_R7(sp)
43#ifdef CONFIG_64BIT
44 PTR_L a4, PT_R8(sp)
45 PTR_L a5, PT_R9(sp)
46 PTR_L a6, PT_R10(sp)
47 PTR_L a7, PT_R11(sp)
48#endif
49#ifdef CONFIG_64BIT
50 PTR_ADDIU sp, PT_SIZE
51#else
52 PTR_ADDIU sp, (PT_SIZE + 8)
53#endif
54.endm
55
56 .macro RETURN_BACK
57 jr ra
58 move ra, AT
59 .endm
60
61#ifdef CONFIG_DYNAMIC_FTRACE
62
63NESTED(ftrace_caller, PT_SIZE, ra)
64 .globl _mcount
65_mcount:
66 b ftrace_stub
67 nop
68 lw t1, function_trace_stop
69 bnez t1, ftrace_stub
70 nop
71
72 MCOUNT_SAVE_REGS
73#ifdef KBUILD_MCOUNT_RA_ADDRESS
74 PTR_S t0, PT_R12(sp) /* t0 saved the location of the return address(at) by -mmcount-ra-address */
75#endif
76
77 move a0, ra /* arg1: next ip, selfaddr */
78 .globl ftrace_call
79ftrace_call:
80 nop /* a placeholder for the call to a real tracing function */
81 move a1, AT /* arg2: the caller's next ip, parent */
82
83#ifdef CONFIG_FUNCTION_GRAPH_TRACER
84 .globl ftrace_graph_call
85ftrace_graph_call:
86 nop
87 nop
88#endif
89
90 MCOUNT_RESTORE_REGS
91 .globl ftrace_stub
92ftrace_stub:
93 RETURN_BACK
94 END(ftrace_caller)
95
96#else /* ! CONFIG_DYNAMIC_FTRACE */
97
98NESTED(_mcount, PT_SIZE, ra)
99 lw t1, function_trace_stop
100 bnez t1, ftrace_stub
101 nop
102 PTR_LA t1, ftrace_stub
103 PTR_L t2, ftrace_trace_function /* Prepare t2 for (1) */
104 bne t1, t2, static_trace
105 nop
106
107#ifdef CONFIG_FUNCTION_GRAPH_TRACER
108 PTR_L t3, ftrace_graph_return
109 bne t1, t3, ftrace_graph_caller
110 nop
111 PTR_LA t1, ftrace_graph_entry_stub
112 PTR_L t3, ftrace_graph_entry
113 bne t1, t3, ftrace_graph_caller
114 nop
115#endif
116 b ftrace_stub
117 nop
118
119static_trace:
120 MCOUNT_SAVE_REGS
121
122 move a0, ra /* arg1: next ip, selfaddr */
123 jalr t2 /* (1) call *ftrace_trace_function */
124 move a1, AT /* arg2: the caller's next ip, parent */
125
126 MCOUNT_RESTORE_REGS
127 .globl ftrace_stub
128ftrace_stub:
129 RETURN_BACK
130 END(_mcount)
131
132#endif /* ! CONFIG_DYNAMIC_FTRACE */
133
134#ifdef CONFIG_FUNCTION_GRAPH_TRACER
135
136NESTED(ftrace_graph_caller, PT_SIZE, ra)
137#ifdef CONFIG_DYNAMIC_FTRACE
138 PTR_L a1, PT_R31(sp) /* load the original ra from the stack */
139#ifdef KBUILD_MCOUNT_RA_ADDRESS
140 PTR_L t0, PT_R12(sp) /* load the original t0 from the stack */
141#endif
142#else
143 MCOUNT_SAVE_REGS
144 move a1, ra /* arg2: next ip, selfaddr */
145#endif
146
147#ifdef KBUILD_MCOUNT_RA_ADDRESS
148 bnez t0, 1f /* non-leaf func: t0 saved the location of the return address */
149 nop
150 PTR_LA t0, PT_R1(sp) /* leaf func: get the location of at(old ra) from our own stack */
1511: move a0, t0 /* arg1: the location of the return address */
152#else
153 PTR_LA a0, PT_R1(sp) /* arg1: &AT -> a0 */
154#endif
155 jal prepare_ftrace_return
156#ifdef CONFIG_FRAME_POINTER
157 move a2, fp /* arg3: frame pointer */
158#else
159#ifdef CONFIG_64BIT
160 PTR_LA a2, PT_SIZE(sp)
161#else
162 PTR_LA a2, (PT_SIZE+8)(sp)
163#endif
164#endif
165
166 MCOUNT_RESTORE_REGS
167 RETURN_BACK
168 END(ftrace_graph_caller)
169
170 .align 2
171 .globl return_to_handler
172return_to_handler:
173 PTR_SUBU sp, PT_SIZE
174 PTR_S v0, PT_R2(sp)
175
176 jal ftrace_return_to_handler
177 PTR_S v1, PT_R3(sp)
178
179 /* restore the real parent address: v0 -> ra */
180 move ra, v0
181
182 PTR_L v0, PT_R2(sp)
183 PTR_L v1, PT_R3(sp)
184 jr ra
185 PTR_ADDIU sp, PT_SIZE
186#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
187
188 .set at
189 .set reorder
diff --git a/arch/mips/kernel/mips_ksyms.c b/arch/mips/kernel/mips_ksyms.c
index 225755d0c1f6..1d04807874db 100644
--- a/arch/mips/kernel/mips_ksyms.c
+++ b/arch/mips/kernel/mips_ksyms.c
@@ -13,6 +13,7 @@
13#include <asm/checksum.h> 13#include <asm/checksum.h>
14#include <asm/pgtable.h> 14#include <asm/pgtable.h>
15#include <asm/uaccess.h> 15#include <asm/uaccess.h>
16#include <asm/ftrace.h>
16 17
17extern void *__bzero(void *__s, size_t __count); 18extern void *__bzero(void *__s, size_t __count);
18extern long __strncpy_from_user_nocheck_asm(char *__to, 19extern long __strncpy_from_user_nocheck_asm(char *__to,
@@ -51,3 +52,7 @@ EXPORT_SYMBOL(csum_partial_copy_nocheck);
51EXPORT_SYMBOL(__csum_partial_copy_user); 52EXPORT_SYMBOL(__csum_partial_copy_user);
52 53
53EXPORT_SYMBOL(invalid_pte_table); 54EXPORT_SYMBOL(invalid_pte_table);
55#ifdef CONFIG_FUNCTION_TRACER
56/* _mcount is defined in arch/mips/kernel/mcount.S */
57EXPORT_SYMBOL(_mcount);
58#endif
diff --git a/arch/mips/kernel/octeon_switch.S b/arch/mips/kernel/octeon_switch.S
index 3952b8323efa..dd18b26a358a 100644
--- a/arch/mips/kernel/octeon_switch.S
+++ b/arch/mips/kernel/octeon_switch.S
@@ -500,4 +500,3 @@ done_restore:
500 nop 500 nop
501 END(octeon_mult_restore) 501 END(octeon_mult_restore)
502 .set pop 502 .set pop
503
diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c
index f3d73e1831c1..99960940d4a4 100644
--- a/arch/mips/kernel/process.c
+++ b/arch/mips/kernel/process.c
@@ -17,7 +17,6 @@
17#include <linux/stddef.h> 17#include <linux/stddef.h>
18#include <linux/unistd.h> 18#include <linux/unistd.h>
19#include <linux/ptrace.h> 19#include <linux/ptrace.h>
20#include <linux/slab.h>
21#include <linux/mman.h> 20#include <linux/mman.h>
22#include <linux/personality.h> 21#include <linux/personality.h>
23#include <linux/sys.h> 22#include <linux/sys.h>
@@ -64,8 +63,13 @@ void __noreturn cpu_idle(void)
64 63
65 smtc_idle_loop_hook(); 64 smtc_idle_loop_hook();
66#endif 65#endif
67 if (cpu_wait) 66
67 if (cpu_wait) {
68 /* Don't trace irqs off for idle */
69 stop_critical_timings();
68 (*cpu_wait)(); 70 (*cpu_wait)();
71 start_critical_timings();
72 }
69 } 73 }
70#ifdef CONFIG_HOTPLUG_CPU 74#ifdef CONFIG_HOTPLUG_CPU
71 if (!cpu_online(cpu) && !cpu_isset(cpu, cpu_callin_map) && 75 if (!cpu_online(cpu) && !cpu_isset(cpu, cpu_callin_map) &&
diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c
index 054861ccb4dd..c51b95ff8644 100644
--- a/arch/mips/kernel/ptrace.c
+++ b/arch/mips/kernel/ptrace.c
@@ -493,36 +493,6 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
493 ret = ptrace_setfpregs(child, (__u32 __user *) data); 493 ret = ptrace_setfpregs(child, (__u32 __user *) data);
494 break; 494 break;
495 495
496 case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */
497 case PTRACE_CONT: { /* restart after signal. */
498 ret = -EIO;
499 if (!valid_signal(data))
500 break;
501 if (request == PTRACE_SYSCALL) {
502 set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
503 }
504 else {
505 clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
506 }
507 child->exit_code = data;
508 wake_up_process(child);
509 ret = 0;
510 break;
511 }
512
513 /*
514 * make the child exit. Best I can do is send it a sigkill.
515 * perhaps it should be put in the status that it wants to
516 * exit.
517 */
518 case PTRACE_KILL:
519 ret = 0;
520 if (child->exit_state == EXIT_ZOMBIE) /* already dead */
521 break;
522 child->exit_code = SIGKILL;
523 wake_up_process(child);
524 break;
525
526 case PTRACE_GET_THREAD_AREA: 496 case PTRACE_GET_THREAD_AREA:
527 ret = put_user(task_thread_info(child)->tp_value, 497 ret = put_user(task_thread_info(child)->tp_value,
528 (unsigned long __user *) data); 498 (unsigned long __user *) data);
diff --git a/arch/mips/kernel/rtlx.c b/arch/mips/kernel/rtlx.c
index 364f066cb497..26f9b9ab19cc 100644
--- a/arch/mips/kernel/rtlx.c
+++ b/arch/mips/kernel/rtlx.c
@@ -23,12 +23,10 @@
23#include <linux/fs.h> 23#include <linux/fs.h>
24#include <linux/init.h> 24#include <linux/init.h>
25#include <asm/uaccess.h> 25#include <asm/uaccess.h>
26#include <linux/slab.h>
27#include <linux/list.h> 26#include <linux/list.h>
28#include <linux/vmalloc.h> 27#include <linux/vmalloc.h>
29#include <linux/elf.h> 28#include <linux/elf.h>
30#include <linux/seq_file.h> 29#include <linux/seq_file.h>
31#include <linux/smp_lock.h>
32#include <linux/syscalls.h> 30#include <linux/syscalls.h>
33#include <linux/moduleloader.h> 31#include <linux/moduleloader.h>
34#include <linux/interrupt.h> 32#include <linux/interrupt.h>
diff --git a/arch/mips/kernel/scall32-o32.S b/arch/mips/kernel/scall32-o32.S
index fd2a9bb620d6..17202bbe843f 100644
--- a/arch/mips/kernel/scall32-o32.S
+++ b/arch/mips/kernel/scall32-o32.S
@@ -583,6 +583,7 @@ einval: li v0, -ENOSYS
583 sys sys_rt_tgsigqueueinfo 4 583 sys sys_rt_tgsigqueueinfo 4
584 sys sys_perf_event_open 5 584 sys sys_perf_event_open 5
585 sys sys_accept4 4 585 sys sys_accept4 4
586 sys sys_recvmmsg 5
586 .endm 587 .endm
587 588
588 /* We pre-compute the number of _instruction_ bytes needed to 589 /* We pre-compute the number of _instruction_ bytes needed to
diff --git a/arch/mips/kernel/scall64-64.S b/arch/mips/kernel/scall64-64.S
index 18bf7f32c5e4..a8a6c596eb04 100644
--- a/arch/mips/kernel/scall64-64.S
+++ b/arch/mips/kernel/scall64-64.S
@@ -420,4 +420,5 @@ sys_call_table:
420 PTR sys_rt_tgsigqueueinfo 420 PTR sys_rt_tgsigqueueinfo
421 PTR sys_perf_event_open 421 PTR sys_perf_event_open
422 PTR sys_accept4 422 PTR sys_accept4
423 PTR sys_recvmmsg
423 .size sys_call_table,.-sys_call_table 424 .size sys_call_table,.-sys_call_table
diff --git a/arch/mips/kernel/scall64-n32.S b/arch/mips/kernel/scall64-n32.S
index 6ebc07976694..a5297e2a353a 100644
--- a/arch/mips/kernel/scall64-n32.S
+++ b/arch/mips/kernel/scall64-n32.S
@@ -181,7 +181,7 @@ EXPORT(sysn32_call_table)
181 PTR sys_exit 181 PTR sys_exit
182 PTR compat_sys_wait4 182 PTR compat_sys_wait4
183 PTR sys_kill /* 6060 */ 183 PTR sys_kill /* 6060 */
184 PTR sys_32_newuname 184 PTR sys_newuname
185 PTR sys_semget 185 PTR sys_semget
186 PTR sys_semop 186 PTR sys_semop
187 PTR sys_n32_semctl 187 PTR sys_n32_semctl
@@ -272,7 +272,7 @@ EXPORT(sysn32_call_table)
272 PTR sys_munlockall 272 PTR sys_munlockall
273 PTR sys_vhangup /* 6150 */ 273 PTR sys_vhangup /* 6150 */
274 PTR sys_pivot_root 274 PTR sys_pivot_root
275 PTR sys_32_sysctl 275 PTR compat_sys_sysctl
276 PTR sys_prctl 276 PTR sys_prctl
277 PTR compat_sys_adjtimex 277 PTR compat_sys_adjtimex
278 PTR compat_sys_setrlimit /* 6155 */ 278 PTR compat_sys_setrlimit /* 6155 */
@@ -385,7 +385,7 @@ EXPORT(sysn32_call_table)
385 PTR sys_fchmodat 385 PTR sys_fchmodat
386 PTR sys_faccessat 386 PTR sys_faccessat
387 PTR compat_sys_pselect6 387 PTR compat_sys_pselect6
388 PTR sys_ppoll /* 6265 */ 388 PTR compat_sys_ppoll /* 6265 */
389 PTR sys_unshare 389 PTR sys_unshare
390 PTR sys_splice 390 PTR sys_splice
391 PTR sys_sync_file_range 391 PTR sys_sync_file_range
@@ -418,4 +418,5 @@ EXPORT(sysn32_call_table)
418 PTR compat_sys_rt_tgsigqueueinfo /* 5295 */ 418 PTR compat_sys_rt_tgsigqueueinfo /* 5295 */
419 PTR sys_perf_event_open 419 PTR sys_perf_event_open
420 PTR sys_accept4 420 PTR sys_accept4
421 PTR compat_sys_recvmmsg
421 .size sysn32_call_table,.-sysn32_call_table 422 .size sysn32_call_table,.-sysn32_call_table
diff --git a/arch/mips/kernel/scall64-o32.S b/arch/mips/kernel/scall64-o32.S
index 14dde4ca932e..813689ef2384 100644
--- a/arch/mips/kernel/scall64-o32.S
+++ b/arch/mips/kernel/scall64-o32.S
@@ -325,7 +325,7 @@ sys_call_table:
325 PTR sys32_sigreturn 325 PTR sys32_sigreturn
326 PTR sys32_clone /* 4120 */ 326 PTR sys32_clone /* 4120 */
327 PTR sys_setdomainname 327 PTR sys_setdomainname
328 PTR sys_32_newuname 328 PTR sys_newuname
329 PTR sys_ni_syscall /* sys_modify_ldt */ 329 PTR sys_ni_syscall /* sys_modify_ldt */
330 PTR compat_sys_adjtimex 330 PTR compat_sys_adjtimex
331 PTR sys_mprotect /* 4125 */ 331 PTR sys_mprotect /* 4125 */
@@ -356,7 +356,7 @@ sys_call_table:
356 PTR sys_ni_syscall /* 4150 */ 356 PTR sys_ni_syscall /* 4150 */
357 PTR sys_getsid 357 PTR sys_getsid
358 PTR sys_fdatasync 358 PTR sys_fdatasync
359 PTR sys_32_sysctl 359 PTR compat_sys_sysctl
360 PTR sys_mlock 360 PTR sys_mlock
361 PTR sys_munlock /* 4155 */ 361 PTR sys_munlock /* 4155 */
362 PTR sys_mlockall 362 PTR sys_mlockall
@@ -538,4 +538,5 @@ sys_call_table:
538 PTR compat_sys_rt_tgsigqueueinfo 538 PTR compat_sys_rt_tgsigqueueinfo
539 PTR sys_perf_event_open 539 PTR sys_perf_event_open
540 PTR sys_accept4 540 PTR sys_accept4
541 PTR compat_sys_recvmmsg
541 .size sys_call_table,.-sys_call_table 542 .size sys_call_table,.-sys_call_table
diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c
index 2b290d70083e..f9513f9e61d3 100644
--- a/arch/mips/kernel/setup.c
+++ b/arch/mips/kernel/setup.c
@@ -58,8 +58,12 @@ EXPORT_SYMBOL(mips_machtype);
58 58
59struct boot_mem_map boot_mem_map; 59struct boot_mem_map boot_mem_map;
60 60
61static char command_line[CL_SIZE]; 61static char __initdata command_line[COMMAND_LINE_SIZE];
62 char arcs_cmdline[CL_SIZE]=CONFIG_CMDLINE; 62char __initdata arcs_cmdline[COMMAND_LINE_SIZE];
63
64#ifdef CONFIG_CMDLINE_BOOL
65static char __initdata builtin_cmdline[COMMAND_LINE_SIZE] = CONFIG_CMDLINE;
66#endif
63 67
64/* 68/*
65 * mips_io_port_base is the begin of the address space to which x86 style 69 * mips_io_port_base is the begin of the address space to which x86 style
@@ -166,26 +170,8 @@ static unsigned long __init init_initrd(void)
166 * already set up initrd_start and initrd_end. In these cases 170 * already set up initrd_start and initrd_end. In these cases
167 * perfom sanity checks and use them if all looks good. 171 * perfom sanity checks and use them if all looks good.
168 */ 172 */
169 if (!initrd_start || initrd_end <= initrd_start) { 173 if (!initrd_start || initrd_end <= initrd_start)
170#ifdef CONFIG_PROBE_INITRD_HEADER
171 u32 *initrd_header;
172
173 /*
174 * See if initrd has been added to the kernel image by
175 * arch/mips/boot/addinitrd.c. In that case a header is
176 * prepended to initrd and is made up by 8 bytes. The first
177 * word is a magic number and the second one is the size of
178 * initrd. Initrd start must be page aligned in any cases.
179 */
180 initrd_header = __va(PAGE_ALIGN(__pa_symbol(&_end) + 8)) - 8;
181 if (initrd_header[0] != 0x494E5244)
182 goto disable;
183 initrd_start = (unsigned long)(initrd_header + 2);
184 initrd_end = initrd_start + initrd_header[1];
185#else
186 goto disable; 174 goto disable;
187#endif
188 }
189 175
190 if (initrd_start & ~PAGE_MASK) { 176 if (initrd_start & ~PAGE_MASK) {
191 pr_err("initrd start must be page aligned\n"); 177 pr_err("initrd start must be page aligned\n");
@@ -476,8 +462,20 @@ static void __init arch_mem_init(char **cmdline_p)
476 pr_info("Determined physical RAM map:\n"); 462 pr_info("Determined physical RAM map:\n");
477 print_memory_map(); 463 print_memory_map();
478 464
479 strlcpy(command_line, arcs_cmdline, sizeof(command_line)); 465#ifdef CONFIG_CMDLINE_BOOL
480 strlcpy(boot_command_line, command_line, COMMAND_LINE_SIZE); 466#ifdef CONFIG_CMDLINE_OVERRIDE
467 strlcpy(boot_command_line, builtin_cmdline, COMMAND_LINE_SIZE);
468#else
469 if (builtin_cmdline[0]) {
470 strlcat(arcs_cmdline, " ", COMMAND_LINE_SIZE);
471 strlcat(arcs_cmdline, builtin_cmdline, COMMAND_LINE_SIZE);
472 }
473 strlcpy(boot_command_line, arcs_cmdline, COMMAND_LINE_SIZE);
474#endif
475#else
476 strlcpy(boot_command_line, arcs_cmdline, COMMAND_LINE_SIZE);
477#endif
478 strlcpy(command_line, boot_command_line, COMMAND_LINE_SIZE);
481 479
482 *cmdline_p = command_line; 480 *cmdline_p = command_line;
483 481
diff --git a/arch/mips/kernel/signal-common.h b/arch/mips/kernel/signal-common.h
index 6c8e8c4246f7..10263b405981 100644
--- a/arch/mips/kernel/signal-common.h
+++ b/arch/mips/kernel/signal-common.h
@@ -26,11 +26,6 @@
26 */ 26 */
27extern void __user *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, 27extern void __user *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs,
28 size_t frame_size); 28 size_t frame_size);
29/*
30 * install trampoline code to get back from the sig handler
31 */
32extern int install_sigtramp(unsigned int __user *tramp, unsigned int syscall);
33
34/* Check and clear pending FPU exceptions in saved CSR */ 29/* Check and clear pending FPU exceptions in saved CSR */
35extern int fpcsr_pending(unsigned int __user *fpcsr); 30extern int fpcsr_pending(unsigned int __user *fpcsr);
36 31
diff --git a/arch/mips/kernel/signal.c b/arch/mips/kernel/signal.c
index 6254041b942f..2099d5a4c4b7 100644
--- a/arch/mips/kernel/signal.c
+++ b/arch/mips/kernel/signal.c
@@ -32,50 +32,33 @@
32#include <asm/ucontext.h> 32#include <asm/ucontext.h>
33#include <asm/cpu-features.h> 33#include <asm/cpu-features.h>
34#include <asm/war.h> 34#include <asm/war.h>
35#include <asm/vdso.h>
35 36
36#include "signal-common.h" 37#include "signal-common.h"
37 38
38/* 39static int (*save_fp_context)(struct sigcontext __user *sc);
39 * Horribly complicated - with the bloody RM9000 workarounds enabled 40static int (*restore_fp_context)(struct sigcontext __user *sc);
40 * the signal trampolines is moving to the end of the structure so we can 41
41 * increase the alignment without breaking software compatibility. 42extern asmlinkage int _save_fp_context(struct sigcontext __user *sc);
42 */ 43extern asmlinkage int _restore_fp_context(struct sigcontext __user *sc);
43#if ICACHE_REFILLS_WORKAROUND_WAR == 0 44
45extern asmlinkage int fpu_emulator_save_context(struct sigcontext __user *sc);
46extern asmlinkage int fpu_emulator_restore_context(struct sigcontext __user *sc);
44 47
45struct sigframe { 48struct sigframe {
46 u32 sf_ass[4]; /* argument save space for o32 */ 49 u32 sf_ass[4]; /* argument save space for o32 */
47 u32 sf_code[2]; /* signal trampoline */ 50 u32 sf_pad[2]; /* Was: signal trampoline */
48 struct sigcontext sf_sc; 51 struct sigcontext sf_sc;
49 sigset_t sf_mask; 52 sigset_t sf_mask;
50}; 53};
51 54
52struct rt_sigframe { 55struct rt_sigframe {
53 u32 rs_ass[4]; /* argument save space for o32 */ 56 u32 rs_ass[4]; /* argument save space for o32 */
54 u32 rs_code[2]; /* signal trampoline */ 57 u32 rs_pad[2]; /* Was: signal trampoline */
55 struct siginfo rs_info;
56 struct ucontext rs_uc;
57};
58
59#else
60
61struct sigframe {
62 u32 sf_ass[4]; /* argument save space for o32 */
63 u32 sf_pad[2];
64 struct sigcontext sf_sc; /* hw context */
65 sigset_t sf_mask;
66 u32 sf_code[8] ____cacheline_aligned; /* signal trampoline */
67};
68
69struct rt_sigframe {
70 u32 rs_ass[4]; /* argument save space for o32 */
71 u32 rs_pad[2];
72 struct siginfo rs_info; 58 struct siginfo rs_info;
73 struct ucontext rs_uc; 59 struct ucontext rs_uc;
74 u32 rs_code[8] ____cacheline_aligned; /* signal trampoline */
75}; 60};
76 61
77#endif
78
79/* 62/*
80 * Helper routines 63 * Helper routines
81 */ 64 */
@@ -257,32 +240,6 @@ void __user *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs,
257 return (void __user *)((sp - frame_size) & (ICACHE_REFILLS_WORKAROUND_WAR ? ~(cpu_icache_line_size()-1) : ALMASK)); 240 return (void __user *)((sp - frame_size) & (ICACHE_REFILLS_WORKAROUND_WAR ? ~(cpu_icache_line_size()-1) : ALMASK));
258} 241}
259 242
260int install_sigtramp(unsigned int __user *tramp, unsigned int syscall)
261{
262 int err;
263
264 /*
265 * Set up the return code ...
266 *
267 * li v0, __NR__foo_sigreturn
268 * syscall
269 */
270
271 err = __put_user(0x24020000 + syscall, tramp + 0);
272 err |= __put_user(0x0000000c , tramp + 1);
273 if (ICACHE_REFILLS_WORKAROUND_WAR) {
274 err |= __put_user(0, tramp + 2);
275 err |= __put_user(0, tramp + 3);
276 err |= __put_user(0, tramp + 4);
277 err |= __put_user(0, tramp + 5);
278 err |= __put_user(0, tramp + 6);
279 err |= __put_user(0, tramp + 7);
280 }
281 flush_cache_sigtramp((unsigned long) tramp);
282
283 return err;
284}
285
286/* 243/*
287 * Atomically swap in the new signal mask, and wait for a signal. 244 * Atomically swap in the new signal mask, and wait for a signal.
288 */ 245 */
@@ -475,8 +432,8 @@ badframe:
475} 432}
476 433
477#ifdef CONFIG_TRAD_SIGNALS 434#ifdef CONFIG_TRAD_SIGNALS
478static int setup_frame(struct k_sigaction * ka, struct pt_regs *regs, 435static int setup_frame(void *sig_return, struct k_sigaction *ka,
479 int signr, sigset_t *set) 436 struct pt_regs *regs, int signr, sigset_t *set)
480{ 437{
481 struct sigframe __user *frame; 438 struct sigframe __user *frame;
482 int err = 0; 439 int err = 0;
@@ -485,8 +442,6 @@ static int setup_frame(struct k_sigaction * ka, struct pt_regs *regs,
485 if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame))) 442 if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame)))
486 goto give_sigsegv; 443 goto give_sigsegv;
487 444
488 err |= install_sigtramp(frame->sf_code, __NR_sigreturn);
489
490 err |= setup_sigcontext(regs, &frame->sf_sc); 445 err |= setup_sigcontext(regs, &frame->sf_sc);
491 err |= __copy_to_user(&frame->sf_mask, set, sizeof(*set)); 446 err |= __copy_to_user(&frame->sf_mask, set, sizeof(*set));
492 if (err) 447 if (err)
@@ -506,7 +461,7 @@ static int setup_frame(struct k_sigaction * ka, struct pt_regs *regs,
506 regs->regs[ 5] = 0; 461 regs->regs[ 5] = 0;
507 regs->regs[ 6] = (unsigned long) &frame->sf_sc; 462 regs->regs[ 6] = (unsigned long) &frame->sf_sc;
508 regs->regs[29] = (unsigned long) frame; 463 regs->regs[29] = (unsigned long) frame;
509 regs->regs[31] = (unsigned long) frame->sf_code; 464 regs->regs[31] = (unsigned long) sig_return;
510 regs->cp0_epc = regs->regs[25] = (unsigned long) ka->sa.sa_handler; 465 regs->cp0_epc = regs->regs[25] = (unsigned long) ka->sa.sa_handler;
511 466
512 DEBUGP("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%lx\n", 467 DEBUGP("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%lx\n",
@@ -520,8 +475,9 @@ give_sigsegv:
520} 475}
521#endif 476#endif
522 477
523static int setup_rt_frame(struct k_sigaction * ka, struct pt_regs *regs, 478static int setup_rt_frame(void *sig_return, struct k_sigaction *ka,
524 int signr, sigset_t *set, siginfo_t *info) 479 struct pt_regs *regs, int signr, sigset_t *set,
480 siginfo_t *info)
525{ 481{
526 struct rt_sigframe __user *frame; 482 struct rt_sigframe __user *frame;
527 int err = 0; 483 int err = 0;
@@ -530,8 +486,6 @@ static int setup_rt_frame(struct k_sigaction * ka, struct pt_regs *regs,
530 if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame))) 486 if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame)))
531 goto give_sigsegv; 487 goto give_sigsegv;
532 488
533 err |= install_sigtramp(frame->rs_code, __NR_rt_sigreturn);
534
535 /* Create siginfo. */ 489 /* Create siginfo. */
536 err |= copy_siginfo_to_user(&frame->rs_info, info); 490 err |= copy_siginfo_to_user(&frame->rs_info, info);
537 491
@@ -564,7 +518,7 @@ static int setup_rt_frame(struct k_sigaction * ka, struct pt_regs *regs,
564 regs->regs[ 5] = (unsigned long) &frame->rs_info; 518 regs->regs[ 5] = (unsigned long) &frame->rs_info;
565 regs->regs[ 6] = (unsigned long) &frame->rs_uc; 519 regs->regs[ 6] = (unsigned long) &frame->rs_uc;
566 regs->regs[29] = (unsigned long) frame; 520 regs->regs[29] = (unsigned long) frame;
567 regs->regs[31] = (unsigned long) frame->rs_code; 521 regs->regs[31] = (unsigned long) sig_return;
568 regs->cp0_epc = regs->regs[25] = (unsigned long) ka->sa.sa_handler; 522 regs->cp0_epc = regs->regs[25] = (unsigned long) ka->sa.sa_handler;
569 523
570 DEBUGP("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%lx\n", 524 DEBUGP("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%lx\n",
@@ -581,8 +535,11 @@ give_sigsegv:
581struct mips_abi mips_abi = { 535struct mips_abi mips_abi = {
582#ifdef CONFIG_TRAD_SIGNALS 536#ifdef CONFIG_TRAD_SIGNALS
583 .setup_frame = setup_frame, 537 .setup_frame = setup_frame,
538 .signal_return_offset = offsetof(struct mips_vdso, signal_trampoline),
584#endif 539#endif
585 .setup_rt_frame = setup_rt_frame, 540 .setup_rt_frame = setup_rt_frame,
541 .rt_signal_return_offset =
542 offsetof(struct mips_vdso, rt_signal_trampoline),
586 .restart = __NR_restart_syscall 543 .restart = __NR_restart_syscall
587}; 544};
588 545
@@ -590,6 +547,8 @@ static int handle_signal(unsigned long sig, siginfo_t *info,
590 struct k_sigaction *ka, sigset_t *oldset, struct pt_regs *regs) 547 struct k_sigaction *ka, sigset_t *oldset, struct pt_regs *regs)
591{ 548{
592 int ret; 549 int ret;
550 struct mips_abi *abi = current->thread.abi;
551 void *vdso = current->mm->context.vdso;
593 552
594 switch(regs->regs[0]) { 553 switch(regs->regs[0]) {
595 case ERESTART_RESTARTBLOCK: 554 case ERESTART_RESTARTBLOCK:
@@ -610,9 +569,11 @@ static int handle_signal(unsigned long sig, siginfo_t *info,
610 regs->regs[0] = 0; /* Don't deal with this again. */ 569 regs->regs[0] = 0; /* Don't deal with this again. */
611 570
612 if (sig_uses_siginfo(ka)) 571 if (sig_uses_siginfo(ka))
613 ret = current->thread.abi->setup_rt_frame(ka, regs, sig, oldset, info); 572 ret = abi->setup_rt_frame(vdso + abi->rt_signal_return_offset,
573 ka, regs, sig, oldset, info);
614 else 574 else
615 ret = current->thread.abi->setup_frame(ka, regs, sig, oldset); 575 ret = abi->setup_frame(vdso + abi->signal_return_offset,
576 ka, regs, sig, oldset);
616 577
617 spin_lock_irq(&current->sighand->siglock); 578 spin_lock_irq(&current->sighand->siglock);
618 sigorsets(&current->blocked, &current->blocked, &ka->sa.sa_mask); 579 sigorsets(&current->blocked, &current->blocked, &ka->sa.sa_mask);
@@ -709,3 +670,40 @@ asmlinkage void do_notify_resume(struct pt_regs *regs, void *unused,
709 key_replace_session_keyring(); 670 key_replace_session_keyring();
710 } 671 }
711} 672}
673
674#ifdef CONFIG_SMP
675static int smp_save_fp_context(struct sigcontext __user *sc)
676{
677 return raw_cpu_has_fpu
678 ? _save_fp_context(sc)
679 : fpu_emulator_save_context(sc);
680}
681
682static int smp_restore_fp_context(struct sigcontext __user *sc)
683{
684 return raw_cpu_has_fpu
685 ? _restore_fp_context(sc)
686 : fpu_emulator_restore_context(sc);
687}
688#endif
689
690static int signal_setup(void)
691{
692#ifdef CONFIG_SMP
693 /* For now just do the cpu_has_fpu check when the functions are invoked */
694 save_fp_context = smp_save_fp_context;
695 restore_fp_context = smp_restore_fp_context;
696#else
697 if (cpu_has_fpu) {
698 save_fp_context = _save_fp_context;
699 restore_fp_context = _restore_fp_context;
700 } else {
701 save_fp_context = fpu_emulator_save_context;
702 restore_fp_context = fpu_emulator_restore_context;
703 }
704#endif
705
706 return 0;
707}
708
709arch_initcall(signal_setup);
diff --git a/arch/mips/kernel/signal32.c b/arch/mips/kernel/signal32.c
index 2e74075ac0ca..a0ed0e052b2e 100644
--- a/arch/mips/kernel/signal32.c
+++ b/arch/mips/kernel/signal32.c
@@ -32,14 +32,22 @@
32#include <asm/system.h> 32#include <asm/system.h>
33#include <asm/fpu.h> 33#include <asm/fpu.h>
34#include <asm/war.h> 34#include <asm/war.h>
35#include <asm/vdso.h>
35 36
36#include "signal-common.h" 37#include "signal-common.h"
37 38
39static int (*save_fp_context32)(struct sigcontext32 __user *sc);
40static int (*restore_fp_context32)(struct sigcontext32 __user *sc);
41
42extern asmlinkage int _save_fp_context32(struct sigcontext32 __user *sc);
43extern asmlinkage int _restore_fp_context32(struct sigcontext32 __user *sc);
44
45extern asmlinkage int fpu_emulator_save_context32(struct sigcontext32 __user *sc);
46extern asmlinkage int fpu_emulator_restore_context32(struct sigcontext32 __user *sc);
47
38/* 48/*
39 * Including <asm/unistd.h> would give use the 64-bit syscall numbers ... 49 * Including <asm/unistd.h> would give use the 64-bit syscall numbers ...
40 */ 50 */
41#define __NR_O32_sigreturn 4119
42#define __NR_O32_rt_sigreturn 4193
43#define __NR_O32_restart_syscall 4253 51#define __NR_O32_restart_syscall 4253
44 52
45/* 32-bit compatibility types */ 53/* 32-bit compatibility types */
@@ -68,47 +76,20 @@ struct ucontext32 {
68 compat_sigset_t uc_sigmask; /* mask last for extensibility */ 76 compat_sigset_t uc_sigmask; /* mask last for extensibility */
69}; 77};
70 78
71/*
72 * Horribly complicated - with the bloody RM9000 workarounds enabled
73 * the signal trampolines is moving to the end of the structure so we can
74 * increase the alignment without breaking software compatibility.
75 */
76#if ICACHE_REFILLS_WORKAROUND_WAR == 0
77
78struct sigframe32 { 79struct sigframe32 {
79 u32 sf_ass[4]; /* argument save space for o32 */ 80 u32 sf_ass[4]; /* argument save space for o32 */
80 u32 sf_code[2]; /* signal trampoline */ 81 u32 sf_pad[2]; /* Was: signal trampoline */
81 struct sigcontext32 sf_sc; 82 struct sigcontext32 sf_sc;
82 compat_sigset_t sf_mask; 83 compat_sigset_t sf_mask;
83}; 84};
84 85
85struct rt_sigframe32 { 86struct rt_sigframe32 {
86 u32 rs_ass[4]; /* argument save space for o32 */ 87 u32 rs_ass[4]; /* argument save space for o32 */
87 u32 rs_code[2]; /* signal trampoline */ 88 u32 rs_pad[2]; /* Was: signal trampoline */
88 compat_siginfo_t rs_info;
89 struct ucontext32 rs_uc;
90};
91
92#else /* ICACHE_REFILLS_WORKAROUND_WAR */
93
94struct sigframe32 {
95 u32 sf_ass[4]; /* argument save space for o32 */
96 u32 sf_pad[2];
97 struct sigcontext32 sf_sc; /* hw context */
98 compat_sigset_t sf_mask;
99 u32 sf_code[8] ____cacheline_aligned; /* signal trampoline */
100};
101
102struct rt_sigframe32 {
103 u32 rs_ass[4]; /* argument save space for o32 */
104 u32 rs_pad[2];
105 compat_siginfo_t rs_info; 89 compat_siginfo_t rs_info;
106 struct ucontext32 rs_uc; 90 struct ucontext32 rs_uc;
107 u32 rs_code[8] __attribute__((aligned(32))); /* signal trampoline */
108}; 91};
109 92
110#endif /* !ICACHE_REFILLS_WORKAROUND_WAR */
111
112/* 93/*
113 * sigcontext handlers 94 * sigcontext handlers
114 */ 95 */
@@ -589,8 +570,8 @@ badframe:
589 force_sig(SIGSEGV, current); 570 force_sig(SIGSEGV, current);
590} 571}
591 572
592static int setup_frame_32(struct k_sigaction * ka, struct pt_regs *regs, 573static int setup_frame_32(void *sig_return, struct k_sigaction *ka,
593 int signr, sigset_t *set) 574 struct pt_regs *regs, int signr, sigset_t *set)
594{ 575{
595 struct sigframe32 __user *frame; 576 struct sigframe32 __user *frame;
596 int err = 0; 577 int err = 0;
@@ -599,8 +580,6 @@ static int setup_frame_32(struct k_sigaction * ka, struct pt_regs *regs,
599 if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame))) 580 if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame)))
600 goto give_sigsegv; 581 goto give_sigsegv;
601 582
602 err |= install_sigtramp(frame->sf_code, __NR_O32_sigreturn);
603
604 err |= setup_sigcontext32(regs, &frame->sf_sc); 583 err |= setup_sigcontext32(regs, &frame->sf_sc);
605 err |= __copy_conv_sigset_to_user(&frame->sf_mask, set); 584 err |= __copy_conv_sigset_to_user(&frame->sf_mask, set);
606 585
@@ -621,7 +600,7 @@ static int setup_frame_32(struct k_sigaction * ka, struct pt_regs *regs,
621 regs->regs[ 5] = 0; 600 regs->regs[ 5] = 0;
622 regs->regs[ 6] = (unsigned long) &frame->sf_sc; 601 regs->regs[ 6] = (unsigned long) &frame->sf_sc;
623 regs->regs[29] = (unsigned long) frame; 602 regs->regs[29] = (unsigned long) frame;
624 regs->regs[31] = (unsigned long) frame->sf_code; 603 regs->regs[31] = (unsigned long) sig_return;
625 regs->cp0_epc = regs->regs[25] = (unsigned long) ka->sa.sa_handler; 604 regs->cp0_epc = regs->regs[25] = (unsigned long) ka->sa.sa_handler;
626 605
627 DEBUGP("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%lx\n", 606 DEBUGP("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%lx\n",
@@ -635,8 +614,9 @@ give_sigsegv:
635 return -EFAULT; 614 return -EFAULT;
636} 615}
637 616
638static int setup_rt_frame_32(struct k_sigaction * ka, struct pt_regs *regs, 617static int setup_rt_frame_32(void *sig_return, struct k_sigaction *ka,
639 int signr, sigset_t *set, siginfo_t *info) 618 struct pt_regs *regs, int signr, sigset_t *set,
619 siginfo_t *info)
640{ 620{
641 struct rt_sigframe32 __user *frame; 621 struct rt_sigframe32 __user *frame;
642 int err = 0; 622 int err = 0;
@@ -646,8 +626,6 @@ static int setup_rt_frame_32(struct k_sigaction * ka, struct pt_regs *regs,
646 if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame))) 626 if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame)))
647 goto give_sigsegv; 627 goto give_sigsegv;
648 628
649 err |= install_sigtramp(frame->rs_code, __NR_O32_rt_sigreturn);
650
651 /* Convert (siginfo_t -> compat_siginfo_t) and copy to user. */ 629 /* Convert (siginfo_t -> compat_siginfo_t) and copy to user. */
652 err |= copy_siginfo_to_user32(&frame->rs_info, info); 630 err |= copy_siginfo_to_user32(&frame->rs_info, info);
653 631
@@ -681,7 +659,7 @@ static int setup_rt_frame_32(struct k_sigaction * ka, struct pt_regs *regs,
681 regs->regs[ 5] = (unsigned long) &frame->rs_info; 659 regs->regs[ 5] = (unsigned long) &frame->rs_info;
682 regs->regs[ 6] = (unsigned long) &frame->rs_uc; 660 regs->regs[ 6] = (unsigned long) &frame->rs_uc;
683 regs->regs[29] = (unsigned long) frame; 661 regs->regs[29] = (unsigned long) frame;
684 regs->regs[31] = (unsigned long) frame->rs_code; 662 regs->regs[31] = (unsigned long) sig_return;
685 regs->cp0_epc = regs->regs[25] = (unsigned long) ka->sa.sa_handler; 663 regs->cp0_epc = regs->regs[25] = (unsigned long) ka->sa.sa_handler;
686 664
687 DEBUGP("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%lx\n", 665 DEBUGP("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%lx\n",
@@ -700,7 +678,11 @@ give_sigsegv:
700 */ 678 */
701struct mips_abi mips_abi_32 = { 679struct mips_abi mips_abi_32 = {
702 .setup_frame = setup_frame_32, 680 .setup_frame = setup_frame_32,
681 .signal_return_offset =
682 offsetof(struct mips_vdso, o32_signal_trampoline),
703 .setup_rt_frame = setup_rt_frame_32, 683 .setup_rt_frame = setup_rt_frame_32,
684 .rt_signal_return_offset =
685 offsetof(struct mips_vdso, o32_rt_signal_trampoline),
704 .restart = __NR_O32_restart_syscall 686 .restart = __NR_O32_restart_syscall
705}; 687};
706 688
@@ -828,3 +810,18 @@ SYSCALL_DEFINE5(32_waitid, int, which, compat_pid_t, pid,
828 info.si_code |= __SI_CHLD; 810 info.si_code |= __SI_CHLD;
829 return copy_siginfo_to_user32(uinfo, &info); 811 return copy_siginfo_to_user32(uinfo, &info);
830} 812}
813
814static int signal32_init(void)
815{
816 if (cpu_has_fpu) {
817 save_fp_context32 = _save_fp_context32;
818 restore_fp_context32 = _restore_fp_context32;
819 } else {
820 save_fp_context32 = fpu_emulator_save_context32;
821 restore_fp_context32 = fpu_emulator_restore_context32;
822 }
823
824 return 0;
825}
826
827arch_initcall(signal32_init);
diff --git a/arch/mips/kernel/signal_n32.c b/arch/mips/kernel/signal_n32.c
index bb277e82d421..2c5df818c65a 100644
--- a/arch/mips/kernel/signal_n32.c
+++ b/arch/mips/kernel/signal_n32.c
@@ -39,13 +39,13 @@
39#include <asm/fpu.h> 39#include <asm/fpu.h>
40#include <asm/cpu-features.h> 40#include <asm/cpu-features.h>
41#include <asm/war.h> 41#include <asm/war.h>
42#include <asm/vdso.h>
42 43
43#include "signal-common.h" 44#include "signal-common.h"
44 45
45/* 46/*
46 * Including <asm/unistd.h> would give use the 64-bit syscall numbers ... 47 * Including <asm/unistd.h> would give use the 64-bit syscall numbers ...
47 */ 48 */
48#define __NR_N32_rt_sigreturn 6211
49#define __NR_N32_restart_syscall 6214 49#define __NR_N32_restart_syscall 6214
50 50
51extern int setup_sigcontext(struct pt_regs *, struct sigcontext __user *); 51extern int setup_sigcontext(struct pt_regs *, struct sigcontext __user *);
@@ -67,27 +67,13 @@ struct ucontextn32 {
67 compat_sigset_t uc_sigmask; /* mask last for extensibility */ 67 compat_sigset_t uc_sigmask; /* mask last for extensibility */
68}; 68};
69 69
70#if ICACHE_REFILLS_WORKAROUND_WAR == 0
71
72struct rt_sigframe_n32 {
73 u32 rs_ass[4]; /* argument save space for o32 */
74 u32 rs_code[2]; /* signal trampoline */
75 struct compat_siginfo rs_info;
76 struct ucontextn32 rs_uc;
77};
78
79#else /* ICACHE_REFILLS_WORKAROUND_WAR */
80
81struct rt_sigframe_n32 { 70struct rt_sigframe_n32 {
82 u32 rs_ass[4]; /* argument save space for o32 */ 71 u32 rs_ass[4]; /* argument save space for o32 */
83 u32 rs_pad[2]; 72 u32 rs_pad[2]; /* Was: signal trampoline */
84 struct compat_siginfo rs_info; 73 struct compat_siginfo rs_info;
85 struct ucontextn32 rs_uc; 74 struct ucontextn32 rs_uc;
86 u32 rs_code[8] ____cacheline_aligned; /* signal trampoline */
87}; 75};
88 76
89#endif /* !ICACHE_REFILLS_WORKAROUND_WAR */
90
91extern void sigset_from_compat(sigset_t *set, compat_sigset_t *compat); 77extern void sigset_from_compat(sigset_t *set, compat_sigset_t *compat);
92 78
93asmlinkage int sysn32_rt_sigsuspend(nabi_no_regargs struct pt_regs regs) 79asmlinkage int sysn32_rt_sigsuspend(nabi_no_regargs struct pt_regs regs)
@@ -173,7 +159,7 @@ badframe:
173 force_sig(SIGSEGV, current); 159 force_sig(SIGSEGV, current);
174} 160}
175 161
176static int setup_rt_frame_n32(struct k_sigaction * ka, 162static int setup_rt_frame_n32(void *sig_return, struct k_sigaction *ka,
177 struct pt_regs *regs, int signr, sigset_t *set, siginfo_t *info) 163 struct pt_regs *regs, int signr, sigset_t *set, siginfo_t *info)
178{ 164{
179 struct rt_sigframe_n32 __user *frame; 165 struct rt_sigframe_n32 __user *frame;
@@ -184,8 +170,6 @@ static int setup_rt_frame_n32(struct k_sigaction * ka,
184 if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame))) 170 if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame)))
185 goto give_sigsegv; 171 goto give_sigsegv;
186 172
187 install_sigtramp(frame->rs_code, __NR_N32_rt_sigreturn);
188
189 /* Create siginfo. */ 173 /* Create siginfo. */
190 err |= copy_siginfo_to_user32(&frame->rs_info, info); 174 err |= copy_siginfo_to_user32(&frame->rs_info, info);
191 175
@@ -219,7 +203,7 @@ static int setup_rt_frame_n32(struct k_sigaction * ka,
219 regs->regs[ 5] = (unsigned long) &frame->rs_info; 203 regs->regs[ 5] = (unsigned long) &frame->rs_info;
220 regs->regs[ 6] = (unsigned long) &frame->rs_uc; 204 regs->regs[ 6] = (unsigned long) &frame->rs_uc;
221 regs->regs[29] = (unsigned long) frame; 205 regs->regs[29] = (unsigned long) frame;
222 regs->regs[31] = (unsigned long) frame->rs_code; 206 regs->regs[31] = (unsigned long) sig_return;
223 regs->cp0_epc = regs->regs[25] = (unsigned long) ka->sa.sa_handler; 207 regs->cp0_epc = regs->regs[25] = (unsigned long) ka->sa.sa_handler;
224 208
225 DEBUGP("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%lx\n", 209 DEBUGP("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%lx\n",
@@ -235,5 +219,7 @@ give_sigsegv:
235 219
236struct mips_abi mips_abi_n32 = { 220struct mips_abi mips_abi_n32 = {
237 .setup_rt_frame = setup_rt_frame_n32, 221 .setup_rt_frame = setup_rt_frame_n32,
222 .rt_signal_return_offset =
223 offsetof(struct mips_vdso, n32_rt_signal_trampoline),
238 .restart = __NR_N32_restart_syscall 224 .restart = __NR_N32_restart_syscall
239}; 225};
diff --git a/arch/mips/kernel/smp.c b/arch/mips/kernel/smp.c
index e72e6844d134..6cdca1956b77 100644
--- a/arch/mips/kernel/smp.c
+++ b/arch/mips/kernel/smp.c
@@ -32,6 +32,7 @@
32#include <linux/cpumask.h> 32#include <linux/cpumask.h>
33#include <linux/cpu.h> 33#include <linux/cpu.h>
34#include <linux/err.h> 34#include <linux/err.h>
35#include <linux/ftrace.h>
35 36
36#include <asm/atomic.h> 37#include <asm/atomic.h>
37#include <asm/cpu.h> 38#include <asm/cpu.h>
@@ -130,7 +131,7 @@ asmlinkage __cpuinit void start_secondary(void)
130/* 131/*
131 * Call into both interrupt handlers, as we share the IPI for them 132 * Call into both interrupt handlers, as we share the IPI for them
132 */ 133 */
133void smp_call_function_interrupt(void) 134void __irq_entry smp_call_function_interrupt(void)
134{ 135{
135 irq_enter(); 136 irq_enter();
136 generic_smp_call_function_single_interrupt(); 137 generic_smp_call_function_single_interrupt();
diff --git a/arch/mips/kernel/smtc.c b/arch/mips/kernel/smtc.c
index 24630fd8ef60..a95dea5459c4 100644
--- a/arch/mips/kernel/smtc.c
+++ b/arch/mips/kernel/smtc.c
@@ -25,6 +25,8 @@
25#include <linux/interrupt.h> 25#include <linux/interrupt.h>
26#include <linux/kernel_stat.h> 26#include <linux/kernel_stat.h>
27#include <linux/module.h> 27#include <linux/module.h>
28#include <linux/ftrace.h>
29#include <linux/slab.h>
28 30
29#include <asm/cpu.h> 31#include <asm/cpu.h>
30#include <asm/processor.h> 32#include <asm/processor.h>
@@ -180,7 +182,7 @@ static int vpemask[2][8] = {
180 {0, 0, 0, 0, 0, 0, 0, 1} 182 {0, 0, 0, 0, 0, 0, 0, 1}
181}; 183};
182int tcnoprog[NR_CPUS]; 184int tcnoprog[NR_CPUS];
183static atomic_t idle_hook_initialized = {0}; 185static atomic_t idle_hook_initialized = ATOMIC_INIT(0);
184static int clock_hang_reported[NR_CPUS]; 186static int clock_hang_reported[NR_CPUS];
185 187
186#endif /* CONFIG_SMTC_IDLE_HOOK_DEBUG */ 188#endif /* CONFIG_SMTC_IDLE_HOOK_DEBUG */
@@ -939,23 +941,29 @@ static void ipi_call_interrupt(void)
939 941
940DECLARE_PER_CPU(struct clock_event_device, mips_clockevent_device); 942DECLARE_PER_CPU(struct clock_event_device, mips_clockevent_device);
941 943
942void ipi_decode(struct smtc_ipi *pipi) 944static void __irq_entry smtc_clock_tick_interrupt(void)
943{ 945{
944 unsigned int cpu = smp_processor_id(); 946 unsigned int cpu = smp_processor_id();
945 struct clock_event_device *cd; 947 struct clock_event_device *cd;
948 int irq = MIPS_CPU_IRQ_BASE + 1;
949
950 irq_enter();
951 kstat_incr_irqs_this_cpu(irq, irq_to_desc(irq));
952 cd = &per_cpu(mips_clockevent_device, cpu);
953 cd->event_handler(cd);
954 irq_exit();
955}
956
957void ipi_decode(struct smtc_ipi *pipi)
958{
946 void *arg_copy = pipi->arg; 959 void *arg_copy = pipi->arg;
947 int type_copy = pipi->type; 960 int type_copy = pipi->type;
948 int irq = MIPS_CPU_IRQ_BASE + 1;
949 961
950 smtc_ipi_nq(&freeIPIq, pipi); 962 smtc_ipi_nq(&freeIPIq, pipi);
951 963
952 switch (type_copy) { 964 switch (type_copy) {
953 case SMTC_CLOCK_TICK: 965 case SMTC_CLOCK_TICK:
954 irq_enter(); 966 smtc_clock_tick_interrupt();
955 kstat_incr_irqs_this_cpu(irq, irq_to_desc(irq));
956 cd = &per_cpu(mips_clockevent_device, cpu);
957 cd->event_handler(cd);
958 irq_exit();
959 break; 967 break;
960 968
961 case LINUX_SMP_IPI: 969 case LINUX_SMP_IPI:
@@ -1331,7 +1339,7 @@ void smtc_get_new_mmu_context(struct mm_struct *mm, unsigned long cpu)
1331 if (!((asid += ASID_INC) & ASID_MASK) ) { 1339 if (!((asid += ASID_INC) & ASID_MASK) ) {
1332 if (cpu_has_vtag_icache) 1340 if (cpu_has_vtag_icache)
1333 flush_icache_all(); 1341 flush_icache_all();
1334 /* Traverse all online CPUs (hack requires contigous range) */ 1342 /* Traverse all online CPUs (hack requires contiguous range) */
1335 for_each_online_cpu(i) { 1343 for_each_online_cpu(i) {
1336 /* 1344 /*
1337 * We don't need to worry about our own CPU, nor those of 1345 * We don't need to worry about our own CPU, nor those of
diff --git a/arch/mips/kernel/spinlock_test.c b/arch/mips/kernel/spinlock_test.c
new file mode 100644
index 000000000000..da61134dfc53
--- /dev/null
+++ b/arch/mips/kernel/spinlock_test.c
@@ -0,0 +1,141 @@
1#include <linux/init.h>
2#include <linux/kthread.h>
3#include <linux/hrtimer.h>
4#include <linux/fs.h>
5#include <linux/debugfs.h>
6#include <linux/module.h>
7#include <linux/spinlock.h>
8
9
10static int ss_get(void *data, u64 *val)
11{
12 ktime_t start, finish;
13 int loops;
14 int cont;
15 DEFINE_RAW_SPINLOCK(ss_spin);
16
17 loops = 1000000;
18 cont = 1;
19
20 start = ktime_get();
21
22 while (cont) {
23 raw_spin_lock(&ss_spin);
24 loops--;
25 if (loops == 0)
26 cont = 0;
27 raw_spin_unlock(&ss_spin);
28 }
29
30 finish = ktime_get();
31
32 *val = ktime_us_delta(finish, start);
33
34 return 0;
35}
36
37DEFINE_SIMPLE_ATTRIBUTE(fops_ss, ss_get, NULL, "%llu\n");
38
39
40
41struct spin_multi_state {
42 raw_spinlock_t lock;
43 atomic_t start_wait;
44 atomic_t enter_wait;
45 atomic_t exit_wait;
46 int loops;
47};
48
49struct spin_multi_per_thread {
50 struct spin_multi_state *state;
51 ktime_t start;
52};
53
54static int multi_other(void *data)
55{
56 int loops;
57 int cont;
58 struct spin_multi_per_thread *pt = data;
59 struct spin_multi_state *s = pt->state;
60
61 loops = s->loops;
62 cont = 1;
63
64 atomic_dec(&s->enter_wait);
65
66 while (atomic_read(&s->enter_wait))
67 ; /* spin */
68
69 pt->start = ktime_get();
70
71 atomic_dec(&s->start_wait);
72
73 while (atomic_read(&s->start_wait))
74 ; /* spin */
75
76 while (cont) {
77 raw_spin_lock(&s->lock);
78 loops--;
79 if (loops == 0)
80 cont = 0;
81 raw_spin_unlock(&s->lock);
82 }
83
84 atomic_dec(&s->exit_wait);
85 while (atomic_read(&s->exit_wait))
86 ; /* spin */
87 return 0;
88}
89
90static int multi_get(void *data, u64 *val)
91{
92 ktime_t finish;
93 struct spin_multi_state ms;
94 struct spin_multi_per_thread t1, t2;
95
96 ms.lock = __RAW_SPIN_LOCK_UNLOCKED("multi_get");
97 ms.loops = 1000000;
98
99 atomic_set(&ms.start_wait, 2);
100 atomic_set(&ms.enter_wait, 2);
101 atomic_set(&ms.exit_wait, 2);
102 t1.state = &ms;
103 t2.state = &ms;
104
105 kthread_run(multi_other, &t2, "multi_get");
106
107 multi_other(&t1);
108
109 finish = ktime_get();
110
111 *val = ktime_us_delta(finish, t1.start);
112
113 return 0;
114}
115
116DEFINE_SIMPLE_ATTRIBUTE(fops_multi, multi_get, NULL, "%llu\n");
117
118
119extern struct dentry *mips_debugfs_dir;
120static int __init spinlock_test(void)
121{
122 struct dentry *d;
123
124 if (!mips_debugfs_dir)
125 return -ENODEV;
126
127 d = debugfs_create_file("spin_single", S_IRUGO,
128 mips_debugfs_dir, NULL,
129 &fops_ss);
130 if (!d)
131 return -ENOMEM;
132
133 d = debugfs_create_file("spin_multi", S_IRUGO,
134 mips_debugfs_dir, NULL,
135 &fops_multi);
136 if (!d)
137 return -ENOMEM;
138
139 return 0;
140}
141device_initcall(spinlock_test);
diff --git a/arch/mips/kernel/syscall.c b/arch/mips/kernel/syscall.c
index fe0d79805603..dd81b0f87518 100644
--- a/arch/mips/kernel/syscall.c
+++ b/arch/mips/kernel/syscall.c
@@ -19,7 +19,6 @@
19#include <linux/string.h> 19#include <linux/string.h>
20#include <linux/syscalls.h> 20#include <linux/syscalls.h>
21#include <linux/file.h> 21#include <linux/file.h>
22#include <linux/slab.h>
23#include <linux/utsname.h> 22#include <linux/utsname.h>
24#include <linux/unistd.h> 23#include <linux/unistd.h>
25#include <linux/sem.h> 24#include <linux/sem.h>
@@ -29,6 +28,7 @@
29#include <linux/module.h> 28#include <linux/module.h>
30#include <linux/ipc.h> 29#include <linux/ipc.h>
31#include <linux/uaccess.h> 30#include <linux/uaccess.h>
31#include <linux/slab.h>
32 32
33#include <asm/asm.h> 33#include <asm/asm.h>
34#include <asm/branch.h> 34#include <asm/branch.h>
@@ -79,7 +79,11 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr,
79 int do_color_align; 79 int do_color_align;
80 unsigned long task_size; 80 unsigned long task_size;
81 81
82 task_size = STACK_TOP; 82#ifdef CONFIG_32BIT
83 task_size = TASK_SIZE;
84#else /* Must be CONFIG_64BIT*/
85 task_size = test_thread_flag(TIF_32BIT_ADDR) ? TASK_SIZE32 : TASK_SIZE;
86#endif
83 87
84 if (len > task_size) 88 if (len > task_size)
85 return -ENOMEM; 89 return -ENOMEM;
@@ -93,7 +97,8 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr,
93 * We do not accept a shared mapping if it would violate 97 * We do not accept a shared mapping if it would violate
94 * cache aliasing constraints. 98 * cache aliasing constraints.
95 */ 99 */
96 if ((flags & MAP_SHARED) && (addr & shm_align_mask)) 100 if ((flags & MAP_SHARED) &&
101 ((addr - (pgoff << PAGE_SHIFT)) & shm_align_mask))
97 return -EINVAL; 102 return -EINVAL;
98 return addr; 103 return addr;
99 } 104 }
@@ -129,31 +134,6 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr,
129 } 134 }
130} 135}
131 136
132/* common code for old and new mmaps */
133static inline unsigned long
134do_mmap2(unsigned long addr, unsigned long len, unsigned long prot,
135 unsigned long flags, unsigned long fd, unsigned long pgoff)
136{
137 unsigned long error = -EBADF;
138 struct file * file = NULL;
139
140 flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
141 if (!(flags & MAP_ANONYMOUS)) {
142 file = fget(fd);
143 if (!file)
144 goto out;
145 }
146
147 down_write(&current->mm->mmap_sem);
148 error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
149 up_write(&current->mm->mmap_sem);
150
151 if (file)
152 fput(file);
153out:
154 return error;
155}
156
157SYSCALL_DEFINE6(mips_mmap, unsigned long, addr, unsigned long, len, 137SYSCALL_DEFINE6(mips_mmap, unsigned long, addr, unsigned long, len,
158 unsigned long, prot, unsigned long, flags, unsigned long, 138 unsigned long, prot, unsigned long, flags, unsigned long,
159 fd, off_t, offset) 139 fd, off_t, offset)
@@ -164,7 +144,7 @@ SYSCALL_DEFINE6(mips_mmap, unsigned long, addr, unsigned long, len,
164 if (offset & ~PAGE_MASK) 144 if (offset & ~PAGE_MASK)
165 goto out; 145 goto out;
166 146
167 result = do_mmap2(addr, len, prot, flags, fd, offset >> PAGE_SHIFT); 147 result = sys_mmap_pgoff(addr, len, prot, flags, fd, offset >> PAGE_SHIFT);
168 148
169out: 149out:
170 return result; 150 return result;
@@ -177,7 +157,7 @@ SYSCALL_DEFINE6(mips_mmap2, unsigned long, addr, unsigned long, len,
177 if (pgoff & (~PAGE_MASK >> 12)) 157 if (pgoff & (~PAGE_MASK >> 12))
178 return -EINVAL; 158 return -EINVAL;
179 159
180 return do_mmap2(addr, len, prot, flags, fd, pgoff >> (PAGE_SHIFT-12)); 160 return sys_mmap_pgoff(addr, len, prot, flags, fd, pgoff >> (PAGE_SHIFT-12));
181} 161}
182 162
183save_static_function(sys_fork); 163save_static_function(sys_fork);
@@ -239,48 +219,6 @@ out:
239 return error; 219 return error;
240} 220}
241 221
242/*
243 * Compacrapability ...
244 */
245SYSCALL_DEFINE1(uname, struct old_utsname __user *, name)
246{
247 if (name && !copy_to_user(name, utsname(), sizeof (*name)))
248 return 0;
249 return -EFAULT;
250}
251
252/*
253 * Compacrapability ...
254 */
255SYSCALL_DEFINE1(olduname, struct oldold_utsname __user *, name)
256{
257 int error;
258
259 if (!name)
260 return -EFAULT;
261 if (!access_ok(VERIFY_WRITE, name, sizeof(struct oldold_utsname)))
262 return -EFAULT;
263
264 error = __copy_to_user(&name->sysname, &utsname()->sysname,
265 __OLD_UTS_LEN);
266 error -= __put_user(0, name->sysname + __OLD_UTS_LEN);
267 error -= __copy_to_user(&name->nodename, &utsname()->nodename,
268 __OLD_UTS_LEN);
269 error -= __put_user(0, name->nodename + __OLD_UTS_LEN);
270 error -= __copy_to_user(&name->release, &utsname()->release,
271 __OLD_UTS_LEN);
272 error -= __put_user(0, name->release + __OLD_UTS_LEN);
273 error -= __copy_to_user(&name->version, &utsname()->version,
274 __OLD_UTS_LEN);
275 error -= __put_user(0, name->version + __OLD_UTS_LEN);
276 error -= __copy_to_user(&name->machine, &utsname()->machine,
277 __OLD_UTS_LEN);
278 error = __put_user(0, name->machine + __OLD_UTS_LEN);
279 error = error ? -EFAULT : 0;
280
281 return error;
282}
283
284SYSCALL_DEFINE1(set_thread_area, unsigned long, addr) 222SYSCALL_DEFINE1(set_thread_area, unsigned long, addr)
285{ 223{
286 struct thread_info *ti = task_thread_info(current); 224 struct thread_info *ti = task_thread_info(current);
@@ -431,94 +369,6 @@ _sys_sysmips(nabi_no_regargs struct pt_regs regs)
431} 369}
432 370
433/* 371/*
434 * sys_ipc() is the de-multiplexer for the SysV IPC calls..
435 *
436 * This is really horribly ugly.
437 */
438SYSCALL_DEFINE6(ipc, unsigned int, call, int, first, int, second,
439 unsigned long, third, void __user *, ptr, long, fifth)
440{
441 int version, ret;
442
443 version = call >> 16; /* hack for backward compatibility */
444 call &= 0xffff;
445
446 switch (call) {
447 case SEMOP:
448 return sys_semtimedop(first, (struct sembuf __user *)ptr,
449 second, NULL);
450 case SEMTIMEDOP:
451 return sys_semtimedop(first, (struct sembuf __user *)ptr,
452 second,
453 (const struct timespec __user *)fifth);
454 case SEMGET:
455 return sys_semget(first, second, third);
456 case SEMCTL: {
457 union semun fourth;
458 if (!ptr)
459 return -EINVAL;
460 if (get_user(fourth.__pad, (void __user *__user *) ptr))
461 return -EFAULT;
462 return sys_semctl(first, second, third, fourth);
463 }
464
465 case MSGSND:
466 return sys_msgsnd(first, (struct msgbuf __user *) ptr,
467 second, third);
468 case MSGRCV:
469 switch (version) {
470 case 0: {
471 struct ipc_kludge tmp;
472 if (!ptr)
473 return -EINVAL;
474
475 if (copy_from_user(&tmp,
476 (struct ipc_kludge __user *) ptr,
477 sizeof(tmp)))
478 return -EFAULT;
479 return sys_msgrcv(first, tmp.msgp, second,
480 tmp.msgtyp, third);
481 }
482 default:
483 return sys_msgrcv(first,
484 (struct msgbuf __user *) ptr,
485 second, fifth, third);
486 }
487 case MSGGET:
488 return sys_msgget((key_t) first, second);
489 case MSGCTL:
490 return sys_msgctl(first, second,
491 (struct msqid_ds __user *) ptr);
492
493 case SHMAT:
494 switch (version) {
495 default: {
496 unsigned long raddr;
497 ret = do_shmat(first, (char __user *) ptr, second,
498 &raddr);
499 if (ret)
500 return ret;
501 return put_user(raddr, (unsigned long __user *) third);
502 }
503 case 1: /* iBCS2 emulator entry point */
504 if (!segment_eq(get_fs(), get_ds()))
505 return -EINVAL;
506 return do_shmat(first, (char __user *) ptr, second,
507 (unsigned long *) third);
508 }
509 case SHMDT:
510 return sys_shmdt((char __user *)ptr);
511 case SHMGET:
512 return sys_shmget(first, second, third);
513 case SHMCTL:
514 return sys_shmctl(first, second,
515 (struct shmid_ds __user *) ptr);
516 default:
517 return -ENOSYS;
518 }
519}
520
521/*
522 * No implemented yet ... 372 * No implemented yet ...
523 */ 373 */
524SYSCALL_DEFINE3(cachectl, char *, addr, int, nbytes, int, op) 374SYSCALL_DEFINE3(cachectl, char *, addr, int, nbytes, int, op)
diff --git a/arch/mips/kernel/time.c b/arch/mips/kernel/time.c
index 1f467d534642..fb7497405510 100644
--- a/arch/mips/kernel/time.c
+++ b/arch/mips/kernel/time.c
@@ -71,39 +71,6 @@ EXPORT_SYMBOL(perf_irq);
71 71
72unsigned int mips_hpt_frequency; 72unsigned int mips_hpt_frequency;
73 73
74void __init clocksource_set_clock(struct clocksource *cs, unsigned int clock)
75{
76 u64 temp;
77 u32 shift;
78
79 /* Find a shift value */
80 for (shift = 32; shift > 0; shift--) {
81 temp = (u64) NSEC_PER_SEC << shift;
82 do_div(temp, clock);
83 if ((temp >> 32) == 0)
84 break;
85 }
86 cs->shift = shift;
87 cs->mult = (u32) temp;
88}
89
90void __cpuinit clockevent_set_clock(struct clock_event_device *cd,
91 unsigned int clock)
92{
93 u64 temp;
94 u32 shift;
95
96 /* Find a shift value */
97 for (shift = 32; shift > 0; shift--) {
98 temp = (u64) clock << shift;
99 do_div(temp, NSEC_PER_SEC);
100 if ((temp >> 32) == 0)
101 break;
102 }
103 cd->shift = shift;
104 cd->mult = (u32) temp;
105}
106
107/* 74/*
108 * This function exists in order to cause an error due to a duplicate 75 * This function exists in order to cause an error due to a duplicate
109 * definition if platform code should have its own implementation. The hook 76 * definition if platform code should have its own implementation. The hook
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
index 0a18b4c62afb..d612c6dcb746 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -25,10 +25,12 @@
25#include <linux/ptrace.h> 25#include <linux/ptrace.h>
26#include <linux/kgdb.h> 26#include <linux/kgdb.h>
27#include <linux/kdebug.h> 27#include <linux/kdebug.h>
28#include <linux/notifier.h>
28 29
29#include <asm/bootinfo.h> 30#include <asm/bootinfo.h>
30#include <asm/branch.h> 31#include <asm/branch.h>
31#include <asm/break.h> 32#include <asm/break.h>
33#include <asm/cop2.h>
32#include <asm/cpu.h> 34#include <asm/cpu.h>
33#include <asm/dsp.h> 35#include <asm/dsp.h>
34#include <asm/fpu.h> 36#include <asm/fpu.h>
@@ -48,6 +50,7 @@
48#include <asm/types.h> 50#include <asm/types.h>
49#include <asm/stacktrace.h> 51#include <asm/stacktrace.h>
50#include <asm/irq.h> 52#include <asm/irq.h>
53#include <asm/uasm.h>
51 54
52extern void check_wait(void); 55extern void check_wait(void);
53extern asmlinkage void r4k_wait(void); 56extern asmlinkage void r4k_wait(void);
@@ -79,10 +82,6 @@ extern asmlinkage void handle_reserved(void);
79extern int fpu_emulator_cop1Handler(struct pt_regs *xcp, 82extern int fpu_emulator_cop1Handler(struct pt_regs *xcp,
80 struct mips_fpu_struct *ctx, int has_fpu); 83 struct mips_fpu_struct *ctx, int has_fpu);
81 84
82#ifdef CONFIG_CPU_CAVIUM_OCTEON
83extern asmlinkage void octeon_cop2_restore(struct octeon_cop2_state *task);
84#endif
85
86void (*board_be_init)(void); 85void (*board_be_init)(void);
87int (*board_be_handler)(struct pt_regs *regs, int is_fixup); 86int (*board_be_handler)(struct pt_regs *regs, int is_fixup);
88void (*board_nmi_handler_setup)(void); 87void (*board_nmi_handler_setup)(void);
@@ -353,9 +352,10 @@ void show_registers(const struct pt_regs *regs)
353 352
354static DEFINE_SPINLOCK(die_lock); 353static DEFINE_SPINLOCK(die_lock);
355 354
356void __noreturn die(const char * str, const struct pt_regs * regs) 355void __noreturn die(const char * str, struct pt_regs * regs)
357{ 356{
358 static int die_counter; 357 static int die_counter;
358 int sig = SIGSEGV;
359#ifdef CONFIG_MIPS_MT_SMTC 359#ifdef CONFIG_MIPS_MT_SMTC
360 unsigned long dvpret = dvpe(); 360 unsigned long dvpret = dvpe();
361#endif /* CONFIG_MIPS_MT_SMTC */ 361#endif /* CONFIG_MIPS_MT_SMTC */
@@ -366,6 +366,10 @@ void __noreturn die(const char * str, const struct pt_regs * regs)
366#ifdef CONFIG_MIPS_MT_SMTC 366#ifdef CONFIG_MIPS_MT_SMTC
367 mips_mt_regdump(dvpret); 367 mips_mt_regdump(dvpret);
368#endif /* CONFIG_MIPS_MT_SMTC */ 368#endif /* CONFIG_MIPS_MT_SMTC */
369
370 if (notify_die(DIE_OOPS, str, regs, 0, current->thread.trap_no, SIGSEGV) == NOTIFY_STOP)
371 sig = 0;
372
369 printk("%s[#%d]:\n", str, ++die_counter); 373 printk("%s[#%d]:\n", str, ++die_counter);
370 show_registers(regs); 374 show_registers(regs);
371 add_taint(TAINT_DIE); 375 add_taint(TAINT_DIE);
@@ -380,7 +384,7 @@ void __noreturn die(const char * str, const struct pt_regs * regs)
380 panic("Fatal exception"); 384 panic("Fatal exception");
381 } 385 }
382 386
383 do_exit(SIGSEGV); 387 do_exit(sig);
384} 388}
385 389
386extern struct exception_table_entry __start___dbe_table[]; 390extern struct exception_table_entry __start___dbe_table[];
@@ -857,6 +861,44 @@ static void mt_ase_fp_affinity(void)
857#endif /* CONFIG_MIPS_MT_FPAFF */ 861#endif /* CONFIG_MIPS_MT_FPAFF */
858} 862}
859 863
864/*
865 * No lock; only written during early bootup by CPU 0.
866 */
867static RAW_NOTIFIER_HEAD(cu2_chain);
868
869int __ref register_cu2_notifier(struct notifier_block *nb)
870{
871 return raw_notifier_chain_register(&cu2_chain, nb);
872}
873
874int cu2_notifier_call_chain(unsigned long val, void *v)
875{
876 return raw_notifier_call_chain(&cu2_chain, val, v);
877}
878
879static int default_cu2_call(struct notifier_block *nfb, unsigned long action,
880 void *data)
881{
882 struct pt_regs *regs = data;
883
884 switch (action) {
885 default:
886 die_if_kernel("Unhandled kernel unaligned access or invalid "
887 "instruction", regs);
888 /* Fall through */
889
890 case CU2_EXCEPTION:
891 force_sig(SIGILL, current);
892 }
893
894 return NOTIFY_OK;
895}
896
897static struct notifier_block default_cu2_notifier = {
898 .notifier_call = default_cu2_call,
899 .priority = 0x80000000, /* Run last */
900};
901
860asmlinkage void do_cpu(struct pt_regs *regs) 902asmlinkage void do_cpu(struct pt_regs *regs)
861{ 903{
862 unsigned int __user *epc; 904 unsigned int __user *epc;
@@ -920,17 +962,9 @@ asmlinkage void do_cpu(struct pt_regs *regs)
920 return; 962 return;
921 963
922 case 2: 964 case 2:
923#ifdef CONFIG_CPU_CAVIUM_OCTEON 965 raw_notifier_call_chain(&cu2_chain, CU2_EXCEPTION, regs);
924 prefetch(&current->thread.cp2); 966 break;
925 local_irq_save(flags); 967
926 KSTK_STATUS(current) |= ST0_CU2;
927 status = read_c0_status();
928 write_c0_status(status | ST0_CU2);
929 octeon_cop2_restore(&(current->thread.cp2));
930 write_c0_status(status & ~ST0_CU2);
931 local_irq_restore(flags);
932 return;
933#endif
934 case 3: 968 case 3:
935 break; 969 break;
936 } 970 }
@@ -1243,21 +1277,25 @@ unsigned long ebase;
1243unsigned long exception_handlers[32]; 1277unsigned long exception_handlers[32];
1244unsigned long vi_handlers[64]; 1278unsigned long vi_handlers[64];
1245 1279
1246/* 1280void __init *set_except_vector(int n, void *addr)
1247 * As a side effect of the way this is implemented we're limited
1248 * to interrupt handlers in the address range from
1249 * KSEG0 <= x < KSEG0 + 256mb on the Nevada. Oh well ...
1250 */
1251void *set_except_vector(int n, void *addr)
1252{ 1281{
1253 unsigned long handler = (unsigned long) addr; 1282 unsigned long handler = (unsigned long) addr;
1254 unsigned long old_handler = exception_handlers[n]; 1283 unsigned long old_handler = exception_handlers[n];
1255 1284
1256 exception_handlers[n] = handler; 1285 exception_handlers[n] = handler;
1257 if (n == 0 && cpu_has_divec) { 1286 if (n == 0 && cpu_has_divec) {
1258 *(u32 *)(ebase + 0x200) = 0x08000000 | 1287 unsigned long jump_mask = ~((1 << 28) - 1);
1259 (0x03ffffff & (handler >> 2)); 1288 u32 *buf = (u32 *)(ebase + 0x200);
1260 local_flush_icache_range(ebase + 0x200, ebase + 0x204); 1289 unsigned int k0 = 26;
1290 if ((handler & jump_mask) == ((ebase + 0x200) & jump_mask)) {
1291 uasm_i_j(&buf, handler & ~jump_mask);
1292 uasm_i_nop(&buf);
1293 } else {
1294 UASM_i_LA(&buf, k0, handler);
1295 uasm_i_jr(&buf, k0);
1296 uasm_i_nop(&buf);
1297 }
1298 local_flush_icache_range(ebase + 0x200, (unsigned long)buf);
1261 } 1299 }
1262 return (void *)old_handler; 1300 return (void *)old_handler;
1263} 1301}
@@ -1367,77 +1405,6 @@ void *set_vi_handler(int n, vi_handler_t addr)
1367 return set_vi_srs_handler(n, addr, 0); 1405 return set_vi_srs_handler(n, addr, 0);
1368} 1406}
1369 1407
1370/*
1371 * This is used by native signal handling
1372 */
1373asmlinkage int (*save_fp_context)(struct sigcontext __user *sc);
1374asmlinkage int (*restore_fp_context)(struct sigcontext __user *sc);
1375
1376extern asmlinkage int _save_fp_context(struct sigcontext __user *sc);
1377extern asmlinkage int _restore_fp_context(struct sigcontext __user *sc);
1378
1379extern asmlinkage int fpu_emulator_save_context(struct sigcontext __user *sc);
1380extern asmlinkage int fpu_emulator_restore_context(struct sigcontext __user *sc);
1381
1382#ifdef CONFIG_SMP
1383static int smp_save_fp_context(struct sigcontext __user *sc)
1384{
1385 return raw_cpu_has_fpu
1386 ? _save_fp_context(sc)
1387 : fpu_emulator_save_context(sc);
1388}
1389
1390static int smp_restore_fp_context(struct sigcontext __user *sc)
1391{
1392 return raw_cpu_has_fpu
1393 ? _restore_fp_context(sc)
1394 : fpu_emulator_restore_context(sc);
1395}
1396#endif
1397
1398static inline void signal_init(void)
1399{
1400#ifdef CONFIG_SMP
1401 /* For now just do the cpu_has_fpu check when the functions are invoked */
1402 save_fp_context = smp_save_fp_context;
1403 restore_fp_context = smp_restore_fp_context;
1404#else
1405 if (cpu_has_fpu) {
1406 save_fp_context = _save_fp_context;
1407 restore_fp_context = _restore_fp_context;
1408 } else {
1409 save_fp_context = fpu_emulator_save_context;
1410 restore_fp_context = fpu_emulator_restore_context;
1411 }
1412#endif
1413}
1414
1415#ifdef CONFIG_MIPS32_COMPAT
1416
1417/*
1418 * This is used by 32-bit signal stuff on the 64-bit kernel
1419 */
1420asmlinkage int (*save_fp_context32)(struct sigcontext32 __user *sc);
1421asmlinkage int (*restore_fp_context32)(struct sigcontext32 __user *sc);
1422
1423extern asmlinkage int _save_fp_context32(struct sigcontext32 __user *sc);
1424extern asmlinkage int _restore_fp_context32(struct sigcontext32 __user *sc);
1425
1426extern asmlinkage int fpu_emulator_save_context32(struct sigcontext32 __user *sc);
1427extern asmlinkage int fpu_emulator_restore_context32(struct sigcontext32 __user *sc);
1428
1429static inline void signal32_init(void)
1430{
1431 if (cpu_has_fpu) {
1432 save_fp_context32 = _save_fp_context32;
1433 restore_fp_context32 = _restore_fp_context32;
1434 } else {
1435 save_fp_context32 = fpu_emulator_save_context32;
1436 restore_fp_context32 = fpu_emulator_restore_context32;
1437 }
1438}
1439#endif
1440
1441extern void cpu_cache_init(void); 1408extern void cpu_cache_init(void);
1442extern void tlb_init(void); 1409extern void tlb_init(void);
1443extern void flush_tlb_handlers(void); 1410extern void flush_tlb_handlers(void);
@@ -1446,6 +1413,7 @@ extern void flush_tlb_handlers(void);
1446 * Timer interrupt 1413 * Timer interrupt
1447 */ 1414 */
1448int cp0_compare_irq; 1415int cp0_compare_irq;
1416int cp0_compare_irq_shift;
1449 1417
1450/* 1418/*
1451 * Performance counter IRQ or -1 if shared with timer 1419 * Performance counter IRQ or -1 if shared with timer
@@ -1536,12 +1504,14 @@ void __cpuinit per_cpu_trap_init(void)
1536 * o read IntCtl.IPPCI to determine the performance counter interrupt 1504 * o read IntCtl.IPPCI to determine the performance counter interrupt
1537 */ 1505 */
1538 if (cpu_has_mips_r2) { 1506 if (cpu_has_mips_r2) {
1539 cp0_compare_irq = (read_c0_intctl() >> 29) & 7; 1507 cp0_compare_irq_shift = CAUSEB_TI - CAUSEB_IP;
1540 cp0_perfcount_irq = (read_c0_intctl() >> 26) & 7; 1508 cp0_compare_irq = (read_c0_intctl() >> INTCTLB_IPTI) & 7;
1509 cp0_perfcount_irq = (read_c0_intctl() >> INTCTLB_IPPCI) & 7;
1541 if (cp0_perfcount_irq == cp0_compare_irq) 1510 if (cp0_perfcount_irq == cp0_compare_irq)
1542 cp0_perfcount_irq = -1; 1511 cp0_perfcount_irq = -1;
1543 } else { 1512 } else {
1544 cp0_compare_irq = CP0_LEGACY_COMPARE_IRQ; 1513 cp0_compare_irq = CP0_LEGACY_COMPARE_IRQ;
1514 cp0_compare_irq_shift = cp0_compare_irq;
1545 cp0_perfcount_irq = -1; 1515 cp0_perfcount_irq = -1;
1546 } 1516 }
1547 1517
@@ -1592,12 +1562,7 @@ static char panic_null_cerr[] __cpuinitdata =
1592void __cpuinit set_uncached_handler(unsigned long offset, void *addr, 1562void __cpuinit set_uncached_handler(unsigned long offset, void *addr,
1593 unsigned long size) 1563 unsigned long size)
1594{ 1564{
1595#ifdef CONFIG_32BIT 1565 unsigned long uncached_ebase = CKSEG1ADDR(ebase);
1596 unsigned long uncached_ebase = KSEG1ADDR(ebase);
1597#endif
1598#ifdef CONFIG_64BIT
1599 unsigned long uncached_ebase = TO_UNCAC(ebase);
1600#endif
1601 1566
1602 if (!addr) 1567 if (!addr)
1603 panic(panic_null_cerr); 1568 panic(panic_null_cerr);
@@ -1634,7 +1599,7 @@ void __init trap_init(void)
1634 ebase = (unsigned long) 1599 ebase = (unsigned long)
1635 __alloc_bootmem(size, 1 << fls(size), 0); 1600 __alloc_bootmem(size, 1 << fls(size), 0);
1636 } else { 1601 } else {
1637 ebase = CAC_BASE; 1602 ebase = CKSEG0;
1638 if (cpu_has_mips_r2) 1603 if (cpu_has_mips_r2)
1639 ebase += (read_c0_ebase() & 0x3ffff000); 1604 ebase += (read_c0_ebase() & 0x3ffff000);
1640 } 1605 }
@@ -1751,13 +1716,10 @@ void __init trap_init(void)
1751 else 1716 else
1752 memcpy((void *)(ebase + 0x080), &except_vec3_generic, 0x80); 1717 memcpy((void *)(ebase + 0x080), &except_vec3_generic, 0x80);
1753 1718
1754 signal_init();
1755#ifdef CONFIG_MIPS32_COMPAT
1756 signal32_init();
1757#endif
1758
1759 local_flush_icache_range(ebase, ebase + 0x400); 1719 local_flush_icache_range(ebase, ebase + 0x400);
1760 flush_tlb_handlers(); 1720 flush_tlb_handlers();
1761 1721
1762 sort_extable(__start___dbe_table, __stop___dbe_table); 1722 sort_extable(__start___dbe_table, __stop___dbe_table);
1723
1724 register_cu2_notifier(&default_cu2_notifier);
1763} 1725}
diff --git a/arch/mips/kernel/unaligned.c b/arch/mips/kernel/unaligned.c
index 67bd626942ab..69b039ca8d83 100644
--- a/arch/mips/kernel/unaligned.c
+++ b/arch/mips/kernel/unaligned.c
@@ -81,6 +81,7 @@
81#include <asm/asm.h> 81#include <asm/asm.h>
82#include <asm/branch.h> 82#include <asm/branch.h>
83#include <asm/byteorder.h> 83#include <asm/byteorder.h>
84#include <asm/cop2.h>
84#include <asm/inst.h> 85#include <asm/inst.h>
85#include <asm/uaccess.h> 86#include <asm/uaccess.h>
86#include <asm/system.h> 87#include <asm/system.h>
@@ -451,17 +452,27 @@ static void emulate_load_store_insn(struct pt_regs *regs,
451 */ 452 */
452 goto sigbus; 453 goto sigbus;
453 454
455 /*
456 * COP2 is available to implementor for application specific use.
457 * It's up to applications to register a notifier chain and do
458 * whatever they have to do, including possible sending of signals.
459 */
454 case lwc2_op: 460 case lwc2_op:
461 cu2_notifier_call_chain(CU2_LWC2_OP, regs);
462 break;
463
455 case ldc2_op: 464 case ldc2_op:
465 cu2_notifier_call_chain(CU2_LDC2_OP, regs);
466 break;
467
456 case swc2_op: 468 case swc2_op:
469 cu2_notifier_call_chain(CU2_SWC2_OP, regs);
470 break;
471
457 case sdc2_op: 472 case sdc2_op:
458 /* 473 cu2_notifier_call_chain(CU2_SDC2_OP, regs);
459 * These are the coprocessor 2 load/stores. The current 474 break;
460 * implementations don't use cp2 and cp2 should always be 475
461 * disabled in c0_status. So send SIGILL.
462 * (No longer true: The Sony Praystation uses cp2 for
463 * 3D matrix operations. Dunno if that thingy has a MMU ...)
464 */
465 default: 476 default:
466 /* 477 /*
467 * Pheeee... We encountered an yet unknown instruction or 478 * Pheeee... We encountered an yet unknown instruction or
diff --git a/arch/mips/kernel/vdso.c b/arch/mips/kernel/vdso.c
new file mode 100644
index 000000000000..b773c1112b14
--- /dev/null
+++ b/arch/mips/kernel/vdso.c
@@ -0,0 +1,112 @@
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) 2009, 2010 Cavium Networks, Inc.
7 */
8
9
10#include <linux/kernel.h>
11#include <linux/err.h>
12#include <linux/sched.h>
13#include <linux/mm.h>
14#include <linux/init.h>
15#include <linux/binfmts.h>
16#include <linux/elf.h>
17#include <linux/vmalloc.h>
18#include <linux/unistd.h>
19
20#include <asm/vdso.h>
21#include <asm/uasm.h>
22
23/*
24 * Including <asm/unistd.h> would give use the 64-bit syscall numbers ...
25 */
26#define __NR_O32_sigreturn 4119
27#define __NR_O32_rt_sigreturn 4193
28#define __NR_N32_rt_sigreturn 6211
29
30static struct page *vdso_page;
31
32static void __init install_trampoline(u32 *tramp, unsigned int sigreturn)
33{
34 uasm_i_addiu(&tramp, 2, 0, sigreturn); /* li v0, sigreturn */
35 uasm_i_syscall(&tramp, 0);
36}
37
38static int __init init_vdso(void)
39{
40 struct mips_vdso *vdso;
41
42 vdso_page = alloc_page(GFP_KERNEL);
43 if (!vdso_page)
44 panic("Cannot allocate vdso");
45
46 vdso = vmap(&vdso_page, 1, 0, PAGE_KERNEL);
47 if (!vdso)
48 panic("Cannot map vdso");
49 clear_page(vdso);
50
51 install_trampoline(vdso->rt_signal_trampoline, __NR_rt_sigreturn);
52#ifdef CONFIG_32BIT
53 install_trampoline(vdso->signal_trampoline, __NR_sigreturn);
54#else
55 install_trampoline(vdso->n32_rt_signal_trampoline,
56 __NR_N32_rt_sigreturn);
57 install_trampoline(vdso->o32_signal_trampoline, __NR_O32_sigreturn);
58 install_trampoline(vdso->o32_rt_signal_trampoline,
59 __NR_O32_rt_sigreturn);
60#endif
61
62 vunmap(vdso);
63
64 pr_notice("init_vdso successfull\n");
65
66 return 0;
67}
68device_initcall(init_vdso);
69
70static unsigned long vdso_addr(unsigned long start)
71{
72 return STACK_TOP;
73}
74
75int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
76{
77 int ret;
78 unsigned long addr;
79 struct mm_struct *mm = current->mm;
80
81 down_write(&mm->mmap_sem);
82
83 addr = vdso_addr(mm->start_stack);
84
85 addr = get_unmapped_area(NULL, addr, PAGE_SIZE, 0, 0);
86 if (IS_ERR_VALUE(addr)) {
87 ret = addr;
88 goto up_fail;
89 }
90
91 ret = install_special_mapping(mm, addr, PAGE_SIZE,
92 VM_READ|VM_EXEC|
93 VM_MAYREAD|VM_MAYWRITE|VM_MAYEXEC|
94 VM_ALWAYSDUMP,
95 &vdso_page);
96
97 if (ret)
98 goto up_fail;
99
100 mm->context.vdso = (void *)addr;
101
102up_fail:
103 up_write(&mm->mmap_sem);
104 return ret;
105}
106
107const char *arch_vma_name(struct vm_area_struct *vma)
108{
109 if (vma->vm_mm && vma->vm_start == (long)vma->vm_mm->context.vdso)
110 return "[vdso]";
111 return NULL;
112}
diff --git a/arch/mips/kernel/vmlinux.lds.S b/arch/mips/kernel/vmlinux.lds.S
index 162b29954baa..f25df73db923 100644
--- a/arch/mips/kernel/vmlinux.lds.S
+++ b/arch/mips/kernel/vmlinux.lds.S
@@ -46,6 +46,7 @@ SECTIONS
46 SCHED_TEXT 46 SCHED_TEXT
47 LOCK_TEXT 47 LOCK_TEXT
48 KPROBES_TEXT 48 KPROBES_TEXT
49 IRQENTRY_TEXT
49 *(.text.*) 50 *(.text.*)
50 *(.fixup) 51 *(.fixup)
51 *(.gnu.warning) 52 *(.gnu.warning)
diff --git a/arch/mips/kernel/vpe.c b/arch/mips/kernel/vpe.c
index 60477529362e..2bd2151c586a 100644
--- a/arch/mips/kernel/vpe.c
+++ b/arch/mips/kernel/vpe.c
@@ -38,7 +38,6 @@
38#include <linux/vmalloc.h> 38#include <linux/vmalloc.h>
39#include <linux/elf.h> 39#include <linux/elf.h>
40#include <linux/seq_file.h> 40#include <linux/seq_file.h>
41#include <linux/smp_lock.h>
42#include <linux/syscalls.h> 41#include <linux/syscalls.h>
43#include <linux/moduleloader.h> 42#include <linux/moduleloader.h>
44#include <linux/interrupt.h> 43#include <linux/interrupt.h>