Skip to content

Commit

Permalink
Merge tag 'drm-intel-next-fixes-2018-02-07' of git://anongit.freedesk…
Browse files Browse the repository at this point in the history
…top.org/drm/drm-intel into drm-next

Fix for pcode timeouts on BXT and GLK, cmdparser fixes and fixes
for new vbt version on CFL and CNL.

GVT contains vGPU reset enhancement, which refines vGPU reset flow
and the support of virtual aperture read/write when x-no-mmap=on
is set in KVM, which is required by a test case from Redhat and
also another fix for virtual OpRegion.

* tag 'drm-intel-next-fixes-2018-02-07' of git://anongit.freedesktop.org/drm/drm-intel:
  drm/i915/bios: add DP max link rate to VBT child device struct
  drm/i915/cnp: Properly handle VBT ddc pin out of bounds.
  drm/i915/cnp: Ignore VBT request for know invalid DDC pin.
  drm/i915/cmdparser: Do not check past the cmd length.
  drm/i915/cmdparser: Check reg_table_count before derefencing.
  drm/i915/bxt, glk: Increase PCODE timeouts during CDCLK freq changing
  drm/i915/gvt: Use KVM r/w to access guest opregion
  drm/i915/gvt: Fix aperture read/write emulation when enable x-no-mmap=on
  drm/i915/gvt: only reset execlist state of one engine during VM engine reset
  drm/i915/gvt: refine intel_vgpu_submission_ops as per engine ops
  • Loading branch information
Dave Airlie committed Feb 7, 2018
2 parents 2dd2779 + 6dd3104 commit 94fc27a
Show file tree
Hide file tree
Showing 17 changed files with 193 additions and 136 deletions.
15 changes: 1 addition & 14 deletions drivers/gpu/drm/i915/gvt/cfg_space.c
Original file line number Diff line number Diff line change
Expand Up @@ -119,16 +119,6 @@ static int map_aperture(struct intel_vgpu *vgpu, bool map)
if (map == vgpu->cfg_space.bar[INTEL_GVT_PCI_BAR_APERTURE].tracked)
return 0;

if (map) {
vgpu->gm.aperture_va = memremap(aperture_pa, aperture_sz,
MEMREMAP_WC);
if (!vgpu->gm.aperture_va)
return -ENOMEM;
} else {
memunmap(vgpu->gm.aperture_va);
vgpu->gm.aperture_va = NULL;
}

val = vgpu_cfg_space(vgpu)[PCI_BASE_ADDRESS_2];
if (val & PCI_BASE_ADDRESS_MEM_TYPE_64)
val = *(u64 *)(vgpu_cfg_space(vgpu) + PCI_BASE_ADDRESS_2);
Expand All @@ -141,11 +131,8 @@ static int map_aperture(struct intel_vgpu *vgpu, bool map)
aperture_pa >> PAGE_SHIFT,
aperture_sz >> PAGE_SHIFT,
map);
if (ret) {
memunmap(vgpu->gm.aperture_va);
vgpu->gm.aperture_va = NULL;
if (ret)
return ret;
}

vgpu->cfg_space.bar[INTEL_GVT_PCI_BAR_APERTURE].tracked = map;
return 0;
Expand Down
22 changes: 11 additions & 11 deletions drivers/gpu/drm/i915/gvt/execlist.c
Original file line number Diff line number Diff line change
Expand Up @@ -521,24 +521,23 @@ static void init_vgpu_execlist(struct intel_vgpu *vgpu, int ring_id)

ctx_status_ptr_reg = execlist_ring_mmio(vgpu->gvt, ring_id,
_EL_OFFSET_STATUS_PTR);

ctx_status_ptr.dw = vgpu_vreg(vgpu, ctx_status_ptr_reg);
ctx_status_ptr.read_ptr = 0;
ctx_status_ptr.write_ptr = 0x7;
vgpu_vreg(vgpu, ctx_status_ptr_reg) = ctx_status_ptr.dw;
}

