2 * Jailhouse, a Linux-based partitioning hypervisor
4 * Copyright (c) Siemens AG, 2014
7 * Ivan Kolchin <ivan.kolchin@siemens.com>
9 * This work is licensed under the terms of the GNU GPL, version 2. See
10 * the COPYING file in the top-level directory.
13 #include <jailhouse/pci.h>
14 #include <jailhouse/utils.h>
16 /* entry for PCI config space whitelist (granting access) */
17 struct pci_cfg_access {
18 u32 reg_num; /** Register number (4-byte aligned) */
19 u32 mask; /** Bit set: access allowed */
22 /* --- Whilelist for writing to PCI config space registers --- */
23 /* Type 1: Endpoints */
24 static const struct pci_cfg_access endpoint_write_access[] = {
25 { 0x04, 0xffffffff }, /* Command, Status */
26 { 0x0c, 0xff000000 }, /* BIST */
27 { 0x3c, 0x000000ff }, /* Int Line */
30 static const struct pci_cfg_access bridge_write_access[] = {
31 { 0x04, 0xffffffff }, /* Command, Status */
32 { 0x0c, 0xff000000 }, /* BIST */
33 { 0x3c, 0xffff00ff }, /* Int Line, Bridge Control */
37 * pci_get_assigned_device() - Look up device owned by a cell
39 * @bdf: 16-bit bus/device/function ID
41 * Return: Valid pointer - owns, NULL - doesn't own.
43 const struct jailhouse_pci_device *
44 pci_get_assigned_device(const struct cell *cell, u16 bdf)
46 const struct jailhouse_pci_device *device =
47 jailhouse_cell_pci_devices(cell->config);
50 for (n = 0; n < cell->config->num_pci_devices; n++)
51 if (((device[n].bus << 8) | device[n].devfn) == bdf)
58 * pci_cfg_write_allowed() - Check general config space write permission
59 * @type: JAILHOUSE_PCI_TYPE_DEVICE or JAILHOUSE_PCI_TYPE_BRIDGE
60 * @reg_num: Register number (4-byte aligned)
61 * @bias: Bias from register base address in bytes
62 * @size: Access size (1, 2 or 4 bytes)
64 * Return: True if writing is allowed, false otherwise.
66 bool pci_cfg_write_allowed(u32 type, u8 reg_num, unsigned int reg_bias,
69 /* initialize list to work around wrong compiler warning */
70 const struct pci_cfg_access *list = NULL;
71 unsigned int n, len = 0;
73 if (type == JAILHOUSE_PCI_TYPE_DEVICE) {
74 list = endpoint_write_access;
75 len = ARRAY_SIZE(endpoint_write_access);
76 } else if (type == JAILHOUSE_PCI_TYPE_BRIDGE) {
77 list = bridge_write_access;
78 len = ARRAY_SIZE(bridge_write_access);
81 for (n = 0; n < len; n++)
82 if (list[n].reg_num == reg_num)
83 return ((list[n].mask >> (reg_bias * 8)) &
84 BYTE_MASK(size)) == BYTE_MASK(size);