Details
-
Bug
-
Resolution: Unresolved
-
P2: Important
-
None
-
5.9.5
-
None
Description
The offset member of struct drm_mode_map_dumb is 64-bit. On a 32-bit system, depending how mmap is called, this offset may be truncated.
For certain drivers the offset always fits a 32-bit integer and mmap succeeds.
However, with qemu's 'virt' machine and virtio-gpu-pci display device, the offset returned by the kernel driver is larger than 2^32. Other drivers using 64-bit offsets include: amdgpu, bochs, cirrus, hisilicon, mgag200, nouveau, qxl, radeon.
In qtbase src/plugins/platforms/linuxfb/qlinuxfbdrmscreen.cpp, currently, QLinuxFbDevice::createFramebuffer calls mmap.
When _FILE_OFFSET_BITS is not defined to 64, the 32-bit version is called, truncating the offset, so mmap fails.
Console output (with a few printks added):
qt.qpa.fb: Got a dumb buffer for size 1024x768, handle 1, pitch 4096, size 3145728
[ 17.337086] drm_mode_addfb2 fb_id=0 width=1024 height=768 format=0x34325258 flags=0x0
[ 17.337418] 0: handle=1 pitch=4096 offset=0 modifier=875713112
[ 17.337636] 1: handle=0 pitch=0 offset=0 modifier=875713112
[ 17.337816] 2: handle=0 pitch=0 offset=0 modifier=875713112
[ 17.337995] 3: handle=0 pitch=0 offset=0 modifier=875713112
[ 17.338446] virtio_gpu_user_framebuffer_create handle=1
[ 17.338824] drm_mode_addfb2 fb_id=70
[ 17.347536] drm_mode_mmap_dumb_ioctl handle=1
[ 17.347788] virtio_gpu_mode_dumb_mmap handle=1
[ 17.347973] virtio_gpu_mode_dumb_mmap offset=100300000
[ 17.348171] drm_mode_mmap_dumb_ioctl offset=0x100300000
[ 17.350638] drm_vma_offset_lookup_locked 0x300 0x300
[ 17.350929] drm_vma_offset_lookup_locked node start=0x100000 size=0x300
[ 17.351216] [TTM] Could not find buffer object to map
Failed to mmap dumb buffer (Invalid argument)
strace output:
148 ioctl(4, DRM_IOCTL_MODE_CREATE_DUMB, 0x7ed5e9f8) = 0
148 write(2, "qt.qpa.fb: Got a dumb buffer for"..., 83) = 83
148 ioctl(4, DRM_IOCTL_MODE_ADDFB, 0x7ed5e99c) = 0
148 ioctl(4, DRM_IOCTL_MODE_MAP_DUMB, 0x7ed5e9d0) = 43
148 mmap2(NULL, 3145728, PROT_READ|PROT_WRITE, MAP_SHARED, 4, 0x300000) = -1 EINVAL (Invalid argument)
148 write(2, "Failed to mmap dumb buffer (Inva"..., 46) = 46
Replacing mmap with mmap64 seems to fix the issue.
Console output:
qt.qpa.fb: Got a dumb buffer for size 1024x768, handle 2, pitch 4096, size 3145728
[ 333.308230] drm_mode_addfb2 fb_id=0 width=1024 height=768 format=0x34325258 flags=0x0
[ 333.308798] 0: handle=2 pitch=4096 offset=0 modifier=875713112
[ 333.309032] 1: handle=0 pitch=0 offset=0 modifier=875713112
[ 333.309234] 2: handle=0 pitch=0 offset=0 modifier=875713112
[ 333.309419] 3: handle=0 pitch=0 offset=0 modifier=875713112
[ 333.309601] virtio_gpu_user_framebuffer_create handle=2
[ 333.309823] drm_mode_addfb2 fb_id=71
[ 333.311300] drm_mode_mmap_dumb_ioctl handle=2
[ 333.311517] virtio_gpu_mode_dumb_mmap handle=2
[ 333.311669] virtio_gpu_mode_dumb_mmap offset=100600000
[ 333.311836] drm_mode_mmap_dumb_ioctl offset=0x100600000
[ 333.313204] drm_vma_offset_lookup_locked 0x100600 0x300
[ 333.313422] drm_vma_offset_lookup_locked node start=0x100300 size=0x300
[ 333.313626] drm_vma_offset_lookup_locked node start=0x100600 size=0x300
qt.qpa.fb: FB is 71, mapped at 0x75953000
strace output:
156 ioctl(4, DRM_IOCTL_MODE_CREATE_DUMB, 0x7ec5a9f8) = 0
156 write(2, "qt.qpa.fb: Got a dumb buffer for"..., 83) = 83
156 ioctl(4, DRM_IOCTL_MODE_ADDFB, 0x7ec5a99c) = 0
156 ioctl(4, DRM_IOCTL_MODE_MAP_DUMB, 0x7ec5a9d0) = 43
156 mmap2(NULL, 3145728, PROT_READ|PROT_WRITE, MAP_SHARED, 4, 0x100300000) = 0x75c48000
156 write(2, "qt.qpa.fb: FB is 70, mapped at 0"..., 42) = 42