160742802SPekka Enberg #ifndef KVM__PCI_H
260742802SPekka Enberg #define KVM__PCI_H
360742802SPekka Enberg
43fdf659dSSasha Levin #include <linux/types.h>
51de74957SSasha Levin #include <linux/kvm.h>
620c64ecaSPekka Enberg #include <linux/pci_regs.h>
7*b0d56e3cSJean-Philippe Brucker #include <linux/virtio_pci.h>
8aa73be70SMatt Evans #include <endian.h>
92f6384f9SAlexandru Elisei #include <stdbool.h>
1076f9c841SCyrill Gorcunov
11b5981636SWill Deacon #include "kvm/devices.h"
12f7c17d7cSPekka Enberg #include "kvm/msi.h"
13ff01b5dbSJean-Philippe Brucker #include "kvm/fdt.h"
14e69b7663SAlexandru Elisei #include "kvm/kvm-arch.h"
15d0297a59SMatt Evans
16465edc9dSAlexandru Elisei #define pci_dev_err(pci_hdr, fmt, ...) \
1734bfe5f6SAlexandru Elisei pr_err("[%04x:%04x] " fmt, (pci_hdr)->vendor_id, (pci_hdr)->device_id, ##__VA_ARGS__)
18465edc9dSAlexandru Elisei #define pci_dev_warn(pci_hdr, fmt, ...) \
1934bfe5f6SAlexandru Elisei pr_warning("[%04x:%04x] " fmt, (pci_hdr)->vendor_id, (pci_hdr)->device_id, ##__VA_ARGS__)
20465edc9dSAlexandru Elisei #define pci_dev_info(pci_hdr, fmt, ...) \
2134bfe5f6SAlexandru Elisei pr_info("[%04x:%04x] " fmt, (pci_hdr)->vendor_id, (pci_hdr)->device_id, ##__VA_ARGS__)
22465edc9dSAlexandru Elisei #define pci_dev_dbg(pci_hdr, fmt, ...) \
2334bfe5f6SAlexandru Elisei pr_debug("[%04x:%04x] " fmt, (pci_hdr)->vendor_id, (pci_hdr)->device_id, ##__VA_ARGS__)
24465edc9dSAlexandru Elisei #define pci_dev_die(pci_hdr, fmt, ...) \
2534bfe5f6SAlexandru Elisei die("[%04x:%04x] " fmt, (pci_hdr)->vendor_id, (pci_hdr)->device_id, ##__VA_ARGS__)
26465edc9dSAlexandru Elisei
274402a581SPekka Enberg /*
284402a581SPekka Enberg * PCI Configuration Mechanism #1 I/O ports. See Section 3.7.4.1.
294402a581SPekka Enberg * ("Configuration Mechanism #1") of the PCI Local Bus Specification 2.1 for
304402a581SPekka Enberg * details.
314402a581SPekka Enberg */
32305b72ceSCyrill Gorcunov #define PCI_CONFIG_ADDRESS 0xcf8
33305b72ceSCyrill Gorcunov #define PCI_CONFIG_DATA 0xcfc
342b9e4709SCyrill Gorcunov #define PCI_CONFIG_BUS_FORWARD 0xcfa
3595d13a52SSasha Levin #define PCI_IO_SIZE 0x100
36854aa2efSJulien Thierry #define PCI_IOPORT_START 0x6200
37305b72ceSCyrill Gorcunov
386078a454SJean-Philippe Brucker struct kvm;
396078a454SJean-Philippe Brucker
40e69b7663SAlexandru Elisei /*
41e69b7663SAlexandru Elisei * On some distributions, pci_regs.h doesn't define PCI_CFG_SPACE_SIZE and
42e69b7663SAlexandru Elisei * PCI_CFG_SPACE_EXP_SIZE, so we define our own.
43e69b7663SAlexandru Elisei */
44e69b7663SAlexandru Elisei #define PCI_CFG_SIZE_LEGACY (1ULL << 24)
45e69b7663SAlexandru Elisei #define PCI_DEV_CFG_SIZE_LEGACY 256
46e69b7663SAlexandru Elisei #define PCI_CFG_SIZE_EXTENDED (1ULL << 28)
47e69b7663SAlexandru Elisei #define PCI_DEV_CFG_SIZE_EXTENDED 4096
48e69b7663SAlexandru Elisei
49e69b7663SAlexandru Elisei #ifdef ARCH_HAS_PCI_EXP
5025c1dc6cSAlexandru Elisei #define arch_has_pci_exp() (true)
5125c1dc6cSAlexandru Elisei
52e69b7663SAlexandru Elisei #define PCI_CFG_SIZE PCI_CFG_SIZE_EXTENDED
53e69b7663SAlexandru Elisei #define PCI_DEV_CFG_SIZE PCI_DEV_CFG_SIZE_EXTENDED
54e69b7663SAlexandru Elisei
55e69b7663SAlexandru Elisei union pci_config_address {
56e69b7663SAlexandru Elisei struct {
57e69b7663SAlexandru Elisei #if __BYTE_ORDER == __LITTLE_ENDIAN
58e69b7663SAlexandru Elisei unsigned reg_offset : 2; /* 1 .. 0 */
59e69b7663SAlexandru Elisei unsigned register_number : 10; /* 11 .. 2 */
60e69b7663SAlexandru Elisei unsigned function_number : 3; /* 14 .. 12 */
61e69b7663SAlexandru Elisei unsigned device_number : 5; /* 19 .. 15 */
62e69b7663SAlexandru Elisei unsigned bus_number : 8; /* 27 .. 20 */
63e69b7663SAlexandru Elisei unsigned reserved : 3; /* 30 .. 28 */
64e69b7663SAlexandru Elisei unsigned enable_bit : 1; /* 31 */
65e69b7663SAlexandru Elisei #else
66e69b7663SAlexandru Elisei unsigned enable_bit : 1; /* 31 */
67e69b7663SAlexandru Elisei unsigned reserved : 3; /* 30 .. 28 */
68e69b7663SAlexandru Elisei unsigned bus_number : 8; /* 27 .. 20 */
69e69b7663SAlexandru Elisei unsigned device_number : 5; /* 19 .. 15 */
70e69b7663SAlexandru Elisei unsigned function_number : 3; /* 14 .. 12 */
71e69b7663SAlexandru Elisei unsigned register_number : 10; /* 11 .. 2 */
72e69b7663SAlexandru Elisei unsigned reg_offset : 2; /* 1 .. 0 */
73e69b7663SAlexandru Elisei #endif
74e69b7663SAlexandru Elisei };
75e69b7663SAlexandru Elisei u32 w;
76e69b7663SAlexandru Elisei };
77e69b7663SAlexandru Elisei
78e69b7663SAlexandru Elisei #else
7925c1dc6cSAlexandru Elisei #define arch_has_pci_exp() (false)
8025c1dc6cSAlexandru Elisei
81e69b7663SAlexandru Elisei #define PCI_CFG_SIZE PCI_CFG_SIZE_LEGACY
82e69b7663SAlexandru Elisei #define PCI_DEV_CFG_SIZE PCI_DEV_CFG_SIZE_LEGACY
83e69b7663SAlexandru Elisei
84aa73be70SMatt Evans union pci_config_address {
85aa73be70SMatt Evans struct {
86aa73be70SMatt Evans #if __BYTE_ORDER == __LITTLE_ENDIAN
87d0297a59SMatt Evans unsigned reg_offset : 2; /* 1 .. 0 */
884402a581SPekka Enberg unsigned register_number : 6; /* 7 .. 2 */
894402a581SPekka Enberg unsigned function_number : 3; /* 10 .. 8 */
904402a581SPekka Enberg unsigned device_number : 5; /* 15 .. 11 */
914402a581SPekka Enberg unsigned bus_number : 8; /* 23 .. 16 */
924402a581SPekka Enberg unsigned reserved : 7; /* 30 .. 24 */
934402a581SPekka Enberg unsigned enable_bit : 1; /* 31 */
94aa73be70SMatt Evans #else
95aa73be70SMatt Evans unsigned enable_bit : 1; /* 31 */
96aa73be70SMatt Evans unsigned reserved : 7; /* 30 .. 24 */
97aa73be70SMatt Evans unsigned bus_number : 8; /* 23 .. 16 */
98aa73be70SMatt Evans unsigned device_number : 5; /* 15 .. 11 */
99aa73be70SMatt Evans unsigned function_number : 3; /* 10 .. 8 */
100aa73be70SMatt Evans unsigned register_number : 6; /* 7 .. 2 */
101d0297a59SMatt Evans unsigned reg_offset : 2; /* 1 .. 0 */
102aa73be70SMatt Evans #endif
103aa73be70SMatt Evans };
104aa73be70SMatt Evans u32 w;
1054402a581SPekka Enberg };
106e69b7663SAlexandru Elisei #endif /* ARCH_HAS_PCI_EXP */
107e69b7663SAlexandru Elisei
108e69b7663SAlexandru Elisei #define PCI_DEV_CFG_MASK (PCI_DEV_CFG_SIZE - 1)
1094402a581SPekka Enberg
110bc485053SSasha Levin struct msix_table {
1111de74957SSasha Levin struct msi_msg msg;
112bc485053SSasha Levin u32 ctrl;
113bc485053SSasha Levin };
114bc485053SSasha Levin
115bc485053SSasha Levin struct msix_cap {
116bc485053SSasha Levin u8 cap;
117bc485053SSasha Levin u8 next;
11806f48103SSasha Levin u16 ctrl;
119bc485053SSasha Levin u32 table_offset;
12006f48103SSasha Levin u32 pba_offset;
121bc485053SSasha Levin };
122bc485053SSasha Levin
1238dd28afeSJean-Philippe Brucker struct msi_cap_64 {
1248dd28afeSJean-Philippe Brucker u8 cap;
1258dd28afeSJean-Philippe Brucker u8 next;
1268dd28afeSJean-Philippe Brucker u16 ctrl;
1278dd28afeSJean-Philippe Brucker u32 address_lo;
1288dd28afeSJean-Philippe Brucker u32 address_hi;
1298dd28afeSJean-Philippe Brucker u16 data;
1308dd28afeSJean-Philippe Brucker u16 _align;
1318dd28afeSJean-Philippe Brucker u32 mask_bits;
1328dd28afeSJean-Philippe Brucker u32 pend_bits;
1338dd28afeSJean-Philippe Brucker };
1348dd28afeSJean-Philippe Brucker
1358dd28afeSJean-Philippe Brucker struct msi_cap_32 {
1368dd28afeSJean-Philippe Brucker u8 cap;
1378dd28afeSJean-Philippe Brucker u8 next;
1388dd28afeSJean-Philippe Brucker u16 ctrl;
1398dd28afeSJean-Philippe Brucker u32 address_lo;
1408dd28afeSJean-Philippe Brucker u16 data;
1418dd28afeSJean-Philippe Brucker u16 _align;
1428dd28afeSJean-Philippe Brucker u32 mask_bits;
1438dd28afeSJean-Philippe Brucker u32 pend_bits;
1448dd28afeSJean-Philippe Brucker };
1458dd28afeSJean-Philippe Brucker
146*b0d56e3cSJean-Philippe Brucker struct virtio_caps {
147*b0d56e3cSJean-Philippe Brucker struct virtio_pci_cap common;
148*b0d56e3cSJean-Philippe Brucker struct virtio_pci_notify_cap notify;
149*b0d56e3cSJean-Philippe Brucker struct virtio_pci_cap isr;
150*b0d56e3cSJean-Philippe Brucker struct virtio_pci_cap device;
151*b0d56e3cSJean-Philippe Brucker struct virtio_pci_cfg_cap pci;
152*b0d56e3cSJean-Philippe Brucker };
153*b0d56e3cSJean-Philippe Brucker
1541a51c93dSJean-Philippe Brucker struct pci_cap_hdr {
1551a51c93dSJean-Philippe Brucker u8 type;
1561a51c93dSJean-Philippe Brucker u8 next;
1571a51c93dSJean-Philippe Brucker };
1581a51c93dSJean-Philippe Brucker
15925c1dc6cSAlexandru Elisei struct pci_exp_cap {
16025c1dc6cSAlexandru Elisei u8 cap;
16125c1dc6cSAlexandru Elisei u8 next;
16225c1dc6cSAlexandru Elisei u16 cap_reg;
16325c1dc6cSAlexandru Elisei u32 dev_cap;
16425c1dc6cSAlexandru Elisei u16 dev_ctrl;
16525c1dc6cSAlexandru Elisei u16 dev_status;
16625c1dc6cSAlexandru Elisei u32 link_cap;
16725c1dc6cSAlexandru Elisei u16 link_ctrl;
16825c1dc6cSAlexandru Elisei u16 link_status;
16925c1dc6cSAlexandru Elisei u32 slot_cap;
17025c1dc6cSAlexandru Elisei u16 slot_ctrl;
17125c1dc6cSAlexandru Elisei u16 slot_status;
17225c1dc6cSAlexandru Elisei u16 root_ctrl;
17325c1dc6cSAlexandru Elisei u16 root_cap;
17425c1dc6cSAlexandru Elisei u32 root_status;
17525c1dc6cSAlexandru Elisei };
17625c1dc6cSAlexandru Elisei
1775a8e4f25SAlexandru Elisei struct pci_device_header;
1785a8e4f25SAlexandru Elisei
1795a8e4f25SAlexandru Elisei typedef int (*bar_activate_fn_t)(struct kvm *kvm,
1805a8e4f25SAlexandru Elisei struct pci_device_header *pci_hdr,
1815a8e4f25SAlexandru Elisei int bar_num, void *data);
1825a8e4f25SAlexandru Elisei typedef int (*bar_deactivate_fn_t)(struct kvm *kvm,
1835a8e4f25SAlexandru Elisei struct pci_device_header *pci_hdr,
1845a8e4f25SAlexandru Elisei int bar_num, void *data);
1855a8e4f25SAlexandru Elisei
186023fdaaeSJean-Philippe Brucker #define PCI_BAR_OFFSET(b) (offsetof(struct pci_device_header, bar[b]))
187023fdaaeSJean-Philippe Brucker
188023fdaaeSJean-Philippe Brucker struct pci_config_operations {
189023fdaaeSJean-Philippe Brucker void (*write)(struct kvm *kvm, struct pci_device_header *pci_hdr,
190e69b7663SAlexandru Elisei u16 offset, void *data, int sz);
191023fdaaeSJean-Philippe Brucker void (*read)(struct kvm *kvm, struct pci_device_header *pci_hdr,
192e69b7663SAlexandru Elisei u16 offset, void *data, int sz);
193023fdaaeSJean-Philippe Brucker };
194023fdaaeSJean-Philippe Brucker
19576f9c841SCyrill Gorcunov struct pci_device_header {
196023fdaaeSJean-Philippe Brucker /* Configuration space, as seen by the guest */
197023fdaaeSJean-Philippe Brucker union {
198023fdaaeSJean-Philippe Brucker struct {
1993fdf659dSSasha Levin u16 vendor_id;
2003fdf659dSSasha Levin u16 device_id;
2013fdf659dSSasha Levin u16 command;
2023fdf659dSSasha Levin u16 status;
203aa73be70SMatt Evans u8 revision_id;
204aa73be70SMatt Evans u8 class[3];
2053fdf659dSSasha Levin u8 cacheline_size;
2063fdf659dSSasha Levin u8 latency_timer;
2073fdf659dSSasha Levin u8 header_type;
2083fdf659dSSasha Levin u8 bist;
2093fdf659dSSasha Levin u32 bar[6];
2103fdf659dSSasha Levin u32 card_bus;
2113fdf659dSSasha Levin u16 subsys_vendor_id;
2123fdf659dSSasha Levin u16 subsys_id;
2133fdf659dSSasha Levin u32 exp_rom_bar;
214aa73be70SMatt Evans u8 capabilities;
215aa73be70SMatt Evans u8 reserved1[3];
2163fdf659dSSasha Levin u32 reserved2;
2173fdf659dSSasha Levin u8 irq_line;
2183fdf659dSSasha Levin u8 irq_pin;
2193fdf659dSSasha Levin u8 min_gnt;
2203fdf659dSSasha Levin u8 max_lat;
221bc485053SSasha Levin struct msix_cap msix;
22225c1dc6cSAlexandru Elisei /* Used only by architectures which support PCIE */
22325c1dc6cSAlexandru Elisei struct pci_exp_cap pci_exp;
224*b0d56e3cSJean-Philippe Brucker struct virtio_caps virtio;
225aa73be70SMatt Evans } __attribute__((packed));
226023fdaaeSJean-Philippe Brucker /* Pad to PCI config space size */
227023fdaaeSJean-Philippe Brucker u8 __pad[PCI_DEV_CFG_SIZE];
228023fdaaeSJean-Philippe Brucker };
229023fdaaeSJean-Philippe Brucker
230023fdaaeSJean-Philippe Brucker /* Private to lkvm */
231023fdaaeSJean-Philippe Brucker u32 bar_size[6];
232465edc9dSAlexandru Elisei bool bar_active[6];
2335a8e4f25SAlexandru Elisei bar_activate_fn_t bar_activate_fn;
2345a8e4f25SAlexandru Elisei bar_deactivate_fn_t bar_deactivate_fn;
2355a8e4f25SAlexandru Elisei void *data;
236023fdaaeSJean-Philippe Brucker struct pci_config_operations cfg_ops;
237ff01b5dbSJean-Philippe Brucker /*
238ff01b5dbSJean-Philippe Brucker * PCI INTx# are level-triggered, but virtual device often feature
239ff01b5dbSJean-Philippe Brucker * edge-triggered INTx# for convenience.
240ff01b5dbSJean-Philippe Brucker */
241ff01b5dbSJean-Philippe Brucker enum irq_type irq_type;
242023fdaaeSJean-Philippe Brucker };
24376f9c841SCyrill Gorcunov
2441a51c93dSJean-Philippe Brucker #define PCI_CAP(pci_hdr, pos) ((void *)(pci_hdr) + (pos))
245*b0d56e3cSJean-Philippe Brucker #define PCI_CAP_OFF(pci_hdr, cap) ((void *)&(pci_hdr)->cap - (void *)(pci_hdr))
2461a51c93dSJean-Philippe Brucker
2471a51c93dSJean-Philippe Brucker #define pci_for_each_cap(pos, cap, hdr) \
2481a51c93dSJean-Philippe Brucker for ((pos) = (hdr)->capabilities & ~3; \
2491a51c93dSJean-Philippe Brucker (cap) = PCI_CAP(hdr, pos), (pos) != 0; \
2501a51c93dSJean-Philippe Brucker (pos) = ((struct pci_cap_hdr *)(cap))->next & ~3)
2511a51c93dSJean-Philippe Brucker
2526d987703SSasha Levin int pci__init(struct kvm *kvm);
2536d987703SSasha Levin int pci__exit(struct kvm *kvm);
254d0297a59SMatt Evans struct pci_device_header *pci__find_dev(u8 dev_num);
255854aa2efSJulien Thierry u32 pci_get_mmio_block(u32 size);
256854aa2efSJulien Thierry u16 pci_get_io_port_block(u32 size);
257c0c45eedSAndre Przywara int pci__assign_irq(struct pci_device_header *pci_hdr);
258d0297a59SMatt Evans void pci__config_wr(struct kvm *kvm, union pci_config_address addr, void *data, int size);
259d0297a59SMatt Evans void pci__config_rd(struct kvm *kvm, union pci_config_address addr, void *data, int size);
26060742802SPekka Enberg
2611a51c93dSJean-Philippe Brucker void *pci_find_cap(struct pci_device_header *hdr, u8 cap_type);
2621a51c93dSJean-Philippe Brucker
2635a8e4f25SAlexandru Elisei int pci__register_bar_regions(struct kvm *kvm, struct pci_device_header *pci_hdr,
2645a8e4f25SAlexandru Elisei bar_activate_fn_t bar_activate_fn,
2655a8e4f25SAlexandru Elisei bar_deactivate_fn_t bar_deactivate_fn, void *data);
2665a8e4f25SAlexandru Elisei
__pci__memory_space_enabled(u16 command)2672f6384f9SAlexandru Elisei static inline bool __pci__memory_space_enabled(u16 command)
2682f6384f9SAlexandru Elisei {
2692f6384f9SAlexandru Elisei return command & PCI_COMMAND_MEMORY;
2702f6384f9SAlexandru Elisei }
2712f6384f9SAlexandru Elisei
pci__memory_space_enabled(struct pci_device_header * pci_hdr)2722f6384f9SAlexandru Elisei static inline bool pci__memory_space_enabled(struct pci_device_header *pci_hdr)
2732f6384f9SAlexandru Elisei {
2742f6384f9SAlexandru Elisei return __pci__memory_space_enabled(pci_hdr->command);
2752f6384f9SAlexandru Elisei }
2762f6384f9SAlexandru Elisei
__pci__io_space_enabled(u16 command)2772f6384f9SAlexandru Elisei static inline bool __pci__io_space_enabled(u16 command)
2782f6384f9SAlexandru Elisei {
2792f6384f9SAlexandru Elisei return command & PCI_COMMAND_IO;
2802f6384f9SAlexandru Elisei }
2812f6384f9SAlexandru Elisei
pci__io_space_enabled(struct pci_device_header * pci_hdr)2822f6384f9SAlexandru Elisei static inline bool pci__io_space_enabled(struct pci_device_header *pci_hdr)
2832f6384f9SAlexandru Elisei {
2842f6384f9SAlexandru Elisei return __pci__io_space_enabled(pci_hdr->command);
2852f6384f9SAlexandru Elisei }
2862f6384f9SAlexandru Elisei
__pci__bar_is_io(u32 bar)2872f6384f9SAlexandru Elisei static inline bool __pci__bar_is_io(u32 bar)
2882f6384f9SAlexandru Elisei {
2892f6384f9SAlexandru Elisei return bar & PCI_BASE_ADDRESS_SPACE_IO;
2902f6384f9SAlexandru Elisei }
2912f6384f9SAlexandru Elisei
pci__bar_is_io(struct pci_device_header * pci_hdr,int bar_num)2922f6384f9SAlexandru Elisei static inline bool pci__bar_is_io(struct pci_device_header *pci_hdr, int bar_num)
2932f6384f9SAlexandru Elisei {
2942f6384f9SAlexandru Elisei return __pci__bar_is_io(pci_hdr->bar[bar_num]);
2952f6384f9SAlexandru Elisei }
2962f6384f9SAlexandru Elisei
pci__bar_is_memory(struct pci_device_header * pci_hdr,int bar_num)2972f6384f9SAlexandru Elisei static inline bool pci__bar_is_memory(struct pci_device_header *pci_hdr, int bar_num)
2982f6384f9SAlexandru Elisei {
2992f6384f9SAlexandru Elisei return !pci__bar_is_io(pci_hdr, bar_num);
3002f6384f9SAlexandru Elisei }
3012f6384f9SAlexandru Elisei
__pci__bar_address(u32 bar)3022f6384f9SAlexandru Elisei static inline u32 __pci__bar_address(u32 bar)
3032f6384f9SAlexandru Elisei {
3042f6384f9SAlexandru Elisei if (__pci__bar_is_io(bar))
3052f6384f9SAlexandru Elisei return bar & PCI_BASE_ADDRESS_IO_MASK;
3062f6384f9SAlexandru Elisei return bar & PCI_BASE_ADDRESS_MEM_MASK;
3072f6384f9SAlexandru Elisei }
3082f6384f9SAlexandru Elisei
pci__bar_address(struct pci_device_header * pci_hdr,int bar_num)3092f6384f9SAlexandru Elisei static inline u32 pci__bar_address(struct pci_device_header *pci_hdr, int bar_num)
3102f6384f9SAlexandru Elisei {
3112f6384f9SAlexandru Elisei return __pci__bar_address(pci_hdr->bar[bar_num]);
3122f6384f9SAlexandru Elisei }
3132f6384f9SAlexandru Elisei
pci__bar_size(struct pci_device_header * pci_hdr,int bar_num)3142f6384f9SAlexandru Elisei static inline u32 pci__bar_size(struct pci_device_header *pci_hdr, int bar_num)
3152f6384f9SAlexandru Elisei {
3162f6384f9SAlexandru Elisei return pci_hdr->bar_size[bar_num];
3172f6384f9SAlexandru Elisei }
3182f6384f9SAlexandru Elisei
31960742802SPekka Enberg #endif /* KVM__PCI_H */
320