xref: /linux/drivers/gpu/drm/i915/gem/i915_gem_stolen.c (revision 95298d63c67673c654c08952672d016212b26054)
1 /*
2  * SPDX-License-Identifier: MIT
3  *
4  * Copyright © 2008-2012 Intel Corporation
5  */
6 
7 #include <linux/errno.h>
8 #include <linux/mutex.h>
9 
10 #include <drm/drm_mm.h>
11 #include <drm/i915_drm.h>
12 
13 #include "gem/i915_gem_region.h"
14 #include "i915_drv.h"
15 #include "i915_gem_stolen.h"
16 #include "i915_vgpu.h"
17 
18 /*
19  * The BIOS typically reserves some of the system's memory for the exclusive
20  * use of the integrated graphics. This memory is no longer available for
21  * use by the OS and so the user finds that his system has less memory
22  * available than he put in. We refer to this memory as stolen.
23  *
24  * The BIOS will allocate its framebuffer from the stolen memory. Our
25  * goal is try to reuse that object for our own fbcon which must always
26  * be available for panics. Anything else we can reuse the stolen memory
27  * for is a boon.
28  */
29 
30 int i915_gem_stolen_insert_node_in_range(struct drm_i915_private *i915,
31 					 struct drm_mm_node *node, u64 size,
32 					 unsigned alignment, u64 start, u64 end)
33 {
34 	int ret;
35 
36 	if (!drm_mm_initialized(&i915->mm.stolen))
37 		return -ENODEV;
38 
39 	/* WaSkipStolenMemoryFirstPage:bdw+ */
40 	if (INTEL_GEN(i915) >= 8 && start < 4096)
41 		start = 4096;
42 
43 	mutex_lock(&i915->mm.stolen_lock);
44 	ret = drm_mm_insert_node_in_range(&i915->mm.stolen, node,
45 					  size, alignment, 0,
46 					  start, end, DRM_MM_INSERT_BEST);
47 	mutex_unlock(&i915->mm.stolen_lock);
48 
49 	return ret;
50 }
51 
52 int i915_gem_stolen_insert_node(struct drm_i915_private *i915,
53 				struct drm_mm_node *node, u64 size,
54 				unsigned alignment)
55 {
56 	return i915_gem_stolen_insert_node_in_range(i915, node, size,
57 						    alignment, 0, U64_MAX);
58 }
59 
60 void i915_gem_stolen_remove_node(struct drm_i915_private *i915,
61 				 struct drm_mm_node *node)
62 {
63 	mutex_lock(&i915->mm.stolen_lock);
64 	drm_mm_remove_node(node);
65 	mutex_unlock(&i915->mm.stolen_lock);
66 }
67 
68 static int i915_adjust_stolen(struct drm_i915_private *i915,
69 			      struct resource *dsm)
70 {
71 	struct i915_ggtt *ggtt = &i915->ggtt;
72 	struct intel_uncore *uncore = ggtt->vm.gt->uncore;
73 	struct resource *r;
74 
75 	if (dsm->start == 0 || dsm->end <= dsm->start)
76 		return -EINVAL;
77 
78 	/*
79 	 * TODO: We have yet too encounter the case where the GTT wasn't at the
80 	 * end of stolen. With that assumption we could simplify this.
81 	 */
82 
83 	/* Make sure we don't clobber the GTT if it's within stolen memory */
84 	if (INTEL_GEN(i915) <= 4 &&
85 	    !IS_G33(i915) && !IS_PINEVIEW(i915) && !IS_G4X(i915)) {
86 		struct resource stolen[2] = {*dsm, *dsm};
87 		struct resource ggtt_res;
88 		resource_size_t ggtt_start;
89 
90 		ggtt_start = intel_uncore_read(uncore, PGTBL_CTL);
91 		if (IS_GEN(i915, 4))
92 			ggtt_start = (ggtt_start & PGTBL_ADDRESS_LO_MASK) |
93 				     (ggtt_start & PGTBL_ADDRESS_HI_MASK) << 28;
94 		else
95 			ggtt_start &= PGTBL_ADDRESS_LO_MASK;
96 
97 		ggtt_res =
98 			(struct resource) DEFINE_RES_MEM(ggtt_start,
99 							 ggtt_total_entries(ggtt) * 4);
100 
101 		if (ggtt_res.start >= stolen[0].start && ggtt_res.start < stolen[0].end)
102 			stolen[0].end = ggtt_res.start;
103 		if (ggtt_res.end > stolen[1].start && ggtt_res.end <= stolen[1].end)
104 			stolen[1].start = ggtt_res.end;
105 
106 		/* Pick the larger of the two chunks */
107 		if (resource_size(&stolen[0]) > resource_size(&stolen[1]))
108 			*dsm = stolen[0];
109 		else
110 			*dsm = stolen[1];
111 
112 		if (stolen[0].start != stolen[1].start ||
113 		    stolen[0].end != stolen[1].end) {
114 			drm_dbg(&i915->drm,
115 				"GTT within stolen memory at %pR\n",
116 				&ggtt_res);
117 			drm_dbg(&i915->drm, "Stolen memory adjusted to %pR\n",
118 				dsm);
119 		}
120 	}
121 
122 	/*
123 	 * Verify that nothing else uses this physical address. Stolen
124 	 * memory should be reserved by the BIOS and hidden from the
125 	 * kernel. So if the region is already marked as busy, something
126 	 * is seriously wrong.
127 	 */
128 	r = devm_request_mem_region(i915->drm.dev, dsm->start,
129 				    resource_size(dsm),
130 				    "Graphics Stolen Memory");
131 	if (r == NULL) {
132 		/*
133 		 * One more attempt but this time requesting region from
134 		 * start + 1, as we have seen that this resolves the region
135 		 * conflict with the PCI Bus.
136 		 * This is a BIOS w/a: Some BIOS wrap stolen in the root
137 		 * PCI bus, but have an off-by-one error. Hence retry the
138 		 * reservation starting from 1 instead of 0.
139 		 * There's also BIOS with off-by-one on the other end.
140 		 */
141 		r = devm_request_mem_region(i915->drm.dev, dsm->start + 1,
142 					    resource_size(dsm) - 2,
143 					    "Graphics Stolen Memory");
144 		/*
145 		 * GEN3 firmware likes to smash pci bridges into the stolen
146 		 * range. Apparently this works.
147 		 */
148 		if (!r && !IS_GEN(i915, 3)) {
149 			drm_err(&i915->drm,
150 				"conflict detected with stolen region: %pR\n",
151 				dsm);
152 
153 			return -EBUSY;
154 		}
155 	}
156 
157 	return 0;
158 }
159 
160 static void i915_gem_cleanup_stolen(struct drm_i915_private *i915)
161 {
162 	if (!drm_mm_initialized(&i915->mm.stolen))
163 		return;
164 
165 	drm_mm_takedown(&i915->mm.stolen);
166 }
167 
168 static void g4x_get_stolen_reserved(struct drm_i915_private *i915,
169 				    struct intel_uncore *uncore,
170 				    resource_size_t *base,
171 				    resource_size_t *size)
172 {
173 	u32 reg_val = intel_uncore_read(uncore,
174 					IS_GM45(i915) ?
175 					CTG_STOLEN_RESERVED :
176 					ELK_STOLEN_RESERVED);
177 	resource_size_t stolen_top = i915->dsm.end + 1;
178 
179 	drm_dbg(&i915->drm, "%s_STOLEN_RESERVED = %08x\n",
180 		IS_GM45(i915) ? "CTG" : "ELK", reg_val);
181 
182 	if ((reg_val & G4X_STOLEN_RESERVED_ENABLE) == 0)
183 		return;
184 
185 	/*
186 	 * Whether ILK really reuses the ELK register for this is unclear.
187 	 * Let's see if we catch anyone with this supposedly enabled on ILK.
188 	 */
189 	drm_WARN(&i915->drm, IS_GEN(i915, 5),
190 		 "ILK stolen reserved found? 0x%08x\n",
191 		 reg_val);
192 
193 	if (!(reg_val & G4X_STOLEN_RESERVED_ADDR2_MASK))
194 		return;
195 
196 	*base = (reg_val & G4X_STOLEN_RESERVED_ADDR2_MASK) << 16;
197 	drm_WARN_ON(&i915->drm,
198 		    (reg_val & G4X_STOLEN_RESERVED_ADDR1_MASK) < *base);
199 
200 	*size = stolen_top - *base;
201 }
202 
203 static void gen6_get_stolen_reserved(struct drm_i915_private *i915,
204 				     struct intel_uncore *uncore,
205 				     resource_size_t *base,
206 				     resource_size_t *size)
207 {
208 	u32 reg_val = intel_uncore_read(uncore, GEN6_STOLEN_RESERVED);
209 
210 	drm_dbg(&i915->drm, "GEN6_STOLEN_RESERVED = %08x\n", reg_val);
211 
212 	if (!(reg_val & GEN6_STOLEN_RESERVED_ENABLE))
213 		return;
214 
215 	*base = reg_val & GEN6_STOLEN_RESERVED_ADDR_MASK;
216 
217 	switch (reg_val & GEN6_STOLEN_RESERVED_SIZE_MASK) {
218 	case GEN6_STOLEN_RESERVED_1M:
219 		*size = 1024 * 1024;
220 		break;
221 	case GEN6_STOLEN_RESERVED_512K:
222 		*size = 512 * 1024;
223 		break;
224 	case GEN6_STOLEN_RESERVED_256K:
225 		*size = 256 * 1024;
226 		break;
227 	case GEN6_STOLEN_RESERVED_128K:
228 		*size = 128 * 1024;
229 		break;
230 	default:
231 		*size = 1024 * 1024;
232 		MISSING_CASE(reg_val & GEN6_STOLEN_RESERVED_SIZE_MASK);
233 	}
234 }
235 
236 static void vlv_get_stolen_reserved(struct drm_i915_private *i915,
237 				    struct intel_uncore *uncore,
238 				    resource_size_t *base,
239 				    resource_size_t *size)
240 {
241 	u32 reg_val = intel_uncore_read(uncore, GEN6_STOLEN_RESERVED);
242 	resource_size_t stolen_top = i915->dsm.end + 1;
243 
244 	drm_dbg(&i915->drm, "GEN6_STOLEN_RESERVED = %08x\n", reg_val);
245 
246 	if (!(reg_val & GEN6_STOLEN_RESERVED_ENABLE))
247 		return;
248 
249 	switch (reg_val & GEN7_STOLEN_RESERVED_SIZE_MASK) {
250 	default:
251 		MISSING_CASE(reg_val & GEN7_STOLEN_RESERVED_SIZE_MASK);
252 		/* fall through */
253 	case GEN7_STOLEN_RESERVED_1M:
254 		*size = 1024 * 1024;
255 		break;
256 	}
257 
258 	/*
259 	 * On vlv, the ADDR_MASK portion is left as 0 and HW deduces the
260 	 * reserved location as (top - size).
261 	 */
262 	*base = stolen_top - *size;
263 }
264 
265 static void gen7_get_stolen_reserved(struct drm_i915_private *i915,
266 				     struct intel_uncore *uncore,
267 				     resource_size_t *base,
268 				     resource_size_t *size)
269 {
270 	u32 reg_val = intel_uncore_read(uncore, GEN6_STOLEN_RESERVED);
271 
272 	drm_dbg(&i915->drm, "GEN6_STOLEN_RESERVED = %08x\n", reg_val);
273 
274 	if (!(reg_val & GEN6_STOLEN_RESERVED_ENABLE))
275 		return;
276 
277 	*base = reg_val & GEN7_STOLEN_RESERVED_ADDR_MASK;
278 
279 	switch (reg_val & GEN7_STOLEN_RESERVED_SIZE_MASK) {
280 	case GEN7_STOLEN_RESERVED_1M:
281 		*size = 1024 * 1024;
282 		break;
283 	case GEN7_STOLEN_RESERVED_256K:
284 		*size = 256 * 1024;
285 		break;
286 	default:
287 		*size = 1024 * 1024;
288 		MISSING_CASE(reg_val & GEN7_STOLEN_RESERVED_SIZE_MASK);
289 	}
290 }
291 
292 static void chv_get_stolen_reserved(struct drm_i915_private *i915,
293 				    struct intel_uncore *uncore,
294 				    resource_size_t *base,
295 				    resource_size_t *size)
296 {
297 	u32 reg_val = intel_uncore_read(uncore, GEN6_STOLEN_RESERVED);
298 
299 	drm_dbg(&i915->drm, "GEN6_STOLEN_RESERVED = %08x\n", reg_val);
300 
301 	if (!(reg_val & GEN6_STOLEN_RESERVED_ENABLE))
302 		return;
303 
304 	*base = reg_val & GEN6_STOLEN_RESERVED_ADDR_MASK;
305 
306 	switch (reg_val & GEN8_STOLEN_RESERVED_SIZE_MASK) {
307 	case GEN8_STOLEN_RESERVED_1M:
308 		*size = 1024 * 1024;
309 		break;
310 	case GEN8_STOLEN_RESERVED_2M:
311 		*size = 2 * 1024 * 1024;
312 		break;
313 	case GEN8_STOLEN_RESERVED_4M:
314 		*size = 4 * 1024 * 1024;
315 		break;
316 	case GEN8_STOLEN_RESERVED_8M:
317 		*size = 8 * 1024 * 1024;
318 		break;
319 	default:
320 		*size = 8 * 1024 * 1024;
321 		MISSING_CASE(reg_val & GEN8_STOLEN_RESERVED_SIZE_MASK);
322 	}
323 }
324 
325 static void bdw_get_stolen_reserved(struct drm_i915_private *i915,
326 				    struct intel_uncore *uncore,
327 				    resource_size_t *base,
328 				    resource_size_t *size)
329 {
330 	u32 reg_val = intel_uncore_read(uncore, GEN6_STOLEN_RESERVED);
331 	resource_size_t stolen_top = i915->dsm.end + 1;
332 
333 	drm_dbg(&i915->drm, "GEN6_STOLEN_RESERVED = %08x\n", reg_val);
334 
335 	if (!(reg_val & GEN6_STOLEN_RESERVED_ENABLE))
336 		return;
337 
338 	if (!(reg_val & GEN6_STOLEN_RESERVED_ADDR_MASK))
339 		return;
340 
341 	*base = reg_val & GEN6_STOLEN_RESERVED_ADDR_MASK;
342 	*size = stolen_top - *base;
343 }
344 
345 static void icl_get_stolen_reserved(struct drm_i915_private *i915,
346 				    struct intel_uncore *uncore,
347 				    resource_size_t *base,
348 				    resource_size_t *size)
349 {
350 	u64 reg_val = intel_uncore_read64(uncore, GEN6_STOLEN_RESERVED);
351 
352 	drm_dbg(&i915->drm, "GEN6_STOLEN_RESERVED = 0x%016llx\n", reg_val);
353 
354 	*base = reg_val & GEN11_STOLEN_RESERVED_ADDR_MASK;
355 
356 	switch (reg_val & GEN8_STOLEN_RESERVED_SIZE_MASK) {
357 	case GEN8_STOLEN_RESERVED_1M:
358 		*size = 1024 * 1024;
359 		break;
360 	case GEN8_STOLEN_RESERVED_2M:
361 		*size = 2 * 1024 * 1024;
362 		break;
363 	case GEN8_STOLEN_RESERVED_4M:
364 		*size = 4 * 1024 * 1024;
365 		break;
366 	case GEN8_STOLEN_RESERVED_8M:
367 		*size = 8 * 1024 * 1024;
368 		break;
369 	default:
370 		*size = 8 * 1024 * 1024;
371 		MISSING_CASE(reg_val & GEN8_STOLEN_RESERVED_SIZE_MASK);
372 	}
373 }
374 
375 static int i915_gem_init_stolen(struct drm_i915_private *i915)
376 {
377 	struct intel_uncore *uncore = &i915->uncore;
378 	resource_size_t reserved_base, stolen_top;
379 	resource_size_t reserved_total, reserved_size;
380 
381 	mutex_init(&i915->mm.stolen_lock);
382 
383 	if (intel_vgpu_active(i915)) {
384 		drm_notice(&i915->drm,
385 			   "%s, disabling use of stolen memory\n",
386 			   "iGVT-g active");
387 		return 0;
388 	}
389 
390 	if (intel_vtd_active() && INTEL_GEN(i915) < 8) {
391 		drm_notice(&i915->drm,
392 			   "%s, disabling use of stolen memory\n",
393 			   "DMAR active");
394 		return 0;
395 	}
396 
397 	if (resource_size(&intel_graphics_stolen_res) == 0)
398 		return 0;
399 
400 	i915->dsm = intel_graphics_stolen_res;
401 
402 	if (i915_adjust_stolen(i915, &i915->dsm))
403 		return 0;
404 
405 	GEM_BUG_ON(i915->dsm.start == 0);
406 	GEM_BUG_ON(i915->dsm.end <= i915->dsm.start);
407 
408 	stolen_top = i915->dsm.end + 1;
409 	reserved_base = stolen_top;
410 	reserved_size = 0;
411 
412 	switch (INTEL_GEN(i915)) {
413 	case 2:
414 	case 3:
415 		break;
416 	case 4:
417 		if (!IS_G4X(i915))
418 			break;
419 		/* fall through */
420 	case 5:
421 		g4x_get_stolen_reserved(i915, uncore,
422 					&reserved_base, &reserved_size);
423 		break;
424 	case 6:
425 		gen6_get_stolen_reserved(i915, uncore,
426 					 &reserved_base, &reserved_size);
427 		break;
428 	case 7:
429 		if (IS_VALLEYVIEW(i915))
430 			vlv_get_stolen_reserved(i915, uncore,
431 						&reserved_base, &reserved_size);
432 		else
433 			gen7_get_stolen_reserved(i915, uncore,
434 						 &reserved_base, &reserved_size);
435 		break;
436 	case 8:
437 	case 9:
438 	case 10:
439 		if (IS_LP(i915))
440 			chv_get_stolen_reserved(i915, uncore,
441 						&reserved_base, &reserved_size);
442 		else
443 			bdw_get_stolen_reserved(i915, uncore,
444 						&reserved_base, &reserved_size);
445 		break;
446 	default:
447 		MISSING_CASE(INTEL_GEN(i915));
448 		/* fall-through */
449 	case 11:
450 	case 12:
451 		icl_get_stolen_reserved(i915, uncore,
452 					&reserved_base,
453 					&reserved_size);
454 		break;
455 	}
456 
457 	/*
458 	 * Our expectation is that the reserved space is at the top of the
459 	 * stolen region and *never* at the bottom. If we see !reserved_base,
460 	 * it likely means we failed to read the registers correctly.
461 	 */
462 	if (!reserved_base) {
463 		drm_err(&i915->drm,
464 			"inconsistent reservation %pa + %pa; ignoring\n",
465 			&reserved_base, &reserved_size);
466 		reserved_base = stolen_top;
467 		reserved_size = 0;
468 	}
469 
470 	i915->dsm_reserved =
471 		(struct resource)DEFINE_RES_MEM(reserved_base, reserved_size);
472 
473 	if (!resource_contains(&i915->dsm, &i915->dsm_reserved)) {
474 		drm_err(&i915->drm,
475 			"Stolen reserved area %pR outside stolen memory %pR\n",
476 			&i915->dsm_reserved, &i915->dsm);
477 		return 0;
478 	}
479 
480 	/* It is possible for the reserved area to end before the end of stolen
481 	 * memory, so just consider the start. */
482 	reserved_total = stolen_top - reserved_base;
483 
484 	drm_dbg(&i915->drm,
485 		"Memory reserved for graphics device: %lluK, usable: %lluK\n",
486 		(u64)resource_size(&i915->dsm) >> 10,
487 		((u64)resource_size(&i915->dsm) - reserved_total) >> 10);
488 
489 	i915->stolen_usable_size =
490 		resource_size(&i915->dsm) - reserved_total;
491 
492 	/* Basic memrange allocator for stolen space. */
493 	drm_mm_init(&i915->mm.stolen, 0, i915->stolen_usable_size);
494 
495 	return 0;
496 }
497 
498 static struct sg_table *
499 i915_pages_create_for_stolen(struct drm_device *dev,
500 			     resource_size_t offset, resource_size_t size)
501 {
502 	struct drm_i915_private *i915 = to_i915(dev);
503 	struct sg_table *st;
504 	struct scatterlist *sg;
505 
506 	GEM_BUG_ON(range_overflows(offset, size, resource_size(&i915->dsm)));
507 
508 	/* We hide that we have no struct page backing our stolen object
509 	 * by wrapping the contiguous physical allocation with a fake
510 	 * dma mapping in a single scatterlist.
511 	 */
512 
513 	st = kmalloc(sizeof(*st), GFP_KERNEL);
514 	if (st == NULL)
515 		return ERR_PTR(-ENOMEM);
516 
517 	if (sg_alloc_table(st, 1, GFP_KERNEL)) {
518 		kfree(st);
519 		return ERR_PTR(-ENOMEM);
520 	}
521 
522 	sg = st->sgl;
523 	sg->offset = 0;
524 	sg->length = size;
525 
526 	sg_dma_address(sg) = (dma_addr_t)i915->dsm.start + offset;
527 	sg_dma_len(sg) = size;
528 
529 	return st;
530 }
531 
532 static int i915_gem_object_get_pages_stolen(struct drm_i915_gem_object *obj)
533 {
534 	struct sg_table *pages =
535 		i915_pages_create_for_stolen(obj->base.dev,
536 					     obj->stolen->start,
537 					     obj->stolen->size);
538 	if (IS_ERR(pages))
539 		return PTR_ERR(pages);
540 
541 	__i915_gem_object_set_pages(obj, pages, obj->stolen->size);
542 
543 	return 0;
544 }
545 
546 static void i915_gem_object_put_pages_stolen(struct drm_i915_gem_object *obj,
547 					     struct sg_table *pages)
548 {
549 	/* Should only be called from i915_gem_object_release_stolen() */
550 	sg_free_table(pages);
551 	kfree(pages);
552 }
553 
554 static void
555 i915_gem_object_release_stolen(struct drm_i915_gem_object *obj)
556 {
557 	struct drm_i915_private *i915 = to_i915(obj->base.dev);
558 	struct drm_mm_node *stolen = fetch_and_zero(&obj->stolen);
559 
560 	GEM_BUG_ON(!stolen);
561 
562 	i915_gem_object_release_memory_region(obj);
563 
564 	i915_gem_stolen_remove_node(i915, stolen);
565 	kfree(stolen);
566 }
567 
568 static const struct drm_i915_gem_object_ops i915_gem_object_stolen_ops = {
569 	.get_pages = i915_gem_object_get_pages_stolen,
570 	.put_pages = i915_gem_object_put_pages_stolen,
571 	.release = i915_gem_object_release_stolen,
572 };
573 
574 static struct drm_i915_gem_object *
575 __i915_gem_object_create_stolen(struct intel_memory_region *mem,
576 				struct drm_mm_node *stolen)
577 {
578 	static struct lock_class_key lock_class;
579 	struct drm_i915_gem_object *obj;
580 	unsigned int cache_level;
581 	int err = -ENOMEM;
582 
583 	obj = i915_gem_object_alloc();
584 	if (!obj)
585 		goto err;
586 
587 	drm_gem_private_object_init(&mem->i915->drm, &obj->base, stolen->size);
588 	i915_gem_object_init(obj, &i915_gem_object_stolen_ops, &lock_class);
589 
590 	obj->stolen = stolen;
591 	obj->read_domains = I915_GEM_DOMAIN_CPU | I915_GEM_DOMAIN_GTT;
592 	cache_level = HAS_LLC(mem->i915) ? I915_CACHE_LLC : I915_CACHE_NONE;
593 	i915_gem_object_set_cache_coherency(obj, cache_level);
594 
595 	err = i915_gem_object_pin_pages(obj);
596 	if (err)
597 		goto cleanup;
598 
599 	i915_gem_object_init_memory_region(obj, mem, 0);
600 
601 	return obj;
602 
603 cleanup:
604 	i915_gem_object_free(obj);
605 err:
606 	return ERR_PTR(err);
607 }
608 
609 static struct drm_i915_gem_object *
610 _i915_gem_object_create_stolen(struct intel_memory_region *mem,
611 			       resource_size_t size,
612 			       unsigned int flags)
613 {
614 	struct drm_i915_private *i915 = mem->i915;
615 	struct drm_i915_gem_object *obj;
616 	struct drm_mm_node *stolen;
617 	int ret;
618 
619 	if (!drm_mm_initialized(&i915->mm.stolen))
620 		return ERR_PTR(-ENODEV);
621 
622 	if (size == 0)
623 		return ERR_PTR(-EINVAL);
624 
625 	stolen = kzalloc(sizeof(*stolen), GFP_KERNEL);
626 	if (!stolen)
627 		return ERR_PTR(-ENOMEM);
628 
629 	ret = i915_gem_stolen_insert_node(i915, stolen, size, 4096);
630 	if (ret) {
631 		obj = ERR_PTR(ret);
632 		goto err_free;
633 	}
634 
635 	obj = __i915_gem_object_create_stolen(mem, stolen);
636 	if (IS_ERR(obj))
637 		goto err_remove;
638 
639 	return obj;
640 
641 err_remove:
642 	i915_gem_stolen_remove_node(i915, stolen);
643 err_free:
644 	kfree(stolen);
645 	return obj;
646 }
647 
648 struct drm_i915_gem_object *
649 i915_gem_object_create_stolen(struct drm_i915_private *i915,
650 			      resource_size_t size)
651 {
652 	return i915_gem_object_create_region(i915->mm.regions[INTEL_REGION_STOLEN],
653 					     size, I915_BO_ALLOC_CONTIGUOUS);
654 }
655 
656 static int init_stolen(struct intel_memory_region *mem)
657 {
658 	intel_memory_region_set_name(mem, "stolen");
659 
660 	/*
661 	 * Initialise stolen early so that we may reserve preallocated
662 	 * objects for the BIOS to KMS transition.
663 	 */
664 	return i915_gem_init_stolen(mem->i915);
665 }
666 
667 static void release_stolen(struct intel_memory_region *mem)
668 {
669 	i915_gem_cleanup_stolen(mem->i915);
670 }
671 
672 static const struct intel_memory_region_ops i915_region_stolen_ops = {
673 	.init = init_stolen,
674 	.release = release_stolen,
675 	.create_object = _i915_gem_object_create_stolen,
676 };
677 
678 struct intel_memory_region *i915_gem_stolen_setup(struct drm_i915_private *i915)
679 {
680 	return intel_memory_region_create(i915,
681 					  intel_graphics_stolen_res.start,
682 					  resource_size(&intel_graphics_stolen_res),
683 					  PAGE_SIZE, 0,
684 					  &i915_region_stolen_ops);
685 }
686 
687 struct drm_i915_gem_object *
688 i915_gem_object_create_stolen_for_preallocated(struct drm_i915_private *i915,
689 					       resource_size_t stolen_offset,
690 					       resource_size_t size)
691 {
692 	struct intel_memory_region *mem = i915->mm.regions[INTEL_REGION_STOLEN];
693 	struct drm_i915_gem_object *obj;
694 	struct drm_mm_node *stolen;
695 	int ret;
696 
697 	if (!drm_mm_initialized(&i915->mm.stolen))
698 		return ERR_PTR(-ENODEV);
699 
700 	drm_dbg(&i915->drm,
701 		"creating preallocated stolen object: stolen_offset=%pa, size=%pa\n",
702 		&stolen_offset, &size);
703 
704 	/* KISS and expect everything to be page-aligned */
705 	if (GEM_WARN_ON(size == 0) ||
706 	    GEM_WARN_ON(!IS_ALIGNED(size, I915_GTT_PAGE_SIZE)) ||
707 	    GEM_WARN_ON(!IS_ALIGNED(stolen_offset, I915_GTT_MIN_ALIGNMENT)))
708 		return ERR_PTR(-EINVAL);
709 
710 	stolen = kzalloc(sizeof(*stolen), GFP_KERNEL);
711 	if (!stolen)
712 		return ERR_PTR(-ENOMEM);
713 
714 	stolen->start = stolen_offset;
715 	stolen->size = size;
716 	mutex_lock(&i915->mm.stolen_lock);
717 	ret = drm_mm_reserve_node(&i915->mm.stolen, stolen);
718 	mutex_unlock(&i915->mm.stolen_lock);
719 	if (ret) {
720 		obj = ERR_PTR(ret);
721 		goto err_free;
722 	}
723 
724 	obj = __i915_gem_object_create_stolen(mem, stolen);
725 	if (IS_ERR(obj))
726 		goto err_stolen;
727 
728 	i915_gem_object_set_cache_coherency(obj, I915_CACHE_NONE);
729 	return obj;
730 
731 err_stolen:
732 	i915_gem_stolen_remove_node(i915, stolen);
733 err_free:
734 	kfree(stolen);
735 	return obj;
736 }
737