From 9791554b45a2acc28247f66a5fd5bbc212a6b8c8 Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Thu, 8 Jan 2015 12:17:37 +0000 Subject: MIPS,prctl: add PR_[GS]ET_FP_MODE prctl options for MIPS Userland code may be built using an ABI which permits linking to objects that have more restrictive floating point requirements. For example, userland code may be built to target the O32 FPXX ABI. Such code may be linked with other FPXX code, or code built for either one of the more restrictive FP32 or FP64. When linking with more restrictive code, the overall requirement of the process becomes that of the more restrictive code. The kernel has no way to know in advance which mode the process will need to be executed in, and indeed it may need to change during execution. The dynamic loader is the only code which will know the overall required mode, and so it needs to have a means to instruct the kernel to switch the FP mode of the process. This patch introduces 2 new options to the prctl syscall which provide such a capability. The FP mode of the process is represented as a simple bitmask combining a number of mode bits mirroring those present in the hardware. Userland can either retrieve the current FP mode of the process: mode = prctl(PR_GET_FP_MODE); or modify the current FP mode of the process: err = prctl(PR_SET_FP_MODE, new_mode); Signed-off-by: Paul Burton Cc: Matthew Fortune Cc: Markos Chandras Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/8899/ Signed-off-by: Ralf Baechle --- arch/mips/kernel/traps.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) (limited to 'arch/mips/kernel/traps.c') diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c index ad3d2031c327..d5fbfb51b9da 100644 --- a/arch/mips/kernel/traps.c +++ b/arch/mips/kernel/traps.c @@ -1134,10 +1134,29 @@ static int default_cu2_call(struct notifier_block *nfb, unsigned long action, return NOTIFY_OK; } +static int wait_on_fp_mode_switch(atomic_t *p) +{ + /* + * The FP mode for this task is currently being switched. That may + * involve modifications to the format of this tasks FP context which + * make it unsafe to proceed with execution for the moment. Instead, + * schedule some other task. + */ + schedule(); + return 0; +} + static int enable_restore_fp_context(int msa) { int err, was_fpu_owner, prior_msa; + /* + * If an FP mode switch is currently underway, wait for it to + * complete before proceeding. + */ + wait_on_atomic_t(¤t->mm->context.fp_mode_switching, + wait_on_fp_mode_switch, TASK_KILLABLE); + if (!used_math()) { /* First time FP context user. */ preempt_disable(); -- cgit v1.2.3 From 4695089f03929c8cfa58470faf6e1e041bfb285a Mon Sep 17 00:00:00 2001 From: Leonid Yegoshin Date: Mon, 24 Nov 2014 12:59:01 +0000 Subject: MIPS: Add cases for CPU_QEMU_GENERIC Add a CPU_QEMU_GENERIC case to various switch statements. Signed-off-by: Leonid Yegoshin Signed-off-by: Markos Chandras --- arch/mips/kernel/traps.c | 1 + 1 file changed, 1 insertion(+) (limited to 'arch/mips/kernel/traps.c') diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c index d5fbfb51b9da..461653ea28c8 100644 --- a/arch/mips/kernel/traps.c +++ b/arch/mips/kernel/traps.c @@ -1559,6 +1559,7 @@ static inline void parity_protection_init(void) case CPU_INTERAPTIV: case CPU_PROAPTIV: case CPU_P5600: + case CPU_QEMU_GENERIC: { #define ERRCTL_PE 0x80000000 #define ERRCTL_L2P 0x00800000 -- cgit v1.2.3 From 9c7d5768681193b3bb9f00409d689141d20d5bff Mon Sep 17 00:00:00 2001 From: Leonid Yegoshin Date: Fri, 14 Nov 2014 11:25:30 +0000 Subject: MIPS: kernel: traps: Add MIPS R6 related definitions Add MIPS R6 support to cache and ftlb exceptions, as well as to the hwrena and ebase register configuration. Signed-off-by: Leonid Yegoshin Signed-off-by: Markos Chandras --- arch/mips/kernel/traps.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'arch/mips/kernel/traps.c') diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c index 461653ea28c8..6e9d8505e128 100644 --- a/arch/mips/kernel/traps.c +++ b/arch/mips/kernel/traps.c @@ -1649,7 +1649,7 @@ asmlinkage void cache_parity_error(void) printk("Decoded c0_cacheerr: %s cache fault in %s reference.\n", reg_val & (1<<30) ? "secondary" : "primary", reg_val & (1<<31) ? "data" : "insn"); - if (cpu_has_mips_r2 && + if ((cpu_has_mips_r2_r6) && ((current_cpu_data.processor_id & 0xff0000) == PRID_COMP_MIPS)) { pr_err("Error bits: %s%s%s%s%s%s%s%s\n", reg_val & (1<<29) ? "ED " : "", @@ -1689,7 +1689,7 @@ asmlinkage void do_ftlb(void) unsigned int reg_val; /* For the moment, report the problem and hang. */ - if (cpu_has_mips_r2 && + if ((cpu_has_mips_r2_r6) && ((current_cpu_data.processor_id & 0xff0000) == PRID_COMP_MIPS)) { pr_err("FTLB error exception, cp0_ecc=0x%08x:\n", read_c0_ecc()); @@ -1978,7 +1978,7 @@ static void configure_hwrena(void) { unsigned int hwrena = cpu_hwrena_impl_bits; - if (cpu_has_mips_r2) + if (cpu_has_mips_r2_r6) hwrena |= 0x0000000f; if (!noulri && cpu_has_userlocal) @@ -2022,7 +2022,7 @@ void per_cpu_trap_init(bool is_boot_cpu) * o read IntCtl.IPTI to determine the timer interrupt * o read IntCtl.IPPCI to determine the performance counter interrupt */ - if (cpu_has_mips_r2) { + if (cpu_has_mips_r2_r6) { cp0_compare_irq_shift = CAUSEB_TI - CAUSEB_IP; cp0_compare_irq = (read_c0_intctl() >> INTCTLB_IPTI) & 7; cp0_perfcount_irq = (read_c0_intctl() >> INTCTLB_IPPCI) & 7; @@ -2113,7 +2113,7 @@ void __init trap_init(void) #else ebase = CKSEG0; #endif - if (cpu_has_mips_r2) + if (cpu_has_mips_r2_r6) ebase += (read_c0_ebase() & 0x3ffff000); } -- cgit v1.2.3 From b0a668fb2038d846a466c7a16a358d874002b697 Mon Sep 17 00:00:00 2001 From: Leonid Yegoshin Date: Wed, 3 Dec 2014 15:47:03 +0000 Subject: MIPS: kernel: mips-r2-to-r6-emul: Add R2 emulator for MIPS R6 MIPS R6 removed quite a few R2 instructions. However, there is plenty of Signed-off-by: Markos Chandras --- arch/mips/kernel/traps.c | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) (limited to 'arch/mips/kernel/traps.c') diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c index 6e9d8505e128..fc157322f609 100644 --- a/arch/mips/kernel/traps.c +++ b/arch/mips/kernel/traps.c @@ -46,6 +46,7 @@ #include #include #include +#include #include #include #include @@ -837,7 +838,7 @@ out: exception_exit(prev_state); } -static void do_trap_or_bp(struct pt_regs *regs, unsigned int code, +void do_trap_or_bp(struct pt_regs *regs, unsigned int code, const char *str) { siginfo_t info; @@ -1027,7 +1028,32 @@ asmlinkage void do_ri(struct pt_regs *regs) unsigned int opcode = 0; int status = -1; + /* + * Avoid any kernel code. Just emulate the R2 instruction + * as quickly as possible. + */ + if (mipsr2_emulation && cpu_has_mips_r6 && + likely(user_mode(regs))) { + if (likely(get_user(opcode, epc) >= 0)) { + status = mipsr2_decoder(regs, opcode); + switch (status) { + case 0: + case SIGEMT: + return; + case SIGILL: + goto no_r2_instr; + default: + process_fpemu_return(status, + ¤t->thread.cp0_baduaddr); + return; + } + } + } + +no_r2_instr: + prev_state = exception_enter(); + if (notify_die(DIE_RI, "RI Fault", regs, 0, regs_to_trapnr(regs), SIGILL) == NOTIFY_STOP) goto out; -- cgit v1.2.3 From 7c151d3d5d7a032e08dbe86ad6088622391bf13e Mon Sep 17 00:00:00 2001 From: Markos Chandras Date: Wed, 3 Dec 2014 12:37:32 +0000 Subject: MIPS: Make use of the ERETNC instruction on MIPS R6 The ERETNC instruction, introduced in MIPS R5, is similar to the ERET one, except it does not clear the LLB bit in the LLADDR register. This feature is necessary to safely emulate R2 LL/SC instructions. However, on context switches, we need to clear the LLAddr/LLB bit in order to make sure that an SC instruction from the new thread will never succeed if it happens to interrupt an LL operation on the same address from the previous thread. Signed-off-by: Markos Chandras --- arch/mips/kernel/traps.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'arch/mips/kernel/traps.c') diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c index fc157322f609..afa447e5e97f 100644 --- a/arch/mips/kernel/traps.c +++ b/arch/mips/kernel/traps.c @@ -1039,12 +1039,14 @@ asmlinkage void do_ri(struct pt_regs *regs) switch (status) { case 0: case SIGEMT: + task_thread_info(current)->r2_emul_return = 1; return; case SIGILL: goto no_r2_instr; default: process_fpemu_return(status, ¤t->thread.cp0_baduaddr); + task_thread_info(current)->r2_emul_return = 1; return; } } -- cgit v1.2.3