Skip to content

Commit

Permalink
drm/i915/gvt: Introduce a framework for tracking HW registers.
Browse files Browse the repository at this point in the history
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: Zhi Wang <zhi.a.wang@intel.com>
Signed-off-by: Zhenyu Wang <zhenyuw@linux.intel.com>
  • Loading branch information
Zhi Wang authored and Zhenyu Wang committed Oct 14, 2016
1 parent 28a60de commit 12d14cc
Show file tree
Hide file tree
Showing 5 changed files with 379 additions and 9 deletions.
2 changes: 1 addition & 1 deletion drivers/gpu/drm/i915/gvt/Makefile
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
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))
30 changes: 23 additions & 7 deletions drivers/gpu/drm/i915/gvt/gvt.c
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down Expand Up @@ -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;
}
}

/**
Expand All @@ -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;
}
Expand All @@ -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.
Expand All @@ -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;
Expand Down
20 changes: 19 additions & 1 deletion drivers/gpu/drm/i915/gvt/gvt.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,23 @@
* 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_
#define _GVT_H_

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

#define GVT_MAX_VGPU 8

Expand All @@ -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 */
Expand Down Expand Up @@ -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;
Expand All @@ -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 */
Expand Down
247 changes: 247 additions & 0 deletions drivers/gpu/drm/i915/gvt/handlers.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,247 @@
/*
* 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;
}
Loading

0 comments on commit 12d14cc

Please sign in to comment.