Hypervisor display graphics card node card0 generation process

start

We know that the bottom layer of the android display module is provided by drm (Direct Rendering Manger), and the sign that the drm driver is loaded is the generation of the graphics card device node:

130|msmnile_gvmq:/sys/class/drm/card0/device/driver # ls /dev/dri/
card0  renderD128
msmnile_gvmq:/sys/class/drm/card0/device/driver #

Now we want to explore how the two file nodes on the android side are generated under the QNX hypervisor (Qualcomm baseline 1.2.1, kernel version 5.4).

Locate the hyp display source code path

We need to track the code and perform necessary debugging to confirm the generation process of these two file nodes, so the first step we need to do now is to determine its driver source code directory.

Start with /dev/ and /sys

Generally, the names of file nodes under /dev/ are special, and are usually specified by the driver module source code or the corresponding subsystem module allocation in the kernel. Here we try to directly search for strings related to card/render, but there are too many search results, and we cannot quickly locate the source code location.

Here we can start from the /sys directory and enter the /sys/class/drm/card0 directory, where we can get some information:

msmnile_gvmq:/sys/class/drm/card0/device # ls
driver  driver_override  drm  modalias  of_node  power  subsystem  uevent
msmnile_gvmq:/sys/class/drm/card0/device # ls
driver  driver_override  drm  modalias  of_node  power  subsystem  uevent
msmnile_gvmq:/sys/class/drm/card0/device # cat of_node/name
qcom,sde_kms_hypmsmnile_gvmq:/sys/class/drm/card0/device # cat dri
driver/           driver_override
msmnile_gvmq:/sys/class/drm/card0/device # cat driver/
bind                                                           soc:qcom,sde-cfg:qcom,sde-sub-cfg@1:qcom,sde_kms_hyp@ae00000/  uevent                                                         unbind
msmnile_gvmq:/sys/class/drm/card0/device # cat driver/

From the obtained information, we know the keywords of the driver when adapting dts: qcom, sde_kms_hyp, and some dts configuration information: soc:qcom, sde-cfg:qcom, sde-sub-cfg@1:qcom, sde_kms_hyp@ae00000

Locate the driver source code path

Now search in the driver directory: qcom, sde-kms-hyp, but it seems that there is no search result.

Then search in the kernel root directory: qcom, sde-kms-hyp, and find that its source code is located in: $KERNEL_ROOT/techpack/display/ directory.

It should be noted that the compilation configuration in the techpack/display directory is not controlled by the kernel config file (the board-level configuration file in the arch/arm64/config directory), but has its own separate configuration file. Open the file: techpack/display/Makefile and we can see:

 The source code of the techpack/display directory actually includes the source code of the LA/LV baseline and the hypervisor display baseline. Here our baseline is the HYP display baseline, so the specific kernel configuration is recorded in the file techpack/display/config/gvmgen3disp.conf.

 These configurations will not be reflected in .config after compilation, nor will they be reflected in /proc/config.gz.

So the code we need to analyze roughly has several directories:

summary

1. We get the keywords related to display in dts from the node information in the /sys directory

2. Locate the driver directory by searching these keywords under $KERNEL_ROOT/techpack/display/

3. After analyzing the code, it is found that the code in the display directory contains the display driver code for single LA/LV baseline and Q+A baseline

4. Confirm that the directory we need to analyze is:

msm-cfg  msm-hyp  msm-hyp-legacy  msm-lease

code analysis

Ignoring the process of code analysis, here is the conclusion directly:

1. Among the codes mentioned above that need to be analyzed, only the code in the red box is useful (msm-cfg&msm-hyp-legacy). The code in the green box will only run register when the kernel driver is loaded, and will not execute the probe function at all.

2. The code in the green box does not compile at all and does not affect the operation of the system . These codes feel like legacy codes

3. When the driver is loaded, the msm-cfg module will be loaded first, and then the msm-hyp-legacy module will be brought up. In essence, they are a module. The purpose is to create the drm device card0 and renderD128 required by the android system. In the driver implementation, these two nodes only provide very limited file operation functions, such as open/close, and ioctl is almost not implemented. This is also clearly stated in the NOTES under the directory :

NOTES about msm drm/kms hyp driver:

This driver registers with drm framework for the purpose of creating the 
/dev/dri/card0 path, which User Space DRM masters rely on. 
Furthermore, per-CRTC VBLANK and PAGE_FLIP events are queued to the device
path to notify User Space components listeners.

No other IOCTL or HW support is provided through this driver.

