2 * Jailhouse, a Linux-based partitioning hypervisor
4 * Copyright (c) Siemens AG, 2014
7 * Ivan Kolchin <ivan.kolchin@siemens.com>
8 * Jan Kiszka <jan.kiszka@siemens.com>
10 * This work is licensed under the terms of the GNU GPL, version 2. See
11 * the COPYING file in the top-level directory.
14 #ifndef _JAILHOUSE_PCI_H
15 #define _JAILHOUSE_PCI_H
19 #define PCI_CFG_COMMAND 0x04
20 # define PCI_CMD_MEM (1 << 1)
21 # define PCI_CMD_MASTER (1 << 2)
22 # define PCI_CMD_INTX_OFF (1 << 10)
23 #define PCI_CFG_STATUS 0x06
24 # define PCI_STS_CAPS (1 << 4)
25 #define PCI_CFG_BAR 0x10
26 # define PCI_BAR_64BIT 0x4
27 #define PCI_CFG_BAR_END 0x27
28 #define PCI_CFG_ROMBAR 0x30
29 #define PCI_CFG_CAPS 0x34
30 #define PCI_CFG_INT 0x3c
32 #define PCI_CONFIG_HEADER_SIZE 0x40
34 #define PCI_NUM_BARS 6
36 #define PCI_DEV_CLASS_MEM 0x05
38 #define PCI_CAP_MSI 0x05
39 #define PCI_CAP_MSIX 0x11
42 * @defgroup PCI PCI Subsystem
44 * The PCI subsystem provides access to PCI resources for the hypervisor and
45 * manages the cell's access to device configuration spaces and MSI-X tables.
46 * The subsystem depends on IOMMU services to configure DMA and interrupt
52 /** Extract PCI bus from BDF form. */
53 #define PCI_BUS(bdf) ((bdf) >> 8)
54 /** Extract PCI device/function from BDF form. */
55 #define PCI_DEVFN(bdf) ((bdf) & 0xff)
56 /** Extract PCI bus, device and function as parameter list from BDF form. */
57 #define PCI_BDF_PARAMS(bdf) (bdf) >> 8, ((bdf) >> 3) & 0x1f, (bdf) & 7
59 /** MSI-X vectors supported per device without extra allocation. */
60 #define PCI_EMBEDDED_MSIX_VECTS 16
63 * Access moderation return codes.
64 * See pci_cfg_read_moderate() and pci_cfg_write_moderate().
66 enum pci_access { PCI_ACCESS_REJECT, PCI_ACCESS_PERFORM, PCI_ACCESS_DONE };
68 /** MSI config space registers. See PCI specification. */
69 union pci_msi_registers {
70 /** @privatesection */
79 } __attribute__((packed)) msg32;
81 u32 padding; /* use msg32 */
84 } __attribute__((packed)) msg64;
87 } __attribute__((packed));
89 /** MSI-X config space registers. See PCI specification. */
90 union pci_msix_registers {
91 /** @privatesection */
97 } __attribute__((packed));
100 } __attribute__((packed));
102 /** MSI-X table entry. See PCI specification. */
103 union pci_msix_vector {
104 /** @privatesection */
110 } __attribute__((packed));
112 /** @publicsection */
113 } __attribute__((packed));
115 struct pci_ivshmem_endpoint;
121 /** Reference to static device configuration. */
122 const struct jailhouse_pci_device *info;
126 u32 bar[PCI_NUM_BARS];
128 /** Shadow state of MSI config space registers. */
129 union pci_msi_registers msi_registers;
131 /** Shadow state of MSI-X config space registers. */
132 union pci_msix_registers msix_registers;
133 /** Next PCI device in this cell with MSI-X support. */
134 struct pci_device *next_msix_device;
135 /** Next virtual PCI device in this cell. */
136 struct pci_device *next_virtual_device;
137 /** ivshmem specific data. */
138 struct pci_ivshmem_endpoint *ivshmem_endpoint;
139 /** Real MSI-X table. */
140 union pci_msix_vector *msix_table;
141 /** Shadow state of MSI-X table. */
142 union pci_msix_vector *msix_vectors;
143 /** Buffer for shadow table of up to PCI_EMBEDDED_MSIX_VECTS vectors. */
144 union pci_msix_vector msix_vector_array[PCI_EMBEDDED_MSIX_VECTS];
149 u32 pci_read_config(u16 bdf, u16 address, unsigned int size);
150 void pci_write_config(u16 bdf, u16 address, u32 value, unsigned int size);
152 struct pci_device *pci_get_assigned_device(const struct cell *cell, u16 bdf);
154 enum pci_access pci_cfg_read_moderate(struct pci_device *device, u16 address,
155 unsigned int size, u32 *value);
156 enum pci_access pci_cfg_write_moderate(struct pci_device *device, u16 address,
157 unsigned int size, u32 value);
159 int pci_mmio_access_handler(const struct cell *cell, bool is_write, u64 addr,
162 int pci_cell_init(struct cell *cell);
163 void pci_cell_exit(struct cell *cell);
165 void pci_config_commit(struct cell *cell_added_removed);
167 unsigned int pci_enabled_msi_vectors(struct pci_device *device);
169 void pci_prepare_handover(void);
170 void pci_shutdown(void);
173 * Read from PCI config space via architecture-specific method.
174 * @param bdf 16-bit bus/device/function ID of target.
175 * @param address Config space access address.
176 * @param size Access size (1, 2 or 4 bytes).
178 * @return Read value.
180 * @see pci_read_config
181 * @see arch_pci_write_config
183 u32 arch_pci_read_config(u16 bdf, u16 address, unsigned int size);
186 * Write to PCI config space via architecture-specific method.
187 * @param bdf 16-bit bus/device/function ID of target.
188 * @param address Config space access address.
189 * @param value Value to be written.
190 * @param size Access size (1, 2 or 4 bytes).
192 * @see pci_write_config
193 * @see arch_pci_read_config
195 void arch_pci_write_config(u16 bdf, u16 address, u32 value, unsigned int size);
198 * Perform architecture-specific steps on physical PCI device addition.
199 * @param cell Cell to which the device is added.
200 * @param device Device to be added.
202 * @return 0 on success, negative error code otherwise.
204 * @see arch_pci_remove_physical_device
206 int arch_pci_add_physical_device(struct cell *cell, struct pci_device *device);
209 * Perform architecture-specific steps on physical PCI device removal.
210 * @param device Device to be removed.
212 * @see arch_pci_add_physical_device
214 void arch_pci_remove_physical_device(struct pci_device *device);
217 * Avoid MSI vector delivery of a given device.
218 * @param device Device to be silenced.
219 * @param cap MSI capability of the device.
221 void arch_pci_suppress_msi(struct pci_device *device,
222 const struct jailhouse_pci_capability *cap);
225 * Update MSI vector mapping for a given device.
226 * @param device Device to be updated.
227 * @param cap MSI capability of the device.
229 * @return 0 on success, negative error code otherwise.
231 * @see arch_pci_update_msix_vector
233 int arch_pci_update_msi(struct pci_device *device,
234 const struct jailhouse_pci_capability *cap);
237 * Update MSI-X vector mapping for a given device and vector.
238 * @param device Device to be updated.
239 * @param index MSI-X vector number.
241 * @return 0 on success, negative error code otherwise.
243 * @see arch_pci_update_msi
245 int arch_pci_update_msix_vector(struct pci_device *device, unsigned int index);
248 * @defgroup PCI-IVSHMEM ivshmem
251 int pci_ivshmem_init(struct cell *cell, struct pci_device *device);
252 void pci_ivshmem_exit(struct pci_device *device);
253 int pci_ivshmem_update_msix(struct pci_device *device);
254 enum pci_access pci_ivshmem_cfg_write(struct pci_device *device,
255 unsigned int row, u32 mask, u32 value);
256 enum pci_access pci_ivshmem_cfg_read(struct pci_device *device, u16 address,
258 int ivshmem_mmio_access_handler(const struct cell *cell, bool is_write,
259 u64 addr, u32 *value);
260 /** @} PCI-IVSHMEM */
262 #endif /* !_JAILHOUSE_PCI_H */