Skip to content

Commit

Permalink
drm/vmwgfx: Implement virtual kms
Browse files Browse the repository at this point in the history
By default vmwgfx doesn't support vblanking or crc generation which
makes it impossible to use various IGT tests to validate vmwgfx.
Implement virtual kernel mode setting, which is mainly related to
simulated vblank support.

Code is very similar to amd's vkms and the vkms module itself, except
that it's integrated with vmwgfx three different output technologies -
legacy, screen object and screen targets.

Make IGT's kms_vblank pass on vmwgfx and allows a lot of other IGT
tests to run with vmwgfx.

Support for vkms needs to be manually enabled by adding:
guestinfo.vmwgfx.vkms_enable = "TRUE"
somewhere in the vmx file, otherwise it's off by default.

Signed-off-by: Zack Rusin <zack.rusin@broadcom.com>
Acked-by: Martin Krastev <martin.krastev@broadcom.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20240412025511.78553-2-zack.rusin@broadcom.com
  • Loading branch information
zackr committed Apr 15, 2024
1 parent bfc7bc5 commit cd2eb57
Show file tree
Hide file tree
Showing 10 changed files with 302 additions and 64 deletions.
2 changes: 1 addition & 1 deletion drivers/gpu/drm/vmwgfx/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,6 @@ vmwgfx-y := vmwgfx_execbuf.o vmwgfx_gmr.o vmwgfx_kms.o vmwgfx_drv.o \
vmwgfx_simple_resource.o vmwgfx_va.o vmwgfx_blit.o \
vmwgfx_validation.o vmwgfx_page_dirty.o vmwgfx_streamoutput.o \
vmwgfx_devcaps.o ttm_object.o vmwgfx_system_manager.o \
vmwgfx_gem.o
vmwgfx_gem.o vmwgfx_vkms.o

obj-$(CONFIG_DRM_VMWGFX) := vmwgfx.o
3 changes: 3 additions & 0 deletions drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
#include "vmwgfx_binding.h"
#include "vmwgfx_devcaps.h"
#include "vmwgfx_mksstat.h"
#include "vmwgfx_vkms.h"
#include "ttm_object.h"

#include <drm/drm_aperture.h>
Expand Down Expand Up @@ -910,6 +911,8 @@ static int vmw_driver_load(struct vmw_private *dev_priv, u32 pci_id)
"Please switch to a supported graphics device to avoid problems.");
}

vmw_vkms_init(dev_priv);

ret = vmw_dma_select_mode(dev_priv);
if (unlikely(ret != 0)) {
drm_info(&dev_priv->drm,
Expand Down
2 changes: 2 additions & 0 deletions drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
Original file line number Diff line number Diff line change
Expand Up @@ -615,6 +615,8 @@ struct vmw_private {

uint32 *devcaps;

bool vkms_enabled;

/*
* mksGuestStat instance-descriptor and pid arrays
*/
Expand Down
15 changes: 8 additions & 7 deletions drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#include "vmwgfx_kms.h"

#include "vmwgfx_bo.h"
#include "vmwgfx_vkms.h"
#include "vmw_surface_cache.h"

#include <drm/drm_atomic.h>
Expand All @@ -37,9 +38,16 @@
#include <drm/drm_sysfs.h>
#include <drm/drm_edid.h>

void vmw_du_init(struct vmw_display_unit *du)
{
hrtimer_init(&du->vkms.timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
du->vkms.timer.function = &vmw_vkms_vblank_simulate;
}

void vmw_du_cleanup(struct vmw_display_unit *du)
{
struct vmw_private *dev_priv = vmw_priv(du->primary.dev);
hrtimer_cancel(&du->vkms.timer);
drm_plane_cleanup(&du->primary);
if (vmw_cmd_supported(dev_priv))
drm_plane_cleanup(&du->cursor.base);
Expand Down Expand Up @@ -957,13 +965,6 @@ void vmw_du_crtc_atomic_begin(struct drm_crtc *crtc,
{
}


void vmw_du_crtc_atomic_flush(struct drm_crtc *crtc,
struct drm_atomic_state *state)
{
}


/**
* vmw_du_crtc_duplicate_state - duplicate crtc state
* @crtc: DRM crtc
Expand Down
9 changes: 7 additions & 2 deletions drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
Original file line number Diff line number Diff line change
Expand Up @@ -376,6 +376,12 @@ struct vmw_display_unit {
bool is_implicit;
int set_gui_x;
int set_gui_y;

struct {
struct hrtimer timer;
ktime_t period_ns;
struct drm_pending_vblank_event *event;
} vkms;
};

#define vmw_crtc_to_du(x) \
Expand All @@ -387,6 +393,7 @@ struct vmw_display_unit {
/*
* Shared display unit functions - vmwgfx_kms.c
*/
void vmw_du_init(struct vmw_display_unit *du);
void vmw_du_cleanup(struct vmw_display_unit *du);
void vmw_du_crtc_save(struct drm_crtc *crtc);
void vmw_du_crtc_restore(struct drm_crtc *crtc);
Expand Down Expand Up @@ -473,8 +480,6 @@ int vmw_du_crtc_atomic_check(struct drm_crtc *crtc,
struct drm_atomic_state *state);
void vmw_du_crtc_atomic_begin(struct drm_crtc *crtc,
struct drm_atomic_state *state);
void vmw_du_crtc_atomic_flush(struct drm_crtc *crtc,
struct drm_atomic_state *state);
void vmw_du_crtc_reset(struct drm_crtc *crtc);
struct drm_crtc_state *vmw_du_crtc_duplicate_state(struct drm_crtc *crtc);
void vmw_du_crtc_destroy_state(struct drm_crtc *crtc,
Expand Down
39 changes: 9 additions & 30 deletions drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@

#include "vmwgfx_bo.h"
#include "vmwgfx_kms.h"
#include "vmwgfx_vkms.h"

#include <drm/drm_atomic.h>
#include <drm/drm_atomic_helper.h>
Expand Down Expand Up @@ -241,33 +242,6 @@ static void vmw_ldu_crtc_mode_set_nofb(struct drm_crtc *crtc)
{
}

/**
* vmw_ldu_crtc_atomic_enable - Noop
*
* @crtc: CRTC associated with the new screen
* @state: Unused
*
* This is called after a mode set has been completed. Here's
* usually a good place to call vmw_ldu_add_active/vmw_ldu_del_active
* but since for LDU the display plane is closely tied to the
* CRTC, it makes more sense to do those at plane update time.
*/
static void vmw_ldu_crtc_atomic_enable(struct drm_crtc *crtc,
struct drm_atomic_state *state)
{
}

/**
* vmw_ldu_crtc_atomic_disable - Turns off CRTC
*
* @crtc: CRTC to be turned off
* @state: Unused
*/
static void vmw_ldu_crtc_atomic_disable(struct drm_crtc *crtc,
struct drm_atomic_state *state)
{
}

static const struct drm_crtc_funcs vmw_legacy_crtc_funcs = {
.gamma_set = vmw_du_crtc_gamma_set,
.destroy = vmw_ldu_crtc_destroy,
Expand All @@ -276,6 +250,9 @@ static const struct drm_crtc_funcs vmw_legacy_crtc_funcs = {
.atomic_destroy_state = vmw_du_crtc_destroy_state,
.set_config = drm_atomic_helper_set_config,
.page_flip = drm_atomic_helper_page_flip,
.enable_vblank = vmw_vkms_enable_vblank,
.disable_vblank = vmw_vkms_disable_vblank,
.get_vblank_timestamp = vmw_vkms_get_vblank_timestamp,
};


Expand Down Expand Up @@ -418,9 +395,9 @@ static const struct drm_crtc_helper_funcs vmw_ldu_crtc_helper_funcs = {
.mode_set_nofb = vmw_ldu_crtc_mode_set_nofb,
.atomic_check = vmw_du_crtc_atomic_check,
.atomic_begin = vmw_du_crtc_atomic_begin,
.atomic_flush = vmw_du_crtc_atomic_flush,
.atomic_enable = vmw_ldu_crtc_atomic_enable,
.atomic_disable = vmw_ldu_crtc_atomic_disable,
.atomic_flush = vmw_vkms_crtc_atomic_flush,
.atomic_enable = vmw_vkms_crtc_atomic_enable,
.atomic_disable = vmw_vkms_crtc_atomic_disable,
};


Expand Down Expand Up @@ -541,6 +518,8 @@ static int vmw_ldu_init(struct vmw_private *dev_priv, unsigned unit)
dev_priv->implicit_placement_property,
1);

vmw_du_init(&ldu->base);

return 0;

err_free_unregister:
Expand Down
28 changes: 13 additions & 15 deletions drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,13 @@

#include "vmwgfx_bo.h"
#include "vmwgfx_kms.h"
#include "vmwgfx_vkms.h"

#include <drm/drm_atomic.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_damage_helper.h>
#include <drm/drm_fourcc.h>
#include <drm/drm_vblank.h>

#define vmw_crtc_to_sou(x) \
container_of(x, struct vmw_screen_object_unit, base.crtc)
Expand Down Expand Up @@ -267,19 +269,6 @@ static void vmw_sou_crtc_helper_prepare(struct drm_crtc *crtc)
{
}

/**
* vmw_sou_crtc_atomic_enable - Noop
*
* @crtc: CRTC associated with the new screen
* @state: Unused
*
* This is called after a mode set has been completed.
*/
static void vmw_sou_crtc_atomic_enable(struct drm_crtc *crtc,
struct drm_atomic_state *state)
{
}

/**
* vmw_sou_crtc_atomic_disable - Turns off CRTC
*
Expand All @@ -302,6 +291,9 @@ static void vmw_sou_crtc_atomic_disable(struct drm_crtc *crtc,
sou = vmw_crtc_to_sou(crtc);
dev_priv = vmw_priv(crtc->dev);

if (dev_priv->vkms_enabled)
drm_crtc_vblank_off(crtc);

if (sou->defined) {
ret = vmw_sou_fifo_destroy(dev_priv, sou);
if (ret)
Expand All @@ -317,6 +309,9 @@ static const struct drm_crtc_funcs vmw_screen_object_crtc_funcs = {
.atomic_destroy_state = vmw_du_crtc_destroy_state,
.set_config = drm_atomic_helper_set_config,
.page_flip = drm_atomic_helper_page_flip,
.enable_vblank = vmw_vkms_enable_vblank,
.disable_vblank = vmw_vkms_disable_vblank,
.get_vblank_timestamp = vmw_vkms_get_vblank_timestamp,
};

/*
Expand Down Expand Up @@ -794,8 +789,8 @@ static const struct drm_crtc_helper_funcs vmw_sou_crtc_helper_funcs = {
.mode_set_nofb = vmw_sou_crtc_mode_set_nofb,
.atomic_check = vmw_du_crtc_atomic_check,
.atomic_begin = vmw_du_crtc_atomic_begin,
.atomic_flush = vmw_du_crtc_atomic_flush,
.atomic_enable = vmw_sou_crtc_atomic_enable,
.atomic_flush = vmw_vkms_crtc_atomic_flush,
.atomic_enable = vmw_vkms_crtc_atomic_enable,
.atomic_disable = vmw_sou_crtc_atomic_disable,
};

Expand Down Expand Up @@ -905,6 +900,9 @@ static int vmw_sou_init(struct vmw_private *dev_priv, unsigned unit)
dev->mode_config.suggested_x_property, 0);
drm_object_attach_property(&connector->base,
dev->mode_config.suggested_y_property, 0);

vmw_du_init(&sou->base);

return 0;

err_free_unregister:
Expand Down
22 changes: 13 additions & 9 deletions drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,14 @@

#include "vmwgfx_bo.h"
#include "vmwgfx_kms.h"
#include "vmwgfx_vkms.h"
#include "vmw_surface_cache.h"

#include <drm/drm_atomic.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_damage_helper.h>
#include <drm/drm_fourcc.h>
#include <drm/drm_vblank.h>

#define vmw_crtc_to_stdu(x) \
container_of(x, struct vmw_screen_target_display_unit, base.crtc)
Expand Down Expand Up @@ -412,19 +414,13 @@ static void vmw_stdu_crtc_helper_prepare(struct drm_crtc *crtc)
{
}

static void vmw_stdu_crtc_atomic_enable(struct drm_crtc *crtc,
struct drm_atomic_state *state)
{
}

static void vmw_stdu_crtc_atomic_disable(struct drm_crtc *crtc,
struct drm_atomic_state *state)
{
struct vmw_private *dev_priv;
struct vmw_screen_target_display_unit *stdu;
int ret;


if (!crtc) {
DRM_ERROR("CRTC is NULL\n");
return;
Expand All @@ -433,6 +429,9 @@ static void vmw_stdu_crtc_atomic_disable(struct drm_crtc *crtc,
stdu = vmw_crtc_to_stdu(crtc);
dev_priv = vmw_priv(crtc->dev);

if (dev_priv->vkms_enabled)
drm_crtc_vblank_off(crtc);

if (stdu->defined) {
ret = vmw_stdu_bind_st(dev_priv, stdu, NULL);
if (ret)
Expand Down Expand Up @@ -770,7 +769,6 @@ int vmw_kms_stdu_surface_dirty(struct vmw_private *dev_priv,
return ret;
}


/*
* Screen Target CRTC dispatch table
*/
Expand All @@ -782,6 +780,9 @@ static const struct drm_crtc_funcs vmw_stdu_crtc_funcs = {
.atomic_destroy_state = vmw_du_crtc_destroy_state,
.set_config = drm_atomic_helper_set_config,
.page_flip = drm_atomic_helper_page_flip,
.enable_vblank = vmw_vkms_enable_vblank,
.disable_vblank = vmw_vkms_disable_vblank,
.get_vblank_timestamp = vmw_vkms_get_vblank_timestamp,
};


Expand Down Expand Up @@ -1457,8 +1458,8 @@ static const struct drm_crtc_helper_funcs vmw_stdu_crtc_helper_funcs = {
.mode_set_nofb = vmw_stdu_crtc_mode_set_nofb,
.atomic_check = vmw_du_crtc_atomic_check,
.atomic_begin = vmw_du_crtc_atomic_begin,
.atomic_flush = vmw_du_crtc_atomic_flush,
.atomic_enable = vmw_stdu_crtc_atomic_enable,
.atomic_flush = vmw_vkms_crtc_atomic_flush,
.atomic_enable = vmw_vkms_crtc_atomic_enable,
.atomic_disable = vmw_stdu_crtc_atomic_disable,
};

Expand Down Expand Up @@ -1575,6 +1576,9 @@ static int vmw_stdu_init(struct vmw_private *dev_priv, unsigned unit)
dev->mode_config.suggested_x_property, 0);
drm_object_attach_property(&connector->base,
dev->mode_config.suggested_y_property, 0);

vmw_du_init(&stdu->base);

return 0;

err_free_unregister:
Expand Down
Loading

0 comments on commit cd2eb57

Please sign in to comment.