1 /* 2 * Generic PCI Express Root Port emulation 3 * 4 * Copyright (C) 2017 Red Hat Inc 5 * 6 * Authors: 7 * Marcel Apfelbaum <marcel@redhat.com> 8 * 9 * This work is licensed under the terms of the GNU GPL, version 2 or later. 10 * See the COPYING file in the top-level directory. 11 */ 12 13 #include "qemu/osdep.h" 14 #include "qapi/error.h" 15 #include "hw/pci/msix.h" 16 #include "hw/pci/pcie_port.h" 17 18 #define TYPE_GEN_PCIE_ROOT_PORT "pcie-root-port" 19 20 #define GEN_PCIE_ROOT_PORT_AER_OFFSET 0x100 21 #define GEN_PCIE_ROOT_PORT_MSIX_NR_VECTOR 1 22 23 typedef struct GenPCIERootPort { 24 /*< private >*/ 25 PCIESlot parent_obj; 26 /*< public >*/ 27 28 bool migrate_msix; 29 } GenPCIERootPort; 30 31 static uint8_t gen_rp_aer_vector(const PCIDevice *d) 32 { 33 return 0; 34 } 35 36 static int gen_rp_interrupts_init(PCIDevice *d, Error **errp) 37 { 38 int rc; 39 40 rc = msix_init_exclusive_bar(d, GEN_PCIE_ROOT_PORT_MSIX_NR_VECTOR, 0, errp); 41 42 if (rc < 0) { 43 assert(rc == -ENOTSUP); 44 } else { 45 msix_vector_use(d, 0); 46 } 47 48 return rc; 49 } 50 51 static void gen_rp_interrupts_uninit(PCIDevice *d) 52 { 53 msix_uninit_exclusive_bar(d); 54 } 55 56 static bool gen_rp_test_migrate_msix(void *opaque, int version_id) 57 { 58 GenPCIERootPort *rp = opaque; 59 60 return rp->migrate_msix; 61 } 62 63 static const VMStateDescription vmstate_rp_dev = { 64 .name = "pcie-root-port", 65 .version_id = 1, 66 .minimum_version_id = 1, 67 .post_load = pcie_cap_slot_post_load, 68 .fields = (VMStateField[]) { 69 VMSTATE_PCI_DEVICE(parent_obj.parent_obj.parent_obj, PCIESlot), 70 VMSTATE_STRUCT(parent_obj.parent_obj.parent_obj.exp.aer_log, 71 PCIESlot, 0, vmstate_pcie_aer_log, PCIEAERLog), 72 VMSTATE_MSIX_TEST(parent_obj.parent_obj.parent_obj.parent_obj, 73 GenPCIERootPort, 74 gen_rp_test_migrate_msix), 75 VMSTATE_END_OF_LIST() 76 } 77 }; 78 79 static Property gen_rp_props[] = { 80 DEFINE_PROP_BOOL("x-migrate-msix", GenPCIERootPort, migrate_msix, true), 81 DEFINE_PROP_END_OF_LIST() 82 }; 83 84 static void gen_rp_dev_class_init(ObjectClass *klass, void *data) 85 { 86 DeviceClass *dc = DEVICE_CLASS(klass); 87 PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); 88 PCIERootPortClass *rpc = PCIE_ROOT_PORT_CLASS(klass); 89 90 k->vendor_id = PCI_VENDOR_ID_REDHAT; 91 k->device_id = PCI_DEVICE_ID_REDHAT_PCIE_RP; 92 dc->desc = "PCI Express Root Port"; 93 dc->vmsd = &vmstate_rp_dev; 94 dc->props = gen_rp_props; 95 rpc->aer_vector = gen_rp_aer_vector; 96 rpc->interrupts_init = gen_rp_interrupts_init; 97 rpc->interrupts_uninit = gen_rp_interrupts_uninit; 98 rpc->aer_offset = GEN_PCIE_ROOT_PORT_AER_OFFSET; 99 } 100 101 static const TypeInfo gen_rp_dev_info = { 102 .name = TYPE_GEN_PCIE_ROOT_PORT, 103 .parent = TYPE_PCIE_ROOT_PORT, 104 .instance_size = sizeof(GenPCIERootPort), 105 .class_init = gen_rp_dev_class_init, 106 }; 107 108 static void gen_rp_register_types(void) 109 { 110 type_register_static(&gen_rp_dev_info); 111 } 112 type_init(gen_rp_register_types) 113