--- zzzz-none-000/linux-3.10.107/arch/mips/kernel/kgdb.c 2017-06-27 09:49:32.000000000 +0000 +++ scorpion-7490-727/linux-3.10.107/arch/mips/kernel/kgdb.c 2021-02-04 17:41:59.000000000 +0000 @@ -32,6 +32,7 @@ #include #include #include +#include static struct hard_trap_info { unsigned char tt; /* Trap type code for MIPS R3xxx and R4xxx */ @@ -208,7 +209,14 @@ static void kgdb_call_nmi_hook(void *ignored) { + mm_segment_t old_fs; + + old_fs = get_fs(); + set_fs(get_ds()); + kgdb_nmicallback(raw_smp_processor_id(), NULL); + + set_fs(old_fs); } void kgdb_roundup_cpus(unsigned long flags) @@ -236,6 +244,9 @@ void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *p) { int reg; + struct thread_info *ti = task_thread_info(p); + unsigned long ksp = (unsigned long)ti + THREAD_SIZE - 32; + struct pt_regs *regs = (struct pt_regs *)ksp - 1; #if (KGDB_GDB_REG_SIZE == 32) u32 *ptr = (u32 *)gdb_regs; #else @@ -243,46 +254,25 @@ #endif for (reg = 0; reg < 16; reg++) - *(ptr++) = 0; + *(ptr++) = regs->regs[reg]; /* S0 - S7 */ - *(ptr++) = p->thread.reg16; - *(ptr++) = p->thread.reg17; - *(ptr++) = p->thread.reg18; - *(ptr++) = p->thread.reg19; - *(ptr++) = p->thread.reg20; - *(ptr++) = p->thread.reg21; - *(ptr++) = p->thread.reg22; - *(ptr++) = p->thread.reg23; + for (reg = 16; reg < 24; reg++) + *(ptr++) = regs->regs[reg]; for (reg = 24; reg < 28; reg++) *(ptr++) = 0; /* GP, SP, FP, RA */ - *(ptr++) = (long)p; - *(ptr++) = p->thread.reg29; - *(ptr++) = p->thread.reg30; - *(ptr++) = p->thread.reg31; - - *(ptr++) = p->thread.cp0_status; - - /* lo, hi */ - *(ptr++) = 0; - *(ptr++) = 0; - - /* - * BadVAddr, Cause - * Ideally these would come from the last exception frame up the stack - * but that requires unwinding, otherwise we can't know much for sure. - */ - *(ptr++) = 0; - *(ptr++) = 0; + for (reg = 28; reg < 32; reg++) + *(ptr++) = regs->regs[reg]; - /* - * PC - * use return address (RA), i.e. the moment after return from resume() - */ - *(ptr++) = p->thread.reg31; + *(ptr++) = regs->cp0_status; + *(ptr++) = regs->lo; + *(ptr++) = regs->hi; + *(ptr++) = regs->cp0_badvaddr; + *(ptr++) = regs->cp0_cause; + *(ptr++) = regs->cp0_epc; } void kgdb_arch_set_pc(struct pt_regs *regs, unsigned long pc) @@ -300,6 +290,7 @@ struct die_args *args = (struct die_args *)ptr; struct pt_regs *regs = args->regs; int trap = (regs->cp0_cause & 0x7c) >> 2; + mm_segment_t old_fs; #ifdef CONFIG_KPROBES /* @@ -314,11 +305,17 @@ if (user_mode(regs)) return NOTIFY_DONE; + /* Kernel mode. Set correct address limit */ + old_fs = get_fs(); + set_fs(get_ds()); + if (atomic_read(&kgdb_active) != -1) kgdb_nmicallback(smp_processor_id(), regs); - if (kgdb_handle_exception(trap, compute_signal(trap), cmd, regs)) + if (kgdb_handle_exception(trap, compute_signal(trap), cmd, regs)) { + set_fs(old_fs); return NOTIFY_DONE; + } if (atomic_read(&kgdb_setting_breakpoint)) if ((trap == 9) && (regs->cp0_epc == (unsigned long)breakinst)) @@ -328,6 +325,7 @@ local_irq_enable(); __flush_cache_all(); + set_fs(old_fs); return NOTIFY_STOP; } @@ -380,10 +378,6 @@ struct kgdb_arch arch_kgdb_ops; -/* - * We use kgdb_early_setup so that functions we need to call now don't - * cause trouble when called again later. - */ int kgdb_arch_init(void) { union mips_instruction insn = {