diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2016-08-06 09:13:11 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-08-06 09:13:11 -0400 |
commit | 4305f42401b29e2e024bd064618faf25aef5cb69 (patch) | |
tree | 1bc924cfa60c9efbb21e07c1d834f495301cffc8 /arch/mips/kernel | |
parent | db8262787e82b5c0fa57bd9d676add187519a751 (diff) | |
parent | 4a89cf810130fde41e3fc729e770cb1a5a87d245 (diff) |
Merge branch 'upstream' of git://git.linux-mips.org/pub/scm/ralf/upstream-linus
Pull MIPS updates from Ralf Baechle:
"This is the main pull request for MIPS for 4.8. Also includes is a
minor SSB cleanup as SSB code traditionally is merged through the MIPS
tree:
ATH25:
- MIPS: Add default configuration for ath25
Boot:
- For zboot, copy appended dtb to the end of the kernel
- store the appended dtb address in a variable
BPF:
- Fix off by one error in offset allocation
Cobalt code:
- Fix typos
Core code:
- debugfs_create_file returns NULL on error, so don't use IS_ERR for
testing for errors.
- Fix double locking issue in RM7000 S-cache code. This would only
affect RM7000 ARC systems on reboot.
- Fix page table corruption on THP permission changes.
- Use compat_sys_keyctl for 32 bit userspace on 64 bit kernels.
David says, there are no compatibility issues raised by this fix.
- Move some signal code around.
- Rewrite r4k count/compare clockevent device registration such that
min_delta_ticks/max_delta_ticks files are guaranteed to be
initialized.
- Only register r4k count/compare as clockevent device if we can
assume the clock to be constant.
- Fix MSA asm warnings in control reg accessors
- uasm and tlbex fixes and tweaking.
- Print segment physical address when EU=1.
- Define AT_VECTOR_SIZE_ARCH for ARCH_DLINFO.
- CP: Allow booting by VP other than VP 0
- Cache handling fixes and optimizations for r4k class caches
- Add hotplug support for R6 processors
- Cleanup hotplug bits in kconfig
- traps: return correct si code for accessing nonmapped addresses
- Remove cpu_has_safe_index_cacheops
Lantiq:
- Register IRQ handler for virtual IRQ number
- Fix EIU interrupt loading code
- Use the real EXIN count
- Fix build error.
Loongson 3:
- Increase HPET_MIN_PROG_DELTA and decrease HPET_MIN_CYCLES
Octeon:
- Delete built-in DTB pruning code for D-Link DSR-1000N.
- Clean up GPIO definitions in dlink_dsr-1000n.dts.
- Add more LEDs to the DSR-100n DTS
- Fix off by one in octeon_irq_gpio_map()
- Typo fixes
- Enable SATA by default in cavium_octeon_defconfig
- Support readq/writeq()
- Remove forced mappings of USB interrupts.
- Ensure DMA descriptors are always in the low 4GB
- Improve USB reset code for OCTEON II.
Pistachio:
- Add maintainers entry for pistachio SoC Support
- Remove plat_setup_iocoherency
Ralink:
- Fix pwm UART in spis group pinmux.
SSB:
- Change bare unsigned to unsigned int to suit coding style
Tools:
- Fix reloc tool compiler warnings.
Other:
- Delete use of ARCH_WANT_OPTIONAL_GPIOLIB"
* 'upstream' of git://git.linux-mips.org/pub/scm/ralf/upstream-linus: (61 commits)
MIPS: mm: Fix definition of R6 cache instruction
MIPS: tools: Fix relocs tool compiler warnings
MIPS: Cobalt: Fix typo
MIPS: Octeon: Fix typo
MIPS: Lantiq: Fix build failure
MIPS: Use CPHYSADDR to implement mips32 __pa
MIPS: Octeon: Dlink_dsr-1000n.dts: add more leds.
MIPS: Octeon: Clean up GPIO definitions in dlink_dsr-1000n.dts.
MIPS: Octeon: Delete built-in DTB pruning code for D-Link DSR-1000N.
MIPS: store the appended dtb address in a variable
MIPS: ZBOOT: copy appended dtb to the end of the kernel
MIPS: ralink: fix spis group pinmux
MIPS: Factor o32 specific code into signal_o32.c
MIPS: non-exec stack & heap when non-exec PT_GNU_STACK is present
MIPS: Use per-mm page to execute branch delay slot instructions
MIPS: Modify error handling
MIPS: c-r4k: Use SMP calls for CM indexed cache ops
MIPS: c-r4k: Avoid small flush_icache_range SMP calls
MIPS: c-r4k: Local flush_icache_range cache op override
MIPS: c-r4k: Split r4k_flush_kernel_vmap_range()
...
Diffstat (limited to 'arch/mips/kernel')
-rw-r--r-- | arch/mips/kernel/Makefile | 2 | ||||
-rw-r--r-- | arch/mips/kernel/cevt-r4k.c | 7 | ||||
-rw-r--r-- | arch/mips/kernel/csrc-r4k.c | 4 | ||||
-rw-r--r-- | arch/mips/kernel/elf.c | 19 | ||||
-rw-r--r-- | arch/mips/kernel/head.S | 21 | ||||
-rw-r--r-- | arch/mips/kernel/mips-r2-to-r6-emul.c | 8 | ||||
-rw-r--r-- | arch/mips/kernel/process.c | 14 | ||||
-rw-r--r-- | arch/mips/kernel/scall64-n32.S | 2 | ||||
-rw-r--r-- | arch/mips/kernel/scall64-o32.S | 2 | ||||
-rw-r--r-- | arch/mips/kernel/segment.c | 13 | ||||
-rw-r--r-- | arch/mips/kernel/setup.c | 4 | ||||
-rw-r--r-- | arch/mips/kernel/signal.c | 8 | ||||
-rw-r--r-- | arch/mips/kernel/signal32.c | 288 | ||||
-rw-r--r-- | arch/mips/kernel/signal_o32.c | 285 | ||||
-rw-r--r-- | arch/mips/kernel/smp-bmips.c | 1 | ||||
-rw-r--r-- | arch/mips/kernel/smp-cps.c | 42 | ||||
-rw-r--r-- | arch/mips/kernel/smp.c | 34 | ||||
-rw-r--r-- | arch/mips/kernel/traps.c | 4 | ||||
-rw-r--r-- | arch/mips/kernel/vdso.c | 10 |
19 files changed, 437 insertions, 331 deletions
diff --git a/arch/mips/kernel/Makefile b/arch/mips/kernel/Makefile index e6053d07072f..4a603a3ea657 100644 --- a/arch/mips/kernel/Makefile +++ b/arch/mips/kernel/Makefile | |||
@@ -71,7 +71,7 @@ obj-$(CONFIG_32BIT) += scall32-o32.o | |||
71 | obj-$(CONFIG_64BIT) += scall64-64.o | 71 | obj-$(CONFIG_64BIT) += scall64-64.o |
72 | obj-$(CONFIG_MIPS32_COMPAT) += linux32.o ptrace32.o signal32.o | 72 | obj-$(CONFIG_MIPS32_COMPAT) += linux32.o ptrace32.o signal32.o |
73 | obj-$(CONFIG_MIPS32_N32) += binfmt_elfn32.o scall64-n32.o signal_n32.o | 73 | obj-$(CONFIG_MIPS32_N32) += binfmt_elfn32.o scall64-n32.o signal_n32.o |
74 | obj-$(CONFIG_MIPS32_O32) += binfmt_elfo32.o scall64-o32.o | 74 | obj-$(CONFIG_MIPS32_O32) += binfmt_elfo32.o scall64-o32.o signal_o32.o |
75 | 75 | ||
76 | obj-$(CONFIG_KGDB) += kgdb.o | 76 | obj-$(CONFIG_KGDB) += kgdb.o |
77 | obj-$(CONFIG_PROC_FS) += proc.o | 77 | obj-$(CONFIG_PROC_FS) += proc.o |
diff --git a/arch/mips/kernel/cevt-r4k.c b/arch/mips/kernel/cevt-r4k.c index e4c21bbf9422..804d2a2a19fe 100644 --- a/arch/mips/kernel/cevt-r4k.c +++ b/arch/mips/kernel/cevt-r4k.c | |||
@@ -276,12 +276,7 @@ int r4k_clockevent_init(void) | |||
276 | CLOCK_EVT_FEAT_C3STOP | | 276 | CLOCK_EVT_FEAT_C3STOP | |
277 | CLOCK_EVT_FEAT_PERCPU; | 277 | CLOCK_EVT_FEAT_PERCPU; |
278 | 278 | ||
279 | clockevent_set_clock(cd, mips_hpt_frequency); | ||
280 | |||
281 | /* Calculate the min / max delta */ | ||
282 | cd->max_delta_ns = clockevent_delta2ns(0x7fffffff, cd); | ||
283 | min_delta = calculate_min_delta(); | 279 | min_delta = calculate_min_delta(); |
284 | cd->min_delta_ns = clockevent_delta2ns(min_delta, cd); | ||
285 | 280 | ||
286 | cd->rating = 300; | 281 | cd->rating = 300; |
287 | cd->irq = irq; | 282 | cd->irq = irq; |
@@ -289,7 +284,7 @@ int r4k_clockevent_init(void) | |||
289 | cd->set_next_event = mips_next_event; | 284 | cd->set_next_event = mips_next_event; |
290 | cd->event_handler = mips_event_handler; | 285 | cd->event_handler = mips_event_handler; |
291 | 286 | ||
292 | clockevents_register_device(cd); | 287 | clockevents_config_and_register(cd, mips_hpt_frequency, min_delta, 0x7fffffff); |
293 | 288 | ||
294 | if (cp0_timer_irq_installed) | 289 | if (cp0_timer_irq_installed) |
295 | return 0; | 290 | return 0; |
diff --git a/arch/mips/kernel/csrc-r4k.c b/arch/mips/kernel/csrc-r4k.c index 1f910563fdf6..d76275da54cb 100644 --- a/arch/mips/kernel/csrc-r4k.c +++ b/arch/mips/kernel/csrc-r4k.c | |||
@@ -23,7 +23,7 @@ static struct clocksource clocksource_mips = { | |||
23 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, | 23 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, |
24 | }; | 24 | }; |
25 | 25 | ||
26 | static u64 notrace r4k_read_sched_clock(void) | 26 | static u64 __maybe_unused notrace r4k_read_sched_clock(void) |
27 | { | 27 | { |
28 | return read_c0_count(); | 28 | return read_c0_count(); |
29 | } | 29 | } |
@@ -82,7 +82,9 @@ int __init init_r4k_clocksource(void) | |||
82 | 82 | ||
83 | clocksource_register_hz(&clocksource_mips, mips_hpt_frequency); | 83 | clocksource_register_hz(&clocksource_mips, mips_hpt_frequency); |
84 | 84 | ||
85 | #ifndef CONFIG_CPU_FREQ | ||
85 | sched_clock_register(r4k_read_sched_clock, 32, mips_hpt_frequency); | 86 | sched_clock_register(r4k_read_sched_clock, 32, mips_hpt_frequency); |
87 | #endif | ||
86 | 88 | ||
87 | return 0; | 89 | return 0; |
88 | } | 90 | } |
diff --git a/arch/mips/kernel/elf.c b/arch/mips/kernel/elf.c index e6eb7f1f7723..6430bff21fff 100644 --- a/arch/mips/kernel/elf.c +++ b/arch/mips/kernel/elf.c | |||
@@ -8,9 +8,12 @@ | |||
8 | * option) any later version. | 8 | * option) any later version. |
9 | */ | 9 | */ |
10 | 10 | ||
11 | #include <linux/binfmts.h> | ||
11 | #include <linux/elf.h> | 12 | #include <linux/elf.h> |
13 | #include <linux/export.h> | ||
12 | #include <linux/sched.h> | 14 | #include <linux/sched.h> |
13 | 15 | ||
16 | #include <asm/cpu-features.h> | ||
14 | #include <asm/cpu-info.h> | 17 | #include <asm/cpu-info.h> |
15 | 18 | ||
16 | /* Whether to accept legacy-NaN and 2008-NaN user binaries. */ | 19 | /* Whether to accept legacy-NaN and 2008-NaN user binaries. */ |
@@ -326,3 +329,19 @@ void mips_set_personality_nan(struct arch_elf_state *state) | |||
326 | BUG(); | 329 | BUG(); |
327 | } | 330 | } |
328 | } | 331 | } |
332 | |||
333 | int mips_elf_read_implies_exec(void *elf_ex, int exstack) | ||
334 | { | ||
335 | if (exstack != EXSTACK_DISABLE_X) { | ||
336 | /* The binary doesn't request a non-executable stack */ | ||
337 | return 1; | ||
338 | } | ||
339 | |||
340 | if (!cpu_has_rixi) { | ||
341 | /* The CPU doesn't support non-executable memory */ | ||
342 | return 1; | ||
343 | } | ||
344 | |||
345 | return 0; | ||
346 | } | ||
347 | EXPORT_SYMBOL(mips_elf_read_implies_exec); | ||
diff --git a/arch/mips/kernel/head.S b/arch/mips/kernel/head.S index 56e8fede3fd8..cf052204eb0a 100644 --- a/arch/mips/kernel/head.S +++ b/arch/mips/kernel/head.S | |||
@@ -93,21 +93,24 @@ NESTED(kernel_entry, 16, sp) # kernel entry point | |||
93 | jr t0 | 93 | jr t0 |
94 | 0: | 94 | 0: |
95 | 95 | ||
96 | #ifdef CONFIG_USE_OF | ||
96 | #ifdef CONFIG_MIPS_RAW_APPENDED_DTB | 97 | #ifdef CONFIG_MIPS_RAW_APPENDED_DTB |
97 | PTR_LA t0, __appended_dtb | 98 | PTR_LA t2, __appended_dtb |
98 | 99 | ||
99 | #ifdef CONFIG_CPU_BIG_ENDIAN | 100 | #ifdef CONFIG_CPU_BIG_ENDIAN |
100 | li t1, 0xd00dfeed | 101 | li t1, 0xd00dfeed |
101 | #else | 102 | #else |
102 | li t1, 0xedfe0dd0 | 103 | li t1, 0xedfe0dd0 |
103 | #endif | 104 | #endif |
104 | lw t2, (t0) | 105 | lw t0, (t2) |
105 | bne t1, t2, not_found | 106 | beq t0, t1, dtb_found |
106 | nop | 107 | #endif |
108 | li t1, -2 | ||
109 | beq a0, t1, dtb_found | ||
110 | move t2, a1 | ||
107 | 111 | ||
108 | move a1, t0 | 112 | li t2, 0 |
109 | PTR_LI a0, -2 | 113 | dtb_found: |
110 | not_found: | ||
111 | #endif | 114 | #endif |
112 | PTR_LA t0, __bss_start # clear .bss | 115 | PTR_LA t0, __bss_start # clear .bss |
113 | LONG_S zero, (t0) | 116 | LONG_S zero, (t0) |
@@ -122,6 +125,10 @@ not_found: | |||
122 | LONG_S a2, fw_arg2 | 125 | LONG_S a2, fw_arg2 |
123 | LONG_S a3, fw_arg3 | 126 | LONG_S a3, fw_arg3 |
124 | 127 | ||
128 | #ifdef CONFIG_USE_OF | ||
129 | LONG_S t2, fw_passed_dtb | ||
130 | #endif | ||
131 | |||
125 | MTC0 zero, CP0_CONTEXT # clear context register | 132 | MTC0 zero, CP0_CONTEXT # clear context register |
126 | PTR_LA $28, init_thread_union | 133 | PTR_LA $28, init_thread_union |
127 | /* Set the SP after an empty pt_regs. */ | 134 | /* Set the SP after an empty pt_regs. */ |
diff --git a/arch/mips/kernel/mips-r2-to-r6-emul.c b/arch/mips/kernel/mips-r2-to-r6-emul.c index 43fbadc78d0a..c3372cac6db2 100644 --- a/arch/mips/kernel/mips-r2-to-r6-emul.c +++ b/arch/mips/kernel/mips-r2-to-r6-emul.c | |||
@@ -283,7 +283,7 @@ static int jr_func(struct pt_regs *regs, u32 ir) | |||
283 | err = mipsr6_emul(regs, nir); | 283 | err = mipsr6_emul(regs, nir); |
284 | if (err > 0) { | 284 | if (err > 0) { |
285 | regs->cp0_epc = nepc; | 285 | regs->cp0_epc = nepc; |
286 | err = mips_dsemul(regs, nir, cepc); | 286 | err = mips_dsemul(regs, nir, epc, cepc); |
287 | if (err == SIGILL) | 287 | if (err == SIGILL) |
288 | err = SIGEMT; | 288 | err = SIGEMT; |
289 | MIPS_R2_STATS(dsemul); | 289 | MIPS_R2_STATS(dsemul); |
@@ -1033,7 +1033,7 @@ repeat: | |||
1033 | if (nir) { | 1033 | if (nir) { |
1034 | err = mipsr6_emul(regs, nir); | 1034 | err = mipsr6_emul(regs, nir); |
1035 | if (err > 0) { | 1035 | if (err > 0) { |
1036 | err = mips_dsemul(regs, nir, cpc); | 1036 | err = mips_dsemul(regs, nir, epc, cpc); |
1037 | if (err == SIGILL) | 1037 | if (err == SIGILL) |
1038 | err = SIGEMT; | 1038 | err = SIGEMT; |
1039 | MIPS_R2_STATS(dsemul); | 1039 | MIPS_R2_STATS(dsemul); |
@@ -1082,7 +1082,7 @@ repeat: | |||
1082 | if (nir) { | 1082 | if (nir) { |
1083 | err = mipsr6_emul(regs, nir); | 1083 | err = mipsr6_emul(regs, nir); |
1084 | if (err > 0) { | 1084 | if (err > 0) { |
1085 | err = mips_dsemul(regs, nir, cpc); | 1085 | err = mips_dsemul(regs, nir, epc, cpc); |
1086 | if (err == SIGILL) | 1086 | if (err == SIGILL) |
1087 | err = SIGEMT; | 1087 | err = SIGEMT; |
1088 | MIPS_R2_STATS(dsemul); | 1088 | MIPS_R2_STATS(dsemul); |
@@ -1149,7 +1149,7 @@ repeat: | |||
1149 | if (nir) { | 1149 | if (nir) { |
1150 | err = mipsr6_emul(regs, nir); | 1150 | err = mipsr6_emul(regs, nir); |
1151 | if (err > 0) { | 1151 | if (err > 0) { |
1152 | err = mips_dsemul(regs, nir, cpc); | 1152 | err = mips_dsemul(regs, nir, epc, cpc); |
1153 | if (err == SIGILL) | 1153 | if (err == SIGILL) |
1154 | err = SIGEMT; | 1154 | err = SIGEMT; |
1155 | MIPS_R2_STATS(dsemul); | 1155 | MIPS_R2_STATS(dsemul); |
diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c index 813ed7829c61..7429ad09fbe3 100644 --- a/arch/mips/kernel/process.c +++ b/arch/mips/kernel/process.c | |||
@@ -30,6 +30,7 @@ | |||
30 | #include <asm/asm.h> | 30 | #include <asm/asm.h> |
31 | #include <asm/bootinfo.h> | 31 | #include <asm/bootinfo.h> |
32 | #include <asm/cpu.h> | 32 | #include <asm/cpu.h> |
33 | #include <asm/dsemul.h> | ||
33 | #include <asm/dsp.h> | 34 | #include <asm/dsp.h> |
34 | #include <asm/fpu.h> | 35 | #include <asm/fpu.h> |
35 | #include <asm/msa.h> | 36 | #include <asm/msa.h> |
@@ -68,11 +69,22 @@ void start_thread(struct pt_regs * regs, unsigned long pc, unsigned long sp) | |||
68 | lose_fpu(0); | 69 | lose_fpu(0); |
69 | clear_thread_flag(TIF_MSA_CTX_LIVE); | 70 | clear_thread_flag(TIF_MSA_CTX_LIVE); |
70 | clear_used_math(); | 71 | clear_used_math(); |
72 | atomic_set(¤t->thread.bd_emu_frame, BD_EMUFRAME_NONE); | ||
71 | init_dsp(); | 73 | init_dsp(); |
72 | regs->cp0_epc = pc; | 74 | regs->cp0_epc = pc; |
73 | regs->regs[29] = sp; | 75 | regs->regs[29] = sp; |
74 | } | 76 | } |
75 | 77 | ||
78 | void exit_thread(struct task_struct *tsk) | ||
79 | { | ||
80 | /* | ||
81 | * User threads may have allocated a delay slot emulation frame. | ||
82 | * If so, clean up that allocation. | ||
83 | */ | ||
84 | if (!(current->flags & PF_KTHREAD)) | ||
85 | dsemul_thread_cleanup(tsk); | ||
86 | } | ||
87 | |||
76 | int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src) | 88 | int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src) |
77 | { | 89 | { |
78 | /* | 90 | /* |
@@ -159,6 +171,8 @@ int copy_thread(unsigned long clone_flags, unsigned long usp, | |||
159 | clear_tsk_thread_flag(p, TIF_FPUBOUND); | 171 | clear_tsk_thread_flag(p, TIF_FPUBOUND); |
160 | #endif /* CONFIG_MIPS_MT_FPAFF */ | 172 | #endif /* CONFIG_MIPS_MT_FPAFF */ |
161 | 173 | ||
174 | atomic_set(&p->thread.bd_emu_frame, BD_EMUFRAME_NONE); | ||
175 | |||
162 | if (clone_flags & CLONE_SETTLS) | 176 | if (clone_flags & CLONE_SETTLS) |
163 | ti->tp_value = regs->regs[7]; | 177 | ti->tp_value = regs->regs[7]; |
164 | 178 | ||
diff --git a/arch/mips/kernel/scall64-n32.S b/arch/mips/kernel/scall64-n32.S index 9c0b387d6427..51d3988933f8 100644 --- a/arch/mips/kernel/scall64-n32.S +++ b/arch/mips/kernel/scall64-n32.S | |||
@@ -348,7 +348,7 @@ EXPORT(sysn32_call_table) | |||
348 | PTR sys_ni_syscall /* available, was setaltroot */ | 348 | PTR sys_ni_syscall /* available, was setaltroot */ |
349 | PTR sys_add_key | 349 | PTR sys_add_key |
350 | PTR sys_request_key | 350 | PTR sys_request_key |
351 | PTR sys_keyctl /* 6245 */ | 351 | PTR compat_sys_keyctl /* 6245 */ |
352 | PTR sys_set_thread_area | 352 | PTR sys_set_thread_area |
353 | PTR sys_inotify_init | 353 | PTR sys_inotify_init |
354 | PTR sys_inotify_add_watch | 354 | PTR sys_inotify_add_watch |
diff --git a/arch/mips/kernel/scall64-o32.S b/arch/mips/kernel/scall64-o32.S index f4f28b1580de..6efa7136748f 100644 --- a/arch/mips/kernel/scall64-o32.S +++ b/arch/mips/kernel/scall64-o32.S | |||
@@ -504,7 +504,7 @@ EXPORT(sys32_call_table) | |||
504 | PTR sys_ni_syscall /* available, was setaltroot */ | 504 | PTR sys_ni_syscall /* available, was setaltroot */ |
505 | PTR sys_add_key /* 4280 */ | 505 | PTR sys_add_key /* 4280 */ |
506 | PTR sys_request_key | 506 | PTR sys_request_key |
507 | PTR sys_keyctl | 507 | PTR compat_sys_keyctl |
508 | PTR sys_set_thread_area | 508 | PTR sys_set_thread_area |
509 | PTR sys_inotify_init | 509 | PTR sys_inotify_init |
510 | PTR sys_inotify_add_watch /* 4285 */ | 510 | PTR sys_inotify_add_watch /* 4285 */ |
diff --git a/arch/mips/kernel/segment.c b/arch/mips/kernel/segment.c index 87bc74a5a518..2703f218202e 100644 --- a/arch/mips/kernel/segment.c +++ b/arch/mips/kernel/segment.c | |||
@@ -26,17 +26,20 @@ static void build_segment_config(char *str, unsigned int cfg) | |||
26 | 26 | ||
27 | /* | 27 | /* |
28 | * Access modes MK, MSK and MUSK are mapped segments. Therefore | 28 | * Access modes MK, MSK and MUSK are mapped segments. Therefore |
29 | * there is no direct physical address mapping. | 29 | * there is no direct physical address mapping unless it becomes |
30 | * unmapped uncached at error level due to EU. | ||
30 | */ | 31 | */ |
31 | if ((am == 0) || (am > 3)) { | 32 | if ((am == 0) || (am > 3) || (cfg & MIPS_SEGCFG_EU)) |
32 | str += sprintf(str, " %03lx", | 33 | str += sprintf(str, " %03lx", |
33 | ((cfg & MIPS_SEGCFG_PA) >> MIPS_SEGCFG_PA_SHIFT)); | 34 | ((cfg & MIPS_SEGCFG_PA) >> MIPS_SEGCFG_PA_SHIFT)); |
35 | else | ||
36 | str += sprintf(str, " UND"); | ||
37 | |||
38 | if ((am == 0) || (am > 3)) | ||
34 | str += sprintf(str, " %01ld", | 39 | str += sprintf(str, " %01ld", |
35 | ((cfg & MIPS_SEGCFG_C) >> MIPS_SEGCFG_C_SHIFT)); | 40 | ((cfg & MIPS_SEGCFG_C) >> MIPS_SEGCFG_C_SHIFT)); |
36 | } else { | 41 | else |
37 | str += sprintf(str, " UND"); | ||
38 | str += sprintf(str, " U"); | 42 | str += sprintf(str, " U"); |
39 | } | ||
40 | 43 | ||
41 | /* Exception configuration. */ | 44 | /* Exception configuration. */ |
42 | str += sprintf(str, " %01ld\n", | 45 | str += sprintf(str, " %01ld\n", |
diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c index ef408a03e818..36cf8d65c47d 100644 --- a/arch/mips/kernel/setup.c +++ b/arch/mips/kernel/setup.c | |||
@@ -875,6 +875,10 @@ void __init setup_arch(char **cmdline_p) | |||
875 | unsigned long kernelsp[NR_CPUS]; | 875 | unsigned long kernelsp[NR_CPUS]; |
876 | unsigned long fw_arg0, fw_arg1, fw_arg2, fw_arg3; | 876 | unsigned long fw_arg0, fw_arg1, fw_arg2, fw_arg3; |
877 | 877 | ||
878 | #ifdef CONFIG_USE_OF | ||
879 | unsigned long fw_passed_dtb; | ||
880 | #endif | ||
881 | |||
878 | #ifdef CONFIG_DEBUG_FS | 882 | #ifdef CONFIG_DEBUG_FS |
879 | struct dentry *mips_debugfs_dir; | 883 | struct dentry *mips_debugfs_dir; |
880 | static int __init debugfs_mips(void) | 884 | static int __init debugfs_mips(void) |
diff --git a/arch/mips/kernel/signal.c b/arch/mips/kernel/signal.c index 1975cd2f7de6..9e224469c788 100644 --- a/arch/mips/kernel/signal.c +++ b/arch/mips/kernel/signal.c | |||
@@ -772,6 +772,14 @@ static void handle_signal(struct ksignal *ksig, struct pt_regs *regs) | |||
772 | struct mips_abi *abi = current->thread.abi; | 772 | struct mips_abi *abi = current->thread.abi; |
773 | void *vdso = current->mm->context.vdso; | 773 | void *vdso = current->mm->context.vdso; |
774 | 774 | ||
775 | /* | ||
776 | * If we were emulating a delay slot instruction, exit that frame such | ||
777 | * that addresses in the sigframe are as expected for userland and we | ||
778 | * don't have a problem if we reuse the thread's frame for an | ||
779 | * instruction within the signal handler. | ||
780 | */ | ||
781 | dsemul_thread_rollback(regs); | ||
782 | |||
775 | if (regs->regs[0]) { | 783 | if (regs->regs[0]) { |
776 | switch(regs->regs[2]) { | 784 | switch(regs->regs[2]) { |
777 | case ERESTART_RESTARTBLOCK: | 785 | case ERESTART_RESTARTBLOCK: |
diff --git a/arch/mips/kernel/signal32.c b/arch/mips/kernel/signal32.c index 78c8349d151c..97b7c51b8251 100644 --- a/arch/mips/kernel/signal32.c +++ b/arch/mips/kernel/signal32.c | |||
@@ -6,129 +6,26 @@ | |||
6 | * Copyright (C) 1991, 1992 Linus Torvalds | 6 | * Copyright (C) 1991, 1992 Linus Torvalds |
7 | * Copyright (C) 1994 - 2000, 2006 Ralf Baechle | 7 | * Copyright (C) 1994 - 2000, 2006 Ralf Baechle |
8 | * Copyright (C) 1999, 2000 Silicon Graphics, Inc. | 8 | * Copyright (C) 1999, 2000 Silicon Graphics, Inc. |
9 | * Copyright (C) 2016, Imagination Technologies Ltd. | ||
9 | */ | 10 | */ |
10 | #include <linux/cache.h> | 11 | #include <linux/compiler.h> |
11 | #include <linux/compat.h> | 12 | #include <linux/errno.h> |
12 | #include <linux/sched.h> | ||
13 | #include <linux/mm.h> | ||
14 | #include <linux/smp.h> | ||
15 | #include <linux/kernel.h> | 13 | #include <linux/kernel.h> |
16 | #include <linux/signal.h> | 14 | #include <linux/signal.h> |
17 | #include <linux/syscalls.h> | 15 | #include <linux/syscalls.h> |
18 | #include <linux/errno.h> | ||
19 | #include <linux/wait.h> | ||
20 | #include <linux/ptrace.h> | ||
21 | #include <linux/suspend.h> | ||
22 | #include <linux/compiler.h> | ||
23 | #include <linux/uaccess.h> | ||
24 | 16 | ||
25 | #include <asm/abi.h> | 17 | #include <asm/compat.h> |
26 | #include <asm/asm.h> | ||
27 | #include <asm/compat-signal.h> | 18 | #include <asm/compat-signal.h> |
28 | #include <linux/bitops.h> | 19 | #include <asm/uaccess.h> |
29 | #include <asm/cacheflush.h> | 20 | #include <asm/unistd.h> |
30 | #include <asm/sim.h> | ||
31 | #include <asm/ucontext.h> | ||
32 | #include <asm/fpu.h> | ||
33 | #include <asm/war.h> | ||
34 | #include <asm/dsp.h> | ||
35 | 21 | ||
36 | #include "signal-common.h" | 22 | #include "signal-common.h" |
37 | 23 | ||
38 | /* | ||
39 | * Including <asm/unistd.h> would give use the 64-bit syscall numbers ... | ||
40 | */ | ||
41 | #define __NR_O32_restart_syscall 4253 | ||
42 | |||
43 | /* 32-bit compatibility types */ | 24 | /* 32-bit compatibility types */ |
44 | 25 | ||
45 | typedef unsigned int __sighandler32_t; | 26 | typedef unsigned int __sighandler32_t; |
46 | typedef void (*vfptr_t)(void); | 27 | typedef void (*vfptr_t)(void); |
47 | 28 | ||
48 | struct ucontext32 { | ||
49 | u32 uc_flags; | ||
50 | s32 uc_link; | ||
51 | compat_stack_t uc_stack; | ||
52 | struct sigcontext32 uc_mcontext; | ||
53 | compat_sigset_t uc_sigmask; /* mask last for extensibility */ | ||
54 | }; | ||
55 | |||
56 | struct sigframe32 { | ||
57 | u32 sf_ass[4]; /* argument save space for o32 */ | ||
58 | u32 sf_pad[2]; /* Was: signal trampoline */ | ||
59 | struct sigcontext32 sf_sc; | ||
60 | compat_sigset_t sf_mask; | ||
61 | }; | ||
62 | |||
63 | struct rt_sigframe32 { | ||
64 | u32 rs_ass[4]; /* argument save space for o32 */ | ||
65 | u32 rs_pad[2]; /* Was: signal trampoline */ | ||
66 | compat_siginfo_t rs_info; | ||
67 | struct ucontext32 rs_uc; | ||
68 | }; | ||
69 | |||
70 | static int setup_sigcontext32(struct pt_regs *regs, | ||
71 | struct sigcontext32 __user *sc) | ||
72 | { | ||
73 | int err = 0; | ||
74 | int i; | ||
75 | |||
76 | err |= __put_user(regs->cp0_epc, &sc->sc_pc); | ||
77 | |||
78 | err |= __put_user(0, &sc->sc_regs[0]); | ||
79 | for (i = 1; i < 32; i++) | ||
80 | err |= __put_user(regs->regs[i], &sc->sc_regs[i]); | ||
81 | |||
82 | err |= __put_user(regs->hi, &sc->sc_mdhi); | ||
83 | err |= __put_user(regs->lo, &sc->sc_mdlo); | ||
84 | if (cpu_has_dsp) { | ||
85 | err |= __put_user(rddsp(DSP_MASK), &sc->sc_dsp); | ||
86 | err |= __put_user(mfhi1(), &sc->sc_hi1); | ||
87 | err |= __put_user(mflo1(), &sc->sc_lo1); | ||
88 | err |= __put_user(mfhi2(), &sc->sc_hi2); | ||
89 | err |= __put_user(mflo2(), &sc->sc_lo2); | ||
90 | err |= __put_user(mfhi3(), &sc->sc_hi3); | ||
91 | err |= __put_user(mflo3(), &sc->sc_lo3); | ||
92 | } | ||
93 | |||
94 | /* | ||
95 | * Save FPU state to signal context. Signal handler | ||
96 | * will "inherit" current FPU state. | ||
97 | */ | ||
98 | err |= protected_save_fp_context(sc); | ||
99 | |||
100 | return err; | ||
101 | } | ||
102 | |||
103 | static int restore_sigcontext32(struct pt_regs *regs, | ||
104 | struct sigcontext32 __user *sc) | ||
105 | { | ||
106 | int err = 0; | ||
107 | s32 treg; | ||
108 | int i; | ||
109 | |||
110 | /* Always make any pending restarted system calls return -EINTR */ | ||
111 | current->restart_block.fn = do_no_restart_syscall; | ||
112 | |||
113 | err |= __get_user(regs->cp0_epc, &sc->sc_pc); | ||
114 | err |= __get_user(regs->hi, &sc->sc_mdhi); | ||
115 | err |= __get_user(regs->lo, &sc->sc_mdlo); | ||
116 | if (cpu_has_dsp) { | ||
117 | err |= __get_user(treg, &sc->sc_hi1); mthi1(treg); | ||
118 | err |= __get_user(treg, &sc->sc_lo1); mtlo1(treg); | ||
119 | err |= __get_user(treg, &sc->sc_hi2); mthi2(treg); | ||
120 | err |= __get_user(treg, &sc->sc_lo2); mtlo2(treg); | ||
121 | err |= __get_user(treg, &sc->sc_hi3); mthi3(treg); | ||
122 | err |= __get_user(treg, &sc->sc_lo3); mtlo3(treg); | ||
123 | err |= __get_user(treg, &sc->sc_dsp); wrdsp(treg, DSP_MASK); | ||
124 | } | ||
125 | |||
126 | for (i = 1; i < 32; i++) | ||
127 | err |= __get_user(regs->regs[i], &sc->sc_regs[i]); | ||
128 | |||
129 | return err ?: protected_restore_fp_context(sc); | ||
130 | } | ||
131 | |||
132 | /* | 29 | /* |
133 | * Atomically swap in the new signal mask, and wait for a signal. | 30 | * Atomically swap in the new signal mask, and wait for a signal. |
134 | */ | 31 | */ |
@@ -247,176 +144,3 @@ int copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from) | |||
247 | 144 | ||
248 | return 0; | 145 | return 0; |
249 | } | 146 | } |
250 | |||
251 | asmlinkage void sys32_sigreturn(nabi_no_regargs struct pt_regs regs) | ||
252 | { | ||
253 | struct sigframe32 __user *frame; | ||
254 | sigset_t blocked; | ||
255 | int sig; | ||
256 | |||
257 | frame = (struct sigframe32 __user *) regs.regs[29]; | ||
258 | if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) | ||
259 | goto badframe; | ||
260 | if (__copy_conv_sigset_from_user(&blocked, &frame->sf_mask)) | ||
261 | goto badframe; | ||
262 | |||
263 | set_current_blocked(&blocked); | ||
264 | |||
265 | sig = restore_sigcontext32(®s, &frame->sf_sc); | ||
266 | if (sig < 0) | ||
267 | goto badframe; | ||
268 | else if (sig) | ||
269 | force_sig(sig, current); | ||
270 | |||
271 | /* | ||
272 | * Don't let your children do this ... | ||
273 | */ | ||
274 | __asm__ __volatile__( | ||
275 | "move\t$29, %0\n\t" | ||
276 | "j\tsyscall_exit" | ||
277 | :/* no outputs */ | ||
278 | :"r" (®s)); | ||
279 | /* Unreached */ | ||
280 | |||
281 | badframe: | ||
282 | force_sig(SIGSEGV, current); | ||
283 | } | ||
284 | |||
285 | asmlinkage void sys32_rt_sigreturn(nabi_no_regargs struct pt_regs regs) | ||
286 | { | ||
287 | struct rt_sigframe32 __user *frame; | ||
288 | sigset_t set; | ||
289 | int sig; | ||
290 | |||
291 | frame = (struct rt_sigframe32 __user *) regs.regs[29]; | ||
292 | if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) | ||
293 | goto badframe; | ||
294 | if (__copy_conv_sigset_from_user(&set, &frame->rs_uc.uc_sigmask)) | ||
295 | goto badframe; | ||
296 | |||
297 | set_current_blocked(&set); | ||
298 | |||
299 | sig = restore_sigcontext32(®s, &frame->rs_uc.uc_mcontext); | ||
300 | if (sig < 0) | ||
301 | goto badframe; | ||
302 | else if (sig) | ||
303 | force_sig(sig, current); | ||
304 | |||
305 | if (compat_restore_altstack(&frame->rs_uc.uc_stack)) | ||
306 | goto badframe; | ||
307 | |||
308 | /* | ||
309 | * Don't let your children do this ... | ||
310 | */ | ||
311 | __asm__ __volatile__( | ||
312 | "move\t$29, %0\n\t" | ||
313 | "j\tsyscall_exit" | ||
314 | :/* no outputs */ | ||
315 | :"r" (®s)); | ||
316 | /* Unreached */ | ||
317 | |||
318 | badframe: | ||
319 | force_sig(SIGSEGV, current); | ||
320 | } | ||
321 | |||
322 | static int setup_frame_32(void *sig_return, struct ksignal *ksig, | ||
323 | struct pt_regs *regs, sigset_t *set) | ||
324 | { | ||
325 | struct sigframe32 __user *frame; | ||
326 | int err = 0; | ||
327 | |||
328 | frame = get_sigframe(ksig, regs, sizeof(*frame)); | ||
329 | if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame))) | ||
330 | return -EFAULT; | ||
331 | |||
332 | err |= setup_sigcontext32(regs, &frame->sf_sc); | ||
333 | err |= __copy_conv_sigset_to_user(&frame->sf_mask, set); | ||
334 | |||
335 | if (err) | ||
336 | return -EFAULT; | ||
337 | |||
338 | /* | ||
339 | * Arguments to signal handler: | ||
340 | * | ||
341 | * a0 = signal number | ||
342 | * a1 = 0 (should be cause) | ||
343 | * a2 = pointer to struct sigcontext | ||
344 | * | ||
345 | * $25 and c0_epc point to the signal handler, $29 points to the | ||
346 | * struct sigframe. | ||
347 | */ | ||
348 | regs->regs[ 4] = ksig->sig; | ||
349 | regs->regs[ 5] = 0; | ||
350 | regs->regs[ 6] = (unsigned long) &frame->sf_sc; | ||
351 | regs->regs[29] = (unsigned long) frame; | ||
352 | regs->regs[31] = (unsigned long) sig_return; | ||
353 | regs->cp0_epc = regs->regs[25] = (unsigned long) ksig->ka.sa.sa_handler; | ||
354 | |||
355 | DEBUGP("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%lx\n", | ||
356 | current->comm, current->pid, | ||
357 | frame, regs->cp0_epc, regs->regs[31]); | ||
358 | |||
359 | return 0; | ||
360 | } | ||
361 | |||
362 | static int setup_rt_frame_32(void *sig_return, struct ksignal *ksig, | ||
363 | struct pt_regs *regs, sigset_t *set) | ||
364 | { | ||
365 | struct rt_sigframe32 __user *frame; | ||
366 | int err = 0; | ||
367 | |||
368 | frame = get_sigframe(ksig, regs, sizeof(*frame)); | ||
369 | if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame))) | ||
370 | return -EFAULT; | ||
371 | |||
372 | /* Convert (siginfo_t -> compat_siginfo_t) and copy to user. */ | ||
373 | err |= copy_siginfo_to_user32(&frame->rs_info, &ksig->info); | ||
374 | |||
375 | /* Create the ucontext. */ | ||
376 | err |= __put_user(0, &frame->rs_uc.uc_flags); | ||
377 | err |= __put_user(0, &frame->rs_uc.uc_link); | ||
378 | err |= __compat_save_altstack(&frame->rs_uc.uc_stack, regs->regs[29]); | ||
379 | err |= setup_sigcontext32(regs, &frame->rs_uc.uc_mcontext); | ||
380 | err |= __copy_conv_sigset_to_user(&frame->rs_uc.uc_sigmask, set); | ||
381 | |||
382 | if (err) | ||
383 | return -EFAULT; | ||
384 | |||
385 | /* | ||
386 | * Arguments to signal handler: | ||
387 | * | ||
388 | * a0 = signal number | ||
389 | * a1 = 0 (should be cause) | ||
390 | * a2 = pointer to ucontext | ||
391 | * | ||
392 | * $25 and c0_epc point to the signal handler, $29 points to | ||
393 | * the struct rt_sigframe32. | ||
394 | */ | ||
395 | regs->regs[ 4] = ksig->sig; | ||
396 | regs->regs[ 5] = (unsigned long) &frame->rs_info; | ||
397 | regs->regs[ 6] = (unsigned long) &frame->rs_uc; | ||
398 | regs->regs[29] = (unsigned long) frame; | ||
399 | regs->regs[31] = (unsigned long) sig_return; | ||
400 | regs->cp0_epc = regs->regs[25] = (unsigned long) ksig->ka.sa.sa_handler; | ||
401 | |||
402 | DEBUGP("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%lx\n", | ||
403 | current->comm, current->pid, | ||
404 | frame, regs->cp0_epc, regs->regs[31]); | ||
405 | |||
406 | return 0; | ||
407 | } | ||
408 | |||
409 | /* | ||
410 | * o32 compatibility on 64-bit kernels, without DSP ASE | ||
411 | */ | ||
412 | struct mips_abi mips_abi_32 = { | ||
413 | .setup_frame = setup_frame_32, | ||
414 | .setup_rt_frame = setup_rt_frame_32, | ||
415 | .restart = __NR_O32_restart_syscall, | ||
416 | |||
417 | .off_sc_fpregs = offsetof(struct sigcontext32, sc_fpregs), | ||
418 | .off_sc_fpc_csr = offsetof(struct sigcontext32, sc_fpc_csr), | ||
419 | .off_sc_used_math = offsetof(struct sigcontext32, sc_used_math), | ||
420 | |||
421 | .vdso = &vdso_image_o32, | ||
422 | }; | ||
diff --git a/arch/mips/kernel/signal_o32.c b/arch/mips/kernel/signal_o32.c new file mode 100644 index 000000000000..5e169fc5ca5c --- /dev/null +++ b/arch/mips/kernel/signal_o32.c | |||
@@ -0,0 +1,285 @@ | |||
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) 1991, 1992 Linus Torvalds | ||
7 | * Copyright (C) 1994 - 2000, 2006 Ralf Baechle | ||
8 | * Copyright (C) 1999, 2000 Silicon Graphics, Inc. | ||
9 | * Copyright (C) 2016, Imagination Technologies Ltd. | ||
10 | */ | ||
11 | #include <linux/compiler.h> | ||
12 | #include <linux/errno.h> | ||
13 | #include <linux/signal.h> | ||
14 | #include <linux/uaccess.h> | ||
15 | |||
16 | #include <asm/abi.h> | ||
17 | #include <asm/compat-signal.h> | ||
18 | #include <asm/dsp.h> | ||
19 | #include <asm/sim.h> | ||
20 | #include <asm/unistd.h> | ||
21 | |||
22 | #include "signal-common.h" | ||
23 | |||
24 | /* | ||
25 | * Including <asm/unistd.h> would give use the 64-bit syscall numbers ... | ||
26 | */ | ||
27 | #define __NR_O32_restart_syscall 4253 | ||
28 | |||
29 | struct sigframe32 { | ||
30 | u32 sf_ass[4]; /* argument save space for o32 */ | ||
31 | u32 sf_pad[2]; /* Was: signal trampoline */ | ||
32 | struct sigcontext32 sf_sc; | ||
33 | compat_sigset_t sf_mask; | ||
34 | }; | ||
35 | |||
36 | struct ucontext32 { | ||
37 | u32 uc_flags; | ||
38 | s32 uc_link; | ||
39 | compat_stack_t uc_stack; | ||
40 | struct sigcontext32 uc_mcontext; | ||
41 | compat_sigset_t uc_sigmask; /* mask last for extensibility */ | ||
42 | }; | ||
43 | |||
44 | struct rt_sigframe32 { | ||
45 | u32 rs_ass[4]; /* argument save space for o32 */ | ||
46 | u32 rs_pad[2]; /* Was: signal trampoline */ | ||
47 | compat_siginfo_t rs_info; | ||
48 | struct ucontext32 rs_uc; | ||
49 | }; | ||
50 | |||
51 | static int setup_sigcontext32(struct pt_regs *regs, | ||
52 | struct sigcontext32 __user *sc) | ||
53 | { | ||
54 | int err = 0; | ||
55 | int i; | ||
56 | |||
57 | err |= __put_user(regs->cp0_epc, &sc->sc_pc); | ||
58 | |||
59 | err |= __put_user(0, &sc->sc_regs[0]); | ||
60 | for (i = 1; i < 32; i++) | ||
61 | err |= __put_user(regs->regs[i], &sc->sc_regs[i]); | ||
62 | |||
63 | err |= __put_user(regs->hi, &sc->sc_mdhi); | ||
64 | err |= __put_user(regs->lo, &sc->sc_mdlo); | ||
65 | if (cpu_has_dsp) { | ||
66 | err |= __put_user(rddsp(DSP_MASK), &sc->sc_dsp); | ||
67 | err |= __put_user(mfhi1(), &sc->sc_hi1); | ||
68 | err |= __put_user(mflo1(), &sc->sc_lo1); | ||
69 | err |= __put_user(mfhi2(), &sc->sc_hi2); | ||
70 | err |= __put_user(mflo2(), &sc->sc_lo2); | ||
71 | err |= __put_user(mfhi3(), &sc->sc_hi3); | ||
72 | err |= __put_user(mflo3(), &sc->sc_lo3); | ||
73 | } | ||
74 | |||
75 | /* | ||
76 | * Save FPU state to signal context. Signal handler | ||
77 | * will "inherit" current FPU state. | ||
78 | */ | ||
79 | err |= protected_save_fp_context(sc); | ||
80 | |||
81 | return err; | ||
82 | } | ||
83 | |||
84 | static int restore_sigcontext32(struct pt_regs *regs, | ||
85 | struct sigcontext32 __user *sc) | ||
86 | { | ||
87 | int err = 0; | ||
88 | s32 treg; | ||
89 | int i; | ||
90 | |||
91 | /* Always make any pending restarted system calls return -EINTR */ | ||
92 | current->restart_block.fn = do_no_restart_syscall; | ||
93 | |||
94 | err |= __get_user(regs->cp0_epc, &sc->sc_pc); | ||
95 | err |= __get_user(regs->hi, &sc->sc_mdhi); | ||
96 | err |= __get_user(regs->lo, &sc->sc_mdlo); | ||
97 | if (cpu_has_dsp) { | ||
98 | err |= __get_user(treg, &sc->sc_hi1); mthi1(treg); | ||
99 | err |= __get_user(treg, &sc->sc_lo1); mtlo1(treg); | ||
100 | err |= __get_user(treg, &sc->sc_hi2); mthi2(treg); | ||
101 | err |= __get_user(treg, &sc->sc_lo2); mtlo2(treg); | ||
102 | err |= __get_user(treg, &sc->sc_hi3); mthi3(treg); | ||
103 | err |= __get_user(treg, &sc->sc_lo3); mtlo3(treg); | ||
104 | err |= __get_user(treg, &sc->sc_dsp); wrdsp(treg, DSP_MASK); | ||
105 | } | ||
106 | |||
107 | for (i = 1; i < 32; i++) | ||
108 | err |= __get_user(regs->regs[i], &sc->sc_regs[i]); | ||
109 | |||
110 | return err ?: protected_restore_fp_context(sc); | ||
111 | } | ||
112 | |||
113 | static int setup_frame_32(void *sig_return, struct ksignal *ksig, | ||
114 | struct pt_regs *regs, sigset_t *set) | ||
115 | { | ||
116 | struct sigframe32 __user *frame; | ||
117 | int err = 0; | ||
118 | |||
119 | frame = get_sigframe(ksig, regs, sizeof(*frame)); | ||
120 | if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame))) | ||
121 | return -EFAULT; | ||
122 | |||
123 | err |= setup_sigcontext32(regs, &frame->sf_sc); | ||
124 | err |= __copy_conv_sigset_to_user(&frame->sf_mask, set); | ||
125 | |||
126 | if (err) | ||
127 | return -EFAULT; | ||
128 | |||
129 | /* | ||
130 | * Arguments to signal handler: | ||
131 | * | ||
132 | * a0 = signal number | ||
133 | * a1 = 0 (should be cause) | ||
134 | * a2 = pointer to struct sigcontext | ||
135 | * | ||
136 | * $25 and c0_epc point to the signal handler, $29 points to the | ||
137 | * struct sigframe. | ||
138 | */ | ||
139 | regs->regs[ 4] = ksig->sig; | ||
140 | regs->regs[ 5] = 0; | ||
141 | regs->regs[ 6] = (unsigned long) &frame->sf_sc; | ||
142 | regs->regs[29] = (unsigned long) frame; | ||
143 | regs->regs[31] = (unsigned long) sig_return; | ||
144 | regs->cp0_epc = regs->regs[25] = (unsigned long) ksig->ka.sa.sa_handler; | ||
145 | |||
146 | DEBUGP("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%lx\n", | ||
147 | current->comm, current->pid, | ||
148 | frame, regs->cp0_epc, regs->regs[31]); | ||
149 | |||
150 | return 0; | ||
151 | } | ||
152 | |||
153 | asmlinkage void sys32_rt_sigreturn(nabi_no_regargs struct pt_regs regs) | ||
154 | { | ||
155 | struct rt_sigframe32 __user *frame; | ||
156 | sigset_t set; | ||
157 | int sig; | ||
158 | |||
159 | frame = (struct rt_sigframe32 __user *) regs.regs[29]; | ||
160 | if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) | ||
161 | goto badframe; | ||
162 | if (__copy_conv_sigset_from_user(&set, &frame->rs_uc.uc_sigmask)) | ||
163 | goto badframe; | ||
164 | |||
165 | set_current_blocked(&set); | ||
166 | |||
167 | sig = restore_sigcontext32(®s, &frame->rs_uc.uc_mcontext); | ||
168 | if (sig < 0) | ||
169 | goto badframe; | ||
170 | else if (sig) | ||
171 | force_sig(sig, current); | ||
172 | |||
173 | if (compat_restore_altstack(&frame->rs_uc.uc_stack)) | ||
174 | goto badframe; | ||
175 | |||
176 | /* | ||
177 | * Don't let your children do this ... | ||
178 | */ | ||
179 | __asm__ __volatile__( | ||
180 | "move\t$29, %0\n\t" | ||
181 | "j\tsyscall_exit" | ||
182 | :/* no outputs */ | ||
183 | :"r" (®s)); | ||
184 | /* Unreached */ | ||
185 | |||
186 | badframe: | ||
187 | force_sig(SIGSEGV, current); | ||
188 | } | ||
189 | |||
190 | static int setup_rt_frame_32(void *sig_return, struct ksignal *ksig, | ||
191 | struct pt_regs *regs, sigset_t *set) | ||
192 | { | ||
193 | struct rt_sigframe32 __user *frame; | ||
194 | int err = 0; | ||
195 | |||
196 | frame = get_sigframe(ksig, regs, sizeof(*frame)); | ||
197 | if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame))) | ||
198 | return -EFAULT; | ||
199 | |||
200 | /* Convert (siginfo_t -> compat_siginfo_t) and copy to user. */ | ||
201 | err |= copy_siginfo_to_user32(&frame->rs_info, &ksig->info); | ||
202 | |||
203 | /* Create the ucontext. */ | ||
204 | err |= __put_user(0, &frame->rs_uc.uc_flags); | ||
205 | err |= __put_user(0, &frame->rs_uc.uc_link); | ||
206 | err |= __compat_save_altstack(&frame->rs_uc.uc_stack, regs->regs[29]); | ||
207 | err |= setup_sigcontext32(regs, &frame->rs_uc.uc_mcontext); | ||
208 | err |= __copy_conv_sigset_to_user(&frame->rs_uc.uc_sigmask, set); | ||
209 | |||
210 | if (err) | ||
211 | return -EFAULT; | ||
212 | |||
213 | /* | ||
214 | * Arguments to signal handler: | ||
215 | * | ||
216 | * a0 = signal number | ||
217 | * a1 = 0 (should be cause) | ||
218 | * a2 = pointer to ucontext | ||
219 | * | ||
220 | * $25 and c0_epc point to the signal handler, $29 points to | ||
221 | * the struct rt_sigframe32. | ||
222 | */ | ||
223 | regs->regs[ 4] = ksig->sig; | ||
224 | regs->regs[ 5] = (unsigned long) &frame->rs_info; | ||
225 | regs->regs[ 6] = (unsigned long) &frame->rs_uc; | ||
226 | regs->regs[29] = (unsigned long) frame; | ||
227 | regs->regs[31] = (unsigned long) sig_return; | ||
228 | regs->cp0_epc = regs->regs[25] = (unsigned long) ksig->ka.sa.sa_handler; | ||
229 | |||
230 | DEBUGP("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%lx\n", | ||
231 | current->comm, current->pid, | ||
232 | frame, regs->cp0_epc, regs->regs[31]); | ||
233 | |||
234 | return 0; | ||
235 | } | ||
236 | |||
237 | /* | ||
238 | * o32 compatibility on 64-bit kernels, without DSP ASE | ||
239 | */ | ||
240 | struct mips_abi mips_abi_32 = { | ||
241 | .setup_frame = setup_frame_32, | ||
242 | .setup_rt_frame = setup_rt_frame_32, | ||
243 | .restart = __NR_O32_restart_syscall, | ||
244 | |||
245 | .off_sc_fpregs = offsetof(struct sigcontext32, sc_fpregs), | ||
246 | .off_sc_fpc_csr = offsetof(struct sigcontext32, sc_fpc_csr), | ||
247 | .off_sc_used_math = offsetof(struct sigcontext32, sc_used_math), | ||
248 | |||
249 | .vdso = &vdso_image_o32, | ||
250 | }; | ||
251 | |||
252 | |||
253 | asmlinkage void sys32_sigreturn(nabi_no_regargs struct pt_regs regs) | ||
254 | { | ||
255 | struct sigframe32 __user *frame; | ||
256 | sigset_t blocked; | ||
257 | int sig; | ||
258 | |||
259 | frame = (struct sigframe32 __user *) regs.regs[29]; | ||
260 | if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) | ||
261 | goto badframe; | ||
262 | if (__copy_conv_sigset_from_user(&blocked, &frame->sf_mask)) | ||
263 | goto badframe; | ||
264 | |||
265 | set_current_blocked(&blocked); | ||
266 | |||
267 | sig = restore_sigcontext32(®s, &frame->sf_sc); | ||
268 | if (sig < 0) | ||
269 | goto badframe; | ||
270 | else if (sig) | ||
271 | force_sig(sig, current); | ||
272 | |||
273 | /* | ||
274 | * Don't let your children do this ... | ||
275 | */ | ||
276 | __asm__ __volatile__( | ||
277 | "move\t$29, %0\n\t" | ||
278 | "j\tsyscall_exit" | ||
279 | :/* no outputs */ | ||
280 | :"r" (®s)); | ||
281 | /* Unreached */ | ||
282 | |||
283 | badframe: | ||
284 | force_sig(SIGSEGV, current); | ||
285 | } | ||
diff --git a/arch/mips/kernel/smp-bmips.c b/arch/mips/kernel/smp-bmips.c index e02addc0307f..6d0f1321e084 100644 --- a/arch/mips/kernel/smp-bmips.c +++ b/arch/mips/kernel/smp-bmips.c | |||
@@ -363,6 +363,7 @@ static int bmips_cpu_disable(void) | |||
363 | pr_info("SMP: CPU%d is offline\n", cpu); | 363 | pr_info("SMP: CPU%d is offline\n", cpu); |
364 | 364 | ||
365 | set_cpu_online(cpu, false); | 365 | set_cpu_online(cpu, false); |
366 | calculate_cpu_foreign_map(); | ||
366 | cpumask_clear_cpu(cpu, &cpu_callin_map); | 367 | cpumask_clear_cpu(cpu, &cpu_callin_map); |
367 | clear_c0_status(IE_IRQ5); | 368 | clear_c0_status(IE_IRQ5); |
368 | 369 | ||
diff --git a/arch/mips/kernel/smp-cps.c b/arch/mips/kernel/smp-cps.c index 05b3201271b4..e9d9fc6c754c 100644 --- a/arch/mips/kernel/smp-cps.c +++ b/arch/mips/kernel/smp-cps.c | |||
@@ -206,7 +206,7 @@ err_out: | |||
206 | } | 206 | } |
207 | } | 207 | } |
208 | 208 | ||
209 | static void boot_core(unsigned core) | 209 | static void boot_core(unsigned int core, unsigned int vpe_id) |
210 | { | 210 | { |
211 | u32 access, stat, seq_state; | 211 | u32 access, stat, seq_state; |
212 | unsigned timeout; | 212 | unsigned timeout; |
@@ -233,8 +233,9 @@ static void boot_core(unsigned core) | |||
233 | mips_cpc_lock_other(core); | 233 | mips_cpc_lock_other(core); |
234 | 234 | ||
235 | if (mips_cm_revision() >= CM_REV_CM3) { | 235 | if (mips_cm_revision() >= CM_REV_CM3) { |
236 | /* Run VP0 following the reset */ | 236 | /* Run only the requested VP following the reset */ |
237 | write_cpc_co_vp_run(0x1); | 237 | write_cpc_co_vp_stop(0xf); |
238 | write_cpc_co_vp_run(1 << vpe_id); | ||
238 | 239 | ||
239 | /* | 240 | /* |
240 | * Ensure that the VP_RUN register is written before the | 241 | * Ensure that the VP_RUN register is written before the |
@@ -306,7 +307,7 @@ static void cps_boot_secondary(int cpu, struct task_struct *idle) | |||
306 | 307 | ||
307 | if (!test_bit(core, core_power)) { | 308 | if (!test_bit(core, core_power)) { |
308 | /* Boot a VPE on a powered down core */ | 309 | /* Boot a VPE on a powered down core */ |
309 | boot_core(core); | 310 | boot_core(core, vpe_id); |
310 | goto out; | 311 | goto out; |
311 | } | 312 | } |
312 | 313 | ||
@@ -397,6 +398,7 @@ static int cps_cpu_disable(void) | |||
397 | atomic_sub(1 << cpu_vpe_id(¤t_cpu_data), &core_cfg->vpe_mask); | 398 | atomic_sub(1 << cpu_vpe_id(¤t_cpu_data), &core_cfg->vpe_mask); |
398 | smp_mb__after_atomic(); | 399 | smp_mb__after_atomic(); |
399 | set_cpu_online(cpu, false); | 400 | set_cpu_online(cpu, false); |
401 | calculate_cpu_foreign_map(); | ||
400 | cpumask_clear_cpu(cpu, &cpu_callin_map); | 402 | cpumask_clear_cpu(cpu, &cpu_callin_map); |
401 | 403 | ||
402 | return 0; | 404 | return 0; |
@@ -411,14 +413,16 @@ static enum { | |||
411 | 413 | ||
412 | void play_dead(void) | 414 | void play_dead(void) |
413 | { | 415 | { |
414 | unsigned cpu, core; | 416 | unsigned int cpu, core, vpe_id; |
415 | 417 | ||
416 | local_irq_disable(); | 418 | local_irq_disable(); |
417 | idle_task_exit(); | 419 | idle_task_exit(); |
418 | cpu = smp_processor_id(); | 420 | cpu = smp_processor_id(); |
419 | cpu_death = CPU_DEATH_POWER; | 421 | cpu_death = CPU_DEATH_POWER; |
420 | 422 | ||
421 | if (cpu_has_mipsmt) { | 423 | pr_debug("CPU%d going offline\n", cpu); |
424 | |||
425 | if (cpu_has_mipsmt || cpu_has_vp) { | ||
422 | core = cpu_data[cpu].core; | 426 | core = cpu_data[cpu].core; |
423 | 427 | ||
424 | /* Look for another online VPE within the core */ | 428 | /* Look for another online VPE within the core */ |
@@ -439,10 +443,21 @@ void play_dead(void) | |||
439 | complete(&cpu_death_chosen); | 443 | complete(&cpu_death_chosen); |
440 | 444 | ||
441 | if (cpu_death == CPU_DEATH_HALT) { | 445 | if (cpu_death == CPU_DEATH_HALT) { |
442 | /* Halt this TC */ | 446 | vpe_id = cpu_vpe_id(&cpu_data[cpu]); |
443 | write_c0_tchalt(TCHALT_H); | 447 | |
444 | instruction_hazard(); | 448 | pr_debug("Halting core %d VP%d\n", core, vpe_id); |
449 | if (cpu_has_mipsmt) { | ||
450 | /* Halt this TC */ | ||
451 | write_c0_tchalt(TCHALT_H); | ||
452 | instruction_hazard(); | ||
453 | } else if (cpu_has_vp) { | ||
454 | write_cpc_cl_vp_stop(1 << vpe_id); | ||
455 | |||
456 | /* Ensure that the VP_STOP register is written */ | ||
457 | wmb(); | ||
458 | } | ||
445 | } else { | 459 | } else { |
460 | pr_debug("Gating power to core %d\n", core); | ||
446 | /* Power down the core */ | 461 | /* Power down the core */ |
447 | cps_pm_enter_state(CPS_PM_POWER_GATED); | 462 | cps_pm_enter_state(CPS_PM_POWER_GATED); |
448 | } | 463 | } |
@@ -469,6 +484,7 @@ static void wait_for_sibling_halt(void *ptr_cpu) | |||
469 | static void cps_cpu_die(unsigned int cpu) | 484 | static void cps_cpu_die(unsigned int cpu) |
470 | { | 485 | { |
471 | unsigned core = cpu_data[cpu].core; | 486 | unsigned core = cpu_data[cpu].core; |
487 | unsigned int vpe_id = cpu_vpe_id(&cpu_data[cpu]); | ||
472 | unsigned stat; | 488 | unsigned stat; |
473 | int err; | 489 | int err; |
474 | 490 | ||
@@ -497,10 +513,12 @@ static void cps_cpu_die(unsigned int cpu) | |||
497 | * in which case the CPC will refuse to power down the core. | 513 | * in which case the CPC will refuse to power down the core. |
498 | */ | 514 | */ |
499 | do { | 515 | do { |
516 | mips_cm_lock_other(core, vpe_id); | ||
500 | mips_cpc_lock_other(core); | 517 | mips_cpc_lock_other(core); |
501 | stat = read_cpc_co_stat_conf(); | 518 | stat = read_cpc_co_stat_conf(); |
502 | stat &= CPC_Cx_STAT_CONF_SEQSTATE_MSK; | 519 | stat &= CPC_Cx_STAT_CONF_SEQSTATE_MSK; |
503 | mips_cpc_unlock_other(); | 520 | mips_cpc_unlock_other(); |
521 | mips_cm_unlock_other(); | ||
504 | } while (stat != CPC_Cx_STAT_CONF_SEQSTATE_D0 && | 522 | } while (stat != CPC_Cx_STAT_CONF_SEQSTATE_D0 && |
505 | stat != CPC_Cx_STAT_CONF_SEQSTATE_D2 && | 523 | stat != CPC_Cx_STAT_CONF_SEQSTATE_D2 && |
506 | stat != CPC_Cx_STAT_CONF_SEQSTATE_U2); | 524 | stat != CPC_Cx_STAT_CONF_SEQSTATE_U2); |
@@ -517,6 +535,12 @@ static void cps_cpu_die(unsigned int cpu) | |||
517 | (void *)(unsigned long)cpu, 1); | 535 | (void *)(unsigned long)cpu, 1); |
518 | if (err) | 536 | if (err) |
519 | panic("Failed to call remote sibling CPU\n"); | 537 | panic("Failed to call remote sibling CPU\n"); |
538 | } else if (cpu_has_vp) { | ||
539 | do { | ||
540 | mips_cm_lock_other(core, vpe_id); | ||
541 | stat = read_cpc_co_vp_running(); | ||
542 | mips_cm_unlock_other(); | ||
543 | } while (stat & (1 << vpe_id)); | ||
520 | } | 544 | } |
521 | } | 545 | } |
522 | 546 | ||
diff --git a/arch/mips/kernel/smp.c b/arch/mips/kernel/smp.c index f9d01e953acb..f95f094f36e4 100644 --- a/arch/mips/kernel/smp.c +++ b/arch/mips/kernel/smp.c | |||
@@ -72,7 +72,7 @@ EXPORT_SYMBOL(cpu_core_map); | |||
72 | * A logcal cpu mask containing only one VPE per core to | 72 | * A logcal cpu mask containing only one VPE per core to |
73 | * reduce the number of IPIs on large MT systems. | 73 | * reduce the number of IPIs on large MT systems. |
74 | */ | 74 | */ |
75 | cpumask_t cpu_foreign_map __read_mostly; | 75 | cpumask_t cpu_foreign_map[NR_CPUS] __read_mostly; |
76 | EXPORT_SYMBOL(cpu_foreign_map); | 76 | EXPORT_SYMBOL(cpu_foreign_map); |
77 | 77 | ||
78 | /* representing cpus for which sibling maps can be computed */ | 78 | /* representing cpus for which sibling maps can be computed */ |
@@ -124,7 +124,7 @@ static inline void set_cpu_core_map(int cpu) | |||
124 | * Calculate a new cpu_foreign_map mask whenever a | 124 | * Calculate a new cpu_foreign_map mask whenever a |
125 | * new cpu appears or disappears. | 125 | * new cpu appears or disappears. |
126 | */ | 126 | */ |
127 | static inline void calculate_cpu_foreign_map(void) | 127 | void calculate_cpu_foreign_map(void) |
128 | { | 128 | { |
129 | int i, k, core_present; | 129 | int i, k, core_present; |
130 | cpumask_t temp_foreign_map; | 130 | cpumask_t temp_foreign_map; |
@@ -141,7 +141,9 @@ static inline void calculate_cpu_foreign_map(void) | |||
141 | cpumask_set_cpu(i, &temp_foreign_map); | 141 | cpumask_set_cpu(i, &temp_foreign_map); |
142 | } | 142 | } |
143 | 143 | ||
144 | cpumask_copy(&cpu_foreign_map, &temp_foreign_map); | 144 | for_each_online_cpu(i) |
145 | cpumask_andnot(&cpu_foreign_map[i], | ||
146 | &temp_foreign_map, &cpu_sibling_map[i]); | ||
145 | } | 147 | } |
146 | 148 | ||
147 | struct plat_smp_ops *mp_ops; | 149 | struct plat_smp_ops *mp_ops; |
@@ -344,16 +346,9 @@ asmlinkage void start_secondary(void) | |||
344 | static void stop_this_cpu(void *dummy) | 346 | static void stop_this_cpu(void *dummy) |
345 | { | 347 | { |
346 | /* | 348 | /* |
347 | * Remove this CPU. Be a bit slow here and | 349 | * Remove this CPU: |
348 | * set the bits for every online CPU so we don't miss | ||
349 | * any IPI whilst taking this VPE down. | ||
350 | */ | 350 | */ |
351 | 351 | ||
352 | cpumask_copy(&cpu_foreign_map, cpu_online_mask); | ||
353 | |||
354 | /* Make it visible to every other CPU */ | ||
355 | smp_mb(); | ||
356 | |||
357 | set_cpu_online(smp_processor_id(), false); | 352 | set_cpu_online(smp_processor_id(), false); |
358 | calculate_cpu_foreign_map(); | 353 | calculate_cpu_foreign_map(); |
359 | local_irq_disable(); | 354 | local_irq_disable(); |
@@ -512,10 +507,17 @@ void flush_tlb_range(struct vm_area_struct *vma, unsigned long start, unsigned l | |||
512 | smp_on_other_tlbs(flush_tlb_range_ipi, &fd); | 507 | smp_on_other_tlbs(flush_tlb_range_ipi, &fd); |
513 | } else { | 508 | } else { |
514 | unsigned int cpu; | 509 | unsigned int cpu; |
510 | int exec = vma->vm_flags & VM_EXEC; | ||
515 | 511 | ||
516 | for_each_online_cpu(cpu) { | 512 | for_each_online_cpu(cpu) { |
513 | /* | ||
514 | * flush_cache_range() will only fully flush icache if | ||
515 | * the VMA is executable, otherwise we must invalidate | ||
516 | * ASID without it appearing to has_valid_asid() as if | ||
517 | * mm has been completely unused by that CPU. | ||
518 | */ | ||
517 | if (cpu != smp_processor_id() && cpu_context(cpu, mm)) | 519 | if (cpu != smp_processor_id() && cpu_context(cpu, mm)) |
518 | cpu_context(cpu, mm) = 0; | 520 | cpu_context(cpu, mm) = !exec; |
519 | } | 521 | } |
520 | } | 522 | } |
521 | local_flush_tlb_range(vma, start, end); | 523 | local_flush_tlb_range(vma, start, end); |
@@ -560,8 +562,14 @@ void flush_tlb_page(struct vm_area_struct *vma, unsigned long page) | |||
560 | unsigned int cpu; | 562 | unsigned int cpu; |
561 | 563 | ||
562 | for_each_online_cpu(cpu) { | 564 | for_each_online_cpu(cpu) { |
565 | /* | ||
566 | * flush_cache_page() only does partial flushes, so | ||
567 | * invalidate ASID without it appearing to | ||
568 | * has_valid_asid() as if mm has been completely unused | ||
569 | * by that CPU. | ||
570 | */ | ||
563 | if (cpu != smp_processor_id() && cpu_context(cpu, vma->vm_mm)) | 571 | if (cpu != smp_processor_id() && cpu_context(cpu, vma->vm_mm)) |
564 | cpu_context(cpu, vma->vm_mm) = 0; | 572 | cpu_context(cpu, vma->vm_mm) = 1; |
565 | } | 573 | } |
566 | } | 574 | } |
567 | local_flush_tlb_page(vma, page); | 575 | local_flush_tlb_page(vma, page); |
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c index 6fb4704bd156..3de85be2486a 100644 --- a/arch/mips/kernel/traps.c +++ b/arch/mips/kernel/traps.c | |||
@@ -704,6 +704,7 @@ asmlinkage void do_ov(struct pt_regs *regs) | |||
704 | int process_fpemu_return(int sig, void __user *fault_addr, unsigned long fcr31) | 704 | int process_fpemu_return(int sig, void __user *fault_addr, unsigned long fcr31) |
705 | { | 705 | { |
706 | struct siginfo si = { 0 }; | 706 | struct siginfo si = { 0 }; |
707 | struct vm_area_struct *vma; | ||
707 | 708 | ||
708 | switch (sig) { | 709 | switch (sig) { |
709 | case 0: | 710 | case 0: |
@@ -744,7 +745,8 @@ int process_fpemu_return(int sig, void __user *fault_addr, unsigned long fcr31) | |||
744 | si.si_addr = fault_addr; | 745 | si.si_addr = fault_addr; |
745 | si.si_signo = sig; | 746 | si.si_signo = sig; |
746 | down_read(¤t->mm->mmap_sem); | 747 | down_read(¤t->mm->mmap_sem); |
747 | if (find_vma(current->mm, (unsigned long)fault_addr)) | 748 | vma = find_vma(current->mm, (unsigned long)fault_addr); |
749 | if (vma && (vma->vm_start <= (unsigned long)fault_addr)) | ||
748 | si.si_code = SEGV_ACCERR; | 750 | si.si_code = SEGV_ACCERR; |
749 | else | 751 | else |
750 | si.si_code = SEGV_MAPERR; | 752 | si.si_code = SEGV_MAPERR; |
diff --git a/arch/mips/kernel/vdso.c b/arch/mips/kernel/vdso.c index 54e1663ce639..9abe447a4b48 100644 --- a/arch/mips/kernel/vdso.c +++ b/arch/mips/kernel/vdso.c | |||
@@ -107,6 +107,16 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp) | |||
107 | if (down_write_killable(&mm->mmap_sem)) | 107 | if (down_write_killable(&mm->mmap_sem)) |
108 | return -EINTR; | 108 | return -EINTR; |
109 | 109 | ||
110 | /* Map delay slot emulation page */ | ||
111 | base = mmap_region(NULL, STACK_TOP, PAGE_SIZE, | ||
112 | VM_READ|VM_WRITE|VM_EXEC| | ||
113 | VM_MAYREAD|VM_MAYWRITE|VM_MAYEXEC, | ||
114 | 0); | ||
115 | if (IS_ERR_VALUE(base)) { | ||
116 | ret = base; | ||
117 | goto out; | ||
118 | } | ||
119 | |||
110 | /* | 120 | /* |
111 | * Determine total area size. This includes the VDSO data itself, the | 121 | * Determine total area size. This includes the VDSO data itself, the |
112 | * data page, and the GIC user page if present. Always create a mapping | 122 | * data page, and the GIC user page if present. Always create a mapping |