]>
Commit | Line | Data |
---|---|---|
f7d6f3fa MA |
1 | /* |
2 | * Generic PCI Express Root Port emulation | |
3 | * | |
4 | * Copyright (C) 2017 Red Hat Inc | |
5 | * | |
6 | * Authors: | |
7 | * Marcel Apfelbaum <[email protected]> | |
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 | ||
bc277a52 MA |
23 | typedef struct GenPCIERootPort { |
24 | /*< private >*/ | |
25 | PCIESlot parent_obj; | |
26 | /*< public >*/ | |
27 | ||
28 | bool migrate_msix; | |
29 | } GenPCIERootPort; | |
30 | ||
f7d6f3fa MA |
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 | ||
ee640c62 | 40 | rc = msix_init_exclusive_bar(d, GEN_PCIE_ROOT_PORT_MSIX_NR_VECTOR, 0, errp); |
f7d6f3fa MA |
41 | |
42 | if (rc < 0) { | |
43 | assert(rc == -ENOTSUP); | |
f7d6f3fa MA |
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 | ||
bc277a52 MA |
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 | ||
f7d6f3fa MA |
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), | |
bc277a52 MA |
72 | VMSTATE_MSIX_TEST(parent_obj.parent_obj.parent_obj.parent_obj, |
73 | GenPCIERootPort, | |
74 | gen_rp_test_migrate_msix), | |
f7d6f3fa MA |
75 | VMSTATE_END_OF_LIST() |
76 | } | |
77 | }; | |
78 | ||
bc277a52 MA |
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 | ||
f7d6f3fa MA |
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; | |
bc277a52 | 94 | dc->props = gen_rp_props; |
f7d6f3fa MA |
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, | |
bc277a52 | 104 | .instance_size = sizeof(GenPCIERootPort), |
f7d6f3fa MA |
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) |