VirtualBox

Changeset 74172 in vbox for trunk/src/VBox/Additions


Ignore:
Timestamp:
Sep 10, 2018 8:17:28 AM (7 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
124944
Message:

Additions/drm: do not unpin an old frame buffer before the new one is in place.
bugref:9240: Additions/linux/vboxvideo: GPU memory management bug
We have seen sporadic cases of [unpin bad] messages in guest dmesg, and were
able to connect some of them to unpinning an old frame buffer when pinning a
new one before the new pin had succeeded. If the new frame buffer was too
big to be pinned in the available video memory the pin operation failed, but
the old frame buffer was already unpinned. As this did not get tracked in
the error path a subsequent unpin operation on it failed with the message
above.
This change fixes that by only unpinning the old frame buffer after the new
one has been successfully pinned. While this potentially increases memory
pressure further, it avoids the case where we unpin the old one, fail to pin
the new one and fail to re-pin the old one, as well as the case of the old one
getting re-pinned at a different address.
Thank you Hans de Goede for review and comments/suggestions.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Additions/linux/drm/vbox_mode.c

    r71947 r74172  
    242242}
    243243
    244 static int vbox_crtc_do_set_base(struct drm_crtc *crtc,
     244static int vbox_crtc_set_base(struct drm_crtc *crtc,
    245245                                 struct drm_framebuffer *old_fb, int x, int y)
    246246{
     
    253253        u64 gpu_addr;
    254254
    255         /* Unpin the previous fb. */
     255        vbox_fb = to_vbox_framebuffer(CRTC_FB(crtc));
     256        obj = vbox_fb->obj;
     257        bo = gem_to_vbox_bo(obj);
     258
     259        ret = vbox_bo_reserve(bo, false);
     260        if (ret)
     261                return ret;
     262
     263        ret = vbox_bo_pin(bo, TTM_PL_FLAG_VRAM, &gpu_addr);
     264        vbox_bo_unreserve(bo);
     265        if (ret)
     266                return ret;
     267
     268        /* Unpin the previous fb.  Do this after the new one has been pinned rather
     269         * than before and re-pinning it on failure in case that fails too. */
    256270        if (old_fb) {
    257271                vbox_fb = to_vbox_framebuffer(old_fb);
     
    259273                bo = gem_to_vbox_bo(obj);
    260274                ret = vbox_bo_reserve(bo, false);
    261                 if (ret)
    262                         return ret;
    263 
    264                 vbox_bo_unpin(bo);
    265                 vbox_bo_unreserve(bo);
    266         }
    267 
    268         vbox_fb = to_vbox_framebuffer(CRTC_FB(crtc));
    269         obj = vbox_fb->obj;
    270         bo = gem_to_vbox_bo(obj);
    271 
    272         ret = vbox_bo_reserve(bo, false);
    273         if (ret)
    274                 return ret;
    275 
    276         ret = vbox_bo_pin(bo, TTM_PL_FLAG_VRAM, &gpu_addr);
    277         vbox_bo_unreserve(bo);
    278         if (ret)
    279                 return ret;
     275                /* This should never fail, as no one else should be accessing it and we
     276                 * should be running under the modeset locks. */
     277                if (!ret) {
     278                        vbox_bo_unpin(bo);
     279                        vbox_bo_unreserve(bo);
     280                }
     281        }
    280282
    281283        vbox_crtc->fb_offset = gpu_addr;
     
    293295}
    294296
    295 static int vbox_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
    296                                    struct drm_framebuffer *old_fb)
    297 {
    298         return vbox_crtc_do_set_base(crtc, old_fb, x, y);
    299 }
    300 
    301297static int vbox_crtc_mode_set(struct drm_crtc *crtc,
    302298                              struct drm_display_mode *mode,
     
    305301{
    306302        struct vbox_private *vbox = crtc->dev->dev_private;
    307         int rc = 0;
    308 
    309         vbox_crtc_mode_set_base(crtc, x, y, old_fb);
    310 
     303        int rc = vbox_crtc_set_base(crtc, old_fb, x, y);
     304        if (rc)
     305                return rc;
    311306        mutex_lock(&vbox->hw_mutex);
    312307        rc = vbox_set_view(crtc);
     
    337332        .mode_fixup = vbox_crtc_mode_fixup,
    338333        .mode_set = vbox_crtc_mode_set,
    339         /* .mode_set_base = vbox_crtc_mode_set_base, */
    340334        .disable = vbox_crtc_disable,
    341335        .prepare = vbox_crtc_prepare,
Note: See TracChangeset for help on using the changeset viewer.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette