Merge tag 'kgdb-4.21-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/danielt/linux
Pull kgdb updates from Daniel Thompson:
"Mostly clean ups although while Doug's was chasing down a odd lockdep
warning he also did some work to improved debugger resilience when
some CPUs fail to respond to the round up request.
The main changes are:
- Fixing a lockdep warning on architectures that cannot use an NMI
for the round up plus related changes to make CPU round up and all
CPU backtrace more resilient.
- Constify the arch ops tables
- A couple of other small clean ups
Two of the three patchsets here include changes that spill over into
arch/. Changes in the arch space are relatively narrow in scope (and
directly related to kgdb). Didn't get comprehensive acks but all
impacted maintainers were Cc:ed in good time"
* tag 'kgdb-4.21-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/danielt/linux:
kgdb/treewide: constify struct kgdb_arch arch_kgdb_ops
mips/kgdb: prepare arch_kgdb_ops for constness
kdb: use bool for binary state indicators
kdb: Don't back trace on a cpu that didn't round up
kgdb: Don't round up a CPU that failed rounding up before
kgdb: Fix kgdb_roundup_cpus() for arches who used smp_call_function()
kgdb: Remove irq flags from roundup
This commit is contained in:
@@ -55,6 +55,7 @@
|
||||
#include <linux/mm.h>
|
||||
#include <linux/vmacache.h>
|
||||
#include <linux/rcupdate.h>
|
||||
#include <linux/irq.h>
|
||||
|
||||
#include <asm/cacheflush.h>
|
||||
#include <asm/byteorder.h>
|
||||
@@ -220,6 +221,62 @@ int __weak kgdb_skipexception(int exception, struct pt_regs *regs)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
|
||||
/*
|
||||
* Default (weak) implementation for kgdb_roundup_cpus
|
||||
*/
|
||||
|
||||
static DEFINE_PER_CPU(call_single_data_t, kgdb_roundup_csd);
|
||||
|
||||
void __weak kgdb_call_nmi_hook(void *ignored)
|
||||
{
|
||||
/*
|
||||
* NOTE: get_irq_regs() is supposed to get the registers from
|
||||
* before the IPI interrupt happened and so is supposed to
|
||||
* show where the processor was. In some situations it's
|
||||
* possible we might be called without an IPI, so it might be
|
||||
* safer to figure out how to make kgdb_breakpoint() work
|
||||
* properly here.
|
||||
*/
|
||||
kgdb_nmicallback(raw_smp_processor_id(), get_irq_regs());
|
||||
}
|
||||
|
||||
void __weak kgdb_roundup_cpus(void)
|
||||
{
|
||||
call_single_data_t *csd;
|
||||
int this_cpu = raw_smp_processor_id();
|
||||
int cpu;
|
||||
int ret;
|
||||
|
||||
for_each_online_cpu(cpu) {
|
||||
/* No need to roundup ourselves */
|
||||
if (cpu == this_cpu)
|
||||
continue;
|
||||
|
||||
csd = &per_cpu(kgdb_roundup_csd, cpu);
|
||||
|
||||
/*
|
||||
* If it didn't round up last time, don't try again
|
||||
* since smp_call_function_single_async() will block.
|
||||
*
|
||||
* If rounding_up is false then we know that the
|
||||
* previous call must have at least started and that
|
||||
* means smp_call_function_single_async() won't block.
|
||||
*/
|
||||
if (kgdb_info[cpu].rounding_up)
|
||||
continue;
|
||||
kgdb_info[cpu].rounding_up = true;
|
||||
|
||||
csd->func = kgdb_call_nmi_hook;
|
||||
ret = smp_call_function_single_async(cpu, csd);
|
||||
if (ret)
|
||||
kgdb_info[cpu].rounding_up = false;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Some architectures need cache flushes when we set/clear a
|
||||
* breakpoint:
|
||||
@@ -535,6 +592,8 @@ return_normal:
|
||||
arch_kgdb_ops.correct_hw_break();
|
||||
if (trace_on)
|
||||
tracing_on();
|
||||
kgdb_info[cpu].debuggerinfo = NULL;
|
||||
kgdb_info[cpu].task = NULL;
|
||||
kgdb_info[cpu].exception_state &=
|
||||
~(DCPU_WANT_MASTER | DCPU_IS_SLAVE);
|
||||
kgdb_info[cpu].enter_kgdb--;
|
||||
@@ -593,7 +652,7 @@ return_normal:
|
||||
|
||||
/* Signal the other CPUs to enter kgdb_wait() */
|
||||
else if ((!kgdb_single_step) && kgdb_do_roundup)
|
||||
kgdb_roundup_cpus(flags);
|
||||
kgdb_roundup_cpus();
|
||||
#endif
|
||||
|
||||
/*
|
||||
@@ -667,6 +726,8 @@ kgdb_restore:
|
||||
if (trace_on)
|
||||
tracing_on();
|
||||
|
||||
kgdb_info[cpu].debuggerinfo = NULL;
|
||||
kgdb_info[cpu].task = NULL;
|
||||
kgdb_info[cpu].exception_state &=
|
||||
~(DCPU_WANT_MASTER | DCPU_IS_SLAVE);
|
||||
kgdb_info[cpu].enter_kgdb--;
|
||||
@@ -747,6 +808,8 @@ int kgdb_nmicallback(int cpu, void *regs)
|
||||
struct kgdb_state kgdb_var;
|
||||
struct kgdb_state *ks = &kgdb_var;
|
||||
|
||||
kgdb_info[cpu].rounding_up = false;
|
||||
|
||||
memset(ks, 0, sizeof(struct kgdb_state));
|
||||
ks->cpu = cpu;
|
||||
ks->linux_regs = regs;
|
||||
|
||||
@@ -42,6 +42,7 @@ struct debuggerinfo_struct {
|
||||
int ret_state;
|
||||
int irq_depth;
|
||||
int enter_kgdb;
|
||||
bool rounding_up;
|
||||
};
|
||||
|
||||
extern struct debuggerinfo_struct kgdb_info[];
|
||||
|
||||
@@ -186,7 +186,16 @@ kdb_bt(int argc, const char **argv)
|
||||
kdb_printf("btc: cpu status: ");
|
||||
kdb_parse("cpu\n");
|
||||
for_each_online_cpu(cpu) {
|
||||
sprintf(buf, "btt 0x%px\n", KDB_TSK(cpu));
|
||||
void *kdb_tsk = KDB_TSK(cpu);
|
||||
|
||||
/* If a CPU failed to round up we could be here */
|
||||
if (!kdb_tsk) {
|
||||
kdb_printf("WARNING: no task for cpu %ld\n",
|
||||
cpu);
|
||||
continue;
|
||||
}
|
||||
|
||||
sprintf(buf, "btt 0x%px\n", kdb_tsk);
|
||||
kdb_parse(buf);
|
||||
touch_nmi_watchdog();
|
||||
}
|
||||
|
||||
@@ -118,13 +118,6 @@ int kdb_stub(struct kgdb_state *ks)
|
||||
kdb_bp_remove();
|
||||
KDB_STATE_CLEAR(DOING_SS);
|
||||
KDB_STATE_SET(PAGER);
|
||||
/* zero out any offline cpu data */
|
||||
for_each_present_cpu(i) {
|
||||
if (!cpu_online(i)) {
|
||||
kgdb_info[i].debuggerinfo = NULL;
|
||||
kgdb_info[i].task = NULL;
|
||||
}
|
||||
}
|
||||
if (ks->err_code == DIE_OOPS || reason == KDB_REASON_OOPS) {
|
||||
ks->pass_exception = 1;
|
||||
KDB_FLAG_SET(CATASTROPHIC);
|
||||
|
||||
@@ -658,7 +658,7 @@ static void kdb_cmderror(int diag)
|
||||
*/
|
||||
struct defcmd_set {
|
||||
int count;
|
||||
int usable;
|
||||
bool usable;
|
||||
char *name;
|
||||
char *usage;
|
||||
char *help;
|
||||
@@ -666,7 +666,7 @@ struct defcmd_set {
|
||||
};
|
||||
static struct defcmd_set *defcmd_set;
|
||||
static int defcmd_set_count;
|
||||
static int defcmd_in_progress;
|
||||
static bool defcmd_in_progress;
|
||||
|
||||
/* Forward references */
|
||||
static int kdb_exec_defcmd(int argc, const char **argv);
|
||||
@@ -676,9 +676,9 @@ static int kdb_defcmd2(const char *cmdstr, const char *argv0)
|
||||
struct defcmd_set *s = defcmd_set + defcmd_set_count - 1;
|
||||
char **save_command = s->command;
|
||||
if (strcmp(argv0, "endefcmd") == 0) {
|
||||
defcmd_in_progress = 0;
|
||||
defcmd_in_progress = false;
|
||||
if (!s->count)
|
||||
s->usable = 0;
|
||||
s->usable = false;
|
||||
if (s->usable)
|
||||
/* macros are always safe because when executed each
|
||||
* internal command re-enters kdb_parse() and is
|
||||
@@ -695,7 +695,7 @@ static int kdb_defcmd2(const char *cmdstr, const char *argv0)
|
||||
if (!s->command) {
|
||||
kdb_printf("Could not allocate new kdb_defcmd table for %s\n",
|
||||
cmdstr);
|
||||
s->usable = 0;
|
||||
s->usable = false;
|
||||
return KDB_NOTIMP;
|
||||
}
|
||||
memcpy(s->command, save_command, s->count * sizeof(*(s->command)));
|
||||
@@ -737,7 +737,7 @@ static int kdb_defcmd(int argc, const char **argv)
|
||||
defcmd_set_count * sizeof(*defcmd_set));
|
||||
s = defcmd_set + defcmd_set_count;
|
||||
memset(s, 0, sizeof(*s));
|
||||
s->usable = 1;
|
||||
s->usable = true;
|
||||
s->name = kdb_strdup(argv[1], GFP_KDB);
|
||||
if (!s->name)
|
||||
goto fail_name;
|
||||
@@ -756,7 +756,7 @@ static int kdb_defcmd(int argc, const char **argv)
|
||||
s->help[strlen(s->help)-1] = '\0';
|
||||
}
|
||||
++defcmd_set_count;
|
||||
defcmd_in_progress = 1;
|
||||
defcmd_in_progress = true;
|
||||
kfree(save_defcmd_set);
|
||||
return 0;
|
||||
fail_help:
|
||||
|
||||
Reference in New Issue
Block a user