xref: /kvmtool/include/kvm/pci.h (revision 465edc9d0fab23f46e9b83af1403577ba98e1937)
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"
13d0297a59SMatt Evans 
14*465edc9dSAlexandru Elisei #define pci_dev_err(pci_hdr, fmt, ...) \
15*465edc9dSAlexandru Elisei 	pr_err("[%04x:%04x] " fmt, pci_hdr->vendor_id, pci_hdr->device_id, ##__VA_ARGS__)
16*465edc9dSAlexandru Elisei #define pci_dev_warn(pci_hdr, fmt, ...) \
17*465edc9dSAlexandru Elisei 	pr_warning("[%04x:%04x] " fmt, pci_hdr->vendor_id, pci_hdr->device_id, ##__VA_ARGS__)
18*465edc9dSAlexandru Elisei #define pci_dev_info(pci_hdr, fmt, ...) \
19*465edc9dSAlexandru Elisei 	pr_info("[%04x:%04x] " fmt, pci_hdr->vendor_id, pci_hdr->device_id, ##__VA_ARGS__)
20*465edc9dSAlexandru Elisei #define pci_dev_dbg(pci_hdr, fmt, ...) \
21*465edc9dSAlexandru Elisei 	pr_debug("[%04x:%04x] " fmt, pci_hdr->vendor_id, pci_hdr->device_id, ##__VA_ARGS__)
22*465edc9dSAlexandru Elisei #define pci_dev_die(pci_hdr, fmt, ...) \
23*465edc9dSAlexandru Elisei 	die("[%04x:%04x] " fmt, pci_hdr->vendor_id, pci_hdr->device_id, ##__VA_ARGS__)
24*465edc9dSAlexandru Elisei 
254402a581SPekka Enberg /*
264402a581SPekka Enberg  * PCI Configuration Mechanism #1 I/O ports. See Section 3.7.4.1.
274402a581SPekka Enberg  * ("Configuration Mechanism #1") of the PCI Local Bus Specification 2.1 for
284402a581SPekka Enberg  * details.
294402a581SPekka Enberg  */
30305b72ceSCyrill Gorcunov #define PCI_CONFIG_ADDRESS	0xcf8
31305b72ceSCyrill Gorcunov #define PCI_CONFIG_DATA		0xcfc
322b9e4709SCyrill Gorcunov #define PCI_CONFIG_BUS_FORWARD	0xcfa
3395d13a52SSasha Levin #define PCI_IO_SIZE		0x100
34854aa2efSJulien Thierry #define PCI_IOPORT_START	0x6200
35b403f2f7SWill Deacon #define PCI_CFG_SIZE		(1ULL << 24)
36305b72ceSCyrill Gorcunov 
376078a454SJean-Philippe Brucker struct kvm;
386078a454SJean-Philippe Brucker 
39aa73be70SMatt Evans union pci_config_address {
40aa73be70SMatt Evans 	struct {
41aa73be70SMatt Evans #if __BYTE_ORDER == __LITTLE_ENDIAN
42d0297a59SMatt Evans 		unsigned	reg_offset	: 2;		/* 1  .. 0  */
434402a581SPekka Enberg 		unsigned	register_number	: 6;		/* 7  .. 2  */
444402a581SPekka Enberg 		unsigned	function_number	: 3;		/* 10 .. 8  */
454402a581SPekka Enberg 		unsigned	device_number	: 5;		/* 15 .. 11 */
464402a581SPekka Enberg 		unsigned	bus_number	: 8;		/* 23 .. 16 */
474402a581SPekka Enberg 		unsigned	reserved	: 7;		/* 30 .. 24 */
484402a581SPekka Enberg 		unsigned	enable_bit	: 1;		/* 31       */
49aa73be70SMatt Evans #else
50aa73be70SMatt Evans 		unsigned	enable_bit	: 1;		/* 31       */
51aa73be70SMatt Evans 		unsigned	reserved	: 7;		/* 30 .. 24 */
52aa73be70SMatt Evans 		unsigned	bus_number	: 8;		/* 23 .. 16 */
53aa73be70SMatt Evans 		unsigned	device_number	: 5;		/* 15 .. 11 */
54aa73be70SMatt Evans 		unsigned	function_number	: 3;		/* 10 .. 8  */
55aa73be70SMatt Evans 		unsigned	register_number	: 6;		/* 7  .. 2  */
56d0297a59SMatt Evans 		unsigned	reg_offset	: 2;		/* 1  .. 0  */
57aa73be70SMatt Evans #endif
58aa73be70SMatt Evans 	};
59aa73be70SMatt Evans 	u32 w;
604402a581SPekka Enberg };
614402a581SPekka Enberg 
62bc485053SSasha Levin struct msix_table {
631de74957SSasha Levin 	struct msi_msg msg;
64bc485053SSasha Levin 	u32 ctrl;
65bc485053SSasha Levin };
66bc485053SSasha Levin 
67bc485053SSasha Levin struct msix_cap {
68bc485053SSasha Levin 	u8 cap;
69bc485053SSasha Levin 	u8 next;
7006f48103SSasha Levin 	u16 ctrl;
71bc485053SSasha Levin 	u32 table_offset;
7206f48103SSasha Levin 	u32 pba_offset;
73bc485053SSasha Levin };
74bc485053SSasha Levin 
758dd28afeSJean-Philippe Brucker struct msi_cap_64 {
768dd28afeSJean-Philippe Brucker 	u8 cap;
778dd28afeSJean-Philippe Brucker 	u8 next;
788dd28afeSJean-Philippe Brucker 	u16 ctrl;
798dd28afeSJean-Philippe Brucker 	u32 address_lo;
808dd28afeSJean-Philippe Brucker 	u32 address_hi;
818dd28afeSJean-Philippe Brucker 	u16 data;
828dd28afeSJean-Philippe Brucker 	u16 _align;
838dd28afeSJean-Philippe Brucker 	u32 mask_bits;
848dd28afeSJean-Philippe Brucker 	u32 pend_bits;
858dd28afeSJean-Philippe Brucker };
868dd28afeSJean-Philippe Brucker 
878dd28afeSJean-Philippe Brucker struct msi_cap_32 {
888dd28afeSJean-Philippe Brucker 	u8 cap;
898dd28afeSJean-Philippe Brucker 	u8 next;
908dd28afeSJean-Philippe Brucker 	u16 ctrl;
918dd28afeSJean-Philippe Brucker 	u32 address_lo;
928dd28afeSJean-Philippe Brucker 	u16 data;
938dd28afeSJean-Philippe Brucker 	u16 _align;
948dd28afeSJean-Philippe Brucker 	u32 mask_bits;
958dd28afeSJean-Philippe Brucker 	u32 pend_bits;
968dd28afeSJean-Philippe Brucker };
978dd28afeSJean-Philippe Brucker 
981a51c93dSJean-Philippe Brucker struct pci_cap_hdr {
991a51c93dSJean-Philippe Brucker 	u8	type;
1001a51c93dSJean-Philippe Brucker 	u8	next;
1011a51c93dSJean-Philippe Brucker };
1021a51c93dSJean-Philippe Brucker 
1035a8e4f25SAlexandru Elisei struct pci_device_header;
1045a8e4f25SAlexandru Elisei 
1055a8e4f25SAlexandru Elisei typedef int (*bar_activate_fn_t)(struct kvm *kvm,
1065a8e4f25SAlexandru Elisei 				 struct pci_device_header *pci_hdr,
1075a8e4f25SAlexandru Elisei 				 int bar_num, void *data);
1085a8e4f25SAlexandru Elisei typedef int (*bar_deactivate_fn_t)(struct kvm *kvm,
1095a8e4f25SAlexandru Elisei 				   struct pci_device_header *pci_hdr,
1105a8e4f25SAlexandru Elisei 				   int bar_num, void *data);
1115a8e4f25SAlexandru Elisei 
112023fdaaeSJean-Philippe Brucker #define PCI_BAR_OFFSET(b)	(offsetof(struct pci_device_header, bar[b]))
113023fdaaeSJean-Philippe Brucker #define PCI_DEV_CFG_SIZE	256
114023fdaaeSJean-Philippe Brucker #define PCI_DEV_CFG_MASK	(PCI_DEV_CFG_SIZE - 1)
115023fdaaeSJean-Philippe Brucker 
116023fdaaeSJean-Philippe Brucker struct pci_config_operations {
117023fdaaeSJean-Philippe Brucker 	void (*write)(struct kvm *kvm, struct pci_device_header *pci_hdr,
118023fdaaeSJean-Philippe Brucker 		      u8 offset, void *data, int sz);
119023fdaaeSJean-Philippe Brucker 	void (*read)(struct kvm *kvm, struct pci_device_header *pci_hdr,
120023fdaaeSJean-Philippe Brucker 		     u8 offset, void *data, int sz);
121023fdaaeSJean-Philippe Brucker };
122023fdaaeSJean-Philippe Brucker 
12376f9c841SCyrill Gorcunov struct pci_device_header {
124023fdaaeSJean-Philippe Brucker 	/* Configuration space, as seen by the guest */
125023fdaaeSJean-Philippe Brucker 	union {
126023fdaaeSJean-Philippe Brucker 		struct {
1273fdf659dSSasha Levin 			u16		vendor_id;
1283fdf659dSSasha Levin 			u16		device_id;
1293fdf659dSSasha Levin 			u16		command;
1303fdf659dSSasha Levin 			u16		status;
131aa73be70SMatt Evans 			u8		revision_id;
132aa73be70SMatt Evans 			u8		class[3];
1333fdf659dSSasha Levin 			u8		cacheline_size;
1343fdf659dSSasha Levin 			u8		latency_timer;
1353fdf659dSSasha Levin 			u8		header_type;
1363fdf659dSSasha Levin 			u8		bist;
1373fdf659dSSasha Levin 			u32		bar[6];
1383fdf659dSSasha Levin 			u32		card_bus;
1393fdf659dSSasha Levin 			u16		subsys_vendor_id;
1403fdf659dSSasha Levin 			u16		subsys_id;
1413fdf659dSSasha Levin 			u32		exp_rom_bar;
142aa73be70SMatt Evans 			u8		capabilities;
143aa73be70SMatt Evans 			u8		reserved1[3];
1443fdf659dSSasha Levin 			u32		reserved2;
1453fdf659dSSasha Levin 			u8		irq_line;
1463fdf659dSSasha Levin 			u8		irq_pin;
1473fdf659dSSasha Levin 			u8		min_gnt;
1483fdf659dSSasha Levin 			u8		max_lat;
149bc485053SSasha Levin 			struct msix_cap msix;
150aa73be70SMatt Evans 		} __attribute__((packed));
151023fdaaeSJean-Philippe Brucker 		/* Pad to PCI config space size */
152023fdaaeSJean-Philippe Brucker 		u8	__pad[PCI_DEV_CFG_SIZE];
153023fdaaeSJean-Philippe Brucker 	};
154023fdaaeSJean-Philippe Brucker 
155023fdaaeSJean-Philippe Brucker 	/* Private to lkvm */
156023fdaaeSJean-Philippe Brucker 	u32			bar_size[6];
157*465edc9dSAlexandru Elisei 	bool			bar_active[6];
1585a8e4f25SAlexandru Elisei 	bar_activate_fn_t	bar_activate_fn;
1595a8e4f25SAlexandru Elisei 	bar_deactivate_fn_t	bar_deactivate_fn;
1605a8e4f25SAlexandru Elisei 	void *data;
161023fdaaeSJean-Philippe Brucker 	struct pci_config_operations	cfg_ops;
162ff01b5dbSJean-Philippe Brucker 	/*
163ff01b5dbSJean-Philippe Brucker 	 * PCI INTx# are level-triggered, but virtual device often feature
164ff01b5dbSJean-Philippe Brucker 	 * edge-triggered INTx# for convenience.
165ff01b5dbSJean-Philippe Brucker 	 */
166ff01b5dbSJean-Philippe Brucker 	enum irq_type	irq_type;
167023fdaaeSJean-Philippe Brucker };
16876f9c841SCyrill Gorcunov 
1691a51c93dSJean-Philippe Brucker #define PCI_CAP(pci_hdr, pos) ((void *)(pci_hdr) + (pos))
1701a51c93dSJean-Philippe Brucker 
1711a51c93dSJean-Philippe Brucker #define pci_for_each_cap(pos, cap, hdr)				\
1721a51c93dSJean-Philippe Brucker 	for ((pos) = (hdr)->capabilities & ~3;			\
1731a51c93dSJean-Philippe Brucker 	     (cap) = PCI_CAP(hdr, pos), (pos) != 0;		\
1741a51c93dSJean-Philippe Brucker 	     (pos) = ((struct pci_cap_hdr *)(cap))->next & ~3)
1751a51c93dSJean-Philippe Brucker 
1766d987703SSasha Levin int pci__init(struct kvm *kvm);
1776d987703SSasha Levin int pci__exit(struct kvm *kvm);
178d0297a59SMatt Evans struct pci_device_header *pci__find_dev(u8 dev_num);
179854aa2efSJulien Thierry u32 pci_get_mmio_block(u32 size);
180854aa2efSJulien Thierry u16 pci_get_io_port_block(u32 size);
181c0c45eedSAndre Przywara int pci__assign_irq(struct pci_device_header *pci_hdr);
182d0297a59SMatt Evans void pci__config_wr(struct kvm *kvm, union pci_config_address addr, void *data, int size);
183d0297a59SMatt Evans void pci__config_rd(struct kvm *kvm, union pci_config_address addr, void *data, int size);
18460742802SPekka Enberg 
1851a51c93dSJean-Philippe Brucker void *pci_find_cap(struct pci_device_header *hdr, u8 cap_type);
1861a51c93dSJean-Philippe Brucker 
1875a8e4f25SAlexandru Elisei int pci__register_bar_regions(struct kvm *kvm, struct pci_device_header *pci_hdr,
1885a8e4f25SAlexandru Elisei 			      bar_activate_fn_t bar_activate_fn,
1895a8e4f25SAlexandru Elisei 			      bar_deactivate_fn_t bar_deactivate_fn, void *data);
1905a8e4f25SAlexandru Elisei 
1912f6384f9SAlexandru Elisei static inline bool __pci__memory_space_enabled(u16 command)
1922f6384f9SAlexandru Elisei {
1932f6384f9SAlexandru Elisei 	return command & PCI_COMMAND_MEMORY;
1942f6384f9SAlexandru Elisei }
1952f6384f9SAlexandru Elisei 
1962f6384f9SAlexandru Elisei static inline bool pci__memory_space_enabled(struct pci_device_header *pci_hdr)
1972f6384f9SAlexandru Elisei {
1982f6384f9SAlexandru Elisei 	return __pci__memory_space_enabled(pci_hdr->command);
1992f6384f9SAlexandru Elisei }
2002f6384f9SAlexandru Elisei 
2012f6384f9SAlexandru Elisei static inline bool __pci__io_space_enabled(u16 command)
2022f6384f9SAlexandru Elisei {
2032f6384f9SAlexandru Elisei 	return command & PCI_COMMAND_IO;
2042f6384f9SAlexandru Elisei }
2052f6384f9SAlexandru Elisei 
2062f6384f9SAlexandru Elisei static inline bool pci__io_space_enabled(struct pci_device_header *pci_hdr)
2072f6384f9SAlexandru Elisei {
2082f6384f9SAlexandru Elisei 	return __pci__io_space_enabled(pci_hdr->command);
2092f6384f9SAlexandru Elisei }
2102f6384f9SAlexandru Elisei 
2112f6384f9SAlexandru Elisei static inline bool __pci__bar_is_io(u32 bar)
2122f6384f9SAlexandru Elisei {
2132f6384f9SAlexandru Elisei 	return bar & PCI_BASE_ADDRESS_SPACE_IO;
2142f6384f9SAlexandru Elisei }
2152f6384f9SAlexandru Elisei 
2162f6384f9SAlexandru Elisei static inline bool pci__bar_is_io(struct pci_device_header *pci_hdr, int bar_num)
2172f6384f9SAlexandru Elisei {
2182f6384f9SAlexandru Elisei 	return __pci__bar_is_io(pci_hdr->bar[bar_num]);
2192f6384f9SAlexandru Elisei }
2202f6384f9SAlexandru Elisei 
2212f6384f9SAlexandru Elisei static inline bool pci__bar_is_memory(struct pci_device_header *pci_hdr, int bar_num)
2222f6384f9SAlexandru Elisei {
2232f6384f9SAlexandru Elisei 	return !pci__bar_is_io(pci_hdr, bar_num);
2242f6384f9SAlexandru Elisei }
2252f6384f9SAlexandru Elisei 
2262f6384f9SAlexandru Elisei static inline u32 __pci__bar_address(u32 bar)
2272f6384f9SAlexandru Elisei {
2282f6384f9SAlexandru Elisei 	if (__pci__bar_is_io(bar))
2292f6384f9SAlexandru Elisei 		return bar & PCI_BASE_ADDRESS_IO_MASK;
2302f6384f9SAlexandru Elisei 	return bar & PCI_BASE_ADDRESS_MEM_MASK;
2312f6384f9SAlexandru Elisei }
2322f6384f9SAlexandru Elisei 
2332f6384f9SAlexandru Elisei static inline u32 pci__bar_address(struct pci_device_header *pci_hdr, int bar_num)
2342f6384f9SAlexandru Elisei {
2352f6384f9SAlexandru Elisei 	return __pci__bar_address(pci_hdr->bar[bar_num]);
2362f6384f9SAlexandru Elisei }
2372f6384f9SAlexandru Elisei 
2382f6384f9SAlexandru Elisei static inline u32 pci__bar_size(struct pci_device_header *pci_hdr, int bar_num)
2392f6384f9SAlexandru Elisei {
2402f6384f9SAlexandru Elisei 	return pci_hdr->bar_size[bar_num];
2412f6384f9SAlexandru Elisei }
2422f6384f9SAlexandru Elisei 
24360742802SPekka Enberg #endif /* KVM__PCI_H */
244