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

Commit 12d14cc4 authored by Zhi Wang's avatar Zhi Wang Committed by Zhenyu Wang
Browse files

drm/i915/gvt: Introduce a framework for tracking HW registers.



This patch introduces a framework for tracking HW registers on different
GEN platforms.

Accesses to GEN HW registers from VMs will be trapped by hypervisor. It
will forward these emulation requests to GVT-g device model, which
requires this framework to search for related register descriptions.

Each MMIO entry in this framework describes a GEN HW registers, e.g.
offset, length, whether it contains RO bits, whether it can be accessed by
LRIs...and also emulation handlers for emulating register reading and
writing.

- Use i915 MMIO register definition & statement.(Joonas)

Signed-off-by: default avatarZhi Wang <zhi.a.wang@intel.com>
Signed-off-by: default avatarZhenyu Wang <zhenyuw@linux.intel.com>
parent 28a60dee
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
GVT_DIR := gvt
GVT_SOURCE := gvt.o aperture_gm.o
GVT_SOURCE := gvt.o aperture_gm.o handlers.o

ccflags-y                      += -I$(src) -I$(src)/$(GVT_DIR) -Wall
i915-y			       += $(addprefix $(GVT_DIR)/, $(GVT_SOURCE))
+23 −7
Original line number Diff line number Diff line
@@ -19,6 +19,15 @@
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 *
 * Authors:
 *    Kevin Tian <kevin.tian@intel.com>
 *    Eddie Dong <eddie.dong@intel.com>
 *
 * Contributors:
 *    Niu Bing <bing.niu@intel.com>
 *    Zhi Wang <zhi.a.wang@intel.com>
 *
 */

#include <linux/types.h>
@@ -84,9 +93,12 @@ int intel_gvt_init_host(void)

static void init_device_info(struct intel_gvt *gvt)
{
	if (IS_BROADWELL(gvt->dev_priv) || IS_SKYLAKE(gvt->dev_priv))
		gvt->device_info.max_support_vgpus = 8;
	/* This function will grow large in GVT device model patches. */
	struct intel_gvt_device_info *info = &gvt->device_info;

	if (IS_BROADWELL(gvt->dev_priv) || IS_SKYLAKE(gvt->dev_priv)) {
		info->max_support_vgpus = 8;
		info->mmio_size = 2 * 1024 * 1024;
	}
}

