Commit c3fc5cd5 authored by Ralf Baechle's avatar Ralf Baechle

MIPS: Implement HAVE_CONTEXT_TRACKING.

This enables support for CONFIG_NO_HZ_FULL.
Signed-off-by: default avatarRalf Baechle <ralf@linux-mips.org>
parent e7f3b48a
config MIPS config MIPS
bool bool
default y default y
select HAVE_CONTEXT_TRACKING
select HAVE_GENERIC_DMA_COHERENT select HAVE_GENERIC_DMA_COHERENT
select HAVE_IDE select HAVE_IDE
select HAVE_OPROFILE select HAVE_OPROFILE
......
...@@ -109,6 +109,7 @@ static inline struct thread_info *current_thread_info(void) ...@@ -109,6 +109,7 @@ static inline struct thread_info *current_thread_info(void)
#define TIF_RESTORE_SIGMASK 9 /* restore signal mask in do_signal() */ #define TIF_RESTORE_SIGMASK 9 /* restore signal mask in do_signal() */
#define TIF_USEDFPU 16 /* FPU was used by this task this quantum (SMP) */ #define TIF_USEDFPU 16 /* FPU was used by this task this quantum (SMP) */
#define TIF_MEMDIE 18 /* is terminating due to OOM killer */ #define TIF_MEMDIE 18 /* is terminating due to OOM killer */
#define TIF_NOHZ 19 /* in adaptive nohz mode */
#define TIF_FIXADE 20 /* Fix address errors in software */ #define TIF_FIXADE 20 /* Fix address errors in software */
#define TIF_LOGADE 21 /* Log address errors to syslog */ #define TIF_LOGADE 21 /* Log address errors to syslog */
#define TIF_32BIT_REGS 22 /* also implies 16/32 fprs */ #define TIF_32BIT_REGS 22 /* also implies 16/32 fprs */
...@@ -124,6 +125,7 @@ static inline struct thread_info *current_thread_info(void) ...@@ -124,6 +125,7 @@ static inline struct thread_info *current_thread_info(void)
#define _TIF_SECCOMP (1<<TIF_SECCOMP) #define _TIF_SECCOMP (1<<TIF_SECCOMP)
#define _TIF_NOTIFY_RESUME (1<<TIF_NOTIFY_RESUME) #define _TIF_NOTIFY_RESUME (1<<TIF_NOTIFY_RESUME)
#define _TIF_USEDFPU (1<<TIF_USEDFPU) #define _TIF_USEDFPU (1<<TIF_USEDFPU)
#define _TIF_NOHZ (1<<TIF_NOHZ)
#define _TIF_FIXADE (1<<TIF_FIXADE) #define _TIF_FIXADE (1<<TIF_FIXADE)
#define _TIF_LOGADE (1<<TIF_LOGADE) #define _TIF_LOGADE (1<<TIF_LOGADE)
#define _TIF_32BIT_REGS (1<<TIF_32BIT_REGS) #define _TIF_32BIT_REGS (1<<TIF_32BIT_REGS)
...@@ -131,16 +133,19 @@ static inline struct thread_info *current_thread_info(void) ...@@ -131,16 +133,19 @@ static inline struct thread_info *current_thread_info(void)
#define _TIF_FPUBOUND (1<<TIF_FPUBOUND) #define _TIF_FPUBOUND (1<<TIF_FPUBOUND)
#define _TIF_LOAD_WATCH (1<<TIF_LOAD_WATCH) #define _TIF_LOAD_WATCH (1<<TIF_LOAD_WATCH)
#define _TIF_WORK_SYSCALL_ENTRY (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT) #define _TIF_WORK_SYSCALL_ENTRY (_TIF_NOHZ | _TIF_SYSCALL_TRACE | \
_TIF_SYSCALL_AUDIT)
/* work to do in syscall_trace_leave() */ /* work to do in syscall_trace_leave() */
#define _TIF_WORK_SYSCALL_EXIT (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT) #define _TIF_WORK_SYSCALL_EXIT (_TIF_NOHZ | _TIF_SYSCALL_TRACE | \
_TIF_SYSCALL_AUDIT)
/* work to do on interrupt/exception return */ /* work to do on interrupt/exception return */
#define _TIF_WORK_MASK \ #define _TIF_WORK_MASK \
(_TIF_SIGPENDING | _TIF_NEED_RESCHED | _TIF_NOTIFY_RESUME) (_TIF_SIGPENDING | _TIF_NEED_RESCHED | _TIF_NOTIFY_RESUME)
/* work to do on any return to u-space */ /* work to do on any return to u-space */
#define _TIF_ALLWORK_MASK (_TIF_WORK_MASK | _TIF_WORK_SYSCALL_EXIT) #define _TIF_ALLWORK_MASK (_TIF_NOHZ | _TIF_WORK_MASK | \
_TIF_WORK_SYSCALL_EXIT)
#endif /* __KERNEL__ */ #endif /* __KERNEL__ */
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
* as published by the Free Software Foundation; either version * as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version. * 2 of the License, or (at your option) any later version.
*/ */
#include <linux/context_tracking.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/ptrace.h> #include <linux/ptrace.h>
...@@ -171,8 +172,12 @@ static volatile int daddi_ov __cpuinitdata; ...@@ -171,8 +172,12 @@ static volatile int daddi_ov __cpuinitdata;
asmlinkage void __init do_daddi_ov(struct pt_regs *regs) asmlinkage void __init do_daddi_ov(struct pt_regs *regs)
{ {
enum ctx_state prev_state;
prev_state = exception_enter();
daddi_ov = 1; daddi_ov = 1;
regs->cp0_epc += 4; regs->cp0_epc += 4;
exception_exit(prev_state);
} }
static inline void check_daddi(void) static inline void check_daddi(void)
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
* binaries. * binaries.
*/ */
#include <linux/compiler.h> #include <linux/compiler.h>
#include <linux/context_tracking.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/mm.h> #include <linux/mm.h>
...@@ -534,6 +535,8 @@ static inline int audit_arch(void) ...@@ -534,6 +535,8 @@ static inline int audit_arch(void)
*/ */
asmlinkage void syscall_trace_enter(struct pt_regs *regs) asmlinkage void syscall_trace_enter(struct pt_regs *regs)
{ {
user_exit();
/* do the secure computing check first */ /* do the secure computing check first */
secure_computing_strict(regs->regs[2]); secure_computing_strict(regs->regs[2]);
...@@ -570,6 +573,13 @@ asmlinkage void syscall_trace_enter(struct pt_regs *regs) ...@@ -570,6 +573,13 @@ asmlinkage void syscall_trace_enter(struct pt_regs *regs)
*/ */
asmlinkage void syscall_trace_leave(struct pt_regs *regs) asmlinkage void syscall_trace_leave(struct pt_regs *regs)
{ {
/*
* We may come here right after calling schedule_user()
* or do_notify_resume(), in which case we can be in RCU
* user mode.
*/
user_exit();
audit_syscall_exit(regs); audit_syscall_exit(regs);
if (!(current->ptrace & PT_PTRACED)) if (!(current->ptrace & PT_PTRACED))
...@@ -592,4 +602,6 @@ asmlinkage void syscall_trace_leave(struct pt_regs *regs) ...@@ -592,4 +602,6 @@ asmlinkage void syscall_trace_leave(struct pt_regs *regs)
send_sig(current->exit_code, current, 1); send_sig(current->exit_code, current, 1);
current->exit_code = 0; current->exit_code = 0;
} }
user_enter();
} }
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
* Copyright (C) 1999, 2000 Silicon Graphics, Inc. * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
*/ */
#include <linux/cache.h> #include <linux/cache.h>
#include <linux/context_tracking.h>
#include <linux/irqflags.h> #include <linux/irqflags.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/mm.h> #include <linux/mm.h>
...@@ -573,6 +574,8 @@ asmlinkage void do_notify_resume(struct pt_regs *regs, void *unused, ...@@ -573,6 +574,8 @@ asmlinkage void do_notify_resume(struct pt_regs *regs, void *unused,
{ {
local_irq_enable(); local_irq_enable();
user_exit();
/* deal with pending signal delivery */ /* deal with pending signal delivery */
if (thread_info_flags & _TIF_SIGPENDING) if (thread_info_flags & _TIF_SIGPENDING)
do_signal(regs); do_signal(regs);
...@@ -581,6 +584,8 @@ asmlinkage void do_notify_resume(struct pt_regs *regs, void *unused, ...@@ -581,6 +584,8 @@ asmlinkage void do_notify_resume(struct pt_regs *regs, void *unused,
clear_thread_flag(TIF_NOTIFY_RESUME); clear_thread_flag(TIF_NOTIFY_RESUME);
tracehook_notify_resume(regs); tracehook_notify_resume(regs);
} }
user_enter();
} }
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
*/ */
#include <linux/bug.h> #include <linux/bug.h>
#include <linux/compiler.h> #include <linux/compiler.h>
#include <linux/context_tracking.h>
#include <linux/kexec.h> #include <linux/kexec.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/kernel.h> #include <linux/kernel.h>
...@@ -423,7 +424,9 @@ asmlinkage void do_be(struct pt_regs *regs) ...@@ -423,7 +424,9 @@ asmlinkage void do_be(struct pt_regs *regs)
const struct exception_table_entry *fixup = NULL; const struct exception_table_entry *fixup = NULL;
int data = regs->cp0_cause & 4; int data = regs->cp0_cause & 4;
int action = MIPS_BE_FATAL; int action = MIPS_BE_FATAL;
enum ctx_state prev_state;
prev_state = exception_enter();
/* XXX For now. Fixme, this searches the wrong table ... */ /* XXX For now. Fixme, this searches the wrong table ... */
if (data && !user_mode(regs)) if (data && !user_mode(regs))
fixup = search_dbe_tables(exception_epc(regs)); fixup = search_dbe_tables(exception_epc(regs));
...@@ -436,11 +439,11 @@ asmlinkage void do_be(struct pt_regs *regs) ...@@ -436,11 +439,11 @@ asmlinkage void do_be(struct pt_regs *regs)
switch (action) { switch (action) {
case MIPS_BE_DISCARD: case MIPS_BE_DISCARD:
return; goto out;
case MIPS_BE_FIXUP: case MIPS_BE_FIXUP:
if (fixup) { if (fixup) {
regs->cp0_epc = fixup->nextinsn; regs->cp0_epc = fixup->nextinsn;
return; goto out;
} }
break; break;
default: default:
...@@ -455,10 +458,13 @@ asmlinkage void do_be(struct pt_regs *regs) ...@@ -455,10 +458,13 @@ asmlinkage void do_be(struct pt_regs *regs)
field, regs->cp0_epc, field, regs->regs[31]); field, regs->cp0_epc, field, regs->regs[31]);
if (notify_die(DIE_OOPS, "bus error", regs, 0, regs_to_trapnr(regs), SIGBUS) if (notify_die(DIE_OOPS, "bus error", regs, 0, regs_to_trapnr(regs), SIGBUS)
== NOTIFY_STOP) == NOTIFY_STOP)
return; goto out;
die_if_kernel("Oops", regs); die_if_kernel("Oops", regs);
force_sig(SIGBUS, current); force_sig(SIGBUS, current);
out:
exception_exit(prev_state);
} }
/* /*
...@@ -673,8 +679,10 @@ static int simulate_sync(struct pt_regs *regs, unsigned int opcode) ...@@ -673,8 +679,10 @@ static int simulate_sync(struct pt_regs *regs, unsigned int opcode)
asmlinkage void do_ov(struct pt_regs *regs) asmlinkage void do_ov(struct pt_regs *regs)
{ {
enum ctx_state prev_state;
siginfo_t info; siginfo_t info;
prev_state = exception_enter();
die_if_kernel("Integer overflow", regs); die_if_kernel("Integer overflow", regs);
info.si_code = FPE_INTOVF; info.si_code = FPE_INTOVF;
...@@ -682,6 +690,7 @@ asmlinkage void do_ov(struct pt_regs *regs) ...@@ -682,6 +690,7 @@ asmlinkage void do_ov(struct pt_regs *regs)
info.si_errno = 0; info.si_errno = 0;
info.si_addr = (void __user *) regs->cp0_epc; info.si_addr = (void __user *) regs->cp0_epc;
force_sig_info(SIGFPE, &info, current); force_sig_info(SIGFPE, &info, current);
exception_exit(prev_state);
} }
int process_fpemu_return(int sig, void __user *fault_addr) int process_fpemu_return(int sig, void __user *fault_addr)
...@@ -713,11 +722,13 @@ int process_fpemu_return(int sig, void __user *fault_addr) ...@@ -713,11 +722,13 @@ int process_fpemu_return(int sig, void __user *fault_addr)
*/ */
asmlinkage void do_fpe(struct pt_regs *regs, unsigned long fcr31) asmlinkage void do_fpe(struct pt_regs *regs, unsigned long fcr31)
{ {
enum ctx_state prev_state;
siginfo_t info = {0}; siginfo_t info = {0};
prev_state = exception_enter();
if (notify_die(DIE_FP, "FP exception", regs, 0, regs_to_trapnr(regs), SIGFPE) if (notify_die(DIE_FP, "FP exception", regs, 0, regs_to_trapnr(regs), SIGFPE)
== NOTIFY_STOP) == NOTIFY_STOP)
return; goto out;
die_if_kernel("FP exception in kernel code", regs); die_if_kernel("FP exception in kernel code", regs);
if (fcr31 & FPU_CSR_UNI_X) { if (fcr31 & FPU_CSR_UNI_X) {
...@@ -753,7 +764,7 @@ asmlinkage void do_fpe(struct pt_regs *regs, unsigned long fcr31) ...@@ -753,7 +764,7 @@ asmlinkage void do_fpe(struct pt_regs *regs, unsigned long fcr31)
/* If something went wrong, signal */ /* If something went wrong, signal */
process_fpemu_return(sig, fault_addr); process_fpemu_return(sig, fault_addr);
return; goto out;
} else if (fcr31 & FPU_CSR_INV_X) } else if (fcr31 & FPU_CSR_INV_X)
info.si_code = FPE_FLTINV; info.si_code = FPE_FLTINV;
else if (fcr31 & FPU_CSR_DIV_X) else if (fcr31 & FPU_CSR_DIV_X)
...@@ -770,6 +781,9 @@ asmlinkage void do_fpe(struct pt_regs *regs, unsigned long fcr31) ...@@ -770,6 +781,9 @@ asmlinkage void do_fpe(struct pt_regs *regs, unsigned long fcr31)
info.si_errno = 0; info.si_errno = 0;
info.si_addr = (void __user *) regs->cp0_epc; info.si_addr = (void __user *) regs->cp0_epc;
force_sig_info(SIGFPE, &info, current); force_sig_info(SIGFPE, &info, current);
out:
exception_exit(prev_state);
} }
static void do_trap_or_bp(struct pt_regs *regs, unsigned int code, static void do_trap_or_bp(struct pt_regs *regs, unsigned int code,
...@@ -835,9 +849,11 @@ static void do_trap_or_bp(struct pt_regs *regs, unsigned int code, ...@@ -835,9 +849,11 @@ static void do_trap_or_bp(struct pt_regs *regs, unsigned int code,
asmlinkage void do_bp(struct pt_regs *regs) asmlinkage void do_bp(struct pt_regs *regs)
{ {
unsigned int opcode, bcode; unsigned int opcode, bcode;
enum ctx_state prev_state;
unsigned long epc; unsigned long epc;
u16 instr[2]; u16 instr[2];
prev_state = exception_enter();
if (get_isa16_mode(regs->cp0_epc)) { if (get_isa16_mode(regs->cp0_epc)) {
/* Calculate EPC. */ /* Calculate EPC. */
epc = exception_epc(regs); epc = exception_epc(regs);
...@@ -852,7 +868,7 @@ asmlinkage void do_bp(struct pt_regs *regs) ...@@ -852,7 +868,7 @@ asmlinkage void do_bp(struct pt_regs *regs)
goto out_sigsegv; goto out_sigsegv;
bcode = (instr[0] >> 6) & 0x3f; bcode = (instr[0] >> 6) & 0x3f;
do_trap_or_bp(regs, bcode, "Break"); do_trap_or_bp(regs, bcode, "Break");
return; goto out;
} }
} else { } else {
if (__get_user(opcode, (unsigned int __user *) exception_epc(regs))) if (__get_user(opcode, (unsigned int __user *) exception_epc(regs)))
...@@ -876,12 +892,12 @@ asmlinkage void do_bp(struct pt_regs *regs) ...@@ -876,12 +892,12 @@ asmlinkage void do_bp(struct pt_regs *regs)
switch (bcode) { switch (bcode) {
case BRK_KPROBE_BP: case BRK_KPROBE_BP:
if (notify_die(DIE_BREAK, "debug", regs, bcode, regs_to_trapnr(regs), SIGTRAP) == NOTIFY_STOP) if (notify_die(DIE_BREAK, "debug", regs, bcode, regs_to_trapnr(regs), SIGTRAP) == NOTIFY_STOP)
return; goto out;
else else
break; break;
case BRK_KPROBE_SSTEPBP: case BRK_KPROBE_SSTEPBP:
if (notify_die(DIE_SSTEPBP, "single_step", regs, bcode, regs_to_trapnr(regs), SIGTRAP) == NOTIFY_STOP) if (notify_die(DIE_SSTEPBP, "single_step", regs, bcode, regs_to_trapnr(regs), SIGTRAP) == NOTIFY_STOP)
return; goto out;
else else
break; break;
default: default:
...@@ -889,18 +905,24 @@ asmlinkage void do_bp(struct pt_regs *regs) ...@@ -889,18 +905,24 @@ asmlinkage void do_bp(struct pt_regs *regs)
} }
do_trap_or_bp(regs, bcode, "Break"); do_trap_or_bp(regs, bcode, "Break");
out:
exception_exit(prev_state);
return; return;
out_sigsegv: out_sigsegv:
force_sig(SIGSEGV, current); force_sig(SIGSEGV, current);
goto out;
} }
asmlinkage void do_tr(struct pt_regs *regs) asmlinkage void do_tr(struct pt_regs *regs)
{ {
u32 opcode, tcode = 0; u32 opcode, tcode = 0;
enum ctx_state prev_state;
u16 instr[2]; u16 instr[2];
unsigned long epc = msk_isa16_mode(exception_epc(regs)); unsigned long epc = msk_isa16_mode(exception_epc(regs));
prev_state = exception_enter();
if (get_isa16_mode(regs->cp0_epc)) { if (get_isa16_mode(regs->cp0_epc)) {
if (__get_user(instr[0], (u16 __user *)(epc + 0)) || if (__get_user(instr[0], (u16 __user *)(epc + 0)) ||
__get_user(instr[1], (u16 __user *)(epc + 2))) __get_user(instr[1], (u16 __user *)(epc + 2)))
...@@ -918,10 +940,14 @@ asmlinkage void do_tr(struct pt_regs *regs) ...@@ -918,10 +940,14 @@ asmlinkage void do_tr(struct pt_regs *regs)
} }
do_trap_or_bp(regs, tcode, "Trap"); do_trap_or_bp(regs, tcode, "Trap");
out:
exception_exit(prev_state);
return; return;
out_sigsegv: out_sigsegv:
force_sig(SIGSEGV, current); force_sig(SIGSEGV, current);
goto out;
} }
asmlinkage void do_ri(struct pt_regs *regs) asmlinkage void do_ri(struct pt_regs *regs)
...@@ -929,17 +955,19 @@ asmlinkage void do_ri(struct pt_regs *regs) ...@@ -929,17 +955,19 @@ asmlinkage void do_ri(struct pt_regs *regs)
unsigned int __user *epc = (unsigned int __user *)exception_epc(regs); unsigned int __user *epc = (unsigned int __user *)exception_epc(regs);
unsigned long old_epc = regs->cp0_epc; unsigned long old_epc = regs->cp0_epc;
unsigned long old31 = regs->regs[31]; unsigned long old31 = regs->regs[31];
enum ctx_state prev_state;
unsigned int opcode = 0; unsigned int opcode = 0;
int status = -1; int status = -1;
prev_state = exception_enter();
if (notify_die(DIE_RI, "RI Fault", regs, 0, regs_to_trapnr(regs), SIGILL) if (notify_die(DIE_RI, "RI Fault", regs, 0, regs_to_trapnr(regs), SIGILL)
== NOTIFY_STOP) == NOTIFY_STOP)
return; goto out;
die_if_kernel("Reserved instruction in kernel code", regs); die_if_kernel("Reserved instruction in kernel code", regs);
if (unlikely(compute_return_epc(regs) < 0)) if (unlikely(compute_return_epc(regs) < 0))
return; goto out;
if (get_isa16_mode(regs->cp0_epc)) { if (get_isa16_mode(regs->cp0_epc)) {
unsigned short mmop[2] = { 0 }; unsigned short mmop[2] = { 0 };
...@@ -974,6 +1002,9 @@ asmlinkage void do_ri(struct pt_regs *regs) ...@@ -974,6 +1002,9 @@ asmlinkage void do_ri(struct pt_regs *regs)
regs->regs[31] = old31; regs->regs[31] = old31;
force_sig(status, current); force_sig(status, current);
} }
out:
exception_exit(prev_state);
} }
/* /*
...@@ -1040,6 +1071,7 @@ static int default_cu2_call(struct notifier_block *nfb, unsigned long action, ...@@ -1040,6 +1071,7 @@ static int default_cu2_call(struct notifier_block *nfb, unsigned long action,
asmlinkage void do_cpu(struct pt_regs *regs) asmlinkage void do_cpu(struct pt_regs *regs)
{ {
enum ctx_state prev_state;
unsigned int __user *epc; unsigned int __user *epc;
unsigned long old_epc, old31; unsigned long old_epc, old31;
unsigned int opcode; unsigned int opcode;
...@@ -1047,6 +1079,7 @@ asmlinkage void do_cpu(struct pt_regs *regs) ...@@ -1047,6 +1079,7 @@ asmlinkage void do_cpu(struct pt_regs *regs)
int status; int status;
unsigned long __maybe_unused flags; unsigned long __maybe_unused flags;
prev_state = exception_enter();
die_if_kernel("do_cpu invoked from kernel context!", regs); die_if_kernel("do_cpu invoked from kernel context!", regs);
cpid = (regs->cp0_cause >> CAUSEB_CE) & 3; cpid = (regs->cp0_cause >> CAUSEB_CE) & 3;
...@@ -1060,7 +1093,7 @@ asmlinkage void do_cpu(struct pt_regs *regs) ...@@ -1060,7 +1093,7 @@ asmlinkage void do_cpu(struct pt_regs *regs)
status = -1; status = -1;
if (unlikely(compute_return_epc(regs) < 0)) if (unlikely(compute_return_epc(regs) < 0))
return; goto out;
if (get_isa16_mode(regs->cp0_epc)) { if (get_isa16_mode(regs->cp0_epc)) {
unsigned short mmop[2] = { 0 }; unsigned short mmop[2] = { 0 };
...@@ -1093,7 +1126,7 @@ asmlinkage void do_cpu(struct pt_regs *regs) ...@@ -1093,7 +1126,7 @@ asmlinkage void do_cpu(struct pt_regs *regs)
force_sig(status, current); force_sig(status, current);
} }
return; goto out;
case 3: case 3:
/* /*
...@@ -1131,19 +1164,26 @@ asmlinkage void do_cpu(struct pt_regs *regs) ...@@ -1131,19 +1164,26 @@ asmlinkage void do_cpu(struct pt_regs *regs)
mt_ase_fp_affinity(); mt_ase_fp_affinity();
} }
return; goto out;
case 2: case 2:
raw_notifier_call_chain(&cu2_chain, CU2_EXCEPTION, regs); raw_notifier_call_chain(&cu2_chain, CU2_EXCEPTION, regs);
return; goto out;
} }
force_sig(SIGILL, current); force_sig(SIGILL, current);
out:
exception_exit(prev_state);
} }
asmlinkage void do_mdmx(struct pt_regs *regs) asmlinkage void do_mdmx(struct pt_regs *regs)
{ {
enum ctx_state prev_state;
prev_state = exception_enter();
force_sig(SIGILL, current); force_sig(SIGILL, current);
exception_exit(prev_state);
} }
/* /*
...@@ -1151,8 +1191,10 @@ asmlinkage void do_mdmx(struct pt_regs *regs) ...@@ -1151,8 +1191,10 @@ asmlinkage void do_mdmx(struct pt_regs *regs)
*/ */
asmlinkage void do_watch(struct pt_regs *regs) asmlinkage void do_watch(struct pt_regs *regs)
{ {
enum ctx_state prev_state;
u32 cause; u32 cause;
prev_state = exception_enter();
/* /*
* Clear WP (bit 22) bit of cause register so we don't loop * Clear WP (bit 22) bit of cause register so we don't loop
* forever. * forever.
...@@ -1174,13 +1216,16 @@ asmlinkage void do_watch(struct pt_regs *regs) ...@@ -1174,13 +1216,16 @@ asmlinkage void do_watch(struct pt_regs *regs)
mips_clear_watch_registers(); mips_clear_watch_registers();
local_irq_enable(); local_irq_enable();
} }
exception_exit(prev_state);
} }
asmlinkage void do_mcheck(struct pt_regs *regs) asmlinkage void do_mcheck(struct pt_regs *regs)
{ {
const int field = 2 * sizeof(unsigned long); const int field = 2 * sizeof(unsigned long);
int multi_match = regs->cp0_status & ST0_TS; int multi_match = regs->cp0_status & ST0_TS;
enum ctx_state prev_state;
prev_state = exception_enter();
show_regs(regs); show_regs(regs);
if (multi_match) { if (multi_match) {
...@@ -1202,6 +1247,7 @@ asmlinkage void do_mcheck(struct pt_regs *regs) ...@@ -1202,6 +1247,7 @@ asmlinkage void do_mcheck(struct pt_regs *regs)
panic("Caught Machine Check exception - %scaused by multiple " panic("Caught Machine Check exception - %scaused by multiple "
"matching entries in the TLB.", "matching entries in the TLB.",
(multi_match) ? "" : "not "); (multi_match) ? "" : "not ");
exception_exit(prev_state);
} }
asmlinkage void do_mt(struct pt_regs *regs) asmlinkage void do_mt(struct pt_regs *regs)
......
...@@ -72,6 +72,7 @@ ...@@ -72,6 +72,7 @@
* A store crossing a page boundary might be executed only partially. * A store crossing a page boundary might be executed only partially.
* Undo the partial store in this case. * Undo the partial store in this case.
*/ */
#include <linux/context_tracking.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/signal.h> #include <linux/signal.h>
#include <linux/smp.h> #include <linux/smp.h>
...@@ -1550,9 +1551,11 @@ static void emulate_load_store_MIPS16e(struct pt_regs *regs, void __user * addr) ...@@ -1550,9 +1551,11 @@ static void emulate_load_store_MIPS16e(struct pt_regs *regs, void __user * addr)
} }
asmlinkage void do_ade(struct pt_regs *regs) asmlinkage void do_ade(struct pt_regs *regs)
{ {
enum ctx_state prev_state;
unsigned int __user *pc; unsigned int __user *pc;
mm_segment_t seg; mm_segment_t seg;
prev_state = exception_enter();
perf_sw_event(PERF_COUNT_SW_ALIGNMENT_FAULTS, perf_sw_event(PERF_COUNT_SW_ALIGNMENT_FAULTS,
1, regs, regs->cp0_badvaddr); 1, regs, regs->cp0_badvaddr);
/* /*
...@@ -1628,6 +1631,7 @@ asmlinkage void do_ade(struct pt_regs *regs) ...@@ -1628,6 +1631,7 @@ asmlinkage void do_ade(struct pt_regs *regs)
/* /*
* XXX On return from the signal handler we should advance the epc * XXX On return from the signal handler we should advance the epc
*/ */
exception_exit(prev_state);
} }
#ifdef CONFIG_DEBUG_FS #ifdef CONFIG_DEBUG_FS
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
* *
* Copyright (C) 1995 - 2000 by Ralf Baechle * Copyright (C) 1995 - 2000 by Ralf Baechle
*/ */
#include <linux/context_tracking.h>
#include <linux/signal.h> #include <linux/signal.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
...@@ -32,8 +33,8 @@ ...@@ -32,8 +33,8 @@
* and the problem, and then passes it off to one of the appropriate * and the problem, and then passes it off to one of the appropriate
* routines. * routines.
*/ */
asmlinkage void __kprobes do_page_fault(struct pt_regs *regs, unsigned long write, static void __kprobes __do_page_fault(struct pt_regs *regs, unsigned long write,
unsigned long address) unsigned long address)
{ {
struct vm_area_struct * vma = NULL; struct vm_area_struct * vma = NULL;
struct task_struct *tsk = current; struct task_struct *tsk = current;
...@@ -312,3 +313,13 @@ asmlinkage void __kprobes do_page_fault(struct pt_regs *regs, unsigned long writ ...@@ -312,3 +313,13 @@ asmlinkage void __kprobes do_page_fault(struct pt_regs *regs, unsigned long writ
} }
#endif #endif
} }
asmlinkage void __kprobes do_page_fault(struct pt_regs *regs,
unsigned long write, unsigned long address)
{
enum ctx_state prev_state;
prev_state = exception_enter();
__do_page_fault(regs, write, address);
exception_exit(prev_state);
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment