xref: /openbmc/qemu/include/hw/cxl/cxl_component.h (revision 29b62a10)
1 /*
2  * QEMU CXL Component
3  *
4  * Copyright (c) 2020 Intel
5  *
6  * This work is licensed under the terms of the GNU GPL, version 2. See the
7  * COPYING file in the top-level directory.
8  */
9 
10 #ifndef CXL_COMPONENT_H
11 #define CXL_COMPONENT_H
12 
13 /* CXL 2.0 - 8.2.4 */
14 #define CXL2_COMPONENT_IO_REGION_SIZE 0x1000
15 #define CXL2_COMPONENT_CM_REGION_SIZE 0x1000
16 #define CXL2_COMPONENT_BLOCK_SIZE 0x10000
17 
18 #include "qemu/compiler.h"
19 #include "qemu/range.h"
20 #include "qemu/typedefs.h"
21 #include "hw/cxl/cxl_cdat.h"
22 #include "hw/register.h"
23 #include "qapi/error.h"
24 
25 enum reg_type {
26     CXL2_DEVICE,
27     CXL2_TYPE3_DEVICE,
28     CXL2_LOGICAL_DEVICE,
29     CXL2_ROOT_PORT,
30     CXL2_UPSTREAM_PORT,
31     CXL2_DOWNSTREAM_PORT
32 };
33 
34 /*
35  * Capability registers are defined at the top of the CXL.cache/mem region and
36  * are packed. For our purposes we will always define the caps in the same
37  * order.
38  * CXL 2.0 - 8.2.5 Table 142 for details.
39  */
40 
41 /* CXL 2.0 - 8.2.5.1 */
42 REG32(CXL_CAPABILITY_HEADER, 0)
43     FIELD(CXL_CAPABILITY_HEADER, ID, 0, 16)
44     FIELD(CXL_CAPABILITY_HEADER, VERSION, 16, 4)
45     FIELD(CXL_CAPABILITY_HEADER, CACHE_MEM_VERSION, 20, 4)
46     FIELD(CXL_CAPABILITY_HEADER, ARRAY_SIZE, 24, 8)
47 
48 #define CXLx_CAPABILITY_HEADER(type, offset)                  \
49     REG32(CXL_##type##_CAPABILITY_HEADER, offset)             \
50         FIELD(CXL_##type##_CAPABILITY_HEADER, ID, 0, 16)      \
51         FIELD(CXL_##type##_CAPABILITY_HEADER, VERSION, 16, 4) \
52         FIELD(CXL_##type##_CAPABILITY_HEADER, PTR, 20, 12)
53 CXLx_CAPABILITY_HEADER(RAS, 0x4)
54 CXLx_CAPABILITY_HEADER(LINK, 0x8)
55 CXLx_CAPABILITY_HEADER(HDM, 0xc)
56 CXLx_CAPABILITY_HEADER(EXTSEC, 0x10)
57 CXLx_CAPABILITY_HEADER(SNOOP, 0x14)
58 
59 /*
60  * Capability structures contain the actual registers that the CXL component
61  * implements. Some of these are specific to certain types of components, but
62  * this implementation leaves enough space regardless.
63  */
64 /* 8.2.5.9 - CXL RAS Capability Structure */
65 
66 /* Give ample space for caps before this */
67 #define CXL_RAS_REGISTERS_OFFSET 0x80
68 #define CXL_RAS_REGISTERS_SIZE   0x58
69 REG32(CXL_RAS_UNC_ERR_STATUS, CXL_RAS_REGISTERS_OFFSET)
70 REG32(CXL_RAS_UNC_ERR_MASK, CXL_RAS_REGISTERS_OFFSET + 0x4)
71 REG32(CXL_RAS_UNC_ERR_SEVERITY, CXL_RAS_REGISTERS_OFFSET + 0x8)
72 REG32(CXL_RAS_COR_ERR_STATUS, CXL_RAS_REGISTERS_OFFSET + 0xc)
73 REG32(CXL_RAS_COR_ERR_MASK, CXL_RAS_REGISTERS_OFFSET + 0x10)
74 REG32(CXL_RAS_ERR_CAP_CTRL, CXL_RAS_REGISTERS_OFFSET + 0x14)
75 /* Offset 0x18 - 0x58 reserved for RAS logs */
76 
77 /* 8.2.5.10 - CXL Security Capability Structure */
78 #define CXL_SEC_REGISTERS_OFFSET \
79     (CXL_RAS_REGISTERS_OFFSET + CXL_RAS_REGISTERS_SIZE)
80 #define CXL_SEC_REGISTERS_SIZE   0 /* We don't implement 1.1 downstream ports */
81 
82 /* 8.2.5.11 - CXL Link Capability Structure */
83 #define CXL_LINK_REGISTERS_OFFSET \
84     (CXL_SEC_REGISTERS_OFFSET + CXL_SEC_REGISTERS_SIZE)
85 #define CXL_LINK_REGISTERS_SIZE   0x38
86 
87 /* 8.2.5.12 - CXL HDM Decoder Capability Structure */
88 #define HDM_DECODE_MAX 10 /* 8.2.5.12.1 */
89 #define CXL_HDM_REGISTERS_OFFSET \
90     (CXL_LINK_REGISTERS_OFFSET + CXL_LINK_REGISTERS_SIZE)
91 #define CXL_HDM_REGISTERS_SIZE (0x10 + 0x20 * HDM_DECODE_MAX)
92 #define HDM_DECODER_INIT(n)                                                    \
93   REG32(CXL_HDM_DECODER##n##_BASE_LO,                                          \
94         CXL_HDM_REGISTERS_OFFSET + (0x20 * n) + 0x10)                          \
95             FIELD(CXL_HDM_DECODER##n##_BASE_LO, L, 28, 4)                      \
96   REG32(CXL_HDM_DECODER##n##_BASE_HI,                                          \
97         CXL_HDM_REGISTERS_OFFSET + (0x20 * n) + 0x14)                          \
98   REG32(CXL_HDM_DECODER##n##_SIZE_LO,                                          \
99         CXL_HDM_REGISTERS_OFFSET + (0x20 * n) + 0x18)                          \
100   REG32(CXL_HDM_DECODER##n##_SIZE_HI,                                          \
101         CXL_HDM_REGISTERS_OFFSET + (0x20 * n) + 0x1C)                          \
102   REG32(CXL_HDM_DECODER##n##_CTRL,                                             \
103         CXL_HDM_REGISTERS_OFFSET + (0x20 * n) + 0x20)                          \
104             FIELD(CXL_HDM_DECODER##n##_CTRL, IG, 0, 4)                         \
105             FIELD(CXL_HDM_DECODER##n##_CTRL, IW, 4, 4)                         \
106             FIELD(CXL_HDM_DECODER##n##_CTRL, LOCK_ON_COMMIT, 8, 1)             \
107             FIELD(CXL_HDM_DECODER##n##_CTRL, COMMIT, 9, 1)                     \
108             FIELD(CXL_HDM_DECODER##n##_CTRL, COMMITTED, 10, 1)                 \
109             FIELD(CXL_HDM_DECODER##n##_CTRL, ERR, 11, 1)                       \
110             FIELD(CXL_HDM_DECODER##n##_CTRL, TYPE, 12, 1)                      \
111   REG32(CXL_HDM_DECODER##n##_TARGET_LIST_LO,                                   \
112         CXL_HDM_REGISTERS_OFFSET + (0x20 * n) + 0x24)                          \
113   REG32(CXL_HDM_DECODER##n##_TARGET_LIST_HI,                                   \
114         CXL_HDM_REGISTERS_OFFSET + (0x20 * n) + 0x28)
115 
116 REG32(CXL_HDM_DECODER_CAPABILITY, CXL_HDM_REGISTERS_OFFSET)
117     FIELD(CXL_HDM_DECODER_CAPABILITY, DECODER_COUNT, 0, 4)
118     FIELD(CXL_HDM_DECODER_CAPABILITY, TARGET_COUNT, 4, 4)
119     FIELD(CXL_HDM_DECODER_CAPABILITY, INTERLEAVE_256B, 8, 1)
120     FIELD(CXL_HDM_DECODER_CAPABILITY, INTERLEAVE_4K, 9, 1)
121     FIELD(CXL_HDM_DECODER_CAPABILITY, POISON_ON_ERR_CAP, 10, 1)
122 REG32(CXL_HDM_DECODER_GLOBAL_CONTROL, CXL_HDM_REGISTERS_OFFSET + 4)
123     FIELD(CXL_HDM_DECODER_GLOBAL_CONTROL, POISON_ON_ERR_EN, 0, 1)
124     FIELD(CXL_HDM_DECODER_GLOBAL_CONTROL, HDM_DECODER_ENABLE, 1, 1)
125 
126 HDM_DECODER_INIT(0);
127 
128 /* 8.2.5.13 - CXL Extended Security Capability Structure (Root complex only) */
129 #define EXTSEC_ENTRY_MAX        256
130 #define CXL_EXTSEC_REGISTERS_OFFSET \
131     (CXL_HDM_REGISTERS_OFFSET + CXL_HDM_REGISTERS_SIZE)
132 #define CXL_EXTSEC_REGISTERS_SIZE   (8 * EXTSEC_ENTRY_MAX + 4)
133 
134 /* 8.2.5.14 - CXL IDE Capability Structure */
135 #define CXL_IDE_REGISTERS_OFFSET \
136     (CXL_EXTSEC_REGISTERS_OFFSET + CXL_EXTSEC_REGISTERS_SIZE)
137 #define CXL_IDE_REGISTERS_SIZE   0x20
138 
139 /* 8.2.5.15 - CXL Snoop Filter Capability Structure */
140 #define CXL_SNOOP_REGISTERS_OFFSET \
141     (CXL_IDE_REGISTERS_OFFSET + CXL_IDE_REGISTERS_SIZE)
142 #define CXL_SNOOP_REGISTERS_SIZE   0x8
143 
144 QEMU_BUILD_BUG_MSG((CXL_SNOOP_REGISTERS_OFFSET + CXL_SNOOP_REGISTERS_SIZE) >= 0x1000,
145                    "No space for registers");
146 
147 typedef struct component_registers {
148     /*
149      * Main memory region to be registered with QEMU core.
150      */
151     MemoryRegion component_registers;
152 
153     /*
154      * 8.2.4 Table 141:
155      *   0x0000 - 0x0fff CXL.io registers
156      *   0x1000 - 0x1fff CXL.cache and CXL.mem
157      *   0x2000 - 0xdfff Implementation specific
158      *   0xe000 - 0xe3ff CXL ARB/MUX registers
159      *   0xe400 - 0xffff RSVD
160      */
161     uint32_t io_registers[CXL2_COMPONENT_IO_REGION_SIZE >> 2];
162     MemoryRegion io;
163 
164     uint32_t cache_mem_registers[CXL2_COMPONENT_CM_REGION_SIZE >> 2];
165     uint32_t cache_mem_regs_write_mask[CXL2_COMPONENT_CM_REGION_SIZE >> 2];
166     MemoryRegion cache_mem;
167 
168     MemoryRegion impl_specific;
169     MemoryRegion arb_mux;
170     MemoryRegion rsvd;
171 
172     /* special_ops is used for any component that needs any specific handling */
173     MemoryRegionOps *special_ops;
174 } ComponentRegisters;
175 
176 /*
177  * A CXL component represents all entities in a CXL hierarchy. This includes,
178  * host bridges, root ports, upstream/downstream switch ports, and devices
179  */
180 typedef struct cxl_component {
181     ComponentRegisters crb;
182     union {
183         struct {
184             Range dvsecs[CXL20_MAX_DVSEC];
185             uint16_t dvsec_offset;
186             struct PCIDevice *pdev;
187         };
188     };
189 
190     CDATObject cdat;
191 } CXLComponentState;
192 
193 void cxl_component_register_block_init(Object *obj,
194                                        CXLComponentState *cxl_cstate,
195                                        const char *type);
196 void cxl_component_register_init_common(uint32_t *reg_state,
197                                         uint32_t *write_msk,
198                                         enum reg_type type);
199 
200 void cxl_component_create_dvsec(CXLComponentState *cxl_cstate,
201                                 enum reg_type cxl_dev_type, uint16_t length,
202                                 uint16_t type, uint8_t rev, uint8_t *body);
203 
204 static inline int cxl_decoder_count_enc(int count)
205 {
206     switch (count) {
207     case 1: return 0;
208     case 2: return 1;
209     case 4: return 2;
210     case 6: return 3;
211     case 8: return 4;
212     case 10: return 5;
213     }
214     return 0;
215 }
216 
217 uint8_t cxl_interleave_ways_enc(int iw, Error **errp);
218 uint8_t cxl_interleave_granularity_enc(uint64_t gran, Error **errp);
219 
220 static inline hwaddr cxl_decode_ig(int ig)
221 {
222     return 1ULL << (ig + 8);
223 }
224 
225 CXLComponentState *cxl_get_hb_cstate(PCIHostState *hb);
226 
227 void cxl_doe_cdat_init(CXLComponentState *cxl_cstate, Error **errp);
228 void cxl_doe_cdat_release(CXLComponentState *cxl_cstate);
229 void cxl_doe_cdat_update(CXLComponentState *cxl_cstate, Error **errp);
230 
231 #endif
232