/**
@@ -104,7 +116,7 @@ void intel_gvt_clean_device(struct drm_i915_private *dev_priv)
	if (WARN_ON(!gvt->initialized))
		return;

	/* Other de-initialization of GVT components will be introduced. */
	intel_gvt_clean_mmio_info(gvt);

	gvt->initialized = false;
}
@@ -123,6 +135,8 @@ void intel_gvt_clean_device(struct drm_i915_private *dev_priv)
int intel_gvt_init_device(struct drm_i915_private *dev_priv)
{
	struct intel_gvt *gvt = &dev_priv->gvt;
	int ret;

	/*
	 * Cannot initialize GVT device without intel_gvt_host gets
	 * initialized first.
@@ -139,9 +153,11 @@ int intel_gvt_init_device(struct drm_i915_private *dev_priv)
	gvt->dev_priv = dev_priv;

	init_device_info(gvt);
	/*
	 * Other initialization of GVT components will be introduce here.
	 */

	ret = intel_gvt_setup_mmio_info(gvt);
	if (ret)
		return ret;

	gvt_dbg_core("gvt device creation is done\n");
	gvt->initialized = true;
	return 0;
+19 −1
Original line number Diff line number Diff line
@@ -19,6 +19,15 @@
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 *
 * Authors:
 *    Kevin Tian <kevin.tian@intel.com>
 *    Eddie Dong <eddie.dong@intel.com>
 *
 * Contributors:
 *    Niu Bing <bing.niu@intel.com>
 *    Zhi Wang <zhi.a.wang@intel.com>
 *
 */

#ifndef _GVT_H_
@@ -26,6 +35,7 @@

#include "debug.h"
#include "hypercall.h"
#include "mmio.h"

#define GVT_MAX_VGPU 8

@@ -45,7 +55,7 @@ extern struct intel_gvt_host intel_gvt_host;
/* Describe per-platform limitations. */
struct intel_gvt_device_info {
	u32 max_support_vgpus;
	/* This data structure will grow bigger in GVT device model patches */
	u32 mmio_size;
};

/* GM resources owned by a vGPU */
@@ -83,6 +93,13 @@ struct intel_gvt_fence {
	unsigned long vgpu_allocated_fence_num;
};

#define INTEL_GVT_MMIO_HASH_BITS 9

struct intel_gvt_mmio {
	u32 *mmio_attribute;
	DECLARE_HASHTABLE(mmio_info_table, INTEL_GVT_MMIO_HASH_BITS);
};

struct intel_gvt {
	struct mutex lock;
	bool initialized;
@@ -93,6 +110,7 @@ struct intel_gvt {
	struct intel_gvt_device_info device_info;
	struct intel_gvt_gm gm;
	struct intel_gvt_fence fence;
	struct intel_gvt_mmio mmio;
};

/* Aperture/GM space definitions for GVT device */
+247 −0
Original line number Diff line number Diff line
/*
 * Copyright(c) 2011-2016 Intel Corporation. All rights reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice (including the next
 * paragraph) shall be included in all copies or substantial portions of the
 * Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 *
 * Authors:
 *    Kevin Tian <kevin.tian@intel.com>
 *    Eddie Dong <eddie.dong@intel.com>
 *    Zhiyuan Lv <zhiyuan.lv@intel.com>
 *
 * Contributors:
 *    Min He <min.he@intel.com>
 *    Tina Zhang <tina.zhang@intel.com>
 *    Pei Zhang <pei.zhang@intel.com>
 *    Niu Bing <bing.niu@intel.com>
 *    Ping Gao <ping.a.gao@intel.com>
 *    Zhi Wang <zhi.a.wang@intel.com>
 *

 */

#include "i915_drv.h"

/* Register contains RO bits */
#define F_RO		(1 << 0)
/* Register contains graphics address */
#define F_GMADR		(1 << 1)
/* Mode mask registers with high 16 bits as the mask bits */
#define F_MODE_MASK	(1 << 2)
/* This reg can be accessed by GPU commands */
#define F_CMD_ACCESS	(1 << 3)
/* This reg has been accessed by a VM */
#define F_ACCESSED	(1 << 4)
/* This reg has been accessed through GPU commands */
#define F_CMD_ACCESSED	(1 << 5)
/* This reg could be accessed by unaligned address */
#define F_UNALIGN	(1 << 6)

unsigned long intel_gvt_get_device_type(struct intel_gvt *gvt)
{
	if (IS_BROADWELL(gvt->dev_priv))
		return D_BDW;
	else if (IS_SKYLAKE(gvt->dev_priv))
		return D_SKL;

	return 0;
}

bool intel_gvt_match_device(struct intel_gvt *gvt,
		unsigned long device)
{
	return intel_gvt_get_device_type(gvt) & device;
}

static int new_mmio_info(struct intel_gvt *gvt,
		u32 offset, u32 flags, u32 size,
		u32 addr_mask, u32 ro_mask, u32 device,
		void *read, void *write)
{
	struct intel_gvt_mmio_info *info, *p;
	u32 start, end, i;

	if (!intel_gvt_match_device(gvt, device))
		return 0;

	if (WARN_ON(!IS_ALIGNED(offset, 4)))
		return -EINVAL;

	start = offset;
	end = offset + size;

	for (i = start; i < end; i += 4) {
		info = kzalloc(sizeof(*info), GFP_KERNEL);
		if (!info)
			return -ENOMEM;

		info->offset = i;
		p = intel_gvt_find_mmio_info(gvt, info->offset);
		if (p)
			gvt_err("dup mmio definition offset %x\n",
				info->offset);
		info->size = size;
		info->length = (i + 4) < end ? 4 : (end - i);
		info->addr_mask = addr_mask;
		info->device = device;
		info->read = read;
		info->write = write;
		gvt->mmio.mmio_attribute[info->offset / 4] = flags;
		INIT_HLIST_NODE(&info->node);
		hash_add(gvt->mmio.mmio_info_table, &info->node, info->offset);
	}
	return 0;
}

#define MMIO_F(reg, s, f, am, rm, d, r, w) do { \
	ret = new_mmio_info(gvt, INTEL_GVT_MMIO_OFFSET(reg), \
		f, s, am, rm, d, r, w); \
	if (ret) \
		return ret; \
} while (0)

#define MMIO_D(reg, d) \
	MMIO_F(reg, 4, 0, 0, 0, d, NULL, NULL)

#define MMIO_DH(reg, d, r, w) \
	MMIO_F(reg, 4, 0, 0, 0, d, r, w)

#define MMIO_DFH(reg, d, f, r, w) \
	MMIO_F(reg, 4, f, 0, 0, d, r, w)

#define MMIO_GM(reg, d, r, w) \
	MMIO_F(reg, 4, F_GMADR, 0xFFFFF000, 0, d, r, w)

#define MMIO_RO(reg, d, f, rm, r, w) \
	MMIO_F(reg, 4, F_RO | f, 0, rm, d, r, w)

#define MMIO_RING_F(prefix, s, f, am, rm, d, r, w) do { \
	MMIO_F(prefix(RENDER_RING_BASE), s, f, am, rm, d, r, w); \
	MMIO_F(prefix(BLT_RING_BASE), s, f, am, rm, d, r, w); \
	MMIO_F(prefix(GEN6_BSD_RING_BASE), s, f, am, rm, d, r, w); \
	MMIO_F(prefix(VEBOX_RING_BASE), s, f, am, rm, d, r, w); \
} while (0)

