]> rtime.felk.cvut.cz Git - jailhouse.git/blob - hypervisor/pci.c
x86: Add handler of accesses to PCI configuration space via I/O ports
[jailhouse.git] / hypervisor / pci.c
1 /*
2  * Jailhouse, a Linux-based partitioning hypervisor
3  *
4  * Copyright (c) Siemens AG, 2014
5  *
6  * Authors:
7  *  Ivan Kolchin <ivan.kolchin@siemens.com>
8  *
9  * This work is licensed under the terms of the GNU GPL, version 2.  See
10  * the COPYING file in the top-level directory.
11  */
12
13 #include <jailhouse/pci.h>
14 #include <jailhouse/utils.h>
15
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 */
20 };
21
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 */
28 };
29 /* Type 2: Bridges */
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 */
34 };
35
36 /**
37  * pci_get_assigned_device() - Look up device owned by a cell
38  * @cell:       Owning cell
39  * @bdf:        16-bit bus/device/function ID
40  *
41  * Return: Valid pointer - owns, NULL - doesn't own.
42  */
43 const struct jailhouse_pci_device *
44 pci_get_assigned_device(const struct cell *cell, u16 bdf)
45 {
46         const struct jailhouse_pci_device *device =
47                 jailhouse_cell_pci_devices(cell->config);
48         u32 n;
49
50         for (n = 0; n < cell->config->num_pci_devices; n++)
51                 if (((device[n].bus << 8) | device[n].devfn) == bdf)
52                         return &device[n];
53
54         return NULL;
55 }
56
57 /**
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)
63  *
64  * Return: True if writing is allowed, false otherwise.
65  */
66 bool pci_cfg_write_allowed(u32 type, u8 reg_num, unsigned int reg_bias,
67                            unsigned int size)
68 {
69         /* initialize list to work around wrong compiler warning */
70         const struct pci_cfg_access *list = NULL;
71         unsigned int n, len = 0;
72
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);
79         }
80
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);
85
86         return false;
87 }