Merge tag 'gvt-gt-next-2021-01-18' of https://github.com/intel/gvt-linux into drm...
authorJoonas Lahtinen <joonas.lahtinen@linux.intel.com>
Thu, 21 Jan 2021 13:10:16 +0000 (15:10 +0200)
committerJoonas Lahtinen <joonas.lahtinen@linux.intel.com>
Thu, 21 Jan 2021 13:10:17 +0000 (15:10 +0200)
gvt-gt-next-2021-01-18

- GVT cmd parser enhancement against guest context (Yan)

Signed-off-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
From: Zhenyu Wang <zhenyuw@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20210118050739.GY15982@zhen-hp.sh.intel.com
drivers/gpu/drm/i915/gvt/cmd_parser.c
drivers/gpu/drm/i915/gvt/cmd_parser.h
drivers/gpu/drm/i915/gvt/gvt.h
drivers/gpu/drm/i915/gvt/handlers.c
drivers/gpu/drm/i915/gvt/mmio.h
drivers/gpu/drm/i915/gvt/reg.h
drivers/gpu/drm/i915/gvt/scheduler.c
drivers/gpu/drm/i915/gvt/vgpu.c

index 3fea967..7fb91de 100644 (file)
 
 #include "i915_drv.h"
 #include "gt/intel_gpu_commands.h"
+#include "gt/intel_lrc.h"
 #include "gt/intel_ring.h"
+#include "gt/intel_gt_requests.h"
 #include "gvt.h"
 #include "i915_pvinfo.h"
 #include "trace.h"
 
+#include "gem/i915_gem_context.h"
+#include "gem/i915_gem_pm.h"
+#include "gt/intel_context.h"
+
 #define INVALID_OP    (~0U)
 
 #define OP_LEN_MI           9
