[Intel-gfx] [PATCH 1/1] drm/i915/mtl: enable local stolen memory
Lucas De Marchi
lucas.demarchi at intel.com
Tue Sep 20 20:05:12 UTC 2022
On Tue, Sep 20, 2022 at 01:31:49AM -0700, Lucas De Marchi wrote:
>On Tue, Sep 20, 2022 at 12:49:40PM +0530, Aravind Iddamsetty wrote:
>>As an integrated GPU, MTL does not have local memory and
>>HAS_LMEM() returns false. However the platform's stolen memory
>>is presented via BAR2 (i.e., the BAR we traditionally consider
>>to be the LMEM BAR) and should be managed by the driver the same
>>way that local memory is on dgpu platforms (which includes
>>setting the "lmem" bit on page table entries). We use the term
>>"local stolen memory" to refer to this model.
>>
>>Cc: Matt Roper <matthew.d.roper at intel.com>
>>Cc: Lucas De Marchi <lucas.demarchi at intel.com>
>>
>>Signed-off-by: CQ Tang <cq.tang at intel.com>
>>Signed-off-by: Aravind Iddamsetty <aravind.iddamsetty at intel.com>
>>Original-author: CQ Tang
>>---
>>drivers/gpu/drm/i915/gem/i915_gem_stolen.c | 113 +++++++++++++++++----
>>drivers/gpu/drm/i915/gt/intel_ggtt.c | 2 +-
>>drivers/gpu/drm/i915/i915_drv.h | 3 +
>>3 files changed, 100 insertions(+), 18 deletions(-)
>>
>>diff --git a/drivers/gpu/drm/i915/gem/i915_gem_stolen.c b/drivers/gpu/drm/i915/gem/i915_gem_stolen.c
>>index acc561c0f0aa..bad5250fb764 100644
>>--- a/drivers/gpu/drm/i915/gem/i915_gem_stolen.c
>>+++ b/drivers/gpu/drm/i915/gem/i915_gem_stolen.c
>>@@ -77,6 +77,19 @@ void i915_gem_stolen_remove_node(struct drm_i915_private *i915,
>> mutex_unlock(&i915->mm.stolen_lock);
>>}
>>
>>+static bool is_dsm_invalid(struct drm_i915_private *i915, struct resource *dsm)
>>+{
>>+ if (!HAS_BAR2_SMEM_STOLEN(i915)) {
>
>I called a similar function as is_dsm_valid() in
>https://patchwork.freedesktop.org/series/108620/
>
>sounds weird with "invalid" and the double negation on return early
>style.
>
>>+ if (dsm->start == 0)
>>+ return true;
>>+ }
>>+
>>+ if (dsm->end <= dsm->start)
>>+ return true;
>>+
>>+ return false;
>>+}
>>+
>>static int i915_adjust_stolen(struct drm_i915_private *i915,
>> struct resource *dsm)
>>{
>>@@ -84,7 +97,7 @@ static int i915_adjust_stolen(struct drm_i915_private *i915,
>> struct intel_uncore *uncore = ggtt->vm.gt->uncore;
>> struct resource *r;
>>
>>- if (dsm->start == 0 || dsm->end <= dsm->start)
>>+ if (is_dsm_invalid(i915, dsm))
>> return -EINVAL;
>>
>> /*
>>@@ -136,7 +149,7 @@ static int i915_adjust_stolen(struct drm_i915_private *i915,
>> * overlaps with the non-stolen system memory range, since lmem is local
>> * to the gpu.
>> */
>>- if (HAS_LMEM(i915))
>>+ if (HAS_LMEM(i915) || HAS_BAR2_SMEM_STOLEN(i915))
>
>comment above makes no sense when you add this. For this specific case
>it's still system memory, reserved by the BIOS and that we access by
>mapping the lmembar
>
>> return 0;
>>
>> /*
>>@@ -371,8 +384,6 @@ static void icl_get_stolen_reserved(struct drm_i915_private *i915,
>>
>> drm_dbg(&i915->drm, "GEN6_STOLEN_RESERVED = 0x%016llx\n", reg_val);
>>
>>- *base = reg_val & GEN11_STOLEN_RESERVED_ADDR_MASK;
>>-
>> switch (reg_val & GEN8_STOLEN_RESERVED_SIZE_MASK) {
>> case GEN8_STOLEN_RESERVED_1M:
>> *size = 1024 * 1024;
>>@@ -390,6 +401,12 @@ static void icl_get_stolen_reserved(struct drm_i915_private *i915,
>> *size = 8 * 1024 * 1024;
>> MISSING_CASE(reg_val & GEN8_STOLEN_RESERVED_SIZE_MASK);
>> }
>>+
>>+ if ((GRAPHICS_VER_FULL(i915) >= IP_VER(12, 70)) && !IS_DGFX(i915))
>>+ /* the base is initialized to stolen top so subtract size to get base */
>>+ *base -= *size;
>
>that doesn't necessarily holds true. According to the spec the wopcm
>base is 1MB aligned so even if it is "at the top", it may not mean it is at the
>very very top that we can just subtract the size.
>
>
>>+ else
>>+ *base = reg_val & GEN11_STOLEN_RESERVED_ADDR_MASK;
>>}
>>
>>static int i915_gem_init_stolen(struct intel_memory_region *mem)
>>@@ -423,8 +440,7 @@ static int i915_gem_init_stolen(struct intel_memory_region *mem)
>> if (i915_adjust_stolen(i915, &i915->dsm))
>> return 0;
>>
>>- GEM_BUG_ON(i915->dsm.start == 0);
>>- GEM_BUG_ON(i915->dsm.end <= i915->dsm.start);
>>+ GEM_BUG_ON(is_dsm_invalid(i915, &i915->dsm));
>>
>> stolen_top = i915->dsm.end + 1;
>> reserved_base = stolen_top;
>>@@ -796,6 +812,46 @@ static const struct intel_memory_region_ops i915_region_stolen_lmem_ops = {
>> .init_object = _i915_gem_object_stolen_init,
>>};
>>
>>+static int get_mtl_gms_size(struct intel_uncore *uncore)
>>+{
>>+ u16 ggc, gms;
>>+
>>+ ggc = intel_uncore_read16(uncore, _MMIO(0x108040));
>
>??
>
>>+
>>+ /* check GGMS, should be fixed 0x3 (8MB) */
>>+ if ((ggc & 0xc0) != 0xc0)
>>+ return -EIO;
>>+
>>+ /* return valid GMS value, -EIO if invalid */
>>+ gms = ggc >> 8;
>>+ switch (gms) {
>>+ case 0x0 ... 0x10:
>>+ return gms * 32;
>>+ case 0x20:
>>+ return 1024;
>>+ case 0x30:
>>+ return 1536;
>>+ case 0x40:
>>+ return 2048;
>>+ case 0xf0 ... 0xfe:
>>+ return (gms - 0xf0 + 1) * 4;
>>+ default:
>>+ return -EIO;
>>+ }
>>+}
>>+
>>+static inline bool lmembar_is_igpu_stolen(struct drm_i915_private *i915)
>
>doesn't deserve an inline. lmembar_is_igpu_stolen() doesn't make much
>sense as the lmembar is never igpu stolen.... you probably mean
>something else here
>
>>+{
>>+ u32 regions = RUNTIME_INFO(i915)->memory_regions;
>>+
>>+ if (regions & REGION_LMEM)
>>+ return false;
>>+
>>+ drm_WARN_ON(&i915->drm, (regions & REGION_STOLEN_LMEM) == 0);
>>+
>>+ return true;
>>+}
>>+
>>struct intel_memory_region *
>>i915_gem_stolen_lmem_setup(struct drm_i915_private *i915, u16 type,
>> u16 instance)
>>@@ -806,19 +862,16 @@ i915_gem_stolen_lmem_setup(struct drm_i915_private *i915, u16 type,
>> struct intel_memory_region *mem;
>> resource_size_t io_start, io_size;
>> resource_size_t min_page_size;
>>+ int ret;
>>
>> if (WARN_ON_ONCE(instance))
>> return ERR_PTR(-ENODEV);
>>
>>- if (!i915_pci_resource_valid(pdev, GEN12_LMEM_BAR))
>>+ if (!i915_pci_resource_valid(pdev, GFXMEM_BAR))
>
>at least for MTL, Bspec 63830 still calls this lmembar. So the rename
>for me is a net loss
>
>> return ERR_PTR(-ENXIO);
>>
>>- /* Use DSM base address instead for stolen memory */
>>- dsm_base = intel_uncore_read64(uncore, GEN12_DSMBASE);
>>- if (IS_DG1(uncore->i915)) {
>>- lmem_size = pci_resource_len(pdev, GEN12_LMEM_BAR);
>>- if (WARN_ON(lmem_size < dsm_base))
>>- return ERR_PTR(-ENODEV);
>>+ if (lmembar_is_igpu_stolen(i915) || IS_DG1(i915)) {
>>+ lmem_size = pci_resource_len(pdev, GFXMEM_BAR);
>
>this looks confusing, but apparently correct. For DG1 the stolen is
>on top of lmem. For MTL, it's on the end of lmembar (256M). This works
>because on DG1 aperture == lmem size.
>
>> } else {
>> resource_size_t lmem_range;
>>
>>@@ -827,13 +880,39 @@ i915_gem_stolen_lmem_setup(struct drm_i915_private *i915, u16 type,
>> lmem_size *= SZ_1G;
>> }
>>
>>- dsm_size = lmem_size - dsm_base;
>>- if (pci_resource_len(pdev, GEN12_LMEM_BAR) < lmem_size) {
>>+ if (HAS_BAR2_SMEM_STOLEN(i915)) {
>>+ /*
>>+ * MTL dsm size is in GGC register, not the bar size.
>
>it's not exclusive to MTL. it has been there for ages and it was never
>the BAR size like this comment says. Or at least it doesn't match the
>else condition that is using the GEN12_DSMBASE register
>
>>+ * also MTL uses offset to DSMBASE in ptes, so i915
>>+ * uses dsm_base = 0 to setup stolen region.
>>+ */
>>+ ret = get_mtl_gms_size(uncore);
>>+ if (ret < 0) {
>>+ drm_err(&i915->drm, "invalid MTL GGC register setting\n");
>>+ return ERR_PTR(ret);
>>+ }
>>+
>>+ dsm_base = 0;
>
>if we stop handling part of the values in the registers as relative to
>the mapping and rather handle them as we read from the registers
>(physical addresses), the size calculations should still match and we
>shouldn't need all the if/else dance. If we pass the right io_start we
>can then make them relative to the mapping by subtracting it, or if we
>don't want GTT to be in the mapping we subtract it.
>
>That makes me wonder if choosing the i915_gem_stolen_lmem_setup() for
>all of this is even the right choice given we are actually talking about
>system memory that is mapped through the lmembar.
another approach could be: handle the several coding style issues,
function names etc. Since this works for MTL, it's better than the
hypothetical solution that is not written and may not work well. I may
have missed something in my analysis. So I'd be fine to go with improved
version of this patch, and I can add to my todo list to try to clean
this up later.
Lucas De Marchi
>
>>+ dsm_size = (resource_size_t)(ret * SZ_1M);
>>+
>>+ GEM_BUG_ON(pci_resource_len(pdev, GFXMEM_BAR) != 256 * SZ_1M);
>>+ GEM_BUG_ON((dsm_size + 8 * SZ_1M) > lmem_size);
>>+ } else {
>>+ /* Use DSM base address instead for stolen memory */
>>+ dsm_base = intel_uncore_read64(uncore, GEN12_DSMBASE);
>>+ if (WARN_ON(lmem_size < dsm_base))
>>+ return ERR_PTR(-ENODEV);
>>+ dsm_size = lmem_size - dsm_base;
>>+ }
>>+
>>+ io_size = dsm_size;
>>+ if (pci_resource_len(pdev, GFXMEM_BAR) < dsm_size) {
>> io_start = 0;
>> io_size = 0;
>>+ } else if (HAS_BAR2_SMEM_STOLEN(i915)) {
>>+ io_start = pci_resource_start(pdev, GFXMEM_BAR) + 8 * SZ_1M;
>
>should be the GGSM?
>
>
>Lucas De Marchi
>
>> } else {
>>- io_start = pci_resource_start(pdev, GEN12_LMEM_BAR) + dsm_base;
>>- io_size = dsm_size;
>>+ io_start = pci_resource_start(pdev, GFXMEM_BAR) + dsm_base;
>> }
>>
>> min_page_size = HAS_64K_PAGES(i915) ? I915_GTT_PAGE_SIZE_64K :
>>diff --git a/drivers/gpu/drm/i915/gt/intel_ggtt.c b/drivers/gpu/drm/i915/gt/intel_ggtt.c
>>index 30cf5c3369d9..b31fe0fb013f 100644
>>--- a/drivers/gpu/drm/i915/gt/intel_ggtt.c
>>+++ b/drivers/gpu/drm/i915/gt/intel_ggtt.c
>>@@ -931,7 +931,7 @@ static int gen8_gmch_probe(struct i915_ggtt *ggtt)
>> unsigned int size;
>> u16 snb_gmch_ctl;
>>
>>- if (!HAS_LMEM(i915)) {
>>+ if (!HAS_LMEM(i915) && !HAS_BAR2_SMEM_STOLEN(i915)) {
>> if (!i915_pci_resource_valid(pdev, GTT_APERTURE_BAR))
>> return -ENXIO;
>>
>>diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
>>index 134fc1621821..ef3120322077 100644
>>--- a/drivers/gpu/drm/i915/i915_drv.h
>>+++ b/drivers/gpu/drm/i915/i915_drv.h
>>@@ -973,6 +973,9 @@ IS_SUBPLATFORM(const struct drm_i915_private *i915,
>>
>>#define HAS_ONE_EU_PER_FUSE_BIT(i915) (INTEL_INFO(i915)->has_one_eu_per_fuse_bit)
>>
>>+#define HAS_BAR2_SMEM_STOLEN(i915) (!HAS_LMEM(i915) && \
>>+ GRAPHICS_VER_FULL(i915) >= IP_VER(12, 70))
>>+
>>/* intel_device_info.c */
>>static inline struct intel_device_info *
>>mkwrite_device_info(struct drm_i915_private *dev_priv)
>>--
>>2.25.1
>>
More information about the Intel-gfx
mailing list