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 <[email protected]>
---
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, &current_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
--
Crash-utility mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://${domain_name}/admin/lists/devel.lists.crash-utility.osci.io/
Contribution Guidelines: https://github.com/crash-utility/crash/wiki

Reply via email to