Kernel commit 009eb5da29a9 ("hrtimer: Remove hrtimer_clock_base::
Get_time") removed the get_time member from struct hrtimer_clock_base.
As a result, the "timer -r" option fails with the following error:
crash> timer -r
timer: invalid structure member offset: hrtimer_clock_base_get_time
FILE: kernel.c LINE: 7953 FUNCTION: dump_hrtimer_clock_base()
As the get_time function is switched by __hrtimer_cb_get_time() function
with clock_id macro value, crash cannot follow their changes
automatically. So change what "timer -r" displays there from the
get_time function name to enum hrtimer_base_type name.
Signed-off-by: Kazuhito Hagio <k-hagio-ab(a)nec.com>
---
I refered to page_flags_init_from_pageflags_enum() function to use
dump_enumerator_list(), pc->flags2 and etc.
defs.h | 1 +
kernel.c | 75 +++++++++++++++++++++++++++++++++++++++++++++++++++----
symbols.c | 2 ++
3 files changed, 73 insertions(+), 5 deletions(-)
diff --git a/defs.h b/defs.h
index ab4aee8520a7..7f87e8e939e9 100644
--- a/defs.h
+++ b/defs.h
@@ -2280,6 +2280,7 @@ struct offset_table { /* stash of commonly-used
offsets */
long bpf_ringbuf_map_rb;
long bpf_ringbuf_consumer_pos;
long bpf_ringbuf_nr_pages;
+ long hrtimer_clock_base_index;
};
struct size_table { /* stash of commonly-used sizes */
diff --git a/kernel.c b/kernel.c
index 13f33742990e..ec287bb55c05 100644
--- a/kernel.c
+++ b/kernel.c
@@ -43,6 +43,7 @@ static void display_bh_1(void);
static void display_bh_2(void);
static void display_bh_3(void);
static void display_bh_4(void);
+static int hrtimer_base_type_init(void);
static void dump_hrtimer_data(const ulong *cpus);
static void dump_hrtimer_clock_base(const void *, const int);
static void dump_hrtimer_base(const void *, const int);
@@ -796,6 +797,12 @@ kernel_init()
"hrtimer_clock_base", "first");
MEMBER_OFFSET_INIT(hrtimer_clock_base_get_time,
"hrtimer_clock_base", "get_time");
+ if (INVALID_MEMBER(hrtimer_clock_base_get_time)) {
+ /* Linux 6.18: 009eb5da29a9 */
+ MEMBER_OFFSET_INIT(hrtimer_clock_base_index, "hrtimer_clock_base",
"index");
+ if (!hrtimer_base_type_init())
+ error(WARNING, "cannot get enum hrtimer_base_type\n");
+ }
}
STRUCT_SIZE_INIT(hrtimer_base, "hrtimer_base");
@@ -7938,6 +7945,52 @@ static int expires_len = -1;
static int softexpires_len = -1;
static int tte_len = -1;
+static char **hrtimer_base_type = NULL;
+static int
+hrtimer_base_type_init(void)
+{
+ long max_bases;
+ int i, c ATTRIBUTE_UNUSED;
+ char buf[BUFSIZE];
+ char *arglist[MAXARGS];
+
+ if (!enumerator_value("HRTIMER_MAX_CLOCK_BASES", &max_bases))
+ return FALSE;
+
+ hrtimer_base_type = (char **)calloc(max_bases, sizeof(char *));
+ if (!hrtimer_base_type)
+ return FALSE;
+
+ pc->flags2 |= ALLOW_FP; /* Required during initialization */
+ open_tmpfile();
+ if (dump_enumerator_list("hrtimer_base_type")) {
+ rewind(pc->tmpfile);
+ while (fgets(buf, BUFSIZE, pc->tmpfile)) {
+ if (!strstr(buf, " = "))
+ continue;
+ c = parse_line(buf, arglist);
+ i = atoi(arglist[2]);
+ if (0 <= i && i < max_bases)
+ hrtimer_base_type[i] = strdup(arglist[0]);
+ }
+ close_tmpfile();
+ pc->flags2 &= ~ALLOW_FP;
+ } else {
+ close_tmpfile();
+ pc->flags2 &= ~ALLOW_FP;
+ free(hrtimer_base_type);
+ hrtimer_base_type = NULL;
+ return FALSE;
+ }
+
+ if (CRASHDEBUG(1)) {
+ for (i = 0; i < max_bases; i++)
+ fprintf(fp, "hrtimer_base_type[%d] = %s\n", i, hrtimer_base_type[i]);
+ }
+
+ return TRUE;
+}
+
static void
dump_hrtimer_clock_base(const void *hrtimer_bases, const int num)
{
@@ -7949,11 +8002,23 @@ dump_hrtimer_clock_base(const void *hrtimer_bases, const int num)
base = (void *)hrtimer_bases + OFFSET(hrtimer_cpu_base_clock_base) +
SIZE(hrtimer_clock_base) * num;
- readmem((ulong)(base + OFFSET(hrtimer_clock_base_get_time)), KVADDR,
- &get_time, sizeof(get_time), "hrtimer_clock_base get_time",
- FAULT_ON_ERROR);
- fprintf(fp, " CLOCK: %d HRTIMER_CLOCK_BASE: %lx [%s]\n", num,
- (ulong)base, value_to_symstr(get_time, buf, 0));
+
+ if (INVALID_MEMBER(hrtimer_clock_base_get_time)) {
+ /* Linux 6.18: 009eb5da29a9 */
+ if (hrtimer_base_type) {
+ uint index;
+ readmem((ulong)(base + OFFSET(hrtimer_clock_base_index)), KVADDR, &index,
+ sizeof(index), "hrtimer_clock_base index", FAULT_ON_ERROR);
+ fprintf(fp, " CLOCK: %d HRTIMER_CLOCK_BASE: %lx [%s]\n", num,
+ (ulong)base, hrtimer_base_type[index]);
+ } else
+ fprintf(fp, " CLOCK: %d HRTIMER_CLOCK_BASE: %lx\n", num, (ulong)base);
+ } else {
+ readmem((ulong)(base + OFFSET(hrtimer_clock_base_get_time)), KVADDR, &get_time,
+ sizeof(get_time), "hrtimer_clock_base get_time", FAULT_ON_ERROR);
+ fprintf(fp, " CLOCK: %d HRTIMER_CLOCK_BASE: %lx [%s]\n", num,
+ (ulong)base, value_to_symstr(get_time, buf, 0));
+ }
/* get current time(uptime) */
get_uptime(NULL, ¤t_time);
diff --git a/symbols.c b/symbols.c
index 480fdb6d98b3..c446beb43a76 100644
--- a/symbols.c
+++ b/symbols.c
@@ -11760,6 +11760,8 @@ dump_offset_table(char *spec, ulong makestruct)
OFFSET(hrtimer_clock_base_first));
fprintf(fp, " hrtimer_clock_base_get_time: %ld\n",
OFFSET(hrtimer_clock_base_get_time));
+ fprintf(fp, " hrtimer_clock_base_index: %ld\n",
+ OFFSET(hrtimer_clock_base_index));
fprintf(fp, " hrtimer_base_first: %ld\n",
OFFSET(hrtimer_base_first));
fprintf(fp, " hrtimer_base_pending: %ld\n",
--
2.31.1