However, it does not mean that the upper layer will not use these interfaces, on the contrary, the upper layer will still use these interfaces frequently

[     0.968418],4,527,-;for debug: now we are msm_drm_register techpack/display/msm-hyp/msm_drv_hyp.c +2212
[     7.729034],4,808,-;for debug: now we are msm_open techpack/display/msm-hyp-legacy/msm_drv_hyp.c +56, proess is:android.hardwar pid 426
[     7.731890],4,810,-;for debug: now we are msm_drm_ioctl techpack/display/msm-hyp-legacy/msm_drv_hyp.c +347, proess is:android.hardwar pid 426,
[     7.732684],4,811,-;for debug: now we are msm_ioctl_query_client_id techpack/display/msm-hyp-legacy/msm_drv_hyp.c +333 
[     7.733158],4,812,-;for debug: now we are _msm_parse_dt techpack/display/msm-hyp-legacy/msm_drv_hyp.c +304 
[     7.764510],6,823,-;for debug: now we are msm_open techpack/display/msm-hyp-legacy/msm_drv_hyp.c +56, proess is:android.hardwar pid 426
[     7.764528],6,824,-;for debug: now we are msm_open techpack/display/msm-hyp-legacy/msm_drv_hyp.c +56, proess is:android.hardwar pid 426
[     7.764542],6,825,-;for debug: now we are msm_open techpack/display/msm-hyp-legacy/msm_drv_hyp.c +56, proess is:android.hardwar pid 426
[     8.054259],6,888,-;for debug: now we are msm_open techpack/display/msm-hyp-legacy/msm_drv_hyp.c +56, proess is:[email protected] pid 426
[     8.054283],6,889,-;for debug: now we are msm_open techpack/display/msm-hyp-legacy/msm_drv_hyp.c +56, proess is:[email protected] pid 426
[     8.054292],6,890,-;for debug: now we are msm_open techpack/display/msm-hyp-legacy/msm_drv_hyp.c +56, proess is:[email protected] pid 426
[     8.054306],6,891,-;for debug: now we are msm_open techpack/display/msm-hyp-legacy/msm_drv_hyp.c +56, proess is:[email protected] pid 426
[    12.488209],6,1234,-;for debug: now we are msm_drm_ioctl techpack/display/msm-hyp-legacy/msm_drv_hyp.c +347, proess is:[email protected] pid 426
[    12.488214],6,1235,-;for debug: now we are msm_ioctl_gem_get techpack/display/msm-hyp-legacy/msm_drv_hyp.c +205, proess is:[email protected] pid
[    12.525305],6,1248,-;for debug: now we are msm_drm_ioctl techpack/display/msm-hyp-legacy/msm_drv_hyp.c +347, proess is:[email protected] pid 426
[    12.525311],6,1249,-;for debug: now we are msm_ioctl_gem_get techpack/display/msm-hyp-legacy/msm_drv_hyp.c +205, proess is:[email protected] pid
[    12.542423],6,1259,-;for debug: now we are msm_drm_write techpack/display/msm-hyp-legacy/msm_drv_hyp.c +160, proess is:DRMFE_EventList pid 516
[    12.542427],6,1260,-;for debug: now we are create_vblank_event techpack/display/msm-hyp-legacy/msm_drv_hyp.c +99, proess is:DRMFE_EventList pi
[    12.775925],6,1268,-;for debug: now we are msm_drm_write techpack/display/msm-hyp-legacy/msm_drv_hyp.c +160, proess is:DRMFE_EventList pid 516
[    12.775929],6,1269,-;for debug: now we are create_vblank_event techpack/display/msm-hyp-legacy/msm_drv_hyp.c +99, proess is:DRMFE_EventList pi
[    12.792664],6,1270,-;for debug: now we are msm_drm_write techpack/display/msm-hyp-legacy/msm_drv_hyp.c +160, proess is:DRMFE_EventList pid 516
[    12.792668],6,1271,-;for debug: now we are create_vblank_event techpack/display/msm-hyp-legacy/msm_drv_hyp.c +99, proess is:DRMFE_EventList pi
[    12.809313],6,1272,-;for debug: now we are msm_drm_write techpack/display/msm-hyp-legacy/msm_drv_hyp.c +160, proess is:DRMFE_EventList pid 516
[    12.809316],6,1273,-;for debug: now we are create_vblank_event techpack/display/msm-hyp-legacy/msm_drv_hyp.c +99, proess is:DRMFE_EventList pi
[    12.825947],6,1274,-;for debug: now we are msm_drm_write techpack/display/msm-hyp-legacy/msm_drv_hyp.c +160, proess is:DRMFE_EventList pid 516
[    12.825951],6,1275,-;for debug: now we are create_vblank_event techpack/display/msm-hyp-legacy/msm_drv_hyp.c +99, proess is:DRMFE_EventList pi
[    12.842704],6,1278,-;for debug: now we are msm_drm_write techpack/display/msm-hyp-legacy/msm_drv_hyp.c +160, proess is:DRMFE_EventList pid 516
[    12.842708],6,1279,-;for debug: now we are create_vblank_event techpack/display/msm-hyp-legacy/msm_drv_hyp.c +99, proess is:DRMFE_EventList pi
[    12.859308],6,1284,-;for debug: now we are msm_drm_write techpack/display/msm-hyp-legacy/msm_drv_hyp.c +160, proess is:DRMFE_EventList pid 516

