查看percpu变量在每个cpu上的基地址
crash> kmem -o
PER-CPU OFFSET VALUES:
CPU 0: ffff88807f600000
CPU 1: ffff88807fa00000
CPU 2: ffff88813d600000
CPU 3: ffff88813da00000
CPU 4: ffff8881bd600000
CPU 5: ffff8881bda00000
CPU 6: ffff88823d600000
CPU 7: ffff88823da00000
查看一个全局的percpu变量的具体值
查看call_single_queue在每个cpu上的地址:
static DEFINE_PER_CPU_SHARED_ALIGNED(struct llist_head, call_single_queue);
查看这个percpu变量在每个cpu上的地址
crash> p call_single_queue
PER-CPU DATA TYPE:
struct llist_head call_single_queue;
PER-CPU ADDRESSES:
[0]: ffff0102ffddb740
[1]: ffff0102ffdfe740
[2]: ffff0102ffe21740
[3]: ffff0102ffe44740
[4]: ffff0102ffe67740
[5]: ffff0102ffe8a740
[6]: ffff0102ffead740
[7]: ffff0102ffed0740
[8]: ffff0102ffef3740
[9]: ffff0102fff16740
[10]: ffff0102fff39740
[11]: ffff0102fff5c740
....
查看某个地址上对应结构体的内容用struct命令:
NAME
struct - structure contentsSYNOPSIS
struct struct_name[.member[,member]][-o][-l offset][-rfuxdp]
[address | symbol][:cpuspec] [count | -c count
例如:struct 结构体名 地址:#percpu 读取第#percpu个 percpu 的内容
或者*指令:
crash> help *
NAME
* - pointer-to short-cutSYNOPSIS
* (struct or union command arguments)DESCRIPTION
This command is a short-cut command that replaces the requirement to enter
"struct" or "union" command names. For details on the arguments to
those commands, enter "help struct" or "help union".EXAMPLES
Dump the page structure at address c02943c0:
crash> *page c02943c0
struct page {
next = 0xc0fae740,
prev = 0xc0018fb0,
inode = 0x0,
offset = 0x3f000,
next_hash = 0xc02d6310,
count = {
counter = 0x1
},
flags = 0x310,
wait = 0xc02943d8,
pprev_hash = 0x0,
buffers = 0x0
}
crash> struct llist_head 0xffff0102ffddb740
struct llist_head {
first = 0xffff0102ffde1a80
}
或者:
crash> *llist_head 0xffff0102ffddb740
struct llist_head {
first = 0xffff0102ffde1a80
}
查看某个,或某几个cpu的内容:
crash> p call_single_queue:0,1,2
per_cpu(call_single_queue, 0) = $12 = {
first = 0xffff0102ffde1a80
}
per_cpu(call_single_queue, 1) = $13 = {
first = 0x0
}
per_cpu(call_single_queue, 2) = $14 = {
first = 0x0
}
读取percpu变量的内容
有如下结构体和per cpu变量cfd_data:
struct call_function_data {
call_single_data_t __percpu *csd;
cpumask_var_t cpumask;
cpumask_var_t cpumask_ipi;
};
static DEFINE_PER_CPU_ALIGNED(struct call_function_data, cfd_data);
需要读取31号cpu的cfd_data,中的csd中的第0号cpu的内容。
首先需要获取31号cpu的cfd_data的内容:
crash> p cfd_data:31
per_cpu(cfd_data, 31) = $15 = {
csd = 0xffff80001180fa80,
cpumask = {{
bits = {18446744071562067967, 18446744073709551615, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
}},
cpumask_ipi = {{
bits = {18446744071562067966, 18446744073709551615, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
}}
}
在读取csd = 0xffff80001180fa80 变量下第0号cpu具体内容:
crash> struct call_single_data_t 0xffff80001180fa80:0
[0]: ffff0102ffde1a80
struct call_single_data_t {
node = {
llist = {
next = 0xffff00ff8a973a08
},
{
u_flags = 17,
a_flags = {
counter = 17
}
},
src = 0,
dst = 0
},
func = 0xffff8000103500d0 <tlb_remove_table_smp_sync>,
info = 0x0
}
或者:
crash> *call_single_data_t 0xffff80001180fa80:0
crash工具学习 —— percpu相关的一些用法 - 摩斯电码 - 博客园 (cnblogs.com)
crash、kdump工具学习 - 摩斯电码 - 博客园 (cnblogs.com)
p和struct的区别
p #SYMBOL变量
默认打变量/符号的内容,如果是结构体也会打印所有结构体的内容,如果是percpu 则打印percpu所有的地址
p #SYMBOL:#N
打印percpu 对应N的内容,如果是a则打印所有的。
struct struct_name[.member[,member]] [address | symbol][:cpuspec]
打印结构体struct_name的内容,或者某个,某些成员。 需要提供地址address或者变量符号名symbol。
如果对应的地址或变量是percpu的,需要提供:cpuspec索引cpu,如果是a则全部。
例如:
crash> p cfd_data:0
per_cpu(cfd_data, 0) = $6 = {
csd = 0xffff80001180d100, //cfd是percpu
cpumask = {{
bits = {18446744073709551614, 18446744073709551615, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
}},
cpumask_ipi = {{
bits = {18446744073709551614, 18446744073709551615, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
}}
}
crash> struct call_single_data_t 0xffff80001180d100 //直接显示percpu将出错,需要提供cpuspec
struct call_single_data_t struct: page excluded: kernel virtual address: ffff80001180d100 type: "gdb_readmem_callback"
crash> struct call_single_data_t 0xffff80001180d100:0
[0]: ffff0102ffddf100
struct call_single_data_t {
node = {
llist = {
next = 0x0
},
{
u_flags = 0,
a_flags = {
counter = 0
}
},
src = 0,
dst = 0
},
func = 0x0,
info = 0x0
}
struct 可以达到部分p的功能。
struct 可以达到部分p的功能。
如果需要显示对应变量,地址为结构体:
crash> struct call_function_data cfd_data:0
[0]: ffff0102ffddb780
struct call_function_data {
csd = 0xffff80001180d100,
cpumask = {{
bits = {18446744073709551614, 18446744073709551615, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
}},
cpumask_ipi = {{
bits = {18446744073709551614, 18446744073709551615, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
}}
}
*号命令。可以实现p或struct功能
*号命令。可以实现p或struct功能
crash> *call_function_data cfd_data:0
[0]: ffff0102ffddb780
struct call_function_data {
csd = 0xffff80001180d100,
cpumask = {{
bits = {18446744073709551614, 18446744073709551615, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
}},
cpumask_ipi = {{
bits = {18446744073709551614, 18446744073709551615, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
}}
}