You've already forked linux-rockchip
mirror of
https://github.com/armbian/linux-rockchip.git
synced 2026-01-06 11:08:10 -08:00
MIPS: uaccess: Remove get_fs/set_fs call sites
Use new helpers to access user/kernel for functions, which are used with user/kernel pointers. Instead of dealing with get_fs/set_fs select user/kernel access via parameter. Signed-off-by: Thomas Bogendoerfer <tsbogend@alpha.franken.de> Reviewed-by: Christoph Hellwig <hch@lst.de>
This commit is contained in:
18
arch/mips/kernel/access-helper.h
Normal file
18
arch/mips/kernel/access-helper.h
Normal file
@@ -0,0 +1,18 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
|
||||
#include <linux/uaccess.h>
|
||||
|
||||
static inline int __get_addr(unsigned long *a, unsigned long *p, bool user)
|
||||
{
|
||||
return user ? get_user(*a, p) : get_kernel_nofault(*a, p);
|
||||
}
|
||||
|
||||
static inline int __get_inst16(u16 *i, u16 *p, bool user)
|
||||
{
|
||||
return user ? get_user(*i, p) : get_kernel_nofault(*i, p);
|
||||
}
|
||||
|
||||
static inline int __get_inst32(u32 *i, u32 *p, bool user)
|
||||
{
|
||||
return user ? get_user(*i, p) : get_kernel_nofault(*i, p);
|
||||
}
|
||||
@@ -72,6 +72,8 @@
|
||||
|
||||
#include <asm/mach-loongson64/cpucfg-emul.h>
|
||||
|
||||
#include "access-helper.h"
|
||||
|
||||
extern void check_wait(void);
|
||||
extern asmlinkage void rollback_handle_int(void);
|
||||
extern asmlinkage void handle_int(void);
|
||||
@@ -108,7 +110,8 @@ void (*board_bind_eic_interrupt)(int irq, int regset);
|
||||
void (*board_ebase_setup)(void);
|
||||
void(*board_cache_error_setup)(void);
|
||||
|
||||
static void show_raw_backtrace(unsigned long reg29, const char *loglvl)
|
||||
static void show_raw_backtrace(unsigned long reg29, const char *loglvl,
|
||||
bool user)
|
||||
{
|
||||
unsigned long *sp = (unsigned long *)(reg29 & ~3);
|
||||
unsigned long addr;
|
||||
@@ -118,9 +121,7 @@ static void show_raw_backtrace(unsigned long reg29, const char *loglvl)
|
||||
printk("%s\n", loglvl);
|
||||
#endif
|
||||
while (!kstack_end(sp)) {
|
||||
unsigned long __user *p =
|
||||
(unsigned long __user *)(unsigned long)sp++;
|
||||
if (__get_user(addr, p)) {
|
||||
if (__get_addr(&addr, sp++, user)) {
|
||||
printk("%s (Bad stack address)", loglvl);
|
||||
break;
|
||||
}
|
||||
@@ -141,7 +142,7 @@ __setup("raw_show_trace", set_raw_show_trace);
|
||||
#endif
|
||||
|
||||
static void show_backtrace(struct task_struct *task, const struct pt_regs *regs,
|
||||
const char *loglvl)
|
||||
const char *loglvl, bool user)
|
||||
{
|
||||
unsigned long sp = regs->regs[29];
|
||||
unsigned long ra = regs->regs[31];
|
||||
@@ -151,7 +152,7 @@ static void show_backtrace(struct task_struct *task, const struct pt_regs *regs,
|
||||
task = current;
|
||||
|
||||
if (raw_show_trace || user_mode(regs) || !__kernel_text_address(pc)) {
|
||||
show_raw_backtrace(sp, loglvl);
|
||||
show_raw_backtrace(sp, loglvl, user);
|
||||
return;
|
||||
}
|
||||
printk("%sCall Trace:\n", loglvl);
|
||||
@@ -167,12 +168,12 @@ static void show_backtrace(struct task_struct *task, const struct pt_regs *regs,
|
||||
* with at least a bit of error checking ...
|
||||
*/
|
||||
static void show_stacktrace(struct task_struct *task,
|
||||
const struct pt_regs *regs, const char *loglvl)
|
||||
const struct pt_regs *regs, const char *loglvl, bool user)
|
||||
{
|
||||
const int field = 2 * sizeof(unsigned long);
|
||||
long stackdata;
|
||||
unsigned long stackdata;
|
||||
int i;
|
||||
unsigned long __user *sp = (unsigned long __user *)regs->regs[29];
|
||||
unsigned long *sp = (unsigned long *)regs->regs[29];
|
||||
|
||||
printk("%sStack :", loglvl);
|
||||
i = 0;
|
||||
@@ -186,7 +187,7 @@ static void show_stacktrace(struct task_struct *task,
|
||||
break;
|
||||
}
|
||||
|
||||
if (__get_user(stackdata, sp++)) {
|
||||
if (__get_addr(&stackdata, sp++, user)) {
|
||||
pr_cont(" (Bad stack address)");
|
||||
break;
|
||||
}
|
||||
@@ -195,13 +196,12 @@ static void show_stacktrace(struct task_struct *task,
|
||||
i++;
|
||||
}
|
||||
pr_cont("\n");
|
||||
show_backtrace(task, regs, loglvl);
|
||||
show_backtrace(task, regs, loglvl, user);
|
||||
}
|
||||
|
||||
void show_stack(struct task_struct *task, unsigned long *sp, const char *loglvl)
|
||||
{
|
||||
struct pt_regs regs;
|
||||
mm_segment_t old_fs = get_fs();
|
||||
|
||||
regs.cp0_status = KSU_KERNEL;
|
||||
if (sp) {
|
||||
@@ -217,33 +217,41 @@ void show_stack(struct task_struct *task, unsigned long *sp, const char *loglvl)
|
||||
prepare_frametrace(®s);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* show_stack() deals exclusively with kernel mode, so be sure to access
|
||||
* the stack in the kernel (not user) address space.
|
||||
*/
|
||||
set_fs(KERNEL_DS);
|
||||
show_stacktrace(task, ®s, loglvl);
|
||||
set_fs(old_fs);
|
||||
show_stacktrace(task, ®s, loglvl, false);
|
||||
}
|
||||
|
||||
static void show_code(unsigned int __user *pc)
|
||||
static void show_code(void *pc, bool user)
|
||||
{
|
||||
long i;
|
||||
unsigned short __user *pc16 = NULL;
|
||||
unsigned short *pc16 = NULL;
|
||||
|
||||
printk("Code:");
|
||||
|
||||
if ((unsigned long)pc & 1)
|
||||
pc16 = (unsigned short __user *)((unsigned long)pc & ~1);
|
||||
pc16 = (u16 *)((unsigned long)pc & ~1);
|
||||
|
||||
for(i = -3 ; i < 6 ; i++) {
|
||||
unsigned int insn;
|
||||
if (pc16 ? __get_user(insn, pc16 + i) : __get_user(insn, pc + i)) {
|
||||
pr_cont(" (Bad address in epc)\n");
|
||||
break;
|
||||
if (pc16) {
|
||||
u16 insn16;
|
||||
|
||||
if (__get_inst16(&insn16, pc16 + i, user))
|
||||
goto bad_address;
|
||||
|
||||
pr_cont("%c%04x%c", (i?' ':'<'), insn16, (i?' ':'>'));
|
||||
} else {
|
||||
u32 insn32;
|
||||
|
||||
if (__get_inst32(&insn32, (u32 *)pc + i, user))
|
||||
goto bad_address;
|
||||
|
||||
pr_cont("%c%08x%c", (i?' ':'<'), insn32, (i?' ':'>'));
|
||||
}
|
||||
pr_cont("%c%0*x%c", (i?' ':'<'), pc16 ? 4 : 8, insn, (i?' ':'>'));
|
||||
}
|
||||
pr_cont("\n");
|
||||
return;
|
||||
|
||||
bad_address:
|
||||
pr_cont(" (Bad address in epc)\n\n");
|
||||
}
|
||||
|
||||
static void __show_regs(const struct pt_regs *regs)
|
||||
@@ -356,7 +364,6 @@ void show_regs(struct pt_regs *regs)
|
||||
void show_registers(struct pt_regs *regs)
|
||||
{
|
||||
const int field = 2 * sizeof(unsigned long);
|
||||
mm_segment_t old_fs = get_fs();
|
||||
|
||||
__show_regs(regs);
|
||||
print_modules();
|
||||
@@ -371,13 +378,9 @@ void show_registers(struct pt_regs *regs)
|
||||
printk("*HwTLS: %0*lx\n", field, tls);
|
||||
}
|
||||
|
||||
if (!user_mode(regs))
|
||||
/* Necessary for getting the correct stack content */
|
||||
set_fs(KERNEL_DS);
|
||||
show_stacktrace(current, regs, KERN_DEFAULT);
|
||||
show_code((unsigned int __user *) regs->cp0_epc);
|
||||
show_stacktrace(current, regs, KERN_DEFAULT, user_mode(regs));
|
||||
show_code((void *)regs->cp0_epc, user_mode(regs));
|
||||
printk("\n");
|
||||
set_fs(old_fs);
|
||||
}
|
||||
|
||||
static DEFINE_RAW_SPINLOCK(die_lock);
|
||||
@@ -1022,18 +1025,14 @@ asmlinkage void do_bp(struct pt_regs *regs)
|
||||
unsigned long epc = msk_isa16_mode(exception_epc(regs));
|
||||
unsigned int opcode, bcode;
|
||||
enum ctx_state prev_state;
|
||||
mm_segment_t seg;
|
||||
|
||||
seg = get_fs();
|
||||
if (!user_mode(regs))
|
||||
set_fs(KERNEL_DS);
|
||||
bool user = user_mode(regs);
|
||||
|
||||
prev_state = exception_enter();
|
||||
current->thread.trap_nr = (regs->cp0_cause >> 2) & 0x1f;
|
||||
if (get_isa16_mode(regs->cp0_epc)) {
|
||||
u16 instr[2];
|
||||
|
||||
if (__get_user(instr[0], (u16 __user *)epc))
|
||||
if (__get_inst16(&instr[0], (u16 *)epc, user))
|
||||
goto out_sigsegv;
|
||||
|
||||
if (!cpu_has_mmips) {
|
||||
@@ -1044,13 +1043,13 @@ asmlinkage void do_bp(struct pt_regs *regs)
|
||||
bcode = instr[0] & 0xf;
|
||||
} else {
|
||||
/* 32-bit microMIPS BREAK */
|
||||
if (__get_user(instr[1], (u16 __user *)(epc + 2)))
|
||||
if (__get_inst16(&instr[1], (u16 *)(epc + 2), user))
|
||||
goto out_sigsegv;
|
||||
opcode = (instr[0] << 16) | instr[1];
|
||||
bcode = (opcode >> 6) & ((1 << 20) - 1);
|
||||
}
|
||||
} else {
|
||||
if (__get_user(opcode, (unsigned int __user *)epc))
|
||||
if (__get_inst32(&opcode, (u32 *)epc, user))
|
||||
goto out_sigsegv;
|
||||
bcode = (opcode >> 6) & ((1 << 20) - 1);
|
||||
}
|
||||
@@ -1100,7 +1099,6 @@ asmlinkage void do_bp(struct pt_regs *regs)
|
||||
do_trap_or_bp(regs, bcode, TRAP_BRKPT, "Break");
|
||||
|
||||
out:
|
||||
set_fs(seg);
|
||||
exception_exit(prev_state);
|
||||
return;
|
||||
|
||||
@@ -1114,25 +1112,21 @@ asmlinkage void do_tr(struct pt_regs *regs)
|
||||
u32 opcode, tcode = 0;
|
||||
enum ctx_state prev_state;
|
||||
u16 instr[2];
|
||||
mm_segment_t seg;
|
||||
bool user = user_mode(regs);
|
||||
unsigned long epc = msk_isa16_mode(exception_epc(regs));
|
||||
|
||||
seg = get_fs();
|
||||
if (!user_mode(regs))
|
||||
set_fs(KERNEL_DS);
|
||||
|
||||
prev_state = exception_enter();
|
||||
current->thread.trap_nr = (regs->cp0_cause >> 2) & 0x1f;
|
||||
if (get_isa16_mode(regs->cp0_epc)) {
|
||||
if (__get_user(instr[0], (u16 __user *)(epc + 0)) ||
|
||||
__get_user(instr[1], (u16 __user *)(epc + 2)))
|
||||
if (__get_inst16(&instr[0], (u16 *)(epc + 0), user) ||
|
||||
__get_inst16(&instr[1], (u16 *)(epc + 2), user))
|
||||
goto out_sigsegv;
|
||||
opcode = (instr[0] << 16) | instr[1];
|
||||
/* Immediate versions don't provide a code. */
|
||||
if (!(opcode & OPCODE))
|
||||
tcode = (opcode >> 12) & ((1 << 4) - 1);
|
||||
} else {
|
||||
if (__get_user(opcode, (u32 __user *)epc))
|
||||
if (__get_inst32(&opcode, (u32 *)epc, user))
|
||||
goto out_sigsegv;
|
||||
/* Immediate versions don't provide a code. */
|
||||
if (!(opcode & OPCODE))
|
||||
@@ -1142,7 +1136,6 @@ asmlinkage void do_tr(struct pt_regs *regs)
|
||||
do_trap_or_bp(regs, tcode, 0, "Trap");
|
||||
|
||||
out:
|
||||
set_fs(seg);
|
||||
exception_exit(prev_state);
|
||||
return;
|
||||
|
||||
@@ -1591,7 +1584,6 @@ asmlinkage void do_mcheck(struct pt_regs *regs)
|
||||
{
|
||||
int multi_match = regs->cp0_status & ST0_TS;
|
||||
enum ctx_state prev_state;
|
||||
mm_segment_t old_fs = get_fs();
|
||||
|
||||
prev_state = exception_enter();
|
||||
show_regs(regs);
|
||||
@@ -1602,12 +1594,7 @@ asmlinkage void do_mcheck(struct pt_regs *regs)
|
||||
dump_tlb_all();
|
||||
}
|
||||
|
||||
if (!user_mode(regs))
|
||||
set_fs(KERNEL_DS);
|
||||
|
||||
show_code((unsigned int __user *) regs->cp0_epc);
|
||||
|
||||
set_fs(old_fs);
|
||||
show_code((void *)regs->cp0_epc, user_mode(regs));
|
||||
|
||||
/*
|
||||
* Some chips may have other causes of machine check (e.g. SB1
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user