Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f2a0dcb1 authored by Thomas Hellstrom's avatar Thomas Hellstrom
Browse files

drm/vmwgfx: Implement 64-bit Otable- and MOB binding v2



Adds the relevant commands to the device interface header and
implements 64-bit binding for 64 bit VMs.

v2: Uppercase command IDs, Correctly use also 64 bit page tables.

Signed-off-by: default avatarThomas Hellstrom <thellstrom@vmware.com>
Reviewed-by: default avatarJakob Bornecrantz <jakob@vmware.com>
parent b360a3ce
Loading
Loading
Loading
Loading
+44 −10
Original line number Diff line number Diff line
@@ -35,6 +35,7 @@
#include "svga_reg.h"

typedef uint32 PPN;
typedef __le64 PPN64;

/*
 * 3D Hardware Version
@@ -1200,7 +1201,7 @@ typedef enum {
#define SVGA_3D_CMD_DESTROY_GB_SHADER        1113
#define SVGA_3D_CMD_BIND_GB_SHADER           1114

#define SVGA_3D_CMD_BIND_SHADERCONSTS        1115
#define SVGA_3D_CMD_SET_OTABLE_BASE64        1115

#define SVGA_3D_CMD_BEGIN_GB_QUERY           1116
#define SVGA_3D_CMD_END_GB_QUERY             1117
@@ -1223,7 +1224,10 @@ typedef enum {

#define SVGA_3D_CMD_SET_GB_SHADERCONSTS_INLINE  1130

#define SVGA_3D_CMD_MAX                      1131
#define SVGA_3D_CMD_DEFINE_GB_MOB64          1135
#define SVGA_3D_CMD_REDEFINE_GB_MOB64        1136

#define SVGA_3D_CMD_MAX                      1142
#define SVGA_3D_CMD_FUTURE_MAX               3000

/*
@@ -1927,6 +1931,9 @@ typedef enum SVGAMobFormat {
   SVGA3D_MOBFMT_PTDEPTH_1 = 1,
   SVGA3D_MOBFMT_PTDEPTH_2 = 2,
   SVGA3D_MOBFMT_RANGE     = 3,
   SVGA3D_MOBFMT_PTDEPTH64_0 = 4,
   SVGA3D_MOBFMT_PTDEPTH64_1 = 5,
   SVGA3D_MOBFMT_PTDEPTH64_2 = 6,
   SVGA3D_MOBFMT_MAX,
} SVGAMobFormat;

@@ -1968,6 +1975,15 @@ struct {
   SVGAMobFormat ptDepth;
} SVGA3dCmdSetOTableBase;  /* SVGA_3D_CMD_SET_OTABLE_BASE */

typedef
struct {
   SVGAOTableType type;
   PPN64 baseAddress;
   uint32 sizeInBytes;
   uint32 validSizeInBytes;
   SVGAMobFormat ptDepth;
} SVGA3dCmdSetOTableBase64;  /* SVGA_3D_CMD_SET_OTABLE_BASE64 */

