Skip to content

Commit b4eec0f

Browse files
committed
Merge tag 'drm-intel-next-fixes-2018-03-22' of git://anongit.freedesktop.org/drm/drm-intel into drm-next
GVT regression fix that caused guest VM GPU hang. Fix for race conditions in declaring GPU wedged (hit in CI). * tag 'drm-intel-next-fixes-2018-03-22' of git://anongit.freedesktop.org/drm/drm-intel: drm/i915/gvt: force to set all context control bits from guest drm/i915/gvt: Update PDPs after a vGPU mm object is pinned. drm/i915/gvt: Invalidate vGPU PPGTT mm objects during a vGPU reset. drm/i915/kvmgt: Handle kzalloc failure drm/i915/gvt: fix spelling mistake: "destoried" -> "destroyed" drm/i915/gvt: Remove reduntant printing of untracked mmio drm/i915/pmu: Work around compiler warnings on some kernel configs drm/i915: Only call tasklet_kill() on the first prepare_reset drm/i915: Wrap engine->schedule in RCU locks for set-wedge protection drm/i915/icl: do not save DDI A/E sharing bit for ICL
2 parents 2a2553c + 8c5cb3c commit b4eec0f

File tree

10 files changed

+119
-41
lines changed

10 files changed

+119
-41
lines changed

drivers/gpu/drm/i915/gvt/gtt.c

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2046,7 +2046,7 @@ static void intel_vgpu_destroy_all_ppgtt_mm(struct intel_vgpu *vgpu)
20462046
}
20472047

20482048
if (GEM_WARN_ON(!list_empty(&vgpu->gtt.ppgtt_mm_list_head)))
2049-
gvt_err("vgpu ppgtt mm is not fully destoried\n");
2049+
gvt_err("vgpu ppgtt mm is not fully destroyed\n");
20502050

20512051
if (GEM_WARN_ON(!radix_tree_empty(&vgpu->gtt.spt_tree))) {
20522052
gvt_err("Why we still has spt not freed?\n");
@@ -2290,6 +2290,28 @@ void intel_gvt_clean_gtt(struct intel_gvt *gvt)
22902290
clean_spt_oos(gvt);
22912291
}
22922292

