xref: /kvmtool/include/kvm/pci.h (revision 25c1dc6c4942ff0949c08780fcad6b324fec6bf7)
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>
7aa73be70SMatt Evans #include <endian.h>
82f6384f9SAlexandru Elisei #include <stdbool.h>
976f9c841SCyrill Gorcunov 
10b5981636SWill Deacon #include "kvm/devices.h"
11f7c17d7cSPekka Enberg #include "kvm/msi.h"
12ff01b5dbSJean-Philippe Brucker #include "kvm/fdt.h"
13e69b7663SAlexandru Elisei #include "kvm/kvm-arch.h"
14d0297a59SMatt Evans 
15465edc9dSAlexandru Elisei #define pci_dev_err(pci_hdr, fmt, ...) \
16465edc9dSAlexandru Elisei 	pr_err("[%04x:%04x] " fmt, pci_hdr->vendor_id, pci_hdr->device_id, ##__VA_ARGS__)
17465edc9dSAlexandru Elisei #define pci_dev_warn(pci_hdr, fmt, ...) \
18465edc9dSAlexandru Elisei 	pr_warning("[%04x:%04x] " fmt, pci_hdr->vendor_id, pci_hdr->device_id, ##__VA_ARGS__)
19465edc9dSAlexandru Elisei #define pci_dev_info(pci_hdr, fmt, ...) \
20465edc9dSAlexandru Elisei 	pr_info("[%04x:%04x] " fmt, pci_hdr->vendor_id, pci_hdr->device_id, ##__VA_ARGS__)
21465edc9dSAlexandru Elisei #define pci_dev_dbg(pci_hdr, fmt, ...) \
22465edc9dSAlexandru Elisei 	pr_debug("[%04x:%04x] " fmt, pci_hdr->vendor_id, pci_hdr->device_id, ##__VA_ARGS__)
23465edc9dSAlexandru Elisei #define pci_dev_die(pci_hdr, fmt, ...) \
24465edc9dSAlexandru Elisei 	die("[%04x:%04x] " fmt, pci_hdr->vendor_id, pci_hdr->device_id, ##__VA_ARGS__)
25465edc9dSAlexandru Elisei 
264402a581SPekka Enberg /*
274402a581SPekka Enberg  * PCI Configuration Mechanism #1 I/O ports. See Section 3.7.4.1.
284402a581SPekka Enberg  * ("Configuration Mechanism #1") of the PCI Local Bus Specification 2.1 for
294402a581SPekka Enberg  * details.
304402a581SPekka Enberg  */
31305b72ceSCyrill Gorcunov #define PCI_CONFIG_ADDRESS	0xcf8
32305b72ceSCyrill Gorcunov #define PCI_CONFIG_DATA		0xcfc
332b9e4709SCyrill Gorcunov #define PCI_CONFIG_BUS_FORWARD	0xcfa
3495d13a52SSasha Levin #define PCI_IO_SIZE		0x100
35854aa2efSJulien Thierry #define PCI_IOPORT_START	0x6200
36305b72ceSCyrill Gorcunov 
376078a454SJean-Philippe Brucker struct kvm;
386078a454SJean-Philippe Brucker 
39e69b7663SAlexandru Elisei /*
40e69b7663SAlexandru Elisei  * On some distributions, pci_regs.h doesn't define PCI_CFG_SPACE_SIZE and
41e69b7663SAlexandru Elisei  * PCI_CFG_SPACE_EXP_SIZE, so we define our own.
42e69b7663SAlexandru Elisei  */
43e69b7663SAlexandru Elisei #define PCI_CFG_SIZE_LEGACY		(1ULL << 24)
44e69b7663SAlexandru Elisei #define PCI_DEV_CFG_SIZE_LEGACY		256
45e69b7663SAlexandru Elisei #define PCI_CFG_SIZE_EXTENDED		(1ULL << 28)
46e69b7663SAlexandru Elisei #define PCI_DEV_CFG_SIZE_EXTENDED 	4096
47e69b7663SAlexandru Elisei 
48e69b7663SAlexandru Elisei #ifdef ARCH_HAS_PCI_EXP
49*25c1dc6cSAlexandru Elisei #define arch_has_pci_exp()	(true)
50*25c1dc6cSAlexandru Elisei 
51e69b7663SAlexandru Elisei #define PCI_CFG_SIZE		PCI_CFG_SIZE_EXTENDED
52e69b7663SAlexandru Elisei #define PCI_DEV_CFG_SIZE	PCI_DEV_CFG_SIZE_EXTENDED
53e69b7663SAlexandru Elisei 
54e69b7663SAlexandru Elisei union pci_config_address {
55e69b7663SAlexandru Elisei 	struct {
56e69b7663SAlexandru Elisei #if __BYTE_ORDER == __LITTLE_ENDIAN
57e69b7663SAlexandru Elisei 		unsigned	reg_offset	: 2;		/* 1  .. 0  */
58e69b7663SAlexandru Elisei 		unsigned	register_number	: 10;		/* 11 .. 2  */
59e69b7663SAlexandru Elisei 		unsigned	function_number	: 3;		/* 14 .. 12 */
60e69b7663SAlexandru Elisei 		unsigned	device_number	: 5;		/* 19 .. 15 */
61e69b7663SAlexandru Elisei 		unsigned	bus_number	: 8;		/* 27 .. 20 */
62e69b7663SAlexandru Elisei 		unsigned	reserved	: 3;		/* 30 .. 28 */
63e69b7663SAlexandru Elisei 		unsigned	enable_bit	: 1;		/* 31       */
64e69b7663SAlexandru Elisei #else
65e69b7663SAlexandru Elisei 		unsigned	enable_bit	: 1;		/* 31       */
66e69b7663SAlexandru Elisei 		unsigned	reserved	: 3;		/* 30 .. 28 */
67e69b7663SAlexandru Elisei 		unsigned	bus_number	: 8;		/* 27 .. 20 */
68e69b7663SAlexandru Elisei 		unsigned	device_number	: 5;		/* 19 .. 15 */
69e69b7663SAlexandru Elisei 		unsigned	function_number	: 3;		/* 14 .. 12 */
70e69b7663SAlexandru Elisei 		unsigned	register_number	: 10;		/* 11 .. 2  */
71e69b7663SAlexandru Elisei 		unsigned	reg_offset	: 2;		/* 1  .. 0  */
72e69b7663SAlexandru Elisei #endif
73e69b7663SAlexandru Elisei 	};
74e69b7663SAlexandru Elisei 	u32 w;
75e69b7663SAlexandru Elisei };
76e69b7663SAlexandru Elisei 
77e69b7663SAlexandru Elisei #else
78*25c1dc6cSAlexandru Elisei #define arch_has_pci_exp()	(false)
79*25c1dc6cSAlexandru Elisei 
80e69b7663SAlexandru Elisei #define PCI_CFG_SIZE		PCI_CFG_SIZE_LEGACY
81e69b7663SAlexandru Elisei #define PCI_DEV_CFG_SIZE	PCI_DEV_CFG_SIZE_LEGACY
82e69b7663SAlexandru Elisei 
83aa73be70SMatt Evans union pci_config_address {
84aa73be70SMatt Evans 	struct {
85aa73be70SMatt Evans #if __BYTE_ORDER == __LITTLE_ENDIAN
86d0297a59SMatt Evans 		unsigned	reg_offset	: 2;		/* 1  .. 0  */
874402a581SPekka Enberg 		unsigned	register_number	: 6;		/* 7  .. 2  */
884402a581SPekka Enberg 		unsigned	function_number	: 3;		/* 10 .. 8  */
894402a581SPekka Enberg 		unsigned	device_number	: 5;		/* 15 .. 11 */
904402a581SPekka Enberg 		unsigned	bus_number	: 8;		/* 23 .. 16 */
914402a581SPekka Enberg 		unsigned	reserved	: 7;		/* 30 .. 24 */
924402a581SPekka Enberg 		unsigned	enable_bit	: 1;		/* 31       */
93aa73be70SMatt Evans #else
94aa73be70SMatt Evans 		unsigned	enable_bit	: 1;		/* 31       */
95aa73be70SMatt Evans 		unsigned	reserved	: 7;		/* 30 .. 24 */
96aa73be70SMatt Evans 		unsigned	bus_number	: 8;		/* 23 .. 16 */
97aa73be70SMatt Evans 		unsigned	device_number	: 5;		/* 15 .. 11 */
98aa73be70SMatt Evans 		unsigned	function_number	: 3;		/* 10 .. 8  */
99aa73be70SMatt Evans 		unsigned	register_number	: 6;		/* 7  .. 2  */
100d0297a59SMatt Evans 		unsigned	reg_offset	: 2;		/* 1  .. 0  */
101aa73be70SMatt Evans #endif
102aa73be70SMatt Evans 	};
103aa73be70SMatt Evans 	u32 w;
1044402a581SPekka Enberg };
105e69b7663SAlexandru Elisei #endif /* ARCH_HAS_PCI_EXP */
106e69b7663SAlexandru Elisei 
107e69b7663SAlexandru Elisei #define PCI_DEV_CFG_MASK	(PCI_DEV_CFG_SIZE - 1)
1084402a581SPekka Enberg 
109bc485053SSasha Levin struct msix_table {
1101de74957SSasha Levin 	struct msi_msg msg;
111bc485053SSasha Levin 	u32 ctrl;
112bc485053SSasha Levin };
113bc485053SSasha Levin 
114bc485053SSasha Levin struct msix_cap {
115bc485053SSasha Levin 	u8 cap;
116bc485053SSasha Levin 	u8 next;
11706f48103SSasha Levin 	u16 ctrl;
118bc485053SSasha Levin 	u32 table_offset;
11906f48103SSasha Levin 	u32 pba_offset;
120bc485053SSasha Levin };
121bc485053SSasha Levin 
1228dd28afeSJean-Philippe Brucker struct msi_cap_64 {
1238dd28afeSJean-Philippe Brucker 	u8 cap;
1248dd28afeSJean-Philippe Brucker 	u8 next;
1258dd28afeSJean-Philippe Brucker 	u16 ctrl;
1268dd28afeSJean-Philippe Brucker 	u32 address_lo;
1278dd28afeSJean-Philippe Brucker 	u32 address_hi;
1288dd28afeSJean-Philippe Brucker 	u16 data;
1298dd28afeSJean-Philippe Brucker 	u16 _align;
1308dd28afeSJean-Philippe Brucker 	u32 mask_bits;
1318dd28afeSJean-Philippe Brucker 	u32 pend_bits;
1328dd28afeSJean-Philippe Brucker };
1338dd28afeSJean-Philippe Brucker 
1348dd28afeSJean-Philippe Brucker struct msi_cap_32 {
1358dd28afeSJean-Philippe Brucker 	u8 cap;
1368dd28afeSJean-Philippe Brucker 	u8 next;
1378dd28afeSJean-Philippe Brucker 	u16 ctrl;
1388dd28afeSJean-Philippe Brucker 	u32 address_lo;
1398dd28afeSJean-Philippe Brucker 	u16 data;
1408dd28afeSJean-Philippe Brucker 	u16 _align;
1418dd28afeSJean-Philippe Brucker 	u32 mask_bits;
1428dd28afeSJean-Philippe Brucker 	u32 pend_bits;
1438dd28afeSJean-Philippe Brucker };
1448dd28afeSJean-Philippe Brucker 
1451a51c93dSJean-Philippe Brucker struct pci_cap_hdr {
1461a51c93dSJean-Philippe Brucker 	u8	type;
1471a51c93dSJean-Philippe Brucker 	u8	next;
1481a51c93dSJean-Philippe Brucker };
1491a51c93dSJean-Philippe Brucker 
150*25c1dc6cSAlexandru Elisei struct pci_exp_cap {
151*25c1dc6cSAlexandru Elisei 	u8 cap;
152*25c1dc6cSAlexandru Elisei 	u8 next;
153*25c1dc6cSAlexandru Elisei 	u16 cap_reg;
154*25c1dc6cSAlexandru Elisei 	u32 dev_cap;
155*25c1dc6cSAlexandru Elisei 	u16 dev_ctrl;
156*25c1dc6cSAlexandru Elisei 	u16 dev_status;
157*25c1dc6cSAlexandru Elisei 	u32 link_cap;
158*25c1dc6cSAlexandru Elisei 	u16 link_ctrl;
159*25c1dc6cSAlexandru Elisei 	u16 link_status;
160*25c1dc6cSAlexandru Elisei 	u32 slot_cap;
161*25c1dc6cSAlexandru Elisei 	u16 slot_ctrl;
162*25c1dc6cSAlexandru Elisei 	u16 slot_status;
163*25c1dc6cSAlexandru Elisei 	u16 root_ctrl;
164*25c1dc6cSAlexandru Elisei 	u16 root_cap;
165*25c1dc6cSAlexandru Elisei 	u32 root_status;
166*25c1dc6cSAlexandru Elisei };
167*25c1dc6cSAlexandru Elisei 
1685a8e4f25SAlexandru Elisei struct pci_device_header;
1695a8e4f25SAlexandru Elisei 
1705a8e4f25SAlexandru Elisei typedef int (*bar_activate_fn_t)(struct kvm *kvm,
1715a8e4f25SAlexandru Elisei 				 struct pci_device_header *pci_hdr,
1725a8e4f25SAlexandru Elisei 				 int bar_num, void *data);
1735a8e4f25SAlexandru Elisei typedef int (*bar_deactivate_fn_t)(struct kvm *kvm,
1745a8e4f25SAlexandru Elisei 				   struct pci_device_header *pci_hdr,
1755a8e4f25SAlexandru Elisei 				   int bar_num, void *data);
1765a8e4f25SAlexandru Elisei 
177023fdaaeSJean-Philippe Brucker #define PCI_BAR_OFFSET(b)	(offsetof(struct pci_device_header, bar[b]))
178023fdaaeSJean-Philippe Brucker 
179023fdaaeSJean-Philippe Brucker struct pci_config_operations {
180023fdaaeSJean-Philippe Brucker 	void (*write)(struct kvm *kvm, struct pci_device_header *pci_hdr,
181e69b7663SAlexandru Elisei 		      u16 offset, void *data, int sz);
182023fdaaeSJean-Philippe Brucker 	void (*read)(struct kvm *kvm, struct pci_device_header *pci_hdr,
183e69b7663SAlexandru Elisei 		     u16 offset, void *data, int sz);
184023fdaaeSJean-Philippe Brucker };
185023fdaaeSJean-Philippe Brucker 
18676f9c841SCyrill Gorcunov struct pci_device_header {
187023fdaaeSJean-Philippe Brucker 	/* Configuration space, as seen by the guest */
188023fdaaeSJean-Philippe Brucker 	union {
189023fdaaeSJean-Philippe Brucker 		struct {
1903fdf659dSSasha Levin 			u16		vendor_id;
1913fdf659dSSasha Levin 			u16		device_id;
1923fdf659dSSasha Levin 			u16		command;
1933fdf659dSSasha Levin 			u16		status;
194aa73be70SMatt Evans 			u8		revision_id;
195aa73be70SMatt Evans 			u8		class[3];
1963fdf659dSSasha Levin 			u8		cacheline_size;
1973fdf659dSSasha Levin 			u8		latency_timer;
1983fdf659dSSasha Levin 			u8		header_type;
1993fdf659dSSasha Levin 			u8		bist;
2003fdf659dSSasha Levin 			u32		bar[6];
2013fdf659dSSasha Levin 			u32		card_bus;
2023fdf659dSSasha Levin 			u16		subsys_vendor_id;
2033fdf659dSSasha Levin 			u16		subsys_id;
2043fdf659dSSasha Levin 			u32		exp_rom_bar;
205aa73be70SMatt Evans 			u8		capabilities;
206aa73be70SMatt Evans 			u8		reserved1[3];
2073fdf659dSSasha Levin 			u32		reserved2;
2083fdf659dSSasha Levin 			u8		irq_line;
2093fdf659dSSasha Levin 			u8		irq_pin;
2103fdf659dSSasha Levin 			u8		min_gnt;
2113fdf659dSSasha Levin 			u8		max_lat;
212bc485053SSasha Levin 			struct msix_cap msix;
213*25c1dc6cSAlexandru Elisei 			/* Used only by architectures which support PCIE */
214*25c1dc6cSAlexandru Elisei 			struct pci_exp_cap pci_exp;
215aa73be70SMatt Evans 		} __attribute__((packed));
216023fdaaeSJean-Philippe Brucker 		/* Pad to PCI config space size */
217023fdaaeSJean-Philippe Brucker 		u8	__pad[PCI_DEV_CFG_SIZE];
218023fdaaeSJean-Philippe Brucker 	};
219023fdaaeSJean-Philippe Brucker 
220023fdaaeSJean-Philippe Brucker 	/* Private to lkvm */
221023fdaaeSJean-Philippe Brucker 	u32			bar_size[6];
222465edc9dSAlexandru Elisei 	bool			bar_active[6];
2235a8e4f25SAlexandru Elisei 	bar_activate_fn_t	bar_activate_fn;
2245a8e4f25SAlexandru Elisei 	bar_deactivate_fn_t	bar_deactivate_fn;
2255a8e4f25SAlexandru Elisei 	void *data;
226023fdaaeSJean-Philippe Brucker 	struct pci_config_operations	cfg_ops;
227ff01b5dbSJean-Philippe Brucker 	/*
228ff01b5dbSJean-Philippe Brucker 	 * PCI INTx# are level-triggered, but virtual device often feature
229ff01b5dbSJean-Philippe Brucker 	 * edge-triggered INTx# for convenience.
230ff01b5dbSJean-Philippe Brucker 	 */
231ff01b5dbSJean-Philippe Brucker 	enum irq_type	irq_type;
232023fdaaeSJean-Philippe Brucker };
23376f9c841SCyrill Gorcunov 
2341a51c93dSJean-Philippe Brucker #define PCI_CAP(pci_hdr, pos) ((void *)(pci_hdr) + (pos))
2351a51c93dSJean-Philippe Brucker 
2361a51c93dSJean-Philippe Brucker #define pci_for_each_cap(pos, cap, hdr)				\
2371a51c93dSJean-Philippe Brucker 	for ((pos) = (hdr)->capabilities & ~3;			\
2381a51c93dSJean-Philippe Brucker 	     (cap) = PCI_CAP(hdr, pos), (pos) != 0;		\
2391a51c93dSJean-Philippe Brucker 	     (pos) = ((struct pci_cap_hdr *)(cap))->next & ~3)
2401a51c93dSJean-Philippe Brucker 
2416d987703SSasha Levin int pci__init(struct kvm *kvm);
2426d987703SSasha Levin int pci__exit(struct kvm *kvm);
243d0297a59SMatt Evans struct pci_device_header *pci__find_dev(u8 dev_num);
244854aa2efSJulien Thierry u32 pci_get_mmio_block(u32 size);
245854aa2efSJulien Thierry u16 pci_get_io_port_block(u32 size);
246c0c45eedSAndre Przywara int pci__assign_irq(struct pci_device_header *pci_hdr);
247d0297a59SMatt Evans void pci__config_wr(struct kvm *kvm, union pci_config_address addr, void *data, int size);
248d0297a59SMatt Evans void pci__config_rd(struct kvm *kvm, union pci_config_address addr, void *data, int size);
24960742802SPekka Enberg 
2501a51c93dSJean-Philippe Brucker void *pci_find_cap(struct pci_device_header *hdr, u8 cap_type);
2511a51c93dSJean-Philippe Brucker 
2525a8e4f25SAlexandru Elisei int pci__register_bar_regions(struct kvm *kvm, struct pci_device_header *pci_hdr,
2535a8e4f25SAlexandru Elisei 			      bar_activate_fn_t bar_activate_fn,
2545a8e4f25SAlexandru Elisei 			      bar_deactivate_fn_t bar_deactivate_fn, void *data);
2555a8e4f25SAlexandru Elisei 
2562f6384f9SAlexandru Elisei static inline bool __pci__memory_space_enabled(u16 command)
2572f6384f9SAlexandru Elisei {
2582f6384f9SAlexandru Elisei 	return command & PCI_COMMAND_MEMORY;
2592f6384f9SAlexandru Elisei }
2602f6384f9SAlexandru Elisei 
2612f6384f9SAlexandru Elisei static inline bool pci__memory_space_enabled(struct pci_device_header *pci_hdr)
2622f6384f9SAlexandru Elisei {
2632f6384f9SAlexandru Elisei 	return __pci__memory_space_enabled(pci_hdr->command);
2642f6384f9SAlexandru Elisei }
2652f6384f9SAlexandru Elisei 
2662f6384f9SAlexandru Elisei static inline bool __pci__io_space_enabled(u16 command)
2672f6384f9SAlexandru Elisei {
2682f6384f9SAlexandru Elisei 	return command & PCI_COMMAND_IO;
2692f6384f9SAlexandru Elisei }
2702f6384f9SAlexandru Elisei 
2712f6384f9SAlexandru Elisei static inline bool pci__io_space_enabled(struct pci_device_header *pci_hdr)
2722f6384f9SAlexandru Elisei {
2732f6384f9SAlexandru Elisei 	return __pci__io_space_enabled(pci_hdr->command);
2742f6384f9SAlexandru Elisei }
2752f6384f9SAlexandru Elisei 
2762f6384f9SAlexandru Elisei static inline bool __pci__bar_is_io(u32 bar)
2772f6384f9SAlexandru Elisei {
2782f6384f9SAlexandru Elisei 	return bar & PCI_BASE_ADDRESS_SPACE_IO;
2792f6384f9SAlexandru Elisei }
2802f6384f9SAlexandru Elisei 
2812f6384f9SAlexandru Elisei static inline bool pci__bar_is_io(struct pci_device_header *pci_hdr, int bar_num)
2822f6384f9SAlexandru Elisei {
2832f6384f9SAlexandru Elisei 	return __pci__bar_is_io(pci_hdr->bar[bar_num]);
2842f6384f9SAlexandru Elisei }
2852f6384f9SAlexandru Elisei 
2862f6384f9SAlexandru Elisei static inline bool pci__bar_is_memory(struct pci_device_header *pci_hdr, int bar_num)
2872f6384f9SAlexandru Elisei {
2882f6384f9SAlexandru Elisei 	return !pci__bar_is_io(pci_hdr, bar_num);
2892f6384f9SAlexandru Elisei }
2902f6384f9SAlexandru Elisei 
2912f6384f9SAlexandru Elisei static inline u32 __pci__bar_address(u32 bar)
2922f6384f9SAlexandru Elisei {
2932f6384f9SAlexandru Elisei 	if (__pci__bar_is_io(bar))
2942f6384f9SAlexandru Elisei 		return bar & PCI_BASE_ADDRESS_IO_MASK;
2952f6384f9SAlexandru Elisei 	return bar & PCI_BASE_ADDRESS_MEM_MASK;
2962f6384f9SAlexandru Elisei }
2972f6384f9SAlexandru Elisei 
2982f6384f9SAlexandru Elisei static inline u32 pci__bar_address(struct pci_device_header *pci_hdr, int bar_num)
2992f6384f9SAlexandru Elisei {
3002f6384f9SAlexandru Elisei 	return __pci__bar_address(pci_hdr->bar[bar_num]);
3012f6384f9SAlexandru Elisei }
3022f6384f9SAlexandru Elisei 
3032f6384f9SAlexandru Elisei static inline u32 pci__bar_size(struct pci_device_header *pci_hdr, int bar_num)
3042f6384f9SAlexandru Elisei {
3052f6384f9SAlexandru Elisei 	return pci_hdr->bar_size[bar_num];
3062f6384f9SAlexandru Elisei }
3072f6384f9SAlexandru Elisei 
30860742802SPekka Enberg #endif /* KVM__PCI_H */
309