hypervisor display显卡节点card0生成过程

文章主要探讨了在QNXhypervisor环境下,基于高通基线1.2.1和内核版本5.4的Android系统中,dev/dri/card0和dev/dri/renderD128两个设备节点的生成过程。通过分析/sys/class/drm/card0目录下的信息,确定了驱动的关键字qcom,sde_kms_hyp,并在$KERNEL_ROOT/techpack/display/目录下找到相关源码。进一步,文章指出驱动加载时msm-cfg模块先加载,然后加载msm-hyp-legacy模块,这两个模块一起创建了所需的drm设备。虽然驱动仅实现了有限的文件操作,但上层应用仍会频繁使用相关接口。最后,文章提到了驱动加载顺序、dts配置和节点使用者的情况。

开始

我们知道android显示模块底层是由drm(Direct Rending Manger)提供的,drm驱动加载完成的标志是显卡设备节点生成:

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

这两个节点是:

/dev/dri/card0

/dev/dri/renderD128

现在我们想探究一下,在QNX hypervisor下(高通基线1.2.1,内核版本5.4),android侧的这两个文件节点是如何生成的.

定位hyp display源码路径

这两个节点是有驱动模块生成的,所以要了解生成的细节,就必须要分析其驱动源码。为了达成我们这篇文章的目的:hypervisor display显卡节点card0生成过程,我们需要下面几个工作

收集信息-》定位驱动源码模块-》分析代码-》信息汇总总结

但是目前摆在我们眼前的第一个问题就是需要搞清楚这两个节点是由哪些驱动源码生成的。.

从/dev/和/sys开始

一般/dev/下的文件节点的名字都具有特殊性,通常由驱动模块源码或者内核中相应的子系统模块分配指定。这里我们尝试直接搜索card/render相关的字符串,但是搜索结果太多,并不能很快的定位源码位置。

这里我们可以从/sys目录入手,进入/sys/class/drm/card0目录,这里可以获取到部分信息:

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/

从获取到的信息中,我们知道驱动在适配dts时候的关键字:qcom,sde_kms_hyp,以及部分dts配置信息:soc:qcom,sde-cfg:qcom,sde-sub-cfg@1:qcom,sde_kms_hyp@ae00000

定位驱动源码路径

现在driver目录下搜索:qcom,sde-kms-hyp,但是好像并没有搜索到结果。

紧接着在内核根目录下搜索:qcom,sde-kms-hyp,发现其源码位于:$KERNEL_ROOT/techpack/display/目录下.

需要注意的是,techpack/display目录下的编译配置并不由kernel config文件控制(arch/arm64/config目录下的板级配置文件),而是自己有单独的配置文件,打开文件:techpack/display/Makefile 我们可以看到:

 techpack/display目录的源码其实是包含了LA/LV基线以及hypervisor display基线的源码的,这里我们的基线是HYP display基线,所以具体的内核配置记录在文件techpack/display/config/gvmgen3disp.conf 中。

 这些配置在编译完成之后不会体现在.config中,也不会体现在/proc/config.gz中.

所以我们需要分析的代码大致有几个目录:

小结

1,我们从/sys目录下的node信息得到在dts中与display相关的关键字

2,通过搜索这些关键字定位驱动目录位于$KERNEL_ROOT/techpack/display/下

3,分析代码发现,display目录下代码包含了单LA/LV基线及Q+A基线的显示驱动代码

4,确认需要我们分析的目录为:

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

代码分析

忽略代码分析的过程,这里直接上结论:

1,前面提到的需要分析的代码中,其实只有红框部分代码有用(msm-cfg&msm-hyp-legacy),绿框中的代码在内核驱动加载的时候只会运行register,而根本不会执行probe函数。

2,绿框中的代码完全不编译也不影响系统运行,这些代码感觉像是历史遗留代码

3,驱动加载时,msm-cfg模块会先加载,然后带起msm-hyp-legacy模块,本质上他们是一个模块,目的是创建android系统需要的drm设备card0 和renderD128,驱动实现中,这两个节点只提供非常有限的文件操作功能,比如open/close,ioctl则几乎不实现。这点在目录下NOTES也说的很明白:

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.

但是,不代表上层不会使用这些接口,相反上层依旧会频繁的使用这些接口

