aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/i915/i915_vgpu.c
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 /drivers/gpu/drm/i915/i915_vgpu.c
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>
Diffstat (limited to 'drivers/gpu/drm/i915/i915_vgpu.c')
-rw-r--r--drivers/gpu/drm/i915/i915_vgpu.c178
1 files changed, 178 insertions, 0 deletions
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}