typedef
struct {
   SVGAOTableType type;
@@ -2007,6 +2023,32 @@ struct SVGA3dCmdRedefineGBMob {
   uint32 sizeInBytes;
} SVGA3dCmdRedefineGBMob;   /* SVGA_3D_CMD_REDEFINE_GB_MOB */

/*
 * Define a memory object (Mob) in the OTable with a PPN64 base.
 */

typedef
struct SVGA3dCmdDefineGBMob64 {
   SVGAMobId mobid;
   SVGAMobFormat ptDepth;
   PPN64 base;
   uint32 sizeInBytes;
}
SVGA3dCmdDefineGBMob64;   /* SVGA_3D_CMD_DEFINE_GB_MOB64 */

/*
 * Redefine an object in the OTable with PPN64 base.
 */

typedef
struct SVGA3dCmdRedefineGBMob64 {
   SVGAMobId mobid;
   SVGAMobFormat ptDepth;
   PPN64 base;
   uint32 sizeInBytes;
}
SVGA3dCmdRedefineGBMob64;   /* SVGA_3D_CMD_REDEFINE_GB_MOB64 */

/*
 * Notification that the page tables have been modified.
 */
@@ -2243,14 +2285,6 @@ typedef struct SVGA3dCmdDestroyGBShader {
   uint32 shid;
} SVGA3dCmdDestroyGBShader;   /* SVGA_3D_CMD_DESTROY_GB_SHADER */


typedef struct SVGA3dCmdBindGBShaderConsts {
   uint32 cid;
   SVGA3dShaderType shaderType;
   SVGA3dShaderConstType shaderConstType;
   uint32 sid;
} SVGA3dCmdBindGBShaderConsts;   /* SVGA_3D_CMD_BIND_SHADERCONSTS */

typedef
struct {
   uint32                  cid;
+1 −1
Original line number Diff line number Diff line
@@ -1730,7 +1730,7 @@ static const struct vmw_cmd_entry const vmw_cmd_entries[SVGA_3D_CMD_MAX] = {
		    true, false, true),
	VMW_CMD_DEF(SVGA_3D_CMD_DESTROY_GB_SHADER, &vmw_cmd_invalid,
		    false, false, true),
	VMW_CMD_DEF(SVGA_3D_CMD_BIND_SHADERCONSTS, &vmw_cmd_invalid,
	VMW_CMD_DEF(SVGA_3D_CMD_SET_OTABLE_BASE64, &vmw_cmd_invalid,
		    false, false, false),
	VMW_CMD_DEF(SVGA_3D_CMD_BEGIN_GB_QUERY, &vmw_cmd_begin_gb_query,
		    true, false, true),
+56 −14
Original line number Diff line number Diff line
@@ -33,13 +33,25 @@

#define VMW_OTABLE_SETUP_SUB ((VMWGFX_ENABLE_SCREEN_TARGET_OTABLE) ? 0 : 1)

/*
 * Currently the MOB interface does not support 64-bit page frame numbers.
 * This might change in the future to be similar to the GMR2 interface
 * when virtual machines support memory beyond 16TB.
 */

#ifdef CONFIG_64BIT
#define VMW_PPN_SIZE 8
#define vmw_cmd_set_otable_base SVGA3dCmdSetOTableBase64
#define VMW_ID_SET_OTABLE_BASE SVGA_3D_CMD_SET_OTABLE_BASE64
#define vmw_cmd_define_gb_mob SVGA3dCmdDefineGBMob64
#define VMW_ID_DEFINE_GB_MOB SVGA_3D_CMD_DEFINE_GB_MOB64
#define VMW_MOBFMT_PTDEPTH_0 SVGA3D_MOBFMT_PTDEPTH64_0
#define VMW_MOBFMT_PTDEPTH_1 SVGA3D_MOBFMT_PTDEPTH64_1
#define VMW_MOBFMT_PTDEPTH_2 SVGA3D_MOBFMT_PTDEPTH64_2
#else
#define VMW_PPN_SIZE 4
#define vmw_cmd_set_otable_base SVGA3dCmdSetOTableBase
#define VMW_ID_SET_OTABLE_BASE SVGA_3D_CMD_SET_OTABLE_BASE
#define vmw_cmd_define_gb_mob SVGA3dCmdDefineGBMob
#define VMW_ID_DEFINE_GB_MOB SVGA_3D_CMD_DEFINE_GB_MOB
#define VMW_MOBFMT_PTDEPTH_0 SVGA3D_MOBFMT_PTDEPTH_0
#define VMW_MOBFMT_PTDEPTH_1 SVGA3D_MOBFMT_PTDEPTH_1
#define VMW_MOBFMT_PTDEPTH_2 SVGA3D_MOBFMT_PTDEPTH_2
#endif

/*
 * struct vmw_mob - Structure containing page table and metadata for a
@@ -93,7 +105,7 @@ static int vmw_setup_otable_base(struct vmw_private *dev_priv,
{
	struct {
		SVGA3dCmdHeader header;
		SVGA3dCmdSetOTableBase body;
		vmw_cmd_set_otable_base body;
	} *cmd;
	struct vmw_mob *mob;
	const struct vmw_sg_table *vsgt;
@@ -113,7 +125,7 @@ static int vmw_setup_otable_base(struct vmw_private *dev_priv,
	}

	if (otable->size <= PAGE_SIZE) {
		mob->pt_level = SVGA3D_MOBFMT_PTDEPTH_0;
		mob->pt_level = VMW_MOBFMT_PTDEPTH_0;
		mob->pt_root_page = vmw_piter_dma_addr(&iter);
	} else if (vsgt->num_regions == 1) {
		mob->pt_level = SVGA3D_MOBFMT_RANGE;
@@ -124,6 +136,7 @@ static int vmw_setup_otable_base(struct vmw_private *dev_priv,
			goto out_no_populate;

		vmw_mob_pt_setup(mob, iter, otable->size >> PAGE_SHIFT);
		mob->pt_level += VMW_MOBFMT_PTDEPTH_1 - SVGA3D_MOBFMT_PTDEPTH_1;
	}

	cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd));
@@ -133,7 +146,7 @@ static int vmw_setup_otable_base(struct vmw_private *dev_priv,
	}

	memset(cmd, 0, sizeof(*cmd));
	cmd->header.id = SVGA_3D_CMD_SET_OTABLE_BASE;
	cmd->header.id = VMW_ID_SET_OTABLE_BASE;
	cmd->header.size = sizeof(cmd->body);
	cmd->body.type = type;
	cmd->body.baseAddress = mob->pt_root_page >> PAGE_SHIFT;
@@ -141,6 +154,13 @@ static int vmw_setup_otable_base(struct vmw_private *dev_priv,
	cmd->body.validSizeInBytes = 0;
	cmd->body.ptDepth = mob->pt_level;

	/*
	 * The device doesn't support this, But the otable size is
	 * determined at compile-time, so this BUG shouldn't trigger
	 * randomly.
	 */
	BUG_ON(mob->pt_level == VMW_MOBFMT_PTDEPTH_2);

	vmw_fifo_commit(dev_priv, sizeof(*cmd));
	otable->page_table = mob;

@@ -403,6 +423,27 @@ out_unreserve:
	return ret;
}

/**
 * vmw_mob_assign_ppn - Assign a value to a page table entry
 *
 * @addr: Pointer to pointer to page table entry.
 * @val: The page table entry
 *
 * Assigns a value to a page table entry pointed to by *@addr and increments
 * *@addr according to the page table entry size.
 */
#if (VMW_PPN_SIZE == 8)
static void vmw_mob_assign_ppn(uint32_t **addr, dma_addr_t val)
{
	*((uint64_t *) *addr) = val >> PAGE_SHIFT;
	*addr += 2;
}
#else
static void vmw_mob_assign_ppn(uint32_t **addr, dma_addr_t val)
{
	*(*addr)++ = val >> PAGE_SHIFT;
}
#endif

/*
 * vmw_mob_build_pt - Build a pagetable
@@ -432,8 +473,8 @@ static unsigned long vmw_mob_build_pt(struct vmw_piter *data_iter,
		save_addr = addr = kmap_atomic(page);

		for (i = 0; i < PAGE_SIZE / VMW_PPN_SIZE; ++i) {
			u32 tmp = vmw_piter_dma_addr(data_iter) >> PAGE_SHIFT;
			*addr++ = tmp;
			vmw_mob_assign_ppn(&addr,
					   vmw_piter_dma_addr(data_iter));
			if (unlikely(--num_data_pages == 0))
				break;
			WARN_ON(!vmw_piter_next(data_iter));
@@ -565,7 +606,7 @@ int vmw_mob_bind(struct vmw_private *dev_priv,
	struct vmw_piter data_iter;
	struct {
		SVGA3dCmdHeader header;
		SVGA3dCmdDefineGBMob body;
		vmw_cmd_define_gb_mob body;
	} *cmd;

	mob->id = mob_id;
@@ -574,7 +615,7 @@ int vmw_mob_bind(struct vmw_private *dev_priv,
		return 0;

	if (likely(num_data_pages == 1)) {
		mob->pt_level = SVGA3D_MOBFMT_PTDEPTH_0;
		mob->pt_level = VMW_MOBFMT_PTDEPTH_0;
		mob->pt_root_page = vmw_piter_dma_addr(&data_iter);
	} else if (vsgt->num_regions == 1) {
		mob->pt_level = SVGA3D_MOBFMT_RANGE;
@@ -586,6 +627,7 @@ int vmw_mob_bind(struct vmw_private *dev_priv,

		vmw_mob_pt_setup(mob, data_iter, num_data_pages);
		pt_set_up = true;
		mob->pt_level += VMW_MOBFMT_PTDEPTH_1 - SVGA3D_MOBFMT_PTDEPTH_1;
	}

	(void) vmw_3d_resource_inc(dev_priv, false);
@@ -597,7 +639,7 @@ int vmw_mob_bind(struct vmw_private *dev_priv,
		goto out_no_cmd_space;
	}

	cmd->header.id = SVGA_3D_CMD_DEFINE_GB_MOB;
	cmd->header.id = VMW_ID_DEFINE_GB_MOB;
	cmd->header.size = sizeof(cmd->body);
	cmd->body.mobid = mob_id;
	cmd->body.ptDepth = mob->pt_level;