Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drm/xe/vf: Use only assigned GGTT region

Each VF is assigned a limited range of the GGTT address space.
To ensure that the VF driver does not use GGTT allocations outside
of the assigned region, explicitly reserve GGTT space below and
above this region when initializing GGTT.

Signed-off-by: Michal Wajdeczko <michal.wajdeczko@intel.com>
Reviewed-by: Michał Winiarski <michal.winiarski@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20240527112015.1020-1-michal.wajdeczko@intel.com

+109 -1
+3
drivers/gpu/drm/xe/xe_device_types.h
··· 196 196 struct { 197 197 /** @sriov.vf.memirq: Memory Based Interrupts. */ 198 198 struct xe_memirq memirq; 199 + 200 + /** @sriov.vf.ggtt_balloon: GGTT regions excluded from use. */ 201 + struct drm_mm_node ggtt_balloon[2]; 199 202 } vf; 200 203 } sriov; 201 204
+13 -1
drivers/gpu/drm/xe/xe_ggtt.c
··· 20 20 #include "xe_device.h" 21 21 #include "xe_gt.h" 22 22 #include "xe_gt_printk.h" 23 + #include "xe_gt_sriov_vf.h" 23 24 #include "xe_gt_tlb_invalidation.h" 24 25 #include "xe_map.h" 25 26 #include "xe_pm.h" ··· 142 141 struct xe_device *xe = tile_to_xe(ggtt->tile); 143 142 struct pci_dev *pdev = to_pci_dev(xe->drm.dev); 144 143 unsigned int gsm_size; 144 + int err; 145 145 146 146 if (IS_SRIOV_VF(xe)) 147 147 gsm_size = SZ_8M; /* GGTT is expected to be 4GiB */ ··· 196 194 mutex_init(&ggtt->lock); 197 195 primelockdep(ggtt); 198 196 199 - return drmm_add_action_or_reset(&xe->drm, ggtt_fini_early, ggtt); 197 + err = drmm_add_action_or_reset(&xe->drm, ggtt_fini_early, ggtt); 198 + if (err) 199 + return err; 200 + 201 + if (IS_SRIOV_VF(xe)) { 202 + err = xe_gt_sriov_vf_prepare_ggtt(xe_tile_get_gt(ggtt->tile, 0)); 203 + if (err) 204 + return err; 205 + } 206 + 207 + return 0; 200 208 } 201 209 202 210 static void xe_ggtt_invalidate(struct xe_ggtt *ggtt);
+92
drivers/gpu/drm/xe/xe_gt_sriov_vf.c
··· 14 14 #include "abi/guc_klvs_abi.h" 15 15 #include "abi/guc_relay_actions_abi.h" 16 16 #include "regs/xe_gt_regs.h" 17 + #include "regs/xe_gtt_defs.h" 17 18 18 19 #include "xe_assert.h" 19 20 #include "xe_device.h" 21 + #include "xe_ggtt.h" 20 22 #include "xe_gt_sriov_printk.h" 21 23 #include "xe_gt_sriov_vf.h" 22 24 #include "xe_gt_sriov_vf_types.h" ··· 27 25 #include "xe_guc_relay.h" 28 26 #include "xe_mmio.h" 29 27 #include "xe_sriov.h" 28 + #include "xe_uc_fw.h" 29 + #include "xe_wopcm.h" 30 30 31 31 #define make_u64_from_u32(hi, lo) ((u64)((u64)(u32)(hi) << 32 | (u32)(lo))) 32 32 ··· 476 472 xe_gt_assert(gt, gt->sriov.vf.self_config.num_ctxs); 477 473 478 474 return gt->sriov.vf.self_config.num_ctxs; 475 + } 476 + 477 + static int vf_balloon_ggtt(struct xe_gt *gt) 478 + { 479 + struct xe_gt_sriov_vf_selfconfig *config = &gt->sriov.vf.self_config; 480 + struct xe_tile *tile = gt_to_tile(gt); 481 + struct xe_ggtt *ggtt = tile->mem.ggtt; 482 + struct xe_device *xe = gt_to_xe(gt); 483 + u64 start, end; 484 + int err; 485 + 486 + xe_gt_assert(gt, IS_SRIOV_VF(xe)); 487 + xe_gt_assert(gt, !xe_gt_is_media_type(gt)); 488 + 489 + if (!config->ggtt_size) 490 + return -ENODATA; 491 + 492 + /* 493 + * VF can only use part of the GGTT as allocated by the PF: 494 + * 495 + * WOPCM GUC_GGTT_TOP 496 + * |<------------ Total GGTT size ------------------>| 497 + * 498 + * VF GGTT base -->|<- size ->| 499 + * 500 + * +--------------------+----------+-----------------+ 501 + * |////////////////////| block |\\\\\\\\\\\\\\\\\| 502 + * +--------------------+----------+-----------------+ 503 + * 504 + * |<--- balloon[0] --->|<-- VF -->|<-- balloon[1] ->| 505 + */ 506 + 507 + start = xe_wopcm_size(xe); 508 + end = config->ggtt_base; 509 + if (end != start) { 510 + err = xe_ggtt_balloon(ggtt, start, end, &tile->sriov.vf.ggtt_balloon[0]); 511 + if (err) 512 + goto failed; 513 + } 514 + 515 + start = config->ggtt_base + config->ggtt_size; 516 + end = GUC_GGTT_TOP; 517 + if (end != start) { 518 + err = xe_ggtt_balloon(ggtt, start, end, &tile->sriov.vf.ggtt_balloon[1]); 519 + if (err) 520 + goto deballoon; 521 + } 522 + 523 + return 0; 524 + 525 + deballoon: 526 + xe_ggtt_deballoon(ggtt, &tile->sriov.vf.ggtt_balloon[0]); 527 + failed: 528 + return err; 529 + } 530 + 531 + static void deballoon_ggtt(struct drm_device *drm, void *arg) 532 + { 533 + struct xe_tile *tile = arg; 534 + struct xe_ggtt *ggtt = tile->mem.ggtt; 535 + 536 + xe_tile_assert(tile, IS_SRIOV_VF(tile_to_xe(tile))); 537 + xe_ggtt_deballoon(ggtt, &tile->sriov.vf.ggtt_balloon[1]); 538 + xe_ggtt_deballoon(ggtt, &tile->sriov.vf.ggtt_balloon[0]); 539 + } 540 + 541 + /** 542 + * xe_gt_sriov_vf_prepare_ggtt - Prepare a VF's GGTT configuration. 543 + * @gt: the &xe_gt 544 + * 545 + * This function is for VF use only. 546 + * 547 + * Return: 0 on success or a negative error code on failure. 548 + */ 549 + int xe_gt_sriov_vf_prepare_ggtt(struct xe_gt *gt) 550 + { 551 + struct xe_tile *tile = gt_to_tile(gt); 552 + struct xe_device *xe = tile_to_xe(tile); 553 + int err; 554 + 555 + if (xe_gt_is_media_type(gt)) 556 + return 0; 557 + 558 + err = vf_balloon_ggtt(gt); 559 + if (err) 560 + return err; 561 + 562 + return drmm_add_action_or_reset(&xe->drm, deballoon_ggtt, tile); 479 563 } 480 564 481 565 static int relay_action_handshake(struct xe_gt *gt, u32 *major, u32 *minor)
+1
drivers/gpu/drm/xe/xe_gt_sriov_vf.h
··· 16 16 int xe_gt_sriov_vf_query_config(struct xe_gt *gt); 17 17 int xe_gt_sriov_vf_connect(struct xe_gt *gt); 18 18 int xe_gt_sriov_vf_query_runtime(struct xe_gt *gt); 19 + int xe_gt_sriov_vf_prepare_ggtt(struct xe_gt *gt); 19 20 20 21 u32 xe_gt_sriov_vf_gmdid(struct xe_gt *gt); 21 22 u16 xe_gt_sriov_vf_guc_ids(struct xe_gt *gt);