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