2293+
/**
2294+
* intel_vgpu_invalidate_ppgtt - invalidate PPGTT instances
2295+
* @vgpu: a vGPU
2296+
*
2297+
* This function is called when invalidate all PPGTT instances of a vGPU.
2298+
*
2299+
*/
2300+
void intel_vgpu_invalidate_ppgtt(struct intel_vgpu *vgpu)
2301+
{
2302+
struct list_head *pos, *n;
2303+
struct intel_vgpu_mm *mm;
2304+
2305+
list_for_each_safe(pos, n, &vgpu->gtt.ppgtt_mm_list_head) {
2306+
mm = container_of(pos, struct intel_vgpu_mm, ppgtt_mm.list);
2307+
if (mm->type == INTEL_GVT_MM_PPGTT) {
2308+
list_del_init(&mm->ppgtt_mm.lru_list);
2309+
if (mm->ppgtt_mm.shadowed)
2310+
invalidate_ppgtt_mm(mm);
2311+
}
2312+
}
2313+
}
2314+
22932315
/**
22942316
* intel_vgpu_reset_ggtt - reset the GGTT entry
22952317
* @vgpu: a vGPU

drivers/gpu/drm/i915/gvt/gtt.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,7 @@ struct intel_vgpu_gtt {
194194
extern int intel_vgpu_init_gtt(struct intel_vgpu *vgpu);
195195
extern void intel_vgpu_clean_gtt(struct intel_vgpu *vgpu);
196196
void intel_vgpu_reset_ggtt(struct intel_vgpu *vgpu);
197+
void intel_vgpu_invalidate_ppgtt(struct intel_vgpu *vgpu);
197198

198199
extern int intel_gvt_init_gtt(struct intel_gvt *gvt);
199200
void intel_vgpu_reset_gtt(struct intel_vgpu *vgpu);

drivers/gpu/drm/i915/gvt/handlers.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1767,6 +1767,10 @@ static int init_generic_mmio_info(struct intel_gvt *gvt)
17671767
MMIO_D(CURBASE(PIPE_B), D_ALL);
17681768
MMIO_D(CURBASE(PIPE_C), D_ALL);
17691769

1770+
MMIO_D(CUR_FBC_CTL(PIPE_A), D_ALL);
1771+
MMIO_D(CUR_FBC_CTL(PIPE_B), D_ALL);
1772+
MMIO_D(CUR_FBC_CTL(PIPE_C), D_ALL);
1773+
17701774
MMIO_D(_MMIO(0x700ac), D_ALL);
17711775
MMIO_D(_MMIO(0x710ac), D_ALL);
17721776
MMIO_D(_MMIO(0x720ac), D_ALL);
@@ -2228,6 +2232,7 @@ static int init_generic_mmio_info(struct intel_gvt *gvt)
22282232

22292233
MMIO_D(HSW_AUD_CFG(PIPE_A), D_ALL);
22302234
MMIO_D(HSW_AUD_PIN_ELD_CP_VLD, D_ALL);
2235+
MMIO_D(HSW_AUD_MISC_CTRL(PIPE_A), D_ALL);
22312236

22322237
MMIO_DH(_MMIO(_TRANS_DDI_FUNC_CTL_A), D_ALL, NULL, NULL);
22332238
MMIO_DH(_MMIO(_TRANS_DDI_FUNC_CTL_B), D_ALL, NULL, NULL);
@@ -2559,6 +2564,7 @@ static int init_broadwell_mmio_info(struct intel_gvt *gvt)
25592564
MMIO_D(WM_MISC, D_BDW);
25602565
MMIO_D(_MMIO(BDW_EDP_PSR_BASE), D_BDW);
25612566

2567+
MMIO_D(_MMIO(0x6671c), D_BDW_PLUS);
25622568
MMIO_D(_MMIO(0x66c00), D_BDW_PLUS);
25632569
MMIO_D(_MMIO(0x66c04), D_BDW_PLUS);
25642570

@@ -2787,6 +2793,7 @@ static int init_skl_mmio_info(struct intel_gvt *gvt)
27872793
MMIO_D(_MMIO(0x70380), D_SKL_PLUS);
27882794
MMIO_D(_MMIO(0x71380), D_SKL_PLUS);
27892795
MMIO_D(_MMIO(0x72380), D_SKL_PLUS);
2796+
MMIO_D(_MMIO(0x7239c), D_SKL_PLUS);
27902797
MMIO_D(_MMIO(0x7039c), D_SKL_PLUS);
27912798

27922799
MMIO_D(_MMIO(0x8f074), D_SKL | D_KBL);
@@ -2801,7 +2808,9 @@ static int init_skl_mmio_info(struct intel_gvt *gvt)
28012808
MMIO_F(_MMIO(0xc800), 0x7f8, F_CMD_ACCESS, 0, 0, D_SKL | D_KBL, NULL, NULL);
28022809
MMIO_F(_MMIO(0xb020), 0x80, F_CMD_ACCESS, 0, 0, D_SKL | D_KBL, NULL, NULL);
28032810

2811+
MMIO_D(RPM_CONFIG0, D_SKL_PLUS);
28042812
MMIO_D(_MMIO(0xd08), D_SKL_PLUS);
2813+
MMIO_D(RC6_LOCATION, D_SKL_PLUS);
28052814
MMIO_DFH(_MMIO(0x20e0), D_SKL_PLUS, F_MODE_MASK, NULL, NULL);
28062815
MMIO_DFH(_MMIO(0x20ec), D_SKL_PLUS, F_MODE_MASK | F_CMD_ACCESS, NULL, NULL);
28072816

drivers/gpu/drm/i915/gvt/kvmgt.c

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -184,15 +184,15 @@ static struct gvt_dma *__gvt_cache_find_gfn(struct intel_vgpu *vgpu, gfn_t gfn)
184184
return NULL;
185185
}
186186

187-
static void __gvt_cache_add(struct intel_vgpu *vgpu, gfn_t gfn,
187+
static int __gvt_cache_add(struct intel_vgpu *vgpu, gfn_t gfn,
188188
dma_addr_t dma_addr)
189189
{
190190
struct gvt_dma *new, *itr;
191191
struct rb_node **link, *parent = NULL;
192192

193193
new = kzalloc(sizeof(struct gvt_dma), GFP_KERNEL);
194194
if (!new)
195-
return;
195+
return -ENOMEM;
196196

197197
new->vgpu = vgpu;
198198
new->gfn = gfn;
@@ -229,6 +229,7 @@ static void __gvt_cache_add(struct intel_vgpu *vgpu, gfn_t gfn,
229229
rb_insert_color(&new->dma_addr_node, &vgpu->vdev.dma_addr_cache);
230230

231231
vgpu->vdev.nr_cache_entries++;
232+
return 0;
232233
}
233234

234235
static void __gvt_cache_remove_entry(struct intel_vgpu *vgpu,
@@ -1586,18 +1587,25 @@ int kvmgt_dma_map_guest_page(unsigned long handle, unsigned long gfn,
15861587
entry = __gvt_cache_find_gfn(info->vgpu, gfn);
15871588
if (!entry) {
15881589
ret = gvt_dma_map_page(vgpu, gfn, dma_addr);
1589-
if (ret) {
1590-
mutex_unlock(&info->vgpu->vdev.cache_lock);
1591-
return ret;
1592-
}
1593-
__gvt_cache_add(info->vgpu, gfn, *dma_addr);
1590+
if (ret)
1591+
goto err_unlock;
1592+
1593+
ret = __gvt_cache_add(info->vgpu, gfn, *dma_addr);
1594+
if (ret)
1595+
goto err_unmap;
15941596
} else {
15951597
kref_get(&entry->ref);
15961598
*dma_addr = entry->dma_addr;
15971599
}
15981600

15991601
mutex_unlock(&info->vgpu->vdev.cache_lock);
16001602
return 0;
1603+
1604+
err_unmap:
1605+
gvt_dma_unmap_page(vgpu, gfn, *dma_addr);
1606+
err_unlock:
1607+
mutex_unlock(&info->vgpu->vdev.cache_lock);
1608+
return ret;
16011609
}
16021610

16031611
static void __gvt_dma_release(struct kref *ref)

drivers/gpu/drm/i915/gvt/scheduler.c

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,29 @@ static void set_context_pdp_root_pointer(
5252
pdp_pair[i].val = pdp[7 - i];
5353
}
5454

55+
static void update_shadow_pdps(struct intel_vgpu_workload *workload)
56+
{
57+
struct intel_vgpu *vgpu = workload->vgpu;
58+
int ring_id = workload->ring_id;
59+
struct i915_gem_context *shadow_ctx = vgpu->submission.shadow_ctx;
60+
struct drm_i915_gem_object *ctx_obj =
61+
shadow_ctx->engine[ring_id].state->obj;
62+
struct execlist_ring_context *shadow_ring_context;
63+
struct page *page;
64+
65+
if (WARN_ON(!workload->shadow_mm))
66+
return;
67+
68+
if (WARN_ON(!atomic_read(&workload->shadow_mm->pincount)))
69+
return;
70+
71+
page = i915_gem_object_get_page(ctx_obj, LRC_STATE_PN);
72+
shadow_ring_context = kmap(page);
73+
set_context_pdp_root_pointer(shadow_ring_context,
74+
(void *)workload->shadow_mm->ppgtt_mm.shadow_pdps);
75+
kunmap(page);
76+
}
77+
5578
static int populate_shadow_context(struct intel_vgpu_workload *workload)
5679
{
5780
struct intel_vgpu *vgpu = workload->vgpu;
@@ -101,8 +124,14 @@ static int populate_shadow_context(struct intel_vgpu_workload *workload)
101124
#define COPY_REG(name) \
102125
intel_gvt_hypervisor_read_gpa(vgpu, workload->ring_context_gpa \
103126
+ RING_CTX_OFF(name.val), &shadow_ring_context->name.val, 4)
127+
#define COPY_REG_MASKED(name) {\
128+
intel_gvt_hypervisor_read_gpa(vgpu, workload->ring_context_gpa \
129+
+ RING_CTX_OFF(name.val),\
130+
&shadow_ring_context->name.val, 4);\
131+
shadow_ring_context->name.val |= 0xffff << 16;\
132+
}
104133

105-
COPY_REG(ctx_ctrl);
134+
COPY_REG_MASKED(ctx_ctrl);
106135
COPY_REG(ctx_timestamp);
107136

108137
if (ring_id == RCS) {
@@ -111,9 +140,7 @@ static int populate_shadow_context(struct intel_vgpu_workload *workload)
111140
COPY_REG(rcs_indirect_ctx_offset);
112141
}
113142
#undef COPY_REG
114-
115-
set_context_pdp_root_pointer(shadow_ring_context,
116-
(void *)workload->shadow_mm->ppgtt_mm.shadow_pdps);
143+
#undef COPY_REG_MASKED
117144

118145
intel_gvt_hypervisor_read_gpa(vgpu,
119146
workload->ring_context_gpa +
@@ -509,6 +536,8 @@ static int prepare_workload(struct intel_vgpu_workload *workload)
509536
return ret;
510537
}
511538

539+
update_shadow_pdps(workload);
540+
512541
ret = intel_vgpu_sync_oos_pages(workload->vgpu);
513542
if (ret) {
514543
gvt_vgpu_err("fail to vgpu sync oos pages\n");

drivers/gpu/drm/i915/gvt/vgpu.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -522,6 +522,7 @@ void intel_gvt_reset_vgpu_locked(struct intel_vgpu *vgpu, bool dmlr,
522522
/* full GPU reset or device model level reset */
523523
if (engine_mask == ALL_ENGINES || dmlr) {
524524
intel_vgpu_select_submission_ops(vgpu, ALL_ENGINES, 0);
525+
intel_vgpu_invalidate_ppgtt(vgpu);
525526
/*fence will not be reset during virtual reset */
526527
if (dmlr) {
527528
intel_vgpu_reset_gtt(vgpu);

drivers/gpu/drm/i915/i915_gem.c

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -471,10 +471,11 @@ static void __fence_set_priority(struct dma_fence *fence, int prio)
471471

472472
rq = to_request(fence);
473473
engine = rq->engine;
474-
if (!engine->schedule)
475-
return;
476474

477-
engine->schedule(rq, prio);
475+
rcu_read_lock();
476+
if (engine->schedule)
477+
engine->schedule(rq, prio);
478+
rcu_read_unlock();
478479
}
479480

480481
static void fence_set_priority(struct dma_fence *fence, int prio)
@@ -2939,8 +2940,16 @@ i915_gem_reset_prepare_engine(struct intel_engine_cs *engine)
29392940
* calling engine->init_hw() and also writing the ELSP.
29402941
* Turning off the execlists->tasklet until the reset is over
29412942
* prevents the race.
2943+
*
2944+
* Note that this needs to be a single atomic operation on the
2945+
* tasklet (flush existing tasks, prevent new tasks) to prevent
2946+
* a race between reset and set-wedged. It is not, so we do the best
2947+
* we can atm and make sure we don't lock the machine up in the more
2948+
* common case of recursively being called from set-wedged from inside
2949+
* i915_reset.
29422950
*/
2943-
tasklet_kill(&engine->execlists.tasklet);
2951+
if (!atomic_read(&engine->execlists.tasklet.count))
2952+
tasklet_kill(&engine->execlists.tasklet);
29442953
tasklet_disable(&engine->execlists.tasklet);
29452954

29462955
/*
@@ -3214,8 +3223,11 @@ void i915_gem_set_wedged(struct drm_i915_private *i915)
32143223
*/
32153224
for_each_engine(engine, i915, id) {
32163225
i915_gem_reset_prepare_engine(engine);
3226+
32173227
engine->submit_request = nop_submit_request;
3228+
engine->schedule = NULL;
32183229
}
3230+
i915->caps.scheduler = 0;
32193231

32203232
/*
32213233
* Make sure no one is running the old callback before we proceed with
@@ -3233,11 +3245,8 @@ void i915_gem_set_wedged(struct drm_i915_private *i915)
32333245
* start to complete all requests.
32343246
*/
32353247
engine->submit_request = nop_complete_submit_request;
3236-
engine->schedule = NULL;
32373248
}
32383249

