master
c 386 lines 10.6 KB
Raw
1 /*
2 * PCIe Data Object Exchange
3 *
4 * Copyright (C) 2021 Avery Design Systems, Inc.
5 *
6 * This work is licensed under the terms of the GNU GPL, version 2 or later.
7 * See the COPYING file in the top-level directory.
8 */
9
10 #include "qemu/osdep.h"
11 #include "qemu/log.h"
12 #include "qemu/error-report.h"
13 #include "qapi/error.h"
14 #include "qemu/range.h"
15 #include "hw/pci/pci.h"
16 #include "hw/pci/pcie.h"
17 #include "hw/pci/pcie_doe.h"
18 #include "hw/pci/msi.h"
19 #include "hw/pci/msix.h"
20
21 #define DWORD_BYTE 4
22
23 typedef struct DoeDiscoveryReq {
24 DOEHeader header;
25 uint8_t index;
26 uint8_t reserved[3];
27 } QEMU_PACKED DoeDiscoveryReq;
28
29 typedef struct DoeDiscoveryRsp {
30 DOEHeader header;
31 uint16_t vendor_id;
32 uint8_t data_obj_type;
33 uint8_t next_index;
34 } QEMU_PACKED DoeDiscoveryRsp;
35
36 static bool pcie_doe_discovery(DOECap *doe_cap)
37 {
38 DoeDiscoveryReq *req = pcie_doe_get_write_mbox_ptr(doe_cap);
39 DoeDiscoveryRsp rsp;
40 uint8_t index = req->index;
41 DOEProtocol *prot;
42
43 /* Discard request if length does not match DoeDiscoveryReq */
44 if (pcie_doe_get_obj_len(req) <
45 DIV_ROUND_UP(sizeof(DoeDiscoveryReq), DWORD_BYTE)) {
46 return false;
47 }
48
49 rsp.header = (DOEHeader) {
50 .vendor_id = PCI_VENDOR_ID_PCI_SIG,
51 .data_obj_type = PCI_SIG_DOE_DISCOVERY,
52 .length = DIV_ROUND_UP(sizeof(DoeDiscoveryRsp), DWORD_BYTE),
53 };
54
55 /* Point to the requested protocol, index 0 must be Discovery */
56 if (index == 0) {
57 rsp.vendor_id = PCI_VENDOR_ID_PCI_SIG;
58 rsp.data_obj_type = PCI_SIG_DOE_DISCOVERY;
59 } else {
60 if (index < doe_cap->protocol_num) {
61 prot = &doe_cap->protocols[index - 1];
62 rsp.vendor_id = prot->vendor_id;
63 rsp.data_obj_type = prot->data_obj_type;
64 } else {
65 rsp.vendor_id = 0xFFFF;
66 rsp.data_obj_type = 0xFF;
67 }
68 }
69
70 if (index + 1 == doe_cap->protocol_num) {
71 rsp.next_index = 0;
72 } else {
73 rsp.next_index = index + 1;
74 }
75
76 pcie_doe_set_rsp(doe_cap, &rsp);
77
78 return true;
79 }
80
81 static void pcie_doe_reset_write_mbox(DOECap *st)
82 {
83 st->write_mbox_len = 0;
84
85 memset(st->write_mbox, 0, PCI_DOE_DW_SIZE_MAX * DWORD_BYTE);
86 }
87
88 static void pcie_doe_reset_mbox(DOECap *st)
89 {
90 st->read_mbox_idx = 0;
91 st->read_mbox_len = 0;
92
93 memset(st->read_mbox, 0, PCI_DOE_DW_SIZE_MAX * DWORD_BYTE);
94
95 pcie_doe_reset_write_mbox(st);
96 }
97
98 void pcie_doe_init(PCIDevice *dev, DOECap *doe_cap, uint16_t offset,
99 DOEProtocol *protocols, bool intr, uint16_t vec)
100 {
101 pcie_add_capability(dev, PCI_EXT_CAP_ID_DOE, 0x1, offset,
102 PCI_DOE_SIZEOF);
103
104 doe_cap->pdev = dev;
105 doe_cap->offset = offset;
106
107 if (intr && (msi_present(dev) || msix_present(dev))) {
108 doe_cap->cap.intr = intr;
109 doe_cap->cap.vec = vec;
110 }
111
112 doe_cap->write_mbox = g_malloc0(PCI_DOE_DW_SIZE_MAX * DWORD_BYTE);
113 doe_cap->read_mbox = g_malloc0(PCI_DOE_DW_SIZE_MAX * DWORD_BYTE);
114
115 pcie_doe_reset_mbox(doe_cap);
116
117 doe_cap->protocols = protocols;
118 for (; protocols->vendor_id; protocols++) {
119 doe_cap->protocol_num++;
120 }
121 assert(doe_cap->protocol_num < PCI_DOE_PROTOCOL_NUM_MAX);
122
123 /* Increment to allow for the discovery protocol */
124 doe_cap->protocol_num++;
125 }
126
127 void pcie_doe_fini(DOECap *doe_cap)
128 {
129 g_free(doe_cap->read_mbox);
130 g_free(doe_cap->write_mbox);
131 g_free(doe_cap);
132 }
133
134 uint32_t pcie_doe_build_protocol(DOEProtocol *p)
135 {
136 return DATA_OBJ_BUILD_HEADER1(p->vendor_id, p->data_obj_type);
137 }
138
139 void *pcie_doe_get_write_mbox_ptr(DOECap *doe_cap)
140 {
141 return doe_cap->write_mbox;
142 }
143
144 /*
145 * Copy the response to read mailbox buffer
146 * This might be called in self-defined handle_request() if a DOE response is
147 * required in the corresponding protocol
148 */
149 void pcie_doe_set_rsp(DOECap *doe_cap, void *rsp)
150 {
151 uint32_t len = pcie_doe_get_obj_len(rsp);
152
153 memcpy(doe_cap->read_mbox + doe_cap->read_mbox_len, rsp, len * DWORD_BYTE);
154 doe_cap->read_mbox_len += len;
155 }
156
157 uint32_t pcie_doe_get_obj_len(void *obj)
158 {
159 uint32_t len;
160
161 if (!obj) {
162 return 0;
163 }
164
165 /* Only lower 18 bits are valid */
166 len = DATA_OBJ_LEN_MASK(((DOEHeader *)obj)->length);
167
168 /* PCIe r6.0 Table 6.29: a value of 00000h indicates 2^18 DW */
169 return (len) ? len : PCI_DOE_DW_SIZE_MAX;
170 }
171
172 static void pcie_doe_irq_assert(DOECap *doe_cap)
173 {
174 PCIDevice *dev = doe_cap->pdev;
175
176 if (doe_cap->cap.intr && doe_cap->ctrl.intr) {
177 if (doe_cap->status.intr) {
178 return;
179 }
180 doe_cap->status.intr = 1;
181
182 if (msix_enabled(dev)) {
183 msix_notify(dev, doe_cap->cap.vec);
184 } else if (msi_enabled(dev)) {
185 msi_notify(dev, doe_cap->cap.vec);
186 }
187 }
188 }
189
190 static void pcie_doe_set_ready(DOECap *doe_cap, bool rdy)
191 {
192 doe_cap->status.ready = rdy;
193
194 if (rdy) {
195 pcie_doe_irq_assert(doe_cap);
196 }
197 }
198
199 static void pcie_doe_set_error(DOECap *doe_cap, bool err)
200 {
201 doe_cap->status.error = err;
202
203 if (err) {
204 pcie_doe_irq_assert(doe_cap);
205 }
206 }
207
208 /*
209 * Check incoming request in write_mbox for protocol format
210 */
211 static void pcie_doe_prepare_rsp(DOECap *doe_cap)
212 {
213 bool success = false;
214 int p;
215 bool (*handle_request)(DOECap *) = NULL;
216
217 if (doe_cap->status.error) {
218 return;
219 }
220
221 if (doe_cap->write_mbox[0] ==
222 DATA_OBJ_BUILD_HEADER1(PCI_VENDOR_ID_PCI_SIG, PCI_SIG_DOE_DISCOVERY)) {
223 handle_request = pcie_doe_discovery;
224 } else {
225 for (p = 0; p < doe_cap->protocol_num - 1; p++) {
226 if (doe_cap->write_mbox[0] ==
227 pcie_doe_build_protocol(&doe_cap->protocols[p])) {
228 handle_request = doe_cap->protocols[p].handle_request;
229 break;
230 }
231 }
232 }
233
234 /*
235 * PCIe r6 DOE 6.30.1:
236 * If the number of DW transferred does not match the
237 * indicated Length for a data object, then the
238 * data object must be silently discarded.
239 */
240 if (handle_request && (doe_cap->write_mbox_len ==
241 pcie_doe_get_obj_len(pcie_doe_get_write_mbox_ptr(doe_cap)))) {
242 success = handle_request(doe_cap);
243 }
244
245 if (success) {
246 pcie_doe_set_ready(doe_cap, 1);
247 } else {
248 pcie_doe_reset_mbox(doe_cap);
249 }
250 }
251
252 /*
253 * Read from DOE config space.
254 * Return false if the address not within DOE_CAP range.
255 */
256 bool pcie_doe_read_config(DOECap *doe_cap, uint32_t addr, int size,
257 uint32_t *buf)
258 {
259 uint32_t shift;
260 uint16_t doe_offset = doe_cap->offset;
261
262 if (!range_covers_byte(doe_offset + PCI_EXP_DOE_CAP,
263 PCI_DOE_SIZEOF - 4, addr)) {
264 return false;
265 }
266
267 addr -= doe_offset;
268 *buf = 0;
269
270 if (range_covers_byte(PCI_EXP_DOE_CAP, DWORD_BYTE, addr)) {
271 *buf = FIELD_DP32(*buf, PCI_DOE_CAP_REG, INTR_SUPP,
272 doe_cap->cap.intr);
273 *buf = FIELD_DP32(*buf, PCI_DOE_CAP_REG, DOE_INTR_MSG_NUM,
274 doe_cap->cap.vec);
275 } else if (range_covers_byte(PCI_EXP_DOE_CTRL, DWORD_BYTE, addr)) {
276 /* Must return ABORT=0 and GO=0 */
277 *buf = FIELD_DP32(*buf, PCI_DOE_CAP_CONTROL, DOE_INTR_EN,
278 doe_cap->ctrl.intr);
279 } else if (range_covers_byte(PCI_EXP_DOE_STATUS, DWORD_BYTE, addr)) {
280 *buf = FIELD_DP32(*buf, PCI_DOE_CAP_STATUS, DOE_BUSY,
281 doe_cap->status.busy);
282 *buf = FIELD_DP32(*buf, PCI_DOE_CAP_STATUS, DOE_INTR_STATUS,
283 doe_cap->status.intr);
284 *buf = FIELD_DP32(*buf, PCI_DOE_CAP_STATUS, DOE_ERROR,
285 doe_cap->status.error);
286 *buf = FIELD_DP32(*buf, PCI_DOE_CAP_STATUS, DATA_OBJ_RDY,
287 doe_cap->status.ready);
288 /* Mailbox should be DW accessed */
289 } else if (addr == PCI_EXP_DOE_RD_DATA_MBOX && size == DWORD_BYTE) {
290 if (doe_cap->status.ready && !doe_cap->status.error) {
291 *buf = doe_cap->read_mbox[doe_cap->read_mbox_idx];
292 }
293 }
294
295 /* Process Alignment */
296 shift = addr % DWORD_BYTE;
297 *buf = extract32(*buf, shift * 8, size * 8);
298
299 return true;
300 }
301
302 /*
303 * Write to DOE config space.
304 * Return if the address not within DOE_CAP range or receives an abort
305 */
306 void pcie_doe_write_config(DOECap *doe_cap,
307 uint32_t addr, uint32_t val, int size)
308 {
309 uint16_t doe_offset = doe_cap->offset;
310 uint32_t shift;
311
312 if (!range_covers_byte(doe_offset + PCI_EXP_DOE_CAP,
313 PCI_DOE_SIZEOF - 4, addr)) {
314 return;
315 }
316
317 /* Process Alignment */
318 shift = addr % DWORD_BYTE;
319 addr -= (doe_offset + shift);
320 val = deposit32(val, shift * 8, size * 8, val);
321
322 switch (addr) {
323 case PCI_EXP_DOE_CTRL:
324 if (FIELD_EX32(val, PCI_DOE_CAP_CONTROL, DOE_ABORT)) {
325 pcie_doe_set_ready(doe_cap, 0);
326 pcie_doe_set_error(doe_cap, 0);
327 pcie_doe_reset_mbox(doe_cap);
328 return;
329 }
330
331 if (FIELD_EX32(val, PCI_DOE_CAP_CONTROL, DOE_GO)) {
332 pcie_doe_prepare_rsp(doe_cap);
333 }
334
335 if (FIELD_EX32(val, PCI_DOE_CAP_CONTROL, DOE_INTR_EN)) {
336 doe_cap->ctrl.intr = 1;
337 /* Clear interrupt bit located within the first byte */
338 } else if (shift == 0) {
339 doe_cap->ctrl.intr = 0;
340 }
341 break;
342 case PCI_EXP_DOE_STATUS:
343 if (FIELD_EX32(val, PCI_DOE_CAP_STATUS, DOE_INTR_STATUS)) {
344 doe_cap->status.intr = 0;
345 }
346 break;
347 case PCI_EXP_DOE_RD_DATA_MBOX:
348 /* Mailbox should be DW accessed */
349 if (size != DWORD_BYTE) {
350 return;
351 }
352 doe_cap->read_mbox_idx++;
353 if (doe_cap->read_mbox_idx == doe_cap->read_mbox_len) {
354 pcie_doe_reset_mbox(doe_cap);
355 pcie_doe_set_ready(doe_cap, 0);
356 } else if (doe_cap->read_mbox_idx > doe_cap->read_mbox_len) {
357 /* Underflow */
358 pcie_doe_set_error(doe_cap, 1);
359 }
360 break;
361 case PCI_EXP_DOE_WR_DATA_MBOX:
362 /* Mailbox should be DW accessed */
363 if (size != DWORD_BYTE) {
364 return;
365 }
366 if (doe_cap->write_mbox_len < PCI_DOE_DW_SIZE_MAX) {
367 doe_cap->write_mbox[doe_cap->write_mbox_len] = val;
368 doe_cap->write_mbox_len++;
369 } else {
370 qemu_log_mask(LOG_GUEST_ERROR,
371 "Mailbox write length (%d) overflow\n",
372 doe_cap->write_mbox_len);
373 /*
374 * Too much data has been written, it can't
375 * "match the Length indicated in DOE Data Object Header 2"
376 * so we drop the entire object.
377 */
378 pcie_doe_reset_write_mbox(doe_cap);
379 }
380 break;
381 case PCI_EXP_DOE_CAP:
382 /* fallthrough */
383 default:
384 break;
385 }
386 }