#define MMIO_RING_D(prefix, d) \
	MMIO_RING_F(prefix, 4, 0, 0, 0, d, NULL, NULL)

#define MMIO_RING_DFH(prefix, d, f, r, w) \
	MMIO_RING_F(prefix, 4, f, 0, 0, d, r, w)

#define MMIO_RING_GM(prefix, d, r, w) \
	MMIO_RING_F(prefix, 4, F_GMADR, 0xFFFF0000, 0, d, r, w)

#define MMIO_RING_RO(prefix, d, f, rm, r, w) \
	MMIO_RING_F(prefix, 4, F_RO | f, 0, rm, d, r, w)

static int init_generic_mmio_info(struct intel_gvt *gvt)
{
	int ret;

	MMIO_F(0, 0, 0, 0, 0, D_ALL, NULL, NULL);
	return 0;
}

static int init_broadwell_mmio_info(struct intel_gvt *gvt)
{
	int ret;

	MMIO_F(0, 0, 0, 0, 0, D_ALL, NULL, NULL);
	return 0;
}

/**
 * intel_gvt_find_mmio_info - find MMIO information entry by aligned offset
 * @gvt: GVT device
 * @offset: register offset
 *
 * This function is used to find the MMIO information entry from hash table
 *
 * Returns:
 * pointer to MMIO information entry, NULL if not exists
 */
struct intel_gvt_mmio_info *intel_gvt_find_mmio_info(struct intel_gvt *gvt,
	unsigned int offset)
{
	struct intel_gvt_mmio_info *e;

	WARN_ON(!IS_ALIGNED(offset, 4));

	hash_for_each_possible(gvt->mmio.mmio_info_table, e, node, offset) {
		if (e->offset == offset)
			return e;
	}
	return NULL;
}

/**
 * intel_gvt_clean_mmio_info - clean up MMIO information table for GVT device
 * @gvt: GVT device
 *
 * This function is called at the driver unloading stage, to clean up the MMIO
 * information table of GVT device
 *
 */
void intel_gvt_clean_mmio_info(struct intel_gvt *gvt)
{
	struct hlist_node *tmp;
	struct intel_gvt_mmio_info *e;
	int i;

	hash_for_each_safe(gvt->mmio.mmio_info_table, i, tmp, e, node)
		kfree(e);

	vfree(gvt->mmio.mmio_attribute);
	gvt->mmio.mmio_attribute = NULL;
}

