mirror of https://gitee.com/openkylin/linux.git
drm/i915: Don't clobber the GTT when it's within stolen memory
On most gen2-4 platforms the GTT can be (or maybe always is?) inside the stolen memory region. If that's the case, reduce the size of the stolen memory appropriately to make make sure we don't clobber the GTT. v2: Deal with gen4 36 bit physical address Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=80151 Acked-by: Chris Wilson <chris@chris-wilson.co.uk> Cc: stable@vger.kernel.org Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
This commit is contained in:
parent
aceb365ca9
commit
f1e1c2129b
|
@ -74,6 +74,50 @@ static unsigned long i915_stolen_to_physical(struct drm_device *dev)
|
|||
if (base == 0)
|
||||
return 0;
|
||||
|
||||
/* make sure we don't clobber the GTT if it's within stolen memory */
|
||||
if (INTEL_INFO(dev)->gen <= 4 && !IS_G33(dev) && !IS_G4X(dev)) {
|
||||
struct {
|
||||
u32 start, end;
|
||||
} stolen[2] = {
|
||||
{ .start = base, .end = base + dev_priv->gtt.stolen_size, },
|
||||
{ .start = base, .end = base + dev_priv->gtt.stolen_size, },
|
||||
};
|
||||
u64 gtt_start, gtt_end;
|
||||
|
||||
gtt_start = I915_READ(PGTBL_CTL);
|
||||
if (IS_GEN4(dev))
|
||||
gtt_start = (gtt_start & PGTBL_ADDRESS_LO_MASK) |
|
||||
(gtt_start & PGTBL_ADDRESS_HI_MASK) << 28;
|
||||
else
|
||||
gtt_start &= PGTBL_ADDRESS_LO_MASK;
|
||||
gtt_end = gtt_start + gtt_total_entries(dev_priv->gtt) * 4;
|
||||
|
||||
if (gtt_start >= stolen[0].start && gtt_start < stolen[0].end)
|
||||
stolen[0].end = gtt_start;
|
||||
if (gtt_end > stolen[1].start && gtt_end <= stolen[1].end)
|
||||
stolen[1].start = gtt_end;
|
||||
|
||||
/* pick the larger of the two chunks */
|
||||
if (stolen[0].end - stolen[0].start >
|
||||
stolen[1].end - stolen[1].start) {
|
||||
base = stolen[0].start;
|
||||
dev_priv->gtt.stolen_size = stolen[0].end - stolen[0].start;
|
||||
} else {
|
||||
base = stolen[1].start;
|
||||
dev_priv->gtt.stolen_size = stolen[1].end - stolen[1].start;
|
||||
}
|
||||
|
||||
if (stolen[0].start != stolen[1].start ||
|
||||
stolen[0].end != stolen[1].end) {
|
||||
DRM_DEBUG_KMS("GTT within stolen memory at 0x%llx-0x%llx\n",
|
||||
(unsigned long long) gtt_start,
|
||||
(unsigned long long) gtt_end - 1);
|
||||
DRM_DEBUG_KMS("Stolen memory adjusted to 0x%x-0x%x\n",
|
||||
base, base + (u32) dev_priv->gtt.stolen_size - 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Verify that nothing else uses this physical address. Stolen
|
||||
* memory should be reserved by the BIOS and hidden from the
|
||||
* kernel. So if the region is already marked as busy, something
|
||||
|
|
|
@ -942,6 +942,9 @@ enum punit_power_well {
|
|||
/*
|
||||
* Instruction and interrupt control regs
|
||||
*/
|
||||
#define PGTBL_CTL 0x02020
|
||||
#define PGTBL_ADDRESS_LO_MASK 0xfffff000 /* bits [31:12] */
|
||||
#define PGTBL_ADDRESS_HI_MASK 0x000000f0 /* bits [35:32] (gen4) */
|
||||
#define PGTBL_ER 0x02024
|
||||
#define RENDER_RING_BASE 0x02000
|
||||
#define BSD_RING_BASE 0x04000
|
||||
|
|
Loading…
Reference in New Issue