[PATCH 04/10] drm/i915/ggtt: Add intel_ggtt_read_entry()
Hogander, Jouni
jouni.hogander at intel.com
Mon Mar 31 12:24:23 UTC 2025
On Thu, 2025-03-13 at 16:08 +0200, Ville Syrjala wrote:
> From: Ville Syrjälä <ville.syrjala at linux.intel.com>
>
> The BIOS FB takeover code wants to read out the PTEs (or at least
> one of them) to figure out wher the FB is lcoated in memory.
Couple of typos here. Consider fixing them before pushing:
Reviewed-by: Jouni Högander <jouni.hogander at intel.com>
> Currently we only do that for systems with LMEMBAR, and we've
> open coded the PTE decoding in the display code. Introduce a more
> proper abstract interface (intel_ggtt_read_entry()) for this purpose,
> and implement it for all platforms.
>
> Signed-off-by: Ville Syrjälä <ville.syrjala at linux.intel.com>
> ---
> drivers/gpu/drm/i915/gt/intel_ggtt.c | 56
> +++++++++++++++++++++++
> drivers/gpu/drm/i915/gt/intel_ggtt_gmch.c | 8 ++++
> drivers/gpu/drm/i915/gt/intel_gtt.h | 6 +++
> 3 files changed, 70 insertions(+)
>
> diff --git a/drivers/gpu/drm/i915/gt/intel_ggtt.c
> b/drivers/gpu/drm/i915/gt/intel_ggtt.c
> index f6c59f20832f..46a5aa4ab9c8 100644
> --- a/drivers/gpu/drm/i915/gt/intel_ggtt.c
> +++ b/drivers/gpu/drm/i915/gt/intel_ggtt.c
> @@ -289,6 +289,14 @@ u64 gen8_ggtt_pte_encode(dma_addr_t addr,
> return pte;
> }
>
> +static dma_addr_t gen8_ggtt_pte_decode(u64 pte, bool *is_present,
> bool *is_local)
> +{
> + *is_present = pte & GEN8_PAGE_PRESENT;
> + *is_local = pte & GEN12_GGTT_PTE_LM;
> +
> + return pte & GEN12_GGTT_PTE_ADDR_MASK;
> +}
> +
> static bool should_update_ggtt_with_bind(struct i915_ggtt *ggtt)
> {
> struct intel_gt *gt = ggtt->vm.gt;
> @@ -435,6 +443,11 @@ static void gen8_set_pte(void __iomem *addr,
> gen8_pte_t pte)
> writeq(pte, addr);
> }
>
> +static gen8_pte_t gen8_get_pte(void __iomem *addr)
> +{
> + return readq(addr);
> +}
> +
> static void gen8_ggtt_insert_page(struct i915_address_space *vm,
> dma_addr_t addr,
> u64 offset,
> @@ -450,6 +463,16 @@ static void gen8_ggtt_insert_page(struct
> i915_address_space *vm,
> ggtt->invalidate(ggtt);
> }
>
> +static dma_addr_t gen8_ggtt_read_entry(struct i915_address_space
> *vm,
> + u64 offset, bool *is_present,
> bool *is_local)
> +{
> + struct i915_ggtt *ggtt = i915_vm_to_ggtt(vm);
> + gen8_pte_t __iomem *pte =
> + (gen8_pte_t __iomem *)ggtt->gsm + offset /
> I915_GTT_PAGE_SIZE;
> +
> + return ggtt->vm.pte_decode(gen8_get_pte(pte), is_present,
> is_local);
> +}
> +
> static void gen8_ggtt_insert_page_bind(struct i915_address_space
> *vm,
> dma_addr_t addr, u64 offset,
> unsigned int pat_index, u32
> flags)
> @@ -605,6 +628,17 @@ static void gen6_ggtt_insert_page(struct
> i915_address_space *vm,
> ggtt->invalidate(ggtt);
> }
>
> +static dma_addr_t gen6_ggtt_read_entry(struct i915_address_space
> *vm,
> + u64 offset,
> + bool *is_present, bool
> *is_local)
> +{
> + struct i915_ggtt *ggtt = i915_vm_to_ggtt(vm);
> + gen6_pte_t __iomem *pte =
> + (gen6_pte_t __iomem *)ggtt->gsm + offset /
> I915_GTT_PAGE_SIZE;
> +
> + return vm->pte_decode(ioread32(pte), is_present, is_local);
> +}
> +
> /*
> * Binds an object into the global gtt with the specified cache
> level.
> * The object will be accessible to the GPU via commands whose
> operands
> @@ -769,6 +803,14 @@ void intel_ggtt_unbind_vma(struct
> i915_address_space *vm,
> vm->clear_range(vm, vma_res->start, vma_res->vma_size);
> }
>
> +dma_addr_t intel_ggtt_read_entry(struct i915_address_space *vm,
> + u64 offset, bool *is_present, bool
> *is_local)
> +{
> + struct i915_ggtt *ggtt = i915_vm_to_ggtt(vm);
> +
> + return ggtt->vm.read_entry(vm, offset, is_present,
> is_local);
> +}
> +
> /*
> * Reserve the top of the GuC address space for firmware images.
> Addresses
> * beyond GUC_GGTT_TOP in the GuC address space are inaccessible by
> GuC,
> @@ -1245,6 +1287,7 @@ static int gen8_gmch_probe(struct i915_ggtt
> *ggtt)
> ggtt->vm.scratch_range = gen8_ggtt_clear_range;
>
> ggtt->vm.insert_entries = gen8_ggtt_insert_entries;
> + ggtt->vm.read_entry = gen8_ggtt_read_entry;
>
> /*
> * Serialize GTT updates with aperture access on BXT if VT-d
> is on,
> @@ -1291,6 +1334,8 @@ static int gen8_gmch_probe(struct i915_ggtt
> *ggtt)
> else
> ggtt->vm.pte_encode = gen8_ggtt_pte_encode;
>
> + ggtt->vm.pte_decode = gen8_ggtt_pte_decode;
> +
> return ggtt_probe_common(ggtt, size);
> }
>
> @@ -1390,6 +1435,14 @@ static u64 iris_pte_encode(dma_addr_t addr,
> return pte;
> }
>
> +static dma_addr_t gen6_pte_decode(u64 pte, bool *is_present, bool
> *is_local)
> +{
> + *is_present = pte & GEN6_PTE_VALID;
> + *is_local = false;
> +
> + return ((pte & 0xff0) << 28) | (pte & ~0xfff);
> +}
> +
> static int gen6_gmch_probe(struct i915_ggtt *ggtt)
> {
> struct drm_i915_private *i915 = ggtt->vm.i915;
> @@ -1428,6 +1481,7 @@ static int gen6_gmch_probe(struct i915_ggtt
> *ggtt)
> ggtt->vm.scratch_range = gen6_ggtt_clear_range;
> ggtt->vm.insert_page = gen6_ggtt_insert_page;
> ggtt->vm.insert_entries = gen6_ggtt_insert_entries;
> + ggtt->vm.read_entry = gen6_ggtt_read_entry;
> ggtt->vm.cleanup = gen6_gmch_remove;
>
> ggtt->invalidate = gen6_ggtt_invalidate;
> @@ -1443,6 +1497,8 @@ static int gen6_gmch_probe(struct i915_ggtt
> *ggtt)
> else
> ggtt->vm.pte_encode = snb_pte_encode;
>
> + ggtt->vm.pte_decode = gen6_pte_decode;
> +
> ggtt->vm.vma_ops.bind_vma = intel_ggtt_bind_vma;
> ggtt->vm.vma_ops.unbind_vma = intel_ggtt_unbind_vma;
>
> diff --git a/drivers/gpu/drm/i915/gt/intel_ggtt_gmch.c
> b/drivers/gpu/drm/i915/gt/intel_ggtt_gmch.c
> index 59eed0a0ce90..c5f5f0bdfb2c 100644
> --- a/drivers/gpu/drm/i915/gt/intel_ggtt_gmch.c
> +++ b/drivers/gpu/drm/i915/gt/intel_ggtt_gmch.c
> @@ -27,6 +27,13 @@ static void gmch_ggtt_insert_page(struct
> i915_address_space *vm,
> intel_gmch_gtt_insert_page(addr, offset >> PAGE_SHIFT,
> flags);
> }
>
> +static dma_addr_t gmch_ggtt_read_entry(struct i915_address_space
> *vm,
> + u64 offset, bool *is_present,
> bool *is_local)
> +{
> + return intel_gmch_gtt_read_entry(offset >> PAGE_SHIFT,
> + is_present, is_local);
> +}
> +
> static void gmch_ggtt_insert_entries(struct i915_address_space *vm,
> struct i915_vma_resource
> *vma_res,
> unsigned int pat_index,
> @@ -103,6 +110,7 @@ int intel_ggtt_gmch_probe(struct i915_ggtt *ggtt)
> ggtt->vm.insert_entries = gmch_ggtt_insert_entries;
> ggtt->vm.clear_range = gmch_ggtt_clear_range;
> ggtt->vm.scratch_range = gmch_ggtt_clear_range;
> + ggtt->vm.read_entry = gmch_ggtt_read_entry;
> ggtt->vm.cleanup = gmch_ggtt_remove;
>
> ggtt->invalidate = gmch_ggtt_invalidate;
> diff --git a/drivers/gpu/drm/i915/gt/intel_gtt.h
> b/drivers/gpu/drm/i915/gt/intel_gtt.h
> index 0a36ea751b63..9d3a3ad567a0 100644
> --- a/drivers/gpu/drm/i915/gt/intel_gtt.h
> +++ b/drivers/gpu/drm/i915/gt/intel_gtt.h
> @@ -312,6 +312,7 @@ struct i915_address_space {
> u64 (*pte_encode)(dma_addr_t addr,
> unsigned int pat_index,
> u32 flags); /* Create a valid PTE */
> + dma_addr_t (*pte_decode)(u64 pte, bool *is_present, bool
> *is_local);
> #define PTE_READ_ONLY BIT(0)
> #define PTE_LM BIT(1)
>
> @@ -340,6 +341,8 @@ struct i915_address_space {
> struct i915_vma_resource
> *vma_res,
> unsigned int pat_index,
> u32 flags);
> + dma_addr_t (*read_entry)(struct i915_address_space *vm,
> + u64 offset, bool *is_present, bool
> *is_local);
> void (*cleanup)(struct i915_address_space *vm);
>
> void (*foreach)(struct i915_address_space *vm,
> @@ -590,6 +593,9 @@ void intel_ggtt_bind_vma(struct
> i915_address_space *vm,
> void intel_ggtt_unbind_vma(struct i915_address_space *vm,
> struct i915_vma_resource *vma_res);
>
> +dma_addr_t intel_ggtt_read_entry(struct i915_address_space *vm,
> + u64 offset, bool *is_present, bool
> *is_local);
> +
> int i915_ggtt_probe_hw(struct drm_i915_private *i915);
> int i915_ggtt_init_hw(struct drm_i915_private *i915);
> int i915_ggtt_enable_hw(struct drm_i915_private *i915);
More information about the Intel-gfx
mailing list