版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。
版权
虚拟化同时被 3 个专栏收录
7 篇文章1 订阅
订阅专栏
2 篇文章0 订阅
订阅专栏
3 篇文章0 订阅
订阅专栏
问题描述:
在虚拟机中进行修改分辨率测试,结果如下:
在win7中测试设置ok。
在Centos7、Ubuntu16.04、Ubuntu18.04中测试均不行。
系统中设置分辨率也只有win7有效,其余均无效,怀疑是QXL驱动问题。
问题排查分析如下:
查看日志中出现如下报错
Jul 2 15:22:28 Ubuntu1604 kernel: [ 6288.266180] qxl 0000:00:02.0: object_init failed for (4104192, 0x00000002)
Jul 2 15:22:28 Ubuntu1604 kernel: [ 6288.266190] [drm:qxl_gem_object_create [qxl]] ERROR Failed to allocate GEM object (4101120, 2, 4096, -12)
Jul 2 15:22:28 Ubuntu1604 kernel: [ 6288.266194] [drm:qxl_alloc_surf_ioctl [qxl]] ERROR qxl_alloc_surf_ioctl: failed to create gem ret=-12
首先对Linux中分辨率设置执行流程进行分析:
1)xorg自动识别pci显卡并使用相应驱动
xorg-server首先会获取到该pci设备的vendor_id,之后对其进行判断,当其值为0x1b36时判断为qxl
显卡设备,并在/usr/lib/xorg/modules/driver中寻找该设备的应用层驱动,qxl应用层驱动名为qxl_drv.so。
2)xorg中的分辨率设置执行流程
Created with Raphaël 2.2.0 设置分辨率 drmmode_xf86crtc_resize(所有库均具有相同入口)
3)xf86-qxl中的分辨率设置执行流程
Created with Raphaël 2.2.0 drmmode_xf86crtc_resize create_primary qxl_bo_create_primary drmIoctl(DRM_IOCTL_QXL_ALLOC_SURF)
libdrm中的分辨率设置执行流程
Created with Raphaël 2.2.0 DRM_IOCTL(DRM_IOCTL_QXL_ALLOC_SURF) ioctl(DRM_IOCTL_QXL_ALLOC_SURF)
kernel中的分辨率设置执行流程
Created with Raphaël 2.2.0 qxl_alloc_surf_ioctl qxl_gem_object_create_with_handle qxl_gem_object_create qxl_bo_create ttm_bo_init
主要出错点在ttm_bo_init中的drm_vma_offset_add,而分配size由drmmode_xf86crtc_resize决定并传入,分配该内存主要用于应用层和内核共享的famebuffer的内存区域,用于xorg存储图像,内核读取。
计算公式如下:
size = (width * cpp + 1) * height
其中cpp = (scrn->bitsPerPixel + 7) / 8
其中bpp一般为32,由于分配该存储空间之时前一段存储空间尚未销毁,实际大小粗略计算为
1920 × 4 × 1080 = 8M
即应为该framebuffer在内核中分配大约8M的共享空间。
而实际能分配内存的上限来自于初始化函数ttm_bo_init_mm中对显存的设置,分配见下调用函数:
ttm_bo_init_mm(&qdev->mman.bdev, TTM_PL_VRAM, num_io_pages);
其中初始化最大值取决于num_io_pages,该值通过如下计算可得出vram_size:
vram_size = num_io_pages * PAGE_SIZE / (1024 * 1024)
值vram_size来源于qemu-system-x86_64执行中使用的的参数vram_size=8388608,该参数由ovirt固定在程序中。
在客户机中运行:
$ lspci -v -s 00:02.0 00:02.0 VGA compatible controller: Red Hat, Inc. QXL paravirtual graphic card (rev 04) (prog-if 00 [VGA controller]) Subsystem: Red Hat, Inc QEMU Virtual Machine Flags: fast devsel, IRQ 10 Memory at f8000000 (32-bit, non-prefetchable) [size=64M] Memory at fc000000 (32-bit, non-prefetchable) [size=8M] Memory at fc850000 (32-bit, non-prefetchable) [size=8K] I/O ports at c040 [size=32] Expansion ROM at fc840000 [disabled] [size=64K] Kernel driver in use: qxl Kernel modules: qxl
可以看到该fc000000中的vram_size是8M,而根据前面计算的new_framebuffer + old_framebuffer的大小
8M + n > vram_size,所以导致了分辨率设置失败,因为分配framebuffer失败。
通过如下命令更新数据库中:
update vmDevice SET vmDevice="{“specParams”:{“vgamem”:“65536”,“heads”:“1”,“vram”:“65536”,“ram”:“65536”},“type”:“video”,“device”:“qxl”,“deviceId”:“026af321-efc4-4859-9c13-5fcffd3f9c06”}" where vmDevice="{“specParams”:{“vgamem”:“16384”,“heads”:“1”,“vram”:“8192”,“ram”:“65536”},“type”:“video”,“device”:“qxl”,“deviceId”:“026af321-efc4-4859-9c13-5fcffd3f9c06”}";
关闭、重新启动虚拟机,执行如下:
$ lspci -v -s 00:02.0 00:02.0 VGA compatible controller: Red Hat, Inc. QXL paravirtual graphic card (rev 04) (prog-if 00 [VGA controller]) Subsystem: Red Hat, Inc QEMU Virtual Machine Flags: fast devsel, IRQ 10 Memory at f0000000 (32-bit, non-prefetchable) [size=128M] Memory at f8000000 (32-bit, non-prefetchable) [size=64M] Memory at fc050000 (32-bit, non-prefetchable) [size=8K] I/O ports at c040 [size=32] Expansion ROM at fc040000 [disabled] [size=64K] Kernel driver in use: qxl Kernel modules: qxl
测试结果:
vram_size大小增大到64M,实测在ubuntu16.04, ubuntu18.04, Centos7中设置分辨率均正常。