xref: /kvmtool/include/kvm/pci.h (revision 6078a4548cfdca42c766c67947986c90310a8546)
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>
876f9c841SCyrill Gorcunov 
9b5981636SWill Deacon #include "kvm/devices.h"
10f7c17d7cSPekka Enberg #include "kvm/msi.h"
11ff01b5dbSJean-Philippe Brucker #include "kvm/fdt.h"
12d0297a59SMatt Evans 
134402a581SPekka Enberg /*
144402a581SPekka Enberg  * PCI Configuration Mechanism #1 I/O ports. See Section 3.7.4.1.
154402a581SPekka Enberg  * ("Configuration Mechanism #1") of the PCI Local Bus Specification 2.1 for
164402a581SPekka Enberg  * details.
174402a581SPekka Enberg  */
18305b72ceSCyrill Gorcunov #define PCI_CONFIG_ADDRESS	0xcf8
19305b72ceSCyrill Gorcunov #define PCI_CONFIG_DATA		0xcfc
202b9e4709SCyrill Gorcunov #define PCI_CONFIG_BUS_FORWARD	0xcfa
2195d13a52SSasha Levin #define PCI_IO_SIZE		0x100
22b403f2f7SWill Deacon #define PCI_CFG_SIZE		(1ULL << 24)
23305b72ceSCyrill Gorcunov 
24*6078a454SJean-Philippe Brucker struct kvm;
25*6078a454SJean-Philippe Brucker 
26aa73be70SMatt Evans union pci_config_address {
27aa73be70SMatt Evans 	struct {
28aa73be70SMatt Evans #if __BYTE_ORDER == __LITTLE_ENDIAN
29d0297a59SMatt Evans 		unsigned	reg_offset	: 2;		/* 1  .. 0  */
304402a581SPekka Enberg 		unsigned	register_number	: 6;		/* 7  .. 2  */
314402a581SPekka Enberg 		unsigned	function_number	: 3;		/* 10 .. 8  */
324402a581SPekka Enberg 		unsigned	device_number	: 5;		/* 15 .. 11 */
334402a581SPekka Enberg 		unsigned	bus_number	: 8;		/* 23 .. 16 */
344402a581SPekka Enberg 		unsigned	reserved	: 7;		/* 30 .. 24 */
354402a581SPekka Enberg 		unsigned	enable_bit	: 1;		/* 31       */
36aa73be70SMatt Evans #else
37aa73be70SMatt Evans 		unsigned	enable_bit	: 1;		/* 31       */
38aa73be70SMatt Evans 		unsigned	reserved	: 7;		/* 30 .. 24 */
39aa73be70SMatt Evans 		unsigned	bus_number	: 8;		/* 23 .. 16 */
40aa73be70SMatt Evans 		unsigned	device_number	: 5;		/* 15 .. 11 */
41aa73be70SMatt Evans 		unsigned	function_number	: 3;		/* 10 .. 8  */
42aa73be70SMatt Evans 		unsigned	register_number	: 6;		/* 7  .. 2  */
43d0297a59SMatt Evans 		unsigned	reg_offset	: 2;		/* 1  .. 0  */
44aa73be70SMatt Evans #endif
45aa73be70SMatt Evans 	};
46aa73be70SMatt Evans 	u32 w;
474402a581SPekka Enberg };
484402a581SPekka Enberg 
49bc485053SSasha Levin struct msix_table {
501de74957SSasha Levin 	struct msi_msg msg;
51bc485053SSasha Levin 	u32 ctrl;
52bc485053SSasha Levin };
53bc485053SSasha Levin 
54bc485053SSasha Levin struct msix_cap {
55bc485053SSasha Levin 	u8 cap;
56bc485053SSasha Levin 	u8 next;
5706f48103SSasha Levin 	u16 ctrl;
58bc485053SSasha Levin 	u32 table_offset;
5906f48103SSasha Levin 	u32 pba_offset;
60bc485053SSasha Levin };
61bc485053SSasha Levin 
621a51c93dSJean-Philippe Brucker struct pci_cap_hdr {
631a51c93dSJean-Philippe Brucker 	u8	type;
641a51c93dSJean-Philippe Brucker 	u8	next;
651a51c93dSJean-Philippe Brucker };
661a51c93dSJean-Philippe Brucker 
67023fdaaeSJean-Philippe Brucker #define PCI_BAR_OFFSET(b)	(offsetof(struct pci_device_header, bar[b]))
68023fdaaeSJean-Philippe Brucker #define PCI_DEV_CFG_SIZE	256
69023fdaaeSJean-Philippe Brucker #define PCI_DEV_CFG_MASK	(PCI_DEV_CFG_SIZE - 1)
70023fdaaeSJean-Philippe Brucker 
71023fdaaeSJean-Philippe Brucker struct pci_device_header;
72023fdaaeSJean-Philippe Brucker 
73023fdaaeSJean-Philippe Brucker struct pci_config_operations {
74023fdaaeSJean-Philippe Brucker 	void (*write)(struct kvm *kvm, struct pci_device_header *pci_hdr,
75023fdaaeSJean-Philippe Brucker 		      u8 offset, void *data, int sz);
76023fdaaeSJean-Philippe Brucker 	void (*read)(struct kvm *kvm, struct pci_device_header *pci_hdr,
77023fdaaeSJean-Philippe Brucker 		     u8 offset, void *data, int sz);
78023fdaaeSJean-Philippe Brucker };
79023fdaaeSJean-Philippe Brucker 
8076f9c841SCyrill Gorcunov struct pci_device_header {
81023fdaaeSJean-Philippe Brucker 	/* Configuration space, as seen by the guest */
82023fdaaeSJean-Philippe Brucker 	union {
83023fdaaeSJean-Philippe Brucker 		struct {
843fdf659dSSasha Levin 			u16		vendor_id;
853fdf659dSSasha Levin 			u16		device_id;
863fdf659dSSasha Levin 			u16		command;
873fdf659dSSasha Levin 			u16		status;
88aa73be70SMatt Evans 			u8		revision_id;
89aa73be70SMatt Evans 			u8		class[3];
903fdf659dSSasha Levin 			u8		cacheline_size;
913fdf659dSSasha Levin 			u8		latency_timer;
923fdf659dSSasha Levin 			u8		header_type;
933fdf659dSSasha Levin 			u8		bist;
943fdf659dSSasha Levin 			u32		bar[6];
953fdf659dSSasha Levin 			u32		card_bus;
963fdf659dSSasha Levin 			u16		subsys_vendor_id;
973fdf659dSSasha Levin 			u16		subsys_id;
983fdf659dSSasha Levin 			u32		exp_rom_bar;
99aa73be70SMatt Evans 			u8		capabilities;
100aa73be70SMatt Evans 			u8		reserved1[3];
1013fdf659dSSasha Levin 			u32		reserved2;
1023fdf659dSSasha Levin 			u8		irq_line;
1033fdf659dSSasha Levin 			u8		irq_pin;
1043fdf659dSSasha Levin 			u8		min_gnt;
1053fdf659dSSasha Levin 			u8		max_lat;
106bc485053SSasha Levin 			struct msix_cap msix;
107aa73be70SMatt Evans 		} __attribute__((packed));
108023fdaaeSJean-Philippe Brucker 		/* Pad to PCI config space size */
109023fdaaeSJean-Philippe Brucker 		u8	__pad[PCI_DEV_CFG_SIZE];
110023fdaaeSJean-Philippe Brucker 	};
111023fdaaeSJean-Philippe Brucker 
112023fdaaeSJean-Philippe Brucker 	/* Private to lkvm */
113023fdaaeSJean-Philippe Brucker 	u32		bar_size[6];
114023fdaaeSJean-Philippe Brucker 	struct pci_config_operations	cfg_ops;
115ff01b5dbSJean-Philippe Brucker 	/*
116ff01b5dbSJean-Philippe Brucker 	 * PCI INTx# are level-triggered, but virtual device often feature
117ff01b5dbSJean-Philippe Brucker 	 * edge-triggered INTx# for convenience.
118ff01b5dbSJean-Philippe Brucker 	 */
119ff01b5dbSJean-Philippe Brucker 	enum irq_type	irq_type;
120023fdaaeSJean-Philippe Brucker };
12176f9c841SCyrill Gorcunov 
1221a51c93dSJean-Philippe Brucker #define PCI_CAP(pci_hdr, pos) ((void *)(pci_hdr) + (pos))
1231a51c93dSJean-Philippe Brucker 
1241a51c93dSJean-Philippe Brucker #define pci_for_each_cap(pos, cap, hdr)				\
1251a51c93dSJean-Philippe Brucker 	for ((pos) = (hdr)->capabilities & ~3;			\
1261a51c93dSJean-Philippe Brucker 	     (cap) = PCI_CAP(hdr, pos), (pos) != 0;		\
1271a51c93dSJean-Philippe Brucker 	     (pos) = ((struct pci_cap_hdr *)(cap))->next & ~3)
1281a51c93dSJean-Philippe Brucker 
1296d987703SSasha Levin int pci__init(struct kvm *kvm);
1306d987703SSasha Levin int pci__exit(struct kvm *kvm);
131d0297a59SMatt Evans struct pci_device_header *pci__find_dev(u8 dev_num);
13295d13a52SSasha Levin u32 pci_get_io_space_block(u32 size);
133b5981636SWill Deacon void pci__assign_irq(struct device_header *dev_hdr);
134d0297a59SMatt Evans void pci__config_wr(struct kvm *kvm, union pci_config_address addr, void *data, int size);
135d0297a59SMatt Evans void pci__config_rd(struct kvm *kvm, union pci_config_address addr, void *data, int size);
13660742802SPekka Enberg 
1371a51c93dSJean-Philippe Brucker void *pci_find_cap(struct pci_device_header *hdr, u8 cap_type);
1381a51c93dSJean-Philippe Brucker 
13960742802SPekka Enberg #endif /* KVM__PCI_H */
140