Commit b1d20405 authored by Michal Wajdeczko's avatar Michal Wajdeczko Committed by Rodrigo Vivi

drm/xe/pf: Introduce Local Memory Translation Table

The Local Memory Translation Table (LMTT) provides additional
abstraction for Virtual Functions (VF) accessing device VRAM.

This code is based on prior work of Michal Winiarski.

In this patch we focus only on LMTT initialization. Remaining LMTT
functions will be used once we add a VF provisioning to the PF.

Bspec: 44117, 52404, 59314
Reviewed-by: default avatarMichał Winiarski <michal.winiarski@intel.com>
Link: https://lore.kernel.org/r/20231128151507.1015-4-michal.wajdeczko@intel.comSigned-off-by: default avatarMichal Wajdeczko <michal.wajdeczko@intel.com>
Signed-off-by: default avatarRodrigo Vivi <rodrigo.vivi@intel.com>
parent 5bcedc9e
......@@ -137,6 +137,11 @@ xe-$(CONFIG_HWMON) += xe_hwmon.o
# graphics virtualization (SR-IOV) support
xe-y += xe_sriov.o
xe-$(CONFIG_PCI_IOV) += \
xe_lmtt.o \
xe_lmtt_2l.o \
xe_lmtt_ml.o
# i915 Display compat #defines and #includes
subdir-ccflags-$(CONFIG_DRM_XE_DISPLAY) += \
-I$(srctree)/$(src)/display/ext \
......
/* SPDX-License-Identifier: MIT */
/*
* Copyright © 2023 Intel Corporation
*/
#ifndef _REGS_XE_SRIOV_REGS_H_
#define _REGS_XE_SRIOV_REGS_H_
#include "regs/xe_reg_defs.h"
#define XE2_LMEM_CFG XE_REG(0x48b0)
#define LMEM_CFG XE_REG(0xcf58)
#define LMEM_EN REG_BIT(31)
#define LMTT_DIR_PTR REG_GENMASK(30, 0) /* in multiples of 64KB */
#endif
......@@ -15,6 +15,7 @@
#include "xe_devcoredump_types.h"
#include "xe_heci_gsc.h"
#include "xe_gt_types.h"
#include "xe_lmtt_types.h"
#include "xe_platform_types.h"
#include "xe_pt_types.h"
#include "xe_pmu.h"
......@@ -186,6 +187,14 @@ struct xe_tile {
struct xe_sa_manager *kernel_bb_pool;
} mem;
/** @sriov: tile level virtualization data */
union {
struct {
/** @sriov.pf.lmtt: Local Memory Translation Table. */
struct xe_lmtt lmtt;
} pf;
} sriov;
/** @migrate: Migration helper for vram blits and clearing */
struct xe_migrate *migrate;
......
......@@ -36,6 +36,7 @@
#include "xe_hw_fence.h"
#include "xe_hw_engine_class_sysfs.h"
#include "xe_irq.h"
#include "xe_lmtt.h"
#include "xe_lrc.h"
#include "xe_map.h"
#include "xe_migrate.h"
......@@ -46,6 +47,7 @@
#include "xe_ring_ops.h"
#include "xe_sa.h"
#include "xe_sched_job.h"
#include "xe_sriov.h"
#include "xe_tuning.h"
#include "xe_uc.h"
#include "xe_vm.h"
......@@ -344,6 +346,8 @@ static int gt_fw_domain_init(struct xe_gt *gt)
err = xe_ggtt_init(gt_to_tile(gt)->mem.ggtt);
if (err)
goto err_force_wake;
if (IS_SRIOV_PF(gt_to_xe(gt)))
xe_lmtt_init(&gt_to_tile(gt)->sriov.pf.lmtt);
}
err = xe_uc_init(&gt->uc);
......@@ -460,6 +464,9 @@ static int all_fw_domain_init(struct xe_gt *gt)
xe_gt_apply_ccs_mode(gt);
}
if (IS_SRIOV_PF(gt_to_xe(gt)) && !xe_gt_is_media_type(gt))
xe_lmtt_init_hw(&gt_to_tile(gt)->sriov.pf.lmtt);
err = xe_force_wake_put(gt_to_fw(gt), XE_FORCEWAKE_ALL);
XE_WARN_ON(err);
xe_device_mem_access_put(gt_to_xe(gt));
......@@ -560,6 +567,9 @@ static int do_gt_restart(struct xe_gt *gt)
if (err)
return err;
if (IS_SRIOV_PF(gt_to_xe(gt)) && !xe_gt_is_media_type(gt))
xe_lmtt_init_hw(&gt_to_tile(gt)->sriov.pf.lmtt);
xe_mocs_init(gt);
err = xe_uc_start(&gt->uc);
if (err)
......
This diff is collapsed.
/* SPDX-License-Identifier: MIT */
/*
* Copyright © 2023 Intel Corporation
*/
#ifndef _XE_LMTT_H_
#define _XE_LMTT_H_
#include <linux/types.h>
struct xe_bo;
struct xe_lmtt;
struct xe_lmtt_ops;
#ifdef CONFIG_PCI_IOV
int xe_lmtt_init(struct xe_lmtt *lmtt);
void xe_lmtt_init_hw(struct xe_lmtt *lmtt);
int xe_lmtt_prepare_pages(struct xe_lmtt *lmtt, unsigned int vfid, u64 range);
int xe_lmtt_populate_pages(struct xe_lmtt *lmtt, unsigned int vfid, struct xe_bo *bo, u64 offset);
void xe_lmtt_drop_pages(struct xe_lmtt *lmtt, unsigned int vfid);
u64 xe_lmtt_estimate_pt_size(struct xe_lmtt *lmtt, u64 size);
#else
static inline int xe_lmtt_init(struct xe_lmtt *lmtt) { return 0; }
static inline void xe_lmtt_init_hw(struct xe_lmtt *lmtt) { }
#endif
#endif
// SPDX-License-Identifier: MIT
/*
* Copyright © 2023 Intel Corporation
*/
#include <linux/align.h>
#include <linux/bitfield.h>
#include <linux/log2.h>
#include <linux/sizes.h>
#include "xe_lmtt_types.h"
#include "xe_macros.h"
/**
* DOC: Two-Level LMTT Structure
*
* LMHAW (Local Memory Host Address Width) is 37 bit (128GB)
*
* LMGAW (Local Memory Guest Address Width) is 37 bit (128GB)
*
* The following figure illustrates the structure and function of the 2L LMTT::
*
* LMTT Directory
* (1 Entry per VF)
* +-----------+ LMTT (per VF)
* | | +-----------+
* | | | |
* | | index: | |
* | | LMEM VF +===========+
* | | offset --> | PTE | ==> LMEM PF offset
* | | +===========+
* index: +===========+ | |
* VFID --> | PDE | -----------------> +-----------+
* +===========+ / \.
* | | / \.
* | | / \.
* | | / \.
* +-----------+ <== [LMTT Directory Ptr] \.
* / \ / \.
* / \ +-----------+-----------------+------+---+
* / \ | 31:HAW-16 | HAW-17:5 | 4:1 | 0 |
* / \ +===========+=================+======+===+
* / \ | Reserved | LMEM Page (2MB) | Rsvd | V |
* / \ +-----------+-----------------+------+---+
* / \.
* +-----------+-----------------+------+---+
* | 31:HAW-12 | HAW-13:4 | 3:1 | 0 |
* +===========+=================+======+===+
* | Reserved | LMTT Ptr (64KB) | Rsvd | V |
* +-----------+-----------------+------+---+
*
*/
typedef u32 lmtt_2l_pde_t;
typedef u32 lmtt_2l_pte_t;
#if IS_ENABLED(CONFIG_DRM_XE_LMTT_2L_128GB)
#define LMTT_2L_HAW 37 /* 128 GiB */
#else
#define LMTT_2L_HAW 35 /* 32 GiB */
#endif
#define LMTT_2L_PDE_MAX_NUM 64 /* SRIOV with PF and 63 VFs, index 0 (PF) is unused */
#define LMTT_2L_PDE_LMTT_PTR GENMASK(LMTT_2L_HAW - 13, 4)
#define LMTT_2L_PDE_VALID BIT(0)
#define LMTT_2L_PTE_MAX_NUM BIT(LMTT_2L_HAW - ilog2(SZ_2M))
#define LMTT_2L_PTE_LMEM_PAGE GENMASK(LMTT_2L_HAW - 17, 5)
#define LMTT_2L_PTE_VALID BIT(0)
static unsigned int lmtt_2l_root_pd_level(void)
{
return 1; /* implementation is 0-based */
}
static unsigned int lmtt_2l_pte_num(unsigned int level)
{
switch (level) {
case 1:
return LMTT_2L_PDE_MAX_NUM;
case 0:
BUILD_BUG_ON(LMTT_2L_HAW == 37 && LMTT_2L_PTE_MAX_NUM != SZ_64K);
BUILD_BUG_ON(LMTT_2L_HAW == 35 && LMTT_2L_PTE_MAX_NUM != SZ_16K);
return LMTT_2L_PTE_MAX_NUM;
default:
return 0;
}
}
static unsigned int lmtt_2l_pte_size(unsigned int level)
{
switch (level) {
case 1:
return sizeof(lmtt_2l_pde_t);
case 0:
return sizeof(lmtt_2l_pte_t);
default:
return 0;
}
}
static unsigned int lmtt_2l_pte_shift(unsigned int level)
{
switch (level) {
case 0:
return ilog2(SZ_2M);
default:
return 0;
}
}
static unsigned int lmtt_2l_pte_index(u64 addr, unsigned int level)
{
addr >>= lmtt_2l_pte_shift(level);
switch (level) {
case 0:
/* SZ_2M increments */
BUILD_BUG_ON_NOT_POWER_OF_2(LMTT_2L_PTE_MAX_NUM);
return addr & (LMTT_2L_PTE_MAX_NUM - 1);
default:
return 0;
}
}
static u64 lmtt_2l_pte_encode(unsigned long offset, unsigned int level)
{
switch (level) {
case 0:
XE_WARN_ON(!IS_ALIGNED(offset, SZ_2M));
XE_WARN_ON(!FIELD_FIT(LMTT_2L_PTE_LMEM_PAGE, offset / SZ_2M));
return FIELD_PREP(LMTT_2L_PTE_LMEM_PAGE, offset / SZ_2M) | LMTT_2L_PTE_VALID;
case 1:
XE_WARN_ON(!IS_ALIGNED(offset, SZ_64K));
XE_WARN_ON(!FIELD_FIT(LMTT_2L_PDE_LMTT_PTR, offset / SZ_64K));
return FIELD_PREP(LMTT_2L_PDE_LMTT_PTR, offset / SZ_64K) | LMTT_2L_PDE_VALID;
default:
XE_WARN_ON(true);
return 0;
}
}
const struct xe_lmtt_ops lmtt_2l_ops = {
.lmtt_root_pd_level = lmtt_2l_root_pd_level,
.lmtt_pte_num = lmtt_2l_pte_num,
.lmtt_pte_size = lmtt_2l_pte_size,
.lmtt_pte_shift = lmtt_2l_pte_shift,
.lmtt_pte_index = lmtt_2l_pte_index,
.lmtt_pte_encode = lmtt_2l_pte_encode,
};
// SPDX-License-Identifier: MIT
/*
* Copyright © 2023 Intel Corporation
*/
#include <linux/align.h>
#include <linux/bitfield.h>
#include <linux/log2.h>
#include <linux/sizes.h>
#include "xe_lmtt_types.h"
#include "xe_macros.h"
/**
* DOC: Multi-Level LMTT Structure
*
* LMHAW (Local Memory Host Address Width) is 48 bit (256TB)
*
* LMGAW (Local Memory Guest Address Width) is 48 bit (256TB)
*
* The following figure illustrates the structure and function of the ML LMTT::
*
* LMTT L3 Directory
* (1 Entry per VF) LMTT L1 Leaf
* +-----------+ +-----------+
* | | LMTT L2 (per VF) | |
* | | +-----------+ | |
* | | | | index: +===========+
* | | | | GDPA --> | PTE | => LMEM PF offset
* | | | | 34:21 +===========+
* | | index: | | | |
* | | LMEM VF +===========+ | |
* | | offset -> | PTE | ----------> +-----------+
* | | GAW-1:35 +===========+ / \.
* index: +===========+ | | / \.
* VFID --> | PDE | ---------> +-----------+ / \.
* +===========+ / / / \.
* | | / / / \.
* +-----------+ <== [LMTT Directory Ptr] / \.
* / \ / / / \.
* / \ / / +-----------+-----------------+------+---+
* / /\ / | 31:HAW-16 | HAW-17:5 | 4:1 | 0 |
* / / \ / +===========+=================+======+===+
* / / \ / | Reserved | LMEM Page (2MB) | Rsvd | V |
* / / +-----------+-----------------+------+---+
* / /
* +-----------+-----------------+------+---+
* | 63:HAW-12 | HAW-13:4 | 3:1 | 0 |
* +===========+=================+======+===+
* | Reserved | LMTT Ptr (64KB) | Rsvd | V |
* +-----------+-----------------+------+---+
*
*/
typedef u64 lmtt_ml_pde_t;
typedef u32 lmtt_ml_pte_t;
#define LMTT_ML_HAW 48 /* 256 TiB */
#define LMTT_ML_PDE_MAX_NUM 64 /* SRIOV with PF and 63 VFs, index 0 (PF) is unused */
#define LMTT_ML_PDE_LMTT_PTR GENMASK_ULL(LMTT_ML_HAW - 13, 4)
#define LMTT_ML_PDE_VALID BIT(0)
#define LMTT_ML_PDE_L2_SHIFT 35
#define LMTT_ML_PDE_L2_MAX_NUM BIT_ULL(LMTT_ML_HAW - 35)
#define LMTT_ML_PTE_MAX_NUM BIT(35 - ilog2(SZ_2M))
#define LMTT_ML_PTE_LMEM_PAGE GENMASK(LMTT_ML_HAW - 17, 5)
#define LMTT_ML_PTE_VALID BIT(0)
static unsigned int lmtt_ml_root_pd_level(void)
{
return 2; /* implementation is 0-based */
}
static unsigned int lmtt_ml_pte_num(unsigned int level)
{
switch (level) {
case 2:
return LMTT_ML_PDE_MAX_NUM;
case 1:
BUILD_BUG_ON(LMTT_ML_HAW == 48 && LMTT_ML_PDE_L2_MAX_NUM != SZ_8K);
return LMTT_ML_PDE_L2_MAX_NUM;
case 0:
BUILD_BUG_ON(LMTT_ML_PTE_MAX_NUM != SZ_16K);
return LMTT_ML_PTE_MAX_NUM;
default:
return 0;
}
}
static unsigned int lmtt_ml_pte_size(unsigned int level)
{
switch (level) {
case 2:
case 1:
return sizeof(lmtt_ml_pde_t);
case 0:
return sizeof(lmtt_ml_pte_t);
default:
return 0;
}
}
static unsigned int lmtt_ml_pte_shift(unsigned int level)
{
switch (level) {
case 1:
BUILD_BUG_ON(BIT_ULL(LMTT_ML_PDE_L2_SHIFT) != SZ_32G);
return ilog2(SZ_32G);
case 0:
return ilog2(SZ_2M);
default:
return 0;
}
}
static unsigned int lmtt_ml_pte_index(u64 addr, unsigned int level)
{
addr >>= lmtt_ml_pte_shift(level);
switch (level) {
case 1:
/* SZ_32G increments */
BUILD_BUG_ON_NOT_POWER_OF_2(LMTT_ML_PDE_L2_MAX_NUM);
return addr & (LMTT_ML_PDE_L2_MAX_NUM - 1);
case 0:
/* SZ_2M increments */
BUILD_BUG_ON_NOT_POWER_OF_2(LMTT_ML_PTE_MAX_NUM);
return addr & (LMTT_ML_PTE_MAX_NUM - 1);
default:
return 0;
}
}
static u64 lmtt_ml_pte_encode(unsigned long offset, unsigned int level)
{
switch (level) {
case 0:
XE_WARN_ON(!IS_ALIGNED(offset, SZ_2M));
XE_WARN_ON(!FIELD_FIT(LMTT_ML_PTE_LMEM_PAGE, offset / SZ_2M));
return FIELD_PREP(LMTT_ML_PTE_LMEM_PAGE, offset / SZ_2M) | LMTT_ML_PTE_VALID;
case 1:
case 2:
XE_WARN_ON(!IS_ALIGNED(offset, SZ_64K));
XE_WARN_ON(!FIELD_FIT(LMTT_ML_PDE_LMTT_PTR, offset / SZ_64K));
return FIELD_PREP(LMTT_ML_PDE_LMTT_PTR, offset / SZ_64K) | LMTT_ML_PDE_VALID;
default:
XE_WARN_ON(true);
return 0;
}
}
const struct xe_lmtt_ops lmtt_ml_ops = {
.lmtt_root_pd_level = lmtt_ml_root_pd_level,
.lmtt_pte_num = lmtt_ml_pte_num,
.lmtt_pte_size = lmtt_ml_pte_size,
.lmtt_pte_shift = lmtt_ml_pte_shift,
.lmtt_pte_index = lmtt_ml_pte_index,
.lmtt_pte_encode = lmtt_ml_pte_encode,
};
/* SPDX-License-Identifier: MIT */
/*
* Copyright © 2023 Intel Corporation
*/
#ifndef _XE_LMTT_TYPES_H_
#define _XE_LMTT_TYPES_H_
#include <linux/types.h>
struct xe_bo;
struct xe_lmtt;
struct xe_lmtt_pt;
struct xe_lmtt_ops;
#define LMTT_PTE_INVALID ULL(0)
/**
* struct xe_lmtt - Local Memory Translation Table Manager
*/
struct xe_lmtt {
/** @pd: root LMTT Directory */
struct xe_lmtt_pt *pd;
/** @ops: LMTT functions */
const struct xe_lmtt_ops *ops;
};
/**
* struct xe_lmtt_pt - Local Memory Translation Table Page Table
*
* Represents single level of the LMTT.
*/
struct xe_lmtt_pt {
/** @level: page table level, 0 is leaf */
unsigned int level;
/** @bo: buffer object with actual LMTT PTE values */
struct xe_bo *bo;
/** @entries: leaf page tables, exist only for root/non-leaf */
struct xe_lmtt_pt *entries[];
};
/**
* struct xe_lmtt_ops - Local Memory Translation Table Operations
*
* Provides abstraction of the LMTT variants.
*/
struct xe_lmtt_ops {
/* private: */
unsigned int (*lmtt_root_pd_level)(void);
unsigned int (*lmtt_pte_num)(unsigned int level);
unsigned int (*lmtt_pte_size)(unsigned int level);
unsigned int (*lmtt_pte_shift)(unsigned int level);
unsigned int (*lmtt_pte_index)(u64 addr, unsigned int level);
u64 (*lmtt_pte_encode)(unsigned long offset, unsigned int level);
};
extern const struct xe_lmtt_ops lmtt_2l_ops;
extern const struct xe_lmtt_ops lmtt_ml_ops;
#endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment