Android virtio-input driver loading process analysis

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

register_virtio_driver

driver_register

__driver_attach

summary

The mystery of missing device configuration information

Add debug log in virtio-mmio

Add debug log in bus_for_each_dev

Translate fdt file

Who modified the dts data?

 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

Guess you like

Origin blog.csdn.net/kill150/article/details/130237978