Skip to content

Commit b2d6ef7

Browse files
xiongzhazhenyw
authored andcommitted
drm/i915/gvt: Let each vgpu has separate opregion memory
Currently every vgpu share a common gvt opregion memory, but it is freed at vgpu destroy, then the later vgpu doesn't have opregion memory once the first vgpu is destroyed. This cause guest function failure like reboot, second or later boot. This patch allocate and init virt opregion memory for each vgpu, so this memory could be freed at vgpu destroy. Signed-off-by: Xiong Zhang <xiong.y.zhang@intel.com> Signed-off-by: Zhenyu Wang <zhenyuw@linux.intel.com>
1 parent 295764c commit b2d6ef7

File tree

3 files changed

+42
-78
lines changed

3 files changed

+42
-78
lines changed

drivers/gpu/drm/i915/gvt/gvt.c

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -323,7 +323,6 @@ void intel_gvt_clean_device(struct drm_i915_private *dev_priv)
323323
intel_gvt_clean_cmd_parser(gvt);
324324
intel_gvt_clean_sched_policy(gvt);
325325
intel_gvt_clean_workload_scheduler(gvt);
326-
intel_gvt_clean_opregion(gvt);
327326
intel_gvt_clean_gtt(gvt);
328327
intel_gvt_clean_irq(gvt);
329328
intel_gvt_clean_mmio_info(gvt);
@@ -397,13 +396,9 @@ int intel_gvt_init_device(struct drm_i915_private *dev_priv)
397396
if (ret)
398397
goto out_clean_irq;
399398

400-
ret = intel_gvt_init_opregion(gvt);
401-
if (ret)
402-
goto out_clean_gtt;
403-
404399
ret = intel_gvt_init_workload_scheduler(gvt);
405400
if (ret)
406-
goto out_clean_opregion;
401+
goto out_clean_gtt;
407402

408403
ret = intel_gvt_init_sched_policy(gvt);
409404
if (ret)
@@ -460,8 +455,6 @@ int intel_gvt_init_device(struct drm_i915_private *dev_priv)
460455
intel_gvt_clean_sched_policy(gvt);
461456
out_clean_workload_scheduler:
462457
intel_gvt_clean_workload_scheduler(gvt);
463-
out_clean_opregion:
464-
intel_gvt_clean_opregion(gvt);
465458
out_clean_gtt:
466459
intel_gvt_clean_gtt(gvt);
467460
out_clean_irq:

drivers/gpu/drm/i915/gvt/gvt.h

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,6 @@ struct intel_vgpu_irq {
125125
struct intel_vgpu_opregion {
126126
void *va;
127127
u32 gfn[INTEL_GVT_OPREGION_PAGES];
128-
struct page *pages[INTEL_GVT_OPREGION_PAGES];
129128
};
130129

131130
#define vgpu_opregion(vgpu) (&(vgpu->opregion))
@@ -265,11 +264,6 @@ struct intel_gvt_firmware {
265264
bool firmware_loaded;
266265
};
267266

268-
struct intel_gvt_opregion {
269-
void *opregion_va;
270-
u32 opregion_pa;
271-
};
272-
273267
#define NR_MAX_INTEL_VGPU_TYPES 20
274268
struct intel_vgpu_type {
275269
char name[16];
@@ -293,7 +287,6 @@ struct intel_gvt {
293287
struct intel_gvt_firmware firmware;
294288
struct intel_gvt_irq irq;
295289
struct intel_gvt_gtt gtt;
296-
struct intel_gvt_opregion opregion;
297290
struct intel_gvt_workload_scheduler scheduler;
298291
struct notifier_block shadow_ctx_notifier_block[I915_NUM_ENGINES];
299292
DECLARE_HASHTABLE(cmd_table, GVT_CMD_HASH_BITS);
@@ -511,9 +504,6 @@ static inline u64 intel_vgpu_get_bar_gpa(struct intel_vgpu *vgpu, int bar)
511504
PCI_BASE_ADDRESS_MEM_MASK;
512505
}
513506

514-
void intel_gvt_clean_opregion(struct intel_gvt *gvt);
515-
int intel_gvt_init_opregion(struct intel_gvt *gvt);
516-
517507
void intel_vgpu_clean_opregion(struct intel_vgpu *vgpu);
518508
int intel_vgpu_init_opregion(struct intel_vgpu *vgpu, u32 gpa);
519509

drivers/gpu/drm/i915/gvt/opregion.c

Lines changed: 41 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -213,16 +213,55 @@ static void virt_vbt_generation(struct vbt *v)
213213
v->driver_features.lvds_config = BDB_DRIVER_FEATURE_NO_LVDS;
214214
}
215215

216+
static int alloc_and_init_virt_opregion(struct intel_vgpu *vgpu)
217+
{
218+
u8 *buf;
219+
struct opregion_header *header;
220+
struct vbt v;
221+
222+
gvt_dbg_core("init vgpu%d opregion\n", vgpu->id);
223+
vgpu_opregion(vgpu)->va = (void *)__get_free_pages(GFP_KERNEL |
224+
__GFP_ZERO,
225+
get_order(INTEL_GVT_OPREGION_SIZE));
226+
if (!vgpu_opregion(vgpu)->va) {
227+
gvt_err("fail to get memory for vgpu virt opregion\n");
228+
return -ENOMEM;
229+
}
230+
231+
/* emulated opregion with VBT mailbox only */
232+
buf = (u8 *)vgpu_opregion(vgpu)->va;
233+
header = (struct opregion_header *)buf;
234+
memcpy(header->signature, OPREGION_SIGNATURE,
235+
sizeof(OPREGION_SIGNATURE));
236+
header->size = 0x8;
237+
header->opregion_ver = 0x02000000;
238+
header->mboxes = MBOX_VBT;
239+
240+
/* for unknown reason, the value in LID field is incorrect
241+
* which block the windows guest, so workaround it by force
242+
* setting it to "OPEN"
243+
*/
244+
buf[INTEL_GVT_OPREGION_CLID] = 0x3;
245+
246+
/* emulated vbt from virt vbt generation */
247+
virt_vbt_generation(&v);
248+
memcpy(buf + INTEL_GVT_OPREGION_VBT_OFFSET, &v, sizeof(struct vbt));
249+
250+
return 0;
251+
}
252+
216253
static int init_vgpu_opregion(struct intel_vgpu *vgpu, u32 gpa)
217254
{
218-
int i;
255+
int i, ret;
219256

220257
if (WARN((vgpu_opregion(vgpu)->va),
221258
"vgpu%d: opregion has been initialized already.\n",
222259
vgpu->id))
223260
return -EINVAL;
224261

225-
vgpu_opregion(vgpu)->va = vgpu->gvt->opregion.opregion_va;
262+
ret = alloc_and_init_virt_opregion(vgpu);
263+
if (ret < 0)
264+
return ret;
226265

227266
for (i = 0; i < INTEL_GVT_OPREGION_PAGES; i++)
228267
vgpu_opregion(vgpu)->gfn[i] = (gpa >> PAGE_SHIFT) + i;
@@ -304,64 +343,6 @@ int intel_vgpu_init_opregion(struct intel_vgpu *vgpu, u32 gpa)
304343
return 0;
305344
}
306345

307-
/**
308-
* intel_gvt_clean_opregion - clean host opergion related stuffs
309-
* @gvt: a GVT device
310-
*
311-
*/
312-
void intel_gvt_clean_opregion(struct intel_gvt *gvt)
313-
{
314-
free_pages((unsigned long)gvt->opregion.opregion_va,
315-
get_order(INTEL_GVT_OPREGION_SIZE));
316-
gvt->opregion.opregion_va = NULL;
317-
}
318-
319-
/**
320-
* intel_gvt_init_opregion - initialize host opergion related stuffs
321-
* @gvt: a GVT device
322-
*
323-
* Returns:
324-
* Zero on success, negative error code if failed.
325-
*/
326-
int intel_gvt_init_opregion(struct intel_gvt *gvt)
327-
{
328-
u8 *buf;
329-
struct opregion_header *header;
330-
struct vbt v;
331-
332-
gvt_dbg_core("init host opregion\n");
333-
334-
gvt->opregion.opregion_va = (void *)__get_free_pages(GFP_KERNEL |
335-
__GFP_ZERO,
336-
get_order(INTEL_GVT_OPREGION_SIZE));
337-
338-
if (!gvt->opregion.opregion_va) {
339-
gvt_err("fail to get memory for virt opregion\n");
340-
return -ENOMEM;
341-
}
342-
343-
/* emulated opregion with VBT mailbox only */
344-
buf = (u8 *)gvt->opregion.opregion_va;
345-
header = (struct opregion_header *)buf;
346-
memcpy(header->signature, OPREGION_SIGNATURE,
347-
sizeof(OPREGION_SIGNATURE));
348-
header->size = 0x8;
349-
header->opregion_ver = 0x02000000;
350-
header->mboxes = MBOX_VBT;
351-
352-
/* for unknown reason, the value in LID field is incorrect
353-
* which block the windows guest, so workaround it by force
354-
* setting it to "OPEN"
355-
*/
356-
buf[INTEL_GVT_OPREGION_CLID] = 0x3;
357-
358-
/* emulated vbt from virt vbt generation */
359-
virt_vbt_generation(&v);
360-
memcpy(buf + INTEL_GVT_OPREGION_VBT_OFFSET, &v, sizeof(struct vbt));
361-
362-
return 0;
363-
}
364-
365346
#define GVT_OPREGION_FUNC(scic) \
366347
({ \
367348
u32 __ret; \

0 commit comments

Comments
 (0)