Table of contents
Full backtrace of virtinput_probe call
kernel_init to do_one_initcall
The process of virtio_input_driver_init matching device and driver through bus
The mystery of missing device configuration information
Add debug log in bus_for_each_dev
register_for_ssr_events function
Full backtrace of virtinput_probe call
The following is the complete backtrace of the process of virinput_probe being called (you can output this information to the kernel log by adding WARN_ON() to the virinput_probe function).
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
This backtrace is roughly divided into three parts:
1, kernel_init to do_one_initcall
2. The process of virtio_input_driver_init matching device and driver through bus
3,virtinput_probe
kernel_init to do_one_initcall
This process is relatively clear. To put it simply, the kernel_init kernel thread will call do_initcall_level to load the driver modules of each level in turn. These driver modules are divided into many levels, and the loading priority of each level is different. These driver modules have already existed in the kernel image according to the corresponding level when the kernel was compiled, and finally called by do_one_initcall to the entry of the function through different offsets.
The process of virtio_input_driver_init matching device and driver through bus
As mentioned earlier, do_one_initcall will call each fn to complete the driver loading, and these fn have been compiled in the kernel image, and placed in the corresponding section during the linking process. When the kernel is compiled, it knows which modules need to be compiled through the kernel config.
Taking the current virtio-input driver function as an example, the fn function in the do_one_initcall function is 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);
It should be noted that we cannot directly search for this function in the kernel source code. This function is usually a macro definition function. Analysis source code file: 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 is defined in the file 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 */
And the definition of module_driver is in the file: 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);
Seeing this, it is clear that the virtio_input_driver_init function definition is composed of virtio_input_driver + _init. Finally, the module_init macro definition of the kernel is registered in the kernel. When the kernel calls do_one_initcall to call the corresponding init functions one by one, it will eventually call the __register function in the above macro definition. This function is actually register_virtio_driver (in the module_driver macro definition second macro argument).
register_virtio_driver will call driver_register to follow the standard linux device driver model process, and finally call virinput_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
We know that the standard linux device driver model involves three concepts: bus, driver, device, here:
bus: virtio is a core level driver and a bus driver. The source code file is: drivers/virtio/virtio.c, other virtio devices are also based on this bus, such as virtio-i2c/virtio-blk, etc.
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: here is virtio_input_driver
device: I haven't found it yet. Usually, the device node information is usually obtained after dts analysis, but we searched the used dts file and found no nodes related to virtio-input.
But it doesn't matter, let's analyze from the virtio_input_driver_init function to see how he actually calls the probe function.
register_virtio_driver
Earlier we mentioned that virtio_input_driver_init actually calls the register_virtio_driver function when registering:
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);
}
The implementation of this function is very simple, first judge whether the feature_table_size and feature_table in the driver have been assigned normally, and then link the driver to the 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);
This function will start to make some judgments, such as judging whether the driver has been loaded to the bus, the most important of which is the bus_add_driver function.
__driver_attach
After a series of calls, this function finally calls the __driver_attach function. The most important call in this function is: ret = driver_match_device(drv, dev);
This line of code is where the driver and device are actually matched.
The implementation of this function code is also very simple. If the bus has its own match function, then call the bus's own match interface, otherwise return 1 directly.
static inline int driver_match_device(struct device_driver *drv,
struct device *dev)
{
return drv->bus->match ? drv->bus->match(dev, drv) : 1;
}
The match function of virtio bus is implemented as follows
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;
}
It can be seen that whether the driver and device will match is determined by the condition id->vendor == VIRTIO_DEV_ANY_ID || id->vendor == dev→id.vendor. In the driver drivers/virtio/virtio_input.c:
static struct virtio_device_id id_table[] = {
{ VIRTIO_ID_INPUT, VIRTIO_DEV_ANY_ID },
{ 0 },
};
summary
The entire virtio-input loading process is roughly divided into three parts
1, kernel_init to do_one_initcall
This process is relatively clear
2. The process of virtio_input_driver_init matching device and driver through bus
This process follows the standard linux device driver model. During the device-driver matching process, the match function defined by the bus is called to match the driver and device. In the virtio-input driver, use id_table to match the driver and device.
3,virtinput_probe
We know that generally speaking, the device is responsible for providing hardware resource information, such as gpio/register address, etc., but so far, we have not found any hardware resource information provided by the virtio-input device.
The mystery of missing device configuration information
We mentioned earlier that we couldn't find any virtio-touch configuration information in the kernel's dts and driver source code, but in fact, the virtio-touch driver loads and works without problems, which is very strange.
Because in theory, virtio-touch should follow the device driver model of the linux platform anyway, and the bus driver device is indispensable.
Add debug log in virtio-mmio
Virtio-mmio is the earliest virtio module from virtio in the kernel. In the probe function of this module, add log:
printk("for debug virtio_mmio_probe pdev->name:%s\n", pdev→name);
It is found that even if the log is printed at this time, it is found that pdev->name has already been assigned, and looking at the entire mmio driver, it seems that there are no interfaces for qnx communication in those places.
This is even more strange, because this experiment shows that our conjecture above may not be true. We need to find the earliest place where the kernel translates dtb into device node, and add the log there.
Add debug log in bus_for_each_dev
Adding a log to this function will print out the names of all device nodes in the kernel. After adding the log, it is found that even at the very beginning of the kernel, the virtio-touch node already exists.
I wonder if the dtb data obtained by the kernel is the data that has been added to the dts node?
Translate fdt file
We know that the msmnile_gvmq:/sys/firmware /fdt file in the kernel is the kernel dtb file, we can convert this file into dts, and confirm whether it contains the virtio-input node.
Use the command: dtc -I dtb -o sa8295p-vm.dts fdt to convert the dts file, in which we can find:
It shows that the virtio-input node is indeed added to the dtb data obtained by the kernel.
Who modified the dts data?
Observe the log file la_gvm.txt every time la starts, you can see that there are several lines of log
I suspect that these lines of logs are the places to add and modify dts. After trying to modify linux-la.config, I found that when the vdev vdev-virtio-input.so node is deleted, the output of the following lines of logs will also decrease. For example, the following log deleted two vdev vdev-virtio-input.so nodes (there were originally three)
We try to start from here.
register_for_ssr_events function
Search register_for_ssr_events in QNX, you can find the file AMSS/platform/vm/vdev/vdev-glink-ssr/vdev.c +683 function register_for_ssr_events, which has the operation of 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;
}
However, after in-depth research, I found that the real virtio register_for_ssr_events function is not called in this module, but the above module shows the possible usage in the virtio-input library (this library is not open source)
But we can use objdump to see the internal functions:
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
Correspondence between virtio and specific devices:
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