From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id EC807C5AE59 for ; Tue, 3 Jun 2025 10:33:37 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 8384110E6F8; Tue, 3 Jun 2025 10:33:37 +0000 (UTC) Authentication-Results: gabe.freedesktop.org; dkim=pass (2048-bit key; unprotected) header.d=intel.com header.i=@intel.com header.b="RuGGudAG"; dkim-atps=neutral Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.19]) by gabe.freedesktop.org (Postfix) with ESMTPS id 9818110E716 for ; Tue, 3 Jun 2025 10:33:35 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1748946816; x=1780482816; h=message-id:date:mime-version:subject:to:references:from: in-reply-to:content-transfer-encoding; bh=KCRnPTUK3lCcMhCRQocBKQwSs+7ShjK/Sy+pKGWlCyU=; b=RuGGudAGY+q9SZR7on3W2mZgn7sfEp/4yvWP5XEbLNVXORzFdT+nWMWA it9YWR7JsuGgqtu1kNtNdEdtRtH37hcDH5kJWU4KGMNKESlKhP6sXvt4H t6uGsuFvHaXZNXqUff4X/uEpSwgiMK71USuFdRIwDvjs+bk/klBoI7Ulh 7ZYjVpoT0OEpjl+HzL/cqlc08AL7Gdf1tP0XXuitVgl0rB5ccNhA+t/GH Id/9q5o35gSC4Rexq0LkLkoOVG3ip9xeoKcpNvgYHeB8cGJZRU9hy7i3M ixW7XPmYlP9GVP+OpsWjwhItRACnIPTGL0V1114Y6bCjCvt5dJKdZAZBm g==; X-CSE-ConnectionGUID: xpQCTTHZTYqXdcpQBqYY9Q== X-CSE-MsgGUID: QesaF9+MQ+2nuPdOWzkx1g== X-IronPort-AV: E=McAfee;i="6700,10204,11451"; a="50102648" X-IronPort-AV: E=Sophos;i="6.16,205,1744095600"; d="scan'208";a="50102648" Received: from orviesa005.jf.intel.com ([10.64.159.145]) by fmvoesa113.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 03 Jun 2025 03:33:35 -0700 X-CSE-ConnectionGUID: SZ7Fkd5IS0GsFwDPlHDm2Q== X-CSE-MsgGUID: 8D291uAlTEKcjRFtsEAMaw== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.16,205,1744095600"; d="scan'208";a="150107138" Received: from irvmail002.ir.intel.com ([10.43.11.120]) by orviesa005.jf.intel.com with ESMTP; 03 Jun 2025 03:33:32 -0700 Received: from [10.245.253.198] (unknown [10.245.253.198]) by irvmail002.ir.intel.com (Postfix) with ESMTP id 8EB2033BE0; Tue, 3 Jun 2025 11:33:31 +0100 (IST) Message-ID: <9e65671d-e014-4b74-a089-93004a43a578@intel.com> Date: Tue, 3 Jun 2025 12:33:31 +0200 MIME-Version: 1.0 User-Agent: Mozilla Thunderbird Subject: Re: [PATCH 2/3] drm/xe/vf: Move tile-related VF functions to separate file To: "Lis, Tomasz" , intel-xe@lists.freedesktop.org References: <20250602103325.549-1-michal.wajdeczko@intel.com> <20250602103325.549-3-michal.wajdeczko@intel.com> <5ed24516-fe4b-4eaa-833c-ce383c2d7f85@intel.com> Content-Language: en-US From: Michal Wajdeczko In-Reply-To: <5ed24516-fe4b-4eaa-833c-ce383c2d7f85@intel.com> Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: intel-xe@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Intel Xe graphics driver List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: intel-xe-bounces@lists.freedesktop.org Sender: "Intel-xe" On 03.06.2025 01:32, Lis, Tomasz wrote: > > On 02.06.2025 12:33, Michal Wajdeczko wrote: >> Some of our VF functions, even if they take a GT pointer, work >> only on primary GT and really are tile-related and would be better >> to keep them separate from the rest of true GT-oriented functions. >> Move them to a file and update to take a tile pointer instead. >> >> Signed-off-by: Michal Wajdeczko >> Cc: Tomasz Lis > > No issues. We've switched the ballooning error from ENODATA to ENOSPC if > ggtt_size is zero, > > but that was very hard to reach anyway since `vf_get_ggtt_info()` > returns with ENODATA earlier. yes, we are checking for zero ggtt_size in vf_get_ggtt_info() and we shouldn't reach any further function if we didn't get any GGTT that's why we have asserts elsewhere to enforce that > > Reviewed-by: Tomasz Lis thanks! > > -Tomasz > >> --- >>   drivers/gpu/drm/xe/Makefile           |   3 +- >>   drivers/gpu/drm/xe/xe_ggtt.c          |   4 +- >>   drivers/gpu/drm/xe/xe_gt_sriov_vf.c   | 245 -------------------------- >>   drivers/gpu/drm/xe/xe_gt_sriov_vf.h   |   4 - >>   drivers/gpu/drm/xe/xe_sriov_vf.c      |   3 +- >>   drivers/gpu/drm/xe/xe_tile_sriov_vf.c | 245 ++++++++++++++++++++++++++ >>   drivers/gpu/drm/xe/xe_tile_sriov_vf.h |  18 ++ >>   7 files changed, 269 insertions(+), 253 deletions(-) >>   create mode 100644 drivers/gpu/drm/xe/xe_tile_sriov_vf.c >>   create mode 100644 drivers/gpu/drm/xe/xe_tile_sriov_vf.h >> >> diff --git a/drivers/gpu/drm/xe/Makefile b/drivers/gpu/drm/xe/Makefile >> index e4bf484d4121..f5f5775acdc0 100644 >> --- a/drivers/gpu/drm/xe/Makefile >> +++ b/drivers/gpu/drm/xe/Makefile >> @@ -139,7 +139,8 @@ xe-y += \ >>       xe_guc_relay.o \ >>       xe_memirq.o \ >>       xe_sriov.o \ >> -    xe_sriov_vf.o >> +    xe_sriov_vf.o \ >> +    xe_tile_sriov_vf.o >>     xe-$(CONFIG_PCI_IOV) += \ >>       xe_gt_sriov_pf.o \ >> diff --git a/drivers/gpu/drm/xe/xe_ggtt.c b/drivers/gpu/drm/xe/xe_ggtt.c >> index af8e53014b87..b9a0fd5ccaba 100644 >> --- a/drivers/gpu/drm/xe/xe_ggtt.c >> +++ b/drivers/gpu/drm/xe/xe_ggtt.c >> @@ -22,12 +22,12 @@ >>   #include "xe_device.h" >>   #include "xe_gt.h" >>   #include "xe_gt_printk.h" >> -#include "xe_gt_sriov_vf.h" >>   #include "xe_gt_tlb_invalidation.h" >>   #include "xe_map.h" >>   #include "xe_mmio.h" >>   #include "xe_pm.h" >>   #include "xe_sriov.h" >> +#include "xe_tile_sriov_vf.h" >>   #include "xe_wa.h" >>   #include "xe_wopcm.h" >>   @@ -258,7 +258,7 @@ int xe_ggtt_init_early(struct xe_ggtt *ggtt) >>           return err; >>         if (IS_SRIOV_VF(xe)) { >> -        err = xe_gt_sriov_vf_prepare_ggtt(xe_tile_get_gt(ggtt->tile, >> 0)); >> +        err = xe_tile_sriov_vf_prepare_ggtt(ggtt->tile); >>           if (err) >>               return err; >>       } >> diff --git a/drivers/gpu/drm/xe/xe_gt_sriov_vf.c b/drivers/gpu/drm/xe/ >> xe_gt_sriov_vf.c >> index acfb3b1b0832..792523cfa6e6 100644 >> --- a/drivers/gpu/drm/xe/xe_gt_sriov_vf.c >> +++ b/drivers/gpu/drm/xe/xe_gt_sriov_vf.c >> @@ -613,168 +613,6 @@ s64 xe_gt_sriov_vf_ggtt_shift(struct xe_gt *gt) >>       return config->ggtt_shift; >>   } >>   -static int vf_init_ggtt_balloons(struct xe_gt *gt) >> -{ >> -    struct xe_tile *tile = gt_to_tile(gt); >> -    struct xe_ggtt *ggtt = tile->mem.ggtt; >> - >> -    xe_gt_assert(gt, IS_SRIOV_VF(gt_to_xe(gt))); >> -    xe_gt_assert(gt, !xe_gt_is_media_type(gt)); >> - >> -    tile->sriov.vf.ggtt_balloon[0] = xe_ggtt_node_init(ggtt); >> -    if (IS_ERR(tile->sriov.vf.ggtt_balloon[0])) >> -        return PTR_ERR(tile->sriov.vf.ggtt_balloon[0]); >> - >> -    tile->sriov.vf.ggtt_balloon[1] = xe_ggtt_node_init(ggtt); >> -    if (IS_ERR(tile->sriov.vf.ggtt_balloon[1])) { >> -        xe_ggtt_node_fini(tile->sriov.vf.ggtt_balloon[0]); >> -        return PTR_ERR(tile->sriov.vf.ggtt_balloon[1]); >> -    } >> - >> -    return 0; >> -} >> - >> -/** >> - * xe_gt_sriov_vf_balloon_ggtt_locked - Insert balloon nodes to limit >> used GGTT address range. >> - * @gt: the &xe_gt struct instance >> - * Return: 0 on success or a negative error code on failure. >> - */ >> -int xe_gt_sriov_vf_balloon_ggtt_locked(struct xe_gt *gt) >> -{ >> -    struct xe_gt_sriov_vf_selfconfig *config = >- >> >sriov.vf.self_config; >> -    struct xe_tile *tile = gt_to_tile(gt); >> -    struct xe_device *xe = gt_to_xe(gt); >> -    u64 start, end; >> -    int err; >> - >> -    xe_gt_assert(gt, IS_SRIOV_VF(xe)); >> -    xe_gt_assert(gt, !xe_gt_is_media_type(gt)); >> -    lockdep_assert_held(&tile->mem.ggtt->lock); >> - >> -    if (!config->ggtt_size) >> -        return -ENODATA; >> - >> -    /* >> -     * VF can only use part of the GGTT as allocated by the PF: >> -     * >> -     *      WOPCM                                  GUC_GGTT_TOP >> -     *      |<------------ Total GGTT size ------------------>| >> -     * >> -     *           VF GGTT base -->|<- size ->| >> -     * >> -     *      +--------------------+----------+-----------------+ >> -     *      |////////////////////|   block  |\\\\\\\\\\\\\\\\\| >> -     *      +--------------------+----------+-----------------+ >> -     * >> -     *      |<--- balloon[0] --->|<-- VF -->|<-- balloon[1] ->| >> -     */ >> - >> -    start = xe_wopcm_size(xe); >> -    end = config->ggtt_base; >> -    if (end != start) { >> -        err = xe_ggtt_node_insert_balloon_locked(tile- >> >sriov.vf.ggtt_balloon[0], >> -                             start, end); >> -        if (err) >> -            return err; >> -    } >> - >> -    start = config->ggtt_base + config->ggtt_size; >> -    end = GUC_GGTT_TOP; >> -    if (end != start) { >> -        err = xe_ggtt_node_insert_balloon_locked(tile- >> >sriov.vf.ggtt_balloon[1], >> -                             start, end); >> -        if (err) { >> -            xe_ggtt_node_remove_balloon_locked(tile- >> >sriov.vf.ggtt_balloon[0]); >> -            return err; >> -        } >> -    } >> - >> -    return 0; >> -} >> - >> -static int vf_balloon_ggtt(struct xe_gt *gt) >> -{ >> -    struct xe_ggtt *ggtt = gt_to_tile(gt)->mem.ggtt; >> -    int err; >> - >> -    mutex_lock(&ggtt->lock); >> -    err = xe_gt_sriov_vf_balloon_ggtt_locked(gt); >> -    mutex_unlock(&ggtt->lock); >> - >> -    return err; >> -} >> - >> -/** >> - * xe_gt_sriov_vf_deballoon_ggtt_locked - Remove balloon nodes. >> - * @gt: the &xe_gt struct instance >> - */ >> -void xe_gt_sriov_vf_deballoon_ggtt_locked(struct xe_gt *gt) >> -{ >> -    struct xe_tile *tile = gt_to_tile(gt); >> - >> -    xe_tile_assert(tile, IS_SRIOV_VF(tile_to_xe(tile))); >> -    xe_ggtt_node_remove_balloon_locked(tile->sriov.vf.ggtt_balloon[1]); >> -    xe_ggtt_node_remove_balloon_locked(tile->sriov.vf.ggtt_balloon[0]); >> -} >> - >> -static void vf_deballoon_ggtt(struct xe_gt *gt) >> -{ >> -    struct xe_tile *tile = gt_to_tile(gt); >> - >> -    mutex_lock(&tile->mem.ggtt->lock); >> -    xe_gt_sriov_vf_deballoon_ggtt_locked(gt); >> -    mutex_unlock(&tile->mem.ggtt->lock); >> -} >> - >> -static void vf_fini_ggtt_balloons(struct xe_gt *gt) >> -{ >> -    struct xe_tile *tile = gt_to_tile(gt); >> - >> -    xe_gt_assert(gt, IS_SRIOV_VF(gt_to_xe(gt))); >> -    xe_gt_assert(gt, !xe_gt_is_media_type(gt)); >> - >> -    xe_ggtt_node_fini(tile->sriov.vf.ggtt_balloon[1]); >> -    xe_ggtt_node_fini(tile->sriov.vf.ggtt_balloon[0]); >> -} >> - >> -static void cleanup_ggtt(struct drm_device *drm, void *arg) >> -{ >> -    struct xe_gt *gt = arg; >> - >> -    vf_deballoon_ggtt(gt); >> -    vf_fini_ggtt_balloons(gt); >> -} >> - >> -/** >> - * xe_gt_sriov_vf_prepare_ggtt - Prepare a VF's GGTT configuration. >> - * @gt: the &xe_gt >> - * >> - * This function is for VF use only. >> - * >> - * Return: 0 on success or a negative error code on failure. >> - */ >> -int xe_gt_sriov_vf_prepare_ggtt(struct xe_gt *gt) >> -{ >> -    struct xe_tile *tile = gt_to_tile(gt); >> -    struct xe_device *xe = tile_to_xe(tile); >> -    int err; >> - >> -    if (xe_gt_is_media_type(gt)) >> -        return 0; >> - >> -    err = vf_init_ggtt_balloons(gt); >> -    if (err) >> -        return err; >> - >> -    err = vf_balloon_ggtt(gt); >> -    if (err) { >> -        vf_fini_ggtt_balloons(gt); >> -        return err; >> -    } >> - >> -    return drmm_add_action_or_reset(&xe->drm, cleanup_ggtt, gt); >> -} >> - >>   static int relay_action_handshake(struct xe_gt *gt, u32 *major, u32 >> *minor) >>   { >>       u32 request[VF2PF_HANDSHAKE_REQUEST_MSG_LEN] = { >> @@ -870,89 +708,6 @@ int xe_gt_sriov_vf_connect(struct xe_gt *gt) >>       return err; >>   } >>   -/** >> - * DOC: GGTT nodes shifting during VF post-migration recovery >> - * >> - * The first fixup applied to the VF KMD structures as part of post- >> migration >> - * recovery is shifting nodes within &xe_ggtt instance. The nodes are >> moved >> - * from range previously assigned to this VF, into newly provisioned >> area. >> - * The changes include balloons, which are resized accordingly. >> - * >> - * The balloon nodes are there to eliminate unavailable ranges from >> use: one >> - * reserves the GGTT area below the range for current VF, and another >> one >> - * reserves area above. >> - * >> - * Below is a GGTT layout of example VF, with a certain address range >> assigned to >> - * said VF, and inaccessible areas above and below: >> - * >> - *  >> 0                                                                        4GiB >> - *  |<--------------------------- Total GGTT size >> ----------------------------->| >> - *      WOPCM                                                         >> GUC_TOP >> - *      |<-------------- Area mappable by xe_ggtt instance >> ---------------->| >> - * >> - *  +---+---------------------------------+---------- >> +----------------------+---+ >> - *  |\\\|/////////////////////////////////|  VF mem  >> |//////////////////////|\\\| >> - *  +---+---------------------------------+---------- >> +----------------------+---+ >> - * >> - * Hardware enforced access rules before migration: >> - * >> - *  |<------- inaccessible for VF ------->||<-- >> inaccessible for VF ->| >> - * >> - * GGTT nodes used for tracking allocations: >> - * >> - *      |<---------- balloon ------------>|<- nodes->|<----- balloon >> ------>| >> - * >> - * After the migration, GGTT area assigned to the VF might have >> shifted, either >> - * to lower or to higher address. But we expect the total size and >> extra areas to >> - * be identical, as migration can only happen between matching >> platforms. >> - * Below is an example of GGTT layout of the VF after migration. >> Content of the >> - * GGTT for VF has been moved to a new area, and we receive its >> address from GuC: >> - * >> - *  +---+----------------------+---------- >> +---------------------------------+---+ >> - *  |\\\|//////////////////////|  VF mem  >> |/////////////////////////////////|\\\| >> - *  +---+----------------------+---------- >> +---------------------------------+---+ >> - * >> - * Hardware enforced access rules after migration: >> - * >> - *  |<- inaccessible for VF -->||<------- inaccessible for >> VF ------->| >> - * >> - * So the VF has a new slice of GGTT assigned, and during migration >> process, the >> - * memory content was copied to that new area. But the &xe_ggtt nodes >> are still >> - * tracking allocations using the old addresses. The nodes within VF >> owned area >> - * have to be shifted, and balloon nodes need to be resized to >> properly mask out >> - * areas not owned by the VF. >> - * >> - * Fixed &xe_ggtt nodes used for tracking allocations: >> - * >> - *     |<------ balloon ------>|<- nodes->|<----------- balloon >> ----------->| >> - * >> - * Due to use of GPU profiles, we do not expect the old and new GGTT >> ares to >> - * overlap; but our node shifting will fix addresses properly >> regardless. >> - */ >> - >> -/** >> - * xe_gt_sriov_vf_fixup_ggtt_nodes - Shift GGTT allocations to match >> assigned range. >> - * @gt: the &xe_gt struct instance >> - * @shift: the shift value >> - * >> - * Since Global GTT is not virtualized, each VF has an assigned range >> - * within the global space. This range might have changed during >> migration, >> - * which requires all memory addresses pointing to GGTT to be shifted. >> - */ >> -void xe_gt_sriov_vf_fixup_ggtt_nodes(struct xe_gt *gt, s64 shift) >> -{ >> -    struct xe_tile *tile = gt_to_tile(gt); >> -    struct xe_ggtt *ggtt = tile->mem.ggtt; >> - >> -    xe_gt_assert(gt, !xe_gt_is_media_type(gt)); >> - >> -    mutex_lock(&ggtt->lock); >> -    xe_gt_sriov_vf_deballoon_ggtt_locked(gt); >> -    xe_ggtt_shift_nodes_locked(ggtt, shift); >> -    xe_gt_sriov_vf_balloon_ggtt_locked(gt); >> -    mutex_unlock(&ggtt->lock); >> -} >> - >>   /** >>    * xe_gt_sriov_vf_migrated_event_handler - Start a VF migration >> recovery, >>    *   or just mark that a GuC is ready for it. >> diff --git a/drivers/gpu/drm/xe/xe_gt_sriov_vf.h b/drivers/gpu/drm/xe/ >> xe_gt_sriov_vf.h >> index 2f96ac0c5dca..6250fe774d89 100644 >> --- a/drivers/gpu/drm/xe/xe_gt_sriov_vf.h >> +++ b/drivers/gpu/drm/xe/xe_gt_sriov_vf.h >> @@ -17,10 +17,6 @@ int xe_gt_sriov_vf_bootstrap(struct xe_gt *gt); >>   int xe_gt_sriov_vf_query_config(struct xe_gt *gt); >>   int xe_gt_sriov_vf_connect(struct xe_gt *gt); >>   int xe_gt_sriov_vf_query_runtime(struct xe_gt *gt); >> -int xe_gt_sriov_vf_prepare_ggtt(struct xe_gt *gt); >> -int xe_gt_sriov_vf_balloon_ggtt_locked(struct xe_gt *gt); >> -void xe_gt_sriov_vf_deballoon_ggtt_locked(struct xe_gt *gt); >> -void xe_gt_sriov_vf_fixup_ggtt_nodes(struct xe_gt *gt, s64 shift); >>   int xe_gt_sriov_vf_notify_resfix_done(struct xe_gt *gt); >>   void xe_gt_sriov_vf_migrated_event_handler(struct xe_gt *gt); >>   diff --git a/drivers/gpu/drm/xe/xe_sriov_vf.c b/drivers/gpu/drm/xe/ >> xe_sriov_vf.c >> index 46466932375c..6526fe450e55 100644 >> --- a/drivers/gpu/drm/xe/xe_sriov_vf.c >> +++ b/drivers/gpu/drm/xe/xe_sriov_vf.c >> @@ -15,6 +15,7 @@ >>   #include "xe_sriov.h" >>   #include "xe_sriov_printk.h" >>   #include "xe_sriov_vf.h" >> +#include "xe_tile_sriov_vf.h" >>     /** >>    * DOC: VF restore procedure in PF KMD and VF KMD >> @@ -211,7 +212,7 @@ static bool >> vf_post_migration_fixup_ggtt_nodes(struct xe_device *xe) >>           shift = xe_gt_sriov_vf_ggtt_shift(gt); >>           if (shift) { >>               need_fixups = true; >> -            xe_gt_sriov_vf_fixup_ggtt_nodes(gt, shift); >> +            xe_tile_sriov_vf_fixup_ggtt_nodes(tile, shift); >>           } >>       } >>       return need_fixups; >> diff --git a/drivers/gpu/drm/xe/xe_tile_sriov_vf.c b/drivers/gpu/drm/ >> xe/xe_tile_sriov_vf.c >> new file mode 100644 >> index 000000000000..88e832894432 >> --- /dev/null >> +++ b/drivers/gpu/drm/xe/xe_tile_sriov_vf.c >> @@ -0,0 +1,245 @@ >> +// SPDX-License-Identifier: MIT >> +/* >> + * Copyright © 2025 Intel Corporation >> + */ >> + >> +#include >> + >> +#include "regs/xe_gtt_defs.h" >> + >> +#include "xe_assert.h" >> +#include "xe_ggtt.h" >> +#include "xe_gt_sriov_vf.h" >> +#include "xe_sriov.h" >> +#include "xe_tile_sriov_vf.h" >> +#include "xe_wopcm.h" >> + >> +static int vf_init_ggtt_balloons(struct xe_tile *tile) >> +{ >> +    struct xe_ggtt *ggtt = tile->mem.ggtt; >> + >> +    xe_tile_assert(tile, IS_SRIOV_VF(tile_to_xe(tile))); >> + >> +    tile->sriov.vf.ggtt_balloon[0] = xe_ggtt_node_init(ggtt); >> +    if (IS_ERR(tile->sriov.vf.ggtt_balloon[0])) >> +        return PTR_ERR(tile->sriov.vf.ggtt_balloon[0]); >> + >> +    tile->sriov.vf.ggtt_balloon[1] = xe_ggtt_node_init(ggtt); >> +    if (IS_ERR(tile->sriov.vf.ggtt_balloon[1])) { >> +        xe_ggtt_node_fini(tile->sriov.vf.ggtt_balloon[0]); >> +        return PTR_ERR(tile->sriov.vf.ggtt_balloon[1]); >> +    } >> + >> +    return 0; >> +} >> + >> +/** >> + * xe_tile_sriov_vf_balloon_ggtt_locked - Insert balloon nodes to >> limit used GGTT address range. >> + * @tile: the &xe_tile struct instance >> + * >> + * Return: 0 on success or a negative error code on failure. >> + */ >> +int xe_tile_sriov_vf_balloon_ggtt_locked(struct xe_tile *tile) >> +{ >> +    u64 ggtt_base = xe_gt_sriov_vf_ggtt_base(tile->primary_gt); >> +    u64 ggtt_size = xe_gt_sriov_vf_ggtt(tile->primary_gt); >> +    struct xe_device *xe = tile_to_xe(tile); >> +    u64 start, end; >> +    int err; >> + >> +    xe_tile_assert(tile, IS_SRIOV_VF(xe)); >> +    xe_tile_assert(tile, ggtt_size); >> +    lockdep_assert_held(&tile->mem.ggtt->lock); >> + >> +    /* >> +     * VF can only use part of the GGTT as allocated by the PF: >> +     * >> +     *      WOPCM                                  GUC_GGTT_TOP >> +     *      |<------------ Total GGTT size ------------------>| >> +     * >> +     *           VF GGTT base -->|<- size ->| >> +     * >> +     *      +--------------------+----------+-----------------+ >> +     *      |////////////////////|   block  |\\\\\\\\\\\\\\\\\| >> +     *      +--------------------+----------+-----------------+ >> +     * >> +     *      |<--- balloon[0] --->|<-- VF -->|<-- balloon[1] ->| >> +     */ >> + >> +    start = xe_wopcm_size(xe); >> +    end = ggtt_base; >> +    if (end != start) { >> +        err = xe_ggtt_node_insert_balloon_locked(tile- >> >sriov.vf.ggtt_balloon[0], >> +                             start, end); >> +        if (err) >> +            return err; >> +    } >> + >> +    start = ggtt_base + ggtt_size; >> +    end = GUC_GGTT_TOP; >> +    if (end != start) { >> +        err = xe_ggtt_node_insert_balloon_locked(tile- >> >sriov.vf.ggtt_balloon[1], >> +                             start, end); >> +        if (err) { >> +            xe_ggtt_node_remove_balloon_locked(tile- >> >sriov.vf.ggtt_balloon[0]); >> +            return err; >> +        } >> +    } >> + >> +    return 0; >> +} >> + >> +static int vf_balloon_ggtt(struct xe_tile *tile) >> +{ >> +    struct xe_ggtt *ggtt = tile->mem.ggtt; >> +    int err; >> + >> +    mutex_lock(&ggtt->lock); >> +    err = xe_tile_sriov_vf_balloon_ggtt_locked(tile); >> +    mutex_unlock(&ggtt->lock); >> + >> +    return err; >> +} >> + >> +/** >> + * xe_tile_sriov_vf_deballoon_ggtt_locked - Remove balloon nodes. >> + * @tile: the &xe_tile struct instance >> + */ >> +void xe_tile_sriov_vf_deballoon_ggtt_locked(struct xe_tile *tile) >> +{ >> +    xe_tile_assert(tile, IS_SRIOV_VF(tile_to_xe(tile))); >> + >> +    xe_ggtt_node_remove_balloon_locked(tile->sriov.vf.ggtt_balloon[1]); >> +    xe_ggtt_node_remove_balloon_locked(tile->sriov.vf.ggtt_balloon[0]); >> +} >> + >> +static void vf_deballoon_ggtt(struct xe_tile *tile) >> +{ >> +    mutex_lock(&tile->mem.ggtt->lock); >> +    xe_tile_sriov_vf_deballoon_ggtt_locked(tile); >> +    mutex_unlock(&tile->mem.ggtt->lock); >> +} >> + >> +static void vf_fini_ggtt_balloons(struct xe_tile *tile) >> +{ >> +    xe_tile_assert(tile, IS_SRIOV_VF(tile_to_xe(tile))); >> + >> +    xe_ggtt_node_fini(tile->sriov.vf.ggtt_balloon[1]); >> +    xe_ggtt_node_fini(tile->sriov.vf.ggtt_balloon[0]); >> +} >> + >> +static void cleanup_ggtt(struct drm_device *drm, void *arg) >> +{ >> +    struct xe_tile *tile = arg; >> + >> +    vf_deballoon_ggtt(tile); >> +    vf_fini_ggtt_balloons(tile); >> +} >> + >> +/** >> + * xe_tile_sriov_vf_prepare_ggtt - Prepare a VF's GGTT configuration. >> + * @tile: the &xe_tile >> + * >> + * This function is for VF use only. >> + * >> + * Return: 0 on success or a negative error code on failure. >> + */ >> +int xe_tile_sriov_vf_prepare_ggtt(struct xe_tile *tile) >> +{ >> +    struct xe_device *xe = tile_to_xe(tile); >> +    int err; >> + >> +    err = vf_init_ggtt_balloons(tile); >> +    if (err) >> +        return err; >> + >> +    err = vf_balloon_ggtt(tile); >> +    if (err) { >> +        vf_fini_ggtt_balloons(tile); >> +        return err; >> +    } >> + >> +    return drmm_add_action_or_reset(&xe->drm, cleanup_ggtt, tile); >> +} >> + >> +/** >> + * DOC: GGTT nodes shifting during VF post-migration recovery >> + * >> + * The first fixup applied to the VF KMD structures as part of post- >> migration >> + * recovery is shifting nodes within &xe_ggtt instance. The nodes are >> moved >> + * from range previously assigned to this VF, into newly provisioned >> area. >> + * The changes include balloons, which are resized accordingly. >> + * >> + * The balloon nodes are there to eliminate unavailable ranges from >> use: one >> + * reserves the GGTT area below the range for current VF, and another >> one >> + * reserves area above. >> + * >> + * Below is a GGTT layout of example VF, with a certain address range >> assigned to >> + * said VF, and inaccessible areas above and below: >> + * >> + *  >> 0                                                                        4GiB >> + *  |<--------------------------- Total GGTT size >> ----------------------------->| >> + *      WOPCM                                                         >> GUC_TOP >> + *      |<-------------- Area mappable by xe_ggtt instance >> ---------------->| >> + * >> + *  +---+---------------------------------+---------- >> +----------------------+---+ >> + *  |\\\|/////////////////////////////////|  VF mem  >> |//////////////////////|\\\| >> + *  +---+---------------------------------+---------- >> +----------------------+---+ >> + * >> + * Hardware enforced access rules before migration: >> + * >> + *  |<------- inaccessible for VF ------->||<-- >> inaccessible for VF ->| >> + * >> + * GGTT nodes used for tracking allocations: >> + * >> + *      |<---------- balloon ------------>|<- nodes->|<----- balloon >> ------>| >> + * >> + * After the migration, GGTT area assigned to the VF might have >> shifted, either >> + * to lower or to higher address. But we expect the total size and >> extra areas to >> + * be identical, as migration can only happen between matching >> platforms. >> + * Below is an example of GGTT layout of the VF after migration. >> Content of the >> + * GGTT for VF has been moved to a new area, and we receive its >> address from GuC: >> + * >> + *  +---+----------------------+---------- >> +---------------------------------+---+ >> + *  |\\\|//////////////////////|  VF mem  >> |/////////////////////////////////|\\\| >> + *  +---+----------------------+---------- >> +---------------------------------+---+ >> + * >> + * Hardware enforced access rules after migration: >> + * >> + *  |<- inaccessible for VF -->||<------- inaccessible for >> VF ------->| >> + * >> + * So the VF has a new slice of GGTT assigned, and during migration >> process, the >> + * memory content was copied to that new area. But the &xe_ggtt nodes >> are still >> + * tracking allocations using the old addresses. The nodes within VF >> owned area >> + * have to be shifted, and balloon nodes need to be resized to >> properly mask out >> + * areas not owned by the VF. >> + * >> + * Fixed &xe_ggtt nodes used for tracking allocations: >> + * >> + *     |<------ balloon ------>|<- nodes->|<----------- balloon >> ----------->| >> + * >> + * Due to use of GPU profiles, we do not expect the old and new GGTT >> ares to >> + * overlap; but our node shifting will fix addresses properly >> regardless. >> + */ >> + >> +/** >> + * xe_tile_sriov_vf_fixup_ggtt_nodes - Shift GGTT allocations to >> match assigned range. >> + * @tile: the &xe_tile struct instance >> + * @shift: the shift value >> + * >> + * Since Global GTT is not virtualized, each VF has an assigned range >> + * within the global space. This range might have changed during >> migration, >> + * which requires all memory addresses pointing to GGTT to be shifted. >> + */ >> +void xe_tile_sriov_vf_fixup_ggtt_nodes(struct xe_tile *tile, s64 shift) >> +{ >> +    struct xe_ggtt *ggtt = tile->mem.ggtt; >> + >> +    mutex_lock(&ggtt->lock); >> + >> +    xe_tile_sriov_vf_deballoon_ggtt_locked(tile); >> +    xe_ggtt_shift_nodes_locked(ggtt, shift); >> +    xe_tile_sriov_vf_balloon_ggtt_locked(tile); >> + >> +    mutex_unlock(&ggtt->lock); >> +} >> diff --git a/drivers/gpu/drm/xe/xe_tile_sriov_vf.h b/drivers/gpu/drm/ >> xe/xe_tile_sriov_vf.h >> new file mode 100644 >> index 000000000000..93eb043171e8 >> --- /dev/null >> +++ b/drivers/gpu/drm/xe/xe_tile_sriov_vf.h >> @@ -0,0 +1,18 @@ >> +/* SPDX-License-Identifier: MIT */ >> +/* >> + * Copyright © 2025 Intel Corporation >> + */ >> + >> +#ifndef _XE_TILE_SRIOV_VF_H_ >> +#define _XE_TILE_SRIOV_VF_H_ >> + >> +#include >> + >> +struct xe_tile; >> + >> +int xe_tile_sriov_vf_prepare_ggtt(struct xe_tile *tile); >> +int xe_tile_sriov_vf_balloon_ggtt_locked(struct xe_tile *tile); >> +void xe_tile_sriov_vf_deballoon_ggtt_locked(struct xe_tile *tile); >> +void xe_tile_sriov_vf_fixup_ggtt_nodes(struct xe_tile *tile, s64 shift); >> + >> +#endif