4. The process of generating card0 and renderD128 in the msm-hyp-legacy module is also very simple. Call drm_dev_alloc in the msm_pdev_probe function in the msm-hyp-legacy module to apply for drm devices, and then call drm_dev_register to register drm devices, and then generate card0&render128 nodes

static int msm_pdev_probe(struct platform_device *pdev)
{
    struct device *dev = &pdev->dev;
    struct drm_device *ddev;
    struct msm_drm_private *priv;
    int ret;

    ddev = drm_dev_alloc(&msm_driver, dev);
    if (!ddev) {
        dev_err(dev, "failed to allocate drm_device\n");
        return -ENOMEM;
    }   

    platform_set_drvdata(pdev, ddev);

    priv = kzalloc(sizeof(*priv), GFP_KERNEL);
    if (!priv) {
        ret = -ENOMEM;
        goto priv_alloc_fail;
    }   

    ddev->dev_private = priv;
    priv->dev = ddev;

    ret = drm_dev_register(ddev, 0); 
    if (ret) {
        dev_err(dev, "failed to register drm device\n");
        goto fail;
    }   

    return 0;

fail:

priv_alloc_fail:
    drm_dev_put(ddev);
    return ret;
}

5. In the drm_dev_register function, two nodes will be generated, namely render128 and card0. Different nodes will be generated by passing the two parameters of DRM_MINOR_RENDER and DRM_MINOR_PRIMARY when calling drm_minor_register. Among them, DRM_MINOR_RENDER is responsible for generating render128, while DRM_MINOR_PRIMARY is responsible for generating card0 nodes.

int drm_dev_register(struct drm_device *dev, unsigned long flags)
{
    struct drm_driver *driver = dev->driver;
    int ret;

    mutex_lock(&drm_global_mutex);

    ret = drm_minor_register(dev, DRM_MINOR_RENDER);
    if (ret)
        goto err_minors;

    ret = drm_minor_register(dev, DRM_MINOR_PRIMARY);
    if (ret)
        goto err_minors;

    ret = create_compat_control_link(dev);
    if (ret)
        goto err_minors;

    dev->registered = true;

    if (dev->driver->load) {
        ret = dev->driver->load(dev, flags);
        if (ret)
            goto err_minors;
    }

    if (drm_core_check_feature(dev, DRIVER_MODESET))
        drm_modeset_register_all(dev);

    ret = 0;

    DRM_INFO("Initialized %s %d.%d.%d %s for %s on minor %d\n",
         driver->name, driver->major, driver->minor,
         driver->patchlevel, driver->date,
         dev->dev ? dev_name(dev->dev) : "virtual device",
         dev->primary->index);

    goto out_unlock;

err_minors:
    remove_compat_control_link(dev);
    drm_minor_unregister(dev, DRM_MINOR_PRIMARY);
    drm_minor_unregister(dev, DRM_MINOR_RENDER);
out_unlock:
    mutex_unlock(&drm_global_mutex);
    return ret;
}

6. If we do a complete drm test on LA's drm driver, will it pass?

From the analysis point of view, Q+A's drm driver is just an empty shelf without any real content, so it cannot be tested.

7. For drivers of the same level, how does the kernel guarantee their loading order? For example, now we have two drivers with the same __initcall level msm_drm_register

There are many ways for the kernel to control the driver loading order, one of which is to control the sequence in the Makefile, such as the module we are currently analyzing:

 The location of msm-cfg should be prior to msm-hyp. From system.map, the msm-cfg module will be loaded prior to the msm-hyp module.

8. How does DTS interact with the driver?

The display-related dts configuration is in the file: arch/arm64/boot/dts/vendor/qcom/display/quin-vm-display.dtsi, and the content is not much:

&soc {
    sde_cfg: qcom,sde-cfg {
        compatible = "qcom,sde-cfg";

        qcom,sde-sub-cfg@0 {
            reg = <0>;
            wfd_kms: qcom,wfd_kms@0 {
                compatible = "qcom,wfd-kms";
                qcom,client-id = "7815";
            };

            qcom,sde_kms_hyp@ae00000 {
                compatible = "qcom,sde-kms-hyp";
                qcom,kms = <&wfd_kms>;
            };
        };

        qcom,sde-sub-cfg@1 {
            reg = <1>;
            qcom,sde_kms_hyp@ae00000 {
                compatible = "qcom,sde-kms-hyp-legacy";
                qcom,client-id = "7815";
            };
        };
    };  
};

This file will be included into the file arch/arm64/boot/dts/vendor/qcom/sa8155-vm-la.dtsi. When the driver is loaded, it will first match the msm-cfg driver module through qcom and sde-cfg , and then this module will bring up the remaining legacy and lease modules.

9, who will use this node:

msmnile_gvmq:/ # lsof | grep renderD128
1|msmnile_gvmq:/ #
1|msmnile_gvmq:/ #
1|msmnile_gvmq:/ #
1|msmnile_gvmq:/ # lsof | grep card0
[email protected]   406     system    7u      CHR              226,0       0t0      16645 /dev/dri/card0
[email protected]   406     system   15u      CHR              226,0       0t0      16645 /dev/dri/card0
[email protected]   406     system   16u      CHR              226,0       0t0      16645 /dev/dri/card0
[email protected]   406     system   17u      CHR              226,0       0t0      16645 /dev/dri/card0
[email protected]   406     system   19u      CHR              226,0       0t0      16645 /dev/dri/card0
[email protected]   406     system   21u      CHR              226,0       0t0      16645 /dev/dri/card0
[email protected]   406     system   22u      CHR              226,0       0t0      16645 /dev/dri/card0
[email protected]   406     system   23u      CHR              226,0       0t0      16645 /dev/dri/card0
msmnile_gvmq:/ #
msmnile_gvmq:/ #
msmnile_gvmq:/ # lsof | grep hgsl
hgsl-release-wq   169       root  cwd       DIR              252,6      4096          2 /
hgsl-release-wq   169       root  rtd       DIR              252,6      4096          2 /
hgsl-release-wq   169       root  txt   unknown                                         /proc/169/exe (readlink: No such file or directory)
[email protected]   399 cameraserv    7u      CHR              241,0       0t0       4542 /dev/hgsl
[email protected]   399 cameraserv    8u      CHR              241,0       0t0       4542 /dev/hgsl
[email protected]   406     system   10u      CHR              241,0       0t0       4542 /dev/hgsl
[email protected]   406     system   11u      CHR              241,0       0t0       4542 /dev/hgsl
[email protected]   406     system   12u      CHR              241,0       0t0       4542 /dev/hgsl
[email protected]   406     system   13u      CHR              241,0       0t0       4542 /dev/hgsl
cameraprovider@   420       root    4u      CHR              241,0       0t0       4542 /dev/hgsl
cameraprovider@   420       root    7u      CHR              241,0       0t0       4542 /dev/hgsl
surfaceflinger   472     system   14u      CHR              241,0       0t0       4542 /dev/hgsl
surfaceflinger   472     system   15u      CHR              241,0       0t0       4542 /dev/hgsl
surfaceflinger   472     system   16u      CHR              241,0       0t0       4542 /dev/hgsl
surfaceflinger   472     system   17u      CHR              241,0       0t0       4542 /dev/hgsl
Binder:1095_3  1095     system  320u      CHR              241,0       0t0       4542 /dev/hgsl
Binder:1095_3  1095     system  330u      CHR              241,0       0t0       4542 /dev/hgsl
Binder:1095_3  1095     system  334u      CHR              241,0       0t0       4542 /dev/hgsl
ndroid.systemui  2167     system   71u      CHR              241,0       0t0       4542 /dev/hgsl
ndroid.systemui  2167     system   72u      CHR              241,0       0t0       4542 /dev/hgsl
ndroid.systemui  2167     system   74u      CHR              241,0       0t0       4542 /dev/hgsl

10. How is the ioctl operation called by the application layer in the Display module passed to the QNX side?

In fact, the ioctl in the Display module will eventually notify the hgsl module in the form of a signal, and the hgsl module will notify QNX through the hab

Guess you like

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