@@ -455,6 +461,7 @@ enum {
        RING_BUFFER_INSTRUCTION,
        BATCH_BUFFER_INSTRUCTION,
        BATCH_BUFFER_2ND_LEVEL,
+       RING_BUFFER_CTX,
 };
 
 enum {
@@ -496,6 +503,7 @@ struct parser_exec_state {
         */
        int saved_buf_addr_type;
        bool is_ctx_wa;
+       bool is_init_ctx;
 
        const struct cmd_info *info;
 
@@ -709,6 +717,11 @@ static inline u32 cmd_val(struct parser_exec_state *s, int index)
        return *cmd_ptr(s, index);
 }
 
+static inline bool is_init_ctx(struct parser_exec_state *s)
+{
+       return (s->buf_type == RING_BUFFER_CTX && s->is_init_ctx);
+}
+
 static void parser_exec_state_dump(struct parser_exec_state *s)
 {
        int cnt = 0;
@@ -722,7 +735,8 @@ static void parser_exec_state_dump(struct parser_exec_state *s)
 
        gvt_dbg_cmd("  %s %s ip_gma(%08lx) ",
                        s->buf_type == RING_BUFFER_INSTRUCTION ?
-                       "RING_BUFFER" : "BATCH_BUFFER",
+                       "RING_BUFFER" : ((s->buf_type == RING_BUFFER_CTX) ?
+                               "CTX_BUFFER" : "BATCH_BUFFER"),
                        s->buf_addr_type == GTT_BUFFER ?
                        "GTT" : "PPGTT", s->ip_gma);
 
@@ -757,7 +771,8 @@ static inline void update_ip_va(struct parser_exec_state *s)
        if (WARN_ON(s->ring_head == s->ring_tail))
                return;
 
-       if (s->buf_type == RING_BUFFER_INSTRUCTION) {
+       if (s->buf_type == RING_BUFFER_INSTRUCTION ||
+                       s->buf_type == RING_BUFFER_CTX) {
                unsigned long ring_top = s->ring_start + s->ring_size;
 
                if (s->ring_head > s->ring_tail) {
@@ -821,68 +836,12 @@ static inline int cmd_length(struct parser_exec_state *s)
        *addr = val; \
 } while (0)
 
-static bool is_shadowed_mmio(unsigned int offset)
-{
-       bool ret = false;
-
-       if ((offset == 0x2168) || /*BB current head register UDW */
-           (offset == 0x2140) || /*BB current header register */
-           (offset == 0x211c) || /*second BB header register UDW */
-           (offset == 0x2114)) { /*second BB header register UDW */
-               ret = true;
-       }
-       return ret;
-}
-
-static inline bool is_force_nonpriv_mmio(unsigned int offset)
-{
-       return (offset >= 0x24d0 && offset < 0x2500);
-}
-
-static int force_nonpriv_reg_handler(struct parser_exec_state *s,
-               unsigned int offset, unsigned int index, char *cmd)
-{
-       struct intel_gvt *gvt = s->vgpu->gvt;
-       unsigned int data;
-       u32 ring_base;
-       u32 nopid;
-
-       if (!strcmp(cmd, "lri"))
-               data = cmd_val(s, index + 1);
-       else {
-               gvt_err("Unexpected forcenonpriv 0x%x write from cmd %s\n",
-                       offset, cmd);
-               return -EINVAL;
-       }
-
-       ring_base = s->engine->mmio_base;
-       nopid = i915_mmio_reg_offset(RING_NOPID(ring_base));
-
-       if (!intel_gvt_in_force_nonpriv_whitelist(gvt, data) &&
-                       data != nopid) {
-               gvt_err("Unexpected forcenonpriv 0x%x LRI write, value=0x%x\n",
-                       offset, data);
-               patch_value(s, cmd_ptr(s, index), nopid);
-               return 0;
-       }
-       return 0;
-}
-
 static inline bool is_mocs_mmio(unsigned int offset)
 {
        return ((offset >= 0xc800) && (offset <= 0xcff8)) ||
                ((offset >= 0xb020) && (offset <= 0xb0a0));
 }
 
-static int mocs_cmd_reg_handler(struct parser_exec_state *s,
-                               unsigned int offset, unsigned int index)
-{
-       if (!is_mocs_mmio(offset))
-               return -EINVAL;
-       vgpu_vreg(s->vgpu, offset) = cmd_val(s, index + 1);
-       return 0;
-}
-
 static int is_cmd_update_pdps(unsigned int offset,
                              struct parser_exec_state *s)
 {
@@ -930,6 +889,7 @@ static int cmd_reg_handler(struct parser_exec_state *s,
        struct intel_vgpu *vgpu = s->vgpu;
        struct intel_gvt *gvt = vgpu->gvt;
        u32 ctx_sr_ctl;
+       u32 *vreg, vreg_old;
 
        if (offset + 4 > gvt->device_info.mmio_size) {
                gvt_vgpu_err("%s access to (%x) outside of MMIO range\n",
@@ -937,34 +897,101 @@ static int cmd_reg_handler(struct parser_exec_state *s,
                return -EFAULT;
        }
 
+       if (is_init_ctx(s)) {
+               struct intel_gvt_mmio_info *mmio_info;
+
+               intel_gvt_mmio_set_cmd_accessible(gvt, offset);
+               mmio_info = intel_gvt_find_mmio_info(gvt, offset);
+               if (mmio_info && mmio_info->write)
+                       intel_gvt_mmio_set_cmd_write_patch(gvt, offset);
+               return 0;
+       }
+
        if (!intel_gvt_mmio_is_cmd_accessible(gvt, offset)) {
                gvt_vgpu_err("%s access to non-render register (%x)\n",
                                cmd, offset);
                return -EBADRQC;
        }
 
-       if (is_shadowed_mmio(offset)) {
-               gvt_vgpu_err("found access of shadowed MMIO %x\n", offset);
-               return 0;
+       if (!strncmp(cmd, "srm", 3) ||
+                       !strncmp(cmd, "lrm", 3)) {
+               if (offset != i915_mmio_reg_offset(GEN8_L3SQCREG4) &&
+                               offset != 0x21f0) {
+                       gvt_vgpu_err("%s access to register (%x)\n",
+                                       cmd, offset);
+                       return -EPERM;
+               } else
+                       return 0;
        }
 
-       if (is_mocs_mmio(offset) &&
-           mocs_cmd_reg_handler(s, offset, index))
-               return -EINVAL;
+       if (!strncmp(cmd, "lrr-src", 7) ||
+                       !strncmp(cmd, "lrr-dst", 7)) {
+               gvt_vgpu_err("not allowed cmd %s\n", cmd);
+               return -EPERM;
+       }
+
+       if (!strncmp(cmd, "pipe_ctrl", 9)) {
+               /* TODO: add LRI POST logic here */
+               return 0;
+       }
 
-       if (is_force_nonpriv_mmio(offset) &&
-               force_nonpriv_reg_handler(s, offset, index, cmd))
+       if (strncmp(cmd, "lri", 3))
                return -EPERM;
 
+       /* below are all lri handlers */
+       vreg = &vgpu_vreg(s->vgpu, offset);
+       if (!intel_gvt_mmio_is_cmd_accessible(gvt, offset)) {
+               gvt_vgpu_err("%s access to non-render register (%x)\n",
+                               cmd, offset);
+               return -EBADRQC;
+       }
+
+       if (is_cmd_update_pdps(offset, s) &&
+           cmd_pdp_mmio_update_handler(s, offset, index))
+               return -EINVAL;
+
        if (offset == i915_mmio_reg_offset(DERRMR) ||
                offset == i915_mmio_reg_offset(FORCEWAKE_MT)) {
                /* Writing to HW VGT_PVINFO_PAGE offset will be discarded */
                patch_value(s, cmd_ptr(s, index), VGT_PVINFO_PAGE);
        }
 
-       if (is_cmd_update_pdps(offset, s) &&
-           cmd_pdp_mmio_update_handler(s, offset, index))
-               return -EINVAL;
+       if (is_mocs_mmio(offset))
+               *vreg = cmd_val(s, index + 1);
+
+       vreg_old = *vreg;
+
+       if (intel_gvt_mmio_is_cmd_write_patch(gvt, offset)) {
+               u32 cmdval_new, cmdval;
+               struct intel_gvt_mmio_info *mmio_info;
+
+               cmdval = cmd_val(s, index + 1);
+
+               mmio_info = intel_gvt_find_mmio_info(gvt, offset);
+               if (!mmio_info) {
+                       cmdval_new = cmdval;
+               } else {
+                       u64 ro_mask = mmio_info->ro_mask;
+                       int ret;
+
+                       if (likely(!ro_mask))
+                               ret = mmio_info->write(s->vgpu, offset,
+                                               &cmdval, 4);
+                       else {
+                               gvt_vgpu_err("try to write RO reg %x\n",
+                                               offset);
+                               ret = -EBADRQC;
+                       }
+                       if (ret)
+                               return ret;
+                       cmdval_new = *vreg;
+               }
+               if (cmdval_new != cmdval)
+                       patch_value(s, cmd_ptr(s, index+1), cmdval_new);
+       }
+
+       /* only patch cmd. restore vreg value if changed in mmio write handler*/
+       *vreg = vreg_old;
 
        /* TODO
         * In order to let workload with inhibit context to generate
@@ -1216,6 +1243,8 @@ static int cmd_handler_mi_batch_buffer_end(struct parser_exec_state *s)
                s->buf_type = BATCH_BUFFER_INSTRUCTION;
                ret = ip_gma_set(s, s->ret_ip_gma_bb);
                s->buf_addr_type = s->saved_buf_addr_type;
+       } else if (s->buf_type == RING_BUFFER_CTX) {
+               ret = ip_gma_set(s, s->ring_tail);
        } else {
                s->buf_type = RING_BUFFER_INSTRUCTION;
                s->buf_addr_type = GTT_BUFFER;
@@ -2764,7 +2793,8 @@ static int command_scan(struct parser_exec_state *s,
        gma_bottom = rb_start +  rb_len;
 
        while (s->ip_gma != gma_tail) {
-               if (s->buf_type == RING_BUFFER_INSTRUCTION) {
+               if (s->buf_type == RING_BUFFER_INSTRUCTION ||
+                               s->buf_type == RING_BUFFER_CTX) {
                        if (!(s->ip_gma >= rb_start) ||
                                !(s->ip_gma < gma_bottom)) {
                                gvt_vgpu_err("ip_gma %lx out of ring scope."
@@ -3057,6 +3087,171 @@ int intel_gvt_scan_and_shadow_wa_ctx(struct intel_shadow_wa_ctx *wa_ctx)
        return 0;
 }
 
+/* generate dummy contexts by sending empty requests to HW, and let
+ * the HW to fill Engine Contexts. This dummy contexts are used for
+ * initialization purpose (update reg whitelist), so referred to as
+ * init context here
+ */
+void intel_gvt_update_reg_whitelist(struct intel_vgpu *vgpu)
+{
+       struct intel_gvt *gvt = vgpu->gvt;
+       struct drm_i915_private *dev_priv = gvt->gt->i915;
+       struct intel_engine_cs *engine;
+       enum intel_engine_id id;
+       const unsigned long start = LRC_STATE_PN * PAGE_SIZE;
+       struct i915_request *rq;
+       struct intel_vgpu_submission *s = &vgpu->submission;
+       struct i915_request *requests[I915_NUM_ENGINES] = {};
+       bool is_ctx_pinned[I915_NUM_ENGINES] = {};
+       int ret;
+
+       if (gvt->is_reg_whitelist_updated)
+               return;
+
+       for_each_engine(engine, &dev_priv->gt, id) {
+               ret = intel_context_pin(s->shadow[id]);
+               if (ret) {
+                       gvt_vgpu_err("fail to pin shadow ctx\n");
+                       goto out;
+               }
+               is_ctx_pinned[id] = true;
+
+               rq = i915_request_create(s->shadow[id]);
+               if (IS_ERR(rq)) {
+                       gvt_vgpu_err("fail to alloc default request\n");
+                       ret = -EIO;
+                       goto out;
+               }
+               requests[id] = i915_request_get(rq);
+               i915_request_add(rq);
+       }
+
+       if (intel_gt_wait_for_idle(&dev_priv->gt,
+                               I915_GEM_IDLE_TIMEOUT) == -ETIME) {
+               ret = -EIO;
+               goto out;
+       }
+
+       /* scan init ctx to update cmd accessible list */
+       for_each_engine(engine, &dev_priv->gt, id) {
+               int size = engine->context_size - PAGE_SIZE;
+               void *vaddr;
+               struct parser_exec_state s;
+               struct drm_i915_gem_object *obj;
+               struct i915_request *rq;
+
+               rq = requests[id];
+               GEM_BUG_ON(!i915_request_completed(rq));
+               GEM_BUG_ON(!intel_context_is_pinned(rq->context));
+               obj = rq->context->state->obj;
+
+               if (!obj) {
+                       ret = -EIO;
+                       goto out;
+               }
+
+               i915_gem_object_set_cache_coherency(obj,
+                                                   I915_CACHE_LLC);
+
+               vaddr = i915_gem_object_pin_map(obj, I915_MAP_WB);
+               if (IS_ERR(vaddr)) {
+                       gvt_err("failed to pin init ctx obj, ring=%d, err=%lx\n",
+                               id, PTR_ERR(vaddr));
+                       goto out;
+               }
+
+               s.buf_type = RING_BUFFER_CTX;
+               s.buf_addr_type = GTT_BUFFER;
+               s.vgpu = vgpu;
+               s.engine = engine;
+               s.ring_start = 0;
+               s.ring_size = size;
+               s.ring_head = 0;
+               s.ring_tail = size;
+               s.rb_va = vaddr + start;
+               s.workload = NULL;
+               s.is_ctx_wa = false;
+               s.is_init_ctx = true;
+
+               /* skipping the first RING_CTX_SIZE(0x50) dwords */
+               ret = ip_gma_set(&s, RING_CTX_SIZE);
+               if (ret) {
+                       i915_gem_object_unpin_map(obj);
+                       goto out;
+               }
+
+               ret = command_scan(&s, 0, size, 0, size);
+               if (ret)
+                       gvt_err("Scan init ctx error\n");
+
+               i915_gem_object_unpin_map(obj);
+       }
+
+out:
+       if (!ret)
+               gvt->is_reg_whitelist_updated = true;
+
+       for (id = 0; id < I915_NUM_ENGINES ; id++) {
+               if (requests[id])
+                       i915_request_put(requests[id]);
+
+               if (is_ctx_pinned[id])
+                       intel_context_unpin(s->shadow[id]);
+       }
+}
+
+int intel_gvt_scan_engine_context(struct intel_vgpu_workload *workload)
+{
+       struct intel_vgpu *vgpu = workload->vgpu;
+       unsigned long gma_head, gma_tail, gma_start, ctx_size;
+       struct parser_exec_state s;
+       int ring_id = workload->engine->id;
+       struct intel_context *ce = vgpu->submission.shadow[ring_id];
+       int ret;
+
+       GEM_BUG_ON(atomic_read(&ce->pin_count) < 0);
+
+       ctx_size = workload->engine->context_size - PAGE_SIZE;
+
+       /* Only ring contxt is loaded to HW for inhibit context, no need to
+        * scan engine context
+        */
+       if (is_inhibit_context(ce))
+               return 0;
+
+       gma_start = i915_ggtt_offset(ce->state) + LRC_STATE_PN*PAGE_SIZE;
+       gma_head = 0;
+       gma_tail = ctx_size;
+
+       s.buf_type = RING_BUFFER_CTX;
+       s.buf_addr_type = GTT_BUFFER;
+       s.vgpu = workload->vgpu;
+       s.engine = workload->engine;
+       s.ring_start = gma_start;
+       s.ring_size = ctx_size;
+       s.ring_head = gma_start + gma_head;
+       s.ring_tail = gma_start + gma_tail;
+       s.rb_va = ce->lrc_reg_state;
+       s.workload = workload;
+       s.is_ctx_wa = false;
+       s.is_init_ctx = false;
+
+       /* don't scan the first RING_CTX_SIZE(0x50) dwords, as it's ring
+        * context
+        */
+       ret = ip_gma_set(&s, gma_start + gma_head + RING_CTX_SIZE);
+       if (ret)
+               goto out;
+
+       ret = command_scan(&s, gma_head, gma_tail,
+               gma_start, ctx_size);
+out:
+       if (ret)
+               gvt_vgpu_err("scan shadow ctx error\n");
+
+       return ret;
+}
+
 static int init_cmd_table(struct intel_gvt *gvt)
 {
        unsigned int gen_type = intel_gvt_get_device_type(gvt);
index ab25d15..d5e95b7 100644 (file)
@@ -50,4 +50,8 @@ int intel_gvt_scan_and_shadow_ringbuffer(struct intel_vgpu_workload *workload);
 
 int intel_gvt_scan_and_shadow_wa_ctx(struct intel_shadow_wa_ctx *wa_ctx);
 
+void intel_gvt_update_reg_whitelist(struct intel_vgpu *vgpu);
+
+int intel_gvt_scan_engine_context(struct intel_vgpu_workload *workload);
+
 #endif
index 62a4807..03c993d 100644 (file)
@@ -248,7 +248,7 @@ struct gvt_mmio_block {
 #define INTEL_GVT_MMIO_HASH_BITS 11
 
 struct intel_gvt_mmio {
-       u8 *mmio_attribute;
+       u16 *mmio_attribute;
 /* Register contains RO bits */
 #define F_RO           (1 << 0)
 /* Register contains graphics address */
@@ -267,6 +267,8 @@ struct intel_gvt_mmio {
  * logical context image
  */
 #define F_SR_IN_CTX    (1 << 7)
+/* Value of command write of this reg needs to be patched */
+#define F_CMD_WRITE_PATCH      (1 << 8)
 
        struct gvt_mmio_block *mmio_block;
        unsigned int num_mmio_block;
@@ -333,6 +335,7 @@ struct intel_gvt {
                u32 *mocs_mmio_offset_list;
                u32 mocs_mmio_offset_list_cnt;
        } engine_mmio_list;
+       bool is_reg_whitelist_updated;
 
        struct dentry *debugfs_root;
 };
@@ -416,6 +419,9 @@ int intel_gvt_load_firmware(struct intel_gvt *gvt);
 #define vgpu_fence_base(vgpu) (vgpu->fence.base)
 #define vgpu_fence_sz(vgpu) (vgpu->fence.size)
 
+/* ring context size i.e. the first 0x50 dwords*/
+#define RING_CTX_SIZE 320
+
 struct intel_vgpu_creation_params {
        __u64 handle;
        __u64 low_gm_sz;  /* in MB */
@@ -687,6 +693,35 @@ static inline void intel_gvt_mmio_set_sr_in_ctx(
 }
 
 void intel_gvt_debugfs_add_vgpu(struct intel_vgpu *vgpu);
+/**
+ * intel_gvt_mmio_set_cmd_write_patch -
+ *                             mark an MMIO if its cmd write needs to be
+ *                             patched
+ * @gvt: a GVT device
+ * @offset: register offset
+ *
+ */
+static inline void intel_gvt_mmio_set_cmd_write_patch(
+                       struct intel_gvt *gvt, unsigned int offset)
+{
+       gvt->mmio.mmio_attribute[offset >> 2] |= F_CMD_WRITE_PATCH;
+}
+
+/**
+ * intel_gvt_mmio_is_cmd_write_patch - check if an mmio's cmd access needs to
+ * be patched
+ * @gvt: a GVT device
+ * @offset: register offset
+ *
+ * Returns:
+ * True if GPU commmand write to an MMIO should be patched
+ */
+static inline bool intel_gvt_mmio_is_cmd_write_patch(
+                       struct intel_gvt *gvt, unsigned int offset)
+{
+       return gvt->mmio.mmio_attribute[offset >> 2] & F_CMD_WRITE_PATCH;
+}
+
 void intel_gvt_debugfs_remove_vgpu(struct intel_vgpu *vgpu);
 void intel_gvt_debugfs_init(struct intel_gvt *gvt);
 void intel_gvt_debugfs_clean(struct intel_gvt *gvt);
index 0d124ce..6eeaeec 100644 (file)
@@ -83,7 +83,7 @@ static void write_vreg(struct intel_vgpu *vgpu, unsigned int offset,
        memcpy(&vgpu_vreg(vgpu, offset), p_data, bytes);
 }
 
-static struct intel_gvt_mmio_info *find_mmio_info(struct intel_gvt *gvt,
+struct intel_gvt_mmio_info *intel_gvt_find_mmio_info(struct intel_gvt *gvt,
                                                  unsigned int offset)
 {
        struct intel_gvt_mmio_info *e;
@@ -96,7 +96,7 @@ static struct intel_gvt_mmio_info *find_mmio_info(struct intel_gvt *gvt,
 }
 
 static int new_mmio_info(struct intel_gvt *gvt,
-               u32 offset, u8 flags, u32 size,
+               u32 offset, u16 flags, u32 size,
                u32 addr_mask, u32 ro_mask, u32 device,
                gvt_mmio_func read, gvt_mmio_func write)
 {
@@ -118,7 +118,7 @@ static int new_mmio_info(struct intel_gvt *gvt,
                        return -ENOMEM;
 
                info->offset = i;
-               p = find_mmio_info(gvt, info->offset);
+               p = intel_gvt_find_mmio_info(gvt, info->offset);
                if (p) {
                        WARN(1, "dup mmio definition offset %x\n",
                                info->offset);
@@ -1965,7 +1965,8 @@ static int init_generic_mmio_info(struct intel_gvt *gvt)
 
        /* RING MODE */
 #define RING_REG(base) _MMIO((base) + 0x29c)
-       MMIO_RING_DFH(RING_REG, D_ALL, F_MODE_MASK | F_CMD_ACCESS, NULL,
+       MMIO_RING_DFH(RING_REG, D_ALL,
+               F_MODE_MASK | F_CMD_ACCESS | F_CMD_WRITE_PATCH, NULL,
                ring_mode_mmio_write);
 #undef RING_REG
 
@@ -2885,8 +2886,8 @@ static int init_bdw_mmio_info(struct intel_gvt *gvt)
        MMIO_DFH(_MMIO(0xb10c), D_BDW, F_CMD_ACCESS, NULL, NULL);
        MMIO_D(_MMIO(0xb110), D_BDW);
 
-       MMIO_F(_MMIO(0x24d0), 48, F_CMD_ACCESS, 0, 0, D_BDW_PLUS,
-               NULL, force_nonpriv_write);
+       MMIO_F(_MMIO(0x24d0), 48, F_CMD_ACCESS | F_CMD_WRITE_PATCH, 0, 0,
+               D_BDW_PLUS, NULL, force_nonpriv_write);
 
        MMIO_D(_MMIO(0x44484), D_BDW_PLUS);
        MMIO_D(_MMIO(0x4448c), D_BDW_PLUS);
@@ -3626,7 +3627,7 @@ int intel_vgpu_mmio_reg_rw(struct intel_vgpu *vgpu, unsigned int offset,
        /*
         * Normal tracked MMIOs.
         */
-       mmio_info = find_mmio_info(gvt, offset);
+       mmio_info = intel_gvt_find_mmio_info(gvt, offset);
        if (!mmio_info) {
                gvt_dbg_mmio("untracked MMIO %08x len %d\n", offset, bytes);
                goto default_rw;
index 9e862dc..7c26af3 100644 (file)
@@ -80,6 +80,9 @@ int intel_gvt_for_each_tracked_mmio(struct intel_gvt *gvt,
        int (*handler)(struct intel_gvt *gvt, u32 offset, void *data),
        void *data);
 
+struct intel_gvt_mmio_info *intel_gvt_find_mmio_info(struct intel_gvt *gvt,
+                                                 unsigned int offset);
+
 int intel_vgpu_init_mmio(struct intel_vgpu *vgpu);
 void intel_vgpu_reset_mmio(struct intel_vgpu *vgpu, bool dmlr);
 void intel_vgpu_clean_mmio(struct intel_vgpu *vgpu);
index b58860d..244cc73 100644 (file)
 #define RING_GFX_MODE(base)    _MMIO((base) + 0x29c)
 #define VF_GUARDBAND           _MMIO(0x83a4)
 
+
+#define BCS_TILE_REGISTER_VAL_OFFSET (0x43*4)
 #endif
index 6af5c06..43f31c2 100644 (file)
@@ -137,6 +137,7 @@ static int populate_shadow_context(struct intel_vgpu_workload *workload)
        int i;
        bool skip = false;
        int ring_id = workload->engine->id;
+       int ret;
 
        GEM_BUG_ON(!intel_context_is_pinned(ctx));
 
@@ -163,16 +164,24 @@ static int populate_shadow_context(struct intel_vgpu_workload *workload)
                COPY_REG(bb_per_ctx_ptr);
                COPY_REG(rcs_indirect_ctx);
                COPY_REG(rcs_indirect_ctx_offset);
-       }
+       } else if (workload->engine->id == BCS0)
+               intel_gvt_hypervisor_read_gpa(vgpu,
+                               workload->ring_context_gpa +
+                               BCS_TILE_REGISTER_VAL_OFFSET,
+                               (void *)shadow_ring_context +
+                               BCS_TILE_REGISTER_VAL_OFFSET, 4);
 #undef COPY_REG
 #undef COPY_REG_MASKED
 
+       /* don't copy Ring Context (the first 0x50 dwords),
+        * only copy the Engine Context part from guest
+        */
        intel_gvt_hypervisor_read_gpa(vgpu,
                        workload->ring_context_gpa +
-                       sizeof(*shadow_ring_context),
+                       RING_CTX_SIZE,
                        (void *)shadow_ring_context +
-                       sizeof(*shadow_ring_context),
-                       I915_GTT_PAGE_SIZE - sizeof(*shadow_ring_context));
+                       RING_CTX_SIZE,
+                       I915_GTT_PAGE_SIZE - RING_CTX_SIZE);
 
        sr_oa_regs(workload, (u32 *)shadow_ring_context, false);
 
@@ -239,6 +248,11 @@ read:
                gpa_size = I915_GTT_PAGE_SIZE;
                dst = context_base + (i << I915_GTT_PAGE_SHIFT);
        }
+       ret = intel_gvt_scan_engine_context(workload);
+       if (ret) {
+               gvt_vgpu_err("invalid cmd found in guest context pages\n");
+               return ret;
+       }
        s->last_ctx[ring_id].valid = true;
        return 0;
 }
index e49944f..5a72263 100644 (file)
@@ -500,9 +500,11 @@ struct intel_vgpu *intel_gvt_create_vgpu(struct intel_gvt *gvt,
 
        mutex_lock(&gvt->lock);
        vgpu = __intel_gvt_create_vgpu(gvt, &param);
-       if (!IS_ERR(vgpu))
+       if (!IS_ERR(vgpu)) {
                /* calculate left instance change for types */
                intel_gvt_update_vgpu_types(gvt);
+               intel_gvt_update_reg_whitelist(vgpu);
+       }
        mutex_unlock(&gvt->lock);
 
        return vgpu;