解决qemu虚拟机无法设置分辨率的问题

3 篇文章 0 订阅
2 篇文章 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)
  1. libdrm中的分辨率设置执行流程
Created with Raphaël 2.2.0 DRM_IOCTL(DRM_IOCTL_QXL_ALLOC_SURF) ioctl(DRM_IOCTL_QXL_ALLOC_SURF)
  1. 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中设置分辨率均正常。

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值