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_mbox(DOECap *st) 82 { 83 st->read_mbox_idx = 0; 84 st->read_mbox_len = 0; 85 st->write_mbox_len = 0; 86 87 memset(st->read_mbox, 0, PCI_DOE_DW_SIZE_MAX * DWORD_BYTE); 88 memset(st->write_mbox, 0, PCI_DOE_DW_SIZE_MAX * DWORD_BYTE); 89 } 90 91 void pcie_doe_init(PCIDevice *dev, DOECap *doe_cap, uint16_t offset, 92 DOEProtocol *protocols, bool intr, uint16_t vec) 93 { 94 pcie_add_capability(dev, PCI_EXT_CAP_ID_DOE, 0x1, offset, 95 PCI_DOE_SIZEOF); 96 97 doe_cap->pdev = dev; 98 doe_cap->offset = offset; 99 100 if (intr && (msi_present(dev) || msix_present(dev))) { 101 doe_cap->cap.intr = intr; 102 doe_cap->cap.vec = vec; 103 } 104 105 doe_cap->write_mbox = g_malloc0(PCI_DOE_DW_SIZE_MAX * DWORD_BYTE); 106 doe_cap->read_mbox = g_malloc0(PCI_DOE_DW_SIZE_MAX * DWORD_BYTE); 107 108 pcie_doe_reset_mbox(doe_cap); 109 110 doe_cap->protocols = protocols; 111 for (; protocols->vendor_id; protocols++) { 112 doe_cap->protocol_num++; 113 } 114 assert(doe_cap->protocol_num < PCI_DOE_PROTOCOL_NUM_MAX); 115 116 /* Increment to allow for the discovery protocol */ 117 doe_cap->protocol_num++; 118 } 119 120 void pcie_doe_fini(DOECap *doe_cap) 121 { 122 g_free(doe_cap->read_mbox); 123 g_free(doe_cap->write_mbox); 124 g_free(doe_cap); 125 } 126 127 uint32_t pcie_doe_build_protocol(DOEProtocol *p) 128 { 129 return DATA_OBJ_BUILD_HEADER1(p->vendor_id, p->data_obj_type); 130 } 131 132 void *pcie_doe_get_write_mbox_ptr(DOECap *doe_cap) 133 { 134 return doe_cap->write_mbox; 135 } 136 137 /* 138 * Copy the response to read mailbox buffer 139 * This might be called in self-defined handle_request() if a DOE response is 140 * required in the corresponding protocol 141 */ 142 void pcie_doe_set_rsp(DOECap *doe_cap, void *rsp) 143 { 144 uint32_t len = pcie_doe_get_obj_len(rsp); 145 146 memcpy(doe_cap->read_mbox + doe_cap->read_mbox_len, rsp, len * DWORD_BYTE); 147 doe_cap->read_mbox_len += len; 148 } 149 150 uint32_t pcie_doe_get_obj_len(void *obj) 151 { 152 uint32_t len; 153 154 if (!obj) { 155 return 0; 156 } 157 158 /* Only lower 18 bits are valid */ 159 len = DATA_OBJ_LEN_MASK(((DOEHeader *)obj)->length); 160 161 /* PCIe r6.0 Table 6.29: a value of 00000h indicates 2^18 DW */ 162 return (len) ? len : PCI_DOE_DW_SIZE_MAX; 163 } 164 165 static void pcie_doe_irq_assert(DOECap *doe_cap) 166 { 167 PCIDevice *dev = doe_cap->pdev; 168 169 if (doe_cap->cap.intr && doe_cap->ctrl.intr) { 170 if (doe_cap->status.intr) { 171 return; 172 } 173 doe_cap->status.intr = 1; 174 175 if (msix_enabled(dev)) { 176 msix_notify(dev, doe_cap->cap.vec); 177 } else if (msi_enabled(dev)) { 178 msi_notify(dev, doe_cap->cap.vec); 179 } 180 } 181 } 182 183 static void pcie_doe_set_ready(DOECap *doe_cap, bool rdy) 184 { 185 doe_cap->status.ready = rdy; 186 187 if (rdy) { 188 pcie_doe_irq_assert(doe_cap); 189 } 190 } 191 192 static void pcie_doe_set_error(DOECap *doe_cap, bool err) 193 { 194 doe_cap->status.error = err; 195 196 if (err) { 197 pcie_doe_irq_assert(doe_cap); 198 } 199 } 200 201 /* 202 * Check incoming request in write_mbox for protocol format 203 */ 204 static void pcie_doe_prepare_rsp(DOECap *doe_cap) 205 { 206 bool success = false; 207 int p; 208 bool (*handle_request)(DOECap *) = NULL; 209 210 if (doe_cap->status.error) { 211 return; 212 } 213 214 if (doe_cap->write_mbox[0] == 215 DATA_OBJ_BUILD_HEADER1(PCI_VENDOR_ID_PCI_SIG, PCI_SIG_DOE_DISCOVERY)) { 216 handle_request = pcie_doe_discovery; 217 } else { 218 for (p = 0; p < doe_cap->protocol_num - 1; p++) { 219 if (doe_cap->write_mbox[0] == 220 pcie_doe_build_protocol(&doe_cap->protocols[p])) { 221 handle_request = doe_cap->protocols[p].handle_request; 222 break; 223 } 224 } 225 } 226 227 /* 228 * PCIe r6 DOE 6.30.1: 229 * If the number of DW transferred does not match the 230 * indicated Length for a data object, then the 231 * data object must be silently discarded. 232 */ 233 if (handle_request && (doe_cap->write_mbox_len == 234 pcie_doe_get_obj_len(pcie_doe_get_write_mbox_ptr(doe_cap)))) { 235 success = handle_request(doe_cap); 236 } 237 238 if (success) { 239 pcie_doe_set_ready(doe_cap, 1); 240 } else { 241 pcie_doe_reset_mbox(doe_cap); 242 } 243 } 244 245 /* 246 * Read from DOE config space. 247 * Return false if the address not within DOE_CAP range. 248 */ 249 bool pcie_doe_read_config(DOECap *doe_cap, uint32_t addr, int size, 250 uint32_t *buf) 251 { 252 uint32_t shift; 253 uint16_t doe_offset = doe_cap->offset; 254 255 if (!range_covers_byte(doe_offset + PCI_EXP_DOE_CAP, 256 PCI_DOE_SIZEOF - 4, addr)) { 257 return false; 258 } 259 260 addr -= doe_offset; 261 *buf = 0; 262 263 if (range_covers_byte(PCI_EXP_DOE_CAP, DWORD_BYTE, addr)) { 264 *buf = FIELD_DP32(*buf, PCI_DOE_CAP_REG, INTR_SUPP, 265 doe_cap->cap.intr); 266 *buf = FIELD_DP32(*buf, PCI_DOE_CAP_REG, DOE_INTR_MSG_NUM, 267 doe_cap->cap.vec); 268 } else if (range_covers_byte(PCI_EXP_DOE_CTRL, DWORD_BYTE, addr)) { 269 /* Must return ABORT=0 and GO=0 */ 270 *buf = FIELD_DP32(*buf, PCI_DOE_CAP_CONTROL, DOE_INTR_EN, 271 doe_cap->ctrl.intr); 272 } else if (range_covers_byte(PCI_EXP_DOE_STATUS, DWORD_BYTE, addr)) { 273 *buf = FIELD_DP32(*buf, PCI_DOE_CAP_STATUS, DOE_BUSY, 274 doe_cap->status.busy); 275 *buf = FIELD_DP32(*buf, PCI_DOE_CAP_STATUS, DOE_INTR_STATUS, 276 doe_cap->status.intr); 277 *buf = FIELD_DP32(*buf, PCI_DOE_CAP_STATUS, DOE_ERROR, 278 doe_cap->status.error); 279 *buf = FIELD_DP32(*buf, PCI_DOE_CAP_STATUS, DATA_OBJ_RDY, 280 doe_cap->status.ready); 281 /* Mailbox should be DW accessed */ 282 } else if (addr == PCI_EXP_DOE_RD_DATA_MBOX && size == DWORD_BYTE) { 283 if (doe_cap->status.ready && !doe_cap->status.error) { 284 *buf = doe_cap->read_mbox[doe_cap->read_mbox_idx]; 285 } 286 } 287 288 /* Process Alignment */ 289 shift = addr % DWORD_BYTE; 290 *buf = extract32(*buf, shift * 8, size * 8); 291 292 return true; 293 } 294 295 /* 296 * Write to DOE config space. 297 * Return if the address not within DOE_CAP range or receives an abort 298 */ 299 void pcie_doe_write_config(DOECap *doe_cap, 300 uint32_t addr, uint32_t val, int size) 301 { 302 uint16_t doe_offset = doe_cap->offset; 303 uint32_t shift; 304 305 if (!range_covers_byte(doe_offset + PCI_EXP_DOE_CAP, 306 PCI_DOE_SIZEOF - 4, addr)) { 307 return; 308 } 309 310 /* Process Alignment */ 311 shift = addr % DWORD_BYTE; 312 addr -= (doe_offset + shift); 313 val = deposit32(val, shift * 8, size * 8, val); 314 315 switch (addr) { 316 case PCI_EXP_DOE_CTRL: 317 if (FIELD_EX32(val, PCI_DOE_CAP_CONTROL, DOE_ABORT)) { 318 pcie_doe_set_ready(doe_cap, 0); 319 pcie_doe_set_error(doe_cap, 0); 320 pcie_doe_reset_mbox(doe_cap); 321 return; 322 } 323 324 if (FIELD_EX32(val, PCI_DOE_CAP_CONTROL, DOE_GO)) { 325 pcie_doe_prepare_rsp(doe_cap); 326 } 327 328 if (FIELD_EX32(val, PCI_DOE_CAP_CONTROL, DOE_INTR_EN)) { 329 doe_cap->ctrl.intr = 1; 330 /* Clear interrupt bit located within the first byte */ 331 } else if (shift == 0) { 332 doe_cap->ctrl.intr = 0; 333 } 334 break; 335 case PCI_EXP_DOE_STATUS: 336 if (FIELD_EX32(val, PCI_DOE_CAP_STATUS, DOE_INTR_STATUS)) { 337 doe_cap->status.intr = 0; 338 } 339 break; 340 case PCI_EXP_DOE_RD_DATA_MBOX: 341 /* Mailbox should be DW accessed */ 342 if (size != DWORD_BYTE) { 343 return; 344 } 345 doe_cap->read_mbox_idx++; 346 if (doe_cap->read_mbox_idx == doe_cap->read_mbox_len) { 347 pcie_doe_reset_mbox(doe_cap); 348 pcie_doe_set_ready(doe_cap, 0); 349 } else if (doe_cap->read_mbox_idx > doe_cap->read_mbox_len) { 350 /* Underflow */ 351 pcie_doe_set_error(doe_cap, 1); 352 } 353 break; 354 case PCI_EXP_DOE_WR_DATA_MBOX: 355 /* Mailbox should be DW accessed */ 356 if (size != DWORD_BYTE) { 357 return; 358 } 359 doe_cap->write_mbox[doe_cap->write_mbox_len] = val; 360 doe_cap->write_mbox_len++; 361 break; 362 case PCI_EXP_DOE_CAP: 363 /* fallthrough */ 364 default: 365 break; 366 } 367 } 368