xref: /dragonfly/sys/dev/drm/i915/i915_gem_gtt.c (revision 38b930d0)
1 /*
2  * Copyright © 2010 Daniel Vetter
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice (including the next
12  * paragraph) shall be included in all copies or substantial portions of the
13  * Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21  * IN THE SOFTWARE.
22  *
23  * $FreeBSD: src/sys/dev/drm2/i915/i915_gem_gtt.c,v 1.1 2012/05/22 11:07:44 kib Exp $
24  */
25 
26 #include <sys/sfbuf.h>
27 
28 #include <drm/drmP.h>
29 #include <drm/i915_drm.h>
30 #include "i915_drv.h"
31 #include "intel_drv.h"
32 
33 /* PPGTT support for Sandybdrige/Gen6 and later */
34 static void
35 i915_ppgtt_clear_range(struct i915_hw_ppgtt *ppgtt,
36     unsigned first_entry, unsigned num_entries)
37 {
38 	uint32_t *pt_vaddr;
39 	uint32_t scratch_pte;
40 	struct sf_buf *sf;
41 	unsigned act_pd, first_pte, last_pte, i;
42 
43 	act_pd = first_entry / I915_PPGTT_PT_ENTRIES;
44 	first_pte = first_entry % I915_PPGTT_PT_ENTRIES;
45 
46 	scratch_pte = GEN6_PTE_ADDR_ENCODE(ppgtt->scratch_page_dma_addr);
47 	scratch_pte |= GEN6_PTE_VALID | GEN6_PTE_CACHE_LLC;
48 
49 	while (num_entries) {
50 		last_pte = first_pte + num_entries;
51 		if (last_pte > I915_PPGTT_PT_ENTRIES)
52 			last_pte = I915_PPGTT_PT_ENTRIES;
53 
54 		sf = sf_buf_alloc(ppgtt->pt_pages[act_pd]);
55 		pt_vaddr = (uint32_t *)(uintptr_t)sf_buf_kva(sf);
56 
57 		for (i = first_pte; i < last_pte; i++)
58 			pt_vaddr[i] = scratch_pte;
59 
60 		sf_buf_free(sf);
61 
62 		num_entries -= last_pte - first_pte;
63 		first_pte = 0;
64 		act_pd++;
65 	}
66 
67 }
68 
69 int
70 i915_gem_init_aliasing_ppgtt(struct drm_device *dev)
71 {
72 	struct drm_i915_private *dev_priv;
73 	struct i915_hw_ppgtt *ppgtt;
74 	u_int first_pd_entry_in_global_pt, i;
75 
76 	dev_priv = dev->dev_private;
77 
78 	/*
79 	 * ppgtt PDEs reside in the global gtt pagetable, which has 512*1024
80 	 * entries. For aliasing ppgtt support we just steal them at the end for
81 	 * now.
82 	 */
83 	first_pd_entry_in_global_pt = 512 * 1024 - I915_PPGTT_PD_ENTRIES;
84 
85 	ppgtt = kmalloc(sizeof(*ppgtt), DRM_I915_GEM, M_WAITOK | M_ZERO);
86 
87 	ppgtt->num_pd_entries = I915_PPGTT_PD_ENTRIES;
88 	ppgtt->pt_pages = kmalloc(sizeof(vm_page_t) * ppgtt->num_pd_entries,
89 	    DRM_I915_GEM, M_WAITOK | M_ZERO);
90 
91 	for (i = 0; i < ppgtt->num_pd_entries; i++) {
92 		ppgtt->pt_pages[i] = vm_page_alloc(NULL, 0,
93 		    VM_ALLOC_NORMAL | VM_ALLOC_ZERO);
94 		if (ppgtt->pt_pages[i] == NULL) {
95 			dev_priv->mm.aliasing_ppgtt = ppgtt;
96 			i915_gem_cleanup_aliasing_ppgtt(dev);
97 			return (-ENOMEM);
98 		}
99 	}
100 
101 	ppgtt->scratch_page_dma_addr = dev_priv->mm.gtt->scratch_page_dma;
102 
103 	i915_ppgtt_clear_range(ppgtt, 0, ppgtt->num_pd_entries *
104 	    I915_PPGTT_PT_ENTRIES);
105 	ppgtt->pd_offset = (first_pd_entry_in_global_pt) * sizeof(uint32_t);
106 	dev_priv->mm.aliasing_ppgtt = ppgtt;
107 	return (0);
108 }
109 
110 static void
111 i915_ppgtt_insert_pages(struct i915_hw_ppgtt *ppgtt, unsigned first_entry,
112     unsigned num_entries, vm_page_t *pages, uint32_t pte_flags)
113 {
114 	uint32_t *pt_vaddr, pte;
115 	struct sf_buf *sf;
116 	unsigned act_pd, first_pte;
117 	unsigned last_pte, i;
118 	vm_paddr_t page_addr;
119 
120 	act_pd = first_entry / I915_PPGTT_PT_ENTRIES;
121 	first_pte = first_entry % I915_PPGTT_PT_ENTRIES;
122 
123 	while (num_entries) {
124 		last_pte = first_pte + num_entries;
125 		if (last_pte > I915_PPGTT_PT_ENTRIES)
126 			last_pte = I915_PPGTT_PT_ENTRIES;
127 
128 		sf = sf_buf_alloc(ppgtt->pt_pages[act_pd]);
129 		pt_vaddr = (uint32_t *)(uintptr_t)sf_buf_kva(sf);
130 
131 		for (i = first_pte; i < last_pte; i++) {
132 			page_addr = VM_PAGE_TO_PHYS(*pages);
133 			pte = GEN6_PTE_ADDR_ENCODE(page_addr);
134 			pt_vaddr[i] = pte | pte_flags;
135 
136 			pages++;
137 		}
138 
139 		sf_buf_free(sf);
140 
141 		num_entries -= last_pte - first_pte;
142 		first_pte = 0;
143 		act_pd++;
144 	}
145 }
146 
147 void
148 i915_ppgtt_bind_object(struct i915_hw_ppgtt *ppgtt,
149     struct drm_i915_gem_object *obj, enum i915_cache_level cache_level)
150 {
151 	struct drm_device *dev;
152 	struct drm_i915_private *dev_priv;
153 	uint32_t pte_flags;
154 
155 	dev = obj->base.dev;
156 	dev_priv = dev->dev_private;
157 	pte_flags = GEN6_PTE_VALID;
158 
159 	switch (cache_level) {
160 	case I915_CACHE_LLC_MLC:
161 		pte_flags |= GEN6_PTE_CACHE_LLC_MLC;
162 		break;
163 	case I915_CACHE_LLC:
164 		pte_flags |= GEN6_PTE_CACHE_LLC;
165 		break;
166 	case I915_CACHE_NONE:
167 		pte_flags |= GEN6_PTE_UNCACHED;
168 		break;
169 	default:
170 		panic("cache mode");
171 	}
172 
173 	i915_ppgtt_insert_pages(ppgtt, obj->gtt_space->start >> PAGE_SHIFT,
174 	    obj->base.size >> PAGE_SHIFT, obj->pages, pte_flags);
175 }
176 
177 void i915_ppgtt_unbind_object(struct i915_hw_ppgtt *ppgtt,
178 			      struct drm_i915_gem_object *obj)
179 {
180 	i915_ppgtt_clear_range(ppgtt, obj->gtt_space->start >> PAGE_SHIFT,
181 	    obj->base.size >> PAGE_SHIFT);
182 }
183 
184 void
185 i915_gem_cleanup_aliasing_ppgtt(struct drm_device *dev)
186 {
187 	struct drm_i915_private *dev_priv;
188 	struct i915_hw_ppgtt *ppgtt;
189 	vm_page_t m;
190 	int i;
191 
192 	dev_priv = dev->dev_private;
193 	ppgtt = dev_priv->mm.aliasing_ppgtt;
194 	if (ppgtt == NULL)
195 		return;
196 	dev_priv->mm.aliasing_ppgtt = NULL;
197 
198 	for (i = 0; i < ppgtt->num_pd_entries; i++) {
199 		m = ppgtt->pt_pages[i];
200 		if (m != NULL) {
201 			vm_page_busy_wait(m, FALSE, "i915gem");
202 			vm_page_unwire(m, 0);
203 			vm_page_free(m);
204 		}
205 	}
206 	drm_free(ppgtt->pt_pages, DRM_I915_GEM);
207 	drm_free(ppgtt, DRM_I915_GEM);
208 }
209 
210 
211 static unsigned int
212 cache_level_to_agp_type(struct drm_device *dev, enum i915_cache_level
213     cache_level)
214 {
215 
216 	switch (cache_level) {
217 	case I915_CACHE_LLC_MLC:
218 		if (INTEL_INFO(dev)->gen >= 6)
219 			return (AGP_USER_CACHED_MEMORY_LLC_MLC);
220 		/*
221 		 * Older chipsets do not have this extra level of CPU
222 		 * cacheing, so fallthrough and request the PTE simply
223 		 * as cached.
224 		 */
225 	case I915_CACHE_LLC:
226 		return (AGP_USER_CACHED_MEMORY);
227 
228 	default:
229 	case I915_CACHE_NONE:
230 		return (AGP_USER_MEMORY);
231 	}
232 }
233 
234 static bool
235 do_idling(struct drm_i915_private *dev_priv)
236 {
237 	bool ret = dev_priv->mm.interruptible;
238 
239 	if (unlikely(dev_priv->mm.gtt->do_idle_maps)) {
240 		dev_priv->mm.interruptible = false;
241 		if (i915_gpu_idle(dev_priv->dev, false)) {
242 			DRM_ERROR("Couldn't idle GPU\n");
243 			/* Wait a bit, in hopes it avoids the hang */
244 			DELAY(10);
245 		}
246 	}
247 
248 	return ret;
249 }
250 
251 static void
252 undo_idling(struct drm_i915_private *dev_priv, bool interruptible)
253 {
254 
255 	if (unlikely(dev_priv->mm.gtt->do_idle_maps))
256 		dev_priv->mm.interruptible = interruptible;
257 }
258 
259 void
260 i915_gem_restore_gtt_mappings(struct drm_device *dev)
261 {
262 	struct drm_i915_private *dev_priv;
263 	struct drm_i915_gem_object *obj;
264 
265 	dev_priv = dev->dev_private;
266 
267 	/* First fill our portion of the GTT with scratch pages */
268 	intel_gtt_clear_range(dev_priv->mm.gtt_start / PAGE_SIZE,
269 	    (dev_priv->mm.gtt_end - dev_priv->mm.gtt_start) / PAGE_SIZE);
270 
271 	list_for_each_entry(obj, &dev_priv->mm.gtt_list, gtt_list) {
272 		i915_gem_clflush_object(obj);
273 		i915_gem_gtt_rebind_object(obj, obj->cache_level);
274 	}
275 
276 	intel_gtt_chipset_flush();
277 }
278 
279 int
280 i915_gem_gtt_bind_object(struct drm_i915_gem_object *obj)
281 {
282 	unsigned int agp_type;
283 
284 	agp_type = cache_level_to_agp_type(obj->base.dev, obj->cache_level);
285 	intel_gtt_insert_pages(obj->gtt_space->start >> PAGE_SHIFT,
286 	    obj->base.size >> PAGE_SHIFT, obj->pages, agp_type);
287 	return (0);
288 }
289 
290 void
291 i915_gem_gtt_rebind_object(struct drm_i915_gem_object *obj,
292     enum i915_cache_level cache_level)
293 {
294 	struct drm_device *dev;
295 	struct drm_i915_private *dev_priv;
296 	unsigned int agp_type;
297 
298 	dev = obj->base.dev;
299 	dev_priv = dev->dev_private;
300 	agp_type = cache_level_to_agp_type(dev, cache_level);
301 
302 	intel_gtt_insert_pages(obj->gtt_space->start >> PAGE_SHIFT,
303 	    obj->base.size >> PAGE_SHIFT, obj->pages, agp_type);
304 }
305 
306 void
307 i915_gem_gtt_unbind_object(struct drm_i915_gem_object *obj)
308 {
309 	struct drm_device *dev = obj->base.dev;
310 	struct drm_i915_private *dev_priv = dev->dev_private;
311 	bool interruptible;
312 
313 	dev = obj->base.dev;
314 	dev_priv = dev->dev_private;
315 
316 	interruptible = do_idling(dev_priv);
317 
318 	intel_gtt_clear_range(obj->gtt_space->start >> PAGE_SHIFT,
319 	    obj->base.size >> PAGE_SHIFT);
320 
321 	undo_idling(dev_priv, interruptible);
322 }
323