[     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:composer@2.4-se 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:composer@2.4-se 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:composer@2.4-se 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:composer@2.4-se 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:composer@2.4-se 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:composer@2.4-se 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:composer@2.4-se 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:composer@2.4-se 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, msm-hyp-legacy模块中生成card0和renderD128的过程也很简单,在msm-hyp-legacy模块中的msm_pdev_probe函数中调用drm_dev_alloc来申请drm设备,然后调用drm_dev_register注册drm设备,进而生成card0&render128节点

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,在drm_dev_register函数中会生成2个节点,即render128和card0,通过调用drm_minor_register时传递DRM_MINOR_RENDER和DRM_MINOR_PRIMARY两种参数来生成不同的节点.其中DRM_MINOR_RENDER负责生成render128,而DRM_MINOR_PRIMARY则是生成card0节点.

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,如果我们对LA的drm驱动做完整的drm测试,他能通过吗?

从分析来看,Q+A的drm驱动只是一个空的架子,没有实质的内容,所以无法进行测试.

7,对于同一个level的驱动,内核如何保证其加载顺序?比如现在我们有两个同是__initcall level的驱动msm_drm_register

内核控制驱动加载顺序的方法有很多种,其中一种就是通过Makefile中的先后顺序进行控制,比如当前我们分析的这个模块:

 msm-cfg的位置要先于msm-hyp,从system.map看msm-cfg模块会优先于msm-hyp模块加载.

8,DTS如何与驱动产生联动的?

display相关的dts配置在文件:arch/arm64/boot/dts/vendor/qcom/display/quin-vm-display.dtsi, 内容也不多:

&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";
            };
        };
    };  
};

这个文件会被include到文件arch/arm64/boot/dts/vendor/qcom/sa8155-vm-la.dtsi 中。驱动加载的时候,会先通过qcom,sde-cfg匹配到msm-cfg驱动模块,在由这个模块带起剩下的legacy和lease模块.

9,都有谁会使用这个节点:

msmnile_gvmq:/ # lsof | grep renderD128
1|msmnile_gvmq:/ #
1|msmnile_gvmq:/ #
1|msmnile_gvmq:/ #
1|msmnile_gvmq:/ # lsof | grep card0
composer@2.4-se   406     system    7u      CHR              226,0       0t0      16645 /dev/dri/card0
composer@2.4-se   406     system   15u      CHR              226,0       0t0      16645 /dev/dri/card0
composer@2.4-se   406     system   16u      CHR              226,0       0t0      16645 /dev/dri/card0
composer@2.4-se   406     system   17u      CHR              226,0       0t0      16645 /dev/dri/card0
composer@2.4-se   406     system   19u      CHR              226,0       0t0      16645 /dev/dri/card0
composer@2.4-se   406     system   21u      CHR              226,0       0t0      16645 /dev/dri/card0
composer@2.4-se   406     system   22u      CHR              226,0       0t0      16645 /dev/dri/card0
composer@2.4-se   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)
provider@2.4-se   399 cameraserv    7u      CHR              241,0       0t0       4542 /dev/hgsl
provider@2.4-se   399 cameraserv    8u      CHR              241,0       0t0       4542 /dev/hgsl
composer@2.4-se   406     system   10u      CHR              241,0       0t0       4542 /dev/hgsl
composer@2.4-se   406     system   11u      CHR              241,0       0t0       4542 /dev/hgsl
composer@2.4-se   406     system   12u      CHR              241,0       0t0       4542 /dev/hgsl
composer@2.4-se   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, Display模块中被应用层调用的ioctl操作是如何传递到QNX侧的?

事实上,Display模块中的ioctl最终会以signal的方式通知hgsl模块,由hgsl模块通过hab通知到QNX

