aboutsummaryrefslogtreecommitdiff
path: root/include/hw/pci/pci_bridge.h
blob: b0f5204d80fe12fbc85218821292b276b649899b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
/*
 * QEMU PCI bridge
 *
 * Copyright (c) 2004 Fabrice Bellard
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 *
 * split out pci bus specific stuff from pci.[hc] to pci_bridge.[hc]
 * Copyright (c) 2009 Isaku Yamahata <yamahata at valinux co jp>
 *                    VA Linux Systems Japan K.K.
 *
 */

#ifndef QEMU_PCI_BRIDGE_H
#define QEMU_PCI_BRIDGE_H

#include "hw/pci/pci_device.h"
#include "hw/pci/pci_bus.h"
#include "hw/cxl/cxl.h"
#include "qom/object.h"

typedef struct PCIBridgeWindows PCIBridgeWindows;

/*
 * Aliases for each of the address space windows that the bridge
 * can forward. Mapped into the bridge's parent's address space,
 * as subregions.
 */
struct PCIBridgeWindows {
    MemoryRegion alias_pref_mem;
    MemoryRegion alias_mem;
    MemoryRegion alias_io;
    /*
     * When bridge control VGA forwarding is enabled, bridges will
     * provide positive decode on the PCI VGA defined I/O port and
     * MMIO ranges.  When enabled forwarding is only qualified on the
     * I/O and memory enable bits in the bridge command register.
     */
    MemoryRegion alias_vga[QEMU_PCI_VGA_NUM_REGIONS];
};

#define TYPE_PCI_BRIDGE "base-pci-bridge"
OBJECT_DECLARE_SIMPLE_TYPE(PCIBridge, PCI_BRIDGE)
#define IS_PCI_BRIDGE(dev) object_dynamic_cast(OBJECT(dev), TYPE_PCI_BRIDGE)

struct PCIBridge {
    /*< private >*/
    PCIDevice parent_obj;
    /*< public >*/

    /* private member */
    PCIBus sec_bus;
    /*
     * Memory regions for the bridge's address spaces.  These regions are not
     * directly added to system_memory/system_io or its descendants.
     * Bridge's secondary bus points to these, so that devices
     * under the bridge see these regions as its address spaces.
     * The regions are as large as the entire address space -
     * they don't take into account any windows.
     */
    MemoryRegion address_space_mem;
    MemoryRegion address_space_io;
    AddressSpace as_mem;
    AddressSpace as_io;

    PCIBridgeWindows windows;

    pci_map_irq_fn map_irq;
    const char *bus_name;

    /* SLT is RO for PCIE to PCIE bridges, but old QEMU versions had it RW */
    bool pcie_writeable_slt_bug;
};

#define PCI_BRIDGE_DEV_PROP_CHASSIS_NR "chassis_nr"
#define PCI_BRIDGE_DEV_PROP_MSI        "msi"
#define PCI_BRIDGE_DEV_PROP_SHPC       "shpc"
typedef struct CXLHost CXLHost;

typedef struct PXBDev {
    /*< private >*/
    PCIDevice parent_obj;
    /*< public >*/

    uint8_t bus_nr;
    uint16_t numa_node;
    bool bypass_iommu;
} PXBDev;

typedef struct PXBPCIEDev {
    /*< private >*/
    PXBDev parent_obj;
} PXBPCIEDev;

#define TYPE_PXB_CXL_BUS "pxb-cxl-bus"
#define TYPE_PXB_DEV "pxb"
OBJECT_DECLARE_SIMPLE_TYPE(PXBDev, PXB_DEV)

typedef struct PXBCXLDev {
    /*< private >*/
    PXBPCIEDev parent_obj;
    /*< public >*/

    bool hdm_for_passthrough;
    CXLHost *cxl_host_bridge; /* Pointer to a CXLHost */
} PXBCXLDev;

#define TYPE_PXB_CXL_DEV "pxb-cxl"
OBJECT_DECLARE_SIMPLE_TYPE(PXBCXLDev, PXB_CXL_DEV)

int pci_bridge_ssvid_init(PCIDevice *dev, uint8_t offset,
                          uint16_t svid, uint16_t ssid,
                          Error **errp);

