You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
Merge tag 'drm-intel-next-2017-08-18' of git://anongit.freedesktop.org/git/drm-intel into drm-next
Final pile of features for 4.14 - New ioctl to change NOA configurations, plus prep (Lionel) - CCS (color compression) scanout support, based on the fancy new modifier additions (Ville&Ben) - Document i915 register macro style (Jani) - Many more gen10/cnl patches (Rodrigo, Pualo, ...) - More gpu reset vs. modeset duct-tape to restore the old way. - prep work for cnl: hpd_pin reorg (Rodrigo), support for more power wells (Imre), i2c pin reorg (Anusha) - drm_syncobj support (Jason Ekstrand) - forcewake vs gpu reset fix (Chris) - execbuf speedup for the no-relocs fastpath, anv/vk low-overhead ftw (Chris) - switch to idr/radixtree instead of the resizing ht for execbuf id->vma lookups (Chris) gvt: - MMIO save/restore optimization (Changbin) - Split workload scan vs. dispatch for more parallel exec (Ping) - vGPU full 48bit ppgtt support (Joonas, Tina) - vGPU hw id expose for perf (Zhenyu) Bunch of work all over to make the igt CI runs more complete/stable. Watch https://intel-gfx-ci.01.org/tree/drm-tip/shards-all.html for progress in getting this ready. Next week we're going into production mode (i.e. will send results to intel-gfx) on hsw, more platforms to come. Also, a new maintainer tram, I'm stepping out. Huge thanks to Jani for being an awesome co-maintainer the past few years, and all the best for Jani, Joonas&Rodrigo as the new maintainers! * tag 'drm-intel-next-2017-08-18' of git://anongit.freedesktop.org/git/drm-intel: (179 commits) drm/i915: Update DRIVER_DATE to 20170818 drm/i915/bxt: use NULL for GPIO connection ID drm/i915: Mark the GT as busy before idling the previous request drm/i915: Trivial grammar fix s/opt of/opt out of/ in comment drm/i915: Replace execbuf vma ht with an idr drm/i915: Simplify eb_lookup_vmas() drm/i915: Convert execbuf to use struct-of-array packing for critical fields drm/i915: Check context status before looking up our obj/vma drm/i915: Don't use MI_STORE_DWORD_IMM on Sandybridge/vcs drm/i915: Stop touching forcewake following a gen6+ engine reset MAINTAINERS: drm/i915 has a new maintainer team drm/i915: Split pin mapping into per platform functions drm/i915/opregion: let user specify override VBT via firmware load drm/i915/cnl: Reuse skl_wm_get_hw_state on Cannonlake. drm/i915/gen10: implement gen 10 watermarks calculations drm/i915/cnl: Fix LSPCON support. drm/i915/vbt: ignore extraneous child devices for a port drm/i915/cnl: Setup PAT Index. drm/i915/edp: Allow alternate fixed mode for eDP if available. drm/i915: Add support for drm syncobjs ...
This commit is contained in:
@@ -417,6 +417,10 @@ integrate with drm/i915 and to handle the `DRM_I915_PERF_OPEN` ioctl.
|
||||
:functions: i915_perf_open_ioctl
|
||||
.. kernel-doc:: drivers/gpu/drm/i915/i915_perf.c
|
||||
:functions: i915_perf_release
|
||||
.. kernel-doc:: drivers/gpu/drm/i915/i915_perf.c
|
||||
:functions: i915_perf_add_config_ioctl
|
||||
.. kernel-doc:: drivers/gpu/drm/i915/i915_perf.c
|
||||
:functions: i915_perf_remove_config_ioctl
|
||||
|
||||
i915 Perf Stream
|
||||
----------------
|
||||
@@ -477,4 +481,16 @@ specific details than found in the more high-level sections.
|
||||
.. kernel-doc:: drivers/gpu/drm/i915/i915_perf.c
|
||||
:internal:
|
||||
|
||||
.. WARNING: DOCPROC directive not supported: !Cdrivers/gpu/drm/i915/i915_irq.c
|
||||
Style
|
||||
=====
|
||||
|
||||
The drm/i915 driver codebase has some style rules in addition to (and, in some
|
||||
cases, deviating from) the kernel coding style.
|
||||
|
||||
Register macro definition style
|
||||
-------------------------------
|
||||
|
||||
The style guide for ``i915_reg.h``.
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/i915/i915_reg.h
|
||||
:doc: The i915 register macro definition style guide
|
||||
|
||||
+2
-1
@@ -6764,8 +6764,9 @@ S: Supported
|
||||
F: drivers/scsi/isci/
|
||||
|
||||
INTEL DRM DRIVERS (excluding Poulsbo, Moorestown and derivative chipsets)
|
||||
M: Daniel Vetter <daniel.vetter@intel.com>
|
||||
M: Jani Nikula <jani.nikula@linux.intel.com>
|
||||
M: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
|
||||
M: Rodrigo Vivi <rodrigo.vivi@intel.com>
|
||||
L: intel-gfx@lists.freedesktop.org
|
||||
W: https://01.org/linuxgraphics/
|
||||
B: https://01.org/linuxgraphics/documentation/how-report-bugs
|
||||
|
||||
@@ -2716,6 +2716,7 @@ int drm_atomic_helper_disable_all(struct drm_device *dev,
|
||||
struct drm_plane *plane;
|
||||
struct drm_crtc_state *crtc_state;
|
||||
struct drm_crtc *crtc;
|
||||
unsigned plane_mask = 0;
|
||||
int ret, i;
|
||||
|
||||
state = drm_atomic_state_alloc(dev);
|
||||
@@ -2758,10 +2759,14 @@ int drm_atomic_helper_disable_all(struct drm_device *dev,
|
||||
goto free;
|
||||
|
||||
drm_atomic_set_fb_for_plane(plane_state, NULL);
|
||||
plane_mask |= BIT(drm_plane_index(plane));
|
||||
plane->old_fb = plane->fb;
|
||||
}
|
||||
|
||||
ret = drm_atomic_commit(state);
|
||||
free:
|
||||
if (plane_mask)
|
||||
drm_atomic_clean_old_fb(dev, plane_mask, ret);
|
||||
drm_atomic_state_put(state);
|
||||
return ret;
|
||||
}
|
||||
@@ -2892,11 +2897,16 @@ int drm_atomic_helper_commit_duplicated_state(struct drm_atomic_state *state,
|
||||
struct drm_connector_state *new_conn_state;
|
||||
struct drm_crtc *crtc;
|
||||
struct drm_crtc_state *new_crtc_state;
|
||||
unsigned plane_mask = 0;
|
||||
struct drm_device *dev = state->dev;
|
||||
int ret;
|
||||
|
||||
state->acquire_ctx = ctx;
|
||||
|
||||
for_each_new_plane_in_state(state, plane, new_plane_state, i)
|
||||
for_each_new_plane_in_state(state, plane, new_plane_state, i) {
|
||||
plane_mask |= BIT(drm_plane_index(plane));
|
||||
state->planes[i].old_state = plane->state;
|
||||
}
|
||||
|
||||
for_each_new_crtc_in_state(state, crtc, new_crtc_state, i)
|
||||
state->crtcs[i].old_state = crtc->state;
|
||||
@@ -2904,7 +2914,11 @@ int drm_atomic_helper_commit_duplicated_state(struct drm_atomic_state *state,
|
||||
for_each_new_connector_in_state(state, connector, new_conn_state, i)
|
||||
state->connectors[i].old_state = connector->state;
|
||||
|
||||
return drm_atomic_commit(state);
|
||||
ret = drm_atomic_commit(state);
|
||||
if (plane_mask)
|
||||
drm_atomic_clean_old_fb(dev, plane_mask, ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_atomic_helper_commit_duplicated_state);
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@ config DRM_I915_DEBUG
|
||||
select DRM_VGEM # used by igt/prime_vgem (dmabuf interop checks)
|
||||
select DRM_DEBUG_MM if DRM=y
|
||||
select DRM_DEBUG_MM_SELFTEST
|
||||
select SW_SYNC # signaling validation framework (igt/syncobj*)
|
||||
select DRM_I915_SW_FENCE_DEBUG_OBJECTS
|
||||
select DRM_I915_SELFTEST
|
||||
default n
|
||||
|
||||
@@ -39,6 +39,7 @@ i915-y += i915_cmd_parser.o \
|
||||
i915_gem_gtt.o \
|
||||
i915_gem_internal.o \
|
||||
i915_gem.o \
|
||||
i915_gem_object.o \
|
||||
i915_gem_render_state.o \
|
||||
i915_gem_request.o \
|
||||
i915_gem_shrinker.o \
|
||||
|
||||
@@ -285,8 +285,8 @@ static int alloc_resource(struct intel_vgpu *vgpu,
|
||||
return 0;
|
||||
|
||||
no_enough_resource:
|
||||
gvt_vgpu_err("fail to allocate resource %s\n", item);
|
||||
gvt_vgpu_err("request %luMB avail %luMB max %luMB taken %luMB\n",
|
||||
gvt_err("fail to allocate resource %s\n", item);
|
||||
gvt_err("request %luMB avail %luMB max %luMB taken %luMB\n",
|
||||
BYTES_TO_MB(request), BYTES_TO_MB(avail),
|
||||
BYTES_TO_MB(max), BYTES_TO_MB(taken));
|
||||
return -ENOSPC;
|
||||
|
||||
@@ -1382,13 +1382,13 @@ static inline int cmd_address_audit(struct parser_exec_state *s,
|
||||
ret = -EINVAL;
|
||||
goto err;
|
||||
}
|
||||
} else if ((!vgpu_gmadr_is_valid(s->vgpu, guest_gma)) ||
|
||||
(!vgpu_gmadr_is_valid(s->vgpu,
|
||||
guest_gma + op_size - 1))) {
|
||||
} else if (!intel_gvt_ggtt_validate_range(vgpu, guest_gma, op_size)) {
|
||||
ret = -EINVAL;
|
||||
goto err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
gvt_vgpu_err("cmd_parser: Malicious %s detected, addr=0x%lx, len=%d!\n",
|
||||
s->info->name, guest_gma, op_size);
|
||||
@@ -2647,7 +2647,7 @@ static int shadow_workload_ring_buffer(struct intel_vgpu_workload *workload)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int intel_gvt_scan_and_shadow_workload(struct intel_vgpu_workload *workload)
|
||||
int intel_gvt_scan_and_shadow_ringbuffer(struct intel_vgpu_workload *workload)
|
||||
{
|
||||
int ret;
|
||||
struct intel_vgpu *vgpu = workload->vgpu;
|
||||
|
||||
@@ -42,7 +42,7 @@ void intel_gvt_clean_cmd_parser(struct intel_gvt *gvt);
|
||||
|
||||
int intel_gvt_init_cmd_parser(struct intel_gvt *gvt);
|
||||
|
||||
int intel_gvt_scan_and_shadow_workload(struct intel_vgpu_workload *workload);
|
||||
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);
|
||||
|
||||
|
||||
@@ -178,9 +178,9 @@ static void emulate_monitor_status_change(struct intel_vgpu *vgpu)
|
||||
SDE_PORTE_HOTPLUG_SPT);
|
||||
vgpu_vreg(vgpu, SKL_FUSE_STATUS) |=
|
||||
SKL_FUSE_DOWNLOAD_STATUS |
|
||||
SKL_FUSE_PG0_DIST_STATUS |
|
||||
SKL_FUSE_PG1_DIST_STATUS |
|
||||
SKL_FUSE_PG2_DIST_STATUS;
|
||||
SKL_FUSE_PG_DIST_STATUS(SKL_PG0) |
|
||||
SKL_FUSE_PG_DIST_STATUS(SKL_PG1) |
|
||||
SKL_FUSE_PG_DIST_STATUS(SKL_PG2);
|
||||
vgpu_vreg(vgpu, LCPLL1_CTL) |=
|
||||
LCPLL_PLL_ENABLE |
|
||||
LCPLL_PLL_LOCK;
|
||||
|
||||
@@ -622,6 +622,7 @@ static int submit_context(struct intel_vgpu *vgpu, int ring_id,
|
||||
struct list_head *q = workload_q_head(vgpu, ring_id);
|
||||
struct intel_vgpu_workload *last_workload = get_last_workload(q);
|
||||
struct intel_vgpu_workload *workload = NULL;
|
||||
struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv;
|
||||
u64 ring_context_gpa;
|
||||
u32 head, tail, start, ctl, ctx_ctl, per_ctx, indirect_ctx;
|
||||
int ret;
|
||||
@@ -685,6 +686,7 @@ static int submit_context(struct intel_vgpu *vgpu, int ring_id,
|
||||
workload->complete = complete_execlist_workload;
|
||||
workload->status = -EINPROGRESS;
|
||||
workload->emulate_schedule_in = emulate_schedule_in;
|
||||
workload->shadowed = false;
|
||||
|
||||
if (ring_id == RCS) {
|
||||
intel_gvt_hypervisor_read_gpa(vgpu, ring_context_gpa +
|
||||
@@ -718,6 +720,17 @@ static int submit_context(struct intel_vgpu *vgpu, int ring_id,
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Only scan and shadow the first workload in the queue
|
||||
* as there is only one pre-allocated buf-obj for shadow.
|
||||
*/
|
||||
if (list_empty(workload_q_head(vgpu, ring_id))) {
|
||||
intel_runtime_pm_get(dev_priv);
|
||||
mutex_lock(&dev_priv->drm.struct_mutex);
|
||||
intel_gvt_scan_and_shadow_workload(workload);
|
||||
mutex_unlock(&dev_priv->drm.struct_mutex);
|
||||
intel_runtime_pm_put(dev_priv);
|
||||
}
|
||||
|
||||
queue_workload(workload);
|
||||
return 0;
|
||||
}
|
||||
@@ -800,6 +813,8 @@ static void clean_workloads(struct intel_vgpu *vgpu, unsigned long engine_mask)
|
||||
list_del_init(&pos->list);
|
||||
free_workload(pos);
|
||||
}
|
||||
|
||||
clear_bit(engine->id, vgpu->shadow_ctx_desc_updated);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -259,7 +259,7 @@ static void write_pte64(struct drm_i915_private *dev_priv,
|
||||
writeq(pte, addr);
|
||||
}
|
||||
|
||||
static inline struct intel_gvt_gtt_entry *gtt_get_entry64(void *pt,
|
||||
static inline int gtt_get_entry64(void *pt,
|
||||
struct intel_gvt_gtt_entry *e,
|
||||
unsigned long index, bool hypervisor_access, unsigned long gpa,
|
||||
struct intel_vgpu *vgpu)
|
||||
@@ -268,22 +268,23 @@ static inline struct intel_gvt_gtt_entry *gtt_get_entry64(void *pt,
|
||||
int ret;
|
||||
|
||||
if (WARN_ON(info->gtt_entry_size != 8))
|
||||
return e;
|
||||
return -EINVAL;
|
||||
|
||||
if (hypervisor_access) {
|
||||
ret = intel_gvt_hypervisor_read_gpa(vgpu, gpa +
|
||||
(index << info->gtt_entry_size_shift),
|
||||
&e->val64, 8);
|
||||
WARN_ON(ret);
|
||||
if (WARN_ON(ret))
|
||||
return ret;
|
||||
} else if (!pt) {
|
||||
e->val64 = read_pte64(vgpu->gvt->dev_priv, index);
|
||||
} else {
|
||||
e->val64 = *((u64 *)pt + index);
|
||||
}
|
||||
return e;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline struct intel_gvt_gtt_entry *gtt_set_entry64(void *pt,
|
||||
static inline int gtt_set_entry64(void *pt,
|
||||
struct intel_gvt_gtt_entry *e,
|
||||
unsigned long index, bool hypervisor_access, unsigned long gpa,
|
||||
struct intel_vgpu *vgpu)
|
||||
@@ -292,19 +293,20 @@ static inline struct intel_gvt_gtt_entry *gtt_set_entry64(void *pt,
|
||||
int ret;
|
||||
|
||||
if (WARN_ON(info->gtt_entry_size != 8))
|
||||
return e;
|
||||
return -EINVAL;
|
||||
|
||||
if (hypervisor_access) {
|
||||
ret = intel_gvt_hypervisor_write_gpa(vgpu, gpa +
|
||||
(index << info->gtt_entry_size_shift),
|
||||
&e->val64, 8);
|
||||
WARN_ON(ret);
|
||||
if (WARN_ON(ret))
|
||||
return ret;
|
||||
} else if (!pt) {
|
||||
write_pte64(vgpu->gvt->dev_priv, index, e->val64);
|
||||
} else {
|
||||
*((u64 *)pt + index) = e->val64;
|
||||
}
|
||||
return e;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define GTT_HAW 46
|
||||
@@ -445,21 +447,25 @@ static int gtt_entry_p2m(struct intel_vgpu *vgpu, struct intel_gvt_gtt_entry *p,
|
||||
/*
|
||||
* MM helpers.
|
||||
*/
|
||||
struct intel_gvt_gtt_entry *intel_vgpu_mm_get_entry(struct intel_vgpu_mm *mm,
|
||||
int intel_vgpu_mm_get_entry(struct intel_vgpu_mm *mm,
|
||||
void *page_table, struct intel_gvt_gtt_entry *e,
|
||||
unsigned long index)
|
||||
{
|
||||
struct intel_gvt *gvt = mm->vgpu->gvt;
|
||||
struct intel_gvt_gtt_pte_ops *ops = gvt->gtt.pte_ops;
|
||||
int ret;
|
||||
|
||||
e->type = mm->page_table_entry_type;
|
||||
|
||||
ops->get_entry(page_table, e, index, false, 0, mm->vgpu);
|
||||
ret = ops->get_entry(page_table, e, index, false, 0, mm->vgpu);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ops->test_pse(e);
|
||||
return e;
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct intel_gvt_gtt_entry *intel_vgpu_mm_set_entry(struct intel_vgpu_mm *mm,
|
||||
int intel_vgpu_mm_set_entry(struct intel_vgpu_mm *mm,
|
||||
void *page_table, struct intel_gvt_gtt_entry *e,
|
||||
unsigned long index)
|
||||
{
|
||||
@@ -472,7 +478,7 @@ struct intel_gvt_gtt_entry *intel_vgpu_mm_set_entry(struct intel_vgpu_mm *mm,
|
||||
/*
|
||||
* PPGTT shadow page table helpers.
|
||||
*/
|
||||
static inline struct intel_gvt_gtt_entry *ppgtt_spt_get_entry(
|
||||
static inline int ppgtt_spt_get_entry(
|
||||
struct intel_vgpu_ppgtt_spt *spt,
|
||||
void *page_table, int type,
|
||||
struct intel_gvt_gtt_entry *e, unsigned long index,
|
||||
@@ -480,20 +486,24 @@ static inline struct intel_gvt_gtt_entry *ppgtt_spt_get_entry(
|
||||
{
|
||||
struct intel_gvt *gvt = spt->vgpu->gvt;
|
||||
struct intel_gvt_gtt_pte_ops *ops = gvt->gtt.pte_ops;
|
||||
int ret;
|
||||
|
||||
e->type = get_entry_type(type);
|
||||
|
||||
if (WARN(!gtt_type_is_entry(e->type), "invalid entry type\n"))
|
||||
return e;
|
||||
return -EINVAL;
|
||||
|
||||
ops->get_entry(page_table, e, index, guest,
|
||||
ret = ops->get_entry(page_table, e, index, guest,
|
||||
spt->guest_page.gfn << GTT_PAGE_SHIFT,
|
||||
spt->vgpu);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ops->test_pse(e);
|
||||
return e;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline struct intel_gvt_gtt_entry *ppgtt_spt_set_entry(
|
||||
static inline int ppgtt_spt_set_entry(
|
||||
struct intel_vgpu_ppgtt_spt *spt,
|
||||
void *page_table, int type,
|
||||
struct intel_gvt_gtt_entry *e, unsigned long index,
|
||||
@@ -503,7 +513,7 @@ static inline struct intel_gvt_gtt_entry *ppgtt_spt_set_entry(
|
||||
struct intel_gvt_gtt_pte_ops *ops = gvt->gtt.pte_ops;
|
||||
|
||||
if (WARN(!gtt_type_is_entry(e->type), "invalid entry type\n"))
|
||||
return e;
|
||||
return -EINVAL;
|
||||
|
||||
return ops->set_entry(page_table, e, index, guest,
|
||||
spt->guest_page.gfn << GTT_PAGE_SHIFT,
|
||||
@@ -792,13 +802,13 @@ static struct intel_vgpu_ppgtt_spt *ppgtt_find_shadow_page(
|
||||
|
||||
#define for_each_present_guest_entry(spt, e, i) \
|
||||
for (i = 0; i < pt_entries(spt); i++) \
|
||||
if (spt->vgpu->gvt->gtt.pte_ops->test_present( \
|
||||
ppgtt_get_guest_entry(spt, e, i)))
|
||||
if (!ppgtt_get_guest_entry(spt, e, i) && \
|
||||
spt->vgpu->gvt->gtt.pte_ops->test_present(e))
|
||||
|
||||
#define for_each_present_shadow_entry(spt, e, i) \
|
||||
for (i = 0; i < pt_entries(spt); i++) \
|
||||
if (spt->vgpu->gvt->gtt.pte_ops->test_present( \
|
||||
ppgtt_get_shadow_entry(spt, e, i)))
|
||||
if (!ppgtt_get_shadow_entry(spt, e, i) && \
|
||||
spt->vgpu->gvt->gtt.pte_ops->test_present(e))
|
||||
|
||||
static void ppgtt_get_shadow_page(struct intel_vgpu_ppgtt_spt *spt)
|
||||
{
|
||||
@@ -979,29 +989,26 @@ fail:
|
||||
}
|
||||
|
||||
static int ppgtt_handle_guest_entry_removal(struct intel_vgpu_guest_page *gpt,
|
||||
unsigned long index)
|
||||
struct intel_gvt_gtt_entry *se, unsigned long index)
|
||||
{
|
||||
struct intel_vgpu_ppgtt_spt *spt = guest_page_to_ppgtt_spt(gpt);
|
||||
struct intel_vgpu_shadow_page *sp = &spt->shadow_page;
|
||||
struct intel_vgpu *vgpu = spt->vgpu;
|
||||
struct intel_gvt_gtt_pte_ops *ops = vgpu->gvt->gtt.pte_ops;
|
||||
struct intel_gvt_gtt_entry e;
|
||||
int ret;
|
||||
|
||||
ppgtt_get_shadow_entry(spt, &e, index);
|
||||
|
||||
trace_gpt_change(spt->vgpu->id, "remove", spt, sp->type, e.val64,
|
||||
trace_gpt_change(spt->vgpu->id, "remove", spt, sp->type, se->val64,
|
||||
index);
|
||||
|
||||
if (!ops->test_present(&e))
|
||||
if (!ops->test_present(se))
|
||||
return 0;
|
||||
|
||||
if (ops->get_pfn(&e) == vgpu->gtt.scratch_pt[sp->type].page_mfn)
|
||||
if (ops->get_pfn(se) == vgpu->gtt.scratch_pt[sp->type].page_mfn)
|
||||
return 0;
|
||||
|
||||
if (gtt_type_is_pt(get_next_pt_type(e.type))) {
|
||||
if (gtt_type_is_pt(get_next_pt_type(se->type))) {
|
||||
struct intel_vgpu_ppgtt_spt *s =
|
||||
ppgtt_find_shadow_page(vgpu, ops->get_pfn(&e));
|
||||
ppgtt_find_shadow_page(vgpu, ops->get_pfn(se));
|
||||
if (!s) {
|
||||
gvt_vgpu_err("fail to find guest page\n");
|
||||
ret = -ENXIO;
|
||||
@@ -1011,12 +1018,10 @@ static int ppgtt_handle_guest_entry_removal(struct intel_vgpu_guest_page *gpt,
|
||||
if (ret)
|
||||
goto fail;
|
||||
}
|
||||
ops->set_pfn(&e, vgpu->gtt.scratch_pt[sp->type].page_mfn);
|
||||
ppgtt_set_shadow_entry(spt, &e, index);
|
||||
return 0;
|
||||
fail:
|
||||
gvt_vgpu_err("fail: shadow page %p guest entry 0x%llx type %d\n",
|
||||
spt, e.val64, e.type);
|
||||
spt, se->val64, se->type);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -1236,22 +1241,37 @@ static int ppgtt_handle_guest_write_page_table(
|
||||
{
|
||||
struct intel_vgpu_ppgtt_spt *spt = guest_page_to_ppgtt_spt(gpt);
|
||||
struct intel_vgpu *vgpu = spt->vgpu;
|
||||
int type = spt->shadow_page.type;
|
||||
struct intel_gvt_gtt_pte_ops *ops = vgpu->gvt->gtt.pte_ops;
|
||||
struct intel_gvt_gtt_entry se;
|
||||
|
||||
int ret;
|
||||
int new_present;
|
||||
|
||||
new_present = ops->test_present(we);
|
||||
|
||||
ret = ppgtt_handle_guest_entry_removal(gpt, index);
|
||||
if (ret)
|
||||
goto fail;
|
||||
/*
|
||||
* Adding the new entry first and then removing the old one, that can
|
||||
* guarantee the ppgtt table is validated during the window between
|
||||
* adding and removal.
|
||||
*/
|
||||
ppgtt_get_shadow_entry(spt, &se, index);
|
||||
|
||||
if (new_present) {
|
||||
ret = ppgtt_handle_guest_entry_add(gpt, we, index);
|
||||
if (ret)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ret = ppgtt_handle_guest_entry_removal(gpt, &se, index);
|
||||
if (ret)
|
||||
goto fail;
|
||||
|
||||
if (!new_present) {
|
||||
ops->set_pfn(&se, vgpu->gtt.scratch_pt[type].page_mfn);
|
||||
ppgtt_set_shadow_entry(spt, &se, index);
|
||||
}
|
||||
|
||||
return 0;
|
||||
fail:
|
||||
gvt_vgpu_err("fail: shadow page %p guest entry 0x%llx type %d.\n",
|
||||
@@ -1323,7 +1343,7 @@ static int ppgtt_handle_guest_write_page_table_bytes(void *gp,
|
||||
struct intel_vgpu *vgpu = spt->vgpu;
|
||||
struct intel_gvt_gtt_pte_ops *ops = vgpu->gvt->gtt.pte_ops;
|
||||
const struct intel_gvt_device_info *info = &vgpu->gvt->device_info;
|
||||
struct intel_gvt_gtt_entry we;
|
||||
struct intel_gvt_gtt_entry we, se;
|
||||
unsigned long index;
|
||||
int ret;
|
||||
|
||||
@@ -1339,7 +1359,8 @@ static int ppgtt_handle_guest_write_page_table_bytes(void *gp,
|
||||
return ret;
|
||||
} else {
|
||||
if (!test_bit(index, spt->post_shadow_bitmap)) {
|
||||
ret = ppgtt_handle_guest_entry_removal(gpt, index);
|
||||
ppgtt_get_shadow_entry(spt, &se, index);
|
||||
ret = ppgtt_handle_guest_entry_removal(gpt, &se, index);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
@@ -1713,8 +1734,10 @@ unsigned long intel_vgpu_gma_to_gpa(struct intel_vgpu_mm *mm, unsigned long gma)
|
||||
if (!vgpu_gmadr_is_valid(vgpu, gma))
|
||||
goto err;
|
||||
|
||||
ggtt_get_guest_entry(mm, &e,
|
||||
gma_ops->gma_to_ggtt_pte_index(gma));
|
||||
ret = ggtt_get_guest_entry(mm, &e,
|
||||
gma_ops->gma_to_ggtt_pte_index(gma));
|
||||
if (ret)
|
||||
goto err;
|
||||
gpa = (pte_ops->get_pfn(&e) << GTT_PAGE_SHIFT)
|
||||
+ (gma & ~GTT_PAGE_MASK);
|
||||
|
||||
@@ -1724,7 +1747,9 @@ unsigned long intel_vgpu_gma_to_gpa(struct intel_vgpu_mm *mm, unsigned long gma)
|
||||
|
||||
switch (mm->page_table_level) {
|
||||
case 4:
|
||||
ppgtt_get_shadow_root_entry(mm, &e, 0);
|
||||
ret = ppgtt_get_shadow_root_entry(mm, &e, 0);
|
||||
if (ret)
|
||||
goto err;
|
||||
gma_index[0] = gma_ops->gma_to_pml4_index(gma);
|
||||
gma_index[1] = gma_ops->gma_to_l4_pdp_index(gma);
|
||||
gma_index[2] = gma_ops->gma_to_pde_index(gma);
|
||||
@@ -1732,15 +1757,19 @@ unsigned long intel_vgpu_gma_to_gpa(struct intel_vgpu_mm *mm, unsigned long gma)
|
||||
index = 4;
|
||||
break;
|
||||
case 3:
|
||||
ppgtt_get_shadow_root_entry(mm, &e,
|
||||
ret = ppgtt_get_shadow_root_entry(mm, &e,
|
||||
gma_ops->gma_to_l3_pdp_index(gma));
|
||||
if (ret)
|
||||
goto err;
|
||||
gma_index[0] = gma_ops->gma_to_pde_index(gma);
|
||||
gma_index[1] = gma_ops->gma_to_pte_index(gma);
|
||||
index = 2;
|
||||
break;
|
||||
case 2:
|
||||
ppgtt_get_shadow_root_entry(mm, &e,
|
||||
ret = ppgtt_get_shadow_root_entry(mm, &e,
|
||||
gma_ops->gma_to_pde_index(gma));
|
||||
if (ret)
|
||||
goto err;
|
||||
gma_index[0] = gma_ops->gma_to_pte_index(gma);
|
||||
index = 1;
|
||||
break;
|
||||
@@ -1755,6 +1784,11 @@ unsigned long intel_vgpu_gma_to_gpa(struct intel_vgpu_mm *mm, unsigned long gma)
|
||||
(i == index - 1));
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
if (!pte_ops->test_present(&e)) {
|
||||
gvt_dbg_core("GMA 0x%lx is not present\n", gma);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
gpa = (pte_ops->get_pfn(&e) << GTT_PAGE_SHIFT)
|
||||
@@ -2329,13 +2363,12 @@ void intel_vgpu_reset_ggtt(struct intel_vgpu *vgpu)
|
||||
/**
|
||||
* intel_vgpu_reset_gtt - reset the all GTT related status
|
||||
* @vgpu: a vGPU
|
||||
* @dmlr: true for vGPU Device Model Level Reset, false for GT Reset
|
||||
*
|
||||
* This function is called from vfio core to reset reset all
|
||||
* GTT related status, including GGTT, PPGTT, scratch page.
|
||||
*
|
||||
*/
|
||||
void intel_vgpu_reset_gtt(struct intel_vgpu *vgpu, bool dmlr)
|
||||
void intel_vgpu_reset_gtt(struct intel_vgpu *vgpu)
|
||||
{
|
||||
int i;
|
||||
|
||||
@@ -2347,9 +2380,6 @@ void intel_vgpu_reset_gtt(struct intel_vgpu *vgpu, bool dmlr)
|
||||
*/
|
||||
intel_vgpu_free_mm(vgpu, INTEL_GVT_MM_PPGTT);
|
||||
|
||||
if (!dmlr)
|
||||
return;
|
||||
|
||||
intel_vgpu_reset_ggtt(vgpu);
|
||||
|
||||
/* clear scratch page for security */
|
||||
|
||||
@@ -49,14 +49,18 @@ struct intel_gvt_gtt_entry {
|
||||
};
|
||||
|
||||
struct intel_gvt_gtt_pte_ops {
|
||||
struct intel_gvt_gtt_entry *(*get_entry)(void *pt,
|
||||
struct intel_gvt_gtt_entry *e,
|
||||
unsigned long index, bool hypervisor_access, unsigned long gpa,
|
||||
struct intel_vgpu *vgpu);
|
||||
struct intel_gvt_gtt_entry *(*set_entry)(void *pt,
|
||||
struct intel_gvt_gtt_entry *e,
|
||||
unsigned long index, bool hypervisor_access, unsigned long gpa,
|
||||
struct intel_vgpu *vgpu);
|
||||
int (*get_entry)(void *pt,
|
||||
struct intel_gvt_gtt_entry *e,
|
||||
unsigned long index,
|
||||
bool hypervisor_access,
|
||||
unsigned long gpa,
|
||||
struct intel_vgpu *vgpu);
|
||||
int (*set_entry)(void *pt,
|
||||
struct intel_gvt_gtt_entry *e,
|
||||
unsigned long index,
|
||||
bool hypervisor_access,
|
||||
unsigned long gpa,
|
||||
struct intel_vgpu *vgpu);
|
||||
bool (*test_present)(struct intel_gvt_gtt_entry *e);
|
||||
void (*clear_present)(struct intel_gvt_gtt_entry *e);
|
||||
bool (*test_pse)(struct intel_gvt_gtt_entry *e);
|
||||
@@ -143,12 +147,12 @@ struct intel_vgpu_mm {
|
||||
struct intel_vgpu *vgpu;
|
||||
};
|
||||
|
||||
extern struct intel_gvt_gtt_entry *intel_vgpu_mm_get_entry(
|
||||
extern int intel_vgpu_mm_get_entry(
|
||||
struct intel_vgpu_mm *mm,
|
||||
void *page_table, struct intel_gvt_gtt_entry *e,
|
||||
unsigned long index);
|
||||
|
||||
extern struct intel_gvt_gtt_entry *intel_vgpu_mm_set_entry(
|
||||
extern int intel_vgpu_mm_set_entry(
|
||||
struct intel_vgpu_mm *mm,
|
||||
void *page_table, struct intel_gvt_gtt_entry *e,
|
||||
unsigned long index);
|
||||
@@ -208,7 +212,7 @@ extern void intel_vgpu_clean_gtt(struct intel_vgpu *vgpu);
|
||||
void intel_vgpu_reset_ggtt(struct intel_vgpu *vgpu);
|
||||
|
||||
extern int intel_gvt_init_gtt(struct intel_gvt *gvt);
|
||||
extern void intel_vgpu_reset_gtt(struct intel_vgpu *vgpu, bool dmlr);
|
||||
void intel_vgpu_reset_gtt(struct intel_vgpu *vgpu);
|
||||
extern void intel_gvt_clean_gtt(struct intel_gvt *gvt);
|
||||
|
||||
extern struct intel_vgpu_mm *intel_gvt_find_ppgtt_mm(struct intel_vgpu *vgpu,
|
||||
|
||||
@@ -167,6 +167,7 @@ struct intel_vgpu {
|
||||
atomic_t running_workload_num;
|
||||
DECLARE_BITMAP(tlb_handle_pending, I915_NUM_ENGINES);
|
||||
struct i915_gem_context *shadow_ctx;
|
||||
DECLARE_BITMAP(shadow_ctx_desc_updated, I915_NUM_ENGINES);
|
||||
|
||||
#if IS_ENABLED(CONFIG_DRM_I915_GVT_KVMGT)
|
||||
struct {
|
||||
@@ -482,6 +483,8 @@ int intel_vgpu_init_opregion(struct intel_vgpu *vgpu, u32 gpa);
|
||||
int intel_vgpu_emulate_opregion_request(struct intel_vgpu *vgpu, u32 swsci);
|
||||
void populate_pvinfo_page(struct intel_vgpu *vgpu);
|
||||
|
||||
int intel_gvt_scan_and_shadow_workload(struct intel_vgpu_workload *workload);
|
||||
|
||||
struct intel_gvt_ops {
|
||||
int (*emulate_cfg_read)(struct intel_vgpu *, unsigned int, void *,
|
||||
unsigned int);
|
||||
|
||||
@@ -113,9 +113,17 @@ static int new_mmio_info(struct intel_gvt *gvt,
|
||||
|
||||
info->offset = i;
|
||||
p = find_mmio_info(gvt, info->offset);
|
||||
if (p)
|
||||
gvt_err("dup mmio definition offset %x\n",
|
||||
if (p) {
|
||||
WARN(1, "dup mmio definition offset %x\n",
|
||||
info->offset);
|
||||
kfree(info);
|
||||
|
||||
/* We return -EEXIST here to make GVT-g load fail.
|
||||
* So duplicated MMIO can be found as soon as
|
||||
* possible.
|
||||
*/
|
||||
return -EEXIST;
|
||||
}
|
||||
|
||||
info->ro_mask = ro_mask;
|
||||
info->device = device;
|
||||
@@ -1222,10 +1230,12 @@ static int power_well_ctl_mmio_write(struct intel_vgpu *vgpu,
|
||||
{
|
||||
write_vreg(vgpu, offset, p_data, bytes);
|
||||
|
||||
if (vgpu_vreg(vgpu, offset) & HSW_PWR_WELL_ENABLE_REQUEST)
|
||||
vgpu_vreg(vgpu, offset) |= HSW_PWR_WELL_STATE_ENABLED;
|
||||
if (vgpu_vreg(vgpu, offset) & HSW_PWR_WELL_CTL_REQ(HSW_DISP_PW_GLOBAL))
|
||||
vgpu_vreg(vgpu, offset) |=
|
||||
HSW_PWR_WELL_CTL_STATE(HSW_DISP_PW_GLOBAL);
|
||||
else
|
||||
vgpu_vreg(vgpu, offset) &= ~HSW_PWR_WELL_STATE_ENABLED;
|
||||
vgpu_vreg(vgpu, offset) &=
|
||||
~HSW_PWR_WELL_CTL_STATE(HSW_DISP_PW_GLOBAL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -2242,10 +2252,17 @@ static int init_generic_mmio_info(struct intel_gvt *gvt)
|
||||
MMIO_D(GEN6_RC6p_THRESHOLD, D_ALL);
|
||||
MMIO_D(GEN6_RC6pp_THRESHOLD, D_ALL);
|
||||
MMIO_D(GEN6_PMINTRMSK, D_ALL);
|
||||
MMIO_DH(HSW_PWR_WELL_BIOS, D_BDW, NULL, power_well_ctl_mmio_write);
|
||||
MMIO_DH(HSW_PWR_WELL_DRIVER, D_BDW, NULL, power_well_ctl_mmio_write);
|
||||
MMIO_DH(HSW_PWR_WELL_KVMR, D_BDW, NULL, power_well_ctl_mmio_write);
|
||||
MMIO_DH(HSW_PWR_WELL_DEBUG, D_BDW, NULL, power_well_ctl_mmio_write);
|
||||
/*
|
||||
* Use an arbitrary power well controlled by the PWR_WELL_CTL
|
||||
* register.
|
||||
*/
|
||||
MMIO_DH(HSW_PWR_WELL_CTL_BIOS(HSW_DISP_PW_GLOBAL), D_BDW, NULL,
|
||||
power_well_ctl_mmio_write);
|
||||
MMIO_DH(HSW_PWR_WELL_CTL_DRIVER(HSW_DISP_PW_GLOBAL), D_BDW, NULL,
|
||||
power_well_ctl_mmio_write);
|
||||
MMIO_DH(HSW_PWR_WELL_CTL_KVMR, D_BDW, NULL, power_well_ctl_mmio_write);
|
||||
MMIO_DH(HSW_PWR_WELL_CTL_DEBUG(HSW_DISP_PW_GLOBAL), D_BDW, NULL,
|
||||
power_well_ctl_mmio_write);
|
||||
MMIO_DH(HSW_PWR_WELL_CTL5, D_BDW, NULL, power_well_ctl_mmio_write);
|
||||
MMIO_DH(HSW_PWR_WELL_CTL6, D_BDW, NULL, power_well_ctl_mmio_write);
|
||||
|
||||
@@ -2581,7 +2598,6 @@ static int init_broadwell_mmio_info(struct intel_gvt *gvt)
|
||||
MMIO_F(0x24d0, 48, F_CMD_ACCESS, 0, 0, D_BDW_PLUS,
|
||||
NULL, force_nonpriv_write);
|
||||
|
||||
MMIO_D(0x22040, D_BDW_PLUS);
|
||||
MMIO_D(0x44484, D_BDW_PLUS);
|
||||
MMIO_D(0x4448c, D_BDW_PLUS);
|
||||
|
||||
@@ -2636,9 +2652,13 @@ static int init_skl_mmio_info(struct intel_gvt *gvt)
|
||||
MMIO_F(_DPD_AUX_CH_CTL, 6 * 4, 0, 0, 0, D_SKL_PLUS, NULL,
|
||||
dp_aux_ch_ctl_mmio_write);
|
||||
|
||||
MMIO_D(HSW_PWR_WELL_BIOS, D_SKL_PLUS);
|
||||
MMIO_DH(HSW_PWR_WELL_DRIVER, D_SKL_PLUS, NULL,
|
||||
skl_power_well_ctl_write);
|
||||
/*
|
||||
* Use an arbitrary power well controlled by the PWR_WELL_CTL
|
||||
* register.
|
||||
*/
|
||||
MMIO_D(HSW_PWR_WELL_CTL_BIOS(SKL_DISP_PW_MISC_IO), D_SKL_PLUS);
|
||||
MMIO_DH(HSW_PWR_WELL_CTL_DRIVER(SKL_DISP_PW_MISC_IO), D_SKL_PLUS, NULL,
|
||||
skl_power_well_ctl_write);
|
||||
MMIO_DH(GEN6_PCODE_MAILBOX, D_SKL_PLUS, NULL, mailbox_write);
|
||||
|
||||
MMIO_D(0xa210, D_SKL_PLUS);
|
||||
@@ -2831,7 +2851,6 @@ static int init_skl_mmio_info(struct intel_gvt *gvt)
|
||||
MMIO_D(0x320f0, D_SKL | D_KBL);
|
||||
|
||||
MMIO_DFH(_REG_VCS2_EXCC, D_SKL_PLUS, F_CMD_ACCESS, NULL, NULL);
|
||||
MMIO_DFH(_REG_VECS_EXCC, D_SKL_PLUS, F_CMD_ACCESS, NULL, NULL);
|
||||
MMIO_D(0x70034, D_SKL_PLUS);
|
||||
MMIO_D(0x71034, D_SKL_PLUS);
|
||||
MMIO_D(0x72034, D_SKL_PLUS);
|
||||
@@ -2849,10 +2868,7 @@ static int init_skl_mmio_info(struct intel_gvt *gvt)
|
||||
NULL, NULL);
|
||||
|
||||
MMIO_D(0x4ab8, D_KBL);
|
||||
MMIO_D(0x940c, D_SKL_PLUS);
|
||||
MMIO_D(0x2248, D_SKL_PLUS | D_KBL);
|
||||
MMIO_D(0x4ab0, D_SKL | D_KBL);
|
||||
MMIO_D(0x20d4, D_SKL | D_KBL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1170,10 +1170,27 @@ vgpu_id_show(struct device *dev, struct device_attribute *attr,
|
||||
return sprintf(buf, "\n");
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
hw_id_show(struct device *dev, struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct mdev_device *mdev = mdev_from_dev(dev);
|
||||
|
||||
if (mdev) {
|
||||
struct intel_vgpu *vgpu = (struct intel_vgpu *)
|
||||
mdev_get_drvdata(mdev);
|
||||
return sprintf(buf, "%u\n",
|
||||
vgpu->shadow_ctx->hw_id);
|
||||
}
|
||||
return sprintf(buf, "\n");
|
||||
}
|
||||
|
||||
static DEVICE_ATTR_RO(vgpu_id);
|
||||
static DEVICE_ATTR_RO(hw_id);
|
||||
|
||||
static struct attribute *intel_vgpu_attrs[] = {
|
||||
&dev_attr_vgpu_id.attr,
|
||||
&dev_attr_hw_id.attr,
|
||||
NULL
|
||||
};
|
||||
|
||||
|
||||
@@ -207,18 +207,16 @@ static void load_mocs(struct intel_vgpu *vgpu, int ring_id)
|
||||
|
||||
offset.reg = regs[ring_id];
|
||||
for (i = 0; i < 64; i++) {
|
||||
gen9_render_mocs[ring_id][i] = I915_READ(offset);
|
||||
gen9_render_mocs[ring_id][i] = I915_READ_FW(offset);
|
||||
I915_WRITE(offset, vgpu_vreg(vgpu, offset));
|
||||
POSTING_READ(offset);
|
||||
offset.reg += 4;
|
||||
}
|
||||
|
||||
if (ring_id == RCS) {
|
||||
l3_offset.reg = 0xb020;
|
||||
for (i = 0; i < 32; i++) {
|
||||
gen9_render_mocs_L3[i] = I915_READ(l3_offset);
|
||||
I915_WRITE(l3_offset, vgpu_vreg(vgpu, l3_offset));
|
||||
POSTING_READ(l3_offset);
|
||||
gen9_render_mocs_L3[i] = I915_READ_FW(l3_offset);
|
||||
I915_WRITE_FW(l3_offset, vgpu_vreg(vgpu, l3_offset));
|
||||
l3_offset.reg += 4;
|
||||
}
|
||||
}
|
||||
@@ -242,18 +240,16 @@ static void restore_mocs(struct intel_vgpu *vgpu, int ring_id)
|
||||
|
||||
offset.reg = regs[ring_id];
|
||||
for (i = 0; i < 64; i++) {
|
||||
vgpu_vreg(vgpu, offset) = I915_READ(offset);
|
||||
I915_WRITE(offset, gen9_render_mocs[ring_id][i]);
|
||||
POSTING_READ(offset);
|
||||
vgpu_vreg(vgpu, offset) = I915_READ_FW(offset);
|
||||
I915_WRITE_FW(offset, gen9_render_mocs[ring_id][i]);
|
||||
offset.reg += 4;
|
||||
}
|
||||
|
||||
if (ring_id == RCS) {
|
||||
l3_offset.reg = 0xb020;
|
||||
for (i = 0; i < 32; i++) {
|
||||
vgpu_vreg(vgpu, l3_offset) = I915_READ(l3_offset);
|
||||
I915_WRITE(l3_offset, gen9_render_mocs_L3[i]);
|
||||
POSTING_READ(l3_offset);
|
||||
vgpu_vreg(vgpu, l3_offset) = I915_READ_FW(l3_offset);
|
||||
I915_WRITE_FW(l3_offset, gen9_render_mocs_L3[i]);
|
||||
l3_offset.reg += 4;
|
||||
}
|
||||
}
|
||||
@@ -272,6 +268,7 @@ static void switch_mmio_to_vgpu(struct intel_vgpu *vgpu, int ring_id)
|
||||
u32 ctx_ctrl = reg_state[CTX_CONTEXT_CONTROL_VAL];
|
||||
u32 inhibit_mask =
|
||||
_MASKED_BIT_ENABLE(CTX_CTRL_ENGINE_CTX_RESTORE_INHIBIT);
|
||||
i915_reg_t last_reg = _MMIO(0);
|
||||
|
||||
if (IS_SKYLAKE(vgpu->gvt->dev_priv)
|
||||
|| IS_KABYLAKE(vgpu->gvt->dev_priv)) {
|
||||
@@ -287,7 +284,7 @@ static void switch_mmio_to_vgpu(struct intel_vgpu *vgpu, int ring_id)
|
||||
if (mmio->ring_id != ring_id)
|
||||
continue;
|
||||
|
||||
mmio->value = I915_READ(mmio->reg);
|
||||
mmio->value = I915_READ_FW(mmio->reg);
|
||||
|
||||
/*
|
||||
* if it is an inhibit context, load in_context mmio
|
||||
@@ -304,13 +301,18 @@ static void switch_mmio_to_vgpu(struct intel_vgpu *vgpu, int ring_id)
|
||||
else
|
||||
v = vgpu_vreg(vgpu, mmio->reg);
|
||||
|
||||
I915_WRITE(mmio->reg, v);
|
||||
POSTING_READ(mmio->reg);
|
||||
I915_WRITE_FW(mmio->reg, v);
|
||||
last_reg = mmio->reg;
|
||||
|
||||
trace_render_mmio(vgpu->id, "load",
|
||||
i915_mmio_reg_offset(mmio->reg),
|
||||
mmio->value, v);
|
||||
}
|
||||
|
||||
/* Make sure the swiched MMIOs has taken effect. */
|
||||
if (likely(INTEL_GVT_MMIO_OFFSET(last_reg)))
|
||||
I915_READ_FW(last_reg);
|
||||
|
||||
handle_tlb_pending_event(vgpu, ring_id);
|
||||
}
|
||||
|
||||
@@ -319,6 +321,7 @@ static void switch_mmio_to_host(struct intel_vgpu *vgpu, int ring_id)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv;
|
||||
struct render_mmio *mmio;
|
||||
i915_reg_t last_reg = _MMIO(0);
|
||||
u32 v;
|
||||
int i, array_size;
|
||||
|
||||
@@ -335,7 +338,7 @@ static void switch_mmio_to_host(struct intel_vgpu *vgpu, int ring_id)
|
||||
if (mmio->ring_id != ring_id)
|
||||
continue;
|
||||
|
||||
vgpu_vreg(vgpu, mmio->reg) = I915_READ(mmio->reg);
|
||||
vgpu_vreg(vgpu, mmio->reg) = I915_READ_FW(mmio->reg);
|
||||
|
||||
if (mmio->mask) {
|
||||
vgpu_vreg(vgpu, mmio->reg) &= ~(mmio->mask << 16);
|
||||
@@ -346,13 +349,17 @@ static void switch_mmio_to_host(struct intel_vgpu *vgpu, int ring_id)
|
||||
if (mmio->in_context)
|
||||
continue;
|
||||
|
||||
I915_WRITE(mmio->reg, v);
|
||||
POSTING_READ(mmio->reg);
|
||||
I915_WRITE_FW(mmio->reg, v);
|
||||
last_reg = mmio->reg;
|
||||
|
||||
trace_render_mmio(vgpu->id, "restore",
|
||||
i915_mmio_reg_offset(mmio->reg),
|
||||
mmio->value, v);
|
||||
}
|
||||
|
||||
/* Make sure the swiched MMIOs has taken effect. */
|
||||
if (likely(INTEL_GVT_MMIO_OFFSET(last_reg)))
|
||||
I915_READ_FW(last_reg);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -367,12 +374,23 @@ static void switch_mmio_to_host(struct intel_vgpu *vgpu, int ring_id)
|
||||
void intel_gvt_switch_mmio(struct intel_vgpu *pre,
|
||||
struct intel_vgpu *next, int ring_id)
|
||||
{
|
||||
struct drm_i915_private *dev_priv;
|
||||
|
||||
if (WARN_ON(!pre && !next))
|
||||
return;
|
||||
|
||||
gvt_dbg_render("switch ring %d from %s to %s\n", ring_id,
|
||||
pre ? "vGPU" : "host", next ? "vGPU" : "HOST");
|
||||
|
||||
dev_priv = pre ? pre->gvt->dev_priv : next->gvt->dev_priv;
|
||||
|
||||
/**
|
||||
* We are using raw mmio access wrapper to improve the
|
||||
* performace for batch mmio read/write, so we need
|
||||
* handle forcewake mannually.
|
||||
*/
|
||||
intel_uncore_forcewake_get(dev_priv, FORCEWAKE_ALL);
|
||||
|
||||
/**
|
||||
* TODO: Optimize for vGPU to vGPU switch by merging
|
||||
* switch_mmio_to_host() and switch_mmio_to_vgpu().
|
||||
@@ -382,4 +400,6 @@ void intel_gvt_switch_mmio(struct intel_vgpu *pre,
|
||||
|
||||
if (next)
|
||||
switch_mmio_to_vgpu(next, ring_id);
|
||||
|
||||
intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL);
|
||||
}
|
||||
|
||||
@@ -184,41 +184,52 @@ static int shadow_context_status_change(struct notifier_block *nb,
|
||||
return NOTIFY_OK;
|
||||
}
|
||||
|
||||
static int dispatch_workload(struct intel_vgpu_workload *workload)
|
||||
static void shadow_context_descriptor_update(struct i915_gem_context *ctx,
|
||||
struct intel_engine_cs *engine)
|
||||
{
|
||||
struct intel_context *ce = &ctx->engine[engine->id];
|
||||
u64 desc = 0;
|
||||
|
||||
desc = ce->lrc_desc;
|
||||
|
||||
/* Update bits 0-11 of the context descriptor which includes flags
|
||||
* like GEN8_CTX_* cached in desc_template
|
||||
*/
|
||||
desc &= U64_MAX << 12;
|
||||
desc |= ctx->desc_template & ((1ULL << 12) - 1);
|
||||
|
||||
ce->lrc_desc = desc;
|
||||
}
|
||||
|
||||
/**
|
||||
* intel_gvt_scan_and_shadow_workload - audit the workload by scanning and
|
||||
* shadow it as well, include ringbuffer,wa_ctx and ctx.
|
||||
* @workload: an abstract entity for each execlist submission.
|
||||
*
|
||||
* This function is called before the workload submitting to i915, to make
|
||||
* sure the content of the workload is valid.
|
||||
*/
|
||||
int intel_gvt_scan_and_shadow_workload(struct intel_vgpu_workload *workload)
|
||||
{
|
||||
int ring_id = workload->ring_id;
|
||||
struct i915_gem_context *shadow_ctx = workload->vgpu->shadow_ctx;
|
||||
struct drm_i915_private *dev_priv = workload->vgpu->gvt->dev_priv;
|
||||
struct intel_engine_cs *engine = dev_priv->engine[ring_id];
|
||||
struct drm_i915_gem_request *rq;
|
||||
struct intel_vgpu *vgpu = workload->vgpu;
|
||||
struct intel_ring *ring;
|
||||
int ret;
|
||||
|
||||
gvt_dbg_sched("ring id %d prepare to dispatch workload %p\n",
|
||||
ring_id, workload);
|
||||
lockdep_assert_held(&dev_priv->drm.struct_mutex);
|
||||
|
||||
if (workload->shadowed)
|
||||
return 0;
|
||||
|
||||
shadow_ctx->desc_template &= ~(0x3 << GEN8_CTX_ADDRESSING_MODE_SHIFT);
|
||||
shadow_ctx->desc_template |= workload->ctx_desc.addressing_mode <<
|
||||
GEN8_CTX_ADDRESSING_MODE_SHIFT;
|
||||
|
||||
mutex_lock(&dev_priv->drm.struct_mutex);
|
||||
|
||||
/* pin shadow context by gvt even the shadow context will be pinned
|
||||
* when i915 alloc request. That is because gvt will update the guest
|
||||
* context from shadow context when workload is completed, and at that
|
||||
* moment, i915 may already unpined the shadow context to make the
|
||||
* shadow_ctx pages invalid. So gvt need to pin itself. After update
|
||||
* the guest context, gvt can unpin the shadow_ctx safely.
|
||||
*/
|
||||
ring = engine->context_pin(engine, shadow_ctx);
|
||||
if (IS_ERR(ring)) {
|
||||
ret = PTR_ERR(ring);
|
||||
gvt_vgpu_err("fail to pin shadow context\n");
|
||||
workload->status = ret;
|
||||
mutex_unlock(&dev_priv->drm.struct_mutex);
|
||||
return ret;
|
||||
}
|
||||
if (!test_and_set_bit(ring_id, vgpu->shadow_ctx_desc_updated))
|
||||
shadow_context_descriptor_update(shadow_ctx,
|
||||
dev_priv->engine[ring_id]);
|
||||
|
||||
rq = i915_gem_request_alloc(dev_priv->engine[ring_id], shadow_ctx);
|
||||
if (IS_ERR(rq)) {
|
||||
@@ -231,7 +242,7 @@ static int dispatch_workload(struct intel_vgpu_workload *workload)
|
||||
|
||||
workload->req = i915_gem_request_get(rq);
|
||||
|
||||
ret = intel_gvt_scan_and_shadow_workload(workload);
|
||||
ret = intel_gvt_scan_and_shadow_ringbuffer(workload);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
@@ -246,25 +257,61 @@ static int dispatch_workload(struct intel_vgpu_workload *workload)
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
workload->shadowed = true;
|
||||
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int dispatch_workload(struct intel_vgpu_workload *workload)
|
||||
{
|
||||
int ring_id = workload->ring_id;
|
||||
struct i915_gem_context *shadow_ctx = workload->vgpu->shadow_ctx;
|
||||
struct drm_i915_private *dev_priv = workload->vgpu->gvt->dev_priv;
|
||||
struct intel_engine_cs *engine = dev_priv->engine[ring_id];
|
||||
struct intel_vgpu *vgpu = workload->vgpu;
|
||||
struct intel_ring *ring;
|
||||
int ret = 0;
|
||||
|
||||
gvt_dbg_sched("ring id %d prepare to dispatch workload %p\n",
|
||||
ring_id, workload);
|
||||
|
||||
mutex_lock(&dev_priv->drm.struct_mutex);
|
||||
|
||||
ret = intel_gvt_scan_and_shadow_workload(workload);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
if (workload->prepare) {
|
||||
ret = workload->prepare(workload);
|
||||
if (ret)
|
||||
goto out;
|
||||
}
|
||||
|
||||
gvt_dbg_sched("ring id %d submit workload to i915 %p\n",
|
||||
ring_id, workload->req);
|
||||
/* pin shadow context by gvt even the shadow context will be pinned
|
||||
* when i915 alloc request. That is because gvt will update the guest
|
||||
* context from shadow context when workload is completed, and at that
|
||||
* moment, i915 may already unpined the shadow context to make the
|
||||
* shadow_ctx pages invalid. So gvt need to pin itself. After update
|
||||
* the guest context, gvt can unpin the shadow_ctx safely.
|
||||
*/
|
||||
ring = engine->context_pin(engine, shadow_ctx);
|
||||
if (IS_ERR(ring)) {
|
||||
ret = PTR_ERR(ring);
|
||||
gvt_vgpu_err("fail to pin shadow context\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
workload->dispatched = true;
|
||||
out:
|
||||
if (ret)
|
||||
workload->status = ret;
|
||||
|
||||
if (!IS_ERR_OR_NULL(rq))
|
||||
i915_add_request(rq);
|
||||
else
|
||||
engine->context_unpin(engine, shadow_ctx);
|
||||
if (!IS_ERR_OR_NULL(workload->req)) {
|
||||
gvt_dbg_sched("ring id %d submit workload to i915 %p\n",
|
||||
ring_id, workload->req);
|
||||
i915_add_request(workload->req);
|
||||
workload->dispatched = true;
|
||||
}
|
||||
|
||||
mutex_unlock(&dev_priv->drm.struct_mutex);
|
||||
return ret;
|
||||
@@ -631,5 +678,7 @@ int intel_vgpu_init_gvt_context(struct intel_vgpu *vgpu)
|
||||
|
||||
vgpu->shadow_ctx->engine[RCS].initialised = true;
|
||||
|
||||
bitmap_zero(vgpu->shadow_ctx_desc_updated, I915_NUM_ENGINES);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -82,6 +82,7 @@ struct intel_vgpu_workload {
|
||||
struct drm_i915_gem_request *req;
|
||||
/* if this workload has been dispatched to i915? */
|
||||
bool dispatched;
|
||||
bool shadowed;
|
||||
int status;
|
||||
|
||||
struct intel_vgpu_mm *shadow_mm;
|
||||
|
||||
@@ -43,6 +43,7 @@ void populate_pvinfo_page(struct intel_vgpu *vgpu)
|
||||
vgpu_vreg(vgpu, vgtif_reg(version_minor)) = 0;
|
||||
vgpu_vreg(vgpu, vgtif_reg(display_ready)) = 0;
|
||||
vgpu_vreg(vgpu, vgtif_reg(vgt_id)) = vgpu->id;
|
||||
vgpu_vreg(vgpu, vgtif_reg(vgt_caps)) = VGT_CAPS_FULL_48BIT_PPGTT;
|
||||
vgpu_vreg(vgpu, vgtif_reg(avail_rs.mappable_gmadr.base)) =
|
||||
vgpu_aperture_gmadr_base(vgpu);
|
||||
vgpu_vreg(vgpu, vgtif_reg(avail_rs.mappable_gmadr.size)) =
|
||||
@@ -504,11 +505,11 @@ void intel_gvt_reset_vgpu_locked(struct intel_vgpu *vgpu, bool dmlr,
|
||||
/* full GPU reset or device model level reset */
|
||||
if (engine_mask == ALL_ENGINES || dmlr) {
|
||||
|
||||
intel_vgpu_reset_gtt(vgpu, dmlr);
|
||||
|
||||
/*fence will not be reset during virtual reset */
|
||||
if (dmlr)
|
||||
if (dmlr) {
|
||||
intel_vgpu_reset_gtt(vgpu);
|
||||
intel_vgpu_reset_resource(vgpu);
|
||||
}
|
||||
|
||||
intel_vgpu_reset_mmio(vgpu, dmlr);
|
||||
populate_pvinfo_page(vgpu);
|
||||
|
||||
@@ -543,75 +543,6 @@ static int i915_gem_gtt_info(struct seq_file *m, void *data)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int i915_gem_pageflip_info(struct seq_file *m, void *data)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = node_to_i915(m->private);
|
||||
struct drm_device *dev = &dev_priv->drm;
|
||||
struct intel_crtc *crtc;
|
||||
int ret;
|
||||
|
||||
ret = mutex_lock_interruptible(&dev->struct_mutex);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
for_each_intel_crtc(dev, crtc) {
|
||||
const char pipe = pipe_name(crtc->pipe);
|
||||
const char plane = plane_name(crtc->plane);
|
||||
struct intel_flip_work *work;
|
||||
|
||||
spin_lock_irq(&dev->event_lock);
|
||||
work = crtc->flip_work;
|
||||
if (work == NULL) {
|
||||
seq_printf(m, "No flip due on pipe %c (plane %c)\n",
|
||||
pipe, plane);
|
||||
} else {
|
||||
u32 pending;
|
||||
u32 addr;
|
||||
|
||||
pending = atomic_read(&work->pending);
|
||||
if (pending) {
|
||||
seq_printf(m, "Flip ioctl preparing on pipe %c (plane %c)\n",
|
||||
pipe, plane);
|
||||
} else {
|
||||
seq_printf(m, "Flip pending (waiting for vsync) on pipe %c (plane %c)\n",
|
||||
pipe, plane);
|
||||
}
|
||||
if (work->flip_queued_req) {
|
||||
struct intel_engine_cs *engine = work->flip_queued_req->engine;
|
||||
|
||||
seq_printf(m, "Flip queued on %s at seqno %x, last submitted seqno %x [current breadcrumb %x], completed? %d\n",
|
||||
engine->name,
|
||||
work->flip_queued_req->global_seqno,
|
||||
intel_engine_last_submit(engine),
|
||||
intel_engine_get_seqno(engine),
|
||||
i915_gem_request_completed(work->flip_queued_req));
|
||||
} else
|
||||
seq_printf(m, "Flip not associated with any ring\n");
|
||||
seq_printf(m, "Flip queued on frame %d, (was ready on frame %d), now %d\n",
|
||||
work->flip_queued_vblank,
|
||||
work->flip_ready_vblank,
|
||||
intel_crtc_get_vblank_counter(crtc));
|
||||
seq_printf(m, "%d prepares\n", atomic_read(&work->pending));
|
||||
|
||||
if (INTEL_GEN(dev_priv) >= 4)
|
||||
addr = I915_HI_DISPBASE(I915_READ(DSPSURF(crtc->plane)));
|
||||
else
|
||||
addr = I915_READ(DSPADDR(crtc->plane));
|
||||
seq_printf(m, "Current scanout address 0x%08x\n", addr);
|
||||
|
||||
if (work->pending_flip_obj) {
|
||||
seq_printf(m, "New framebuffer address 0x%08lx\n", (long)work->gtt_offset);
|
||||
seq_printf(m, "MMIO update completed? %d\n", addr == work->gtt_offset);
|
||||
}
|
||||
}
|
||||
spin_unlock_irq(&dev->event_lock);
|
||||
}
|
||||
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int i915_gem_batch_pool_info(struct seq_file *m, void *data)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = node_to_i915(m->private);
|
||||
@@ -2023,12 +1954,6 @@ static int i915_context_status(struct seq_file *m, void *unused)
|
||||
seq_putc(m, '\n');
|
||||
}
|
||||
|
||||
seq_printf(m,
|
||||
"\tvma hashtable size=%u (actual %lu), count=%u\n",
|
||||
ctx->vma_lut.ht_size,
|
||||
BIT(ctx->vma_lut.ht_bits),
|
||||
ctx->vma_lut.ht_count);
|
||||
|
||||
seq_putc(m, '\n');
|
||||
}
|
||||
|
||||
@@ -2852,7 +2777,7 @@ out:
|
||||
static int i915_energy_uJ(struct seq_file *m, void *data)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = node_to_i915(m->private);
|
||||
u64 power;
|
||||
unsigned long long power;
|
||||
u32 units;
|
||||
|
||||
if (INTEL_GEN(dev_priv) < 6)
|
||||
@@ -2860,15 +2785,18 @@ static int i915_energy_uJ(struct seq_file *m, void *data)
|
||||
|
||||
intel_runtime_pm_get(dev_priv);
|
||||
|
||||
rdmsrl(MSR_RAPL_POWER_UNIT, power);
|
||||
power = (power & 0x1f00) >> 8;
|
||||
units = 1000000 / (1 << power); /* convert to uJ */
|
||||
if (rdmsrl_safe(MSR_RAPL_POWER_UNIT, &power)) {
|
||||
intel_runtime_pm_put(dev_priv);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
units = (power & 0x1f00) >> 8;
|
||||
power = I915_READ(MCH_SECP_NRG_STTS);
|
||||
power *= units;
|
||||
power = (1000000 * power) >> units; /* convert to uJ */
|
||||
|
||||
intel_runtime_pm_put(dev_priv);
|
||||
|
||||
seq_printf(m, "%llu", (long long unsigned)power);
|
||||
seq_printf(m, "%llu", power);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -3394,8 +3322,10 @@ static int i915_engine_info(struct seq_file *m, void *unused)
|
||||
ptr = I915_READ(RING_CONTEXT_STATUS_PTR(engine));
|
||||
read = GEN8_CSB_READ_PTR(ptr);
|
||||
write = GEN8_CSB_WRITE_PTR(ptr);
|
||||
seq_printf(m, "\tExeclist CSB read %d, write %d\n",
|
||||
read, write);
|
||||
seq_printf(m, "\tExeclist CSB read %d, write %d, interrupt posted? %s\n",
|
||||
read, write,
|
||||
yesno(test_bit(ENGINE_IRQ_EXECLIST,
|
||||
&engine->irq_posted)));
|
||||
if (read >= GEN8_CSB_ENTRIES)
|
||||
read = 0;
|
||||
if (write >= GEN8_CSB_ENTRIES)
|
||||
@@ -4624,7 +4554,7 @@ static void gen9_sseu_device_status(struct drm_i915_private *dev_priv,
|
||||
|
||||
sseu->slice_mask |= BIT(s);
|
||||
|
||||
if (IS_GEN9_BC(dev_priv))
|
||||
if (IS_GEN9_BC(dev_priv) || IS_CANNONLAKE(dev_priv))
|
||||
sseu->subslice_mask =
|
||||
INTEL_INFO(dev_priv)->sseu.subslice_mask;
|
||||
|
||||
@@ -4854,7 +4784,6 @@ static const struct drm_info_list i915_debugfs_list[] = {
|
||||
{"i915_gem_gtt", i915_gem_gtt_info, 0},
|
||||
{"i915_gem_pin_display", i915_gem_gtt_info, 0, (void *)1},
|
||||
{"i915_gem_stolen", i915_gem_stolen_list_info },
|
||||
{"i915_gem_pageflip", i915_gem_pageflip_info, 0},
|
||||
{"i915_gem_request", i915_gem_request_info, 0},
|
||||
{"i915_gem_seqno", i915_gem_seqno_info, 0},
|
||||
{"i915_gem_fence_regs", i915_gem_fence_regs_info, 0},
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user