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 #include <jailhouse/control.h>
15 #include <jailhouse/mmio.h>
16 #include <jailhouse/pci.h>
17 #include <jailhouse/printk.h>
18 #include <jailhouse/utils.h>
20 #define PCI_CONFIG_HEADER_SIZE 0x40
22 #define PCI_CAP_MSI 0x05
23 #define PCI_CAP_MSIX 0x11
25 #define for_each_configured_pci_device(dev, cell) \
26 for ((dev) = (cell)->pci_devices; \
27 (dev) - (cell)->pci_devices < (cell)->config->num_pci_devices; \
30 #define for_each_pci_cap(cap, dev, counter) \
31 for ((cap) = jailhouse_cell_pci_caps((dev)->cell->config) + \
32 (dev)->info->caps_start, (counter) = 0; \
33 (counter) < (dev)->info->num_caps; \
36 /* entry for PCI config space whitelist (granting access) */
37 struct pci_cfg_access {
38 u32 reg_num; /** Register number (4-byte aligned) */
39 u32 mask; /** Bit set: access allowed */
42 /* --- Whilelist for writing to PCI config space registers --- */
43 /* Type 1: Endpoints */
44 static const struct pci_cfg_access endpoint_write_access[] = {
45 { 0x04, 0xffffffff }, /* Command, Status */
46 { 0x0c, 0xff00ffff }, /* BIST, Latency Timer, Cacheline */
47 { 0x3c, 0x000000ff }, /* Int Line */
50 static const struct pci_cfg_access bridge_write_access[] = {
51 { 0x04, 0xffffffff }, /* Command, Status */
52 { 0x0c, 0xff00ffff }, /* BIST, Latency Timer, Cacheline */
53 { 0x3c, 0xffff00ff }, /* Int Line, Bridge Control */
56 static void *pci_space;
57 static u64 mmcfg_start, mmcfg_end;
60 static void *pci_get_device_mmcfg_base(u16 bdf)
62 return pci_space + ((unsigned long)bdf << 12);
66 * pci_read_config() - Read from PCI config space
67 * @bdf: 16-bit bus/device/function ID of target
68 * @address: Config space access address
69 * @size: Access size (1, 2 or 4 bytes)
73 u32 pci_read_config(u16 bdf, u16 address, unsigned int size)
75 void *mmcfg_addr = pci_get_device_mmcfg_base(bdf) + address;
77 if (!pci_space || PCI_BUS(bdf) > end_bus)
78 return arch_pci_read_config(bdf, address, size);
81 return mmio_read8(mmcfg_addr);
83 return mmio_read16(mmcfg_addr);
85 return mmio_read32(mmcfg_addr);
89 * pci_write_config() - Write to PCI config space
90 * @bdf: 16-bit bus/device/function ID of target
91 * @address: Config space access address
92 * @value: Value to be written
93 * @size: Access size (1, 2 or 4 bytes)
95 void pci_write_config(u16 bdf, u16 address, u32 value, unsigned int size)
97 void *mmcfg_addr = pci_get_device_mmcfg_base(bdf) + address;
99 if (!pci_space || PCI_BUS(bdf) > end_bus)
100 return arch_pci_write_config(bdf, address, value, size);
103 mmio_write8(mmcfg_addr, value);
105 mmio_write16(mmcfg_addr, value);
107 mmio_write32(mmcfg_addr, value);
111 * pci_get_assigned_device() - Look up device owned by a cell
113 * @bdf: 16-bit bus/device/function ID
115 * Return: Pointer to owned PCI device or NULL.
117 struct pci_device *pci_get_assigned_device(const struct cell *cell, u16 bdf)
119 const struct jailhouse_pci_device *dev_info =
120 jailhouse_cell_pci_devices(cell->config);
123 /* We iterate over the static device information to increase cache
125 for (n = 0; n < cell->config->num_pci_devices; n++)
126 if (dev_info[n].bdf == bdf)
127 return cell->pci_devices[n].cell ?
128 &cell->pci_devices[n] : NULL;
134 * pci_find_capability() - Look up capability at given config space address
135 * @device: The device to be accessed
136 * @address: Config space access address
138 * Return: Corresponding capability structure or NULL if none found.
140 static const struct jailhouse_pci_capability *
141 pci_find_capability(struct pci_device *device, u16 address)
143 const struct jailhouse_pci_capability *cap =
144 jailhouse_cell_pci_caps(device->cell->config) +
145 device->info->caps_start;
148 for (n = 0; n < device->info->num_caps; n++, cap++)
149 if (cap->start <= address && cap->start + cap->len > address)
156 * pci_cfg_read_moderate() - Moderate config space read access
157 * @device: The device to be accessed; if NULL, access will be emulated,
158 * returning a value of -1
159 * @address: Config space address
160 * @size: Access size (1, 2 or 4 bytes)
161 * @value: Pointer to buffer to receive the emulated value if
162 * PCI_ACCESS_DONE is returned
164 * Return: PCI_ACCESS_PERFORM or PCI_ACCESS_DONE.
166 enum pci_access pci_cfg_read_moderate(struct pci_device *device, u16 address,
167 unsigned int size, u32 *value)
169 const struct jailhouse_pci_capability *cap;
170 unsigned int cap_offs;
174 return PCI_ACCESS_DONE;
177 if (address < PCI_CONFIG_HEADER_SIZE)
178 return PCI_ACCESS_PERFORM;
180 cap = pci_find_capability(device, address);
182 return PCI_ACCESS_PERFORM;
184 cap_offs = address - cap->start;
185 if (cap->id == PCI_CAP_MSI && cap_offs >= 4 &&
186 (cap_offs < 10 || (device->info->msi_64bits && cap_offs < 14))) {
187 *value = device->msi_registers.raw[cap_offs / 4] >>
188 ((cap_offs % 4) * 8);
189 return PCI_ACCESS_DONE;
192 return PCI_ACCESS_PERFORM;
196 * pci_cfg_write_moderate() - Moderate config space write access
197 * @device: The device to be accessed; if NULL, access will be rejected
198 * @address: Config space address
199 * @size: Access size (1, 2 or 4 bytes)
200 * @value: Value to be written
202 * Return: PCI_ACCESS_REJECT, PCI_ACCESS_PERFORM or PCI_ACCESS_DONE.
204 enum pci_access pci_cfg_write_moderate(struct pci_device *device, u16 address,
205 unsigned int size, u32 value)
207 const struct jailhouse_pci_capability *cap;
208 /* initialize list to work around wrong compiler warning */
209 const struct pci_cfg_access *list = NULL;
210 unsigned int bias_shift = (address % 4) * 8;
211 unsigned int n, cap_offs, len = 0;
212 u32 mask = BYTE_MASK(size);
215 return PCI_ACCESS_REJECT;
217 if (address < PCI_CONFIG_HEADER_SIZE) {
218 if (device->info->type == JAILHOUSE_PCI_TYPE_DEVICE) {
219 list = endpoint_write_access;
220 len = ARRAY_SIZE(endpoint_write_access);
221 } else if (device->info->type == JAILHOUSE_PCI_TYPE_BRIDGE) {
222 list = bridge_write_access;
223 len = ARRAY_SIZE(bridge_write_access);
226 for (n = 0; n < len; n++) {
227 if (list[n].reg_num == (address & 0xffc) &&
228 ((list[n].mask >> bias_shift) & mask) == mask)
229 return PCI_ACCESS_PERFORM;
232 return PCI_ACCESS_REJECT;
235 cap = pci_find_capability(device, address);
236 if (!cap || !(cap->flags & JAILHOUSE_PCICAPS_WRITE))
237 return PCI_ACCESS_REJECT;
239 cap_offs = address - cap->start;
240 if (cap->id == PCI_CAP_MSI &&
241 (cap_offs < 10 || (device->info->msi_64bits && cap_offs < 14))) {
242 value <<= bias_shift;
244 device->msi_registers.raw[cap_offs / 4] &= ~mask;
245 device->msi_registers.raw[cap_offs / 4] |= value;
247 if (pci_update_msi(device, cap) < 0)
248 return PCI_ACCESS_REJECT;
251 * Address and data words are emulated, the control word is
255 return PCI_ACCESS_DONE;
258 return PCI_ACCESS_PERFORM;
262 * pci_init() - Initialization of PCI module
264 * Return: 0 - success, error code - if error.
268 unsigned int mmcfg_size;
271 err = pci_cell_init(&root_cell);
275 mmcfg_start = system_config->platform_info.x86.mmconfig_base;
276 if (mmcfg_start == 0)
279 end_bus = system_config->platform_info.x86.mmconfig_end_bus;
280 mmcfg_size = (end_bus + 1) * 256 * 4096;
281 mmcfg_end = mmcfg_start + mmcfg_size - 4;
283 pci_space = page_alloc(&remap_pool, mmcfg_size / PAGE_SIZE);
287 return page_map_create(&hv_paging_structs, mmcfg_start, mmcfg_size,
288 (unsigned long)pci_space,
289 PAGE_DEFAULT_FLAGS | PAGE_FLAG_UNCACHED,
290 PAGE_MAP_NON_COHERENT);
294 * pci_mmio_access_handler() - Handler for MMIO-accesses to PCI config space
295 * @cell: Request issuing cell
296 * @is_write: True if write access
297 * @addr: Address accessed
298 * @value: Pointer to value for reading/writing
300 * Return: 1 if handled successfully, 0 if unhandled, -1 on access error
302 int pci_mmio_access_handler(const struct cell *cell, bool is_write,
303 u64 addr, u32 *value)
305 u32 mmcfg_offset, reg_addr;
306 struct pci_device *device;
307 enum pci_access access;
309 if (!pci_space || addr < mmcfg_start || addr > mmcfg_end)
312 mmcfg_offset = addr - mmcfg_start;
313 reg_addr = mmcfg_offset & 0xfff;
314 /* access must be DWORD-aligned */
318 device = pci_get_assigned_device(cell, mmcfg_offset >> 12);
321 access = pci_cfg_write_moderate(device, reg_addr, 4, *value);
322 if (access == PCI_ACCESS_REJECT)
324 if (access == PCI_ACCESS_PERFORM)
325 mmio_write32(pci_space + mmcfg_offset, *value);
327 access = pci_cfg_read_moderate(device, reg_addr, 4, value);
328 if (access == PCI_ACCESS_PERFORM)
329 *value = mmio_read32(pci_space + mmcfg_offset);
335 panic_printk("FATAL: Invalid PCI MMCONFIG write, device %02x:%02x.%x, "
336 "reg: %\n", PCI_BDF_PARAMS(mmcfg_offset >> 12), reg_addr);
341 unsigned int pci_enabled_msi_vectors(struct pci_device *device)
343 return device->msi_registers.msg32.enable ?
344 1 << device->msi_registers.msg32.mme : 0;
347 static void pci_save_msi(struct pci_device *device,
348 const struct jailhouse_pci_capability *cap)
350 u16 bdf = device->info->bdf;
353 for (n = 0; n < (device->info->msi_64bits ? 4 : 3); n++)
354 device->msi_registers.raw[n] =
355 pci_read_config(bdf, cap->start + n * 4, 4);
358 static void pci_restore_msi(struct pci_device *device,
359 const struct jailhouse_pci_capability *cap)
363 for (n = 1; n < (device->info->msi_64bits ? 4 : 3); n++)
364 pci_write_config(device->info->bdf, cap->start + n * 4,
365 device->msi_registers.raw[n], 4);
369 * pci_prepare_handover() - Prepare the handover of PCI devices to Jailhouse or
372 void pci_prepare_handover(void)
374 const struct jailhouse_pci_capability *cap;
375 struct pci_device *device;
378 if (!root_cell.pci_devices)
381 for_each_configured_pci_device(device, &root_cell) {
383 for_each_pci_cap(cap, device, n)
384 if (cap->id == PCI_CAP_MSI)
385 pci_suppress_msi(device, cap);
390 static int pci_add_device(struct cell *cell, struct pci_device *device)
392 printk("Adding PCI device %02x:%02x.%x to cell \"%s\"\n",
393 PCI_BDF_PARAMS(device->info->bdf), cell->config->name);
394 return arch_pci_add_device(cell, device);
397 static void pci_remove_device(struct pci_device *device)
399 printk("Removing PCI device %02x:%02x.%x from cell \"%s\"\n",
400 PCI_BDF_PARAMS(device->info->bdf), device->cell->config->name);
401 arch_pci_remove_device(device);
402 pci_write_config(device->info->bdf, PCI_CFG_COMMAND,
403 PCI_CMD_INTX_OFF, 2);
406 int pci_cell_init(struct cell *cell)
408 unsigned long array_size = PAGE_ALIGN(cell->config->num_pci_devices *
409 sizeof(struct pci_device));
410 const struct jailhouse_pci_device *dev_infos =
411 jailhouse_cell_pci_devices(cell->config);
412 const struct jailhouse_pci_capability *cap;
413 struct pci_device *device, *root_device;
414 unsigned int ndev, ncap;
417 cell->pci_devices = page_alloc(&mem_pool, array_size / PAGE_SIZE);
418 if (!cell->pci_devices)
422 * We order device states in the same way as the static information
423 * so that we can use the index of the latter to find the former. For
424 * the other way around and for obtaining the owner cell, we use more
425 * handy pointers. The cell pointer also encodes active ownership.
427 for (ndev = 0; ndev < cell->config->num_pci_devices; ndev++) {
428 device = &cell->pci_devices[ndev];
429 device->info = &dev_infos[ndev];
431 root_device = pci_get_assigned_device(&root_cell,
432 dev_infos[ndev].bdf);
434 pci_remove_device(root_device);
435 root_device->cell = NULL;
438 err = pci_add_device(cell, device);
446 for_each_pci_cap(cap, device, ncap)
447 if (cap->id == PCI_CAP_MSI)
448 pci_save_msi(device, cap);
449 else if (cap->id == PCI_CAP_MSIX)
451 printk("MSI-X left out @%02x:%02x.%x!\n",
452 PCI_BDF_PARAMS(device->info->bdf));
455 if (cell == &root_cell)
456 pci_prepare_handover();
461 static void pci_return_device_to_root_cell(struct pci_device *device)
463 struct pci_device *root_device;
465 for_each_configured_pci_device(root_device, &root_cell)
466 if (root_device->info->domain == device->info->domain &&
467 root_device->info->bdf == device->info->bdf) {
468 if (pci_add_device(&root_cell, root_device) < 0)
469 printk("WARNING: Failed to re-assign PCI "
470 "device to root cell\n");
472 root_device->cell = &root_cell;
477 void pci_cell_exit(struct cell *cell)
479 unsigned long array_size = PAGE_ALIGN(cell->config->num_pci_devices *
480 sizeof(struct pci_device));
481 struct pci_device *device;
484 * Do not destroy the root cell. We will shut down the complete
485 * hypervisor instead.
487 if (cell == &root_cell)
490 for_each_configured_pci_device(device, cell)
492 pci_remove_device(device);
493 pci_return_device_to_root_cell(device);
496 page_free(&mem_pool, cell->pci_devices, array_size / PAGE_SIZE);
499 void pci_config_commit(struct cell *cell_added_removed)
501 const struct jailhouse_pci_capability *cap;
502 struct pci_device *device;
506 if (!cell_added_removed)
509 for_each_configured_pci_device(device, &root_cell)
511 for_each_pci_cap(cap, device, n) {
512 if (cap->id == PCI_CAP_MSI)
513 err = pci_update_msi(device, cap);
521 panic_printk("FATAL: Unsupported MSI/MSI-X state, device %02x:%02x.%x,"
522 " cap %d\n", PCI_BDF_PARAMS(device->info->bdf), cap->id);
526 void pci_shutdown(void)
528 const struct jailhouse_pci_capability *cap;
529 struct pci_device *device;
532 if (!root_cell.pci_devices)
535 for_each_configured_pci_device(device, &root_cell)
537 for_each_pci_cap(cap, device, n)
538 if (cap->id == PCI_CAP_MSI)
539 pci_restore_msi(device, cap);