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-2015-02-14' of git://anongit.freedesktop.org/drm-intel into drm-next
- use the atomic helpers for plane_upate/disable hooks (Matt Roper) - refactor the initial plane config code (Damien) - ppgtt prep patches for dynamic pagetable alloc (Ben Widawsky, reworked and rebased by a lot of other people) - framebuffer modifier support from Tvrtko Ursulin, drm core code from Rob Clark - piles of workaround patches for skl from Damien and Nick Hoath - vGPU support for xengt on the client side (Yu Zhang) - and the usual smaller things all over * tag 'drm-intel-next-2015-02-14' of git://anongit.freedesktop.org/drm-intel: (88 commits) drm/i915: Update DRIVER_DATE to 20150214 drm/i915: Remove references to previously removed UMS config option drm/i915/skl: Use a LRI for WaDisableDgMirrorFixInHalfSliceChicken5 drm/i915/skl: Fix always true comparison in a revision id check drm/i915/skl: Implement WaEnableLbsSlaRetryTimerDecrement drm/i915/skl: Implement WaSetDisablePixMaskCammingAndRhwoInCommonSliceChicken drm/i915: Add process identifier to requests drm/i915/skl: Implement WaBarrierPerformanceFixDisable drm/i915/skl: Implement WaCcsTlbPrefetchDisable:skl drm/i915/skl: Implement WaDisableChickenBitTSGBarrierAckForFFSliceCS drm/i915/skl: Implement WaDisableHDCInvalidation drm/i915/skl: Implement WaDisableLSQCROPERFforOCL drm/i915/skl: Implement WaDisablePartialResolveInVc drm/i915/skl: Introduce a SKL specific init_workarounds() drm/i915/skl: Document that we implement WaRsClearFWBitsAtReset drm/i915/skl: Implement WaSetGAPSunitClckGateDisable drm/i915/skl: Make the init clock gating function skylake specific drm/i915/skl: Provide a gen9 specific init_render_ring() drm/i915/skl: Document the WM read latency W/A with its name drm/i915/skl: Also detect eDRAM on SKL ...
This commit is contained in:
@@ -3979,6 +3979,11 @@ int num_ioctls;</synopsis>
|
||||
!Fdrivers/gpu/drm/i915/i915_irq.c intel_runtime_pm_disable_interrupts
|
||||
!Fdrivers/gpu/drm/i915/i915_irq.c intel_runtime_pm_enable_interrupts
|
||||
</sect2>
|
||||
<sect2>
|
||||
<title>Intel GVT-g Guest Support(vGPU)</title>
|
||||
!Pdrivers/gpu/drm/i915/i915_vgpu.c Intel GVT-g guest support
|
||||
!Idrivers/gpu/drm/i915/i915_vgpu.c
|
||||
</sect2>
|
||||
</sect1>
|
||||
<sect1>
|
||||
<title>Display Hardware Handling</title>
|
||||
|
||||
@@ -3272,6 +3272,12 @@ static int framebuffer_check(const struct drm_mode_fb_cmd2 *r)
|
||||
DRM_DEBUG_KMS("bad pitch %u for plane %d\n", r->pitches[i], i);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (r->modifier[i] && !(r->flags & DRM_MODE_FB_MODIFIERS)) {
|
||||
DRM_DEBUG_KMS("bad fb modifier %llu for plane %d\n",
|
||||
r->modifier[i], i);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -3285,7 +3291,7 @@ static struct drm_framebuffer *add_framebuffer_internal(struct drm_device *dev,
|
||||
struct drm_framebuffer *fb;
|
||||
int ret;
|
||||
|
||||
if (r->flags & ~DRM_MODE_FB_INTERLACED) {
|
||||
if (r->flags & ~(DRM_MODE_FB_INTERLACED | DRM_MODE_FB_MODIFIERS)) {
|
||||
DRM_DEBUG_KMS("bad framebuffer flags 0x%08x\n", r->flags);
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
@@ -3301,6 +3307,12 @@ static struct drm_framebuffer *add_framebuffer_internal(struct drm_device *dev,
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
if (r->flags & DRM_MODE_FB_MODIFIERS &&
|
||||
!dev->mode_config.allow_fb_modifiers) {
|
||||
DRM_DEBUG_KMS("driver does not support fb modifiers\n");
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
ret = framebuffer_check(r);
|
||||
if (ret)
|
||||
return ERR_PTR(ret);
|
||||
|
||||
@@ -837,6 +837,7 @@ void drm_helper_mode_fill_fb_struct(struct drm_framebuffer *fb,
|
||||
for (i = 0; i < 4; i++) {
|
||||
fb->pitches[i] = mode_cmd->pitches[i];
|
||||
fb->offsets[i] = mode_cmd->offsets[i];
|
||||
fb->modifier[i] = mode_cmd->modifier[i];
|
||||
}
|
||||
drm_fb_get_bpp_depth(mode_cmd->pixel_format, &fb->depth,
|
||||
&fb->bits_per_pixel);
|
||||
|
||||
@@ -321,6 +321,9 @@ static int drm_getcap(struct drm_device *dev, void *data, struct drm_file *file_
|
||||
else
|
||||
req->value = 64;
|
||||
break;
|
||||
case DRM_CAP_ADDFB2_MODIFIERS:
|
||||
req->value = dev->mode_config.allow_fb_modifiers;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@@ -83,6 +83,9 @@ i915-y += dvo_ch7017.o \
|
||||
intel_sdvo.o \
|
||||
intel_tv.o
|
||||
|
||||
# virtual gpu code
|
||||
i915-y += i915_vgpu.o
|
||||
|
||||
# legacy horrors
|
||||
i915-y += i915_dma.o \
|
||||
i915_ums.o
|
||||
|
||||
@@ -1778,11 +1778,12 @@ static int i915_gem_framebuffer_info(struct seq_file *m, void *data)
|
||||
ifbdev = dev_priv->fbdev;
|
||||
fb = to_intel_framebuffer(ifbdev->helper.fb);
|
||||
|
||||
seq_printf(m, "fbcon size: %d x %d, depth %d, %d bpp, refcount %d, obj ",
|
||||
seq_printf(m, "fbcon size: %d x %d, depth %d, %d bpp, modifier 0x%llx, refcount %d, obj ",
|
||||
fb->base.width,
|
||||
fb->base.height,
|
||||
fb->base.depth,
|
||||
fb->base.bits_per_pixel,
|
||||
fb->base.modifier[0],
|
||||
atomic_read(&fb->base.refcount.refcount));
|
||||
describe_obj(m, fb->obj);
|
||||
seq_putc(m, '\n');
|
||||
@@ -1793,11 +1794,12 @@ static int i915_gem_framebuffer_info(struct seq_file *m, void *data)
|
||||
if (ifbdev && &fb->base == ifbdev->helper.fb)
|
||||
continue;
|
||||
|
||||
seq_printf(m, "user size: %d x %d, depth %d, %d bpp, refcount %d, obj ",
|
||||
seq_printf(m, "user size: %d x %d, depth %d, %d bpp, modifier 0x%llx, refcount %d, obj ",
|
||||
fb->base.width,
|
||||
fb->base.height,
|
||||
fb->base.depth,
|
||||
fb->base.bits_per_pixel,
|
||||
fb->base.modifier[0],
|
||||
atomic_read(&fb->base.refcount.refcount));
|
||||
describe_obj(m, fb->obj);
|
||||
seq_putc(m, '\n');
|
||||
@@ -4226,10 +4228,7 @@ i915_max_freq_set(void *data, u64 val)
|
||||
|
||||
dev_priv->rps.max_freq_softlimit = val;
|
||||
|
||||
if (IS_VALLEYVIEW(dev))
|
||||
valleyview_set_rps(dev, val);
|
||||
else
|
||||
gen6_set_rps(dev, val);
|
||||
intel_set_rps(dev, val);
|
||||
|
||||
mutex_unlock(&dev_priv->rps.hw_lock);
|
||||
|
||||
@@ -4304,10 +4303,7 @@ i915_min_freq_set(void *data, u64 val)
|
||||
|
||||
dev_priv->rps.min_freq_softlimit = val;
|
||||
|
||||
if (IS_VALLEYVIEW(dev))
|
||||
valleyview_set_rps(dev, val);
|
||||
else
|
||||
gen6_set_rps(dev, val);
|
||||
intel_set_rps(dev, val);
|
||||
|
||||
mutex_unlock(&dev_priv->rps.hw_lock);
|
||||
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
#include "intel_drv.h"
|
||||
#include <drm/i915_drm.h>
|
||||
#include "i915_drv.h"
|
||||
#include "i915_vgpu.h"
|
||||
#include "i915_trace.h"
|
||||
#include <linux/pci.h>
|
||||
#include <linux/console.h>
|
||||
@@ -842,6 +843,13 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Notify a valid surface after modesetting,
|
||||
* when running inside a VM.
|
||||
*/
|
||||
if (intel_vgpu_active(dev))
|
||||
I915_WRITE(vgtif_reg(display_ready), VGT_DRV_DISPLAY_READY);
|
||||
|
||||
i915_setup_sysfs(dev);
|
||||
|
||||
if (INTEL_INFO(dev)->num_pipes) {
|
||||
|
||||
@@ -369,6 +369,19 @@ static const struct intel_device_info intel_skylake_info = {
|
||||
IVB_CURSOR_OFFSETS,
|
||||
};
|
||||
|
||||
static const struct intel_device_info intel_skylake_gt3_info = {
|
||||
.is_preliminary = 1,
|
||||
.is_skylake = 1,
|
||||
.gen = 9, .num_pipes = 3,
|
||||
.need_gfx_hws = 1, .has_hotplug = 1,
|
||||
.ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING | BSD2_RING,
|
||||
.has_llc = 1,
|
||||
.has_ddi = 1,
|
||||
.has_fbc = 1,
|
||||
GEN_DEFAULT_PIPEOFFSETS,
|
||||
IVB_CURSOR_OFFSETS,
|
||||
};
|
||||
|
||||
/*
|
||||
* Make sure any device matches here are from most specific to most
|
||||
* general. For example, since the Quanta match is based on the subsystem
|
||||
@@ -406,7 +419,9 @@ static const struct intel_device_info intel_skylake_info = {
|
||||
INTEL_BDW_GT3M_IDS(&intel_broadwell_gt3m_info), \
|
||||
INTEL_BDW_GT3D_IDS(&intel_broadwell_gt3d_info), \
|
||||
INTEL_CHV_IDS(&intel_cherryview_info), \
|
||||
INTEL_SKL_IDS(&intel_skylake_info)
|
||||
INTEL_SKL_GT1_IDS(&intel_skylake_info), \
|
||||
INTEL_SKL_GT2_IDS(&intel_skylake_info), \
|
||||
INTEL_SKL_GT3_IDS(&intel_skylake_gt3_info) \
|
||||
|
||||
static const struct pci_device_id pciidlist[] = { /* aka */
|
||||
INTEL_PCI_IDS,
|
||||
@@ -1630,11 +1645,9 @@ static int __init i915_init(void)
|
||||
|
||||
if (!(driver.driver_features & DRIVER_MODESET)) {
|
||||
driver.get_vblank_timestamp = NULL;
|
||||
#ifndef CONFIG_DRM_I915_UMS
|
||||
/* Silently fail loading to not upset userspace. */
|
||||
DRM_DEBUG_DRIVER("KMS and UMS disabled.\n");
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1650,10 +1663,8 @@ static int __init i915_init(void)
|
||||
|
||||
static void __exit i915_exit(void)
|
||||
{
|
||||
#ifndef CONFIG_DRM_I915_UMS
|
||||
if (!(driver.driver_features & DRIVER_MODESET))
|
||||
return; /* Never loaded a driver. */
|
||||
#endif
|
||||
|
||||
drm_pci_exit(&driver, &i915_pci_driver);
|
||||
}
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
#define _I915_DRV_H_
|
||||
|
||||
#include <uapi/drm/i915_drm.h>
|
||||
#include <uapi/drm/drm_fourcc.h>
|
||||
|
||||
#include "i915_reg.h"
|
||||
#include "intel_bios.h"
|
||||
@@ -55,7 +56,7 @@
|
||||
|
||||
#define DRIVER_NAME "i915"
|
||||
#define DRIVER_DESC "Intel Graphics"
|
||||
#define DRIVER_DATE "20150130"
|
||||
#define DRIVER_DATE "20150214"
|
||||
|
||||
#undef WARN_ON
|
||||
/* Many gcc seem to no see through this and fall over :( */
|
||||
@@ -772,10 +773,10 @@ struct intel_context {
|
||||
};
|
||||
|
||||
struct i915_fbc {
|
||||
unsigned long size;
|
||||
unsigned long uncompressed_size;
|
||||
unsigned threshold;
|
||||
unsigned int fb_id;
|
||||
enum plane plane;
|
||||
struct intel_crtc *crtc;
|
||||
int y;
|
||||
|
||||
struct drm_mm_node compressed_fb;
|
||||
@@ -1640,6 +1641,10 @@ struct i915_workarounds {
|
||||
u32 count;
|
||||
};
|
||||
|
||||
struct i915_virtual_gpu {
|
||||
bool active;
|
||||
};
|
||||
|
||||
struct drm_i915_private {
|
||||
struct drm_device *dev;
|
||||
struct kmem_cache *slab;
|
||||
@@ -1652,6 +1657,8 @@ struct drm_i915_private {
|
||||
|
||||
struct intel_uncore uncore;
|
||||
|
||||
struct i915_virtual_gpu vgpu;
|
||||
|
||||
struct intel_gmbus gmbus[GMBUS_NUM_PORTS];
|
||||
|
||||
|
||||
@@ -2153,6 +2160,9 @@ struct drm_i915_gem_request {
|
||||
/** file_priv list entry for this request */
|
||||
struct list_head client_list;
|
||||
|
||||
/** process identifier submitting this request */
|
||||
struct pid *pid;
|
||||
|
||||
uint32_t uniq;
|
||||
|
||||
/**
|
||||
@@ -2339,6 +2349,7 @@ struct drm_i915_cmd_table {
|
||||
})
|
||||
#define INTEL_INFO(p) (&__I915__(p)->info)
|
||||
#define INTEL_DEVID(p) (INTEL_INFO(p)->device_id)
|
||||
#define INTEL_REVID(p) (__I915__(p)->dev->pdev->revision)
|
||||
|
||||
#define IS_I830(dev) (INTEL_DEVID(dev) == 0x3577)
|
||||
#define IS_845G(dev) (INTEL_DEVID(dev) == 0x2562)
|
||||
@@ -2361,9 +2372,6 @@ struct drm_i915_cmd_table {
|
||||
#define IS_IVB_GT1(dev) (INTEL_DEVID(dev) == 0x0156 || \
|
||||
INTEL_DEVID(dev) == 0x0152 || \
|
||||
INTEL_DEVID(dev) == 0x015a)
|
||||
#define IS_SNB_GT1(dev) (INTEL_DEVID(dev) == 0x0102 || \
|
||||
INTEL_DEVID(dev) == 0x0106 || \
|
||||
INTEL_DEVID(dev) == 0x010A)
|
||||
#define IS_VALLEYVIEW(dev) (INTEL_INFO(dev)->is_valleyview)
|
||||
#define IS_CHERRYVIEW(dev) (INTEL_INFO(dev)->is_valleyview && IS_GEN8(dev))
|
||||
#define IS_HASWELL(dev) (INTEL_INFO(dev)->is_haswell)
|
||||
@@ -2386,6 +2394,12 @@ struct drm_i915_cmd_table {
|
||||
INTEL_DEVID(dev) == 0x0A1E)
|
||||
#define IS_PRELIMINARY_HW(intel_info) ((intel_info)->is_preliminary)
|
||||
|
||||
#define SKL_REVID_A0 (0x0)
|
||||
#define SKL_REVID_B0 (0x1)
|
||||
#define SKL_REVID_C0 (0x2)
|
||||
#define SKL_REVID_D0 (0x3)
|
||||
#define SKL_REVID_E0 (0x4)
|
||||
|
||||
/*
|
||||
* The genX designation typically refers to the render engine, so render
|
||||
* capability related checks should use IS_GEN, while display and other checks
|
||||
@@ -2493,8 +2507,6 @@ extern int i915_max_ioctl;
|
||||
|
||||
extern int i915_suspend_legacy(struct drm_device *dev, pm_message_t state);
|
||||
extern int i915_resume_legacy(struct drm_device *dev);
|
||||
extern int i915_master_create(struct drm_device *dev, struct drm_master *master);
|
||||
extern void i915_master_destroy(struct drm_device *dev, struct drm_master *master);
|
||||
|
||||
/* i915_params.c */
|
||||
struct i915_params {
|
||||
@@ -2577,6 +2589,10 @@ void intel_uncore_forcewake_get(struct drm_i915_private *dev_priv,
|
||||
void intel_uncore_forcewake_put(struct drm_i915_private *dev_priv,
|
||||
enum forcewake_domains domains);
|
||||
void assert_forcewakes_inactive(struct drm_i915_private *dev_priv);
|
||||
static inline bool intel_vgpu_active(struct drm_device *dev)
|
||||
{
|
||||
return to_i915(dev)->vgpu.active;
|
||||
}
|
||||
|
||||
void
|
||||
i915_enable_pipestat(struct drm_i915_private *dev_priv, enum pipe pipe,
|
||||
@@ -3182,8 +3198,7 @@ extern void i915_redisable_vga(struct drm_device *dev);
|
||||
extern void i915_redisable_vga_power_on(struct drm_device *dev);
|
||||
extern bool ironlake_set_drps(struct drm_device *dev, u8 val);
|
||||
extern void intel_init_pch_refclk(struct drm_device *dev);
|
||||
extern void gen6_set_rps(struct drm_device *dev, u8 val);
|
||||
extern void valleyview_set_rps(struct drm_device *dev, u8 val);
|
||||
extern void intel_set_rps(struct drm_device *dev, u8 val);
|
||||
extern void intel_set_memory_cxsr(struct drm_i915_private *dev_priv,
|
||||
bool enable);
|
||||
extern void intel_detect_pch(struct drm_device *dev);
|
||||
@@ -3196,8 +3211,6 @@ int i915_reg_read_ioctl(struct drm_device *dev, void *data,
|
||||
int i915_get_reset_stats_ioctl(struct drm_device *dev, void *data,
|
||||
struct drm_file *file);
|
||||
|
||||
void intel_notify_mmio_flip(struct intel_engine_cs *ring);
|
||||
|
||||
/* overlay */
|
||||
extern struct intel_overlay_error_state *intel_overlay_capture_error_state(struct drm_device *dev);
|
||||
extern void intel_overlay_print_error_state(struct drm_i915_error_state_buf *e,
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
#include <drm/drm_vma_manager.h>
|
||||
#include <drm/i915_drm.h>
|
||||
#include "i915_drv.h"
|
||||
#include "i915_vgpu.h"
|
||||
#include "i915_trace.h"
|
||||
#include "intel_drv.h"
|
||||
#include <linux/oom.h>
|
||||
@@ -2492,6 +2493,8 @@ int __i915_add_request(struct intel_engine_cs *ring,
|
||||
list_add_tail(&request->client_list,
|
||||
&file_priv->mm.request_list);
|
||||
spin_unlock(&file_priv->mm.lock);
|
||||
|
||||
request->pid = get_pid(task_pid(current));
|
||||
}
|
||||
|
||||
trace_i915_gem_request_add(request);
|
||||
@@ -2572,6 +2575,8 @@ static void i915_gem_free_request(struct drm_i915_gem_request *request)
|
||||
list_del(&request->list);
|
||||
i915_gem_request_remove_from_client(request);
|
||||
|
||||
put_pid(request->pid);
|
||||
|
||||
i915_gem_request_unreference(request);
|
||||
}
|
||||
|
||||
@@ -4987,6 +4992,10 @@ i915_gem_load(struct drm_device *dev)
|
||||
else
|
||||
dev_priv->num_fence_regs = 8;
|
||||
|
||||
if (intel_vgpu_active(dev))
|
||||
dev_priv->num_fence_regs =
|
||||
I915_READ(vgtif_reg(avail_rs.fence_num));
|
||||
|
||||
/* Initialize fence registers to zero */
|
||||
INIT_LIST_HEAD(&dev_priv->mm.fence_list);
|
||||
i915_gem_restore_fences(dev);
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
#include <drm/drmP.h>
|
||||
#include <drm/i915_drm.h>
|
||||
#include "i915_drv.h"
|
||||
#include "i915_vgpu.h"
|
||||
#include "i915_trace.h"
|
||||
#include "intel_drv.h"
|
||||
|
||||
@@ -103,6 +104,9 @@ static int sanitize_enable_ppgtt(struct drm_device *dev, int enable_ppgtt)
|
||||
has_aliasing_ppgtt = INTEL_INFO(dev)->gen >= 6;
|
||||
has_full_ppgtt = INTEL_INFO(dev)->gen >= 7;
|
||||
|
||||
if (intel_vgpu_active(dev))
|
||||
has_full_ppgtt = false; /* emulation is too hard */
|
||||
|
||||
/*
|
||||
* We don't allow disabling PPGTT for gen9+ as it's a requirement for
|
||||
* execlists, the sole mechanism available to submit work.
|
||||
@@ -375,7 +379,7 @@ static void gen8_ppgtt_insert_entries(struct i915_address_space *vm,
|
||||
pt_vaddr = NULL;
|
||||
|
||||
for_each_sg_page(pages->sgl, &sg_iter, pages->nents, 0) {
|
||||
if (WARN_ON(pdpe >= GEN8_LEGACY_PDPS))
|
||||
if (WARN_ON(pdpe >= GEN8_LEGACY_PDPES))
|
||||
break;
|
||||
|
||||
if (pt_vaddr == NULL)
|
||||
@@ -486,7 +490,7 @@ bail:
|
||||
static int gen8_ppgtt_allocate_page_tables(struct i915_hw_ppgtt *ppgtt,
|
||||
const int max_pdp)
|
||||
{
|
||||
struct page **pt_pages[GEN8_LEGACY_PDPS];
|
||||
struct page **pt_pages[GEN8_LEGACY_PDPES];
|
||||
int i, ret;
|
||||
|
||||
for (i = 0; i < max_pdp; i++) {
|
||||
@@ -537,7 +541,7 @@ static int gen8_ppgtt_allocate_page_directories(struct i915_hw_ppgtt *ppgtt,
|
||||
return -ENOMEM;
|
||||
|
||||
ppgtt->num_pd_pages = 1 << get_order(max_pdp << PAGE_SHIFT);
|
||||
BUG_ON(ppgtt->num_pd_pages > GEN8_LEGACY_PDPS);
|
||||
BUG_ON(ppgtt->num_pd_pages > GEN8_LEGACY_PDPES);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -797,6 +801,16 @@ static int hsw_mm_switch(struct i915_hw_ppgtt *ppgtt,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int vgpu_mm_switch(struct i915_hw_ppgtt *ppgtt,
|
||||
struct intel_engine_cs *ring)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(ppgtt->base.dev);
|
||||
|
||||
I915_WRITE(RING_PP_DIR_DCLV(ring), PP_DIR_DCLV_2G);
|
||||
I915_WRITE(RING_PP_DIR_BASE(ring), get_pd_offset(ppgtt));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gen7_mm_switch(struct i915_hw_ppgtt *ppgtt,
|
||||
struct intel_engine_cs *ring)
|
||||
{
|
||||
@@ -1032,11 +1046,14 @@ alloc:
|
||||
goto alloc;
|
||||
}
|
||||
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (ppgtt->node.start < dev_priv->gtt.mappable_end)
|
||||
DRM_DEBUG("Forced to use aperture for PDEs\n");
|
||||
|
||||
ppgtt->num_pd_entries = GEN6_PPGTT_PD_ENTRIES;
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gen6_ppgtt_allocate_page_tables(struct i915_hw_ppgtt *ppgtt)
|
||||
@@ -1123,6 +1140,9 @@ static int gen6_ppgtt_init(struct i915_hw_ppgtt *ppgtt)
|
||||
} else
|
||||
BUG();
|
||||
|
||||
if (intel_vgpu_active(dev))
|
||||
ppgtt->switch_mm = vgpu_mm_switch;
|
||||
|
||||
ret = gen6_ppgtt_alloc(ppgtt);
|
||||
if (ret)
|
||||
return ret;
|
||||
@@ -1753,6 +1773,16 @@ static int i915_gem_setup_global_gtt(struct drm_device *dev,
|
||||
|
||||
/* Subtract the guard page ... */
|
||||
drm_mm_init(&ggtt_vm->mm, start, end - start - PAGE_SIZE);
|
||||
|
||||
dev_priv->gtt.base.start = start;
|
||||
dev_priv->gtt.base.total = end - start;
|
||||
|
||||
if (intel_vgpu_active(dev)) {
|
||||
ret = intel_vgt_balloon(dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (!HAS_LLC(dev))
|
||||
dev_priv->gtt.base.mm.color_adjust = i915_gtt_color_adjust;
|
||||
|
||||
@@ -1772,9 +1802,6 @@ static int i915_gem_setup_global_gtt(struct drm_device *dev,
|
||||
vma->bound |= GLOBAL_BIND;
|
||||
}
|
||||
|
||||
dev_priv->gtt.base.start = start;
|
||||
dev_priv->gtt.base.total = end - start;
|
||||
|
||||
/* Clear any non-preallocated blocks */
|
||||
drm_mm_for_each_hole(entry, &ggtt_vm->mm, hole_start, hole_end) {
|
||||
DRM_DEBUG_KMS("clearing unused GTT space: [%lx, %lx]\n",
|
||||
@@ -1826,6 +1853,9 @@ void i915_global_gtt_cleanup(struct drm_device *dev)
|
||||
}
|
||||
|
||||
if (drm_mm_initialized(&vm->mm)) {
|
||||
if (intel_vgpu_active(dev))
|
||||
intel_vgt_deballoon();
|
||||
|
||||
drm_mm_takedown(&vm->mm);
|
||||
list_del(&vm->global_link);
|
||||
}
|
||||
|
||||
@@ -88,7 +88,7 @@ typedef gen8_gtt_pte_t gen8_ppgtt_pde_t;
|
||||
#define GEN8_PDE_MASK 0x1ff
|
||||
#define GEN8_PTE_SHIFT 12
|
||||
#define GEN8_PTE_MASK 0x1ff
|
||||
#define GEN8_LEGACY_PDPS 4
|
||||
#define GEN8_LEGACY_PDPES 4
|
||||
#define GEN8_PTES_PER_PAGE (PAGE_SIZE / sizeof(gen8_gtt_pte_t))
|
||||
#define GEN8_PDES_PER_PAGE (PAGE_SIZE / sizeof(gen8_ppgtt_pde_t))
|
||||
|
||||
@@ -273,16 +273,16 @@ struct i915_hw_ppgtt {
|
||||
unsigned num_pd_pages; /* gen8+ */
|
||||
union {
|
||||
struct page **pt_pages;
|
||||
struct page **gen8_pt_pages[GEN8_LEGACY_PDPS];
|
||||
struct page **gen8_pt_pages[GEN8_LEGACY_PDPES];
|
||||
};
|
||||
struct page *pd_pages;
|
||||
union {
|
||||
uint32_t pd_offset;
|
||||
dma_addr_t pd_dma_addr[GEN8_LEGACY_PDPS];
|
||||
dma_addr_t pd_dma_addr[GEN8_LEGACY_PDPES];
|
||||
};
|
||||
union {
|
||||
dma_addr_t *pt_dma_addr;
|
||||
dma_addr_t *gen8_pt_dma_addr[4];
|
||||
dma_addr_t *gen8_pt_dma_addr[GEN8_LEGACY_PDPES];
|
||||
};
|
||||
|
||||
struct drm_i915_file_private *file_priv;
|
||||
|
||||
@@ -231,7 +231,7 @@ static int i915_setup_compression(struct drm_device *dev, int size, int fb_cpp)
|
||||
dev_priv->mm.stolen_base + compressed_llb->start);
|
||||
}
|
||||
|
||||
dev_priv->fbc.size = size / dev_priv->fbc.threshold;
|
||||
dev_priv->fbc.uncompressed_size = size;
|
||||
|
||||
DRM_DEBUG_KMS("reserved %d bytes of contiguous stolen space for FBC\n",
|
||||
size);
|
||||
@@ -253,7 +253,7 @@ int i915_gem_stolen_setup_compression(struct drm_device *dev, int size, int fb_c
|
||||
if (!drm_mm_initialized(&dev_priv->mm.stolen))
|
||||
return -ENODEV;
|
||||
|
||||
if (size < dev_priv->fbc.size)
|
||||
if (size < dev_priv->fbc.uncompressed_size)
|
||||
return 0;
|
||||
|
||||
/* Release any current block */
|
||||
@@ -266,7 +266,7 @@ void i915_gem_stolen_cleanup_compression(struct drm_device *dev)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
|
||||
if (dev_priv->fbc.size == 0)
|
||||
if (dev_priv->fbc.uncompressed_size == 0)
|
||||
return;
|
||||
|
||||
drm_mm_remove_node(&dev_priv->fbc.compressed_fb);
|
||||
@@ -276,7 +276,7 @@ void i915_gem_stolen_cleanup_compression(struct drm_device *dev)
|
||||
kfree(dev_priv->fbc.compressed_llb);
|
||||
}
|
||||
|
||||
dev_priv->fbc.size = 0;
|
||||
dev_priv->fbc.uncompressed_size = 0;
|
||||
}
|
||||
|
||||
void i915_gem_cleanup_stolen(struct drm_device *dev)
|
||||
|
||||
@@ -994,12 +994,11 @@ static void i915_gem_record_rings(struct drm_device *dev,
|
||||
i915_error_ggtt_object_create(dev_priv,
|
||||
ring->scratch.obj);
|
||||
|
||||
if (request->file_priv) {
|
||||
if (request->pid) {
|
||||
struct task_struct *task;
|
||||
|
||||
rcu_read_lock();
|
||||
task = pid_task(request->file_priv->file->pid,
|
||||
PIDTYPE_PID);
|
||||
task = pid_task(request->pid, PIDTYPE_PID);
|
||||
if (task) {
|
||||
strcpy(error->ring[i].comm, task->comm);
|
||||
error->ring[i].pid = task->pid;
|
||||
|
||||
@@ -1243,10 +1243,7 @@ static void gen6_pm_rps_work(struct work_struct *work)
|
||||
|
||||
dev_priv->rps.last_adj = new_delay - dev_priv->rps.cur_freq;
|
||||
|
||||
if (IS_VALLEYVIEW(dev_priv->dev))
|
||||
valleyview_set_rps(dev_priv->dev, new_delay);
|
||||
else
|
||||
gen6_set_rps(dev_priv->dev, new_delay);
|
||||
intel_set_rps(dev_priv->dev, new_delay);
|
||||
|
||||
mutex_unlock(&dev_priv->rps.hw_lock);
|
||||
}
|
||||
|
||||
@@ -140,6 +140,7 @@
|
||||
#define GEN8_RING_PDP_LDW(ring, n) ((ring)->mmio_base+0x270 + (n) * 8)
|
||||
|
||||
#define GAM_ECOCHK 0x4090
|
||||
#define BDW_DISABLE_HDC_INVALIDATION (1<<25)
|
||||
#define ECOCHK_SNB_BIT (1<<10)
|
||||
#define HSW_ECOCHK_ARB_PRIO_SOL (1<<6)
|
||||
#define ECOCHK_PPGTT_CACHE64B (0x3<<3)
|
||||
@@ -586,6 +587,19 @@ enum punit_power_well {
|
||||
PUNIT_POWER_WELL_NUM,
|
||||
};
|
||||
|
||||
enum skl_disp_power_wells {
|
||||
SKL_DISP_PW_MISC_IO,
|
||||
SKL_DISP_PW_DDI_A_E,
|
||||
SKL_DISP_PW_DDI_B,
|
||||
SKL_DISP_PW_DDI_C,
|
||||
SKL_DISP_PW_DDI_D,
|
||||
SKL_DISP_PW_1 = 14,
|
||||
SKL_DISP_PW_2,
|
||||
};
|
||||
|
||||
#define SKL_POWER_WELL_STATE(pw) (1 << ((pw) * 2))
|
||||
#define SKL_POWER_WELL_REQ(pw) (1 << (((pw) * 2) + 1))
|
||||
|
||||
#define PUNIT_REG_PWRGT_CTRL 0x60
|
||||
#define PUNIT_REG_PWRGT_STATUS 0x61
|
||||
#define PUNIT_PWRGT_MASK(power_well) (3 << ((power_well) * 2))
|
||||
@@ -1470,6 +1484,7 @@ enum punit_power_well {
|
||||
#define CACHE_MODE_1 0x7004 /* IVB+ */
|
||||
#define PIXEL_SUBSPAN_COLLECT_OPT_DISABLE (1<<6)
|
||||
#define GEN8_4x4_STC_OPTIMIZATION_DISABLE (1<<6)
|
||||
#define GEN9_PARTIAL_RESOLVE_IN_VC_DISABLE (1<<1)
|
||||
|
||||
#define GEN6_BLITTER_ECOSKPD 0x221d0
|
||||
#define GEN6_BLITTER_LOCK_SHIFT 16
|
||||
@@ -5221,15 +5236,22 @@ enum punit_power_well {
|
||||
#define HSW_NDE_RSTWRN_OPT 0x46408
|
||||
#define RESET_PCH_HANDSHAKE_ENABLE (1<<4)
|
||||
|
||||
#define FF_SLICE_CS_CHICKEN2 0x02e4
|
||||
#define GEN9_TSG_BARRIER_ACK_DISABLE (1<<8)
|
||||
|
||||
/* GEN7 chicken */
|
||||
#define GEN7_COMMON_SLICE_CHICKEN1 0x7010
|
||||
# define GEN7_CSC1_RHWO_OPT_DISABLE_IN_RCC ((1<<10) | (1<<26))
|
||||
# define GEN9_RHWO_OPTIMIZATION_DISABLE (1<<14)
|
||||
#define COMMON_SLICE_CHICKEN2 0x7014
|
||||
# define GEN8_CSC2_SBE_VUE_CACHE_CONSERVATIVE (1<<0)
|
||||
|
||||
#define HIZ_CHICKEN 0x7018
|
||||
# define CHV_HZ_8X8_MODE_IN_1X (1<<15)
|
||||
|
||||
#define GEN9_SLICE_COMMON_ECO_CHICKEN0 0x7308
|
||||
#define DISABLE_PIXEL_MASK_CAMMING (1<<14)
|
||||
|
||||
#define GEN7_L3SQCREG1 0xB010
|
||||
#define VLV_B0_WA_L3SQCREG1_VALUE 0x00D30000
|
||||
|
||||
@@ -5245,11 +5267,16 @@ enum punit_power_well {
|
||||
#define GEN7_L3SQCREG4 0xb034
|
||||
#define L3SQ_URB_READ_CAM_MATCH_DISABLE (1<<27)
|
||||
|
||||
#define GEN8_L3SQCREG4 0xb118
|
||||
#define GEN8_LQSC_RO_PERF_DIS (1<<27)
|
||||
|
||||
/* GEN8 chicken */
|
||||
#define HDC_CHICKEN0 0x7300
|
||||
#define HDC_FORCE_NON_COHERENT (1<<4)
|
||||
#define HDC_DONOT_FETCH_MEM_WHEN_MASKED (1<<11)
|
||||
#define HDC_FENCE_DEST_SLM_DISABLE (1<<14)
|
||||
#define HDC_DONOT_FETCH_MEM_WHEN_MASKED (1<<11)
|
||||
#define HDC_FORCE_CONTEXT_SAVE_RESTORE_NON_COHERENT (1<<5)
|
||||
#define HDC_FORCE_NON_COHERENT (1<<4)
|
||||
#define HDC_BARRIER_PERFORMANCE_DISABLE (1<<10)
|
||||
|
||||
/* WaCatErrorRejectionIssue */
|
||||
#define GEN7_SQ_CHICKEN_MBCUNIT_CONFIG 0x9030
|
||||
@@ -5258,6 +5285,9 @@ enum punit_power_well {
|
||||
#define HSW_SCRATCH1 0xb038
|
||||
#define HSW_SCRATCH1_L3_DATA_ATOMICS_DISABLE (1<<27)
|
||||
|
||||
#define BDW_SCRATCH1 0xb11c
|
||||
#define GEN9_LBS_SLA_RETRY_TIMER_DECREMENT_ENABLE (1<<2)
|
||||
|
||||
/* PCH */
|
||||
|
||||
/* south display engine interrupt: IBX */
|
||||
@@ -5980,6 +6010,7 @@ enum punit_power_well {
|
||||
#define HSW_IDICR 0x9008
|
||||
#define IDIHASHMSK(x) (((x) & 0x3f) << 16)
|
||||
#define HSW_EDRAM_PRESENT 0x120010
|
||||
#define EDRAM_ENABLED 0x1
|
||||
|
||||
#define GEN6_UCGCTL1 0x9400
|
||||
# define GEN6_EU_TCUNIT_CLOCK_GATE_DISABLE (1 << 16)
|
||||
@@ -6003,6 +6034,7 @@ enum punit_power_well {
|
||||
#define GEN6_RSTCTL 0x9420
|
||||
|
||||
#define GEN8_UCGCTL6 0x9430
|
||||
#define GEN8_GAPSUNIT_CLOCK_GATE_DISABLE (1<<24)
|
||||
#define GEN8_SDEUNIT_CLOCK_GATE_DISABLE (1<<14)
|
||||
|
||||
#define GEN6_GFXPAUSE 0xA000
|
||||
@@ -6185,6 +6217,7 @@ enum punit_power_well {
|
||||
|
||||
#define GEN9_HALF_SLICE_CHICKEN5 0xe188
|
||||
#define GEN9_DG_MIRROR_FIX_ENABLE (1<<5)
|
||||
#define GEN9_CCS_TLB_PREFETCH_ENABLE (1<<3)
|
||||
|
||||
#define GEN8_ROW_CHICKEN 0xe4f0
|
||||
#define PARTIAL_INSTRUCTION_SHOOTDOWN_DISABLE (1<<8)
|
||||
@@ -6200,8 +6233,12 @@ enum punit_power_well {
|
||||
#define HALF_SLICE_CHICKEN3 0xe184
|
||||
#define HSW_SAMPLE_C_PERFORMANCE (1<<9)
|
||||
#define GEN8_CENTROID_PIXEL_OPT_DIS (1<<8)
|
||||
#define GEN9_DISABLE_OCL_OOB_SUPPRESS_LOGIC (1<<5)
|
||||
#define GEN8_SAMPLER_POWER_BYPASS_DIS (1<<1)
|
||||
|
||||
#define GEN9_HALF_SLICE_CHICKEN7 0xe194
|
||||
#define GEN9_ENABLE_YV12_BUGFIX (1<<4)
|
||||
|
||||
/* Audio */
|
||||
#define G4X_AUD_VID_DID (dev_priv->info.display_mmio_offset + 0x62020)
|
||||
#define INTEL_AUDIO_DEVCL 0x808629FB
|
||||
@@ -6351,6 +6388,13 @@ enum punit_power_well {
|
||||
#define HSW_PWR_WELL_FORCE_ON (1<<19)
|
||||
#define HSW_PWR_WELL_CTL6 0x45414
|
||||
|
||||
/* SKL Fuse Status */
|
||||
#define SKL_FUSE_STATUS 0x42000
|
||||
#define SKL_FUSE_DOWNLOAD_STATUS (1<<31)
|
||||
#define SKL_FUSE_PG0_DIST_STATUS (1<<27)
|
||||
#define SKL_FUSE_PG1_DIST_STATUS (1<<26)
|
||||
#define SKL_FUSE_PG2_DIST_STATUS (1<<25)
|
||||
|
||||
/* Per-pipe DDI Function Control */
|
||||
#define TRANS_DDI_FUNC_CTL_A 0x60400
|
||||
#define TRANS_DDI_FUNC_CTL_B 0x61400
|
||||
|
||||
@@ -402,10 +402,7 @@ static ssize_t gt_max_freq_mhz_store(struct device *kdev,
|
||||
/* We still need *_set_rps to process the new max_delay and
|
||||
* update the interrupt limits and PMINTRMSK even though
|
||||
* frequency request may be unchanged. */
|
||||
if (IS_VALLEYVIEW(dev))
|
||||
valleyview_set_rps(dev, val);
|
||||
else
|
||||
gen6_set_rps(dev, val);
|
||||
intel_set_rps(dev, val);
|
||||
|
||||
mutex_unlock(&dev_priv->rps.hw_lock);
|
||||
|
||||
@@ -464,10 +461,7 @@ static ssize_t gt_min_freq_mhz_store(struct device *kdev,
|
||||
/* We still need *_set_rps to process the new min_delay and
|
||||
* update the interrupt limits and PMINTRMSK even though
|
||||
* frequency request may be unchanged. */
|
||||
if (IS_VALLEYVIEW(dev))
|
||||
valleyview_set_rps(dev, val);
|
||||
else
|
||||
gen6_set_rps(dev, val);
|
||||
intel_set_rps(dev, val);
|
||||
|
||||
mutex_unlock(&dev_priv->rps.hw_lock);
|
||||
|
||||
|
||||
@@ -115,7 +115,7 @@ TRACE_EVENT(i915_vma_bind,
|
||||
TP_STRUCT__entry(
|
||||
__field(struct drm_i915_gem_object *, obj)
|
||||
__field(struct i915_address_space *, vm)
|
||||
__field(u32, offset)
|
||||
__field(u64, offset)
|
||||
__field(u32, size)
|
||||
__field(unsigned, flags)
|
||||
),
|
||||
@@ -128,7 +128,7 @@ TRACE_EVENT(i915_vma_bind,
|
||||
__entry->flags = flags;
|
||||
),
|
||||
|
||||
TP_printk("obj=%p, offset=%08x size=%x%s vm=%p",
|
||||
TP_printk("obj=%p, offset=%016llx size=%x%s vm=%p",
|
||||
__entry->obj, __entry->offset, __entry->size,
|
||||
__entry->flags & PIN_MAPPABLE ? ", mappable" : "",
|
||||
__entry->vm)
|
||||
@@ -141,7 +141,7 @@ TRACE_EVENT(i915_vma_unbind,
|
||||
TP_STRUCT__entry(
|
||||
__field(struct drm_i915_gem_object *, obj)
|
||||
__field(struct i915_address_space *, vm)
|
||||
__field(u32, offset)
|
||||
__field(u64, offset)
|
||||
__field(u32, size)
|
||||
),
|
||||
|
||||
@@ -152,7 +152,7 @@ TRACE_EVENT(i915_vma_unbind,
|
||||
__entry->size = vma->node.size;
|
||||
),
|
||||
|
||||
TP_printk("obj=%p, offset=%08x size=%x vm=%p",
|
||||
TP_printk("obj=%p, offset=%016llx size=%x vm=%p",
|
||||
__entry->obj, __entry->offset, __entry->size, __entry->vm)
|
||||
);
|
||||
|
||||
|
||||
@@ -0,0 +1,264 @@
|
||||
/*
|
||||
* Copyright(c) 2011-2015 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "intel_drv.h"
|
||||
#include "i915_vgpu.h"
|
||||
|
||||
/**
|
||||
* DOC: Intel GVT-g guest support
|
||||
*
|
||||
* Intel GVT-g is a graphics virtualization technology which shares the
|
||||
* GPU among multiple virtual machines on a time-sharing basis. Each
|
||||
* virtual machine is presented a virtual GPU (vGPU), which has equivalent
|
||||
* features as the underlying physical GPU (pGPU), so i915 driver can run
|
||||
* seamlessly in a virtual machine. This file provides vGPU specific
|
||||
* optimizations when running in a virtual machine, to reduce the complexity
|
||||
* of vGPU emulation and to improve the overall performance.
|
||||
*
|
||||
* A primary function introduced here is so-called "address space ballooning"
|
||||
* technique. Intel GVT-g partitions global graphics memory among multiple VMs,
|
||||
* so each VM can directly access a portion of the memory without hypervisor's
|
||||
* intervention, e.g. filling textures or queuing commands. However with the
|
||||
* partitioning an unmodified i915 driver would assume a smaller graphics
|
||||
* memory starting from address ZERO, then requires vGPU emulation module to
|
||||
* translate the graphics address between 'guest view' and 'host view', for
|
||||
* all registers and command opcodes which contain a graphics memory address.
|
||||
* To reduce the complexity, Intel GVT-g introduces "address space ballooning",
|
||||
* by telling the exact partitioning knowledge to each guest i915 driver, which
|
||||
* then reserves and prevents non-allocated portions from allocation. Thus vGPU
|
||||
* emulation module only needs to scan and validate graphics addresses without
|
||||
* complexity of address translation.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* i915_check_vgpu - detect virtual GPU
|
||||
* @dev: drm device *
|
||||
*
|
||||
* This function is called at the initialization stage, to detect whether
|
||||
* running on a vGPU.
|
||||
*/
|
||||
void i915_check_vgpu(struct drm_device *dev)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(dev);
|
||||
uint64_t magic;
|
||||
uint32_t version;
|
||||
|
||||
BUILD_BUG_ON(sizeof(struct vgt_if) != VGT_PVINFO_SIZE);
|
||||
|
||||
if (!IS_HASWELL(dev))
|
||||
return;
|
||||
|
||||
magic = readq(dev_priv->regs + vgtif_reg(magic));
|
||||
if (magic != VGT_MAGIC)
|
||||
return;
|
||||
|
||||
version = INTEL_VGT_IF_VERSION_ENCODE(
|
||||
readw(dev_priv->regs + vgtif_reg(version_major)),
|
||||
readw(dev_priv->regs + vgtif_reg(version_minor)));
|
||||
if (version != INTEL_VGT_IF_VERSION) {
|
||||
DRM_INFO("VGT interface version mismatch!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
dev_priv->vgpu.active = true;
|
||||
DRM_INFO("Virtual GPU for Intel GVT-g detected.\n");
|
||||
}
|
||||
|
||||
struct _balloon_info_ {
|
||||
/*
|
||||
* There are up to 2 regions per mappable/unmappable graphic
|
||||
* memory that might be ballooned. Here, index 0/1 is for mappable
|
||||
* graphic memory, 2/3 for unmappable graphic memory.
|
||||
*/
|
||||
struct drm_mm_node space[4];
|
||||
};
|
||||
|
||||
static struct _balloon_info_ bl_info;
|
||||
|
||||
/**
|
||||
* intel_vgt_deballoon - deballoon reserved graphics address trunks
|
||||
*
|
||||
* This function is called to deallocate the ballooned-out graphic memory, when
|
||||
* driver is unloaded or when ballooning fails.
|
||||
*/
|
||||
void intel_vgt_deballoon(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
DRM_DEBUG("VGT deballoon.\n");
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
if (bl_info.space[i].allocated)
|
||||
drm_mm_remove_node(&bl_info.space[i]);
|
||||
}
|
||||
|
||||
memset(&bl_info, 0, sizeof(bl_info));
|
||||
}
|
||||
|
||||
static int vgt_balloon_space(struct drm_mm *mm,
|
||||
struct drm_mm_node *node,
|
||||
unsigned long start, unsigned long end)
|
||||
{
|
||||
unsigned long size = end - start;
|
||||
|
||||
if (start == end)
|
||||
return -EINVAL;
|
||||
|
||||
DRM_INFO("balloon space: range [ 0x%lx - 0x%lx ] %lu KiB.\n",
|
||||
start, end, size / 1024);
|
||||
|
||||
node->start = start;
|
||||
node->size = size;
|
||||
|
||||
return drm_mm_reserve_node(mm, node);
|
||||
}
|
||||
|
||||
/**
|
||||
* intel_vgt_balloon - balloon out reserved graphics address trunks
|
||||
* @dev: drm device
|
||||
*
|
||||
* This function is called at the initialization stage, to balloon out the
|
||||
* graphic address space allocated to other vGPUs, by marking these spaces as
|
||||
* reserved. The ballooning related knowledge(starting address and size of
|
||||
* the mappable/unmappable graphic memory) is described in the vgt_if structure
|
||||
* in a reserved mmio range.
|
||||
*
|
||||
* To give an example, the drawing below depicts one typical scenario after
|
||||
* ballooning. Here the vGPU1 has 2 pieces of graphic address spaces ballooned
|
||||
* out each for the mappable and the non-mappable part. From the vGPU1 point of
|
||||
* view, the total size is the same as the physical one, with the start address
|
||||
* of its graphic space being zero. Yet there are some portions ballooned out(
|
||||
* the shadow part, which are marked as reserved by drm allocator). From the
|
||||
* host point of view, the graphic address space is partitioned by multiple
|
||||
* vGPUs in different VMs.
|
||||
*
|
||||
* vGPU1 view Host view
|
||||
* 0 ------> +-----------+ +-----------+
|
||||
* ^ |///////////| | vGPU3 |
|
||||
* | |///////////| +-----------+
|
||||
* | |///////////| | vGPU2 |
|
||||
* | +-----------+ +-----------+
|
||||
* mappable GM | available | ==> | vGPU1 |
|
||||
* | +-----------+ +-----------+
|
||||
* | |///////////| | |
|
||||
* v |///////////| | Host |
|
||||
* +=======+===========+ +===========+
|
||||
* ^ |///////////| | vGPU3 |
|
||||
* | |///////////| +-----------+
|
||||
* | |///////////| | vGPU2 |
|
||||
* | +-----------+ +-----------+
|
||||
* unmappable GM | available | ==> | vGPU1 |
|
||||
* | +-----------+ +-----------+
|
||||
* | |///////////| | |
|
||||
* | |///////////| | Host |
|
||||
* v |///////////| | |
|
||||
* total GM size ------> +-----------+ +-----------+
|
||||
*
|
||||
* Returns:
|
||||
* zero on success, non-zero if configuration invalid or ballooning failed
|
||||
*/
|
||||
int intel_vgt_balloon(struct drm_device *dev)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(dev);
|
||||
struct i915_address_space *ggtt_vm = &dev_priv->gtt.base;
|
||||
unsigned long ggtt_vm_end = ggtt_vm->start + ggtt_vm->total;
|
||||
|
||||
unsigned long mappable_base, mappable_size, mappable_end;
|
||||
unsigned long unmappable_base, unmappable_size, unmappable_end;
|
||||
int ret;
|
||||
|
||||
mappable_base = I915_READ(vgtif_reg(avail_rs.mappable_gmadr.base));
|
||||
mappable_size = I915_READ(vgtif_reg(avail_rs.mappable_gmadr.size));
|
||||
unmappable_base = I915_READ(vgtif_reg(avail_rs.nonmappable_gmadr.base));
|
||||
unmappable_size = I915_READ(vgtif_reg(avail_rs.nonmappable_gmadr.size));
|
||||
|
||||
mappable_end = mappable_base + mappable_size;
|
||||
unmappable_end = unmappable_base + unmappable_size;
|
||||
|
||||
DRM_INFO("VGT ballooning configuration:\n");
|
||||
DRM_INFO("Mappable graphic memory: base 0x%lx size %ldKiB\n",
|
||||
mappable_base, mappable_size / 1024);
|
||||
DRM_INFO("Unmappable graphic memory: base 0x%lx size %ldKiB\n",
|
||||
unmappable_base, unmappable_size / 1024);
|
||||
|
||||
if (mappable_base < ggtt_vm->start ||
|
||||
mappable_end > dev_priv->gtt.mappable_end ||
|
||||
unmappable_base < dev_priv->gtt.mappable_end ||
|
||||
unmappable_end > ggtt_vm_end) {
|
||||
DRM_ERROR("Invalid ballooning configuration!\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Unmappable graphic memory ballooning */
|
||||
if (unmappable_base > dev_priv->gtt.mappable_end) {
|
||||
ret = vgt_balloon_space(&ggtt_vm->mm,
|
||||
&bl_info.space[2],
|
||||
dev_priv->gtt.mappable_end,
|
||||
unmappable_base);
|
||||
|
||||
if (ret)
|
||||
goto err;
|
||||
}
|
||||
|
||||
/*
|
||||
* No need to partition out the last physical page,
|
||||
* because it is reserved to the guard page.
|
||||
*/
|
||||
if (unmappable_end < ggtt_vm_end - PAGE_SIZE) {
|
||||
ret = vgt_balloon_space(&ggtt_vm->mm,
|
||||
&bl_info.space[3],
|
||||
unmappable_end,
|
||||
ggtt_vm_end - PAGE_SIZE);
|
||||
if (ret)
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Mappable graphic memory ballooning */
|
||||
if (mappable_base > ggtt_vm->start) {
|
||||
ret = vgt_balloon_space(&ggtt_vm->mm,
|
||||
&bl_info.space[0],
|
||||
ggtt_vm->start, mappable_base);
|
||||
|
||||
if (ret)
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (mappable_end < dev_priv->gtt.mappable_end) {
|
||||
ret = vgt_balloon_space(&ggtt_vm->mm,
|
||||
&bl_info.space[1],
|
||||
mappable_end,
|
||||
dev_priv->gtt.mappable_end);
|
||||
|
||||
if (ret)
|
||||
goto err;
|
||||
}
|
||||
|
||||
DRM_INFO("VGT balloon successfully\n");
|
||||
return 0;
|
||||
|
||||
err:
|
||||
DRM_ERROR("VGT balloon fail\n");
|
||||
intel_vgt_deballoon();
|
||||
return ret;
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* Copyright(c) 2011-2015 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef _I915_VGPU_H_
|
||||
#define _I915_VGPU_H_
|
||||
|
||||
/* The MMIO offset of the shared info between guest and host emulator */
|
||||
#define VGT_PVINFO_PAGE 0x78000
|
||||
#define VGT_PVINFO_SIZE 0x1000
|
||||
|
||||
/*
|
||||
* The following structure pages are defined in GEN MMIO space
|
||||
* for virtualization. (One page for now)
|
||||
*/
|
||||
#define VGT_MAGIC 0x4776544776544776 /* 'vGTvGTvG' */
|
||||
#define VGT_VERSION_MAJOR 1
|
||||
#define VGT_VERSION_MINOR 0
|
||||
|
||||
#define INTEL_VGT_IF_VERSION_ENCODE(major, minor) ((major) << 16 | (minor))
|
||||
#define INTEL_VGT_IF_VERSION \
|
||||
INTEL_VGT_IF_VERSION_ENCODE(VGT_VERSION_MAJOR, VGT_VERSION_MINOR)
|
||||
|
||||
struct vgt_if {
|
||||
uint64_t magic; /* VGT_MAGIC */
|
||||
uint16_t version_major;
|
||||
uint16_t version_minor;
|
||||
uint32_t vgt_id; /* ID of vGT instance */
|
||||
uint32_t rsv1[12]; /* pad to offset 0x40 */
|
||||
/*
|
||||
* Data structure to describe the balooning info of resources.
|
||||
* Each VM can only have one portion of continuous area for now.
|
||||
* (May support scattered resource in future)
|
||||
* (starting from offset 0x40)
|
||||
*/
|
||||
struct {
|
||||
/* Aperture register balooning */
|
||||
struct {
|
||||
uint32_t base;
|
||||
uint32_t size;
|
||||
} mappable_gmadr; /* aperture */
|
||||
/* GMADR register balooning */
|
||||
struct {
|
||||
uint32_t base;
|
||||
uint32_t size;
|
||||
} nonmappable_gmadr; /* non aperture */
|
||||
/* allowed fence registers */
|
||||
uint32_t fence_num;
|
||||
uint32_t rsv2[3];
|
||||
} avail_rs; /* available/assigned resource */
|
||||
uint32_t rsv3[0x200 - 24]; /* pad to half page */
|
||||
/*
|
||||
* The bottom half page is for response from Gfx driver to hypervisor.
|
||||
* Set to reserved fields temporarily by now.
|
||||
*/
|
||||
uint32_t rsv4;
|
||||
uint32_t display_ready; /* ready for display owner switch */
|
||||
uint32_t rsv5[0x200 - 2]; /* pad to one page */
|
||||
} __packed;
|
||||
|
||||
#define vgtif_reg(x) \
|
||||
(VGT_PVINFO_PAGE + (long)&((struct vgt_if *)NULL)->x)
|
||||
|
||||
/* vGPU display status to be used by the host side */
|
||||
#define VGT_DRV_DISPLAY_NOT_READY 0
|
||||
#define VGT_DRV_DISPLAY_READY 1 /* ready for display switch */
|
||||
|
||||
extern void i915_check_vgpu(struct drm_device *dev);
|
||||
extern int intel_vgt_balloon(struct drm_device *dev);
|
||||
extern void intel_vgt_deballoon(void);
|
||||
|
||||
#endif /* _I915_VGPU_H_ */
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user