目录
virtio_input_driver_init通过bus匹配device和driver的过程
virtinput_probe调用的完整backtrace
下面是virtinput_probe被调用过程完整的backtrace(你可以通过在virtinput_probe函数中加入WARN_ON()把这些信息输出到内核日志中).
virtinput_probe+0xfc/0xaec
virtio_dev_probe+0x1a8/0x474
really_probe+0x1cc/0x78c
driver_probe_device+0xb4/0x13c
device_driver_attach+0x6c/0xac
__driver_attach+0xd4/0x22c
bus_for_each_dev+0x9c/0x108
driver_attach+0x24/0x30
bus_add_driver+0x124/0x204
driver_register+0x78/0x114
register_virtio_driver+0x2c/0x3c
virtio_input_driver_init+0x18/0x24
do_one_initcall+0x198/0x368
do_initcall_level+0x188/0x1b0
do_basic_setup+0x30/0x4c
kernel_init_freeable+0xc0/0x140
kernel_init+0x18/0x2b4
这个backtrace大致分为了三个部分:
1,kernel_init到do_one_initcall
2,virtio_input_driver_init通过bus去匹配device和driver的过程
3,virtinput_probe
kernel_init到do_one_initcall
这个过程相对清晰,简单来说就是,kernel_init内核线程会调用do_initcall_level依次去加载各个level的驱动模块,这些驱动模块被分为了很多个level,每个level加载的优先并不同。 这些驱动模块在内核编译的时候已经按照对应的level存在于内核镜像中,最终由do_one_initcall通过不同的offset调用到函数的入口.
virtio_input_driver_init通过bus匹配device和driver的过程
前面提到do_one_initcall会调用各个fn来完成驱动加载,而这些fn是已经编译在内核镜像中,在链接的过程中,放在了对应的section.内核在编译的时候通过kernel config知道那些module是需要编译的。
以当前virtio-input这个驱动函数为例,do_one_initcall函数中的fn函数即为virtio_input_driver_init
int __init_or_module do_one_initcall(initcall_t fn)
{
int count = preempt_count();
char msgbuf[64];
int ret;
if (initcall_blacklisted(fn))
return -EPERM;
do_trace_initcall_start(fn);
ret = fn();
do_trace_initcall_finish(fn, ret);
需要注意的是我们并不能在内核源码中直接搜索到这个函数,这个函数通常是一个宏定义函数。分析源码文件:drivers/virtio/virtio_input.c
module_virtio_driver(virtio_input_driver);
MODULE_DEVICE_TABLE(virtio, id_table);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Virtio input device driver");
MODULE_AUTHOR("Gerd Hoffmann <[email protected]>")
module_virtio_driver定义在文件include/linux/virtio.h
/* module_virtio_driver() - Helper macro for drivers that don't do
* anything special in module init/exit. This eliminates a lot of
* boilerplate. Each module may only use this macro once, and
* calling it replaces module_init() and module_exit()
*/
#define module_virtio_driver(__virtio_driver) \
module_driver(__virtio_driver, register_virtio_driver, \
unregister_virtio_driver)
#endif /* _LINUX_VIRTIO_H */
而module_driver的定义在文件:include/linux/device.h
#define module_driver(__driver, __register, __unregister, ...) \
static int __init __driver##_init(void) \
{ \
return __register(&(__driver) , ##__VA_ARGS__); \
} \
module_init(__driver##_init); \
static void __exit __driver##_exit(void) \
{ \
__unregister(&(__driver) , ##__VA_ARGS__); \
} \
module_exit(__driver##_exit);
看到这里就清晰了virtio_input_driver_init函数定义,他是由virtio_input_driver + _init构成的. 最终由内核的module_init宏定义注册到内核中. 在内核调用do_one_initcall挨个调用对应的init函数时,最终会调用到上面宏定义中的__register函数,这个函数其实就是register_virtio_driver(module_driver宏定义中第二个宏参数).
register_virtio_driver会调用driver_register走标准的linux设备驱动模型流程,最终调用了virtinput_probe.
really_probe+0x1cc/0x78c
driver_probe_device+0xb4/0x13c
device_driver_attach+0x6c/0xac
__driver_attach+0xd4/0x22c
bus_for_each_dev+0x9c/0x108
driver_attach+0x24/0x30
bus_add_driver+0x124/0x204
driver_register+0x78/0x114
我们知道,标准的linux设备驱动模型涉及到三个概念:bus、driver、device,这里:
bus:virtio, 是core level的驱动,是一种bus驱动。源码文件为:drivers/virtio/virtio.c, 其他virtio设备也是基于这个bus,例如virtio-i2c/virtio-blk等.
static struct bus_type virtio_bus = {
.name = "virtio",
.match = virtio_dev_match,
.dev_groups = virtio_dev_groups,
.uevent = virtio_uevent,
.probe = virtio_dev_probe,
.remove = virtio_dev_remove,
};
...skip...
static void __exit virtio_exit(void)
{
bus_unregister(&virtio_bus);
ida_destroy(&virtio_index_ida);
}
core_initcall(virtio_init);
module_exit(virtio_exit);
driver:这里是virtio_input_driver
device: 暂时还没找着,通常device node信息一般是由dts解析后得到,但是我们搜索了使用的dts文件,并没有发现和virtio-input相关的节点.
不过没关系,我们从virtio_input_driver_init函数开始分析,看看他是如何真正调用到probe函数的.
register_virtio_driver
前面我们提到virtio_input_driver_init在注册的时候实际调用的是register_virtio_driver函数:
int register_virtio_driver(struct virtio_driver *driver)
{
/* Catch this early. */
BUG_ON(driver->feature_table_size && !driver->feature_table);
driver->driver.bus = &virtio_bus;
return driver_register(&driver->driver);
}
这个函数实现很简单,先判断了驱动中的feature_table_size 和feature_table是否已经被正常赋值.,然后将驱动与bus挂钩.
driver_register
...skip....
other = driver_find(drv->name, drv->bus);
if (other) {
printk(KERN_ERR "Error: Driver '%s' is already registered, "
"aborting...\n", drv->name);
return -EBUSY;
}
ret = bus_add_driver(drv);
if (ret)
return ret;
ret = driver_add_groups(drv, drv->groups);
if (ret) {
bus_remove_driver(drv);
return ret;
}
kobject_uevent(&drv->p->kobj, KOBJ_ADD);
这个函数开始会做一些判断,比如判断这个driver是不是已经加载到bus过,其中最重要的是bus_add_driver函数。
__driver_attach
这个函数经过一些列的调用之后,最后调用到了__driver_attach函数,这个函数中最重要的是调用是:ret = driver_match_device(drv, dev);
这行代码是真正将driver和device匹配起来的地方.
这个函数代码实现也很简单,如果bus有自己的match函数,则调用bus自己的match接口,否则直接返回1.
static inline int driver_match_device(struct device_driver *drv,
struct device *dev)
{
return drv->bus->match ? drv->bus->match(dev, drv) : 1;
}
而virtio bus的match函数实现如下
static inline int virtio_id_match(const struct virtio_device *dev,
const struct virtio_device_id *id)
{
if (id->device != dev->id.device && id->device != VIRTIO_DEV_ANY_ID)
return 0;
return id->vendor == VIRTIO_DEV_ANY_ID || id->vendor == dev->id.vendor;
}
/* This looks through all the IDs a driver claims to support. If any of them
* match, we return 1 and the kernel will call virtio_dev_probe(). */
static int virtio_dev_match(struct device *_dv, struct device_driver *_dr)
{
unsigned int i;
struct virtio_device *dev = dev_to_virtio(_dv);
const struct virtio_device_id *ids;
ids = drv_to_virtio(_dr)->id_table;
for (i = 0; ids[i].device; i++)
if (virtio_id_match(dev, &ids[i]))
return 1;
return 0;
}
可以看到,driver和device是否会match是通过条件id->vendor == VIRTIO_DEV_ANY_ID || id->vendor == dev→id.vendor来判定的.而在驱动drivers/virtio/virtio_input.c中:
static struct virtio_device_id id_table[] = {
{ VIRTIO_ID_INPUT, VIRTIO_DEV_ANY_ID },
{ 0 },
};
小结
整个virtio-input加载的过程大致分为了三个部分
1,kernel_init到do_one_initcall
这个过程比较清晰
2,virtio_input_driver_init通过bus去匹配device和driver的过程
这个过程遵循了标准的linux设备驱动模型,在device-driver匹配的过程中,调用了bus定义的match函数去匹配driver和device。在virtio-input驱动中,通过id_table去匹配驱动和设备.
3,virtinput_probe
我们知道一般来说,device负责提供硬件资源信息,比如gpio/寄存器地址等等,但是目前为止,我们还没发现virtio-input设备有提供任何硬件资源信息。
device配置信息失踪之谜
前面我们提到我们在kernel的dts和驱动源码中是找不到任何virtio-touch的配置信息的,但是实际上,virtio-touch驱动加载和工作没有问题,这个就很奇怪了。
因为理论上,不管怎样virtio-touch都应该应该遵循linux平台设备驱动模型,bus driver device 三者缺一不可。
在virtio-mmio中添加debug log
virtio-mmio是内核中virtio起的最早的virtio模块,在这个模块的probe函数中,添加log:
printk("for debug virtio_mmio_probe pdev->name:%s\n", pdev→name);
发现即使在这个时候打印log,发现pdev->name也已经被赋值了,而且查看整个mmio的驱动,好像没有那些地方存在于qnx通信的接口。
这就更奇怪了,因为这个实验说明,我们上面的猜想可能是不成立的,我们需要找到最早内核把dtb转译成device node的地方,在那个地方添加log。
在bus_for_each_dev添加debug log
在这个函数中添加log,会把内核中所有的device node的名字都打印出来,添加log后发现,即使在内核最开始的时候,virtio-touch的节点就已经存在。
怀疑是不是内核拿到的dtb数据就是已经添加了dts node的数据?
转译fdt文件
我们知道内核中的msmnile_gvmq:/sys/firmware/fdt 文件就是内核dtb文件,我们可以把这个文件转换成dts,确认里面是否包含virtio-input的节点。
使用指令:dtc -I dtb -o sa8295p-vm.dts fdt 转换得到dts文件,在里面我们能找到:
说明内核拿到的dtb数据中的确是添加了virtio-input节点的.
是谁修改了dts数据?
观察每次la启动的日志文件la_gvm.txt,可以看到有几行log
怀疑这几行log是添加修改dts的地方,尝试修改linux-la.config之后发现,删除vdev vdev-virtio-input.so节点的同时,下面几行log的输出也会变少.比如下面的log删除了两个vdev vdev-virtio-input.so节点(原本有三个)
我们尝试从这里面入手.
register_for_ssr_events函数
在QNX中搜索register_for_ssr_events,可以发现文件 AMSS/platform/vm/vdev/vdev-glink-ssr/vdev.c +683 存在函数register_for_ssr_events,其中就有对dts的操作
static int register_for_ssr_events(glink_ssr_virt_dev_t *dev)
{
uint64_t client_magic = 0;
uint32_t event_mask = 0;
char * client_name = "vdev_glink_ssr";
void *handle;
const void *fdt;
int offset;
int ret = EOK;
QVM_LOG(GLINK_SSRVIRTLOG_ERROR, "%s ++", __func__);
printf("%s ++\r\n", __func__);
fdt = fdt_get_root();
if (!fdt) {
QVM_LOG(GLINK_SSRVIRTLOG_ERROR, "/glink-ssr fdt_get_root failed");
return -1;
}
不过深入去研究之后发现,真正virtio的register_for_ssr_events函数并不是在这个模块中调用的,只是上面的模块展示了virtio-input库中可能的用法(这个库并不开源)
不过我们可以用objdump看看内部函数:
root@ubuntu$ ~/SDP/./host/linux/x86_64/usr/bin/ntoaarch64-objdump -x ./qnx_bins/prebuilt_QNX700/target/qnx7/x86_64/lib/dll/vdev-virtio-input.so
./qnx_bins/prebuilt_QNX700/target/qnx7/x86_64/lib/dll/vdev-virtio-input.so: file format elf64-little
./qnx_bins/prebuilt_QNX700/target/qnx7/x86_64/lib/dll/vdev-virtio-input.so
architecture: UNKNOWN!, flags 0x00000150:
HAS_SYMS, DYNAMIC, D_PAGED
start address 0x0000000000001dc0
Program Header:
LOAD off 0x0000000000000000 vaddr 0x0000000000000000 paddr 0x0000000000000000 align 2**21
filesz 0x0000000000024a34 memsz 0x0000000000024a34 flags r-x
LOAD off 0x0000000000024b20 vaddr 0x0000000000224b20 paddr 0x0000000000224b20 align 2**21
filesz 0x0000000000000558 memsz 0x00000000000005b0 flags rw-
DYNAMIC off 0x0000000000024b88 vaddr 0x0000000000224b88 paddr 0x0000000000224b88 align 2**3
filesz 0x00000000000001e0 memsz 0x00000000000001e0 flags rw-
NOTE off 0x00000000000001c8 vaddr 0x00000000000001c8 paddr 0x00000000000001c8 align 2**2
filesz 0x0000000000000020 memsz 0x0000000000000020 flags r--
NOTE off 0x0000000000024a1c vaddr 0x0000000000024a1c paddr 0x0000000000024a1c align 2**2
filesz 0x0000000000000018 memsz 0x0000000000000018 flags r--
EH_FRAME off 0x0000000000024408 vaddr 0x0000000000024408 paddr 0x0000000000024408 align 2**2
filesz 0x00000000000000bc memsz 0x00000000000000bc flags r--
RELRO off 0x0000000000024b20 vaddr 0x0000000000224b20 paddr 0x0000000000224b20 align 2**0
filesz 0x00000000000004e0 memsz 0x00000000000004e0 flags r--
Dynamic Section:
NEEDED libscreen.so.1
NEEDED libc.so.4
SONAME vdev-virtio-input.so
SYMBOLIC 0x0000000000000000
INIT 0x0000000000001930
FINI 0x000000000000585a
INIT_ARRAY 0x0000000000224b20
INIT_ARRAYSZ 0x0000000000000010
FINI_ARRAY 0x0000000000224b30
FINI_ARRAYSZ 0x0000000000000008
GNU_HASH 0x00000000000001e8
STRTAB 0x0000000000000a40
SYMTAB 0x0000000000000230
STRSZ 0x0000000000000607
SYMENT 0x0000000000000018
PLTGOT 0x0000000000224d68
PLTRELSZ 0x00000000000006a8
PLTREL 0x0000000000000007
JMPREL 0x0000000000001288
RELA 0x0000000000001048
RELASZ 0x0000000000000240
RELAENT 0x0000000000000018
BIND_NOW 0x0000000000000000
FLAGS_1 0x0000000000000001
RELACOUNT 0x0000000000000011
Sections:
Idx Name Size VMA LMA File off Algn
0 .note.gnu.build-id 00000020 00000000000001c8 00000000000001c8 000001c8 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
1 .gnu.hash 00000048 00000000000001e8 00000000000001e8 000001e8 2**3
CONTENTS, ALLOC, LOAD, READONLY, DATA
2 .dynsym 00000810 0000000000000230 0000000000000230 00000230 2**3
CONTENTS, ALLOC, LOAD, READONLY, DATA
3 .dynstr 00000607 0000000000000a40 0000000000000a40 00000a40 2**0
CONTENTS, ALLOC, LOAD, READONLY, DATA
4 .rela.dyn 00000240 0000000000001048 0000000000001048 00001048 2**3
CONTENTS, ALLOC, LOAD, READONLY, DATA
5 .rela.plt 000006a8 0000000000001288 0000000000001288 00001288 2**3
CONTENTS, ALLOC, LOAD, READONLY, DATA
6 .init 00000009 0000000000001930 0000000000001930 00001930 2**0
CONTENTS, ALLOC, LOAD, READONLY, CODE
7 .plt 00000480 0000000000001940 0000000000001940 00001940 2**4
CONTENTS, ALLOC, LOAD, READONLY, CODE
8 .text 00003a9a 0000000000001dc0 0000000000001dc0 00001dc0 2**4
CONTENTS, ALLOC, LOAD, READONLY, CODE
9 .fini 00000009 000000000000585a 000000000000585a 0000585a 2**0
CONTENTS, ALLOC, LOAD, READONLY, CODE
10 .rodata 0001eb88 0000000000005880 0000000000005880 00005880 2**5
CONTENTS, ALLOC, LOAD, READONLY, DATA
11 .eh_frame_hdr 000000bc 0000000000024408 0000000000024408 00024408 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
12 .eh_frame 00000554 00000000000244c8 00000000000244c8 000244c8 2**3
CONTENTS, ALLOC, LOAD, READONLY, DATA
13 .note 00000018 0000000000024a1c 0000000000024a1c 00024a1c 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
14 .init_array 00000010 0000000000224b20 0000000000224b20 00024b20 2**3
CONTENTS, ALLOC, LOAD, DATA
15 .fini_array 00000008 0000000000224b30 0000000000224b30 00024b30 2**3
CONTENTS, ALLOC, LOAD, DATA
16 .jcr 00000008 0000000000224b38 0000000000224b38 00024b38 2**3
CONTENTS, ALLOC, LOAD, DATA
17 .data.rel.ro 00000048 0000000000224b40 0000000000224b40 00024b40 2**5
CONTENTS, ALLOC, LOAD, DATA
18 .dynamic 000001e0 0000000000224b88 0000000000224b88 00024b88 2**3
CONTENTS, ALLOC, LOAD, DATA
19 .got 00000288 0000000000224d68 0000000000224d68 00024d68 2**3
CONTENTS, ALLOC, LOAD, DATA
20 .data 00000078 0000000000225000 0000000000225000 00025000 2**5
CONTENTS, ALLOC, LOAD, DATA
21 .bss 00000050 0000000000225080 0000000000225080 00025078 2**5
ALLOC
22 .comment 0000003e 0000000000000000 0000000000000000 00025078 2**0
CONTENTS, READONLY
23 QNX_usage 00000cc4 0000000000000000 0000000000000000 000250b6 2**0
CONTENTS, READONLY
24 .gnu_debuglink 00000020 0000000000000000 0000000000000000 00025d7a 2**0
CONTENTS, READONLY
25 QNX_info 000000ed 0000000000000000 0000000000000000 00025d9a 2**0
CONTENTS, READONLY
SYMBOL TABLE:
0000000000000001 l *ABS* 0000000000000000 __pic__
0000000000000001 l *ABS* 0000000000000000 __PIC__
0000000000000001 l *ABS* 0000000000000000 __pic__
0000000000000001 l *ABS* 0000000000000000 __PIC__
0000000000024508 l O .eh_frame 0000000000000000 __EH_FRAME_BEGIN__
0000000000224b38 l O .jcr 0000000000000000 __JCR_LIST__
0000000000001de0 l F .text 0000000000000000 deregister_tm_clones
0000000000001e20 l F .text 0000000000000000 register_tm_clones
0000000000001e70 l F .text 0000000000000000 __do_global_dtors_aux
0000000000225080 l O .bss 0000000000000001 completed.6154
0000000000224b30 l O .fini_array 0000000000000000 __do_global_dtors_aux_fini_array_entry
0000000000001ec0 l F .text 0000000000000000 frame_dummy
00000000002250a0 l O .bss 0000000000000030 object.6159
0000000000224b20 l O .init_array 0000000000000000 __frame_dummy_init_array_entry
0000000000000001 l *ABS* 0000000000000000 __pic__
0000000000000001 l *ABS* 0000000000000000 __PIC__
0000000000001f10 l F .text 0000000000000033 vdinput_pulse
0000000000001f50 l F .text 000000000000022b vi_event_transfer
0000000000002180 l F .text 00000000000000a9 vdinput_vread
0000000000002230 l F .text 0000000000000132 vi_device_lookup
0000000000002370 l F .text 000000000000004c vi_device_touches
00000000000023c0 l F .text 0000000000000081 vi_device_coords
0000000000002450 l F .text 000000000000008c vi_device_moved
00000000000024e0 l F .text 0000000000000077 vi_config_insert.isra.9
0000000000002560 l F .text 00000000000002f3 abs_dimensions
0000000000002860 l F .text 000000000000007d vi_config_merge
00000000000028e0 l F .text 000000000000069b screen_device_insertion
0000000000005d80 l O .rodata 000000000001e4ce keyboard_map_keys
0000000000005d68 l O .rodata 000000000000000a touch_map_taps
0000000000005d78 l O .rodata 0000000000000008 pointer_map_buttons
0000000000002f80 l F .text 0000000000001559 event_via_screen
0000000000005d50 l O .rodata 0000000000000011 __func__.10353
0000000000005d20 l O .rodata 0000000000000008 overflow.10144
0000000000005d30 l O .rodata 0000000000000017 __func__.10307
00000000000044e0 l F .text 00000000000000a3 vi_state_reset
0000000000004590 l F .text 00000000000002b3 vdinput_vwrite
0000000000004850 l F .text 000000000000007a vdinput_pulse_thread
0000000000004a20 l F .text 00000000000005cf vi_screen_setup
0000000000004ff0 l F .text 000000000000077b vdinput_control
0000000000024260 l O .rodata 0000000000000020 input_description
0000000000001dc0 l F .text 0000000000000011 vdinput_register
0000000000225020 l O .data 0000000000000058 vdinput_factory.10591
0000000000224b40 l O .data.rel.ro 0000000000000048 vdinput_options.10590
0000000000000001 l *ABS* 0000000000000000 __pic__
0000000000000001 l *ABS* 0000000000000000 __PIC__
0000000000000001 l *ABS* 0000000000000000 __pic__
0000000000000001 l *ABS* 0000000000000000 __PIC__
0000000000024a18 l O .eh_frame 0000000000000000 __FRAME_END__
0000000000224b38 l O .jcr 0000000000000000 __JCR_END__
0000000000224b88 l O .dynamic 0000000000000000 _DYNAMIC
0000000000225078 l O .data 0000000000000000 __TMC_END__
0000000000225000 l O .data 0000000000000000 __dso_handle
0000000000224d68 l O .got 0000000000000000 _GLOBAL_OFFSET_TABLE_
00000000000001c8 l d .note.gnu.build-id 0000000000000000 .note.gnu.build-id
00000000000001e8 l d .gnu.hash 0000000000000000 .gnu.hash
0000000000000230 l d .dynsym 0000000000000000 .dynsym
0000000000000a40 l d .dynstr 0000000000000000 .dynstr
0000000000001048 l d .rela.dyn 0000000000000000 .rela.dyn
0000000000001288 l d .rela.plt 0000000000000000 .rela.plt
0000000000001930 l d .init 0000000000000000 .init
0000000000001940 l d .plt 0000000000000000 .plt
0000000000001dc0 l d .text 0000000000000000 .text
000000000000585a l d .fini 0000000000000000 .fini
0000000000005880 l d .rodata 0000000000000000 .rodata
0000000000024408 l d .eh_frame_hdr 0000000000000000 .eh_frame_hdr
00000000000244c8 l d .eh_frame 0000000000000000 .eh_frame
0000000000024a1c l d .note 0000000000000000 .note
0000000000224b20 l d .init_array 0000000000000000 .init_array
0000000000224b30 l d .fini_array 0000000000000000 .fini_array
0000000000224b38 l d .jcr 0000000000000000 .jcr
0000000000224b40 l d .data.rel.ro 0000000000000000 .data.rel.ro
0000000000224b88 l d .dynamic 0000000000000000 .dynamic
0000000000224d68 l d .got 0000000000000000 .got
0000000000225000 l d .data 0000000000000000 .data
0000000000225080 l d .bss 0000000000000000 .bss
0000000000000000 l d .comment 0000000000000000 .comment
0000000000000000 l d QNX_usage 0000000000000000 QNX_usage
0000000000000000 l d .gnu_debuglink 0000000000000000 .gnu_debuglink
0000000000000000 l d QNX_info 0000000000000000 QNX_info
0000000000000000 *UND* 0000000000000000 vio_setup_queues
0000000000005770 g F .text 0000000000000033 virtq_avail_get
0000000000000000 *UND* 0000000000000000 guest_cpu_read
0000000000000000 F *UND* 0000000000000000 pthread_cond_signal
0000000000000000 F *UND* 0000000000000000 screen_get_window_property_pv
0000000000000000 F *UND* 0000000000000000 strerror
0000000000000000 *UND* 0000000000000000 gfdt_update_prop_string
00000000000057b0 g F .text 00000000000000aa virtq_used_put_notify
0000000000000000 F *UND* 0000000000000000 screen_set_window_property_pv
0000000000000000 F *UND* 0000000000000000 snprintf
0000000000000000 F *UND* 0000000000000000 screen_get_device_property_iv
00000000000048d0 g F .text 0000000000000141 set_display
0000000000000000 *UND* 0000000000000000 vio_ctrl_pci_bars
0000000000000000 O *UND* 0000000000000000 __stack_chk_guard
0000000000000000 *UND* 0000000000000000 qvm_outf
0000000000000000 F *UND* 0000000000000000 screen_create_window_buffers
0000000000000000 F *UND* 0000000000000000 getpid
0000000000000000 F *UND* 0000000000000000 screen_destroy_event
0000000000000000 F *UND* 0000000000000000 screen_flush_context
0000000000000000 F *UND* 0000000000000000 pthread_cancel
0000000000000000 F *UND* 0000000000000000 screen_create_window_type
0000000000000000 *UND* 0000000000000000 gasp_unmap
0000000000000000 w F *UND* 0000000000000000 __cxa_finalize
0000000000000000 F *UND* 0000000000000000 screen_set_session_property_pv
0000000000000000 F *UND* 0000000000000000 malloc
0000000000000000 F *UND* 0000000000000000 screen_destroy_session
0000000000000000 *UND* 0000000000000000 vio_init_queue
0000000000000000 F *UND* 0000000000000000 screen_destroy_window
0000000000000000 F *UND* 0000000000000000 screen_set_session_property_iv
0000000000000000 *UND* 0000000000000000 qvm_outff
0000000000000000 F *UND* 0000000000000000 __stack_chk_fail
0000000000001930 g F .init 0000000000000000 _init
0000000000000000 F *UND* 0000000000000000 screen_create_event
0000000000000000 F *UND* 0000000000000000 screen_set_window_property_iv
0000000000000000 F *UND* 0000000000000000 screen_get_event
0000000000000000 F *UND* 0000000000000000 calloc
0000000000000000 F *UND* 0000000000000000 screen_get_event_property_pv
0000000000000000 F *UND* 0000000000000000 screen_notify
0000000000000000 w *UND* 0000000000000000 __deregister_frame_info
0000000000000000 *UND* 0000000000000000 vio_read
0000000000000000 w *UND* 0000000000000000 _ITM_registerTMCloneTable
0000000000000000 *UND* 0000000000000000 guest_cpu_write
0000000000000000 F *UND* 0000000000000000 __get_errno_ptr
0000000000000000 *UND* 0000000000000000 gfdt_update_reg
0000000000000000 *UND* 0000000000000000 gfdt_update_node
0000000000000000 *UND* 0000000000000000 vdev_register_factory
0000000000000000 F *UND* 0000000000000000 screen_create_session_type
0000000000000000 F *UND* 0000000000000000 strlcpy
0000000000000000 F *UND* 0000000000000000 strncmp
0000000000000000 F *UND* 0000000000000000 pthread_cond_init
0000000000000000 F *UND* 0000000000000000 sscanf
0000000000001dc0 g .text 0000000000000000 _btext
0000000000000000 F *UND* 0000000000000000 screen_set_window_property_cv
0000000000000000 w *UND* 0000000000000000 _ITM_deregisterTMCloneTable
0000000000225078 g .bss 0000000000000000 __bss_start
0000000000000000 F *UND* 0000000000000000 memset
0000000000000000 *UND* 0000000000000000 qvm_parse_num
0000000000000000 F *UND* 0000000000000000 screen_get_window_property_cv
0000000000000000 F *UND* 0000000000000000 strcmp
0000000000000000 F *UND* 0000000000000000 pthread_mutex_unlock
0000000000000000 *UND* 0000000000000000 vio_write
000000000000585a g F .fini 0000000000000000 _fini
0000000000000000 F *UND* 0000000000000000 screen_get_window_property_iv
0000000000000000 F *UND* 0000000000000000 screen_get_event_property_iv
0000000000000000 *UND* 0000000000000000 vio_init
0000000000000000 F *UND* 0000000000000000 screen_create_context
0000000000225078 g .data 0000000000000000 _edata
00000000002250d0 g .bss 0000000000000000 _end
0000000000000000 F *UND* 0000000000000000 pthread_mutex_lock
0000000000000000 F *UND* 0000000000000000 pthread_cond_wait
0000000000000000 *UND* 0000000000000000 vio_reset
0000000000000000 F *UND* 0000000000000000 pthread_cond_destroy
0000000000000000 *UND* 0000000000000000 gfdt_update_interrupts
0000000000000000 F *UND* 0000000000000000 screen_get_context_property_pv
0000000000000000 F *UND* 0000000000000000 screen_get_display_property_iv
0000000000000000 *UND* 0000000000000000 vdev_pulse
0000000000000000 F *UND* 0000000000000000 screen_destroy_context
0000000000000000 *UND* 0000000000000000 gasp_map_vdma
0000000000000000 w *UND* 0000000000000000 _Jv_RegisterClasses
0000000000000000 F *UND* 0000000000000000 pthread_join
0000000000000000 w *UND* 0000000000000000 __register_frame_info
0000000000000000 *UND* 0000000000000000 vdev_thread_create
0000000000000000 F *UND* 0000000000000000 screen_get_context_property_iv
0000000000000000 F *UND* 0000000000000000 free
virtio与具体设备对应关系:
msmnile_gvmq:/ # cat /proc/interrupts | grep virt
5: 206598 0 0 0 0 0 0 GICv3 80 Level virtio0-1c200000.virtio_clock
6: 6 0 0 0 0 0 0 GICv3 81 Level virtio1-1c300000.virtio_clock
7: 139 0 0 0 0 0 0 GICv3 74 Level virtio2-1c700000.virtio_regulator
8: 0 0 0 0 0 0 0 GICv3 77 Level virtio3-1c800000.virtio-spmi
159: 8 0 0 0 0 0 0 GICv3 40 Level virtio4-1c450000.virtio_blk, virtio8-1c0b0000.virtio_blk
160: 5 0 0 0 0 0 0 GICv3 43 Level virtio5-1c460000.virtio_blk
161: 5 0 0 0 0 0 0 GICv3 44 Level virtio6-1c470000.virtio_blk
162: 115140 0 0 0 0 0 0 GICv3 45 Level virtio7-1c480000.virtio_blk
163: 2 0 0 0 0 0 0 GICv3 48 Level virtio9-1c140000.virtio_blk
164: 1 0 0 0 0 0 0 GICv3 49 Level virtio10-1c0f0000.virtio_blk
165: 0 0 0 0 0 0 0 GICv3 46 Level virtio11-1c380000.virtio_input_mtouch
166: 0 0 0 0 0 0 0 GICv3 42 Level virtio12-1c0d0000.virtio_input_mtouch
167: 0 0 0 0 0 0 0 GICv3 82 Level virtio13-1c900000.virtio_fastrpc
168: 33871 0 0 0 0 0 0 GICv3 76 Level virtio14-1c1c0000.virtio_net
169: 19030 0 0 0 0 0 0 GICv3 41 Level virtio15-1c0c0000.virtio_net
195: 643 0 0 0 0 0 0 GICv3 37 Level virtio16-1c090000.virtio_console
197: 0 0 0 0 0 0 0 GICv3 47 Level virtio17-1c150000.virtio_input_keyboard