1 /* 2 * SPDX-License-Identifier: GPL-2.0-or-later 3 * 4 * Emulation of a CXL Switch Mailbox CCI PCIe function. 5 * 6 * Copyright (c) 2023 Huawei Technologies. 7 * 8 * From www.computeexpresslink.org 9 * Compute Express Link (CXL) Specification revision 3.0 Version 1.0 10 */ 11 #include "qemu/osdep.h" 12 #include "hw/pci/pci.h" 13 #include "hw/pci-bridge/cxl_upstream_port.h" 14 #include "qapi/error.h" 15 #include "qemu/log.h" 16 #include "qemu/module.h" 17 #include "hw/qdev-properties.h" 18 #include "hw/cxl/cxl.h" 19 20 #define CXL_SWCCI_MSIX_MBOX 3 21 22 static void cswmbcci_reset(DeviceState *dev) 23 { 24 CSWMBCCIDev *cswmb = CXL_SWITCH_MAILBOX_CCI(dev); 25 cxl_device_register_init_swcci(cswmb, CXL_SWCCI_MSIX_MBOX); 26 } 27 28 static void cswbcci_realize(PCIDevice *pci_dev, Error **errp) 29 { 30 CSWMBCCIDev *cswmb = CXL_SWITCH_MAILBOX_CCI(pci_dev); 31 CXLComponentState *cxl_cstate = &cswmb->cxl_cstate; 32 CXLDeviceState *cxl_dstate = &cswmb->cxl_dstate; 33 CXLDVSECRegisterLocator *regloc_dvsec; 34 CXLUpstreamPort *usp; 35 36 if (!cswmb->target) { 37 error_setg(errp, "Target not set"); 38 return; 39 } 40 usp = CXL_USP(cswmb->target); 41 42 pcie_endpoint_cap_init(pci_dev, 0x80); 43 cxl_cstate->dvsec_offset = 0x100; 44 cxl_cstate->pdev = pci_dev; 45 cswmb->cci = &usp->swcci; 46 cxl_device_register_block_init(OBJECT(pci_dev), cxl_dstate, cswmb->cci); 47 pci_register_bar(pci_dev, 0, 48 PCI_BASE_ADDRESS_SPACE_MEMORY | 49 PCI_BASE_ADDRESS_MEM_TYPE_64, 50 &cxl_dstate->device_registers); 51 regloc_dvsec = &(CXLDVSECRegisterLocator) { 52 .rsvd = 0, 53 .reg0_base_lo = RBI_CXL_DEVICE_REG | 0, 54 .reg0_base_hi = 0, 55 }; 56 cxl_component_create_dvsec(cxl_cstate, CXL3_SWITCH_MAILBOX_CCI, 57 REG_LOC_DVSEC_LENGTH, REG_LOC_DVSEC, 58 REG_LOC_DVSEC_REVID, (uint8_t *)regloc_dvsec); 59 60 cxl_initialize_mailbox_swcci(cswmb->cci, DEVICE(pci_dev), 61 DEVICE(cswmb->target), 62 CXL_MAILBOX_MAX_PAYLOAD_SIZE); 63 } 64 65 static void cswmbcci_exit(PCIDevice *pci_dev) 66 { 67 /* Nothing to do here yet */ 68 } 69 70 static const Property cxl_switch_cci_props[] = { 71 DEFINE_PROP_LINK("target", CSWMBCCIDev, 72 target, TYPE_CXL_USP, PCIDevice *), 73 }; 74 75 static void cswmbcci_class_init(ObjectClass *oc, void *data) 76 { 77 DeviceClass *dc = DEVICE_CLASS(oc); 78 PCIDeviceClass *pc = PCI_DEVICE_CLASS(oc); 79 80 pc->realize = cswbcci_realize; 81 pc->exit = cswmbcci_exit; 82 /* Serial bus, CXL Switch CCI */ 83 pc->class_id = 0x0c0b; 84 /* 85 * Huawei Technologies 86 * CXL Switch Mailbox CCI - DID assigned for emulation only. 87 * No real hardware will ever use this ID. 88 */ 89 pc->vendor_id = 0x19e5; 90 pc->device_id = 0xa123; 91 pc->revision = 0; 92 dc->desc = "CXL Switch Mailbox CCI"; 93 device_class_set_legacy_reset(dc, cswmbcci_reset); 94 device_class_set_props(dc, cxl_switch_cci_props); 95 } 96 97 static const TypeInfo cswmbcci_info = { 98 .name = TYPE_CXL_SWITCH_MAILBOX_CCI, 99 .parent = TYPE_PCI_DEVICE, 100 .class_init = cswmbcci_class_init, 101 .instance_size = sizeof(CSWMBCCIDev), 102 .interfaces = (InterfaceInfo[]) { 103 { INTERFACE_PCIE_DEVICE }, 104 { } 105 }, 106 }; 107 108 static void cxl_switch_mailbox_cci_register(void) 109 { 110 type_register_static(&cswmbcci_info); 111 } 112 type_init(cxl_switch_mailbox_cci_register); 113