3239-
i915->caps.scheduler = 0;
3240-
32413250
/*
32423251
* Make sure no request can slip through without getting completed by
32433252
* either this call here to intel_engine_init_global_seqno, or the one

drivers/gpu/drm/i915/i915_pmu.c

Lines changed: 13 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -433,7 +433,7 @@ static u64 __get_rc6(struct drm_i915_private *i915)
433433
return val;
434434
}
435435

436-
static u64 get_rc6(struct drm_i915_private *i915, bool locked)
436+
static u64 get_rc6(struct drm_i915_private *i915)
437437
{
438438
#if IS_ENABLED(CONFIG_PM)
439439
unsigned long flags;
@@ -449,8 +449,7 @@ static u64 get_rc6(struct drm_i915_private *i915, bool locked)
449449
* previously.
450450
*/
451451

452-
if (!locked)
453-
spin_lock_irqsave(&i915->pmu.lock, flags);
452+
spin_lock_irqsave(&i915->pmu.lock, flags);
454453

455454
if (val >= i915->pmu.sample[__I915_SAMPLE_RC6_ESTIMATED].cur) {
456455
i915->pmu.sample[__I915_SAMPLE_RC6_ESTIMATED].cur = 0;
@@ -459,12 +458,10 @@ static u64 get_rc6(struct drm_i915_private *i915, bool locked)
459458
val = i915->pmu.sample[__I915_SAMPLE_RC6_ESTIMATED].cur;
460459
}
461460