static void clean_execlist(struct intel_vgpu *vgpu)
static void clean_execlist(struct intel_vgpu *vgpu, unsigned long engine_mask)
{
enum intel_engine_id i;
unsigned int tmp;
struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv;
struct intel_engine_cs *engine;
struct intel_vgpu_submission *s = &vgpu->submission;

for_each_engine(engine, vgpu->gvt->dev_priv, i) {
struct intel_vgpu_submission *s = &vgpu->submission;

kfree(s->ring_scan_buffer[i]);
s->ring_scan_buffer[i] = NULL;
s->ring_scan_buffer_size[i] = 0;
for_each_engine_masked(engine, dev_priv, engine_mask, tmp) {
kfree(s->ring_scan_buffer[engine->id]);
s->ring_scan_buffer[engine->id] = NULL;
s->ring_scan_buffer_size[engine->id] = 0;
}
}

Expand All @@ -553,9 +552,10 @@ static void reset_execlist(struct intel_vgpu *vgpu,
init_vgpu_execlist(vgpu, engine->id);
}

static int init_execlist(struct intel_vgpu *vgpu)
static int init_execlist(struct intel_vgpu *vgpu,
unsigned long engine_mask)
{
reset_execlist(vgpu, ALL_ENGINES);
reset_execlist(vgpu, engine_mask);
return 0;
}

Expand Down
6 changes: 2 additions & 4 deletions drivers/gpu/drm/i915/gvt/gvt.h
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,6 @@ struct intel_gvt_device_info {
struct intel_vgpu_gm {
u64 aperture_sz;
u64 hidden_sz;
void *aperture_va;
struct drm_mm_node low_gm_node;
struct drm_mm_node high_gm_node;
};
Expand Down Expand Up @@ -127,7 +126,6 @@ struct intel_vgpu_irq {
struct intel_vgpu_opregion {
bool mapped;
void *va;
void *va_gopregion;
u32 gfn[INTEL_GVT_OPREGION_PAGES];
};

Expand All @@ -152,8 +150,8 @@ enum {

struct intel_vgpu_submission_ops {
const char *name;
int (*init)(struct intel_vgpu *vgpu);
void (*clean)(struct intel_vgpu *vgpu);
int (*init)(struct intel_vgpu *vgpu, unsigned long engine_mask);
void (*clean)(struct intel_vgpu *vgpu, unsigned long engine_mask);
void (*reset)(struct intel_vgpu *vgpu, unsigned long engine_mask);
};

Expand Down
7 changes: 2 additions & 5 deletions drivers/gpu/drm/i915/gvt/handlers.c
Original file line number Diff line number Diff line change
Expand Up @@ -1494,7 +1494,6 @@ static int elsp_mmio_write(struct intel_vgpu *vgpu, unsigned int offset,
static int ring_mode_mmio_write(struct intel_vgpu *vgpu, unsigned int offset,
void *p_data, unsigned int bytes)
{
struct intel_vgpu_submission *s = &vgpu->submission;
u32 data = *(u32 *)p_data;
int ring_id = intel_gvt_render_mmio_to_ring_id(vgpu->gvt, offset);
bool enable_execlist;
Expand Down Expand Up @@ -1523,11 +1522,9 @@ static int ring_mode_mmio_write(struct intel_vgpu *vgpu, unsigned int offset,
if (!enable_execlist)
return 0;

if (s->active)
return 0;

ret = intel_vgpu_select_submission_ops(vgpu,
INTEL_VGPU_EXECLIST_SUBMISSION);
ENGINE_MASK(ring_id),
INTEL_VGPU_EXECLIST_SUBMISSION);
if (ret)
return ret;

Expand Down
36 changes: 34 additions & 2 deletions drivers/gpu/drm/i915/gvt/kvmgt.c
Original file line number Diff line number Diff line change
Expand Up @@ -651,6 +651,39 @@ static int intel_vgpu_bar_rw(struct intel_vgpu *vgpu, int bar, uint64_t off,
return ret;
}

static inline bool intel_vgpu_in_aperture(struct intel_vgpu *vgpu, uint64_t off)
{
return off >= vgpu_aperture_offset(vgpu) &&
off < vgpu_aperture_offset(vgpu) + vgpu_aperture_sz(vgpu);
}

static int intel_vgpu_aperture_rw(struct intel_vgpu *vgpu, uint64_t off,
void *buf, unsigned long count, bool is_write)
{
void *aperture_va;

if (!intel_vgpu_in_aperture(vgpu, off) ||
!intel_vgpu_in_aperture(vgpu, off + count)) {
gvt_vgpu_err("Invalid aperture offset %llu\n", off);
return -EINVAL;
}

aperture_va = io_mapping_map_wc(&vgpu->gvt->dev_priv->ggtt.iomap,
ALIGN_DOWN(off, PAGE_SIZE),
count + offset_in_page(off));
if (!aperture_va)
return -EIO;

if (is_write)
memcpy(aperture_va + offset_in_page(off), buf, count);
else
memcpy(buf, aperture_va + offset_in_page(off), count);

io_mapping_unmap(aperture_va);

return 0;
}

static ssize_t intel_vgpu_rw(struct mdev_device *mdev, char *buf,
size_t count, loff_t *ppos, bool is_write)
{
Expand Down Expand Up @@ -679,8 +712,7 @@ static ssize_t intel_vgpu_rw(struct mdev_device *mdev, char *buf,
buf, count, is_write);
break;
case VFIO_PCI_BAR2_REGION_INDEX:
ret = intel_vgpu_bar_rw(vgpu, PCI_BASE_ADDRESS_2, pos,
buf, count, is_write);
ret = intel_vgpu_aperture_rw(vgpu, pos, buf, count, is_write);
break;
case VFIO_PCI_BAR1_REGION_INDEX:
case VFIO_PCI_BAR3_REGION_INDEX:
Expand Down
42 changes: 0 additions & 42 deletions drivers/gpu/drm/i915/gvt/mmio.c
Original file line number Diff line number Diff line change
Expand Up @@ -56,38 +56,6 @@ int intel_vgpu_gpa_to_mmio_offset(struct intel_vgpu *vgpu, u64 gpa)
(reg >= gvt->device_info.gtt_start_offset \
&& reg < gvt->device_info.gtt_start_offset + gvt_ggtt_sz(gvt))

static bool vgpu_gpa_is_aperture(struct intel_vgpu *vgpu, uint64_t gpa)
{
u64 aperture_gpa = intel_vgpu_get_bar_gpa(vgpu, PCI_BASE_ADDRESS_2);
u64 aperture_sz = vgpu_aperture_sz(vgpu);

return gpa >= aperture_gpa && gpa < aperture_gpa + aperture_sz;
}

static int vgpu_aperture_rw(struct intel_vgpu *vgpu, uint64_t gpa,
void *pdata, unsigned int size, bool is_read)
{
u64 aperture_gpa = intel_vgpu_get_bar_gpa(vgpu, PCI_BASE_ADDRESS_2);
u64 offset = gpa - aperture_gpa;

if (!vgpu_gpa_is_aperture(vgpu, gpa + size - 1)) {
gvt_vgpu_err("Aperture rw out of range, offset %llx, size %d\n",
offset, size);
return -EINVAL;
}

if (!vgpu->gm.aperture_va) {
gvt_vgpu_err("BAR is not enabled\n");
return -ENXIO;
}

if (is_read)
memcpy(pdata, vgpu->gm.aperture_va + offset, size);
else
memcpy(vgpu->gm.aperture_va + offset, pdata, size);
return 0;
}

static void failsafe_emulate_mmio_rw(struct intel_vgpu *vgpu, uint64_t pa,
void *p_data, unsigned int bytes, bool read)
{
Expand Down Expand Up @@ -144,11 +112,6 @@ int intel_vgpu_emulate_mmio_read(struct intel_vgpu *vgpu, uint64_t pa,
}
mutex_lock(&gvt->lock);

if (vgpu_gpa_is_aperture(vgpu, pa)) {
ret = vgpu_aperture_rw(vgpu, pa, p_data, bytes, true);
goto out;
}

offset = intel_vgpu_gpa_to_mmio_offset(vgpu, pa);

if (WARN_ON(bytes > 8))
Expand Down Expand Up @@ -222,11 +185,6 @@ int intel_vgpu_emulate_mmio_write(struct intel_vgpu *vgpu, uint64_t pa,

mutex_lock(&gvt->lock);

if (vgpu_gpa_is_aperture(vgpu, pa)) {
ret = vgpu_aperture_rw(vgpu, pa, p_data, bytes, false);
goto out;
}

offset = intel_vgpu_gpa_to_mmio_offset(vgpu, pa);

if (WARN_ON(bytes > 8))
Expand Down
98 changes: 70 additions & 28 deletions drivers/gpu/drm/i915/gvt/opregion.c
Original file line number Diff line number Diff line change
Expand Up @@ -299,21 +299,13 @@ int intel_vgpu_opregion_base_write_handler(struct intel_vgpu *vgpu, u32 gpa)
{

int i, ret = 0;
unsigned long pfn;

gvt_dbg_core("emulate opregion from kernel\n");

switch (intel_gvt_host.hypervisor_type) {
case INTEL_GVT_HYPERVISOR_KVM:
pfn = intel_gvt_hypervisor_gfn_to_mfn(vgpu, gpa >> PAGE_SHIFT);
vgpu_opregion(vgpu)->va_gopregion = memremap(pfn << PAGE_SHIFT,
INTEL_GVT_OPREGION_SIZE,
MEMREMAP_WB);
if (!vgpu_opregion(vgpu)->va_gopregion) {
gvt_vgpu_err("failed to map guest opregion\n");
ret = -EFAULT;
}
vgpu_opregion(vgpu)->mapped = true;
for (i = 0; i < INTEL_GVT_OPREGION_PAGES; i++)
vgpu_opregion(vgpu)->gfn[i] = (gpa >> PAGE_SHIFT) + i;
break;
case INTEL_GVT_HYPERVISOR_XEN:
/**
Expand Down Expand Up @@ -352,10 +344,7 @@ void intel_vgpu_clean_opregion(struct intel_vgpu *vgpu)
if (vgpu_opregion(vgpu)->mapped)
map_vgpu_opregion(vgpu, false);
} else if (intel_gvt_host.hypervisor_type == INTEL_GVT_HYPERVISOR_KVM) {
if (vgpu_opregion(vgpu)->mapped) {
memunmap(vgpu_opregion(vgpu)->va_gopregion);
vgpu_opregion(vgpu)->va_gopregion = NULL;
}
/* Guest opregion is released by VFIO */
}
free_pages((unsigned long)vgpu_opregion(vgpu)->va,
get_order(INTEL_GVT_OPREGION_SIZE));
Expand Down Expand Up @@ -480,19 +469,40 @@ static bool querying_capabilities(u32 scic)
*/
int intel_vgpu_emulate_opregion_request(struct intel_vgpu *vgpu, u32 swsci)
{
u32 *scic, *parm;
u32 scic, parm;
u32 func, subfunc;
u64 scic_pa = 0, parm_pa = 0;
int ret;

switch (intel_gvt_host.hypervisor_type) {
case INTEL_GVT_HYPERVISOR_XEN:
scic = vgpu_opregion(vgpu)->va + INTEL_GVT_OPREGION_SCIC;
parm = vgpu_opregion(vgpu)->va + INTEL_GVT_OPREGION_PARM;
scic = *((u32 *)vgpu_opregion(vgpu)->va +
INTEL_GVT_OPREGION_SCIC);
parm = *((u32 *)vgpu_opregion(vgpu)->va +
INTEL_GVT_OPREGION_PARM);
break;
case INTEL_GVT_HYPERVISOR_KVM:
scic = vgpu_opregion(vgpu)->va_gopregion +
INTEL_GVT_OPREGION_SCIC;
parm = vgpu_opregion(vgpu)->va_gopregion +
INTEL_GVT_OPREGION_PARM;
scic_pa = (vgpu_opregion(vgpu)->gfn[0] << PAGE_SHIFT) +
INTEL_GVT_OPREGION_SCIC;
parm_pa = (vgpu_opregion(vgpu)->gfn[0] << PAGE_SHIFT) +
INTEL_GVT_OPREGION_PARM;

ret = intel_gvt_hypervisor_read_gpa(vgpu, scic_pa,
&scic, sizeof(scic));
if (ret) {
gvt_vgpu_err("guest opregion read error %d, gpa 0x%llx, len %lu\n",
ret, scic_pa, sizeof(scic));
return ret;
}

ret = intel_gvt_hypervisor_read_gpa(vgpu, parm_pa,
&parm, sizeof(parm));
if (ret) {
gvt_vgpu_err("guest opregion read error %d, gpa 0x%llx, len %lu\n",
ret, scic_pa, sizeof(scic));
return ret;
}

break;
default:
gvt_vgpu_err("not supported hypervisor\n");
Expand All @@ -510,9 +520,9 @@ int intel_vgpu_emulate_opregion_request(struct intel_vgpu *vgpu, u32 swsci)
return 0;
}

func = GVT_OPREGION_FUNC(*scic);
subfunc = GVT_OPREGION_SUBFUNC(*scic);
if (!querying_capabilities(*scic)) {
func = GVT_OPREGION_FUNC(scic);
subfunc = GVT_OPREGION_SUBFUNC(scic);
if (!querying_capabilities(scic)) {
gvt_vgpu_err("requesting runtime service: func \"%s\","
" subfunc \"%s\"\n",
opregion_func_name(func),
Expand All @@ -521,11 +531,43 @@ int intel_vgpu_emulate_opregion_request(struct intel_vgpu *vgpu, u32 swsci)
* emulate exit status of function call, '0' means
* "failure, generic, unsupported or unknown cause"
*/
*scic &= ~OPREGION_SCIC_EXIT_MASK;
return 0;
scic &= ~OPREGION_SCIC_EXIT_MASK;
goto out;
}

scic = 0;
parm = 0;

out:
switch (intel_gvt_host.hypervisor_type) {
case INTEL_GVT_HYPERVISOR_XEN:
*((u32 *)vgpu_opregion(vgpu)->va +
INTEL_GVT_OPREGION_SCIC) = scic;
*((u32 *)vgpu_opregion(vgpu)->va +
INTEL_GVT_OPREGION_PARM) = parm;
break;
case INTEL_GVT_HYPERVISOR_KVM:
ret = intel_gvt_hypervisor_write_gpa(vgpu, scic_pa,
&scic, sizeof(scic));
if (ret) {
gvt_vgpu_err("guest opregion write error %d, gpa 0x%llx, len %lu\n",
ret, scic_pa, sizeof(scic));
return ret;
}

ret = intel_gvt_hypervisor_write_gpa(vgpu, parm_pa,
&parm, sizeof(parm));
if (ret) {
gvt_vgpu_err("guest opregion write error %d, gpa 0x%llx, len %lu\n",
ret, scic_pa, sizeof(scic));
return ret;
}

break;
default:
gvt_vgpu_err("not supported hypervisor\n");
return -EINVAL;
}

*scic = 0;
*parm = 0;
return 0;
}
Loading

0 comments on commit 94fc27a

Please sign in to comment.