Skip to content

Commit bb55a8d

Browse files
committed
Add watchdog parser
Signed-off-by: quic_wya <[email protected]>
1 parent 5f54285 commit bb55a8d

File tree

6 files changed

+309
-1
lines changed

6 files changed

+309
-1
lines changed

CMakeLists.txt

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,8 @@ list(APPEND PLUGIN_SOURCES
9797
coredump/coredump.cpp
9898
coredump/core.cpp
9999
thermal/thermal.cpp
100-
memory/meminfo.cpp)
100+
memory/meminfo.cpp
101+
watchdog/wdt.cpp)
101102
add_library(plugins SHARED ${PLUGIN_SOURCES})
102103
if (CMAKE_BUILD_TARGET_ARCH STREQUAL "arm64")
103104
target_sources(plugins PRIVATE coredump/arm/arm64.cpp
@@ -281,4 +282,10 @@ add_library(meminfo SHARED
281282
memory/meminfo.cpp)
282283
set_target_properties(meminfo PROPERTIES PREFIX "")
283284

285+
# =================== build watchdog ===================
286+
add_library(wdt SHARED
287+
${PLUGIN_SOURCES}
288+
watchdog/wdt.cpp)
289+
set_target_properties(wdt PROPERTIES PREFIX "")
290+
284291
endif()

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ Supprot module:
8484
| coredump ||| dump the coredump info |
8585
| thermal ||| parser all thermal zone temperature info |
8686
| meminfo ||| parser meminfo |
87+
| watchdog ||| parser watchdog info |
8788

8889
| module | Android-11.0(30) | Android-12.0(31) | Android-13.0(33) | comment |
8990
| -------- | ------------------- | ------------------- | ------------------- | ----------------- |

USAGE.md

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ Supprot command:
2626
| [cpu](#cpu) ||||| show cpu frequency |
2727
| [coredump](#coredump) ||| | | generate coredump |
2828
| [tm](#tm) ||||| show thermal info |
29+
| [wdt](#wdt) ||||| show watchdog info |
2930

3031

3132
| command | Android-11(30) | Android-12(31) | Android-13(33) | comment |
@@ -1079,6 +1080,51 @@ crash> rtb -a
10791080
[234.501836] [12532249398] <0>: LOGK_IRQ interrupt:1 handled from addr ffffffd4d627c7b4 ipi_handler.04f2cb5359f849bb5e8105832b6bf932.cfi_jt Line 888 of "arch/arm64/ke rnel/entry.S"
10801081
```
10811082

1083+
## wdt
1084+
This command is used to view watchdog info.
1085+
1086+
### wdt -a
1087+
Display watchdog info.
1088+
```
1089+
crash> wdt -a
1090+
enabled : True
1091+
wdt_base : c5a66000
1092+
user_pet_enabled : False
1093+
pet_time : 9.36s
1094+
bark_time : 15s
1095+
bite_time : 18s
1096+
bark_irq : 25
1097+
user_pet_complete : True
1098+
wakeup_irq_enable : True
1099+
in_panic : True
1100+
irq_ppi : False
1101+
freeze_in_progress : False
1102+
1103+
pet_timer:
1104+
jiffies : 4299314482
1105+
expires : 4348153
1106+
timer_expired : False
1107+
timer_fired : 14784480161054
1108+
last_jiffies_update : 14790618520938
1109+
tick_next_period : 14790621854271
1110+
tick_do_timer_cpu : 3
1111+
1112+
watchdog_thread:
1113+
watchdog_task : eb1d5c80
1114+
pid : 40
1115+
cpu : 0
1116+
task_state : IN
1117+
last_run : 14784480389231
1118+
thread_start : 14784480630012
1119+
last_pet : 14784480640950
1120+
do_ipi_ping : True
1121+
ping cpu[0] : 1203198795~1203203274(4479ns)
1122+
ping cpu[1] : 0~0(0ns)
1123+
ping cpu[2] : 0~0(0ns)
1124+
ping cpu[3] : 0~0(0ns)
1125+
1126+
```
1127+
10821128
### rtb -c 'cpu'
10831129
Display rtb log with cpu.
10841130
```

plugins.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
#include "coredump/coredump.h"
3838
#include "thermal/thermal.h"
3939
#include "memory/meminfo.h"
40+
#include "watchdog/wdt.h"
4041
#pragma GCC diagnostic push
4142
#pragma GCC diagnostic ignored "-Wpointer-arith"
4243

@@ -68,6 +69,7 @@ std::shared_ptr<CpuInfo> CpuInfo::instance = nullptr;
6869
std::shared_ptr<Coredump> Coredump::instance = nullptr;
6970
std::shared_ptr<Thermal> Thermal::instance = nullptr;
7071
std::shared_ptr<Meminfo> Meminfo::instance = nullptr;
72+
std::shared_ptr<Watchdog> Watchdog::instance = nullptr;
7173

7274
extern "C" void __attribute__((constructor)) plugin_init(void) {
7375
// fprintf(fp, "plugin_init\n");
@@ -95,6 +97,7 @@ extern "C" void __attribute__((constructor)) plugin_init(void) {
9597
Coredump::instance = std::make_shared<Coredump>(Swap::instance);
9698
Thermal::instance = std::make_shared<Thermal>();
9799
Meminfo::instance = std::make_shared<Meminfo>();
100+
Watchdog::instance = std::make_shared<Watchdog>();
98101

99102
static struct command_table_entry command_table[] = {
100103
{ &Binder::instance->cmd_name[0], &Binder::wrapper_func, Binder::instance->cmd_help, 0 },
@@ -121,6 +124,7 @@ extern "C" void __attribute__((constructor)) plugin_init(void) {
121124
{ &Coredump::instance->cmd_name[0], &Coredump::wrapper_func, Coredump::instance->cmd_help, 0 },
122125
{ &Thermal::instance->cmd_name[0], &Thermal::wrapper_func, Thermal::instance->cmd_help, 0 },
123126
{ &Meminfo::instance->cmd_name[0], &Meminfo::wrapper_func, Meminfo::instance->cmd_help, 0 },
127+
{ &Watchdog::instance->cmd_name[0], &Watchdog::wrapper_func, Watchdog::instance->cmd_help, 0 },
124128
{ NULL }
125129
};
126130
register_extension(command_table);
@@ -152,6 +156,7 @@ extern "C" void __attribute__((destructor)) plugin_fini(void) {
152156
Coredump::instance.reset();
153157
Thermal::instance.reset();
154158
Meminfo::instance.reset();
159+
Watchdog::instance.reset();
155160
}
156161

157162
#endif // BUILD_TARGET_TOGETHER

watchdog/wdt.cpp

Lines changed: 219 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,219 @@
1+
/**
2+
* Copyright (c) 2024-2025 Qualcomm Innovation Center, Inc. All rights reserved.
3+
*
4+
* This program is free software; you can redistribute it and/or modify
5+
* it under the terms of the GNU General Public License version 2 and
6+
* only version 2 as published by the Free Software Foundation.
7+
*
8+
* This program is distributed in the hope that it will be useful,
9+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
10+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+
* GNU General Public License for more details.
12+
*
13+
* SPDX-License-Identifier: GPL-2.0-only
14+
*/
15+
16+
#include "wdt.h"
17+
18+
#pragma GCC diagnostic push
19+
#pragma GCC diagnostic ignored "-Wpointer-arith"
20+
21+
#ifndef BUILD_TARGET_TOGETHER
22+
DEFINE_PLUGIN_COMMAND(Watchdog)
23+
#endif
24+
25+
void Watchdog::cmd_main(void) {
26+
int c;
27+
std::string cppString;
28+
if (argcnt < 2) cmd_usage(pc->curcmd, SYNOPSIS);
29+
while ((c = getopt(argcnt, args, "a")) != EOF) {
30+
switch(c) {
31+
case 'a':
32+
print_watchdog_info();
33+
break;
34+
default:
35+
argerrs++;
36+
break;
37+
}
38+
}
39+
if (argerrs)
40+
cmd_usage(pc->curcmd, SYNOPSIS);
41+
}
42+
43+
Watchdog::Watchdog(){
44+
field_init(msm_watchdog_data,base);
45+
field_init(msm_watchdog_data,pet_time);
46+
field_init(msm_watchdog_data,bark_time);
47+
field_init(msm_watchdog_data,bark_irq);
48+
field_init(msm_watchdog_data,do_ipi_ping);
49+
field_init(msm_watchdog_data,in_panic);
50+
field_init(msm_watchdog_data,wakeup_irq_enable);
51+
field_init(msm_watchdog_data,irq_ppi);
52+
field_init(msm_watchdog_data,last_pet);
53+
field_init(msm_watchdog_data,alive_mask);
54+
field_init(msm_watchdog_data,wdog_cpu_dd);
55+
field_init(msm_watchdog_data,enabled);
56+
field_init(msm_watchdog_data,user_pet_enabled);
57+
field_init(msm_watchdog_data,watchdog_task);
58+
field_init(msm_watchdog_data,pet_timer);
59+
field_init(msm_watchdog_data,timer_expired);
60+
field_init(msm_watchdog_data,user_pet_complete);
61+
field_init(msm_watchdog_data,timer_fired);
62+
field_init(msm_watchdog_data,thread_start);
63+
field_init(msm_watchdog_data,ping_start);
64+
field_init(msm_watchdog_data,ping_end);
65+
field_init(msm_watchdog_data,cpu_idle_pc_state);
66+
field_init(msm_watchdog_data,freeze_in_progress);
67+
field_init(msm_watchdog_data,irq_counts);
68+
field_init(msm_watchdog_data,ipi_counts);
69+
field_init(msm_watchdog_data,irq_counts_running);
70+
field_init(msm_watchdog_data,user_pet_timer);
71+
field_init(msm_watchdog_data,watchdog_task);
72+
field_init(timer_list,expires);
73+
struct_init(msm_watchdog_data);
74+
cmd_name = "wdt";
75+
help_str_list={
76+
"wdt", /* command name */
77+
"dump watchdog information", /* short description */
78+
"-a \n"
79+
" This command dumps the watchdog info.",
80+
"\n",
81+
"EXAMPLES",
82+
" Display watchdog info:",
83+
" %s> wdt -a",
84+
" enabled : True",
85+
" base : c5a66000",
86+
" user_pet_enabled : False",
87+
" pet_time : 9.36s",
88+
" bark_time : 15s",
89+
" bite_time : 18s",
90+
" bark_irq : 25",
91+
" user_pet_complete : True",
92+
" wakeup_irq_enable : True",
93+
" in_panic : True",
94+
" irq_ppi : False",
95+
" freeze_in_progress : False",
96+
"",
97+
" pet_timer:",
98+
" jiffies : 4299314482",
99+
" expires : 4348153",
100+
" timer_expired : False",
101+
" timer_fired : 14784480161054",
102+
" last_jiffies_update : 14790618520938",
103+
" tick_next_period : 14790621854271",
104+
" tick_do_timer_cpu : 3",
105+
"",
106+
" watchdog_thread:",
107+
" watchdog_task : eb1d5c80",
108+
" pid : 40",
109+
" cpu : 0",
110+
" task_state : IN",
111+
" last_run : 14784480389231",
112+
" thread_start : 14784480630012",
113+
" last_pet : 14784480640950",
114+
" do_ipi_ping : True",
115+
" ping cpu[0] : 1203198795~1203203274(4479ns)",
116+
" ping cpu[1] : 0~0(0ns)",
117+
" ping cpu[2] : 0~0(0ns)",
118+
" ping cpu[3] : 0~0(0ns)",
119+
"\n",
120+
};
121+
initialize();
122+
}
123+
124+
void Watchdog::print_watchdog_info(){
125+
if (!csymbol_exists("wdog_data")){
126+
fprintf(fp, "wdog_data doesn't exist in this kernel!\n");
127+
return;
128+
}
129+
ulong wdt_addr = read_pointer(csymbol_value("wdog_data"),"wdog_data");
130+
if (!is_kvaddr(wdt_addr)) {
131+
fprintf(fp, "wdog_data address is invalid!\n");
132+
return;
133+
}
134+
void *wdt_buf = read_struct(wdt_addr,"msm_watchdog_data");
135+
if (!wdt_buf) {
136+
return;
137+
}
138+
ulong base = UINT(wdt_buf + field_offset(msm_watchdog_data,base));
139+
uint pet_time = UINT(wdt_buf + field_offset(msm_watchdog_data,pet_time));
140+
uint bark_time = UINT(wdt_buf + field_offset(msm_watchdog_data,bark_time));
141+
uint bark_irq = UINT(wdt_buf + field_offset(msm_watchdog_data,bark_irq));
142+
bool enabled = BOOL(wdt_buf + field_offset(msm_watchdog_data,enabled));
143+
bool user_pet_enabled = BOOL(wdt_buf + field_offset(msm_watchdog_data,user_pet_enabled));
144+
bool do_ipi_ping = BOOL(wdt_buf + field_offset(msm_watchdog_data,do_ipi_ping));
145+
bool in_panic = BOOL(wdt_buf + field_offset(msm_watchdog_data,in_panic));
146+
bool wakeup_irq_enable = BOOL(wdt_buf + field_offset(msm_watchdog_data,wakeup_irq_enable));
147+
bool irq_ppi = BOOL(wdt_buf + field_offset(msm_watchdog_data,irq_ppi));
148+
bool timer_expired = BOOL(wdt_buf + field_offset(msm_watchdog_data,timer_expired));
149+
bool user_pet_complete = BOOL(wdt_buf + field_offset(msm_watchdog_data,user_pet_complete));
150+
bool freeze_in_progress = BOOL(wdt_buf + field_offset(msm_watchdog_data,freeze_in_progress));
151+
uint64_t last_pet = ULONGLONG(wdt_buf + field_offset(msm_watchdog_data,last_pet));
152+
uint64_t timer_fired = ULONGLONG(wdt_buf + field_offset(msm_watchdog_data,timer_fired));
153+
uint64_t thread_start = ULONGLONG(wdt_buf + field_offset(msm_watchdog_data,thread_start));
154+
ulong watchdog_task = ULONG(wdt_buf + field_offset(msm_watchdog_data,watchdog_task));
155+
FREEBUF(wdt_buf);
156+
long state = task_state(watchdog_task);
157+
struct task_context* tc = task_to_context(watchdog_task);
158+
uint64_t jiffies = 0;
159+
if (csymbol_exists("jiffies")){
160+
jiffies = read_ulonglong(csymbol_value("jiffies"),"jiffies");
161+
}else if (csymbol_exists("jiffies_64")){
162+
jiffies = read_ulonglong(csymbol_value("jiffies_64"),"jiffies");
163+
}
164+
uint64_t last_jiffies_update = read_ulonglong(csymbol_value("last_jiffies_update"),"last_jiffies_update");
165+
uint64_t tick_next_period = read_ulonglong(csymbol_value("tick_next_period"),"tick_next_period");
166+
int tick_do_timer_cpu = read_int(csymbol_value("tick_do_timer_cpu"),"tick_do_timer_cpu");
167+
ulong expires = read_ulong(wdt_addr + field_offset(msm_watchdog_data,pet_timer) + field_offset(timer_list,expires),"expires");
168+
char buf[BUFSIZE];
169+
std::ostringstream oss;
170+
oss << std::left << std::setw(20) << "enabled : " << (enabled ? "True":"False") << "\n"
171+
<< std::left << std::setw(20) << "wdt_base : " << std::hex << base << "\n"
172+
<< std::left << std::setw(20) << "user_pet_enabled : " << (user_pet_enabled ? "True":"False") << "\n"
173+
<< std::left << std::setw(20) << "pet_time : " << std::dec << ((double)pet_time / 1000) << "s\n"
174+
<< std::left << std::setw(20) << "bark_time : " << std::dec << ((double)bark_time / 1000) << "s\n"
175+
<< std::left << std::setw(20) << "bite_time : " << std::dec << ((double)bark_time + 3 * 1000)/1000 << "s\n"
176+
<< std::left << std::setw(20) << "bark_irq : " << std::dec << bark_irq << "\n"
177+
<< std::left << std::setw(20) << "user_pet_complete : " << (user_pet_complete ? "True":"False") << "\n"
178+
<< std::left << std::setw(20) << "wakeup_irq_enable : " << (wakeup_irq_enable ? "True":"False") << "\n"
179+
<< std::left << std::setw(20) << "in_panic : " << (in_panic ? "True":"False") << "\n"
180+
<< std::left << std::setw(20) << "irq_ppi : " << (irq_ppi ? "True":"False") << "\n"
181+
<< std::left << std::setw(20) << "freeze_in_progress : " << (freeze_in_progress ? "True":"False") << "\n\n"
182+
<< std::left << "pet_timer: " << "\n"
183+
<< std::left << std::setw(20) << " jiffies : " << std::dec << jiffies << "\n"
184+
<< std::left << std::setw(20) << " expires : " << std::dec << expires << "\n"
185+
<< std::left << std::setw(20) << " timer_expired : " << (timer_expired ? "True":"False") << "\n"
186+
<< std::left << std::setw(20) << " timer_fired : " << std::dec << timer_fired << "\n"
187+
<< std::left << std::setw(20) << " last_jiffies_update : " << std::dec << last_jiffies_update << "\n"
188+
<< std::left << std::setw(20) << " tick_next_period : " << std::dec << tick_next_period << "\n"
189+
<< std::left << std::setw(20) << " tick_do_timer_cpu : " << std::dec << tick_do_timer_cpu << "\n\n"
190+
<< std::left << "watchdog_thread: " << "\n"
191+
<< std::left << std::setw(20) << " watchdog_task : " << std::hex << watchdog_task << "\n"
192+
<< std::left << std::setw(20) << " pid : " << std::dec << tc->pid << "\n"
193+
<< std::left << std::setw(20) << " cpu : " << std::dec << tc->processor << "\n"
194+
<< std::left << std::setw(20) << " task_state : " << task_state_string(watchdog_task, buf, 0) << "\n"
195+
<< std::left << std::setw(20) << " last_run : " << task_last_run(watchdog_task) << "\n"
196+
<< std::left << std::setw(20) << " thread_start : " << std::dec << thread_start << "\n"
197+
<< std::left << std::setw(20) << " last_pet : " << std::dec << last_pet << "\n"
198+
<< std::left << std::setw(20) << " do_ipi_ping : " << (do_ipi_ping ? "True":"False") << "\n";
199+
ulong ping_start_addr = wdt_addr + field_offset(msm_watchdog_data,ping_start);
200+
ulong ping_end_addr = wdt_addr + field_offset(msm_watchdog_data,ping_end);
201+
ulong cips_addr = wdt_addr + field_offset(msm_watchdog_data,cpu_idle_pc_state);
202+
for (size_t i = 0; i < NR_CPUS; i++) {
203+
if (!kt->__per_cpu_offset[i])
204+
continue;
205+
ulong ping_start = read_ulonglong(ping_start_addr + i * sizeof(unsigned long long),"ping_start");
206+
ulong ping_end = read_ulonglong(ping_end_addr + i * sizeof(unsigned long long),"ping_end");
207+
ulong cips = read_int(cips_addr + i * sizeof(int),"cpu_idle_pc_state");
208+
std::string pcpu = "ping cpu[" + std::to_string(i) + "]";
209+
oss << std::left << " " << std::setw(20) << pcpu << ": " << ping_start << "~" << ping_end << "(" << (ping_end - ping_start)<< "ns)" << "\n";
210+
}
211+
oss << std::left << "-----------------------------------------------" << "\n";
212+
if (timer_expired == false){
213+
oss << std::left << "pet_timer is not trigger !" << "\n";
214+
}
215+
fprintf(fp, "%s \n",oss.str().c_str());
216+
}
217+
218+
219+
#pragma GCC diagnostic pop

watchdog/wdt.h

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/**
2+
* Copyright (c) 2024-2025 Qualcomm Innovation Center, Inc. All rights reserved.
3+
*
4+
* This program is free software; you can redistribute it and/or modify
5+
* it under the terms of the GNU General Public License version 2 and
6+
* only version 2 as published by the Free Software Foundation.
7+
*
8+
* This program is distributed in the hope that it will be useful,
9+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
10+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+
* GNU General Public License for more details.
12+
*
13+
* SPDX-License-Identifier: GPL-2.0-only
14+
*/
15+
16+
#ifndef WDT_DEFS_H_
17+
#define WDT_DEFS_H_
18+
19+
#include "plugin.h"
20+
21+
class Watchdog : public PaserPlugin {
22+
public:
23+
Watchdog();
24+
25+
void cmd_main(void) override;
26+
void print_watchdog_info();
27+
DEFINE_PLUGIN_INSTANCE(Watchdog)
28+
};
29+
30+
#endif // WDT_DEFS_H_

0 commit comments

Comments
 (0)