462-
if (!locked)
463-
spin_unlock_irqrestore(&i915->pmu.lock, flags);
461+
spin_unlock_irqrestore(&i915->pmu.lock, flags);
464462
} else {
465463
struct pci_dev *pdev = i915->drm.pdev;
466464
struct device *kdev = &pdev->dev;
467-
unsigned long flags2;
468465

469466
/*
470467
* We are runtime suspended.
@@ -473,10 +470,8 @@ static u64 get_rc6(struct drm_i915_private *i915, bool locked)
473470
* on top of the last known real value, as the approximated RC6
474471
* counter value.
475472
*/
476-
if (!locked)
477-
spin_lock_irqsave(&i915->pmu.lock, flags);
478-
479-
spin_lock_irqsave(&kdev->power.lock, flags2);
473+
spin_lock_irqsave(&i915->pmu.lock, flags);
474+
spin_lock(&kdev->power.lock);
480475

481476
if (!i915->pmu.sample[__I915_SAMPLE_RC6_ESTIMATED].cur)
482477
i915->pmu.suspended_jiffies_last =
@@ -486,14 +481,13 @@ static u64 get_rc6(struct drm_i915_private *i915, bool locked)
486481
i915->pmu.suspended_jiffies_last;
487482
val += jiffies - kdev->power.accounting_timestamp;
488483

489-
spin_unlock_irqrestore(&kdev->power.lock, flags2);
484+
spin_unlock(&kdev->power.lock);
490485

491486
val = jiffies_to_nsecs(val);
492487
val += i915->pmu.sample[__I915_SAMPLE_RC6].cur;
493488
i915->pmu.sample[__I915_SAMPLE_RC6_ESTIMATED].cur = val;
494489

495-
if (!locked)
496-
spin_unlock_irqrestore(&i915->pmu.lock, flags);
490+
spin_unlock_irqrestore(&i915->pmu.lock, flags);
497491
}
498492

