0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036 #include <linux/kthread.h>
0037
0038 #include "gem/i915_gem_pm.h"
0039 #include "gt/intel_context.h"
0040 #include "gt/intel_execlists_submission.h"
0041 #include "gt/intel_gt_regs.h"
0042 #include "gt/intel_lrc.h"
0043 #include "gt/intel_ring.h"
0044
0045 #include "i915_drv.h"
0046 #include "i915_gem_gtt.h"
0047 #include "i915_perf_oa_regs.h"
0048 #include "gvt.h"
0049
0050 #define RING_CTX_OFF(x) \
0051 offsetof(struct execlist_ring_context, x)
0052
0053 static void set_context_pdp_root_pointer(
0054 struct execlist_ring_context *ring_context,
0055 u32 pdp[8])
0056 {
0057 int i;
0058
0059 for (i = 0; i < 8; i++)
0060 ring_context->pdps[i].val = pdp[7 - i];
0061 }
0062
0063 static void update_shadow_pdps(struct intel_vgpu_workload *workload)
0064 {
0065 struct execlist_ring_context *shadow_ring_context;
0066 struct intel_context *ctx = workload->req->context;
0067
0068 if (WARN_ON(!workload->shadow_mm))
0069 return;
0070
0071 if (WARN_ON(!atomic_read(&workload->shadow_mm->pincount)))
0072 return;
0073
0074 shadow_ring_context = (struct execlist_ring_context *)ctx->lrc_reg_state;
0075 set_context_pdp_root_pointer(shadow_ring_context,
0076 (void *)workload->shadow_mm->ppgtt_mm.shadow_pdps);
0077 }
0078
0079
0080
0081
0082
0083
0084 static void sr_oa_regs(struct intel_vgpu_workload *workload,
0085 u32 *reg_state, bool save)
0086 {
0087 struct drm_i915_private *dev_priv = workload->vgpu->gvt->gt->i915;
0088 u32 ctx_oactxctrl = dev_priv->perf.ctx_oactxctrl_offset;
0089 u32 ctx_flexeu0 = dev_priv->perf.ctx_flexeu0_offset;
0090 int i = 0;
0091 u32 flex_mmio[] = {
0092 i915_mmio_reg_offset(EU_PERF_CNTL0),
0093 i915_mmio_reg_offset(EU_PERF_CNTL1),
0094 i915_mmio_reg_offset(EU_PERF_CNTL2),
0095 i915_mmio_reg_offset(EU_PERF_CNTL3),
0096 i915_mmio_reg_offset(EU_PERF_CNTL4),
0097 i915_mmio_reg_offset(EU_PERF_CNTL5),
0098 i915_mmio_reg_offset(EU_PERF_CNTL6),
0099 };
0100
0101 if (workload->engine->id != RCS0)
0102 return;
0103
0104 if (save) {
0105 workload->oactxctrl = reg_state[ctx_oactxctrl + 1];
0106
0107 for (i = 0; i < ARRAY_SIZE(workload->flex_mmio); i++) {
0108 u32 state_offset = ctx_flexeu0 + i * 2;
0109
0110 workload->flex_mmio[i] = reg_state[state_offset + 1];
0111 }
0112 } else {
0113 reg_state[ctx_oactxctrl] =
0114 i915_mmio_reg_offset(GEN8_OACTXCONTROL);
0115 reg_state[ctx_oactxctrl + 1] = workload->oactxctrl;
0116
0117 for (i = 0; i < ARRAY_SIZE(workload->flex_mmio); i++) {
0118 u32 state_offset = ctx_flexeu0 + i * 2;
0119 u32 mmio = flex_mmio[i];
0120
0121 reg_state[state_offset] = mmio;
0122 reg_state[state_offset + 1] = workload->flex_mmio[i];
0123 }
0124 }
0125 }
0126
0127 static int populate_shadow_context(struct intel_vgpu_workload *workload)
0128 {
0129 struct intel_vgpu *vgpu = workload->vgpu;
0130 struct intel_gvt *gvt = vgpu->gvt;
0131 struct intel_context *ctx = workload->req->context;
0132 struct execlist_ring_context *shadow_ring_context;
0133 void *dst;
0134 void *context_base;
0135 unsigned long context_gpa, context_page_num;
0136 unsigned long gpa_base;
0137 unsigned long gpa_size;
0138 struct intel_vgpu_submission *s = &vgpu->submission;
0139 int i;
0140 bool skip = false;
0141 int ring_id = workload->engine->id;
0142 int ret;
0143
0144 GEM_BUG_ON(!intel_context_is_pinned(ctx));
0145
0146 context_base = (void *) ctx->lrc_reg_state -
0147 (LRC_STATE_PN << I915_GTT_PAGE_SHIFT);
0148
0149 shadow_ring_context = (void *) ctx->lrc_reg_state;
0150
0151 sr_oa_regs(workload, (u32 *)shadow_ring_context, true);
0152 #define COPY_REG(name) \
0153 intel_gvt_read_gpa(vgpu, workload->ring_context_gpa \
0154 + RING_CTX_OFF(name.val), &shadow_ring_context->name.val, 4)
0155 #define COPY_REG_MASKED(name) {\
0156 intel_gvt_read_gpa(vgpu, workload->ring_context_gpa \
0157 + RING_CTX_OFF(name.val),\
0158 &shadow_ring_context->name.val, 4);\
0159 shadow_ring_context->name.val |= 0xffff << 16;\
0160 }
0161
0162 COPY_REG_MASKED(ctx_ctrl);
0163 COPY_REG(ctx_timestamp);
0164
0165 if (workload->engine->id == RCS0) {
0166 COPY_REG(bb_per_ctx_ptr);
0167 COPY_REG(rcs_indirect_ctx);
0168 COPY_REG(rcs_indirect_ctx_offset);
0169 } else if (workload->engine->id == BCS0)
0170 intel_gvt_read_gpa(vgpu,
0171 workload->ring_context_gpa +
0172 BCS_TILE_REGISTER_VAL_OFFSET,
0173 (void *)shadow_ring_context +
0174 BCS_TILE_REGISTER_VAL_OFFSET, 4);
0175 #undef COPY_REG
0176 #undef COPY_REG_MASKED
0177
0178
0179
0180
0181 intel_gvt_read_gpa(vgpu,
0182 workload->ring_context_gpa +
0183 RING_CTX_SIZE,
0184 (void *)shadow_ring_context +
0185 RING_CTX_SIZE,
0186 I915_GTT_PAGE_SIZE - RING_CTX_SIZE);
0187
0188 sr_oa_regs(workload, (u32 *)shadow_ring_context, false);
0189
0190 gvt_dbg_sched("ring %s workload lrca %x, ctx_id %x, ctx gpa %llx",
0191 workload->engine->name, workload->ctx_desc.lrca,
0192 workload->ctx_desc.context_id,
0193 workload->ring_context_gpa);
0194
0195
0196
0197
0198
0199
0200
0201 if (s->last_ctx[ring_id].valid &&
0202 (s->last_ctx[ring_id].lrca ==
0203 workload->ctx_desc.lrca) &&
0204 (s->last_ctx[ring_id].ring_context_gpa ==
0205 workload->ring_context_gpa))
0206 skip = true;
0207
0208 s->last_ctx[ring_id].lrca = workload->ctx_desc.lrca;
0209 s->last_ctx[ring_id].ring_context_gpa = workload->ring_context_gpa;
0210
0211 if (IS_RESTORE_INHIBIT(shadow_ring_context->ctx_ctrl.val) || skip)
0212 return 0;
0213
0214 s->last_ctx[ring_id].valid = false;
0215 context_page_num = workload->engine->context_size;
0216 context_page_num = context_page_num >> PAGE_SHIFT;
0217
0218 if (IS_BROADWELL(gvt->gt->i915) && workload->engine->id == RCS0)
0219 context_page_num = 19;
0220
0221
0222
0223
0224 gpa_size = 0;
0225 for (i = 2; i < context_page_num; i++) {
0226 context_gpa = intel_vgpu_gma_to_gpa(vgpu->gtt.ggtt_mm,
0227 (u32)((workload->ctx_desc.lrca + i) <<
0228 I915_GTT_PAGE_SHIFT));
0229 if (context_gpa == INTEL_GVT_INVALID_ADDR) {
0230 gvt_vgpu_err("Invalid guest context descriptor\n");
0231 return -EFAULT;
0232 }
0233
0234 if (gpa_size == 0) {
0235 gpa_base = context_gpa;
0236 dst = context_base + (i << I915_GTT_PAGE_SHIFT);
0237 } else if (context_gpa != gpa_base + gpa_size)
0238 goto read;
0239
0240 gpa_size += I915_GTT_PAGE_SIZE;
0241
0242 if (i == context_page_num - 1)
0243 goto read;
0244
0245 continue;
0246
0247 read:
0248 intel_gvt_read_gpa(vgpu, gpa_base, dst, gpa_size);
0249 gpa_base = context_gpa;
0250 gpa_size = I915_GTT_PAGE_SIZE;
0251 dst = context_base + (i << I915_GTT_PAGE_SHIFT);
0252 }
0253 ret = intel_gvt_scan_engine_context(workload);
0254 if (ret) {
0255 gvt_vgpu_err("invalid cmd found in guest context pages\n");
0256 return ret;
0257 }
0258 s->last_ctx[ring_id].valid = true;
0259 return 0;
0260 }
0261
0262 static inline bool is_gvt_request(struct i915_request *rq)
0263 {
0264 return intel_context_force_single_submission(rq->context);
0265 }
0266
0267 static void save_ring_hw_state(struct intel_vgpu *vgpu,
0268 const struct intel_engine_cs *engine)
0269 {
0270 struct intel_uncore *uncore = engine->uncore;
0271 i915_reg_t reg;
0272
0273 reg = RING_INSTDONE(engine->mmio_base);
0274 vgpu_vreg(vgpu, i915_mmio_reg_offset(reg)) =
0275 intel_uncore_read(uncore, reg);
0276
0277 reg = RING_ACTHD(engine->mmio_base);
0278 vgpu_vreg(vgpu, i915_mmio_reg_offset(reg)) =
0279 intel_uncore_read(uncore, reg);
0280
0281 reg = RING_ACTHD_UDW(engine->mmio_base);
0282 vgpu_vreg(vgpu, i915_mmio_reg_offset(reg)) =
0283 intel_uncore_read(uncore, reg);
0284 }
0285
0286 static int shadow_context_status_change(struct notifier_block *nb,
0287 unsigned long action, void *data)
0288 {
0289 struct i915_request *rq = data;
0290 struct intel_gvt *gvt = container_of(nb, struct intel_gvt,
0291 shadow_ctx_notifier_block[rq->engine->id]);
0292 struct intel_gvt_workload_scheduler *scheduler = &gvt->scheduler;
0293 enum intel_engine_id ring_id = rq->engine->id;
0294 struct intel_vgpu_workload *workload;
0295 unsigned long flags;
0296
0297 if (!is_gvt_request(rq)) {
0298 spin_lock_irqsave(&scheduler->mmio_context_lock, flags);
0299 if (action == INTEL_CONTEXT_SCHEDULE_IN &&
0300 scheduler->engine_owner[ring_id]) {
0301
0302 intel_gvt_switch_mmio(scheduler->engine_owner[ring_id],
0303 NULL, rq->engine);
0304 scheduler->engine_owner[ring_id] = NULL;
0305 }
0306 spin_unlock_irqrestore(&scheduler->mmio_context_lock, flags);
0307
0308 return NOTIFY_OK;
0309 }
0310
0311 workload = scheduler->current_workload[ring_id];
0312 if (unlikely(!workload))
0313 return NOTIFY_OK;
0314
0315 switch (action) {
0316 case INTEL_CONTEXT_SCHEDULE_IN:
0317 spin_lock_irqsave(&scheduler->mmio_context_lock, flags);
0318 if (workload->vgpu != scheduler->engine_owner[ring_id]) {
0319
0320 intel_gvt_switch_mmio(scheduler->engine_owner[ring_id],
0321 workload->vgpu, rq->engine);
0322 scheduler->engine_owner[ring_id] = workload->vgpu;
0323 } else
0324 gvt_dbg_sched("skip ring %d mmio switch for vgpu%d\n",
0325 ring_id, workload->vgpu->id);
0326 spin_unlock_irqrestore(&scheduler->mmio_context_lock, flags);
0327 atomic_set(&workload->shadow_ctx_active, 1);
0328 break;
0329 case INTEL_CONTEXT_SCHEDULE_OUT:
0330 save_ring_hw_state(workload->vgpu, rq->engine);
0331 atomic_set(&workload->shadow_ctx_active, 0);
0332 break;
0333 case INTEL_CONTEXT_SCHEDULE_PREEMPTED:
0334 save_ring_hw_state(workload->vgpu, rq->engine);
0335 break;
0336 default:
0337 WARN_ON(1);
0338 return NOTIFY_OK;
0339 }
0340 wake_up(&workload->shadow_ctx_status_wq);
0341 return NOTIFY_OK;
0342 }
0343
0344 static void
0345 shadow_context_descriptor_update(struct intel_context *ce,
0346 struct intel_vgpu_workload *workload)
0347 {
0348 u64 desc = ce->lrc.desc;
0349
0350
0351
0352
0353
0354 desc &= ~(0x3ull << GEN8_CTX_ADDRESSING_MODE_SHIFT);
0355 desc |= (u64)workload->ctx_desc.addressing_mode <<
0356 GEN8_CTX_ADDRESSING_MODE_SHIFT;
0357
0358 ce->lrc.desc = desc;
0359 }
0360
0361 static int copy_workload_to_ring_buffer(struct intel_vgpu_workload *workload)
0362 {
0363 struct intel_vgpu *vgpu = workload->vgpu;
0364 struct i915_request *req = workload->req;
0365 void *shadow_ring_buffer_va;
0366 u32 *cs;
0367 int err;
0368
0369 if (GRAPHICS_VER(req->engine->i915) == 9 && is_inhibit_context(req->context))
0370 intel_vgpu_restore_inhibit_context(vgpu, req);
0371
0372
0373
0374
0375
0376
0377
0378
0379
0380
0381
0382 if (req->engine->emit_init_breadcrumb) {
0383 err = req->engine->emit_init_breadcrumb(req);
0384 if (err) {
0385 gvt_vgpu_err("fail to emit init breadcrumb\n");
0386 return err;
0387 }
0388 }
0389
0390
0391 cs = intel_ring_begin(workload->req, workload->rb_len / sizeof(u32));
0392 if (IS_ERR(cs)) {
0393 gvt_vgpu_err("fail to alloc size =%ld shadow ring buffer\n",
0394 workload->rb_len);
0395 return PTR_ERR(cs);
0396 }
0397
0398 shadow_ring_buffer_va = workload->shadow_ring_buffer_va;
0399
0400
0401 workload->shadow_ring_buffer_va = cs;
0402
0403 memcpy(cs, shadow_ring_buffer_va,
0404 workload->rb_len);
0405
0406 cs += workload->rb_len / sizeof(u32);
0407 intel_ring_advance(workload->req, cs);
0408
0409 return 0;
0410 }
0411
0412 static void release_shadow_wa_ctx(struct intel_shadow_wa_ctx *wa_ctx)
0413 {
0414 if (!wa_ctx->indirect_ctx.obj)
0415 return;
0416
0417 i915_gem_object_lock(wa_ctx->indirect_ctx.obj, NULL);
0418 i915_gem_object_unpin_map(wa_ctx->indirect_ctx.obj);
0419 i915_gem_object_unlock(wa_ctx->indirect_ctx.obj);
0420 i915_gem_object_put(wa_ctx->indirect_ctx.obj);
0421
0422 wa_ctx->indirect_ctx.obj = NULL;
0423 wa_ctx->indirect_ctx.shadow_va = NULL;
0424 }
0425
0426 static void set_dma_address(struct i915_page_directory *pd, dma_addr_t addr)
0427 {
0428 struct scatterlist *sg = pd->pt.base->mm.pages->sgl;
0429
0430
0431 sg->dma_address = addr;
0432 }
0433
0434 static void set_context_ppgtt_from_shadow(struct intel_vgpu_workload *workload,
0435 struct intel_context *ce)
0436 {
0437 struct intel_vgpu_mm *mm = workload->shadow_mm;
0438 struct i915_ppgtt *ppgtt = i915_vm_to_ppgtt(ce->vm);
0439 int i = 0;
0440
0441 if (mm->ppgtt_mm.root_entry_type == GTT_TYPE_PPGTT_ROOT_L4_ENTRY) {
0442 set_dma_address(ppgtt->pd, mm->ppgtt_mm.shadow_pdps[0]);
0443 } else {
0444 for (i = 0; i < GVT_RING_CTX_NR_PDPS; i++) {
0445 struct i915_page_directory * const pd =
0446 i915_pd_entry(ppgtt->pd, i);
0447
0448
0449
0450 if (!pd)
0451 break;
0452
0453 set_dma_address(pd, mm->ppgtt_mm.shadow_pdps[i]);
0454 }
0455 }
0456 }
0457
0458 static int
0459 intel_gvt_workload_req_alloc(struct intel_vgpu_workload *workload)
0460 {
0461 struct intel_vgpu *vgpu = workload->vgpu;
0462 struct intel_vgpu_submission *s = &vgpu->submission;
0463 struct i915_request *rq;
0464
0465 if (workload->req)
0466 return 0;
0467
0468 rq = i915_request_create(s->shadow[workload->engine->id]);
0469 if (IS_ERR(rq)) {
0470 gvt_vgpu_err("fail to allocate gem request\n");
0471 return PTR_ERR(rq);
0472 }
0473
0474 workload->req = i915_request_get(rq);
0475 return 0;
0476 }
0477
0478
0479
0480
0481
0482
0483
0484
0485
0486 int intel_gvt_scan_and_shadow_workload(struct intel_vgpu_workload *workload)
0487 {
0488 struct intel_vgpu *vgpu = workload->vgpu;
0489 struct intel_vgpu_submission *s = &vgpu->submission;
0490 int ret;
0491
0492 lockdep_assert_held(&vgpu->vgpu_lock);
0493
0494 if (workload->shadow)
0495 return 0;
0496
0497 if (!test_and_set_bit(workload->engine->id, s->shadow_ctx_desc_updated))
0498 shadow_context_descriptor_update(s->shadow[workload->engine->id],
0499 workload);
0500
0501 ret = intel_gvt_scan_and_shadow_ringbuffer(workload);
0502 if (ret)
0503 return ret;
0504
0505 if (workload->engine->id == RCS0 &&
0506 workload->wa_ctx.indirect_ctx.size) {
0507 ret = intel_gvt_scan_and_shadow_wa_ctx(&workload->wa_ctx);
0508 if (ret)
0509 goto err_shadow;
0510 }
0511
0512 workload->shadow = true;
0513 return 0;
0514
0515 err_shadow:
0516 release_shadow_wa_ctx(&workload->wa_ctx);
0517 return ret;
0518 }
0519
0520 static void release_shadow_batch_buffer(struct intel_vgpu_workload *workload);
0521
0522 static int prepare_shadow_batch_buffer(struct intel_vgpu_workload *workload)
0523 {
0524 struct intel_gvt *gvt = workload->vgpu->gvt;
0525 const int gmadr_bytes = gvt->device_info.gmadr_bytes_in_cmd;
0526 struct intel_vgpu_shadow_bb *bb;
0527 struct i915_gem_ww_ctx ww;
0528 int ret;
0529
0530 list_for_each_entry(bb, &workload->shadow_bb, list) {
0531
0532
0533
0534
0535
0536
0537
0538 if (bb->bb_offset)
0539 bb->bb_start_cmd_va = workload->shadow_ring_buffer_va
0540 + bb->bb_offset;
0541
0542
0543
0544
0545
0546
0547
0548
0549
0550
0551 if (!bb->ppgtt) {
0552 i915_gem_ww_ctx_init(&ww, false);
0553 retry:
0554 i915_gem_object_lock(bb->obj, &ww);
0555
0556 bb->vma = i915_gem_object_ggtt_pin_ww(bb->obj, &ww,
0557 NULL, 0, 0, 0);
0558 if (IS_ERR(bb->vma)) {
0559 ret = PTR_ERR(bb->vma);
0560 if (ret == -EDEADLK) {
0561 ret = i915_gem_ww_ctx_backoff(&ww);
0562 if (!ret)
0563 goto retry;
0564 }
0565 goto err;
0566 }
0567
0568
0569 bb->bb_start_cmd_va[1] = i915_ggtt_offset(bb->vma);
0570 if (gmadr_bytes == 8)
0571 bb->bb_start_cmd_va[2] = 0;
0572
0573 ret = i915_vma_move_to_active(bb->vma,
0574 workload->req,
0575 0);
0576 if (ret)
0577 goto err;
0578
0579
0580 i915_gem_object_flush_map(bb->obj);
0581 i915_gem_ww_ctx_fini(&ww);
0582 }
0583 }
0584 return 0;
0585 err:
0586 i915_gem_ww_ctx_fini(&ww);
0587 release_shadow_batch_buffer(workload);
0588 return ret;
0589 }
0590
0591 static void update_wa_ctx_2_shadow_ctx(struct intel_shadow_wa_ctx *wa_ctx)
0592 {
0593 struct intel_vgpu_workload *workload =
0594 container_of(wa_ctx, struct intel_vgpu_workload, wa_ctx);
0595 struct i915_request *rq = workload->req;
0596 struct execlist_ring_context *shadow_ring_context =
0597 (struct execlist_ring_context *)rq->context->lrc_reg_state;
0598
0599 shadow_ring_context->bb_per_ctx_ptr.val =
0600 (shadow_ring_context->bb_per_ctx_ptr.val &
0601 (~PER_CTX_ADDR_MASK)) | wa_ctx->per_ctx.shadow_gma;
0602 shadow_ring_context->rcs_indirect_ctx.val =
0603 (shadow_ring_context->rcs_indirect_ctx.val &
0604 (~INDIRECT_CTX_ADDR_MASK)) | wa_ctx->indirect_ctx.shadow_gma;
0605 }
0606
0607 static int prepare_shadow_wa_ctx(struct intel_shadow_wa_ctx *wa_ctx)
0608 {
0609 struct i915_vma *vma;
0610 unsigned char *per_ctx_va =
0611 (unsigned char *)wa_ctx->indirect_ctx.shadow_va +
0612 wa_ctx->indirect_ctx.size;
0613 struct i915_gem_ww_ctx ww;
0614 int ret;
0615
0616 if (wa_ctx->indirect_ctx.size == 0)
0617 return 0;
0618
0619 i915_gem_ww_ctx_init(&ww, false);
0620 retry:
0621 i915_gem_object_lock(wa_ctx->indirect_ctx.obj, &ww);
0622
0623 vma = i915_gem_object_ggtt_pin_ww(wa_ctx->indirect_ctx.obj, &ww, NULL,
0624 0, CACHELINE_BYTES, 0);
0625 if (IS_ERR(vma)) {
0626 ret = PTR_ERR(vma);
0627 if (ret == -EDEADLK) {
0628 ret = i915_gem_ww_ctx_backoff(&ww);
0629 if (!ret)
0630 goto retry;
0631 }
0632 return ret;
0633 }
0634
0635 i915_gem_ww_ctx_fini(&ww);
0636
0637
0638
0639
0640
0641
0642 wa_ctx->indirect_ctx.shadow_gma = i915_ggtt_offset(vma);
0643
0644 wa_ctx->per_ctx.shadow_gma = *((unsigned int *)per_ctx_va + 1);
0645 memset(per_ctx_va, 0, CACHELINE_BYTES);
0646
0647 update_wa_ctx_2_shadow_ctx(wa_ctx);
0648 return 0;
0649 }
0650
0651 static void update_vreg_in_ctx(struct intel_vgpu_workload *workload)
0652 {
0653 vgpu_vreg_t(workload->vgpu, RING_START(workload->engine->mmio_base)) =
0654 workload->rb_start;
0655 }
0656
0657 static void release_shadow_batch_buffer(struct intel_vgpu_workload *workload)
0658 {
0659 struct intel_vgpu_shadow_bb *bb, *pos;
0660
0661 if (list_empty(&workload->shadow_bb))
0662 return;
0663
0664 bb = list_first_entry(&workload->shadow_bb,
0665 struct intel_vgpu_shadow_bb, list);
0666
0667 list_for_each_entry_safe(bb, pos, &workload->shadow_bb, list) {
0668 if (bb->obj) {
0669 i915_gem_object_lock(bb->obj, NULL);
0670 if (bb->va && !IS_ERR(bb->va))
0671 i915_gem_object_unpin_map(bb->obj);
0672
0673 if (bb->vma && !IS_ERR(bb->vma))
0674 i915_vma_unpin(bb->vma);
0675
0676 i915_gem_object_unlock(bb->obj);
0677 i915_gem_object_put(bb->obj);
0678 }
0679 list_del(&bb->list);
0680 kfree(bb);
0681 }
0682 }
0683
0684 static int
0685 intel_vgpu_shadow_mm_pin(struct intel_vgpu_workload *workload)
0686 {
0687 struct intel_vgpu *vgpu = workload->vgpu;
0688 struct intel_vgpu_mm *m;
0689 int ret = 0;
0690
0691 ret = intel_vgpu_pin_mm(workload->shadow_mm);
0692 if (ret) {
0693 gvt_vgpu_err("fail to vgpu pin mm\n");
0694 return ret;
0695 }
0696
0697 if (workload->shadow_mm->type != INTEL_GVT_MM_PPGTT ||
0698 !workload->shadow_mm->ppgtt_mm.shadowed) {
0699 gvt_vgpu_err("workload shadow ppgtt isn't ready\n");
0700 return -EINVAL;
0701 }
0702
0703 if (!list_empty(&workload->lri_shadow_mm)) {
0704 list_for_each_entry(m, &workload->lri_shadow_mm,
0705 ppgtt_mm.link) {
0706 ret = intel_vgpu_pin_mm(m);
0707 if (ret) {
0708 list_for_each_entry_from_reverse(m,
0709 &workload->lri_shadow_mm,
0710 ppgtt_mm.link)
0711 intel_vgpu_unpin_mm(m);
0712 gvt_vgpu_err("LRI shadow ppgtt fail to pin\n");
0713 break;
0714 }
0715 }
0716 }
0717
0718 if (ret)
0719 intel_vgpu_unpin_mm(workload->shadow_mm);
0720
0721 return ret;
0722 }
0723
0724 static void
0725 intel_vgpu_shadow_mm_unpin(struct intel_vgpu_workload *workload)
0726 {
0727 struct intel_vgpu_mm *m;
0728
0729 if (!list_empty(&workload->lri_shadow_mm)) {
0730 list_for_each_entry(m, &workload->lri_shadow_mm,
0731 ppgtt_mm.link)
0732 intel_vgpu_unpin_mm(m);
0733 }
0734 intel_vgpu_unpin_mm(workload->shadow_mm);
0735 }
0736
0737 static int prepare_workload(struct intel_vgpu_workload *workload)
0738 {
0739 struct intel_vgpu *vgpu = workload->vgpu;
0740 struct intel_vgpu_submission *s = &vgpu->submission;
0741 int ret = 0;
0742
0743 ret = intel_vgpu_shadow_mm_pin(workload);
0744 if (ret) {
0745 gvt_vgpu_err("fail to pin shadow mm\n");
0746 return ret;
0747 }
0748
0749 update_shadow_pdps(workload);
0750
0751 set_context_ppgtt_from_shadow(workload, s->shadow[workload->engine->id]);
0752
0753 ret = intel_vgpu_sync_oos_pages(workload->vgpu);
0754 if (ret) {
0755 gvt_vgpu_err("fail to vgpu sync oos pages\n");
0756 goto err_unpin_mm;
0757 }
0758
0759 ret = intel_vgpu_flush_post_shadow(workload->vgpu);
0760 if (ret) {
0761 gvt_vgpu_err("fail to flush post shadow\n");
0762 goto err_unpin_mm;
0763 }
0764
0765 ret = copy_workload_to_ring_buffer(workload);
0766 if (ret) {
0767 gvt_vgpu_err("fail to generate request\n");
0768 goto err_unpin_mm;
0769 }
0770
0771 ret = prepare_shadow_batch_buffer(workload);
0772 if (ret) {
0773 gvt_vgpu_err("fail to prepare_shadow_batch_buffer\n");
0774 goto err_unpin_mm;
0775 }
0776
0777 ret = prepare_shadow_wa_ctx(&workload->wa_ctx);
0778 if (ret) {
0779 gvt_vgpu_err("fail to prepare_shadow_wa_ctx\n");
0780 goto err_shadow_batch;
0781 }
0782
0783 if (workload->prepare) {
0784 ret = workload->prepare(workload);
0785 if (ret)
0786 goto err_shadow_wa_ctx;
0787 }
0788
0789 return 0;
0790 err_shadow_wa_ctx:
0791 release_shadow_wa_ctx(&workload->wa_ctx);
0792 err_shadow_batch:
0793 release_shadow_batch_buffer(workload);
0794 err_unpin_mm:
0795 intel_vgpu_shadow_mm_unpin(workload);
0796 return ret;
0797 }
0798
0799 static int dispatch_workload(struct intel_vgpu_workload *workload)
0800 {
0801 struct intel_vgpu *vgpu = workload->vgpu;
0802 struct i915_request *rq;
0803 int ret;
0804
0805 gvt_dbg_sched("ring id %s prepare to dispatch workload %p\n",
0806 workload->engine->name, workload);
0807
0808 mutex_lock(&vgpu->vgpu_lock);
0809
0810 ret = intel_gvt_workload_req_alloc(workload);
0811 if (ret)
0812 goto err_req;
0813
0814 ret = intel_gvt_scan_and_shadow_workload(workload);
0815 if (ret)
0816 goto out;
0817
0818 ret = populate_shadow_context(workload);
0819 if (ret) {
0820 release_shadow_wa_ctx(&workload->wa_ctx);
0821 goto out;
0822 }
0823
0824 ret = prepare_workload(workload);
0825 out:
0826 if (ret) {
0827
0828
0829
0830 rq = fetch_and_zero(&workload->req);
0831 i915_request_put(rq);
0832 }
0833
0834 if (!IS_ERR_OR_NULL(workload->req)) {
0835 gvt_dbg_sched("ring id %s submit workload to i915 %p\n",
0836 workload->engine->name, workload->req);
0837 i915_request_add(workload->req);
0838 workload->dispatched = true;
0839 }
0840 err_req:
0841 if (ret)
0842 workload->status = ret;
0843 mutex_unlock(&vgpu->vgpu_lock);
0844 return ret;
0845 }
0846
0847 static struct intel_vgpu_workload *
0848 pick_next_workload(struct intel_gvt *gvt, struct intel_engine_cs *engine)
0849 {
0850 struct intel_gvt_workload_scheduler *scheduler = &gvt->scheduler;
0851 struct intel_vgpu_workload *workload = NULL;
0852
0853 mutex_lock(&gvt->sched_lock);
0854
0855
0856
0857
0858
0859 if (!scheduler->current_vgpu) {
0860 gvt_dbg_sched("ring %s stop - no current vgpu\n", engine->name);
0861 goto out;
0862 }
0863
0864 if (scheduler->need_reschedule) {
0865 gvt_dbg_sched("ring %s stop - will reschedule\n", engine->name);
0866 goto out;
0867 }
0868
0869 if (!scheduler->current_vgpu->active ||
0870 list_empty(workload_q_head(scheduler->current_vgpu, engine)))
0871 goto out;
0872
0873
0874
0875
0876
0877 if (scheduler->current_workload[engine->id]) {
0878 workload = scheduler->current_workload[engine->id];
0879 gvt_dbg_sched("ring %s still have current workload %p\n",
0880 engine->name, workload);
0881 goto out;
0882 }
0883
0884
0885
0886
0887
0888
0889
0890 scheduler->current_workload[engine->id] =
0891 list_first_entry(workload_q_head(scheduler->current_vgpu,
0892 engine),
0893 struct intel_vgpu_workload, list);
0894
0895 workload = scheduler->current_workload[engine->id];
0896
0897 gvt_dbg_sched("ring %s pick new workload %p\n", engine->name, workload);
0898
0899 atomic_inc(&workload->vgpu->submission.running_workload_num);
0900 out:
0901 mutex_unlock(&gvt->sched_lock);
0902 return workload;
0903 }
0904
0905 static void update_guest_pdps(struct intel_vgpu *vgpu,
0906 u64 ring_context_gpa, u32 pdp[8])
0907 {
0908 u64 gpa;
0909 int i;
0910
0911 gpa = ring_context_gpa + RING_CTX_OFF(pdps[0].val);
0912
0913 for (i = 0; i < 8; i++)
0914 intel_gvt_write_gpa(vgpu, gpa + i * 8, &pdp[7 - i], 4);
0915 }
0916
0917 static __maybe_unused bool
0918 check_shadow_context_ppgtt(struct execlist_ring_context *c, struct intel_vgpu_mm *m)
0919 {
0920 if (m->ppgtt_mm.root_entry_type == GTT_TYPE_PPGTT_ROOT_L4_ENTRY) {
0921 u64 shadow_pdp = c->pdps[7].val | (u64) c->pdps[6].val << 32;
0922
0923 if (shadow_pdp != m->ppgtt_mm.shadow_pdps[0]) {
0924 gvt_dbg_mm("4-level context ppgtt not match LRI command\n");
0925 return false;
0926 }
0927 return true;
0928 } else {
0929
0930 gvt_dbg_mm("invalid shadow mm type\n");
0931 return false;
0932 }
0933 }
0934
0935 static void update_guest_context(struct intel_vgpu_workload *workload)
0936 {
0937 struct i915_request *rq = workload->req;
0938 struct intel_vgpu *vgpu = workload->vgpu;
0939 struct execlist_ring_context *shadow_ring_context;
0940 struct intel_context *ctx = workload->req->context;
0941 void *context_base;
0942 void *src;
0943 unsigned long context_gpa, context_page_num;
0944 unsigned long gpa_base;
0945 unsigned long gpa_size;
0946 int i;
0947 u32 ring_base;
0948 u32 head, tail;
0949 u16 wrap_count;
0950
0951 gvt_dbg_sched("ring id %d workload lrca %x\n", rq->engine->id,
0952 workload->ctx_desc.lrca);
0953
0954 GEM_BUG_ON(!intel_context_is_pinned(ctx));
0955
0956 head = workload->rb_head;
0957 tail = workload->rb_tail;
0958 wrap_count = workload->guest_rb_head >> RB_HEAD_WRAP_CNT_OFF;
0959
0960 if (tail < head) {
0961 if (wrap_count == RB_HEAD_WRAP_CNT_MAX)
0962 wrap_count = 0;
0963 else
0964 wrap_count += 1;
0965 }
0966
0967 head = (wrap_count << RB_HEAD_WRAP_CNT_OFF) | tail;
0968
0969 ring_base = rq->engine->mmio_base;
0970 vgpu_vreg_t(vgpu, RING_TAIL(ring_base)) = tail;
0971 vgpu_vreg_t(vgpu, RING_HEAD(ring_base)) = head;
0972
0973 context_page_num = rq->engine->context_size;
0974 context_page_num = context_page_num >> PAGE_SHIFT;
0975
0976 if (IS_BROADWELL(rq->engine->i915) && rq->engine->id == RCS0)
0977 context_page_num = 19;
0978
0979 context_base = (void *) ctx->lrc_reg_state -
0980 (LRC_STATE_PN << I915_GTT_PAGE_SHIFT);
0981
0982
0983
0984
0985 gpa_size = 0;
0986 for (i = 2; i < context_page_num; i++) {
0987 context_gpa = intel_vgpu_gma_to_gpa(vgpu->gtt.ggtt_mm,
0988 (u32)((workload->ctx_desc.lrca + i) <<
0989 I915_GTT_PAGE_SHIFT));
0990 if (context_gpa == INTEL_GVT_INVALID_ADDR) {
0991 gvt_vgpu_err("invalid guest context descriptor\n");
0992 return;
0993 }
0994
0995 if (gpa_size == 0) {
0996 gpa_base = context_gpa;
0997 src = context_base + (i << I915_GTT_PAGE_SHIFT);
0998 } else if (context_gpa != gpa_base + gpa_size)
0999 goto write;
1000
1001 gpa_size += I915_GTT_PAGE_SIZE;
1002
1003 if (i == context_page_num - 1)
1004 goto write;
1005
1006 continue;
1007
1008 write:
1009 intel_gvt_write_gpa(vgpu, gpa_base, src, gpa_size);
1010 gpa_base = context_gpa;
1011 gpa_size = I915_GTT_PAGE_SIZE;
1012 src = context_base + (i << I915_GTT_PAGE_SHIFT);
1013 }
1014
1015 intel_gvt_write_gpa(vgpu, workload->ring_context_gpa +
1016 RING_CTX_OFF(ring_header.val), &workload->rb_tail, 4);
1017
1018 shadow_ring_context = (void *) ctx->lrc_reg_state;
1019
1020 if (!list_empty(&workload->lri_shadow_mm)) {
1021 struct intel_vgpu_mm *m = list_last_entry(&workload->lri_shadow_mm,
1022 struct intel_vgpu_mm,
1023 ppgtt_mm.link);
1024 GEM_BUG_ON(!check_shadow_context_ppgtt(shadow_ring_context, m));
1025 update_guest_pdps(vgpu, workload->ring_context_gpa,
1026 (void *)m->ppgtt_mm.guest_pdps);
1027 }
1028
1029 #define COPY_REG(name) \
1030 intel_gvt_write_gpa(vgpu, workload->ring_context_gpa + \
1031 RING_CTX_OFF(name.val), &shadow_ring_context->name.val, 4)
1032
1033 COPY_REG(ctx_ctrl);
1034 COPY_REG(ctx_timestamp);
1035
1036 #undef COPY_REG
1037
1038 intel_gvt_write_gpa(vgpu,
1039 workload->ring_context_gpa +
1040 sizeof(*shadow_ring_context),
1041 (void *)shadow_ring_context +
1042 sizeof(*shadow_ring_context),
1043 I915_GTT_PAGE_SIZE - sizeof(*shadow_ring_context));
1044 }
1045
1046 void intel_vgpu_clean_workloads(struct intel_vgpu *vgpu,
1047 intel_engine_mask_t engine_mask)
1048 {
1049 struct intel_vgpu_submission *s = &vgpu->submission;
1050 struct intel_engine_cs *engine;
1051 struct intel_vgpu_workload *pos, *n;
1052 intel_engine_mask_t tmp;
1053
1054
1055 for_each_engine_masked(engine, vgpu->gvt->gt, engine_mask, tmp) {
1056 list_for_each_entry_safe(pos, n,
1057 &s->workload_q_head[engine->id], list) {
1058 list_del_init(&pos->list);
1059 intel_vgpu_destroy_workload(pos);
1060 }
1061 clear_bit(engine->id, s->shadow_ctx_desc_updated);
1062 }
1063 }
1064
1065 static void complete_current_workload(struct intel_gvt *gvt, int ring_id)
1066 {
1067 struct intel_gvt_workload_scheduler *scheduler = &gvt->scheduler;
1068 struct intel_vgpu_workload *workload =
1069 scheduler->current_workload[ring_id];
1070 struct intel_vgpu *vgpu = workload->vgpu;
1071 struct intel_vgpu_submission *s = &vgpu->submission;
1072 struct i915_request *rq = workload->req;
1073 int event;
1074
1075 mutex_lock(&vgpu->vgpu_lock);
1076 mutex_lock(&gvt->sched_lock);
1077
1078
1079
1080
1081
1082 if (rq) {
1083 wait_event(workload->shadow_ctx_status_wq,
1084 !atomic_read(&workload->shadow_ctx_active));
1085
1086
1087
1088
1089
1090
1091 if (likely(workload->status == -EINPROGRESS)) {
1092 if (workload->req->fence.error == -EIO)
1093 workload->status = -EIO;
1094 else
1095 workload->status = 0;
1096 }
1097
1098 if (!workload->status &&
1099 !(vgpu->resetting_eng & BIT(ring_id))) {
1100 update_guest_context(workload);
1101
1102 for_each_set_bit(event, workload->pending_events,
1103 INTEL_GVT_EVENT_MAX)
1104 intel_vgpu_trigger_virtual_event(vgpu, event);
1105 }
1106
1107 i915_request_put(fetch_and_zero(&workload->req));
1108 }
1109
1110 gvt_dbg_sched("ring id %d complete workload %p status %d\n",
1111 ring_id, workload, workload->status);
1112
1113 scheduler->current_workload[ring_id] = NULL;
1114
1115 list_del_init(&workload->list);
1116
1117 if (workload->status || vgpu->resetting_eng & BIT(ring_id)) {
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131 intel_vgpu_clean_workloads(vgpu, BIT(ring_id));
1132 }
1133
1134 workload->complete(workload);
1135
1136 intel_vgpu_shadow_mm_unpin(workload);
1137 intel_vgpu_destroy_workload(workload);
1138
1139 atomic_dec(&s->running_workload_num);
1140 wake_up(&scheduler->workload_complete_wq);
1141
1142 if (gvt->scheduler.need_reschedule)
1143 intel_gvt_request_service(gvt, INTEL_GVT_REQUEST_EVENT_SCHED);
1144
1145 mutex_unlock(&gvt->sched_lock);
1146 mutex_unlock(&vgpu->vgpu_lock);
1147 }
1148
1149 static int workload_thread(void *arg)
1150 {
1151 struct intel_engine_cs *engine = arg;
1152 const bool need_force_wake = GRAPHICS_VER(engine->i915) >= 9;
1153 struct intel_gvt *gvt = engine->i915->gvt;
1154 struct intel_gvt_workload_scheduler *scheduler = &gvt->scheduler;
1155 struct intel_vgpu_workload *workload = NULL;
1156 struct intel_vgpu *vgpu = NULL;
1157 int ret;
1158 DEFINE_WAIT_FUNC(wait, woken_wake_function);
1159
1160 gvt_dbg_core("workload thread for ring %s started\n", engine->name);
1161
1162 while (!kthread_should_stop()) {
1163 intel_wakeref_t wakeref;
1164
1165 add_wait_queue(&scheduler->waitq[engine->id], &wait);
1166 do {
1167 workload = pick_next_workload(gvt, engine);
1168 if (workload)
1169 break;
1170 wait_woken(&wait, TASK_INTERRUPTIBLE,
1171 MAX_SCHEDULE_TIMEOUT);
1172 } while (!kthread_should_stop());
1173 remove_wait_queue(&scheduler->waitq[engine->id], &wait);
1174
1175 if (!workload)
1176 break;
1177
1178 gvt_dbg_sched("ring %s next workload %p vgpu %d\n",
1179 engine->name, workload,
1180 workload->vgpu->id);
1181
1182 wakeref = intel_runtime_pm_get(engine->uncore->rpm);
1183
1184 gvt_dbg_sched("ring %s will dispatch workload %p\n",
1185 engine->name, workload);
1186
1187 if (need_force_wake)
1188 intel_uncore_forcewake_get(engine->uncore,
1189 FORCEWAKE_ALL);
1190
1191
1192
1193
1194
1195
1196 update_vreg_in_ctx(workload);
1197
1198 ret = dispatch_workload(workload);
1199
1200 if (ret) {
1201 vgpu = workload->vgpu;
1202 gvt_vgpu_err("fail to dispatch workload, skip\n");
1203 goto complete;
1204 }
1205
1206 gvt_dbg_sched("ring %s wait workload %p\n",
1207 engine->name, workload);
1208 i915_request_wait(workload->req, 0, MAX_SCHEDULE_TIMEOUT);
1209
1210 complete:
1211 gvt_dbg_sched("will complete workload %p, status: %d\n",
1212 workload, workload->status);
1213
1214 complete_current_workload(gvt, engine->id);
1215
1216 if (need_force_wake)
1217 intel_uncore_forcewake_put(engine->uncore,
1218 FORCEWAKE_ALL);
1219
1220 intel_runtime_pm_put(engine->uncore->rpm, wakeref);
1221 if (ret && (vgpu_is_vm_unhealthy(ret)))
1222 enter_failsafe_mode(vgpu, GVT_FAILSAFE_GUEST_ERR);
1223 }
1224 return 0;
1225 }
1226
1227 void intel_gvt_wait_vgpu_idle(struct intel_vgpu *vgpu)
1228 {
1229 struct intel_vgpu_submission *s = &vgpu->submission;
1230 struct intel_gvt *gvt = vgpu->gvt;
1231 struct intel_gvt_workload_scheduler *scheduler = &gvt->scheduler;
1232
1233 if (atomic_read(&s->running_workload_num)) {
1234 gvt_dbg_sched("wait vgpu idle\n");
1235
1236 wait_event(scheduler->workload_complete_wq,
1237 !atomic_read(&s->running_workload_num));
1238 }
1239 }
1240
1241 void intel_gvt_clean_workload_scheduler(struct intel_gvt *gvt)
1242 {
1243 struct intel_gvt_workload_scheduler *scheduler = &gvt->scheduler;
1244 struct intel_engine_cs *engine;
1245 enum intel_engine_id i;
1246
1247 gvt_dbg_core("clean workload scheduler\n");
1248
1249 for_each_engine(engine, gvt->gt, i) {
1250 atomic_notifier_chain_unregister(
1251 &engine->context_status_notifier,
1252 &gvt->shadow_ctx_notifier_block[i]);
1253 kthread_stop(scheduler->thread[i]);
1254 }
1255 }
1256
1257 int intel_gvt_init_workload_scheduler(struct intel_gvt *gvt)
1258 {
1259 struct intel_gvt_workload_scheduler *scheduler = &gvt->scheduler;
1260 struct intel_engine_cs *engine;
1261 enum intel_engine_id i;
1262 int ret;
1263
1264 gvt_dbg_core("init workload scheduler\n");
1265
1266 init_waitqueue_head(&scheduler->workload_complete_wq);
1267
1268 for_each_engine(engine, gvt->gt, i) {
1269 init_waitqueue_head(&scheduler->waitq[i]);
1270
1271 scheduler->thread[i] = kthread_run(workload_thread, engine,
1272 "gvt:%s", engine->name);
1273 if (IS_ERR(scheduler->thread[i])) {
1274 gvt_err("fail to create workload thread\n");
1275 ret = PTR_ERR(scheduler->thread[i]);
1276 goto err;
1277 }
1278
1279 gvt->shadow_ctx_notifier_block[i].notifier_call =
1280 shadow_context_status_change;
1281 atomic_notifier_chain_register(&engine->context_status_notifier,
1282 &gvt->shadow_ctx_notifier_block[i]);
1283 }
1284
1285 return 0;
1286
1287 err:
1288 intel_gvt_clean_workload_scheduler(gvt);
1289 return ret;
1290 }
1291
1292 static void
1293 i915_context_ppgtt_root_restore(struct intel_vgpu_submission *s,
1294 struct i915_ppgtt *ppgtt)
1295 {
1296 int i;
1297
1298 if (i915_vm_is_4lvl(&ppgtt->vm)) {
1299 set_dma_address(ppgtt->pd, s->i915_context_pml4);
1300 } else {
1301 for (i = 0; i < GEN8_3LVL_PDPES; i++) {
1302 struct i915_page_directory * const pd =
1303 i915_pd_entry(ppgtt->pd, i);
1304
1305 set_dma_address(pd, s->i915_context_pdps[i]);
1306 }
1307 }
1308 }
1309
1310
1311
1312
1313
1314
1315
1316
1317 void intel_vgpu_clean_submission(struct intel_vgpu *vgpu)
1318 {
1319 struct intel_vgpu_submission *s = &vgpu->submission;
1320 struct intel_engine_cs *engine;
1321 enum intel_engine_id id;
1322
1323 intel_vgpu_select_submission_ops(vgpu, ALL_ENGINES, 0);
1324
1325 i915_context_ppgtt_root_restore(s, i915_vm_to_ppgtt(s->shadow[0]->vm));
1326 for_each_engine(engine, vgpu->gvt->gt, id)
1327 intel_context_put(s->shadow[id]);
1328
1329 kmem_cache_destroy(s->workloads);
1330 }
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341 void intel_vgpu_reset_submission(struct intel_vgpu *vgpu,
1342 intel_engine_mask_t engine_mask)
1343 {
1344 struct intel_vgpu_submission *s = &vgpu->submission;
1345
1346 if (!s->active)
1347 return;
1348
1349 intel_vgpu_clean_workloads(vgpu, engine_mask);
1350 s->ops->reset(vgpu, engine_mask);
1351 }
1352
1353 static void
1354 i915_context_ppgtt_root_save(struct intel_vgpu_submission *s,
1355 struct i915_ppgtt *ppgtt)
1356 {
1357 int i;
1358
1359 if (i915_vm_is_4lvl(&ppgtt->vm)) {
1360 s->i915_context_pml4 = px_dma(ppgtt->pd);
1361 } else {
1362 for (i = 0; i < GEN8_3LVL_PDPES; i++) {
1363 struct i915_page_directory * const pd =
1364 i915_pd_entry(ppgtt->pd, i);
1365
1366 s->i915_context_pdps[i] = px_dma(pd);
1367 }
1368 }
1369 }
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381 int intel_vgpu_setup_submission(struct intel_vgpu *vgpu)
1382 {
1383 struct drm_i915_private *i915 = vgpu->gvt->gt->i915;
1384 struct intel_vgpu_submission *s = &vgpu->submission;
1385 struct intel_engine_cs *engine;
1386 struct i915_ppgtt *ppgtt;
1387 enum intel_engine_id i;
1388 int ret;
1389
1390 ppgtt = i915_ppgtt_create(to_gt(i915), I915_BO_ALLOC_PM_EARLY);
1391 if (IS_ERR(ppgtt))
1392 return PTR_ERR(ppgtt);
1393
1394 i915_context_ppgtt_root_save(s, ppgtt);
1395
1396 for_each_engine(engine, vgpu->gvt->gt, i) {
1397 struct intel_context *ce;
1398
1399 INIT_LIST_HEAD(&s->workload_q_head[i]);
1400 s->shadow[i] = ERR_PTR(-EINVAL);
1401
1402 ce = intel_context_create(engine);
1403 if (IS_ERR(ce)) {
1404 ret = PTR_ERR(ce);
1405 goto out_shadow_ctx;
1406 }
1407
1408 i915_vm_put(ce->vm);
1409 ce->vm = i915_vm_get(&ppgtt->vm);
1410 intel_context_set_single_submission(ce);
1411
1412
1413 if (!intel_uc_wants_guc_submission(&engine->gt->uc))
1414 ce->ring_size = SZ_2M;
1415
1416 s->shadow[i] = ce;
1417 }
1418
1419 bitmap_zero(s->shadow_ctx_desc_updated, I915_NUM_ENGINES);
1420
1421 s->workloads = kmem_cache_create_usercopy("gvt-g_vgpu_workload",
1422 sizeof(struct intel_vgpu_workload), 0,
1423 SLAB_HWCACHE_ALIGN,
1424 offsetof(struct intel_vgpu_workload, rb_tail),
1425 sizeof_field(struct intel_vgpu_workload, rb_tail),
1426 NULL);
1427
1428 if (!s->workloads) {
1429 ret = -ENOMEM;
1430 goto out_shadow_ctx;
1431 }
1432
1433 atomic_set(&s->running_workload_num, 0);
1434 bitmap_zero(s->tlb_handle_pending, I915_NUM_ENGINES);
1435
1436 memset(s->last_ctx, 0, sizeof(s->last_ctx));
1437
1438 i915_vm_put(&ppgtt->vm);
1439 return 0;
1440
1441 out_shadow_ctx:
1442 i915_context_ppgtt_root_restore(s, ppgtt);
1443 for_each_engine(engine, vgpu->gvt->gt, i) {
1444 if (IS_ERR(s->shadow[i]))
1445 break;
1446
1447 intel_context_put(s->shadow[i]);
1448 }
1449 i915_vm_put(&ppgtt->vm);
1450 return ret;
1451 }
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465 int intel_vgpu_select_submission_ops(struct intel_vgpu *vgpu,
1466 intel_engine_mask_t engine_mask,
1467 unsigned int interface)
1468 {
1469 struct drm_i915_private *i915 = vgpu->gvt->gt->i915;
1470 struct intel_vgpu_submission *s = &vgpu->submission;
1471 const struct intel_vgpu_submission_ops *ops[] = {
1472 [INTEL_VGPU_EXECLIST_SUBMISSION] =
1473 &intel_vgpu_execlist_submission_ops,
1474 };
1475 int ret;
1476
1477 if (drm_WARN_ON(&i915->drm, interface >= ARRAY_SIZE(ops)))
1478 return -EINVAL;
1479
1480 if (drm_WARN_ON(&i915->drm,
1481 interface == 0 && engine_mask != ALL_ENGINES))
1482 return -EINVAL;
1483
1484 if (s->active)
1485 s->ops->clean(vgpu, engine_mask);
1486
1487 if (interface == 0) {
1488 s->ops = NULL;
1489 s->virtual_submission_interface = 0;
1490 s->active = false;
1491 gvt_dbg_core("vgpu%d: remove submission ops\n", vgpu->id);
1492 return 0;
1493 }
1494
1495 ret = ops[interface]->init(vgpu, engine_mask);
1496 if (ret)
1497 return ret;
1498
1499 s->ops = ops[interface];
1500 s->virtual_submission_interface = interface;
1501 s->active = true;
1502
1503 gvt_dbg_core("vgpu%d: activate ops [ %s ]\n",
1504 vgpu->id, s->ops->name);
1505
1506 return 0;
1507 }
1508
1509
1510
1511
1512
1513
1514
1515
1516 void intel_vgpu_destroy_workload(struct intel_vgpu_workload *workload)
1517 {
1518 struct intel_vgpu_submission *s = &workload->vgpu->submission;
1519
1520 intel_context_unpin(s->shadow[workload->engine->id]);
1521 release_shadow_batch_buffer(workload);
1522 release_shadow_wa_ctx(&workload->wa_ctx);
1523
1524 if (!list_empty(&workload->lri_shadow_mm)) {
1525 struct intel_vgpu_mm *m, *mm;
1526 list_for_each_entry_safe(m, mm, &workload->lri_shadow_mm,
1527 ppgtt_mm.link) {
1528 list_del(&m->ppgtt_mm.link);
1529 intel_vgpu_mm_put(m);
1530 }
1531 }
1532
1533 GEM_BUG_ON(!list_empty(&workload->lri_shadow_mm));
1534 if (workload->shadow_mm)
1535 intel_vgpu_mm_put(workload->shadow_mm);
1536
1537 kmem_cache_free(s->workloads, workload);
1538 }
1539
1540 static struct intel_vgpu_workload *
1541 alloc_workload(struct intel_vgpu *vgpu)
1542 {
1543 struct intel_vgpu_submission *s = &vgpu->submission;
1544 struct intel_vgpu_workload *workload;
1545
1546 workload = kmem_cache_zalloc(s->workloads, GFP_KERNEL);
1547 if (!workload)
1548 return ERR_PTR(-ENOMEM);
1549
1550 INIT_LIST_HEAD(&workload->list);
1551 INIT_LIST_HEAD(&workload->shadow_bb);
1552 INIT_LIST_HEAD(&workload->lri_shadow_mm);
1553
1554 init_waitqueue_head(&workload->shadow_ctx_status_wq);
1555 atomic_set(&workload->shadow_ctx_active, 0);
1556
1557 workload->status = -EINPROGRESS;
1558 workload->vgpu = vgpu;
1559
1560 return workload;
1561 }
1562
1563 #define RING_CTX_OFF(x) \
1564 offsetof(struct execlist_ring_context, x)
1565
1566 static void read_guest_pdps(struct intel_vgpu *vgpu,
1567 u64 ring_context_gpa, u32 pdp[8])
1568 {
1569 u64 gpa;
1570 int i;
1571
1572 gpa = ring_context_gpa + RING_CTX_OFF(pdps[0].val);
1573
1574 for (i = 0; i < 8; i++)
1575 intel_gvt_read_gpa(vgpu,
1576 gpa + i * 8, &pdp[7 - i], 4);
1577 }
1578
1579 static int prepare_mm(struct intel_vgpu_workload *workload)
1580 {
1581 struct execlist_ctx_descriptor_format *desc = &workload->ctx_desc;
1582 struct intel_vgpu_mm *mm;
1583 struct intel_vgpu *vgpu = workload->vgpu;
1584 enum intel_gvt_gtt_type root_entry_type;
1585 u64 pdps[GVT_RING_CTX_NR_PDPS];
1586
1587 switch (desc->addressing_mode) {
1588 case 1:
1589 root_entry_type = GTT_TYPE_PPGTT_ROOT_L3_ENTRY;
1590 break;
1591 case 3:
1592 root_entry_type = GTT_TYPE_PPGTT_ROOT_L4_ENTRY;
1593 break;
1594 default:
1595 gvt_vgpu_err("Advanced Context mode(SVM) is not supported!\n");
1596 return -EINVAL;
1597 }
1598
1599 read_guest_pdps(workload->vgpu, workload->ring_context_gpa, (void *)pdps);
1600
1601 mm = intel_vgpu_get_ppgtt_mm(workload->vgpu, root_entry_type, pdps);
1602 if (IS_ERR(mm))
1603 return PTR_ERR(mm);
1604
1605 workload->shadow_mm = mm;
1606 return 0;
1607 }
1608
1609 #define same_context(a, b) (((a)->context_id == (b)->context_id) && \
1610 ((a)->lrca == (b)->lrca))
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625 struct intel_vgpu_workload *
1626 intel_vgpu_create_workload(struct intel_vgpu *vgpu,
1627 const struct intel_engine_cs *engine,
1628 struct execlist_ctx_descriptor_format *desc)
1629 {
1630 struct intel_vgpu_submission *s = &vgpu->submission;
1631 struct list_head *q = workload_q_head(vgpu, engine);
1632 struct intel_vgpu_workload *last_workload = NULL;
1633 struct intel_vgpu_workload *workload = NULL;
1634 u64 ring_context_gpa;
1635 u32 head, tail, start, ctl, ctx_ctl, per_ctx, indirect_ctx;
1636 u32 guest_head;
1637 int ret;
1638
1639 ring_context_gpa = intel_vgpu_gma_to_gpa(vgpu->gtt.ggtt_mm,
1640 (u32)((desc->lrca + 1) << I915_GTT_PAGE_SHIFT));
1641 if (ring_context_gpa == INTEL_GVT_INVALID_ADDR) {
1642 gvt_vgpu_err("invalid guest context LRCA: %x\n", desc->lrca);
1643 return ERR_PTR(-EINVAL);
1644 }
1645
1646 intel_gvt_read_gpa(vgpu, ring_context_gpa +
1647 RING_CTX_OFF(ring_header.val), &head, 4);
1648
1649 intel_gvt_read_gpa(vgpu, ring_context_gpa +
1650 RING_CTX_OFF(ring_tail.val), &tail, 4);
1651
1652 guest_head = head;
1653
1654 head &= RB_HEAD_OFF_MASK;
1655 tail &= RB_TAIL_OFF_MASK;
1656
1657 list_for_each_entry_reverse(last_workload, q, list) {
1658
1659 if (same_context(&last_workload->ctx_desc, desc)) {
1660 gvt_dbg_el("ring %s cur workload == last\n",
1661 engine->name);
1662 gvt_dbg_el("ctx head %x real head %lx\n", head,
1663 last_workload->rb_tail);
1664
1665
1666
1667
1668 head = last_workload->rb_tail;
1669 break;
1670 }
1671 }
1672
1673 gvt_dbg_el("ring %s begin a new workload\n", engine->name);
1674
1675
1676 intel_gvt_read_gpa(vgpu, ring_context_gpa +
1677 RING_CTX_OFF(rb_start.val), &start, 4);
1678 intel_gvt_read_gpa(vgpu, ring_context_gpa +
1679 RING_CTX_OFF(rb_ctrl.val), &ctl, 4);
1680 intel_gvt_read_gpa(vgpu, ring_context_gpa +
1681 RING_CTX_OFF(ctx_ctrl.val), &ctx_ctl, 4);
1682
1683 if (!intel_gvt_ggtt_validate_range(vgpu, start,
1684 _RING_CTL_BUF_SIZE(ctl))) {
1685 gvt_vgpu_err("context contain invalid rb at: 0x%x\n", start);
1686 return ERR_PTR(-EINVAL);
1687 }
1688
1689 workload = alloc_workload(vgpu);
1690 if (IS_ERR(workload))
1691 return workload;
1692
1693 workload->engine = engine;
1694 workload->ctx_desc = *desc;
1695 workload->ring_context_gpa = ring_context_gpa;
1696 workload->rb_head = head;
1697 workload->guest_rb_head = guest_head;
1698 workload->rb_tail = tail;
1699 workload->rb_start = start;
1700 workload->rb_ctl = ctl;
1701
1702 if (engine->id == RCS0) {
1703 intel_gvt_read_gpa(vgpu, ring_context_gpa +
1704 RING_CTX_OFF(bb_per_ctx_ptr.val), &per_ctx, 4);
1705 intel_gvt_read_gpa(vgpu, ring_context_gpa +
1706 RING_CTX_OFF(rcs_indirect_ctx.val), &indirect_ctx, 4);
1707
1708 workload->wa_ctx.indirect_ctx.guest_gma =
1709 indirect_ctx & INDIRECT_CTX_ADDR_MASK;
1710 workload->wa_ctx.indirect_ctx.size =
1711 (indirect_ctx & INDIRECT_CTX_SIZE_MASK) *
1712 CACHELINE_BYTES;
1713
1714 if (workload->wa_ctx.indirect_ctx.size != 0) {
1715 if (!intel_gvt_ggtt_validate_range(vgpu,
1716 workload->wa_ctx.indirect_ctx.guest_gma,
1717 workload->wa_ctx.indirect_ctx.size)) {
1718 gvt_vgpu_err("invalid wa_ctx at: 0x%lx\n",
1719 workload->wa_ctx.indirect_ctx.guest_gma);
1720 kmem_cache_free(s->workloads, workload);
1721 return ERR_PTR(-EINVAL);
1722 }
1723 }
1724
1725 workload->wa_ctx.per_ctx.guest_gma =
1726 per_ctx & PER_CTX_ADDR_MASK;
1727 workload->wa_ctx.per_ctx.valid = per_ctx & 1;
1728 if (workload->wa_ctx.per_ctx.valid) {
1729 if (!intel_gvt_ggtt_validate_range(vgpu,
1730 workload->wa_ctx.per_ctx.guest_gma,
1731 CACHELINE_BYTES)) {
1732 gvt_vgpu_err("invalid per_ctx at: 0x%lx\n",
1733 workload->wa_ctx.per_ctx.guest_gma);
1734 kmem_cache_free(s->workloads, workload);
1735 return ERR_PTR(-EINVAL);
1736 }
1737 }
1738 }
1739
1740 gvt_dbg_el("workload %p ring %s head %x tail %x start %x ctl %x\n",
1741 workload, engine->name, head, tail, start, ctl);
1742
1743 ret = prepare_mm(workload);
1744 if (ret) {
1745 kmem_cache_free(s->workloads, workload);
1746 return ERR_PTR(ret);
1747 }
1748
1749
1750
1751
1752 if (list_empty(q)) {
1753 intel_wakeref_t wakeref;
1754
1755 with_intel_runtime_pm(engine->gt->uncore->rpm, wakeref)
1756 ret = intel_gvt_scan_and_shadow_workload(workload);
1757 }
1758
1759 if (ret) {
1760 if (vgpu_is_vm_unhealthy(ret))
1761 enter_failsafe_mode(vgpu, GVT_FAILSAFE_GUEST_ERR);
1762 intel_vgpu_destroy_workload(workload);
1763 return ERR_PTR(ret);
1764 }
1765
1766 ret = intel_context_pin(s->shadow[engine->id]);
1767 if (ret) {
1768 intel_vgpu_destroy_workload(workload);
1769 return ERR_PTR(ret);
1770 }
1771
1772 return workload;
1773 }
1774
1775
1776
1777
1778
1779 void intel_vgpu_queue_workload(struct intel_vgpu_workload *workload)
1780 {
1781 list_add_tail(&workload->list,
1782 workload_q_head(workload->vgpu, workload->engine));
1783 intel_gvt_kick_schedule(workload->vgpu->gvt);
1784 wake_up(&workload->vgpu->gvt->scheduler.waitq[workload->engine->id]);
1785 }