unning kernel seems to be up-to-date. No services need to be restarted. No containers need to be restarted. No user sessions are running outdated binaries. No VM guests are running outdated hypervisor (qemu) binaries on this host. [1] 14461 Error: unable to open display :1 root@srv771551:~# The XKEYBOARD keymap compiler (xkbcomp) reports: > Warning: Could not resolve keysym XF86CameraAccessEnable > Warning: Could not resolve keysym XF86CameraAccessDisable > Warning: Could not resolve keysym XF86CameraAccessToggle > Warning: Could not resolve keysym XF86NextElement > Warning: Could not resolve keysym XF86PreviousElement > Warning: Could not resolve keysym XF86AutopilotEngageToggle > Warning: Could not resolve keysym XF86MarkWaypoint > Warning: Could not resolve keysym XF86Sos > Warning: Could not resolve keysym XF86NavChart > Warning: Could not resolve keysym XF86FishingChart > Warning: Could not resolve keysym XF86SingleRangeRadar > Warning: Could not resolve keysym XF86DualRangeRadar > Warning: Could not resolve keysym XF86RadarOverlay > Warning: Could not resolve keysym XF86TraditionalSonar > Warning: Could not resolve keysym XF86ClearvuSonar > Warning: Could not resolve keysym XF86SidevuSonar > Warning: Could not resolve keysym XF86NavInfo Errors from xkbcomp are not fatal to the X server # 查看详细的DRM初始 查看详细的DRM初始化日志 sudo dmesg | grep -iE 'drm|i915|amdgpu|nouveau' # 强制重新加载图形模块(以Intel为例) sudo rmmod i915 sudo modprobe i915 debug=1 [ 8.488129] ACPI: bus type drm_connector registered [ 11.694958] systemd[1]: Starting modprobe@drm.service - Load Kernel Module drm... rmmod: ERROR: Module i915 is not currently loaded modprobe: FATAL: Module i915 not found in directory /lib/modules/6.8.0-60-generic root@srv771551:~# # 检查物理显示接口状态 sudo apt install edid-decode -y sudo cat /sys/class/drm/card0-DP-1/edid | edid-decode # 检测显示端口热插拔状态 grep -H . /sys/class/drm/*/status Reading package lists... Done Building dependency tree... Done Reading state information... Done The following NEW packages will be installed: edid-decode 0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded. Need to get 134 kB of archives. After this operation, 350 kB of additional disk space will be used. Get:1 http://in.archive.ubuntu.com/ubuntu noble/universe amd64 edid-decode amd64 0.1~git20220315.cb74358c2896-1.1 [134 kB] Fetched 134 kB in 1s (126 kB/s) Selecting previously unselected package edid-decode. (Reading database ... 104591 files and directories currently installed.) Preparing to unpack .../edid-decode_0.1~git20220315.cb74358c2896-1.1_amd64.deb ... Unpacking edid-decode (0.1~git20220315.cb74358c2896-1.1) ... Setting up edid-decode (0.1~git20220315.cb74358c2896-1.1) ... Processing triggers for man-db (2.12.0-4build2) ... Scanning processes... Scanning linux images... Running kernel seems to be up-to-date. No services need to be restarted. No containers need to be restarted. No user sessions are running outdated binaries. No VM guests are running outdated hypervisor (qemu) binaries on this host. cat: /sys/class/drm/card0-DP-1/edid: No such file or directory EDID of 'stdin' was empty. grep: /sys/class/drm/*/status: No such file or directory root@srv771551:~# # 使用LLVMpipe软件渲染 sudo apt install mesa-utils -y LIBGL_ALWAYS_SOFTWARE=1 glxinfo | grep "OpenGL renderer" # 验证CPU渲染能力 MESA_GL_VERSION_OVERRIDE=4.5 glxgears Reading package lists... Done Building dependency tree... Done Reading state information... Done mesa-utils is already the newest version (9.0.0-2). 0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded. OpenGL renderer string: llvmpipe (LLVM 19.1.1, 256 bits) The XKEYBOARD keymap compiler (xkbcomp) reports: > Warning: Could not resolve keysym XF86CameraAccessEnable > Warning: Could not resolve keysym XF86CameraAccessDisable > Warning: Could not resolve keysym XF86CameraAccessToggle > Warning: Could not resolve keysym XF86NextElement > Warning: Could not resolve keysym XF86PreviousElement > Warning: Could not resolve keysym XF86AutopilotEngageToggle > Warning: Could not resolve keysym XF86MarkWaypoint > Warning: Could not resolve keysym XF86Sos > Warning: Could not resolve keysym XF86NavChart > Warning: Could not resolve keysym XF86FishingChart > Warning: Could not resolve keysym XF86SingleRangeRadar > Warning: Could not resolve keysym XF86DualRangeRadar > Warning: Could not resolve keysym XF86RadarOverlay > Warning: Could not resolve keysym XF86TraditionalSonar > Warning: Could not resolve keysym XF86ClearvuSonar > Warning: Could not resolve keysym XF86SidevuSonar > Warning: Could not resolve keysym XF86NavInfo Errors from xkbcomp are not fatal to the X server 6622 frames in 5.0 seconds = 1324.350 FPS 5306 frames in 5.0 seconds = 1061.041 FPS 6476 frames in 5.0 seconds = 1295.068 FPS 7356 frames in 5.0 seconds = 1471.104 FPS 7530 frames in 5.0 seconds = 1505.943 FPS 7202 frames in 5.0 seconds = 1440.160 FPS 6918 frames in 5.0 seconds = 1383.580 FPS 6448 frames in 5.0 seconds = 1289.433 FPS 6896 frames in 5.0 seconds = 1379.091 FPS 7166 frames in 5.0 seconds = 1433.100 FPS
05-29
Hypervisor 配置中,虚拟 GPU(vGPU)的作用是为虚拟机提供硬件级别的图形加速能力。通过将物理 GPU 设备分配给一个或多个虚拟机,可以实现对 3D 图形、视频编解码以及通用计算任务(如 AI 计算)的支持。然而,在某些配置场景下,尽管 GPU 设备已经出现在 PCI 总线上,但在虚拟机内部却无法识别到该设备。 ### vGPU 虚拟机中找不到设备的原因分析 1. **Hypervisor 中的 CPUID 控制设置不当** - `hypervisor.cpuid.v0="FALSE"` 是一种用于屏蔽虚拟化特征的配置选项,常见于 VMware ESXi 环境中。此设置会阻止虚拟机检测到运行在虚拟化环境中的事实,可能导致某些驱动程序(尤其是 NVIDIA 显卡驱动)无法正确初始化 GPU 设备。 - 如果未正确配置此参数,NVIDIA 驱动可能因检测到虚拟化标志而拒绝加载,从而导致虚拟机内看不到 GPU 设备[^2]。 2. **设备直通配置错误** - 在进行 GPU 直通时,必须确保物理 GPU 已从宿主机中完全卸载,并正确绑定到 VFIO 或其他支持直通的驱动上。若 GPU 设备仍被宿主机占用,则虚拟机无法访问该设备。 - 对于 Windows 宿主机,需使用 PowerShell 命令卸载设备并将其分配给虚拟机: ```powershell Dismount-VMHostAssignableDevice -VMHost $vmHost -DevicePath $devicePath Add-VMAssignableDevice -VM $vm -DevicePath $devicePath ``` 若未执行上述步骤,设备可能无法被虚拟机识别[^1]。 3. **MMIO 地址空间不足** - GPU 设备需要足够的 MMIO(Memory-Mapped I/O)空间来映射其寄存器和显存区域。若 MMIO 分配过小,可能导致地址冲突或设备初始化失败。 - 在配置虚拟机时,应预留至少 512 MB 的额外缓冲区以避免此类问题。 4. **固件与 BIOS 设置限制** - 某些 GPU(尤其是消费级显卡如 NVIDIA GTX/RTX 系列)对虚拟化有严格的限制,要求 BIOS 中启用 IOMMU(Intel VT-d 或 AMD-Vi),并在虚拟机中使用特定固件(如 OVMF)启动。 - 若 BIOS 中未启用相关功能,或未正确配置固件镜像路径,GPU 可能无法完成基本的初始化过程,从而导致设备不可见。 5. **操作系统与驱动兼容性问题** - 即使设备已成功直通至虚拟机,若操作系统中未安装合适的驱动程序,也无法识别 GPU。例如,在 Ubuntu 中尝试使用 NVIDIA 显卡时,由于默认内核模块冲突或驱动版本不兼容,可能出现“nvidia-smi 找不到设备”的情况。 - 此类问题在使用 EXSI + Ubuntu 组合时尤为常见,部分用户转而采用 Debian 以获得更好的兼容性[^3]。 6. **虚拟机配置文件缺失关键参数** - 在 KVM/QEMU 环境中,若虚拟机 XML 配置文件中未正确添加 GPU 设备信息,或地址总线号不匹配,也可能导致设备无法识别。需确保 `<hostdev>` 标签中包含正确的 PCI 地址信息: ```xml <hostdev mode='subsystem' type='pci' managed='yes'> <source> <address domain='0x0000' bus='0x01' slot='0x00' function='0x0'/> </source> </hostdev> ``` ###
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值