From 5f6c7648e556f41a3064bb6dceb9e102c50b618d Mon Sep 17 00:00:00 2001 From: John Ogness Date: Wed, 3 Mar 2021 11:15:24 +0100 Subject: printk: kmsg_dumper: remove @active field All 6 kmsg_dumpers do not benefit from the @active flag: (provide their own synchronization) - arch/powerpc/kernel/nvram_64.c - arch/um/kernel/kmsg_dump.c - drivers/mtd/mtdoops.c - fs/pstore/platform.c (only dump on KMSG_DUMP_PANIC, which does not require synchronization) - arch/powerpc/platforms/powernv/opal-kmsg.c - drivers/hv/vmbus_drv.c The other 2 kmsg_dump users also do not rely on @active: (hard-code @active to always be true) - arch/powerpc/xmon/xmon.c - kernel/debug/kdb/kdb_main.c Therefore, @active can be removed. Signed-off-by: John Ogness Reviewed-by: Petr Mladek Signed-off-by: Petr Mladek Link: https://lore.kernel.org/r/20210303101528.29901-12-john.ogness@linutronix.de --- kernel/debug/kdb/kdb_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'kernel/debug') diff --git a/kernel/debug/kdb/kdb_main.c b/kernel/debug/kdb/kdb_main.c index 930ac1b25ec7..315169d5e119 100644 --- a/kernel/debug/kdb/kdb_main.c +++ b/kernel/debug/kdb/kdb_main.c @@ -2101,7 +2101,7 @@ static int kdb_dmesg(int argc, const char **argv) int adjust = 0; int n = 0; int skip = 0; - struct kmsg_dumper dumper = { .active = 1 }; + struct kmsg_dumper dumper; size_t len; char buf[201]; -- cgit v1.2.3-71-gd317 From f9f3f02db98bbe678a8e57fe9432b196174744a3 Mon Sep 17 00:00:00 2001 From: John Ogness Date: Wed, 3 Mar 2021 11:15:25 +0100 Subject: printk: introduce a kmsg_dump iterator Rather than storing the iterator information in the registered kmsg_dumper structure, create a separate iterator structure. The kmsg_dump_iter structure can reside on the stack of the caller, thus allowing lockless use of the kmsg_dump functions. Update code that accesses the kernel logs using the kmsg_dumper structure to use the new kmsg_dump_iter structure. For kmsg_dumpers, this also means adding a call to kmsg_dump_rewind() to initialize the iterator. All this is in preparation for removal of @logbuf_lock. Signed-off-by: John Ogness Reviewed-by: Kees Cook # pstore Reviewed-by: Petr Mladek Signed-off-by: Petr Mladek Link: https://lore.kernel.org/r/20210303101528.29901-13-john.ogness@linutronix.de --- arch/powerpc/kernel/nvram_64.c | 8 ++++-- arch/powerpc/xmon/xmon.c | 6 ++-- arch/um/kernel/kmsg_dump.c | 5 +++- drivers/hv/vmbus_drv.c | 4 ++- drivers/mtd/mtdoops.c | 5 +++- fs/pstore/platform.c | 5 +++- include/linux/kmsg_dump.h | 36 +++++++++++++----------- kernel/debug/kdb/kdb_main.c | 10 +++---- kernel/printk/printk.c | 63 +++++++++++++++++++++--------------------- 9 files changed, 80 insertions(+), 62 deletions(-) (limited to 'kernel/debug') diff --git a/arch/powerpc/kernel/nvram_64.c b/arch/powerpc/kernel/nvram_64.c index 532f22637783..3c8d9bbb51cf 100644 --- a/arch/powerpc/kernel/nvram_64.c +++ b/arch/powerpc/kernel/nvram_64.c @@ -647,6 +647,7 @@ static void oops_to_nvram(struct kmsg_dumper *dumper, { struct oops_log_info *oops_hdr = (struct oops_log_info *)oops_buf; static unsigned int oops_count = 0; + static struct kmsg_dump_iter iter; static bool panicking = false; static DEFINE_SPINLOCK(lock); unsigned long flags; @@ -681,13 +682,14 @@ static void oops_to_nvram(struct kmsg_dumper *dumper, return; if (big_oops_buf) { - kmsg_dump_get_buffer(dumper, false, + kmsg_dump_rewind(&iter); + kmsg_dump_get_buffer(&iter, false, big_oops_buf, big_oops_buf_sz, &text_len); rc = zip_oops(text_len); } if (rc != 0) { - kmsg_dump_rewind(dumper); - kmsg_dump_get_buffer(dumper, false, + kmsg_dump_rewind(&iter); + kmsg_dump_get_buffer(&iter, false, oops_data, oops_data_sz, &text_len); err_type = ERR_TYPE_KERNEL_PANIC; oops_hdr->version = cpu_to_be16(OOPS_HDR_VERSION); diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c index a777573a0c38..dbcf403b1d8d 100644 --- a/arch/powerpc/xmon/xmon.c +++ b/arch/powerpc/xmon/xmon.c @@ -3005,7 +3005,7 @@ print_address(unsigned long addr) static void dump_log_buf(void) { - struct kmsg_dumper dumper; + struct kmsg_dump_iter iter; unsigned char buf[128]; size_t len; @@ -3017,9 +3017,9 @@ dump_log_buf(void) catch_memory_errors = 1; sync(); - kmsg_dump_rewind_nolock(&dumper); + kmsg_dump_rewind_nolock(&iter); xmon_start_pagination(); - while (kmsg_dump_get_line_nolock(&dumper, false, buf, sizeof(buf), &len)) { + while (kmsg_dump_get_line_nolock(&iter, false, buf, sizeof(buf), &len)) { buf[len] = '\0'; printf("%s", buf); } diff --git a/arch/um/kernel/kmsg_dump.c b/arch/um/kernel/kmsg_dump.c index a765d235e50e..0224fcb36e22 100644 --- a/arch/um/kernel/kmsg_dump.c +++ b/arch/um/kernel/kmsg_dump.c @@ -10,6 +10,7 @@ static void kmsg_dumper_stdout(struct kmsg_dumper *dumper, enum kmsg_dump_reason reason) { + static struct kmsg_dump_iter iter; static DEFINE_SPINLOCK(lock); static char line[1024]; struct console *con; @@ -35,8 +36,10 @@ static void kmsg_dumper_stdout(struct kmsg_dumper *dumper, if (!spin_trylock_irqsave(&lock, flags)) return; + kmsg_dump_rewind(&iter); + printf("kmsg_dump:\n"); - while (kmsg_dump_get_line(dumper, true, line, sizeof(line), &len)) { + while (kmsg_dump_get_line(&iter, true, line, sizeof(line), &len)) { line[len] = '\0'; printf("%s", line); } diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c index 10dce9f91216..b341b144bde8 100644 --- a/drivers/hv/vmbus_drv.c +++ b/drivers/hv/vmbus_drv.c @@ -1391,6 +1391,7 @@ static void vmbus_isr(void) static void hv_kmsg_dump(struct kmsg_dumper *dumper, enum kmsg_dump_reason reason) { + struct kmsg_dump_iter iter; size_t bytes_written; phys_addr_t panic_pa; @@ -1404,7 +1405,8 @@ static void hv_kmsg_dump(struct kmsg_dumper *dumper, * Write dump contents to the page. No need to synchronize; panic should * be single-threaded. */ - kmsg_dump_get_buffer(dumper, false, hv_panic_page, HV_HYP_PAGE_SIZE, + kmsg_dump_rewind(&iter); + kmsg_dump_get_buffer(&iter, false, hv_panic_page, HV_HYP_PAGE_SIZE, &bytes_written); if (bytes_written) hyperv_report_panic_msg(panic_pa, bytes_written); diff --git a/drivers/mtd/mtdoops.c b/drivers/mtd/mtdoops.c index 8bbfba40a554..862c4a889234 100644 --- a/drivers/mtd/mtdoops.c +++ b/drivers/mtd/mtdoops.c @@ -277,14 +277,17 @@ static void mtdoops_do_dump(struct kmsg_dumper *dumper, { struct mtdoops_context *cxt = container_of(dumper, struct mtdoops_context, dump); + struct kmsg_dump_iter iter; /* Only dump oopses if dump_oops is set */ if (reason == KMSG_DUMP_OOPS && !dump_oops) return; + kmsg_dump_rewind(&iter); + if (test_and_set_bit(0, &cxt->oops_buf_busy)) return; - kmsg_dump_get_buffer(dumper, true, cxt->oops_buf + MTDOOPS_HEADER_SIZE, + kmsg_dump_get_buffer(&iter, true, cxt->oops_buf + MTDOOPS_HEADER_SIZE, record_size - MTDOOPS_HEADER_SIZE, NULL); clear_bit(0, &cxt->oops_buf_busy); diff --git a/fs/pstore/platform.c b/fs/pstore/platform.c index d963ae7902f9..b9614db48b1d 100644 --- a/fs/pstore/platform.c +++ b/fs/pstore/platform.c @@ -385,6 +385,7 @@ void pstore_record_init(struct pstore_record *record, static void pstore_dump(struct kmsg_dumper *dumper, enum kmsg_dump_reason reason) { + struct kmsg_dump_iter iter; unsigned long total = 0; const char *why; unsigned int part = 1; @@ -405,6 +406,8 @@ static void pstore_dump(struct kmsg_dumper *dumper, } } + kmsg_dump_rewind(&iter); + oopscount++; while (total < kmsg_bytes) { char *dst; @@ -435,7 +438,7 @@ static void pstore_dump(struct kmsg_dumper *dumper, dst_size -= header_size; /* Write dump contents. */ - if (!kmsg_dump_get_buffer(dumper, true, dst + header_size, + if (!kmsg_dump_get_buffer(&iter, true, dst + header_size, dst_size, &dump_size)) break; diff --git a/include/linux/kmsg_dump.h b/include/linux/kmsg_dump.h index 84eaa2090efa..36c8c57e1051 100644 --- a/include/linux/kmsg_dump.h +++ b/include/linux/kmsg_dump.h @@ -29,6 +29,16 @@ enum kmsg_dump_reason { KMSG_DUMP_MAX }; +/** + * struct kmsg_dump_iter - iterator for retrieving kernel messages + * @cur_seq: Points to the oldest message to dump + * @next_seq: Points after the newest message to dump + */ +struct kmsg_dump_iter { + u64 cur_seq; + u64 next_seq; +}; + /** * struct kmsg_dumper - kernel crash message dumper structure * @list: Entry in the dumper list (private) @@ -36,35 +46,29 @@ enum kmsg_dump_reason { * through the record iterator * @max_reason: filter for highest reason number that should be dumped * @registered: Flag that specifies if this is already registered - * @cur_seq: Points to the oldest message to dump - * @next_seq: Points after the newest message to dump */ struct kmsg_dumper { struct list_head list; void (*dump)(struct kmsg_dumper *dumper, enum kmsg_dump_reason reason); enum kmsg_dump_reason max_reason; bool registered; - - /* private state of the kmsg iterator */ - u64 cur_seq; - u64 next_seq; }; #ifdef CONFIG_PRINTK void kmsg_dump(enum kmsg_dump_reason reason); -bool kmsg_dump_get_line_nolock(struct kmsg_dumper *dumper, bool syslog, +bool kmsg_dump_get_line_nolock(struct kmsg_dump_iter *iter, bool syslog, char *line, size_t size, size_t *len); -bool kmsg_dump_get_line(struct kmsg_dumper *dumper, bool syslog, +bool kmsg_dump_get_line(struct kmsg_dump_iter *iter, bool syslog, char *line, size_t size, size_t *len); -bool kmsg_dump_get_buffer(struct kmsg_dumper *dumper, bool syslog, +bool kmsg_dump_get_buffer(struct kmsg_dump_iter *iter, bool syslog, char *buf, size_t size, size_t *len_out); -void kmsg_dump_rewind_nolock(struct kmsg_dumper *dumper); +void kmsg_dump_rewind_nolock(struct kmsg_dump_iter *iter); -void kmsg_dump_rewind(struct kmsg_dumper *dumper); +void kmsg_dump_rewind(struct kmsg_dump_iter *iter); int kmsg_dump_register(struct kmsg_dumper *dumper); @@ -76,30 +80,30 @@ static inline void kmsg_dump(enum kmsg_dump_reason reason) { } -static inline bool kmsg_dump_get_line_nolock(struct kmsg_dumper *dumper, +static inline bool kmsg_dump_get_line_nolock(struct kmsg_dump_iter *iter, bool syslog, const char *line, size_t size, size_t *len) { return false; } -static inline bool kmsg_dump_get_line(struct kmsg_dumper *dumper, bool syslog, +static inline bool kmsg_dump_get_line(struct kmsg_dump_iter *iter, bool syslog, const char *line, size_t size, size_t *len) { return false; } -static inline bool kmsg_dump_get_buffer(struct kmsg_dumper *dumper, bool syslog, +static inline bool kmsg_dump_get_buffer(struct kmsg_dump_iter *iter, bool syslog, char *buf, size_t size, size_t *len) { return false; } -static inline void kmsg_dump_rewind_nolock(struct kmsg_dumper *dumper) +static inline void kmsg_dump_rewind_nolock(struct kmsg_dump_iter *iter) { } -static inline void kmsg_dump_rewind(struct kmsg_dumper *dumper) +static inline void kmsg_dump_rewind(struct kmsg_dump_iter *iter) { } diff --git a/kernel/debug/kdb/kdb_main.c b/kernel/debug/kdb/kdb_main.c index 315169d5e119..8544d7a55a57 100644 --- a/kernel/debug/kdb/kdb_main.c +++ b/kernel/debug/kdb/kdb_main.c @@ -2101,7 +2101,7 @@ static int kdb_dmesg(int argc, const char **argv) int adjust = 0; int n = 0; int skip = 0; - struct kmsg_dumper dumper; + struct kmsg_dump_iter iter; size_t len; char buf[201]; @@ -2126,8 +2126,8 @@ static int kdb_dmesg(int argc, const char **argv) kdb_set(2, setargs); } - kmsg_dump_rewind_nolock(&dumper); - while (kmsg_dump_get_line_nolock(&dumper, 1, NULL, 0, NULL)) + kmsg_dump_rewind_nolock(&iter); + while (kmsg_dump_get_line_nolock(&iter, 1, NULL, 0, NULL)) n++; if (lines < 0) { @@ -2159,8 +2159,8 @@ static int kdb_dmesg(int argc, const char **argv) if (skip >= n || skip < 0) return 0; - kmsg_dump_rewind_nolock(&dumper); - while (kmsg_dump_get_line_nolock(&dumper, 1, buf, sizeof(buf), &len)) { + kmsg_dump_rewind_nolock(&iter); + while (kmsg_dump_get_line_nolock(&iter, 1, buf, sizeof(buf), &len)) { if (skip) { skip--; continue; diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c index ce4cc64ba7c9..b49dee256947 100644 --- a/kernel/printk/printk.c +++ b/kernel/printk/printk.c @@ -3390,7 +3390,6 @@ EXPORT_SYMBOL_GPL(kmsg_dump_reason_str); void kmsg_dump(enum kmsg_dump_reason reason) { struct kmsg_dumper *dumper; - unsigned long flags; rcu_read_lock(); list_for_each_entry_rcu(dumper, &dump_list, list) { @@ -3407,12 +3406,6 @@ void kmsg_dump(enum kmsg_dump_reason reason) if (reason > max_reason) continue; - /* initialize iterator with data about the stored records */ - logbuf_lock_irqsave(flags); - dumper->cur_seq = latched_seq_read_nolock(&clear_seq); - dumper->next_seq = prb_next_seq(prb); - logbuf_unlock_irqrestore(flags); - /* invoke dumper which will iterate over records */ dumper->dump(dumper, reason); } @@ -3421,7 +3414,7 @@ void kmsg_dump(enum kmsg_dump_reason reason) /** * kmsg_dump_get_line_nolock - retrieve one kmsg log line (unlocked version) - * @dumper: registered kmsg dumper + * @iter: kmsg dump iterator * @syslog: include the "<4>" prefixes * @line: buffer to copy the line to * @size: maximum size of the buffer @@ -3438,24 +3431,28 @@ void kmsg_dump(enum kmsg_dump_reason reason) * * The function is similar to kmsg_dump_get_line(), but grabs no locks. */ -bool kmsg_dump_get_line_nolock(struct kmsg_dumper *dumper, bool syslog, +bool kmsg_dump_get_line_nolock(struct kmsg_dump_iter *iter, bool syslog, char *line, size_t size, size_t *len) { + u64 min_seq = latched_seq_read_nolock(&clear_seq); struct printk_info info; unsigned int line_count; struct printk_record r; size_t l = 0; bool ret = false; + if (iter->cur_seq < min_seq) + iter->cur_seq = min_seq; + prb_rec_init_rd(&r, &info, line, size); /* Read text or count text lines? */ if (line) { - if (!prb_read_valid(prb, dumper->cur_seq, &r)) + if (!prb_read_valid(prb, iter->cur_seq, &r)) goto out; l = record_print_text(&r, syslog, printk_time); } else { - if (!prb_read_valid_info(prb, dumper->cur_seq, + if (!prb_read_valid_info(prb, iter->cur_seq, &info, &line_count)) { goto out; } @@ -3464,7 +3461,7 @@ bool kmsg_dump_get_line_nolock(struct kmsg_dumper *dumper, bool syslog, } - dumper->cur_seq = r.info->seq + 1; + iter->cur_seq = r.info->seq + 1; ret = true; out: if (len) @@ -3474,7 +3471,7 @@ out: /** * kmsg_dump_get_line - retrieve one kmsg log line - * @dumper: registered kmsg dumper + * @iter: kmsg dump iterator * @syslog: include the "<4>" prefixes * @line: buffer to copy the line to * @size: maximum size of the buffer @@ -3489,14 +3486,14 @@ out: * A return value of FALSE indicates that there are no more records to * read. */ -bool kmsg_dump_get_line(struct kmsg_dumper *dumper, bool syslog, +bool kmsg_dump_get_line(struct kmsg_dump_iter *iter, bool syslog, char *line, size_t size, size_t *len) { unsigned long flags; bool ret; logbuf_lock_irqsave(flags); - ret = kmsg_dump_get_line_nolock(dumper, syslog, line, size, len); + ret = kmsg_dump_get_line_nolock(iter, syslog, line, size, len); logbuf_unlock_irqrestore(flags); return ret; @@ -3505,7 +3502,7 @@ EXPORT_SYMBOL_GPL(kmsg_dump_get_line); /** * kmsg_dump_get_buffer - copy kmsg log lines - * @dumper: registered kmsg dumper + * @iter: kmsg dump iterator * @syslog: include the "<4>" prefixes * @buf: buffer to copy the line to * @size: maximum size of the buffer @@ -3522,9 +3519,10 @@ EXPORT_SYMBOL_GPL(kmsg_dump_get_line); * A return value of FALSE indicates that there are no more records to * read. */ -bool kmsg_dump_get_buffer(struct kmsg_dumper *dumper, bool syslog, +bool kmsg_dump_get_buffer(struct kmsg_dump_iter *iter, bool syslog, char *buf, size_t size, size_t *len_out) { + u64 min_seq = latched_seq_read_nolock(&clear_seq); struct printk_info info; struct printk_record r; unsigned long flags; @@ -3537,16 +3535,19 @@ bool kmsg_dump_get_buffer(struct kmsg_dumper *dumper, bool syslog, if (!buf || !size) goto out; + if (iter->cur_seq < min_seq) + iter->cur_seq = min_seq; + logbuf_lock_irqsave(flags); - if (prb_read_valid_info(prb, dumper->cur_seq, &info, NULL)) { - if (info.seq != dumper->cur_seq) { + if (prb_read_valid_info(prb, iter->cur_seq, &info, NULL)) { + if (info.seq != iter->cur_seq) { /* messages are gone, move to first available one */ - dumper->cur_seq = info.seq; + iter->cur_seq = info.seq; } } /* last entry */ - if (dumper->cur_seq >= dumper->next_seq) { + if (iter->cur_seq >= iter->next_seq) { logbuf_unlock_irqrestore(flags); goto out; } @@ -3557,7 +3558,7 @@ bool kmsg_dump_get_buffer(struct kmsg_dumper *dumper, bool syslog, * because this function (by way of record_print_text()) will * not write more than size-1 bytes of text into @buf. */ - seq = find_first_fitting_seq(dumper->cur_seq, dumper->next_seq, + seq = find_first_fitting_seq(iter->cur_seq, iter->next_seq, size - 1, syslog, time); /* @@ -3570,7 +3571,7 @@ bool kmsg_dump_get_buffer(struct kmsg_dumper *dumper, bool syslog, len = 0; prb_for_each_record(seq, prb, seq, &r) { - if (r.info->seq >= dumper->next_seq) + if (r.info->seq >= iter->next_seq) break; len += record_print_text(&r, syslog, time); @@ -3579,7 +3580,7 @@ bool kmsg_dump_get_buffer(struct kmsg_dumper *dumper, bool syslog, prb_rec_init_rd(&r, &info, buf + len, size - len); } - dumper->next_seq = next_seq; + iter->next_seq = next_seq; ret = true; logbuf_unlock_irqrestore(flags); out: @@ -3591,7 +3592,7 @@ EXPORT_SYMBOL_GPL(kmsg_dump_get_buffer); /** * kmsg_dump_rewind_nolock - reset the iterator (unlocked version) - * @dumper: registered kmsg dumper + * @iter: kmsg dump iterator * * Reset the dumper's iterator so that kmsg_dump_get_line() and * kmsg_dump_get_buffer() can be called again and used multiple @@ -3599,26 +3600,26 @@ EXPORT_SYMBOL_GPL(kmsg_dump_get_buffer); * * The function is similar to kmsg_dump_rewind(), but grabs no locks. */ -void kmsg_dump_rewind_nolock(struct kmsg_dumper *dumper) +void kmsg_dump_rewind_nolock(struct kmsg_dump_iter *iter) { - dumper->cur_seq = latched_seq_read_nolock(&clear_seq); - dumper->next_seq = prb_next_seq(prb); + iter->cur_seq = latched_seq_read_nolock(&clear_seq); + iter->next_seq = prb_next_seq(prb); } /** * kmsg_dump_rewind - reset the iterator - * @dumper: registered kmsg dumper + * @iter: kmsg dump iterator * * Reset the dumper's iterator so that kmsg_dump_get_line() and * kmsg_dump_get_buffer() can be called again and used multiple * times within the same dumper.dump() callback. */ -void kmsg_dump_rewind(struct kmsg_dumper *dumper) +void kmsg_dump_rewind(struct kmsg_dump_iter *iter) { unsigned long flags; logbuf_lock_irqsave(flags); - kmsg_dump_rewind_nolock(dumper); + kmsg_dump_rewind_nolock(iter); logbuf_unlock_irqrestore(flags); } EXPORT_SYMBOL_GPL(kmsg_dump_rewind); -- cgit v1.2.3-71-gd317 From a4f987653241db9fa1f99531b430cebb83f1eae1 Mon Sep 17 00:00:00 2001 From: John Ogness Date: Wed, 3 Mar 2021 11:15:27 +0100 Subject: printk: kmsg_dump: remove _nolock() variants kmsg_dump_rewind() and kmsg_dump_get_line() are lockless, so there is no need for _nolock() variants. Remove these functions and switch all callers of the _nolock() variants. The functions without _nolock() were chosen because they are already exported to kernel modules. Signed-off-by: John Ogness Reviewed-by: Petr Mladek Signed-off-by: Petr Mladek Link: https://lore.kernel.org/r/20210303101528.29901-15-john.ogness@linutronix.de --- arch/powerpc/xmon/xmon.c | 4 +-- include/linux/kmsg_dump.h | 16 ------------ kernel/debug/kdb/kdb_main.c | 8 +++--- kernel/printk/printk.c | 60 ++++++--------------------------------------- 4 files changed, 14 insertions(+), 74 deletions(-) (limited to 'kernel/debug') diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c index dbcf403b1d8d..dd0e0aac954e 100644 --- a/arch/powerpc/xmon/xmon.c +++ b/arch/powerpc/xmon/xmon.c @@ -3017,9 +3017,9 @@ dump_log_buf(void) catch_memory_errors = 1; sync(); - kmsg_dump_rewind_nolock(&iter); + kmsg_dump_rewind(&iter); xmon_start_pagination(); - while (kmsg_dump_get_line_nolock(&iter, false, buf, sizeof(buf), &len)) { + while (kmsg_dump_get_line(&iter, false, buf, sizeof(buf), &len)) { buf[len] = '\0'; printf("%s", buf); } diff --git a/include/linux/kmsg_dump.h b/include/linux/kmsg_dump.h index 36c8c57e1051..906521c2329c 100644 --- a/include/linux/kmsg_dump.h +++ b/include/linux/kmsg_dump.h @@ -57,17 +57,12 @@ struct kmsg_dumper { #ifdef CONFIG_PRINTK void kmsg_dump(enum kmsg_dump_reason reason); -bool kmsg_dump_get_line_nolock(struct kmsg_dump_iter *iter, bool syslog, - char *line, size_t size, size_t *len); - bool kmsg_dump_get_line(struct kmsg_dump_iter *iter, bool syslog, char *line, size_t size, size_t *len); bool kmsg_dump_get_buffer(struct kmsg_dump_iter *iter, bool syslog, char *buf, size_t size, size_t *len_out); -void kmsg_dump_rewind_nolock(struct kmsg_dump_iter *iter); - void kmsg_dump_rewind(struct kmsg_dump_iter *iter); int kmsg_dump_register(struct kmsg_dumper *dumper); @@ -80,13 +75,6 @@ static inline void kmsg_dump(enum kmsg_dump_reason reason) { } -static inline bool kmsg_dump_get_line_nolock(struct kmsg_dump_iter *iter, - bool syslog, const char *line, - size_t size, size_t *len) -{ - return false; -} - static inline bool kmsg_dump_get_line(struct kmsg_dump_iter *iter, bool syslog, const char *line, size_t size, size_t *len) { @@ -99,10 +87,6 @@ static inline bool kmsg_dump_get_buffer(struct kmsg_dump_iter *iter, bool syslog return false; } -static inline void kmsg_dump_rewind_nolock(struct kmsg_dump_iter *iter) -{ -} - static inline void kmsg_dump_rewind(struct kmsg_dump_iter *iter) { } diff --git a/kernel/debug/kdb/kdb_main.c b/kernel/debug/kdb/kdb_main.c index 8544d7a55a57..67d9f2403b52 100644 --- a/kernel/debug/kdb/kdb_main.c +++ b/kernel/debug/kdb/kdb_main.c @@ -2126,8 +2126,8 @@ static int kdb_dmesg(int argc, const char **argv) kdb_set(2, setargs); } - kmsg_dump_rewind_nolock(&iter); - while (kmsg_dump_get_line_nolock(&iter, 1, NULL, 0, NULL)) + kmsg_dump_rewind(&iter); + while (kmsg_dump_get_line(&iter, 1, NULL, 0, NULL)) n++; if (lines < 0) { @@ -2159,8 +2159,8 @@ static int kdb_dmesg(int argc, const char **argv) if (skip >= n || skip < 0) return 0; - kmsg_dump_rewind_nolock(&iter); - while (kmsg_dump_get_line_nolock(&iter, 1, buf, sizeof(buf), &len)) { + kmsg_dump_rewind(&iter); + while (kmsg_dump_get_line(&iter, 1, buf, sizeof(buf), &len)) { if (skip) { skip--; continue; diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c index 8994bc192b88..602de86d4e76 100644 --- a/kernel/printk/printk.c +++ b/kernel/printk/printk.c @@ -3373,7 +3373,7 @@ void kmsg_dump(enum kmsg_dump_reason reason) } /** - * kmsg_dump_get_line_nolock - retrieve one kmsg log line (unlocked version) + * kmsg_dump_get_line - retrieve one kmsg log line * @iter: kmsg dump iterator * @syslog: include the "<4>" prefixes * @line: buffer to copy the line to @@ -3388,22 +3388,22 @@ void kmsg_dump(enum kmsg_dump_reason reason) * * A return value of FALSE indicates that there are no more records to * read. - * - * The function is similar to kmsg_dump_get_line(), but grabs no locks. */ -bool kmsg_dump_get_line_nolock(struct kmsg_dump_iter *iter, bool syslog, - char *line, size_t size, size_t *len) +bool kmsg_dump_get_line(struct kmsg_dump_iter *iter, bool syslog, + char *line, size_t size, size_t *len) { u64 min_seq = latched_seq_read_nolock(&clear_seq); struct printk_info info; unsigned int line_count; struct printk_record r; + unsigned long flags; size_t l = 0; bool ret = false; if (iter->cur_seq < min_seq) iter->cur_seq = min_seq; + printk_safe_enter_irqsave(flags); prb_rec_init_rd(&r, &info, line, size); /* Read text or count text lines? */ @@ -3424,40 +3424,11 @@ bool kmsg_dump_get_line_nolock(struct kmsg_dump_iter *iter, bool syslog, iter->cur_seq = r.info->seq + 1; ret = true; out: + printk_safe_exit_irqrestore(flags); if (len) *len = l; return ret; } - -/** - * kmsg_dump_get_line - retrieve one kmsg log line - * @iter: kmsg dump iterator - * @syslog: include the "<4>" prefixes - * @line: buffer to copy the line to - * @size: maximum size of the buffer - * @len: length of line placed into buffer - * - * Start at the beginning of the kmsg buffer, with the oldest kmsg - * record, and copy one record into the provided buffer. - * - * Consecutive calls will return the next available record moving - * towards the end of the buffer with the youngest messages. - * - * A return value of FALSE indicates that there are no more records to - * read. - */ -bool kmsg_dump_get_line(struct kmsg_dump_iter *iter, bool syslog, - char *line, size_t size, size_t *len) -{ - unsigned long flags; - bool ret; - - printk_safe_enter_irqsave(flags); - ret = kmsg_dump_get_line_nolock(iter, syslog, line, size, len); - printk_safe_exit_irqrestore(flags); - - return ret; -} EXPORT_SYMBOL_GPL(kmsg_dump_get_line); /** @@ -3550,22 +3521,6 @@ out: } EXPORT_SYMBOL_GPL(kmsg_dump_get_buffer); -/** - * kmsg_dump_rewind_nolock - reset the iterator (unlocked version) - * @iter: kmsg dump iterator - * - * Reset the dumper's iterator so that kmsg_dump_get_line() and - * kmsg_dump_get_buffer() can be called again and used multiple - * times within the same dumper.dump() callback. - * - * The function is similar to kmsg_dump_rewind(), but grabs no locks. - */ -void kmsg_dump_rewind_nolock(struct kmsg_dump_iter *iter) -{ - iter->cur_seq = latched_seq_read_nolock(&clear_seq); - iter->next_seq = prb_next_seq(prb); -} - /** * kmsg_dump_rewind - reset the iterator * @iter: kmsg dump iterator @@ -3579,7 +3534,8 @@ void kmsg_dump_rewind(struct kmsg_dump_iter *iter) unsigned long flags; printk_safe_enter_irqsave(flags); - kmsg_dump_rewind_nolock(iter); + iter->cur_seq = latched_seq_read_nolock(&clear_seq); + iter->next_seq = prb_next_seq(prb); printk_safe_exit_irqrestore(flags); } EXPORT_SYMBOL_GPL(kmsg_dump_rewind); -- cgit v1.2.3-71-gd317 From d027fdc4fa30a409e7425219d0d089e4e4ebdc4d Mon Sep 17 00:00:00 2001 From: Sumit Garg Date: Wed, 24 Feb 2021 12:46:53 +0530 Subject: kdb: Remove redundant function definitions/prototypes Cleanup kdb code to get rid of unused function definitions/prototypes. Signed-off-by: Sumit Garg Link: https://lore.kernel.org/r/20210224071653.409150-1-sumit.garg@linaro.org Reviewed-by: Douglas Anderson Signed-off-by: Daniel Thompson --- kernel/debug/kdb/kdb_private.h | 2 -- kernel/debug/kdb/kdb_support.c | 18 ------------------ 2 files changed, 20 deletions(-) (limited to 'kernel/debug') diff --git a/kernel/debug/kdb/kdb_private.h b/kernel/debug/kdb/kdb_private.h index 6cb92f7bbbd0..135a706c2e78 100644 --- a/kernel/debug/kdb/kdb_private.h +++ b/kernel/debug/kdb/kdb_private.h @@ -207,9 +207,7 @@ extern unsigned long kdb_task_state(const struct task_struct *p, unsigned long mask); extern void kdb_ps_suppressed(void); extern void kdb_ps1(const struct task_struct *p); -extern void kdb_print_nameval(const char *name, unsigned long val); extern void kdb_send_sig(struct task_struct *p, int sig); -extern void kdb_meminfo_proc_show(void); extern char kdb_getchar(void); extern char *kdb_getstr(char *, size_t, const char *); extern void kdb_gdb_state_pass(char *buf); diff --git a/kernel/debug/kdb/kdb_support.c b/kernel/debug/kdb/kdb_support.c index f7c1885abeb6..91bb666d7c03 100644 --- a/kernel/debug/kdb/kdb_support.c +++ b/kernel/debug/kdb/kdb_support.c @@ -654,24 +654,6 @@ unsigned long kdb_task_state(const struct task_struct *p, unsigned long mask) return (mask & kdb_task_state_string(state)) != 0; } -/* - * kdb_print_nameval - Print a name and its value, converting the - * value to a symbol lookup if possible. - * Inputs: - * name field name to print - * val value of field - */ -void kdb_print_nameval(const char *name, unsigned long val) -{ - kdb_symtab_t symtab; - kdb_printf(" %-11.11s ", name); - if (kdbnearsym(val, &symtab)) - kdb_symbol_print(val, &symtab, - KDB_SP_VALUE|KDB_SP_SYMSIZE|KDB_SP_NEWLINE); - else - kdb_printf("0x%lx\n", val); -} - /* Last ditch allocator for debugging, so we can still debug even when * the GFP_ATOMIC pool has been exhausted. The algorithms are tuned * for space usage, not for speed. One smallish memory pool, the free -- cgit v1.2.3-71-gd317 From e4f291b3f7bb1855318e1009de65585a72d595ad Mon Sep 17 00:00:00 2001 From: Sumit Garg Date: Wed, 24 Feb 2021 12:38:27 +0530 Subject: kdb: Simplify kdb commands registration Simplify kdb commands registration via using linked list instead of static array for commands storage. Signed-off-by: Sumit Garg Link: https://lore.kernel.org/r/20210224070827.408771-1-sumit.garg@linaro.org Reviewed-by: Douglas Anderson [daniel.thompson@linaro.org: Removed a bunch of .cmd_minline = 0 initializers] Signed-off-by: Daniel Thompson --- kernel/debug/kdb/kdb_bp.c | 75 ++++--- kernel/debug/kdb/kdb_main.c | 446 ++++++++++++++++++++++++----------------- kernel/debug/kdb/kdb_private.h | 3 + 3 files changed, 311 insertions(+), 213 deletions(-) (limited to 'kernel/debug') diff --git a/kernel/debug/kdb/kdb_bp.c b/kernel/debug/kdb/kdb_bp.c index ec4940146612..2168f8dacb99 100644 --- a/kernel/debug/kdb/kdb_bp.c +++ b/kernel/debug/kdb/kdb_bp.c @@ -522,6 +522,54 @@ static int kdb_ss(int argc, const char **argv) return KDB_CMD_SS; } +static kdbtab_t bptab[] = { + { .cmd_name = "bp", + .cmd_func = kdb_bp, + .cmd_usage = "[]", + .cmd_help = "Set/Display breakpoints", + .cmd_flags = KDB_ENABLE_FLOW_CTRL | KDB_REPEAT_NO_ARGS, + }, + { .cmd_name = "bl", + .cmd_func = kdb_bp, + .cmd_usage = "[]", + .cmd_help = "Display breakpoints", + .cmd_flags = KDB_ENABLE_FLOW_CTRL | KDB_REPEAT_NO_ARGS, + }, + { .cmd_name = "bc", + .cmd_func = kdb_bc, + .cmd_usage = "", + .cmd_help = "Clear Breakpoint", + .cmd_flags = KDB_ENABLE_FLOW_CTRL, + }, + { .cmd_name = "be", + .cmd_func = kdb_bc, + .cmd_usage = "", + .cmd_help = "Enable Breakpoint", + .cmd_flags = KDB_ENABLE_FLOW_CTRL, + }, + { .cmd_name = "bd", + .cmd_func = kdb_bc, + .cmd_usage = "", + .cmd_help = "Disable Breakpoint", + .cmd_flags = KDB_ENABLE_FLOW_CTRL, + }, + { .cmd_name = "ss", + .cmd_func = kdb_ss, + .cmd_usage = "", + .cmd_help = "Single Step", + .cmd_minlen = 1, + .cmd_flags = KDB_ENABLE_FLOW_CTRL | KDB_REPEAT_NO_ARGS, + }, +}; + +static kdbtab_t bphcmd = { + .cmd_name = "bph", + .cmd_func = kdb_bp, + .cmd_usage = "[]", + .cmd_help = "[datar [length]|dataw [length]] Set hw brk", + .cmd_flags = KDB_ENABLE_FLOW_CTRL | KDB_REPEAT_NO_ARGS, +}; + /* Initialize the breakpoint table and register breakpoint commands. */ void __init kdb_initbptab(void) @@ -537,30 +585,7 @@ void __init kdb_initbptab(void) for (i = 0, bp = kdb_breakpoints; i < KDB_MAXBPT; i++, bp++) bp->bp_free = 1; - kdb_register_flags("bp", kdb_bp, "[]", - "Set/Display breakpoints", 0, - KDB_ENABLE_FLOW_CTRL | KDB_REPEAT_NO_ARGS); - kdb_register_flags("bl", kdb_bp, "[]", - "Display breakpoints", 0, - KDB_ENABLE_FLOW_CTRL | KDB_REPEAT_NO_ARGS); + kdb_register_table(bptab, ARRAY_SIZE(bptab)); if (arch_kgdb_ops.flags & KGDB_HW_BREAKPOINT) - kdb_register_flags("bph", kdb_bp, "[]", - "[datar [length]|dataw [length]] Set hw brk", 0, - KDB_ENABLE_FLOW_CTRL | KDB_REPEAT_NO_ARGS); - kdb_register_flags("bc", kdb_bc, "", - "Clear Breakpoint", 0, - KDB_ENABLE_FLOW_CTRL); - kdb_register_flags("be", kdb_bc, "", - "Enable Breakpoint", 0, - KDB_ENABLE_FLOW_CTRL); - kdb_register_flags("bd", kdb_bc, "", - "Disable Breakpoint", 0, - KDB_ENABLE_FLOW_CTRL); - - kdb_register_flags("ss", kdb_ss, "", - "Single Step", 1, - KDB_ENABLE_FLOW_CTRL | KDB_REPEAT_NO_ARGS); - /* - * Architecture dependent initialization. - */ + kdb_register_table(&bphcmd, 1); } diff --git a/kernel/debug/kdb/kdb_main.c b/kernel/debug/kdb/kdb_main.c index 930ac1b25ec7..95a1b1f54326 100644 --- a/kernel/debug/kdb/kdb_main.c +++ b/kernel/debug/kdb/kdb_main.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include @@ -84,15 +85,8 @@ static unsigned int kdb_continue_catastrophic = static unsigned int kdb_continue_catastrophic; #endif -/* kdb_commands describes the available commands. */ -static kdbtab_t *kdb_commands; -#define KDB_BASE_CMD_MAX 50 -static int kdb_max_commands = KDB_BASE_CMD_MAX; -static kdbtab_t kdb_base_commands[KDB_BASE_CMD_MAX]; -#define for_each_kdbcmd(cmd, num) \ - for ((cmd) = kdb_base_commands, (num) = 0; \ - num < kdb_max_commands; \ - num++, num == KDB_BASE_CMD_MAX ? cmd = kdb_commands : cmd++) +/* kdb_cmds_head describes the available commands. */ +static LIST_HEAD(kdb_cmds_head); typedef struct _kdbmsg { int km_diag; /* kdb diagnostic */ @@ -921,7 +915,7 @@ int kdb_parse(const char *cmdstr) char *cp; char *cpp, quoted; kdbtab_t *tp; - int i, escaped, ignore_errors = 0, check_grep = 0; + int escaped, ignore_errors = 0, check_grep = 0; /* * First tokenize the command string. @@ -1011,25 +1005,17 @@ int kdb_parse(const char *cmdstr) ++argv[0]; } - for_each_kdbcmd(tp, i) { - if (tp->cmd_name) { - /* - * If this command is allowed to be abbreviated, - * check to see if this is it. - */ - - if (tp->cmd_minlen - && (strlen(argv[0]) <= tp->cmd_minlen)) { - if (strncmp(argv[0], - tp->cmd_name, - tp->cmd_minlen) == 0) { - break; - } - } + list_for_each_entry(tp, &kdb_cmds_head, list_node) { + /* + * If this command is allowed to be abbreviated, + * check to see if this is it. + */ + if (tp->cmd_minlen && (strlen(argv[0]) <= tp->cmd_minlen) && + (strncmp(argv[0], tp->cmd_name, tp->cmd_minlen) == 0)) + break; - if (strcmp(argv[0], tp->cmd_name) == 0) - break; - } + if (strcmp(argv[0], tp->cmd_name) == 0) + break; } /* @@ -1037,19 +1023,15 @@ int kdb_parse(const char *cmdstr) * few characters of this match any of the known commands. * e.g., md1c20 should match md. */ - if (i == kdb_max_commands) { - for_each_kdbcmd(tp, i) { - if (tp->cmd_name) { - if (strncmp(argv[0], - tp->cmd_name, - strlen(tp->cmd_name)) == 0) { - break; - } - } + if (list_entry_is_head(tp, &kdb_cmds_head, list_node)) { + list_for_each_entry(tp, &kdb_cmds_head, list_node) { + if (strncmp(argv[0], tp->cmd_name, + strlen(tp->cmd_name)) == 0) + break; } } - if (i < kdb_max_commands) { + if (!list_entry_is_head(tp, &kdb_cmds_head, list_node)) { int result; if (!kdb_check_flags(tp->cmd_flags, kdb_cmd_enabled, argc <= 1)) @@ -2428,17 +2410,14 @@ static int kdb_kgdb(int argc, const char **argv) static int kdb_help(int argc, const char **argv) { kdbtab_t *kt; - int i; kdb_printf("%-15.15s %-20.20s %s\n", "Command", "Usage", "Description"); kdb_printf("-----------------------------" "-----------------------------\n"); - for_each_kdbcmd(kt, i) { + list_for_each_entry(kt, &kdb_cmds_head, list_node) { char *space = ""; if (KDB_FLAG(CMD_INTERRUPT)) return 0; - if (!kt->cmd_name) - continue; if (!kdb_check_flags(kt->cmd_flags, kdb_cmd_enabled, true)) continue; if (strlen(kt->cmd_usage) > 20) @@ -2659,7 +2638,6 @@ static int kdb_grep_help(int argc, const char **argv) * Returns: * zero for success, one if a duplicate command. */ -#define kdb_command_extend 50 /* arbitrary */ int kdb_register_flags(char *cmd, kdb_func_t func, char *usage, @@ -2667,49 +2645,20 @@ int kdb_register_flags(char *cmd, short minlen, kdb_cmdflags_t flags) { - int i; kdbtab_t *kp; - /* - * Brute force method to determine duplicates - */ - for_each_kdbcmd(kp, i) { - if (kp->cmd_name && (strcmp(kp->cmd_name, cmd) == 0)) { + list_for_each_entry(kp, &kdb_cmds_head, list_node) { + if (strcmp(kp->cmd_name, cmd) == 0) { kdb_printf("Duplicate kdb command registered: " "%s, func %px help %s\n", cmd, func, help); return 1; } } - /* - * Insert command into first available location in table - */ - for_each_kdbcmd(kp, i) { - if (kp->cmd_name == NULL) - break; - } - - if (i >= kdb_max_commands) { - kdbtab_t *new = kmalloc_array(kdb_max_commands - - KDB_BASE_CMD_MAX + - kdb_command_extend, - sizeof(*new), - GFP_KDB); - if (!new) { - kdb_printf("Could not allocate new kdb_command " - "table\n"); - return 1; - } - if (kdb_commands) { - memcpy(new, kdb_commands, - (kdb_max_commands - KDB_BASE_CMD_MAX) * sizeof(*new)); - kfree(kdb_commands); - } - memset(new + kdb_max_commands - KDB_BASE_CMD_MAX, 0, - kdb_command_extend * sizeof(*new)); - kdb_commands = new; - kp = kdb_commands + kdb_max_commands - KDB_BASE_CMD_MAX; - kdb_max_commands += kdb_command_extend; + kp = kmalloc(sizeof(*kp), GFP_KDB); + if (!kp) { + kdb_printf("Could not allocate new kdb_command table\n"); + return 1; } kp->cmd_name = cmd; @@ -2718,11 +2667,27 @@ int kdb_register_flags(char *cmd, kp->cmd_help = help; kp->cmd_minlen = minlen; kp->cmd_flags = flags; + kp->is_dynamic = true; + + list_add_tail(&kp->list_node, &kdb_cmds_head); return 0; } EXPORT_SYMBOL_GPL(kdb_register_flags); +/* + * kdb_register_table() - This function is used to register a kdb command + * table. + * @kp: pointer to kdb command table + * @len: length of kdb command table + */ +void kdb_register_table(kdbtab_t *kp, size_t len) +{ + while (len--) { + list_add_tail(&kp->list_node, &kdb_cmds_head); + kp++; + } +} /* * kdb_register - Compatibility register function for commands that do @@ -2757,15 +2722,16 @@ EXPORT_SYMBOL_GPL(kdb_register); */ int kdb_unregister(char *cmd) { - int i; kdbtab_t *kp; /* * find the command. */ - for_each_kdbcmd(kp, i) { - if (kp->cmd_name && (strcmp(kp->cmd_name, cmd) == 0)) { - kp->cmd_name = NULL; + list_for_each_entry(kp, &kdb_cmds_head, list_node) { + if (strcmp(kp->cmd_name, cmd) == 0) { + list_del(&kp->list_node); + if (kp->is_dynamic) + kfree(kp); return 0; } } @@ -2775,118 +2741,222 @@ int kdb_unregister(char *cmd) } EXPORT_SYMBOL_GPL(kdb_unregister); -/* Initialize the kdb command table. */ -static void __init kdb_inittab(void) -{ - int i; - kdbtab_t *kp; - - for_each_kdbcmd(kp, i) - kp->cmd_name = NULL; - - kdb_register_flags("md", kdb_md, "", - "Display Memory Contents, also mdWcN, e.g. md8c1", 1, - KDB_ENABLE_MEM_READ | KDB_REPEAT_NO_ARGS); - kdb_register_flags("mdr", kdb_md, " ", - "Display Raw Memory", 0, - KDB_ENABLE_MEM_READ | KDB_REPEAT_NO_ARGS); - kdb_register_flags("mdp", kdb_md, " ", - "Display Physical Memory", 0, - KDB_ENABLE_MEM_READ | KDB_REPEAT_NO_ARGS); - kdb_register_flags("mds", kdb_md, "", - "Display Memory Symbolically", 0, - KDB_ENABLE_MEM_READ | KDB_REPEAT_NO_ARGS); - kdb_register_flags("mm", kdb_mm, " ", - "Modify Memory Contents", 0, - KDB_ENABLE_MEM_WRITE | KDB_REPEAT_NO_ARGS); - kdb_register_flags("go", kdb_go, "[]", - "Continue Execution", 1, - KDB_ENABLE_REG_WRITE | KDB_ENABLE_ALWAYS_SAFE_NO_ARGS); - kdb_register_flags("rd", kdb_rd, "", - "Display Registers", 0, - KDB_ENABLE_REG_READ); - kdb_register_flags("rm", kdb_rm, " ", - "Modify Registers", 0, - KDB_ENABLE_REG_WRITE); - kdb_register_flags("ef", kdb_ef, "", - "Display exception frame", 0, - KDB_ENABLE_MEM_READ); - kdb_register_flags("bt", kdb_bt, "[]", - "Stack traceback", 1, - KDB_ENABLE_MEM_READ | KDB_ENABLE_INSPECT_NO_ARGS); - kdb_register_flags("btp", kdb_bt, "", - "Display stack for process ", 0, - KDB_ENABLE_INSPECT); - kdb_register_flags("bta", kdb_bt, "[D|R|S|T|C|Z|E|U|I|M|A]", - "Backtrace all processes matching state flag", 0, - KDB_ENABLE_INSPECT); - kdb_register_flags("btc", kdb_bt, "", - "Backtrace current process on each cpu", 0, - KDB_ENABLE_INSPECT); - kdb_register_flags("btt", kdb_bt, "", - "Backtrace process given its struct task address", 0, - KDB_ENABLE_MEM_READ | KDB_ENABLE_INSPECT_NO_ARGS); - kdb_register_flags("env", kdb_env, "", - "Show environment variables", 0, - KDB_ENABLE_ALWAYS_SAFE); - kdb_register_flags("set", kdb_set, "", - "Set environment variables", 0, - KDB_ENABLE_ALWAYS_SAFE); - kdb_register_flags("help", kdb_help, "", - "Display Help Message", 1, - KDB_ENABLE_ALWAYS_SAFE); - kdb_register_flags("?", kdb_help, "", - "Display Help Message", 0, - KDB_ENABLE_ALWAYS_SAFE); - kdb_register_flags("cpu", kdb_cpu, "", - "Switch to new cpu", 0, - KDB_ENABLE_ALWAYS_SAFE_NO_ARGS); - kdb_register_flags("kgdb", kdb_kgdb, "", - "Enter kgdb mode", 0, 0); - kdb_register_flags("ps", kdb_ps, "[|A]", - "Display active task list", 0, - KDB_ENABLE_INSPECT); - kdb_register_flags("pid", kdb_pid, "", - "Switch to another task", 0, - KDB_ENABLE_INSPECT); - kdb_register_flags("reboot", kdb_reboot, "", - "Reboot the machine immediately", 0, - KDB_ENABLE_REBOOT); +static kdbtab_t maintab[] = { + { .cmd_name = "md", + .cmd_func = kdb_md, + .cmd_usage = "", + .cmd_help = "Display Memory Contents, also mdWcN, e.g. md8c1", + .cmd_minlen = 1, + .cmd_flags = KDB_ENABLE_MEM_READ | KDB_REPEAT_NO_ARGS, + }, + { .cmd_name = "mdr", + .cmd_func = kdb_md, + .cmd_usage = " ", + .cmd_help = "Display Raw Memory", + .cmd_flags = KDB_ENABLE_MEM_READ | KDB_REPEAT_NO_ARGS, + }, + { .cmd_name = "mdp", + .cmd_func = kdb_md, + .cmd_usage = " ", + .cmd_help = "Display Physical Memory", + .cmd_flags = KDB_ENABLE_MEM_READ | KDB_REPEAT_NO_ARGS, + }, + { .cmd_name = "mds", + .cmd_func = kdb_md, + .cmd_usage = "", + .cmd_help = "Display Memory Symbolically", + .cmd_flags = KDB_ENABLE_MEM_READ | KDB_REPEAT_NO_ARGS, + }, + { .cmd_name = "mm", + .cmd_func = kdb_mm, + .cmd_usage = " ", + .cmd_help = "Modify Memory Contents", + .cmd_flags = KDB_ENABLE_MEM_WRITE | KDB_REPEAT_NO_ARGS, + }, + { .cmd_name = "go", + .cmd_func = kdb_go, + .cmd_usage = "[]", + .cmd_help = "Continue Execution", + .cmd_minlen = 1, + .cmd_flags = KDB_ENABLE_REG_WRITE | + KDB_ENABLE_ALWAYS_SAFE_NO_ARGS, + }, + { .cmd_name = "rd", + .cmd_func = kdb_rd, + .cmd_usage = "", + .cmd_help = "Display Registers", + .cmd_flags = KDB_ENABLE_REG_READ, + }, + { .cmd_name = "rm", + .cmd_func = kdb_rm, + .cmd_usage = " ", + .cmd_help = "Modify Registers", + .cmd_flags = KDB_ENABLE_REG_WRITE, + }, + { .cmd_name = "ef", + .cmd_func = kdb_ef, + .cmd_usage = "", + .cmd_help = "Display exception frame", + .cmd_flags = KDB_ENABLE_MEM_READ, + }, + { .cmd_name = "bt", + .cmd_func = kdb_bt, + .cmd_usage = "[]", + .cmd_help = "Stack traceback", + .cmd_minlen = 1, + .cmd_flags = KDB_ENABLE_MEM_READ | KDB_ENABLE_INSPECT_NO_ARGS, + }, + { .cmd_name = "btp", + .cmd_func = kdb_bt, + .cmd_usage = "", + .cmd_help = "Display stack for process ", + .cmd_flags = KDB_ENABLE_INSPECT, + }, + { .cmd_name = "bta", + .cmd_func = kdb_bt, + .cmd_usage = "[D|R|S|T|C|Z|E|U|I|M|A]", + .cmd_help = "Backtrace all processes matching state flag", + .cmd_flags = KDB_ENABLE_INSPECT, + }, + { .cmd_name = "btc", + .cmd_func = kdb_bt, + .cmd_usage = "", + .cmd_help = "Backtrace current process on each cpu", + .cmd_flags = KDB_ENABLE_INSPECT, + }, + { .cmd_name = "btt", + .cmd_func = kdb_bt, + .cmd_usage = "", + .cmd_help = "Backtrace process given its struct task address", + .cmd_flags = KDB_ENABLE_MEM_READ | KDB_ENABLE_INSPECT_NO_ARGS, + }, + { .cmd_name = "env", + .cmd_func = kdb_env, + .cmd_usage = "", + .cmd_help = "Show environment variables", + .cmd_flags = KDB_ENABLE_ALWAYS_SAFE, + }, + { .cmd_name = "set", + .cmd_func = kdb_set, + .cmd_usage = "", + .cmd_help = "Set environment variables", + .cmd_flags = KDB_ENABLE_ALWAYS_SAFE, + }, + { .cmd_name = "help", + .cmd_func = kdb_help, + .cmd_usage = "", + .cmd_help = "Display Help Message", + .cmd_minlen = 1, + .cmd_flags = KDB_ENABLE_ALWAYS_SAFE, + }, + { .cmd_name = "?", + .cmd_func = kdb_help, + .cmd_usage = "", + .cmd_help = "Display Help Message", + .cmd_flags = KDB_ENABLE_ALWAYS_SAFE, + }, + { .cmd_name = "cpu", + .cmd_func = kdb_cpu, + .cmd_usage = "", + .cmd_help = "Switch to new cpu", + .cmd_flags = KDB_ENABLE_ALWAYS_SAFE_NO_ARGS, + }, + { .cmd_name = "kgdb", + .cmd_func = kdb_kgdb, + .cmd_usage = "", + .cmd_help = "Enter kgdb mode", + .cmd_flags = 0, + }, + { .cmd_name = "ps", + .cmd_func = kdb_ps, + .cmd_usage = "[|A]", + .cmd_help = "Display active task list", + .cmd_flags = KDB_ENABLE_INSPECT, + }, + { .cmd_name = "pid", + .cmd_func = kdb_pid, + .cmd_usage = "", + .cmd_help = "Switch to another task", + .cmd_flags = KDB_ENABLE_INSPECT, + }, + { .cmd_name = "reboot", + .cmd_func = kdb_reboot, + .cmd_usage = "", + .cmd_help = "Reboot the machine immediately", + .cmd_flags = KDB_ENABLE_REBOOT, + }, #if defined(CONFIG_MODULES) - kdb_register_flags("lsmod", kdb_lsmod, "", - "List loaded kernel modules", 0, - KDB_ENABLE_INSPECT); + { .cmd_name = "lsmod", + .cmd_func = kdb_lsmod, + .cmd_usage = "", + .cmd_help = "List loaded kernel modules", + .cmd_flags = KDB_ENABLE_INSPECT, + }, #endif #if defined(CONFIG_MAGIC_SYSRQ) - kdb_register_flags("sr", kdb_sr, "", - "Magic SysRq key", 0, - KDB_ENABLE_ALWAYS_SAFE); + { .cmd_name = "sr", + .cmd_func = kdb_sr, + .cmd_usage = "", + .cmd_help = "Magic SysRq key", + .cmd_flags = KDB_ENABLE_ALWAYS_SAFE, + }, #endif #if defined(CONFIG_PRINTK) - kdb_register_flags("dmesg", kdb_dmesg, "[lines]", - "Display syslog buffer", 0, - KDB_ENABLE_ALWAYS_SAFE); + { .cmd_name = "dmesg", + .cmd_func = kdb_dmesg, + .cmd_usage = "[lines]", + .cmd_help = "Display syslog buffer", + .cmd_flags = KDB_ENABLE_ALWAYS_SAFE, + }, #endif - if (arch_kgdb_ops.enable_nmi) { - kdb_register_flags("disable_nmi", kdb_disable_nmi, "", - "Disable NMI entry to KDB", 0, - KDB_ENABLE_ALWAYS_SAFE); - } - kdb_register_flags("defcmd", kdb_defcmd, "name \"usage\" \"help\"", - "Define a set of commands, down to endefcmd", 0, - KDB_ENABLE_ALWAYS_SAFE); - kdb_register_flags("kill", kdb_kill, "<-signal> ", - "Send a signal to a process", 0, - KDB_ENABLE_SIGNAL); - kdb_register_flags("summary", kdb_summary, "", - "Summarize the system", 4, - KDB_ENABLE_ALWAYS_SAFE); - kdb_register_flags("per_cpu", kdb_per_cpu, " [] []", - "Display per_cpu variables", 3, - KDB_ENABLE_MEM_READ); - kdb_register_flags("grephelp", kdb_grep_help, "", - "Display help on | grep", 0, - KDB_ENABLE_ALWAYS_SAFE); + { .cmd_name = "defcmd", + .cmd_func = kdb_defcmd, + .cmd_usage = "name \"usage\" \"help\"", + .cmd_help = "Define a set of commands, down to endefcmd", + .cmd_flags = KDB_ENABLE_ALWAYS_SAFE, + }, + { .cmd_name = "kill", + .cmd_func = kdb_kill, + .cmd_usage = "<-signal> ", + .cmd_help = "Send a signal to a process", + .cmd_flags = KDB_ENABLE_SIGNAL, + }, + { .cmd_name = "summary", + .cmd_func = kdb_summary, + .cmd_usage = "", + .cmd_help = "Summarize the system", + .cmd_minlen = 4, + .cmd_flags = KDB_ENABLE_ALWAYS_SAFE, + }, + { .cmd_name = "per_cpu", + .cmd_func = kdb_per_cpu, + .cmd_usage = " [] []", + .cmd_help = "Display per_cpu variables", + .cmd_minlen = 3, + .cmd_flags = KDB_ENABLE_MEM_READ, + }, + { .cmd_name = "grephelp", + .cmd_func = kdb_grep_help, + .cmd_usage = "", + .cmd_help = "Display help on | grep", + .cmd_flags = KDB_ENABLE_ALWAYS_SAFE, + }, +}; + +static kdbtab_t nmicmd = { + .cmd_name = "disable_nmi", + .cmd_func = kdb_disable_nmi, + .cmd_usage = "", + .cmd_help = "Disable NMI entry to KDB", + .cmd_flags = KDB_ENABLE_ALWAYS_SAFE, +}; + +/* Initialize the kdb command table. */ +static void __init kdb_inittab(void) +{ + kdb_register_table(maintab, ARRAY_SIZE(maintab)); + if (arch_kgdb_ops.enable_nmi) + kdb_register_table(&nmicmd, 1); } /* Execute any commands defined in kdb_cmds. */ diff --git a/kernel/debug/kdb/kdb_private.h b/kernel/debug/kdb/kdb_private.h index 135a706c2e78..ccbed9089808 100644 --- a/kernel/debug/kdb/kdb_private.h +++ b/kernel/debug/kdb/kdb_private.h @@ -174,8 +174,11 @@ typedef struct _kdbtab { short cmd_minlen; /* Minimum legal # command * chars required */ kdb_cmdflags_t cmd_flags; /* Command behaviour flags */ + struct list_head list_node; /* Command list */ + bool is_dynamic; /* Command table allocation type */ } kdbtab_t; +extern void kdb_register_table(kdbtab_t *kp, size_t len); extern int kdb_bt(int, const char **); /* KDB display back trace */ /* KDB breakpoint management functions */ -- cgit v1.2.3-71-gd317 From 2bbd9b0f2b4ec0afa80b52b1a68bd3bc80618275 Mon Sep 17 00:00:00 2001 From: Bhaskar Chowdhury Date: Wed, 17 Mar 2021 16:16:58 +0530 Subject: kernel: debug: Ordinary typo fixes in the file gdbstub.c s/overwitten/overwritten/ s/procesing/processing/ Signed-off-by: Bhaskar Chowdhury Link: https://lore.kernel.org/r/20210317104658.4053473-1-unixbhaskar@gmail.com Acked-by: Randy Dunlap Signed-off-by: Daniel Thompson --- kernel/debug/gdbstub.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'kernel/debug') diff --git a/kernel/debug/gdbstub.c b/kernel/debug/gdbstub.c index e149a0ac9e9e..8372897402f4 100644 --- a/kernel/debug/gdbstub.c +++ b/kernel/debug/gdbstub.c @@ -321,7 +321,7 @@ int kgdb_hex2long(char **ptr, unsigned long *long_val) /* * Copy the binary array pointed to by buf into mem. Fix $, #, and * 0x7d escaped with 0x7d. Return -EFAULT on failure or 0 on success. - * The input buf is overwitten with the result to write to mem. + * The input buf is overwritten with the result to write to mem. */ static int kgdb_ebin2mem(char *buf, char *mem, int count) { @@ -952,7 +952,7 @@ static int gdb_cmd_exception_pass(struct kgdb_state *ks) } /* - * This function performs all gdbserial command procesing + * This function performs all gdbserial command processing */ int gdb_serial_stub(struct kgdb_state *ks) { -- cgit v1.2.3-71-gd317 From 83fa2d13d628be901a21cdfb3553963cd8858052 Mon Sep 17 00:00:00 2001 From: Sumit Garg Date: Mon, 8 Feb 2021 13:32:22 +0530 Subject: kdb: Refactor env variables get/set code Add two new kdb environment access methods as kdb_setenv() and kdb_printenv() in order to abstract out environment access code from kdb command functions. Also, replace (char *)0 with NULL as an initializer for environment variables array. Signed-off-by: Sumit Garg Reviewed-by: Douglas Anderson Link: https://lore.kernel.org/r/1612771342-16883-1-git-send-email-sumit.garg@linaro.org [daniel.thompson@linaro.org: Replaced (char *)0/NULL initializers with an array size] Signed-off-by: Daniel Thompson --- kernel/debug/kdb/kdb_main.c | 142 +++++++++++++++++++++----------------------- 1 file changed, 68 insertions(+), 74 deletions(-) (limited to 'kernel/debug') diff --git a/kernel/debug/kdb/kdb_main.c b/kernel/debug/kdb/kdb_main.c index 95a1b1f54326..405d24aa5156 100644 --- a/kernel/debug/kdb/kdb_main.c +++ b/kernel/debug/kdb/kdb_main.c @@ -140,42 +140,18 @@ static const int __nkdb_err = ARRAY_SIZE(kdbmsgs); * KDB_ENVBUFSIZE if required). */ -static char *__env[] = { +static char *__env[31] = { #if defined(CONFIG_SMP) - "PROMPT=[%d]kdb> ", + "PROMPT=[%d]kdb> ", #else - "PROMPT=kdb> ", + "PROMPT=kdb> ", #endif - "MOREPROMPT=more> ", - "RADIX=16", - "MDCOUNT=8", /* lines of md output */ - KDB_PLATFORM_ENV, - "DTABCOUNT=30", - "NOSECT=1", - (char *)0, - (char *)0, - (char *)0, - (char *)0, - (char *)0, - (char *)0, - (char *)0, - (char *)0, - (char *)0, - (char *)0, - (char *)0, - (char *)0, - (char *)0, - (char *)0, - (char *)0, - (char *)0, - (char *)0, - (char *)0, - (char *)0, - (char *)0, - (char *)0, - (char *)0, - (char *)0, - (char *)0, + "MOREPROMPT=more> ", + "RADIX=16", + "MDCOUNT=8", /* lines of md output */ + KDB_PLATFORM_ENV, + "DTABCOUNT=30", + "NOSECT=1", }; static const int __nenv = ARRAY_SIZE(__env); @@ -317,6 +293,63 @@ int kdbgetintenv(const char *match, int *value) return diag; } +/* + * kdb_setenv() - Alter an existing environment variable or create a new one. + * @var: Name of the variable + * @val: Value of the variable + * + * Return: Zero on success, a kdb diagnostic on failure. + */ +static int kdb_setenv(const char *var, const char *val) +{ + int i; + char *ep; + size_t varlen, vallen; + + varlen = strlen(var); + vallen = strlen(val); + ep = kdballocenv(varlen + vallen + 2); + if (ep == (char *)0) + return KDB_ENVBUFFULL; + + sprintf(ep, "%s=%s", var, val); + + for (i = 0; i < __nenv; i++) { + if (__env[i] + && ((strncmp(__env[i], var, varlen) == 0) + && ((__env[i][varlen] == '\0') + || (__env[i][varlen] == '=')))) { + __env[i] = ep; + return 0; + } + } + + /* + * Wasn't existing variable. Fit into slot. + */ + for (i = 0; i < __nenv-1; i++) { + if (__env[i] == (char *)0) { + __env[i] = ep; + return 0; + } + } + + return KDB_ENVFULL; +} + +/* + * kdb_printenv() - Display the current environment variables. + */ +static void kdb_printenv(void) +{ + int i; + + for (i = 0; i < __nenv; i++) { + if (__env[i]) + kdb_printf("%s\n", __env[i]); + } +} + /* * kdbgetularg - This function will convert a numeric string into an * unsigned long value. @@ -374,10 +407,6 @@ int kdbgetu64arg(const char *arg, u64 *value) */ int kdb_set(int argc, const char **argv) { - int i; - char *ep; - size_t varlen, vallen; - /* * we can be invoked two ways: * set var=value argv[1]="var", argv[2]="value" @@ -422,37 +451,7 @@ int kdb_set(int argc, const char **argv) * Tokenizer squashed the '=' sign. argv[1] is variable * name, argv[2] = value. */ - varlen = strlen(argv[1]); - vallen = strlen(argv[2]); - ep = kdballocenv(varlen + vallen + 2); - if (ep == (char *)0) - return KDB_ENVBUFFULL; - - sprintf(ep, "%s=%s", argv[1], argv[2]); - - ep[varlen+vallen+1] = '\0'; - - for (i = 0; i < __nenv; i++) { - if (__env[i] - && ((strncmp(__env[i], argv[1], varlen) == 0) - && ((__env[i][varlen] == '\0') - || (__env[i][varlen] == '=')))) { - __env[i] = ep; - return 0; - } - } - - /* - * Wasn't existing variable. Fit into slot. - */ - for (i = 0; i < __nenv-1; i++) { - if (__env[i] == (char *)0) { - __env[i] = ep; - return 0; - } - } - - return KDB_ENVFULL; + return kdb_setenv(argv[1], argv[2]); } static int kdb_check_regs(void) @@ -2055,12 +2054,7 @@ static int kdb_lsmod(int argc, const char **argv) static int kdb_env(int argc, const char **argv) { - int i; - - for (i = 0; i < __nenv; i++) { - if (__env[i]) - kdb_printf("%s\n", __env[i]); - } + kdb_printenv(); if (KDB_DEBUG(MASK)) kdb_printf("KDBDEBUG=0x%x\n", -- cgit v1.2.3-71-gd317