1 // SPDX-License-Identifier: MIT
3 * Copyright © 2021-2022 Intel Corporation
4 * Copyright (C) 2021-2002 Red Hat
7 #include <drm/drm_managed.h>
8 #include <drm/drm_mm.h>
10 #include <drm/ttm/ttm_device.h>
11 #include <drm/ttm/ttm_placement.h>
12 #include <drm/ttm/ttm_range_manager.h>
14 #include "regs/xe_regs.h"
16 #include "xe_device.h"
19 #include "xe_res_cursor.h"
20 #include "xe_ttm_stolen_mgr.h"
21 #include "xe_ttm_vram_mgr.h"
23 struct xe_ttm_stolen_mgr {
24 struct xe_ttm_vram_mgr base;
27 resource_size_t io_base;
29 resource_size_t stolen_base;
31 void *__iomem mapping;
34 static inline struct xe_ttm_stolen_mgr *
35 to_stolen_mgr(struct ttm_resource_manager *man)
37 return container_of(man, struct xe_ttm_stolen_mgr, base.manager);
41 * xe_ttm_stolen_cpu_inaccessible - Can we directly CPU access stolen memory for
45 * On some integrated platforms we can't directly access stolen via the CPU
46 * (like some normal system memory). Also on small-bar systems for discrete,
47 * since stolen is always as the end of normal VRAM, and the BAR likely doesn't
48 * stretch that far. However CPU access of stolen is generally rare, and at
49 * least on discrete should not be needed.
51 * If this is indeed inaccessible then we fallback to using the GGTT mappable
52 * aperture for CPU access. On discrete platforms we have no such thing, so when
53 * later attempting to CPU map the memory an error is instead thrown.
55 bool xe_ttm_stolen_cpu_inaccessible(struct xe_device *xe)
57 struct ttm_resource_manager *ttm_mgr =
58 ttm_manager_type(&xe->ttm, XE_PL_STOLEN);
59 struct xe_ttm_stolen_mgr *mgr;
64 mgr = to_stolen_mgr(ttm_mgr);
66 return !mgr->io_base || GRAPHICS_VERx100(xe) < 1270;
69 static s64 detect_bar2_dgfx(struct xe_device *xe, struct xe_ttm_stolen_mgr *mgr)
71 struct pci_dev *pdev = to_pci_dev(xe->drm.dev);
72 struct xe_gt *gt = to_gt(xe);
73 u64 vram_size, stolen_size;
76 err = xe_mmio_total_vram_size(xe, &vram_size, NULL);
78 drm_info(&xe->drm, "Querying total vram size failed\n");
82 /* Use DSM base address instead for stolen memory */
83 mgr->stolen_base = xe_mmio_read64(gt, GEN12_DSMBASE.reg) & GEN12_BDSM_MASK;
84 if (drm_WARN_ON(&xe->drm, vram_size < mgr->stolen_base))
87 stolen_size = vram_size - mgr->stolen_base;
88 if (mgr->stolen_base + stolen_size <= pci_resource_len(pdev, 2))
89 mgr->io_base = pci_resource_start(pdev, 2) + mgr->stolen_base;
92 * There may be few KB of platform dependent reserved memory at the end
93 * of lmem which is not part of the DSM. Such reserved memory portion is
94 * always less then DSM granularity so align down the stolen_size to DSM
95 * granularity to accommodate such reserve lmem portion.
97 return ALIGN_DOWN(stolen_size, SZ_1M);
100 static u32 detect_bar2_integrated(struct xe_device *xe, struct xe_ttm_stolen_mgr *mgr)
102 struct pci_dev *pdev = to_pci_dev(xe->drm.dev);
106 ggc = xe_mmio_read32(to_gt(xe), GGC.reg);
108 /* check GGMS, should be fixed 0x3 (8MB) */
109 if (drm_WARN_ON(&xe->drm, (ggc & GGMS_MASK) != GGMS_MASK))
112 mgr->stolen_base = mgr->io_base = pci_resource_start(pdev, 2) + SZ_8M;
114 /* return valid GMS value, -EIO if invalid */
115 gms = REG_FIELD_GET(GMS_MASK, ggc);
118 stolen_size = gms * 32 * SZ_1M;
121 stolen_size = (gms - 0xf0 + 1) * 4 * SZ_1M;
127 if (drm_WARN_ON(&xe->drm, stolen_size + SZ_8M > pci_resource_len(pdev, 2)))
133 extern struct resource intel_graphics_stolen_res;
135 static u64 detect_stolen(struct xe_device *xe, struct xe_ttm_stolen_mgr *mgr)
139 mgr->io_base = pci_resource_start(to_pci_dev(xe->drm.dev), 2);
141 /* Stolen memory is x86 only */
142 mgr->stolen_base = intel_graphics_stolen_res.start;
143 return resource_size(&intel_graphics_stolen_res);
149 void xe_ttm_stolen_mgr_init(struct xe_device *xe)
151 struct xe_ttm_stolen_mgr *mgr = drmm_kzalloc(&xe->drm, sizeof(*mgr), GFP_KERNEL);
152 struct pci_dev *pdev = to_pci_dev(xe->drm.dev);
153 u64 stolen_size, pgsize;
157 stolen_size = detect_bar2_dgfx(xe, mgr);
158 else if (GRAPHICS_VERx100(xe) >= 1270)
159 stolen_size = detect_bar2_integrated(xe, mgr);
161 stolen_size = detect_stolen(xe, mgr);
164 drm_dbg_kms(&xe->drm, "No stolen memory support\n");
168 pgsize = xe->info.vram_flags & XE_VRAM_FLAGS_NEED64K ? SZ_64K : SZ_4K;
169 if (pgsize < PAGE_SIZE)
172 err = __xe_ttm_vram_mgr_init(xe, &mgr->base, XE_PL_STOLEN, stolen_size, pgsize);
174 drm_dbg_kms(&xe->drm, "Stolen mgr init failed: %i\n", err);
178 drm_dbg_kms(&xe->drm, "Initialized stolen memory support with %llu bytes\n",
181 if (!xe_ttm_stolen_cpu_inaccessible(xe))
182 mgr->mapping = devm_ioremap_wc(&pdev->dev, mgr->io_base, stolen_size);
185 u64 xe_ttm_stolen_io_offset(struct xe_bo *bo, u32 offset)
187 struct xe_device *xe = xe_bo_device(bo);
188 struct ttm_resource_manager *ttm_mgr = ttm_manager_type(&xe->ttm, XE_PL_STOLEN);
189 struct xe_ttm_stolen_mgr *mgr = to_stolen_mgr(ttm_mgr);
190 struct xe_res_cursor cur;
192 XE_BUG_ON(!mgr->io_base);
194 if (!IS_DGFX(xe) && xe_ttm_stolen_cpu_inaccessible(xe))
195 return mgr->io_base + xe_bo_ggtt_addr(bo) + offset;
197 xe_res_first(bo->ttm.resource, offset, 4096, &cur);
198 return mgr->io_base + cur.start;
201 static int __xe_ttm_stolen_io_mem_reserve_bar2(struct xe_device *xe,
202 struct xe_ttm_stolen_mgr *mgr,
203 struct ttm_resource *mem)
205 struct xe_res_cursor cur;
210 xe_res_first(mem, 0, 4096, &cur);
211 mem->bus.offset = cur.start;
213 drm_WARN_ON(&xe->drm, !(mem->placement & TTM_PL_FLAG_CONTIGUOUS));
215 if (mem->placement & TTM_PL_FLAG_CONTIGUOUS && mgr->mapping)
216 mem->bus.addr = (u8 *)mgr->mapping + mem->bus.offset;
218 mem->bus.offset += mgr->io_base;
219 mem->bus.is_iomem = true;
220 mem->bus.caching = ttm_write_combined;
225 static int __xe_ttm_stolen_io_mem_reserve_stolen(struct xe_device *xe,
226 struct xe_ttm_stolen_mgr *mgr,
227 struct ttm_resource *mem)
230 struct xe_bo *bo = ttm_to_xe_bo(mem->bo);
232 XE_BUG_ON(IS_DGFX(xe));
234 /* XXX: Require BO to be mapped to GGTT? */
235 if (drm_WARN_ON(&xe->drm, !(bo->flags & XE_BO_CREATE_GGTT_BIT)))
238 /* GGTT is always contiguously mapped */
239 mem->bus.offset = xe_bo_ggtt_addr(bo) + mgr->io_base;
241 mem->bus.is_iomem = true;
242 mem->bus.caching = ttm_write_combined;
246 /* How is it even possible to get here without gen12 stolen? */
247 drm_WARN_ON(&xe->drm, 1);
252 int xe_ttm_stolen_io_mem_reserve(struct xe_device *xe, struct ttm_resource *mem)
254 struct ttm_resource_manager *ttm_mgr = ttm_manager_type(&xe->ttm, XE_PL_STOLEN);
255 struct xe_ttm_stolen_mgr *mgr = ttm_mgr ? to_stolen_mgr(ttm_mgr) : NULL;
257 if (!mgr || !mgr->io_base)
260 if (!xe_ttm_stolen_cpu_inaccessible(xe))
261 return __xe_ttm_stolen_io_mem_reserve_bar2(xe, mgr, mem);
263 return __xe_ttm_stolen_io_mem_reserve_stolen(xe, mgr, mem);
266 u64 xe_ttm_stolen_gpu_offset(struct xe_device *xe)
268 struct xe_ttm_stolen_mgr *mgr =
269 to_stolen_mgr(ttm_manager_type(&xe->ttm, XE_PL_STOLEN));
271 return mgr->stolen_base;