aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYu Zhang <yu.c.zhang@linux.intel.com>2015-02-10 06:05:48 -0500
committerDaniel Vetter <daniel.vetter@ffwll.ch>2015-02-13 17:28:23 -0500
commit5dda8fa356587832e5373498d8b973d66735762d (patch)
treef8f01a75840def0fb0f3b389a4b0b50182bd1b2c
parentcf9d2890da19d9544d655554da907049e8226d14 (diff)
drm/i915: Adds graphic address space ballooning logic
With Intel GVT-g, the global graphic memory space is partitioned by multiple vGPU instances in different VMs. The ballooning code is called in i915_gem_setup_global_gtt(), utilizing the drm mm allocator APIs to mark the graphic address space which are partitioned out to other vGPUs as reserved. With ballooning, host side does not need to translate a grahpic address from guest view to host view. By now, current implementation only support the static ballooning, but in the future, with more cooperation from guest driver, the same interfaces can be extended to grow/shrink the guest graphic memory dynamically. v2: take Chris and Daniel's comments: - no guard page between different VMs - use drm_mm_reserve_node() to do the reservation for ballooning, instead of the previous drm_mm_insert_node_in_range_generic() v3: take Daniel's comments: - move ballooning functions into i915_vgpu.c - add kerneldoc to ballooning functions v4: take Tvrtko's comments: - more accurate comments and commit message Signed-off-by: Yu Zhang <yu.c.zhang@linux.intel.com> Signed-off-by: Jike Song <jike.song@intel.com> Signed-off-by: Zhi Wang <zhi.a.wang@intel.com> Signed-off-by: Eddie Dong <eddie.dong@intel.com> Reviewed-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
-rw-r--r--drivers/gpu/drm/i915/i915_gem_gtt.c17
-rw-r--r--drivers/gpu/drm/i915/i915_vgpu.c178
-rw-r--r--drivers/gpu/drm/i915/i915_vgpu.h2
3 files changed, 194 insertions, 3 deletions
diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c
index b48b586dc287..057f905b25b0 100644
--- a/drivers/gpu/drm/i915/i915_gem_gtt.c
+++ b/drivers/gpu/drm/i915/i915_gem_gtt.c
@@ -27,6 +27,7 @@
27#include <drm/drmP.h> 27#include <drm/drmP.h>
28#include <drm/i915_drm.h> 28#include <drm/i915_drm.h>
29#include "i915_drv.h" 29#include "i915_drv.h"
30#include "i915_vgpu.h"
30#include "i915_trace.h" 31#include "i915_trace.h"
31#include "intel_drv.h" 32#include "intel_drv.h"
32 33
@@ -1756,6 +1757,16 @@ static int i915_gem_setup_global_gtt(struct drm_device *dev,
1756 1757
1757 /* Subtract the guard page ... */ 1758 /* Subtract the guard page ... */
1758 drm_mm_init(&ggtt_vm->mm, start, end - start - PAGE_SIZE); 1759 drm_mm_init(&ggtt_vm->mm, start, end - start - PAGE_SIZE);
1760
1761 dev_priv->gtt.base.start = start;
1762 dev_priv->gtt.base.total = end - start;
1763
1764 if (intel_vgpu_active(dev)) {
1765 ret = intel_vgt_balloon(dev);
1766 if (ret)
1767 return ret;
1768 }
1769
1759 if (!HAS_LLC(dev)) 1770 if (!HAS_LLC(dev))
1760 dev_priv->gtt.base.mm.color_adjust = i915_gtt_color_adjust; 1771 dev_priv->gtt.base.mm.color_adjust = i915_gtt_color_adjust;
1761 1772
@@ -1775,9 +1786,6 @@ static int i915_gem_setup_global_gtt(struct drm_device *dev,
1775 vma->bound |= GLOBAL_BIND; 1786 vma->bound |= GLOBAL_BIND;
1776 } 1787 }
1777 1788
1778 dev_priv->gtt.base.start = start;
1779 dev_priv->gtt.base.total = end - start;
1780
1781 /* Clear any non-preallocated blocks */ 1789 /* Clear any non-preallocated blocks */
1782 drm_mm_for_each_hole(entry, &ggtt_vm->mm, hole_start, hole_end) { 1790 drm_mm_for_each_hole(entry, &ggtt_vm->mm, hole_start, hole_end) {
1783 DRM_DEBUG_KMS("clearing unused GTT space: [%lx, %lx]\n", 1791 DRM_DEBUG_KMS("clearing unused GTT space: [%lx, %lx]\n",
@@ -1829,6 +1837,9 @@ void i915_global_gtt_cleanup(struct drm_device *dev)
1829 } 1837 }
1830 1838
1831 if (drm_mm_initialized(&vm->mm)) { 1839 if (drm_mm_initialized(&vm->mm)) {
1840 if (intel_vgpu_active(dev))
1841 intel_vgt_deballoon();
1842
1832 drm_mm_takedown(&vm->mm); 1843 drm_mm_takedown(&vm->mm);
1833 list_del(&vm->global_link); 1844 list_del(&vm->global_link);
1834 } 1845 }
diff --git a/drivers/gpu/drm/i915/i915_vgpu.c b/drivers/gpu/drm/i915/i915_vgpu.c
index 995a6003ed78..5eee75bff170 100644
--- a/drivers/gpu/drm/i915/i915_vgpu.c
+++ b/drivers/gpu/drm/i915/i915_vgpu.c
@@ -84,3 +84,181 @@ void i915_check_vgpu(struct drm_device *dev)
84 dev_priv->vgpu.active = true; 84 dev_priv->vgpu.active = true;
85 DRM_INFO("Virtual GPU for Intel GVT-g detected.\n"); 85 DRM_INFO("Virtual GPU for Intel GVT-g detected.\n");
86} 86}
87
88struct _balloon_info_ {
89 /*
90 * There are up to 2 regions per mappable/unmappable graphic
91 * memory that might be ballooned. Here, index 0/1 is for mappable
92 * graphic memory, 2/3 for unmappable graphic memory.
93 */
94 struct drm_mm_node space[4];
95};
96
97static struct _balloon_info_ bl_info;
98
99/**
100 * intel_vgt_deballoon - deballoon reserved graphics address trunks
101 *
102 * This function is called to deallocate the ballooned-out graphic memory, when
103 * driver is unloaded or when ballooning fails.
104 */
105void intel_vgt_deballoon(void)
106{
107 int i;
108
109 DRM_DEBUG("VGT deballoon.\n");
110
111 for (i = 0; i < 4; i++) {
112 if (bl_info.space[i].allocated)
113 drm_mm_remove_node(&bl_info.space[i]);
114 }
115
116 memset(&bl_info, 0, sizeof(bl_info));
117}
118
119static int vgt_balloon_space(struct drm_mm *mm,
120 struct drm_mm_node *node,
121 unsigned long start, unsigned long end)
122{
123 unsigned long size = end - start;
124
125 if (start == end)
126 return -EINVAL;
127
128 DRM_INFO("balloon space: range [ 0x%lx - 0x%lx ] %lu KiB.\n",
129 start, end, size / 1024);
130
131 node->start = start;
132 node->size = size;
133
134 return drm_mm_reserve_node(mm, node);
135}
136
137/**
138 * intel_vgt_balloon - balloon out reserved graphics address trunks
139 * @dev: drm device
140 *
141 * This function is called at the initialization stage, to balloon out the
142 * graphic address space allocated to other vGPUs, by marking these spaces as
143 * reserved. The ballooning related knowledge(starting address and size of
144 * the mappable/unmappable graphic memory) is described in the vgt_if structure
145 * in a reserved mmio range.
146 *
147 * To give an example, the drawing below depicts one typical scenario after
148 * ballooning. Here the vGPU1 has 2 pieces of graphic address spaces ballooned
149 * out each for the mappable and the non-mappable part. From the vGPU1 point of
150 * view, the total size is the same as the physical one, with the start address
151 * of its graphic space being zero. Yet there are some portions ballooned out(
152 * the shadow part, which are marked as reserved by drm allocator). From the
153 * host point of view, the graphic address space is partitioned by multiple
154 * vGPUs in different VMs.
155 *
156 * vGPU1 view Host view
157 * 0 ------> +-----------+ +-----------+
158 * ^ |///////////| | vGPU3 |
159 * | |///////////| +-----------+
160 * | |///////////| | vGPU2 |
161 * | +-----------+ +-----------+
162 * mappable GM | available | ==> | vGPU1 |
163 * | +-----------+ +-----------+
164 * | |///////////| | |
165 * v |///////////| | Host |
166 * +=======+===========+ +===========+
167 * ^ |///////////| | vGPU3 |
168 * | |///////////| +-----------+
169 * | |///////////| | vGPU2 |
170 * | +-----------+ +-----------+
171 * unmappable GM | available | ==> | vGPU1 |
172 * | +-----------+ +-----------+
173 * | |///////////| | |
174 * | |///////////| | Host |
175 * v |///////////| | |
176 * total GM size ------> +-----------+ +-----------+
177 *
178 * Returns:
179 * zero on success, non-zero if configuration invalid or ballooning failed
180 */
181int intel_vgt_balloon(struct drm_device *dev)
182{
183 struct drm_i915_private *dev_priv = to_i915(dev);
184 struct i915_address_space *ggtt_vm = &dev_priv->gtt.base;
185 unsigned long ggtt_vm_end = ggtt_vm->start + ggtt_vm->total;
186
187 unsigned long mappable_base, mappable_size, mappable_end;
188 unsigned long unmappable_base, unmappable_size, unmappable_end;
189 int ret;
190
191 mappable_base = I915_READ(vgtif_reg(avail_rs.mappable_gmadr.base));
192 mappable_size = I915_READ(vgtif_reg(avail_rs.mappable_gmadr.size));
193 unmappable_base = I915_READ(vgtif_reg(avail_rs.nonmappable_gmadr.base));
194 unmappable_size = I915_READ(vgtif_reg(avail_rs.nonmappable_gmadr.size));
195
196 mappable_end = mappable_base + mappable_size;
197 unmappable_end = unmappable_base + unmappable_size;
198
199 DRM_INFO("VGT ballooning configuration:\n");
200 DRM_INFO("Mappable graphic memory: base 0x%lx size %ldKiB\n",
201 mappable_base, mappable_size / 1024);
202 DRM_INFO("Unmappable graphic memory: base 0x%lx size %ldKiB\n",
203 unmappable_base, unmappable_size / 1024);
204
205 if (mappable_base < ggtt_vm->start ||
206 mappable_end > dev_priv->gtt.mappable_end ||
207 unmappable_base < dev_priv->gtt.mappable_end ||
208 unmappable_end > ggtt_vm_end) {
209 DRM_ERROR("Invalid ballooning configuration!\n");
210 return -EINVAL;
211 }
212
213 /* Unmappable graphic memory ballooning */
214 if (unmappable_base > dev_priv->gtt.mappable_end) {
215 ret = vgt_balloon_space(&ggtt_vm->mm,
216 &bl_info.space[2],
217 dev_priv->gtt.mappable_end,
218 unmappable_base);
219
220 if (ret)
221 goto err;
222 }
223
224 /*
225 * No need to partition out the last physical page,
226 * because it is reserved to the guard page.
227 */
228 if (unmappable_end < ggtt_vm_end - PAGE_SIZE) {
229 ret = vgt_balloon_space(&ggtt_vm->mm,
230 &bl_info.space[3],
231 unmappable_end,
232 ggtt_vm_end - PAGE_SIZE);
233 if (ret)
234 goto err;
235 }
236
237 /* Mappable graphic memory ballooning */
238 if (mappable_base > ggtt_vm->start) {
239 ret = vgt_balloon_space(&ggtt_vm->mm,
240 &bl_info.space[0],
241 ggtt_vm->start, mappable_base);
242
243 if (ret)
244 goto err;
245 }
246
247 if (mappable_end < dev_priv->gtt.mappable_end) {
248 ret = vgt_balloon_space(&ggtt_vm->mm,
249 &bl_info.space[1],
250 mappable_end,
251 dev_priv->gtt.mappable_end);
252
253 if (ret)
254 goto err;
255 }
256
257 DRM_INFO("VGT balloon successfully\n");
258 return 0;
259
260err:
261 DRM_ERROR("VGT balloon fail\n");
262 intel_vgt_deballoon();
263 return ret;
264}
diff --git a/drivers/gpu/drm/i915/i915_vgpu.h b/drivers/gpu/drm/i915/i915_vgpu.h
index aa72e146d6c8..3ed01a7ac48e 100644
--- a/drivers/gpu/drm/i915/i915_vgpu.h
+++ b/drivers/gpu/drm/i915/i915_vgpu.h
@@ -81,5 +81,7 @@ struct vgt_if {
81 (VGT_PVINFO_PAGE + (long)&((struct vgt_if *)NULL)->x) 81 (VGT_PVINFO_PAGE + (long)&((struct vgt_if *)NULL)->x)
82 82
83extern void i915_check_vgpu(struct drm_device *dev); 83extern void i915_check_vgpu(struct drm_device *dev);
84extern int intel_vgt_balloon(struct drm_device *dev);
85extern void intel_vgt_deballoon(void);
84 86
85#endif /* _I915_VGPU_H_ */ 87#endif /* _I915_VGPU_H_ */