PCIDevice *pci_bridge_get_device(PCIBus *bus);
PCIBus *pci_bridge_get_sec_bus(PCIBridge *br);

pcibus_t pci_bridge_get_base(const PCIDevice *bridge, uint8_t type);
pcibus_t pci_bridge_get_limit(const PCIDevice *bridge, uint8_t type);

void pci_bridge_update_mappings(PCIBridge *br);
void pci_bridge_write_config(PCIDevice *d,
                             uint32_t address, uint32_t val, int len);
void pci_bridge_disable_base_limit(PCIDevice *dev);
void pci_bridge_reset(DeviceState *qdev);

void pci_bridge_initfn(PCIDevice *pci_dev, const char *typename);
void pci_bridge_exitfn(PCIDevice *pci_dev);

void pci_bridge_dev_plug_cb(HotplugHandler *hotplug_dev, DeviceState *dev,
                            Error **errp);
void pci_bridge_dev_unplug_cb(HotplugHandler *hotplug_dev, DeviceState *dev,
                              Error **errp);
void pci_bridge_dev_unplug_request_cb(HotplugHandler *hotplug_dev,
                                      DeviceState *dev, Error **errp);

/*
 * before qdev initialization(qdev_init()), this function sets bus_name and
 * map_irq callback which are necessary for pci_bridge_initfn() to
 * initialize bus.
 */
void pci_bridge_map_irq(PCIBridge *br, const char* bus_name,
                        pci_map_irq_fn map_irq);

/* TODO: add this define to pci_regs.h in linux and then in qemu. */
#define  PCI_BRIDGE_CTL_VGA_16BIT       0x10    /* VGA 16-bit decode */
#define  PCI_BRIDGE_CTL_DISCARD         0x100   /* Primary discard timer */
#define  PCI_BRIDGE_CTL_SEC_DISCARD     0x200   /* Secondary discard timer */
#define  PCI_BRIDGE_CTL_DISCARD_STATUS  0x400   /* Discard timer status */
#define  PCI_BRIDGE_CTL_DISCARD_SERR    0x800   /* Discard timer SERR# enable */

typedef struct PCIBridgeQemuCap {
    uint8_t id;     /* Standard PCI capability header field */
    uint8_t next;   /* Standard PCI capability header field */
    uint8_t len;    /* Standard PCI vendor-specific capability header field */
    uint8_t type;   /* Red Hat vendor-specific capability type.
                       Types are defined with REDHAT_PCI_CAP_ prefix */

    uint32_t bus_res;   /* Minimum number of buses to reserve */
    uint64_t io;        /* IO space to reserve */
    uint32_t mem;       /* Non-prefetchable memory to reserve */
    /* At most one of the following two fields may be set to a value
     * different from -1 */
    uint32_t mem_pref_32; /* Prefetchable memory to reserve (32-bit MMIO) */
    uint64_t mem_pref_64; /* Prefetchable memory to reserve (64-bit MMIO) */
} PCIBridgeQemuCap;

#define REDHAT_PCI_CAP_TYPE_OFFSET      3
#define REDHAT_PCI_CAP_RESOURCE_RESERVE 1

/*
 * PCI BUS/IO/MEM/PREFMEM additional resources recorded as a
 * capability in PCI configuration space to reserve on firmware init.
 */
typedef struct PCIResReserve {
    uint32_t bus;
    uint64_t io;
    uint64_t mem_non_pref;
    uint64_t mem_pref_32;
    uint64_t mem_pref_64;
} PCIResReserve;

#define REDHAT_PCI_CAP_RES_RESERVE_BUS_RES     4
#define REDHAT_PCI_CAP_RES_RESERVE_IO          8
#define REDHAT_PCI_CAP_RES_RESERVE_MEM         16
#define REDHAT_PCI_CAP_RES_RESERVE_PREF_MEM_32 20
#define REDHAT_PCI_CAP_RES_RESERVE_PREF_MEM_64 24
#define REDHAT_PCI_CAP_RES_RESERVE_CAP_SIZE    32

int pci_bridge_qemu_reserve_cap_init(PCIDevice *dev, int cap_offset,
                               PCIResReserve res_reserve, Error **errp);

#endif /* QEMU_PCI_BRIDGE_H */