/**
 * intel_gvt_setup_mmio_info - setup MMIO information table for GVT device
 * @gvt: GVT device
 *
 * This function is called at the initialization stage, to setup the MMIO
 * information table for GVT device
 *
 * Returns:
 * zero on success, negative if failed.
 */
int intel_gvt_setup_mmio_info(struct intel_gvt *gvt)
{
	struct intel_gvt_device_info *info = &gvt->device_info;
	struct drm_i915_private *dev_priv = gvt->dev_priv;
	int ret;

	gvt->mmio.mmio_attribute = vzalloc(info->mmio_size);
	if (!gvt->mmio.mmio_attribute)
		return -ENOMEM;

	ret = init_generic_mmio_info(gvt);
	if (ret)
		goto err;

	if (IS_BROADWELL(dev_priv)) {
		ret = init_broadwell_mmio_info(gvt);
		if (ret)
			goto err;
	}
	return 0;
err:
	intel_gvt_clean_mmio_info(gvt);
	return ret;
}
+89 −0
Original line number Diff line number Diff line
/*
 * Copyright(c) 2011-2016 Intel Corporation. All rights reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice (including the next
 * paragraph) shall be included in all copies or substantial portions of the
 * Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 *
 * Authors:
 *    Ke Yu
 *    Kevin Tian <kevin.tian@intel.com>
 *    Dexuan Cui
 *
 * Contributors:
 *    Tina Zhang <tina.zhang@intel.com>
 *    Min He <min.he@intel.com>
 *    Niu Bing <bing.niu@intel.com>
 *    Zhi Wang <zhi.a.wang@intel.com>
 *
 */

#ifndef _GVT_MMIO_H_
#define _GVT_MMIO_H_

struct intel_gvt;
struct intel_vgpu;

#define D_SNB   (1 << 0)
#define D_IVB   (1 << 1)
#define D_HSW   (1 << 2)
#define D_BDW   (1 << 3)
#define D_SKL	(1 << 4)

#define D_GEN9PLUS	(D_SKL)
#define D_GEN8PLUS	(D_BDW | D_SKL)
#define D_GEN75PLUS	(D_HSW | D_BDW | D_SKL)
#define D_GEN7PLUS	(D_IVB | D_HSW | D_BDW | D_SKL)

#define D_SKL_PLUS	(D_SKL)
#define D_BDW_PLUS	(D_BDW | D_SKL)
#define D_HSW_PLUS	(D_HSW | D_BDW | D_SKL)
#define D_IVB_PLUS	(D_IVB | D_HSW | D_BDW | D_SKL)

#define D_PRE_BDW	(D_SNB | D_IVB | D_HSW)
#define D_PRE_SKL	(D_SNB | D_IVB | D_HSW | D_BDW)
#define D_ALL		(D_SNB | D_IVB | D_HSW | D_BDW | D_SKL)

struct intel_gvt_mmio_info {
	u32 offset;
	u32 size;
	u32 length;
	u32 addr_mask;
	u64 ro_mask;
	u32 device;
	int (*read)(struct intel_vgpu *, unsigned int, void *, unsigned int);
	int (*write)(struct intel_vgpu *, unsigned int, void *, unsigned int);
	u32 addr_range;
	struct hlist_node node;
};

unsigned long intel_gvt_get_device_type(struct intel_gvt *gvt);
bool intel_gvt_match_device(struct intel_gvt *gvt, unsigned long device);

int intel_gvt_setup_mmio_info(struct intel_gvt *gvt);
void intel_gvt_clean_mmio_info(struct intel_gvt *gvt);

struct intel_gvt_mmio_info *intel_gvt_find_mmio_info(struct intel_gvt *gvt,
						     unsigned int offset);
#define INTEL_GVT_MMIO_OFFSET(reg) ({ \
	typeof(reg) __reg = reg; \
	u32 *offset = (u32 *)&__reg; \
	*offset; \
})

#endif