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
206
207
208
209
210
211
212
|
/*
* Copyright (c) 2019 Nutanix Inc. All rights reserved.
*
* Authors: Thanos Makatos <thanos@nutanix.com>
* Swapnil Ingle <swapnil.ingle@nutanix.com>
* Felipe Franciosi <felipe@nutanix.com>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of Nutanix nor the names of its contributors may be
* used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
*
*/
#ifndef LIBVFIO_USER_PCI_H
#define LIBVFIO_USER_PCI_H
#include <stdint.h>
#include <stdbool.h>
#include <linux/pci_regs.h>
#ifdef __cplusplus
extern "C" {
#endif
/*
* These are already defined in include/uapi/linux/pci_regs.h, however that
* file doesn't seem to installed.
*/
#define PCI_CFG_SPACE_SIZE 256
#define PCI_CFG_SPACE_EXP_SIZE 4096
/*
* TODO lots of the sizes of each member are defined in pci_regs.h, use those
* instead?
*/
typedef union {
uint32_t raw;
struct {
uint16_t vid;
uint16_t sid;
} __attribute__ ((packed));
} __attribute__ ((packed)) vfu_pci_hdr_ss_t;
_Static_assert(sizeof(vfu_pci_hdr_ss_t) == 0x4, "bad SS size");
typedef union {
uint8_t raw;
} __attribute__ ((packed)) vfu_pci_hdr_bist_t;
_Static_assert(sizeof(vfu_pci_hdr_bist_t) == 0x1, "bad BIST size");
typedef union {
uint32_t raw;
union {
struct {
unsigned int region_type:1;
unsigned int locatable:2;
unsigned int prefetchable:1;
unsigned int base_address:28;
} __attribute__ ((packed)) mem;
struct {
unsigned int region_type:1;
unsigned int reserved:1;
unsigned int base_address:30;
} __attribute__ ((packed)) io;
} __attribute__ ((packed));
} __attribute__ ((packed)) vfu_bar_t;
_Static_assert(sizeof(vfu_bar_t) == 0x4, "bad BAR size");
typedef union {
uint8_t raw;
} __attribute__ ((packed)) vfu_pci_hdr_htype_t;
_Static_assert(sizeof(vfu_pci_hdr_htype_t) == 0x1, "bad HTYPE size");
typedef union {
uint8_t raw[3];
struct {
uint8_t pi;
uint8_t scc;
uint8_t bcc;
} __attribute__ ((packed));
} __attribute__ ((packed)) vfu_pci_hdr_cc_t;
_Static_assert(sizeof(vfu_pci_hdr_cc_t) == 0x3, "bad CC size");
/* device status */
typedef union {
uint16_t raw;
struct {
unsigned int res1:3;
unsigned int is:1;
unsigned int cl:1;
unsigned int c66:1;
unsigned int res2:1;
unsigned int fbc:1;
unsigned int dpd:1;
unsigned int devt:2;
unsigned int sta:1;
unsigned int rta:1;
unsigned int rma:1;
unsigned int sse:1;
unsigned int dpe:1;
} __attribute__ ((packed));
} __attribute__ ((packed)) vfu_pci_hdr_sts_t;
_Static_assert(sizeof(vfu_pci_hdr_sts_t) == 0x2, "bad STS size");
typedef union {
uint16_t raw;
struct {
uint8_t iose:1;
uint8_t mse:1;
uint8_t bme:1;
uint8_t sce:1;
uint8_t mwie:1;
uint8_t vga:1;
uint8_t pee:1;
uint8_t zero:1;
uint8_t see:1;
uint8_t fbe:1;
uint8_t id:1;
uint8_t res1:5;
} __attribute__ ((packed));
} __attribute__ ((packed)) vfu_pci_hdr_cmd_t;
_Static_assert(sizeof(vfu_pci_hdr_cmd_t) == 0x2, "bad CMD size");
typedef union {
uint32_t raw;
struct {
uint16_t vid;
uint16_t did;
} __attribute__ ((packed));
} __attribute__ ((packed)) vfu_pci_hdr_id_t;
_Static_assert(sizeof(vfu_pci_hdr_id_t) == 0x4, "bad ID size");
typedef union {
uint16_t raw;
struct {
uint8_t iline;
uint8_t ipin;
} __attribute__ ((packed));
} __attribute__ ((packed)) vfu_pci_hdr_intr_t;
_Static_assert(sizeof(vfu_pci_hdr_intr_t) == 0x2, "bad INTR size");
typedef union {
uint8_t raw[PCI_STD_HEADER_SIZEOF];
struct {
vfu_pci_hdr_id_t id;
vfu_pci_hdr_cmd_t cmd;
vfu_pci_hdr_sts_t sts;
uint8_t rid;
vfu_pci_hdr_cc_t cc;
uint8_t cls;
uint8_t mlt;
vfu_pci_hdr_htype_t htype;
vfu_pci_hdr_bist_t bist;
#define PCI_BARS_NR 6
vfu_bar_t bars[PCI_BARS_NR];
uint32_t ccptr;
vfu_pci_hdr_ss_t ss;
uint32_t erom;
uint8_t cap;
uint8_t res1[7];
vfu_pci_hdr_intr_t intr;
uint8_t mgnt;
uint8_t mlat;
} __attribute__ ((packed));
} __attribute__ ((packed)) vfu_pci_hdr_t;
_Static_assert(sizeof(vfu_pci_hdr_t) == 0x40, "bad PCI header size");
typedef struct {
uint8_t raw[PCI_CFG_SPACE_SIZE - PCI_STD_HEADER_SIZEOF];
} __attribute__ ((packed)) vfu_pci_non_std_config_space_t;
_Static_assert(sizeof(vfu_pci_non_std_config_space_t) == 0xc0,
"bad non-standard PCI configuration space size");
typedef struct {
union {
uint8_t raw[PCI_CFG_SPACE_SIZE];
struct {
vfu_pci_hdr_t hdr;
vfu_pci_non_std_config_space_t non_std;
} __attribute__ ((packed));
} __attribute__ ((packed));
uint8_t extended[];
} __attribute__ ((packed)) vfu_pci_config_space_t;
_Static_assert(sizeof(vfu_pci_config_space_t) == 0x100,
"bad PCI configuration space size");
#ifdef __cplusplus
}
#endif
#endif /* LIBVFIO_USER_PCI_H */
/* ex: set tabstop=4 shiftwidth=4 softtabstop=4 expandtab: */
|