Hi Georges,
Thanks for the fix. Just some nits:
On Thu, Apr 30, 2026 at 3:37 AM Aureau, Georges (Kernel Tools ERT)
<georges.aureau(a)hpe.com> wrote:
On kernels 6.17 and higher, DATE is not displayed properly:
crash> sys | grep -e DATE -e REL
DATE: Wed Dec 31 18:00:00 CST 1969
RELEASE: 7.0.0-14-generic
The function get_xtime() was enhanced to support:
- kernel 6.17 ("shadow_timekeeper" moved to "tk_core")
- kernel 7.0 ("tk_core" is now "timekeeper_data[0]).
I checked the kernel log history:
struct tk_data is introduced in v6.13 by 10f7c178a9dad803e8
"timekeeping: Define a struct type for tk_core to make it reusable".
and tk_core to be made to timekeeper_data[0] by 22c62b9a84b8f16ca
"timekeeping: Introduce auxiliary timekeepers", this is in v6.17.
So kernel >= v6.13 should have this patch applied before the time to
be displayed correctly. So the kernel info is misleading and better be
corrected.
With this get_xtime() enhancement:
crash> sys | grep DATE
DATE: Mon Apr 27 09:19:50 CDT 2026
Signed-off-by: Georges Aureau <georges.aureau(a)hpe.com>
--
defs.h | 1 +
kernel.c | 19 ++++++++++++++++++-
2 files changed, 19 insertions(+), 1 deletion(-)
diff --git a/defs.h b/defs.h
index a6f4372..c07b9a2 100644
--- a/defs.h
+++ b/defs.h
@@ -2290,6 +2290,7 @@ struct offset_table { /* stash of commonly-used
offsets */
long bpf_ringbuf_nr_pages;
long hrtimer_clock_base_index;
long klp_patch_list;
+ long tk_data_timekeeper;
};
struct size_table { /* stash of commonly-used sizes */
diff --git a/kernel.c b/kernel.c
index 8781d6a..d54e825 100644
--- a/kernel.c
+++ b/kernel.c
@@ -258,6 +258,7 @@ kernel_init()
MEMBER_OFFSET_INIT(timekeeper_xtime, "timekeeper", "xtime");
MEMBER_OFFSET_INIT(timekeeper_xtime_sec, "timekeeper",
"xtime_sec");
+ MEMBER_OFFSET_INIT(tk_data_timekeeper, "tk_data",
"timekeeper");
get_xtime(&kt->date);
if (CRASHDEBUG(1))
fprintf(fp, "xtime timespec.tv_sec: %lx: %s\n",
@@ -11134,7 +11135,23 @@ get_xtime(struct timespec *date)
struct syment *sp;
uint64_t xtime_sec;
- if (VALID_MEMBER(timekeeper_xtime) &&
+ if (VALID_MEMBER(tk_data_timekeeper) &&
+ VALID_MEMBER(timekeeper_xtime_sec)) {
+ long offset = OFFSET(tk_data_timekeeper) +
+ OFFSET(timekeeper_xtime_sec);
+ if ((sp = kernel_symbol_search("timekeeper_data"))) {
+ readmem(sp->value + offset, KVADDR,
+ &xtime_sec, sizeof(uint64_t),
+ "timekeeper_data xtime_sec", RETURN_ON_ERROR);
+ date->tv_sec = (__time_t)xtime_sec;
+ } else if ((sp = kernel_symbol_search("tk_core"))) {
+ readmem(sp->value + offset, KVADDR,
+ &xtime_sec, sizeof(uint64_t),
+ "tk_core xtime_sec", RETURN_ON_ERROR);
+ date->tv_sec = (__time_t)xtime_sec;
+ }
I think we don't need distinguish timekeeper_data or tk_core's
readmem(), the kernel data structure is unchanged, all are: struct
tk_data -> member timekeeper -> member xtime_sec. So a simple:
if ((sp = kernel_symbol_search("timekeeper_data")) || (sp =
kernel_symbol_search("tk_core"))) {
readmem(sp->value + offset, KVADDR,
&xtime_sec, sizeof(uint64_t),
"tk_data timekeeper xtime_sec", RETURN_ON_ERROR);
}
should work. What do you think?
Thanks,
Tao Liu
+ }
+ else if (VALID_MEMBER(timekeeper_xtime) &&
(sp = kernel_symbol_search("timekeeper"))) {
readmem(sp->value + OFFSET(timekeeper_xtime), KVADDR,
date, sizeof(struct timespec),
--
Crash-utility mailing list -- devel(a)lists.crash-utility.osci.io
To unsubscribe send an email to devel-leave(a)lists.crash-utility.osci.io
https://${domain_name}/admin/lists/devel.lists.crash-utility.osci.io/
Contribution Guidelines:
https://github.com/crash-utility/crash/wiki