499493
return val;
@@ -502,7 +496,7 @@ static u64 get_rc6(struct drm_i915_private *i915, bool locked)
502496
#endif
503497
}
504498

505-
static u64 __i915_pmu_event_read(struct perf_event *event, bool locked)
499+
static u64 __i915_pmu_event_read(struct perf_event *event)
506500
{
507501
struct drm_i915_private *i915 =
508502
container_of(event->pmu, typeof(*i915), pmu.base);
@@ -540,7 +534,7 @@ static u64 __i915_pmu_event_read(struct perf_event *event, bool locked)
540534
val = count_interrupts(i915);
541535
break;
542536
case I915_PMU_RC6_RESIDENCY:
543-
val = get_rc6(i915, locked);
537+
val = get_rc6(i915);
544538
break;
545539
}
546540
}
@@ -555,7 +549,7 @@ static void i915_pmu_event_read(struct perf_event *event)
555549

556550
again:
557551
prev = local64_read(&hwc->prev_count);
558-
new = __i915_pmu_event_read(event, false);
552+
new = __i915_pmu_event_read(event);
559553

560554
if (local64_cmpxchg(&hwc->prev_count, prev, new) != prev)
561555
goto again;
@@ -605,14 +599,14 @@ static void i915_pmu_enable(struct perf_event *event)
605599
engine->pmu.enable_count[sample]++;
606600
}
607601

602+
spin_unlock_irqrestore(&i915->pmu.lock, flags);
603+
608604
/*
609605
* Store the current counter value so we can report the correct delta
610606
* for all listeners. Even when the event was already enabled and has
611607
* an existing non-zero value.
612608
*/
613-
local64_set(&event->hw.prev_count, __i915_pmu_event_read(event, true));
614-
615-
spin_unlock_irqrestore(&i915->pmu.lock, flags);
609+
local64_set(&event->hw.prev_count, __i915_pmu_event_read(event));
616610
}
617611

618612
static void i915_pmu_disable(struct perf_event *event)

drivers/gpu/drm/i915/i915_request.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1081,8 +1081,10 @@ void __i915_request_add(struct i915_request *request, bool flush_caches)
10811081
* decide whether to preempt the entire chain so that it is ready to
10821082
* run at the earliest possible convenience.
10831083
*/
1084+
rcu_read_lock();
10841085
if (engine->schedule)
10851086
engine->schedule(request, request->ctx->priority);
1087+
rcu_read_unlock();
10861088

10871089
local_bh_disable();
10881090
i915_sw_fence_commit(&request->submit);

0 commit comments

Comments
 (0)