Skip to content

Commit f23ab38

Browse files
committed
Add icc parser
1 parent 535f77a commit f23ab38

File tree

4 files changed

+383
-1
lines changed

4 files changed

+383
-1
lines changed

CMakeLists.txt

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,8 @@ list(APPEND PLUGIN_SOURCES
107107
debugimage/cpu64_ctx_v14.cpp
108108
debugimage/cpu64_ctx_v20.cpp
109109
ipc/ipc.cpp
110-
regulator/regulator.cpp)
110+
regulator/regulator.cpp
111+
icc/icc.cpp)
111112
add_library(plugins SHARED ${PLUGIN_SOURCES})
112113
if (CMAKE_BUILD_TARGET_ARCH STREQUAL "arm64")
113114
target_sources(plugins PRIVATE coredump/arm/arm64.cpp
@@ -325,4 +326,10 @@ add_library(reg SHARED
325326
${PLUGIN_SOURCES}
326327
regulator/regulator.cpp)
327328
set_target_properties(reg PROPERTIES PREFIX "")
329+
330+
# =================== build icc ===================
331+
add_library(icc SHARED
332+
${PLUGIN_SOURCES}
333+
icc/icc.cpp)
334+
set_target_properties(icc PROPERTIES PREFIX "")
328335
endif()

icc/icc.cpp

Lines changed: 305 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,305 @@
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 "icc.h"
17+
18+
#pragma GCC diagnostic push
19+
#pragma GCC diagnostic ignored "-Wpointer-arith"
20+
21+
#ifndef BUILD_TARGET_TOGETHER
22+
DEFINE_PLUGIN_COMMAND(ICC)
23+
#endif
24+
25+
void ICC::cmd_main(void) {
26+
int c;
27+
std::string cppString;
28+
if (argcnt < 2) cmd_usage(pc->curcmd, SYNOPSIS);
29+
if (provider_list.size() == 0){
30+
parser_icc_provider();
31+
}
32+
while ((c = getopt(argcnt, args, "apn:r:")) != EOF) {
33+
switch(c) {
34+
case 'a':
35+
print_icc_info();
36+
break;
37+
case 'p':
38+
print_icc_provider();
39+
break;
40+
case 'n':
41+
cppString.assign(optarg);
42+
print_icc_nodes(cppString);
43+
break;
44+
case 'r':
45+
cppString.assign(optarg);
46+
print_icc_request(cppString);
47+
break;
48+
default:
49+
argerrs++;
50+
break;
51+
}
52+
}
53+
if (argerrs)
54+
cmd_usage(pc->curcmd, SYNOPSIS);
55+
}
56+
57+
ICC::ICC(){
58+
field_init(icc_provider,provider_list);
59+
field_init(icc_provider,nodes);
60+
field_init(icc_provider,dev);
61+
field_init(icc_provider,users);
62+
field_init(icc_provider,data);
63+
struct_init(icc_provider);
64+
field_init(icc_node,id);
65+
field_init(icc_node,name);
66+
field_init(icc_node,node_list);
67+
field_init(icc_node,avg_bw);
68+
field_init(icc_node,peak_bw);
69+
field_init(icc_node,init_avg);
70+
field_init(icc_node,init_peak);
71+
field_init(icc_node,data);
72+
field_init(icc_node,req_list);
73+
struct_init(icc_node);
74+
field_init(icc_req,req_node);
75+
field_init(icc_req,dev);
76+
field_init(icc_req,enabled);
77+
field_init(icc_req,tag);
78+
field_init(icc_req,avg_bw);
79+
field_init(icc_req,peak_bw);
80+
struct_init(icc_req);
81+
cmd_name = "icc";
82+
help_str_list={
83+
"icc", /* command name */
84+
"dump icc information", /* short description */
85+
"-a \n"
86+
" icc -p\n"
87+
" icc -n <icc provider name>\n"
88+
" icc -r <icc node name>\n"
89+
" This command dumps the cma info.",
90+
"\n",
91+
"EXAMPLES",
92+
" Display all icc provider/node/request info:",
93+
" %s> icc -a",
94+
" icc_provider:ffffff8002241140 soc:interconnect",
95+
" icc_node:ffffff8002106980 avg_bw:2 peak_bw:1 [qup0_core_master]",
96+
" icc_req:ffffff801adf7990 avg_bw:76800 peak_bw:76800 [4a90000.spi]",
97+
" icc_req:ffffff801adf7790 avg_bw:1 peak_bw:1 [4a84000.i2c]",
98+
" icc_req:ffffff8019444e10 avg_bw:1 peak_bw:1 [4a80000.i2c]",
99+
"\n",
100+
" Display all icc provider:",
101+
" %s> icc -p",
102+
" icc_provider users data Name",
103+
" ffffff8002241140 10 ffffff8006998040 soc:interconnect",
104+
" ffffff8002249d40 12 ffffff800699c040 soc:interconnect@0",
105+
" ffffff8002249b40 12 ffffff8002220040 soc:interconnect@1",
106+
" ffffff8002249340 30 ffffff8002224040 1900000.interconnect",
107+
"\n",
108+
" Display all icc node of specified provider by provider name:",
109+
" %s> icc -n 4480000.interconnect",
110+
" icc_node id avg_bw peak_bw data Name",
111+
" ffffff8002254400 0 478572 2188000 ffffffeedf05e1f0 apps_proc",
112+
" ffffff800224b480 1 0 0 ffffffeedf05e360 mas_snoc_bimc_rt",
113+
" ffffff800224be80 2 0 0 ffffffeedf05e4d0 mas_snoc_bimc_nrt",
114+
" ffffff8002254f80 3 396800 2160000 ffffffeedf05e640 mas_snoc_bimc",
115+
"\n",
116+
" Display all icc request of specified node by node name:",
117+
" %s> icc -r apps_proc",
118+
" icc_req enabled tag avg_bw peak_bw Name",
119+
" ffffff8018162e10 true 0 0 40000 4e00000.hsusb",
120+
" ffffff801a28aa10 true 0 0 0 4453000.qrng",
121+
" ffffff8018e09410 false 0 76800 76800 4a90000.spi",
122+
" ffffff8018e08410 false 0 1 1 4a84000.i2c",
123+
" ffffff80157b7a10 true 0 1 1 4a80000.i2c",
124+
"\n",
125+
};
126+
initialize();
127+
}
128+
129+
void ICC::print_icc_request(std::string node_name){
130+
for (const auto& provider_ptr : provider_list) {
131+
for (const auto& node_ptr : provider_ptr->node_list) {
132+
if (node_ptr->name != node_name){
133+
continue;
134+
}
135+
if(node_ptr->req_list.size() == 0) return;
136+
std::ostringstream oss_hd;
137+
oss_hd << std::left << std::setw(VADDR_PRLEN) << "icc_req" << " "
138+
<< std::left << std::setw(7) << "enabled" << " "
139+
<< std::left << std::setw(4) << "tag" << " "
140+
<< std::left << std::setw(10) << "avg_bw" << " "
141+
<< std::left << std::setw(10) << "peak_bw" << " "
142+
<< std::left << "Name";
143+
fprintf(fp, "%s \n",oss_hd.str().c_str());
144+
for (const auto& req_ptr : node_ptr->req_list) {
145+
std::ostringstream oss;
146+
oss << std::left << std::setw(VADDR_PRLEN) << std::hex << req_ptr->addr << " "
147+
<< std::left << std::setw(7) << (req_ptr->enabled ? "true": "false") << " "
148+
<< std::left << std::setw(4) << std::dec << req_ptr->tag << " "
149+
<< std::left << std::setw(10) << std::dec << req_ptr->avg_bw << " "
150+
<< std::left << std::setw(10) << std::dec << req_ptr->peak_bw << " "
151+
<< std::left << req_ptr->name;
152+
fprintf(fp, "%s \n",oss.str().c_str());
153+
}
154+
}
155+
}
156+
}
157+
158+
void ICC::print_icc_nodes(std::string provider_name){
159+
for (const auto& provider_ptr : provider_list) {
160+
if (provider_ptr->name != provider_name){
161+
continue;
162+
}
163+
if(provider_ptr->node_list.size() == 0) return;
164+
std::ostringstream oss_hd;
165+
oss_hd << std::left << std::setw(VADDR_PRLEN) << "icc_node" << " "
166+
<< std::left << std::setw(5) << "id" << " "
167+
<< std::left << std::setw(10) << "avg_bw" << " "
168+
<< std::left << std::setw(10) << "peak_bw" << " "
169+
<< std::left << std::setw(16) << "qcom_icc_node" << " "
170+
<< std::left << "Name";
171+
fprintf(fp, "%s \n",oss_hd.str().c_str());
172+
for (const auto& node_ptr : provider_ptr->node_list) {
173+
std::ostringstream oss;
174+
oss << std::left << std::setw(VADDR_PRLEN) << std::hex << node_ptr->addr << " "
175+
<< std::left << std::setw(5) << std::dec << node_ptr->id << " "
176+
<< std::left << std::setw(10) << std::dec << node_ptr->avg_bw << " "
177+
<< std::left << std::setw(10) << std::dec << node_ptr->peak_bw << " "
178+
<< std::left << std::setw(16) << std::hex << node_ptr->data << " "
179+
<< std::left << node_ptr->name;
180+
fprintf(fp, "%s \n",oss.str().c_str());
181+
}
182+
}
183+
}
184+
185+
void ICC::print_icc_info(){
186+
for (const auto& provider_ptr : provider_list) {
187+
std::ostringstream provider;
188+
provider << std::left << "icc_provider:" << std::hex << provider_ptr->addr << " "
189+
<< std::left << provider_ptr->name;
190+
fprintf(fp, "%s \n",provider.str().c_str());
191+
for (const auto& node_ptr : provider_ptr->node_list) {
192+
std::ostringstream node;
193+
node << std::left << " icc_node:" << std::hex << node_ptr->addr << " "
194+
<< std::left << "avg_bw:" << std::dec << node_ptr->avg_bw << " "
195+
<< std::left << "peak_bw:" << std::dec << node_ptr->peak_bw << " "
196+
<< std::left << "[" << node_ptr->name << "]";
197+
fprintf(fp, "%s \n",node.str().c_str());
198+
for (const auto& req_ptr : node_ptr->req_list) {
199+
std::ostringstream req;
200+
req << std::left << " icc_req:" << std::hex << req_ptr->addr << " "
201+
<< std::left << "avg_bw:" << std::dec << req_ptr->avg_bw << " "
202+
<< std::left << "peak_bw:" << std::dec << req_ptr->peak_bw << " "
203+
<< std::left << "[" << req_ptr->name << "]";
204+
fprintf(fp, "%s \n",req.str().c_str());
205+
}
206+
}
207+
fprintf(fp, "\n\n");
208+
}
209+
}
210+
211+
void ICC::print_icc_provider(){
212+
if(provider_list.size() == 0) return;
213+
std::ostringstream oss_hd;
214+
oss_hd << std::left << std::setw(VADDR_PRLEN) << "icc_provider" << " "
215+
<< std::left << std::setw(5) << "users" << " "
216+
// << std::left << std::setw(VADDR_PRLEN) << "data" << " "
217+
<< std::left << "Name";
218+
fprintf(fp, "%s \n",oss_hd.str().c_str());
219+
for (const auto& provider_ptr : provider_list) {
220+
std::ostringstream oss;
221+
oss << std::left << std::setw(VADDR_PRLEN) << std::hex << provider_ptr->addr << " "
222+
<< std::left << std::setw(5) << std::dec << provider_ptr->users << " "
223+
// << std::left << std::setw(VADDR_PRLEN) << std::hex << provider_ptr->data << " "
224+
<< std::left << provider_ptr->name;
225+
fprintf(fp, "%s \n",oss.str().c_str());
226+
}
227+
}
228+
229+
void ICC::parser_icc_provider(){
230+
if (!csymbol_exists("icc_providers")){
231+
fprintf(fp, "icc_providers doesn't exist in this kernel!\n");
232+
return;
233+
}
234+
ulong icc_providers_addr = csymbol_value("icc_providers");
235+
if (!is_kvaddr(icc_providers_addr)) {
236+
fprintf(fp, "icc_providers address is invalid!\n");
237+
return;
238+
}
239+
int offset = field_offset(icc_provider, provider_list);
240+
for (const auto& addr : for_each_list(icc_providers_addr,offset)) {
241+
std::shared_ptr<icc_provider> provider_ptr = std::make_shared<icc_provider>();
242+
provider_ptr->addr = addr;
243+
// provider_ptr->data = read_pointer(addr + field_offset(icc_provider,data),"data");
244+
provider_ptr->users = read_int(addr + field_offset(icc_provider,users),"users");
245+
ulong dev_addr = read_pointer(addr + field_offset(icc_provider,dev),"dev");
246+
ulong nodes_addr = addr + field_offset(icc_provider,nodes);
247+
if (is_kvaddr(dev_addr)){
248+
ulong name_addr = read_pointer(dev_addr,"name addr");
249+
if (is_kvaddr(name_addr)){
250+
provider_ptr->name = read_cstring(name_addr,64, "name");
251+
}
252+
}
253+
parser_icc_node(provider_ptr,nodes_addr);
254+
provider_list.push_back(provider_ptr);
255+
}
256+
}
257+
258+
void ICC::parser_icc_node(std::shared_ptr<icc_provider> provider_ptr,ulong head){
259+
int offset = field_offset(icc_node, node_list);
260+
for (const auto& addr : for_each_list(head,offset)) {
261+
void *node_buf = read_struct(addr,"icc_node");
262+
if (!node_buf) {
263+
continue;
264+
}
265+
std::shared_ptr<icc_node> node_ptr = std::make_shared<icc_node>();
266+
node_ptr->addr = addr;
267+
node_ptr->id = UINT(node_buf + field_offset(icc_node,id));
268+
node_ptr->avg_bw = UINT(node_buf + field_offset(icc_node,avg_bw));
269+
node_ptr->peak_bw = UINT(node_buf + field_offset(icc_node,peak_bw));
270+
node_ptr->data = ULONG(node_buf + field_offset(icc_node,data));
271+
FREEBUF(node_buf);
272+
ulong name_addr = read_pointer(addr + field_offset(icc_node,name),"name addr");
273+
if (is_kvaddr(name_addr)){
274+
node_ptr->name = read_cstring(name_addr,64, "name");
275+
}
276+
provider_ptr->node_list.push_back(node_ptr);
277+
parser_icc_req(node_ptr, addr + field_offset(icc_node,req_list));
278+
}
279+
}
280+
281+
void ICC::parser_icc_req(std::shared_ptr<icc_node> node_ptr,ulong head){
282+
int offset = field_offset(icc_req, req_node);
283+
for (const auto& addr : for_each_hlist(head,offset)) {
284+
void *req_buf = read_struct(addr,"icc_req");
285+
if (!req_buf) {
286+
continue;
287+
}
288+
std::shared_ptr<icc_req> req_ptr = std::make_shared<icc_req>();
289+
req_ptr->addr = addr;
290+
req_ptr->tag = UINT(req_buf + field_offset(icc_req,tag));
291+
req_ptr->avg_bw = UINT(req_buf + field_offset(icc_req,avg_bw));
292+
req_ptr->peak_bw = UINT(req_buf + field_offset(icc_req,peak_bw));
293+
req_ptr->enabled = BOOL(req_buf + field_offset(icc_req,enabled));
294+
ulong dev_addr = ULONG(req_buf + field_offset(icc_req,dev));
295+
FREEBUF(req_buf);
296+
if (is_kvaddr(dev_addr)){
297+
ulong name_addr = read_pointer(dev_addr,"name addr");
298+
if (is_kvaddr(name_addr)){
299+
req_ptr->name = read_cstring(name_addr,64, "name");
300+
}
301+
}
302+
node_ptr->req_list.push_back(req_ptr);
303+
}
304+
}
305+
#pragma GCC diagnostic pop

icc/icc.h

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
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 ICC_DEFS_H_
17+
#define ICC_DEFS_H_
18+
19+
#include "plugin.h"
20+
21+
struct icc_req {
22+
ulong addr;
23+
bool enabled;
24+
int32_t tag;
25+
int32_t avg_bw;
26+
int32_t peak_bw;
27+
std::string name;
28+
};
29+
30+
struct icc_node {
31+
ulong addr;
32+
int id;
33+
int32_t avg_bw;
34+
int32_t peak_bw;
35+
ulong data;
36+
std::string name;
37+
std::vector<std::shared_ptr<icc_req>> req_list;
38+
};
39+
40+
struct icc_provider {
41+
ulong addr;
42+
int users;
43+
std::string name;
44+
std::vector<std::shared_ptr<icc_node>> node_list;
45+
};
46+
47+
class ICC : public PaserPlugin {
48+
private:
49+
std::vector<std::shared_ptr<icc_provider>> provider_list;
50+
51+
public:
52+
ICC();
53+
void print_icc_request(std::string node_name);
54+
void print_icc_nodes(std::string provider_name);
55+
void print_icc_info();
56+
void print_icc_provider();
57+
void cmd_main(void) override;
58+
void parser_icc_provider();
59+
void parser_icc_node(std::shared_ptr<icc_provider> provider_ptr, ulong head);
60+
void parser_icc_req(std::shared_ptr<icc_node> node_ptr, ulong head);
61+
DEFINE_PLUGIN_INSTANCE(ICC)
62+
};
63+
64+
#endif // ICC_DEFS_H_

0 commit comments

Comments
 (0)