xref: /kvmtool/include/kvm/pci.h (revision ff01b5dbbd040d39619f0f033da6eac5dbed3b2b)
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"
10d0297a59SMatt Evans #include "kvm/kvm.h"
11f7c17d7cSPekka Enberg #include "kvm/msi.h"
12*ff01b5dbSJean-Philippe Brucker #include "kvm/fdt.h"
13d0297a59SMatt Evans 
144402a581SPekka Enberg /*
154402a581SPekka Enberg  * PCI Configuration Mechanism #1 I/O ports. See Section 3.7.4.1.
164402a581SPekka Enberg  * ("Configuration Mechanism #1") of the PCI Local Bus Specification 2.1 for
174402a581SPekka Enberg  * details.
184402a581SPekka Enberg  */
19305b72ceSCyrill Gorcunov #define PCI_CONFIG_ADDRESS	0xcf8
20305b72ceSCyrill Gorcunov #define PCI_CONFIG_DATA		0xcfc
212b9e4709SCyrill Gorcunov #define PCI_CONFIG_BUS_FORWARD	0xcfa
2295d13a52SSasha Levin #define PCI_IO_SIZE		0x100
23b403f2f7SWill Deacon #define PCI_CFG_SIZE		(1ULL << 24)
24305b72ceSCyrill Gorcunov 
25aa73be70SMatt Evans union pci_config_address {
26aa73be70SMatt Evans 	struct {
27aa73be70SMatt Evans #if __BYTE_ORDER == __LITTLE_ENDIAN
28d0297a59SMatt Evans 		unsigned	reg_offset	: 2;		/* 1  .. 0  */
294402a581SPekka Enberg 		unsigned	register_number	: 6;		/* 7  .. 2  */
304402a581SPekka Enberg 		unsigned	function_number	: 3;		/* 10 .. 8  */
314402a581SPekka Enberg 		unsigned	device_number	: 5;		/* 15 .. 11 */
324402a581SPekka Enberg 		unsigned	bus_number	: 8;		/* 23 .. 16 */
334402a581SPekka Enberg 		unsigned	reserved	: 7;		/* 30 .. 24 */
344402a581SPekka Enberg 		unsigned	enable_bit	: 1;		/* 31       */
35aa73be70SMatt Evans #else
36aa73be70SMatt Evans 		unsigned	enable_bit	: 1;		/* 31       */
37aa73be70SMatt Evans 		unsigned	reserved	: 7;		/* 30 .. 24 */
38aa73be70SMatt Evans 		unsigned	bus_number	: 8;		/* 23 .. 16 */
39aa73be70SMatt Evans 		unsigned	device_number	: 5;		/* 15 .. 11 */
40aa73be70SMatt Evans 		unsigned	function_number	: 3;		/* 10 .. 8  */
41aa73be70SMatt Evans 		unsigned	register_number	: 6;		/* 7  .. 2  */
42d0297a59SMatt Evans 		unsigned	reg_offset	: 2;		/* 1  .. 0  */
43aa73be70SMatt Evans #endif
44aa73be70SMatt Evans 	};
45aa73be70SMatt Evans 	u32 w;
464402a581SPekka Enberg };
474402a581SPekka Enberg 
48bc485053SSasha Levin struct msix_table {
491de74957SSasha Levin 	struct msi_msg msg;
50bc485053SSasha Levin 	u32 ctrl;
51bc485053SSasha Levin };
52bc485053SSasha Levin 
53bc485053SSasha Levin struct msix_cap {
54bc485053SSasha Levin 	u8 cap;
55bc485053SSasha Levin 	u8 next;
5606f48103SSasha Levin 	u16 ctrl;
57bc485053SSasha Levin 	u32 table_offset;
5806f48103SSasha Levin 	u32 pba_offset;
59bc485053SSasha Levin };
60bc485053SSasha Levin 
61023fdaaeSJean-Philippe Brucker #define PCI_BAR_OFFSET(b)	(offsetof(struct pci_device_header, bar[b]))
62023fdaaeSJean-Philippe Brucker #define PCI_DEV_CFG_SIZE	256
63023fdaaeSJean-Philippe Brucker #define PCI_DEV_CFG_MASK	(PCI_DEV_CFG_SIZE - 1)
64023fdaaeSJean-Philippe Brucker 
65023fdaaeSJean-Philippe Brucker struct pci_device_header;
66023fdaaeSJean-Philippe Brucker 
67023fdaaeSJean-Philippe Brucker struct pci_config_operations {
68023fdaaeSJean-Philippe Brucker 	void (*write)(struct kvm *kvm, struct pci_device_header *pci_hdr,
69023fdaaeSJean-Philippe Brucker 		      u8 offset, void *data, int sz);
70023fdaaeSJean-Philippe Brucker 	void (*read)(struct kvm *kvm, struct pci_device_header *pci_hdr,
71023fdaaeSJean-Philippe Brucker 		     u8 offset, void *data, int sz);
72023fdaaeSJean-Philippe Brucker };
73023fdaaeSJean-Philippe Brucker 
7476f9c841SCyrill Gorcunov struct pci_device_header {
75023fdaaeSJean-Philippe Brucker 	/* Configuration space, as seen by the guest */
76023fdaaeSJean-Philippe Brucker 	union {
77023fdaaeSJean-Philippe Brucker 		struct {
783fdf659dSSasha Levin 			u16		vendor_id;
793fdf659dSSasha Levin 			u16		device_id;
803fdf659dSSasha Levin 			u16		command;
813fdf659dSSasha Levin 			u16		status;
82aa73be70SMatt Evans 			u8		revision_id;
83aa73be70SMatt Evans 			u8		class[3];
843fdf659dSSasha Levin 			u8		cacheline_size;
853fdf659dSSasha Levin 			u8		latency_timer;
863fdf659dSSasha Levin 			u8		header_type;
873fdf659dSSasha Levin 			u8		bist;
883fdf659dSSasha Levin 			u32		bar[6];
893fdf659dSSasha Levin 			u32		card_bus;
903fdf659dSSasha Levin 			u16		subsys_vendor_id;
913fdf659dSSasha Levin 			u16		subsys_id;
923fdf659dSSasha Levin 			u32		exp_rom_bar;
93aa73be70SMatt Evans 			u8		capabilities;
94aa73be70SMatt Evans 			u8		reserved1[3];
953fdf659dSSasha Levin 			u32		reserved2;
963fdf659dSSasha Levin 			u8		irq_line;
973fdf659dSSasha Levin 			u8		irq_pin;
983fdf659dSSasha Levin 			u8		min_gnt;
993fdf659dSSasha Levin 			u8		max_lat;
100bc485053SSasha Levin 			struct msix_cap msix;
101aa73be70SMatt Evans 		} __attribute__((packed));
102023fdaaeSJean-Philippe Brucker 		/* Pad to PCI config space size */
103023fdaaeSJean-Philippe Brucker 		u8	__pad[PCI_DEV_CFG_SIZE];
104023fdaaeSJean-Philippe Brucker 	};
105023fdaaeSJean-Philippe Brucker 
106023fdaaeSJean-Philippe Brucker 	/* Private to lkvm */
107023fdaaeSJean-Philippe Brucker 	u32		bar_size[6];
108023fdaaeSJean-Philippe Brucker 	struct pci_config_operations	cfg_ops;
109*ff01b5dbSJean-Philippe Brucker 	/*
110*ff01b5dbSJean-Philippe Brucker 	 * PCI INTx# are level-triggered, but virtual device often feature
111*ff01b5dbSJean-Philippe Brucker 	 * edge-triggered INTx# for convenience.
112*ff01b5dbSJean-Philippe Brucker 	 */
113*ff01b5dbSJean-Philippe Brucker 	enum irq_type	irq_type;
114023fdaaeSJean-Philippe Brucker };
11576f9c841SCyrill Gorcunov 
1166d987703SSasha Levin int pci__init(struct kvm *kvm);
1176d987703SSasha Levin int pci__exit(struct kvm *kvm);
118d0297a59SMatt Evans struct pci_device_header *pci__find_dev(u8 dev_num);
11995d13a52SSasha Levin u32 pci_get_io_space_block(u32 size);
120b5981636SWill Deacon void pci__assign_irq(struct device_header *dev_hdr);
121d0297a59SMatt Evans void pci__config_wr(struct kvm *kvm, union pci_config_address addr, void *data, int size);
122d0297a59SMatt Evans void pci__config_rd(struct kvm *kvm, union pci_config_address addr, void *data, int size);
12360742802SPekka Enberg 
12460742802SPekka Enberg #endif /* KVM__PCI_H */
125