xref: /linux/drivers/gpu/drm/xe/xe_lmtt_2l.c (revision 41c177cf354126a22443b5c80cec9fdd313e67e1)
1 // SPDX-License-Identifier: MIT
2 /*
3  * Copyright © 2023 Intel Corporation
4  */
5 
6 #include <linux/align.h>
7 #include <linux/bitfield.h>
8 #include <linux/log2.h>
9 #include <linux/sizes.h>
10 
11 #include "xe_lmtt_types.h"
12 #include "xe_macros.h"
13 
14 /**
15  * DOC: Two-Level LMTT Structure
16  *
17  * LMHAW (Local Memory Host Address Width) is 37 bit (128GB)
18  *
19  * LMGAW (Local Memory Guest Address Width) is 37 bit (128GB)
20  *
21  * The following figure illustrates the structure and function of the 2L LMTT::
22  *
23  *            LMTT Directory
24  *           (1 Entry per VF)
25  *            +-----------+                     LMTT (per VF)
26  *            |           |                     +-----------+
27  *            |           |                     |           |
28  *            |           |          index:     |           |
29  *            |           |          LMEM VF    +===========+
30  *            |           |          offset --> |    PTE    | ==> LMEM PF offset
31  *            |           |                     +===========+
32  *   index:   +===========+                     |           |
33  *   VFID --> |    PDE    |  -----------------> +-----------+
34  *            +===========+                    /              \.
35  *            |           |                   /                 \.
36  *            |           |                  /                    \.
37  *            |           |                 /                       \.
38  *            +-----------+ <== [LMTT Directory Ptr]                  \.
39  *           /             \              /                             \.
40  *          /               \         +-----------+-----------------+------+---+
41  *         /                 \        | 31:HAW-16 |        HAW-17:5 |  4:1 | 0 |
42  *        /                   \       +===========+=================+======+===+
43  *       /                     \      |  Reserved | LMEM Page (2MB) | Rsvd | V |
44  *      /                       \     +-----------+-----------------+------+---+
45  *     /                         \.
46  *   +-----------+-----------------+------+---+
47  *   | 31:HAW-12 |        HAW-13:4 |  3:1 | 0 |
48  *   +===========+=================+======+===+
49  *   |  Reserved | LMTT Ptr (64KB) | Rsvd | V |
50  *   +-----------+-----------------+------+---+
51  *
52  */
53 
54 typedef u32 lmtt_2l_pde_t;
55 typedef u32 lmtt_2l_pte_t;
56 
57 #if IS_ENABLED(CONFIG_DRM_XE_LMTT_2L_128GB)
58 #define LMTT_2L_HAW			37 /* 128 GiB */
59 #else
60 #define LMTT_2L_HAW			35 /* 32 GiB */
61 #endif
62 
63 #define LMTT_2L_PDE_MAX_NUM		64 /* SRIOV with PF and 63 VFs, index 0 (PF) is unused */
64 #define LMTT_2L_PDE_LMTT_PTR		GENMASK(LMTT_2L_HAW - 13, 4)
65 #define LMTT_2L_PDE_VALID		BIT(0)
66 
67 #define LMTT_2L_PTE_MAX_NUM		BIT(LMTT_2L_HAW - ilog2(SZ_2M))
68 #define LMTT_2L_PTE_LMEM_PAGE		GENMASK(LMTT_2L_HAW - 17, 5)
69 #define LMTT_2L_PTE_VALID		BIT(0)
70 
lmtt_2l_root_pd_level(void)71 static unsigned int lmtt_2l_root_pd_level(void)
72 {
73 	return 1; /* implementation is 0-based */
74 }
75 
lmtt_2l_pte_num(unsigned int level)76 static unsigned int lmtt_2l_pte_num(unsigned int level)
77 {
78 	switch (level) {
79 	case 1:
80 		return LMTT_2L_PDE_MAX_NUM;
81 	case 0:
82 		BUILD_BUG_ON(LMTT_2L_HAW == 37 && LMTT_2L_PTE_MAX_NUM != SZ_64K);
83 		BUILD_BUG_ON(LMTT_2L_HAW == 35 && LMTT_2L_PTE_MAX_NUM != SZ_16K);
84 		return LMTT_2L_PTE_MAX_NUM;
85 	default:
86 		return 0;
87 	}
88 }
89 
lmtt_2l_pte_size(unsigned int level)90 static unsigned int lmtt_2l_pte_size(unsigned int level)
91 {
92 	switch (level) {
93 	case 1:
94 		return sizeof(lmtt_2l_pde_t);
95 	case 0:
96 		return sizeof(lmtt_2l_pte_t);
97 	default:
98 		return 0;
99 	}
100 }
101 
lmtt_2l_pte_shift(unsigned int level)102 static unsigned int lmtt_2l_pte_shift(unsigned int level)
103 {
104 	switch (level) {
105 	case 0:
106 		return ilog2(SZ_2M);
107 	default:
108 		return 0;
109 	}
110 }
111 
lmtt_2l_pte_index(u64 addr,unsigned int level)112 static unsigned int lmtt_2l_pte_index(u64 addr, unsigned int level)
113 {
114 	addr >>= lmtt_2l_pte_shift(level);
115 
116 	switch (level) {
117 	case 0:
118 		/* SZ_2M increments */
119 		BUILD_BUG_ON_NOT_POWER_OF_2(LMTT_2L_PTE_MAX_NUM);
120 		return addr & (LMTT_2L_PTE_MAX_NUM - 1);
121 	default:
122 		return 0;
123 	}
124 }
125 
lmtt_2l_pte_encode(unsigned long offset,unsigned int level)126 static u64 lmtt_2l_pte_encode(unsigned long offset, unsigned int level)
127 {
128 	switch (level) {
129 	case 0:
130 		XE_WARN_ON(!IS_ALIGNED(offset, SZ_2M));
131 		XE_WARN_ON(!FIELD_FIT(LMTT_2L_PTE_LMEM_PAGE, offset / SZ_2M));
132 		return FIELD_PREP(LMTT_2L_PTE_LMEM_PAGE, offset / SZ_2M) | LMTT_2L_PTE_VALID;
133 	case 1:
134 		XE_WARN_ON(!IS_ALIGNED(offset, SZ_64K));
135 		XE_WARN_ON(!FIELD_FIT(LMTT_2L_PDE_LMTT_PTR, offset / SZ_64K));
136 		return FIELD_PREP(LMTT_2L_PDE_LMTT_PTR, offset / SZ_64K) | LMTT_2L_PDE_VALID;
137 	default:
138 		XE_WARN_ON(true);
139 		return 0;
140 	}
141 }
142 
143 const struct xe_lmtt_ops lmtt_2l_ops = {
144 	.lmtt_root_pd_level = lmtt_2l_root_pd_level,
145 	.lmtt_pte_num = lmtt_2l_pte_num,
146 	.lmtt_pte_size = lmtt_2l_pte_size,
147 	.lmtt_pte_shift = lmtt_2l_pte_shift,
148 	.lmtt_pte_index = lmtt_2l_pte_index,
149 	.lmtt_pte_encode = lmtt_2l_pte_encode,
150 };
151