On 2024/01/22 3:31, Edward Chron wrote: > Submission to Project: crash > Component: dmesg > Files: kernel.c printk.c symbols.c help.c defs.h > Code level patch applied against: 8.0.4++ - latest code pulled from > https://github.com/crash-utility/crash.git > crash Issue #164 > Patch Version #2: per review from Hagio Kazuhito <k-hagio-ab@xxxxxxx> Thanks for the update, looks good to me. Acked-by: Kazuhito Hagio <k-hagio-ab@xxxxxxx> Thanks, Kazu > Tested with Kernel version and makedumpfile version: > Linux Kernel Testing: Linux catalina 6.6.6 #4 SMP PREEMPT_DYNAMIC > Tue Dec 12 23:11:30 PST 2023 x86_64 GNU/Linux > Linux 5.4.264 #9 SMP > Thu Dec 21 07:00:08 PST 2023 > makedumpfile Testing: makedumpfile: version 1.7.4++ > (released on 6 Nov 2023) > Issue 13 for makedumpfile: adds support for > demsg PRINTK_CALLER id field patch applied > dmesg Testing: util-linux 2.39.3++ > Issue 2609 for sys-utils dmesg: adds support for > dmesg PRINTK_CALLER id field to standard > dmesg kmsg interface patch applied > > Add support so that dmesg entries include the optional Linux Kernel > debug CONFIG option PRINTK_CALLER which adds an optional dmesg field > that contains the Thread Id or CPU Id that is issuing the printk to > add the message to the kernel ring buffer. If enabled, this CONFIG > option makes debugging simpler as dmesg entries for a specific > thread or CPU can be recognized. > > The dmesg command supports printing the PRINTK_CALLER field. The > old syslog format (dmesg -S) and recently support was added for dmesg > using /dev/kmsg interface with util-linux Issue #2609 as we upstreamed > a commit that is under review. > > We've upstreamed a patch for makedumpfile that adds support for > the PRINTK_CALLER id field so it will be available with the > commands: > > makedumpfile --dump-dmesg /proc/vmcore dmesgfile > makedumpfile --dump-dmesg -x vmlinux /proc/vmcore dmesgfile > > The additional field provided by PRINTK_CALLER is only present > if it was configured for the Linux kernel on the running system. The > PRINTK_CALLER is a debug option and not configured by default so the > dmesg output will only change for those kernels where the option was > configured when the kernel was built. For users who went to the > trouble to configure PRINTK_CALLER and have the extra field available > for debugging, having dmesg print the field is very helpful and so > will be makedumpfile and so it would be very useful to have crash > support for dump analysis. > > Size of the PRINTK_CALLER field is determined by the maximum number > tasks that can be run on the system which is limited by the value of > /proc/sys/kernel/pid_max as pid values are from 0 to value - 1. > This value determines the number of id digits needed by the caller id. > The PRINTK_CALLER field is printed as T<id> for a Task Id or C<id> > for a CPU Id for a printk in CPU context. The values are left space > padded and enclosed in parentheses such as: > [ T123] or [ C16] > > Displaying the PRINTK_CALLER field in the log/dmesg record output: > ----------------------------------------------------------------- > > Given the layout of log/dmesg records printed by crash, for example: > > crash> log -m > ... > [ 0.000000] <7>e820: remove [mem 0xff000000-0xffffffff] reserved > [ 0.000000] <6>SMBIOS 3.4.0 present. > ... > [ 0.014179] <6>Secure boot disabled > [ 0.014179] <6>RAMDISK: [mem 0x3cf4f000-0x437bbfff] > ... > [ 663.328848] <6>sysrq: Trigger a crash > [ 663.328859] <0>Kernel panic - not syncing: sysrq triggered crash > > Our patch adds the PRINTK_CALLER field after the timestamp if the > printk_caller log / dmesg option (-c) is selected: > > crash> log -m -c > ... > [ 0.014179] [ T1] <6>Secure boot disabled > [ 0.014179] [ T29] <6>RAMDISK: [mem 0x3cf4f000-0x437bbfff] > ... > > This is consistent placement with dmesg and makedumpfile. > > To produce dmesg output with the PRINTK_CALLER id included, we add > a new log / dmesg command option: -c > > The PRINTK_CALLER id field is printed only if the -c option is selected. > The description of the log -c option that is seen in the help is: > > crash> log help > > log > dump system message buffer > [-Ttdmasc] > > ... > ... > > -c Display the caller id field that identifies either the thread id or > the CPU id (if in CPU context) that called printk(), if available. > Generally available on Linux 5.1 to 5.9 kernels configured with > CONFIG_PRINTK_CALLER or Linux 5.10 and later kernels. > > Also seen in the help file : > > Display the caller id that identifies the thread id of the task (begins > with 'T') or the processor id (begins with 'C' for in CPU context) that > called printk(), if available. > > crash> log -c > ... > [ 0.014179] [ T1] Secure boot disabled > [ 0.014179] [ T29] RAMDISK: [mem 0x3cf4f000-0x437bbfff] > [ 0.198789] [ C0] DMAR: DRHD: handling fault status reg 3 > ... > > Signed-off-by: Ivan Delalande <colona@xxxxxxxxxx> > Signed-off-by: Edward Chron <echron@xxxxxxxxxx> > --- > defs.h | 18 ++++++++++++------ > help.c | 19 +++++++++++++++++-- > kernel.c | 25 ++++++++++++++++++++++++- > printk.c | 34 ++++++++++++++++++++++++++++++++++ > symbols.c | 2 ++ > 6 files changed, 98 insertions(+), 18 deletions(-) > > diff --git a/defs.h b/defs.h > index 2a29c07..488214f 100644 > --- a/defs.h > +++ b/defs.h > @@ -2228,8 +2228,13 @@ struct offset_table { /* stash of commonly-used offsets */ > long irq_data_irq; > long zspage_huge; > long zram_comp_algs; > + long log_caller_id; > }; > > +/* caller_id default and max character sizes based on pid field size */ > +#define PID_CHARS_MAX 16 /* Max Number of PID characters */ > +#define PID_CHARS_DEFAULT 8 /* Default number of PID characters */ > + > struct size_table { /* stash of commonly-used sizes */ > long page; > long free_area_struct; > @@ -6044,12 +6049,13 @@ void dump_log(int); > void parse_kernel_version(char *); > > #define LOG_LEVEL(v) ((v) & 0x07) > -#define SHOW_LOG_LEVEL (0x1) > -#define SHOW_LOG_DICT (0x2) > -#define SHOW_LOG_TEXT (0x4) > -#define SHOW_LOG_AUDIT (0x8) > -#define SHOW_LOG_CTIME (0x10) > -#define SHOW_LOG_SAFE (0x20) > +#define SHOW_LOG_LEVEL (0x1) > +#define SHOW_LOG_DICT (0x2) > +#define SHOW_LOG_TEXT (0x4) > +#define SHOW_LOG_AUDIT (0x8) > +#define SHOW_LOG_CTIME (0x10) > +#define SHOW_LOG_SAFE (0x20) > +#define SHOW_LOG_CALLER (0x40) > void set_cpu(int); > void clear_machdep_cache(void); > struct stack_hook *gather_text_list(struct bt_info *); > diff --git a/help.c b/help.c > index a4319dd..ae02a57 100644 > --- a/help.c > +++ b/help.c > @@ -4023,7 +4023,7 @@ NULL > char *help_log[] = { > "log", > "dump system message buffer", > -"[-Ttdmas]", > +"[-Ttdmasc]", > " This command dumps the kernel log_buf contents in chronological order. The", > " command supports the older log_buf formats, which may or may not contain a", > " timestamp inserted prior to each message, as well as the newer variable-length", > @@ -4046,7 +4046,11 @@ char *help_log[] = { > " been copied out to the user-space audit daemon.", > " -s Dump the printk logs remaining in kernel safe per-CPU buffers that", > " have not been flushed out to log_buf.", > -" ", > +" -c Display the caller id field that identifies either the thread id or", > +" the CPU id (if in CPU context) that called printk(), if available.", > +" Generally available on Linux 5.1 to 5.9 kernels configured with", > +" CONFIG_PRINTK_CALLER or Linux 5.10 and later kernels.", > +" ", > "\nEXAMPLES", > " Dump the kernel message buffer:\n", > " %s> log", > @@ -4214,6 +4218,17 @@ char *help_log[] = { > " CPU: 0 ADDR: ffff8ca4fbc1ad00 LEN: 0 MESSAGE_LOST: 0", > " (empty)", > " ...", > +" ", > +" Display the caller id that identifies the thread id of the task (begins", > +" with 'T') or the processor id (begins with 'C' for in CPU context) that", > +" called printk(), if available.\n", > +" %s> log -c", > +" ...", > +" [ 0.014179] [ T1] Secure boot disabled", > +" [ 0.014179] [ T29] RAMDISK: [mem 0x3cf4f000-0x437bbfff]", > +" [ 0.198789] [ C0] DMAR: DRHD: handling fault status reg 3", > +" ...", > + > NULL > }; > > diff --git a/kernel.c b/kernel.c > index 6dcf414..bcd10f9 100644 > --- a/kernel.c > +++ b/kernel.c > @@ -5089,7 +5089,7 @@ cmd_log(void) > > msg_flags = 0; > > - while ((c = getopt(argcnt, args, "Ttdmas")) != EOF) { > + while ((c = getopt(argcnt, args, "Ttdmasc")) != EOF) { > switch(c) > { > case 'T': > @@ -5110,6 +5110,9 @@ cmd_log(void) > case 's': > msg_flags |= SHOW_LOG_SAFE; > break; > + case 'c': > + msg_flags |= SHOW_LOG_CALLER; > + break; > default: > argerrs++; > break; > @@ -5369,6 +5372,24 @@ dump_log_entry(char *logptr, int msg_flags) > fprintf(fp, "%s", buf); > } > > + /* The PRINTK_CALLER id field was introduced with Linux-5.1 so if > + * requested, Kernel version >= 5.1 and field exists print caller_id. > + */ > + if (msg_flags & SHOW_LOG_CALLER && > + VALID_MEMBER(log_caller_id)) { > + const unsigned int cpuid = 0x80000000; > + char cbuf[PID_CHARS_MAX]; > + unsigned int cid; > + > + /* Get id type, isolate just id value in cid for print */ > + cid = UINT(logptr + OFFSET(log_caller_id)); > + sprintf(cbuf, "%c%d", (cid & cpuid) ? 'C' : 'T', cid & ~cpuid); > + sprintf(buf, "[%*s] ", PID_CHARS_DEFAULT, cbuf); > + > + ilen += strlen(buf); > + fprintf(fp, "%s", buf); > + } > + > level = LOG_LEVEL(level); > > if (msg_flags & SHOW_LOG_LEVEL) { > @@ -5424,6 +5445,8 @@ dump_variable_length_record_log(int msg_flags) > * from log to printk_log. See 62e32ac3505a0cab. > */ > log_struct_name = "printk_log"; > + MEMBER_OFFSET_INIT(log_caller_id, "printk_log", > + "caller_id"); > } else > log_struct_name = "log"; > > diff --git a/printk.c b/printk.c > index 8658016..ae3fa4f 100644 > --- a/printk.c > +++ b/printk.c > @@ -9,6 +9,7 @@ struct prb_map { > unsigned long desc_ring_count; > char *descs; > char *infos; > + unsigned int pid_max_chars; > > char *text_data_ring; > unsigned long text_data_ring_size; > @@ -162,6 +163,24 @@ dump_record(struct prb_map *m, unsigned long id, int msg_flags) > fprintf(fp, "%s", buf); > } > > + /* > + * The lockless ringbuffer introduced in Linux-5.10 always has > + * the caller_id field available, so if requested, print it. > + */ > + if (msg_flags & SHOW_LOG_CALLER) { > + const unsigned int cpuid = 0x80000000; > + char cbuf[PID_CHARS_MAX]; > + unsigned int cid; > + > + /* Get id type, isolate id value in cid for print */ > + cid = UINT(info + OFFSET(printk_info_caller_id)); > + sprintf(cbuf, "%c%d", (cid & cpuid) ? 'C' : 'T', cid & ~cpuid); > + sprintf(buf, "[%*s] ", m->pid_max_chars, cbuf); > + > + ilen += strlen(buf); > + fprintf(fp, "%s", buf); > + } > + > if (msg_flags & SHOW_LOG_LEVEL) { > level = UCHAR(info + OFFSET(printk_info_level)) >> 5; > sprintf(buf, "<%x>", level); > @@ -262,6 +281,21 @@ dump_lockless_record_log(int msg_flags) > goto out_text_data; > } > > + /* If caller_id was requested, get the pid_max value for print */ > + if (msg_flags & SHOW_LOG_CALLER) { > + unsigned int pidmax; > + > + get_symbol_data("pid_max", sizeof(pidmax), &pidmax); > + if (pidmax <= 99999) > + m.pid_max_chars = 6; > + else if (pidmax <= 999999) > + m.pid_max_chars = 7; > + else > + m.pid_max_chars = PID_CHARS_DEFAULT; > + } else { > + m.pid_max_chars = PID_CHARS_DEFAULT; > + } > + > /* ready to go */ > > tail_id = ULONG(m.desc_ring + OFFSET(prb_desc_ring_tail_id) + > diff --git a/symbols.c b/symbols.c > index 88a3fd1..554d109 100644 > --- a/symbols.c > +++ b/symbols.c > @@ -11524,6 +11524,8 @@ dump_offset_table(char *spec, ulong makestruct) > OFFSET(log_level)); > fprintf(fp, " log_flags_level: %ld\n", > OFFSET(log_flags_level)); > + fprintf(fp, " log_caller_id: %ld\n", > + OFFSET(log_caller_id)); > > fprintf(fp, " printk_info_seq: %ld\n", OFFSET(printk_info_seq)); > fprintf(fp, " printk_info_ts_nseq: %ld\n", OFFSET(printk_info_ts_nsec)); -- Crash-utility mailing list -- devel@xxxxxxxxxxxxxxxxxxxxxxxxxxx To unsubscribe send an email to devel-leave@xxxxxxxxxxxxxxxxxxxxxxxxxxx https://${domain_name}/admin/lists/devel.lists.crash-utility.osci.io/ Contribution Guidelines: https://github.com/crash-utility/crash/wiki