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> 8*2f6384f9SAlexandru 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 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 23854aa2efSJulien Thierry #define PCI_IOPORT_START 0x6200 24b403f2f7SWill Deacon #define PCI_CFG_SIZE (1ULL << 24) 25305b72ceSCyrill Gorcunov 266078a454SJean-Philippe Brucker struct kvm; 276078a454SJean-Philippe Brucker 28aa73be70SMatt Evans union pci_config_address { 29aa73be70SMatt Evans struct { 30aa73be70SMatt Evans #if __BYTE_ORDER == __LITTLE_ENDIAN 31d0297a59SMatt Evans unsigned reg_offset : 2; /* 1 .. 0 */ 324402a581SPekka Enberg unsigned register_number : 6; /* 7 .. 2 */ 334402a581SPekka Enberg unsigned function_number : 3; /* 10 .. 8 */ 344402a581SPekka Enberg unsigned device_number : 5; /* 15 .. 11 */ 354402a581SPekka Enberg unsigned bus_number : 8; /* 23 .. 16 */ 364402a581SPekka Enberg unsigned reserved : 7; /* 30 .. 24 */ 374402a581SPekka Enberg unsigned enable_bit : 1; /* 31 */ 38aa73be70SMatt Evans #else 39aa73be70SMatt Evans unsigned enable_bit : 1; /* 31 */ 40aa73be70SMatt Evans unsigned reserved : 7; /* 30 .. 24 */ 41aa73be70SMatt Evans unsigned bus_number : 8; /* 23 .. 16 */ 42aa73be70SMatt Evans unsigned device_number : 5; /* 15 .. 11 */ 43aa73be70SMatt Evans unsigned function_number : 3; /* 10 .. 8 */ 44aa73be70SMatt Evans unsigned register_number : 6; /* 7 .. 2 */ 45d0297a59SMatt Evans unsigned reg_offset : 2; /* 1 .. 0 */ 46aa73be70SMatt Evans #endif 47aa73be70SMatt Evans }; 48aa73be70SMatt Evans u32 w; 494402a581SPekka Enberg }; 504402a581SPekka Enberg 51bc485053SSasha Levin struct msix_table { 521de74957SSasha Levin struct msi_msg msg; 53bc485053SSasha Levin u32 ctrl; 54bc485053SSasha Levin }; 55bc485053SSasha Levin 56bc485053SSasha Levin struct msix_cap { 57bc485053SSasha Levin u8 cap; 58bc485053SSasha Levin u8 next; 5906f48103SSasha Levin u16 ctrl; 60bc485053SSasha Levin u32 table_offset; 6106f48103SSasha Levin u32 pba_offset; 62bc485053SSasha Levin }; 63bc485053SSasha Levin 648dd28afeSJean-Philippe Brucker struct msi_cap_64 { 658dd28afeSJean-Philippe Brucker u8 cap; 668dd28afeSJean-Philippe Brucker u8 next; 678dd28afeSJean-Philippe Brucker u16 ctrl; 688dd28afeSJean-Philippe Brucker u32 address_lo; 698dd28afeSJean-Philippe Brucker u32 address_hi; 708dd28afeSJean-Philippe Brucker u16 data; 718dd28afeSJean-Philippe Brucker u16 _align; 728dd28afeSJean-Philippe Brucker u32 mask_bits; 738dd28afeSJean-Philippe Brucker u32 pend_bits; 748dd28afeSJean-Philippe Brucker }; 758dd28afeSJean-Philippe Brucker 768dd28afeSJean-Philippe Brucker struct msi_cap_32 { 778dd28afeSJean-Philippe Brucker u8 cap; 788dd28afeSJean-Philippe Brucker u8 next; 798dd28afeSJean-Philippe Brucker u16 ctrl; 808dd28afeSJean-Philippe Brucker u32 address_lo; 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 871a51c93dSJean-Philippe Brucker struct pci_cap_hdr { 881a51c93dSJean-Philippe Brucker u8 type; 891a51c93dSJean-Philippe Brucker u8 next; 901a51c93dSJean-Philippe Brucker }; 911a51c93dSJean-Philippe Brucker 92023fdaaeSJean-Philippe Brucker #define PCI_BAR_OFFSET(b) (offsetof(struct pci_device_header, bar[b])) 93023fdaaeSJean-Philippe Brucker #define PCI_DEV_CFG_SIZE 256 94023fdaaeSJean-Philippe Brucker #define PCI_DEV_CFG_MASK (PCI_DEV_CFG_SIZE - 1) 95023fdaaeSJean-Philippe Brucker 96023fdaaeSJean-Philippe Brucker struct pci_device_header; 97023fdaaeSJean-Philippe Brucker 98023fdaaeSJean-Philippe Brucker struct pci_config_operations { 99023fdaaeSJean-Philippe Brucker void (*write)(struct kvm *kvm, struct pci_device_header *pci_hdr, 100023fdaaeSJean-Philippe Brucker u8 offset, void *data, int sz); 101023fdaaeSJean-Philippe Brucker void (*read)(struct kvm *kvm, struct pci_device_header *pci_hdr, 102023fdaaeSJean-Philippe Brucker u8 offset, void *data, int sz); 103023fdaaeSJean-Philippe Brucker }; 104023fdaaeSJean-Philippe Brucker 10576f9c841SCyrill Gorcunov struct pci_device_header { 106023fdaaeSJean-Philippe Brucker /* Configuration space, as seen by the guest */ 107023fdaaeSJean-Philippe Brucker union { 108023fdaaeSJean-Philippe Brucker struct { 1093fdf659dSSasha Levin u16 vendor_id; 1103fdf659dSSasha Levin u16 device_id; 1113fdf659dSSasha Levin u16 command; 1123fdf659dSSasha Levin u16 status; 113aa73be70SMatt Evans u8 revision_id; 114aa73be70SMatt Evans u8 class[3]; 1153fdf659dSSasha Levin u8 cacheline_size; 1163fdf659dSSasha Levin u8 latency_timer; 1173fdf659dSSasha Levin u8 header_type; 1183fdf659dSSasha Levin u8 bist; 1193fdf659dSSasha Levin u32 bar[6]; 1203fdf659dSSasha Levin u32 card_bus; 1213fdf659dSSasha Levin u16 subsys_vendor_id; 1223fdf659dSSasha Levin u16 subsys_id; 1233fdf659dSSasha Levin u32 exp_rom_bar; 124aa73be70SMatt Evans u8 capabilities; 125aa73be70SMatt Evans u8 reserved1[3]; 1263fdf659dSSasha Levin u32 reserved2; 1273fdf659dSSasha Levin u8 irq_line; 1283fdf659dSSasha Levin u8 irq_pin; 1293fdf659dSSasha Levin u8 min_gnt; 1303fdf659dSSasha Levin u8 max_lat; 131bc485053SSasha Levin struct msix_cap msix; 132aa73be70SMatt Evans } __attribute__((packed)); 133023fdaaeSJean-Philippe Brucker /* Pad to PCI config space size */ 134023fdaaeSJean-Philippe Brucker u8 __pad[PCI_DEV_CFG_SIZE]; 135023fdaaeSJean-Philippe Brucker }; 136023fdaaeSJean-Philippe Brucker 137023fdaaeSJean-Philippe Brucker /* Private to lkvm */ 138023fdaaeSJean-Philippe Brucker u32 bar_size[6]; 139023fdaaeSJean-Philippe Brucker struct pci_config_operations cfg_ops; 140ff01b5dbSJean-Philippe Brucker /* 141ff01b5dbSJean-Philippe Brucker * PCI INTx# are level-triggered, but virtual device often feature 142ff01b5dbSJean-Philippe Brucker * edge-triggered INTx# for convenience. 143ff01b5dbSJean-Philippe Brucker */ 144ff01b5dbSJean-Philippe Brucker enum irq_type irq_type; 145023fdaaeSJean-Philippe Brucker }; 14676f9c841SCyrill Gorcunov 1471a51c93dSJean-Philippe Brucker #define PCI_CAP(pci_hdr, pos) ((void *)(pci_hdr) + (pos)) 1481a51c93dSJean-Philippe Brucker 1491a51c93dSJean-Philippe Brucker #define pci_for_each_cap(pos, cap, hdr) \ 1501a51c93dSJean-Philippe Brucker for ((pos) = (hdr)->capabilities & ~3; \ 1511a51c93dSJean-Philippe Brucker (cap) = PCI_CAP(hdr, pos), (pos) != 0; \ 1521a51c93dSJean-Philippe Brucker (pos) = ((struct pci_cap_hdr *)(cap))->next & ~3) 1531a51c93dSJean-Philippe Brucker 1546d987703SSasha Levin int pci__init(struct kvm *kvm); 1556d987703SSasha Levin int pci__exit(struct kvm *kvm); 156d0297a59SMatt Evans struct pci_device_header *pci__find_dev(u8 dev_num); 157854aa2efSJulien Thierry u32 pci_get_mmio_block(u32 size); 158854aa2efSJulien Thierry u16 pci_get_io_port_block(u32 size); 159c0c45eedSAndre Przywara int pci__assign_irq(struct pci_device_header *pci_hdr); 160d0297a59SMatt Evans void pci__config_wr(struct kvm *kvm, union pci_config_address addr, void *data, int size); 161d0297a59SMatt Evans void pci__config_rd(struct kvm *kvm, union pci_config_address addr, void *data, int size); 16260742802SPekka Enberg 1631a51c93dSJean-Philippe Brucker void *pci_find_cap(struct pci_device_header *hdr, u8 cap_type); 1641a51c93dSJean-Philippe Brucker 165*2f6384f9SAlexandru Elisei static inline bool __pci__memory_space_enabled(u16 command) 166*2f6384f9SAlexandru Elisei { 167*2f6384f9SAlexandru Elisei return command & PCI_COMMAND_MEMORY; 168*2f6384f9SAlexandru Elisei } 169*2f6384f9SAlexandru Elisei 170*2f6384f9SAlexandru Elisei static inline bool pci__memory_space_enabled(struct pci_device_header *pci_hdr) 171*2f6384f9SAlexandru Elisei { 172*2f6384f9SAlexandru Elisei return __pci__memory_space_enabled(pci_hdr->command); 173*2f6384f9SAlexandru Elisei } 174*2f6384f9SAlexandru Elisei 175*2f6384f9SAlexandru Elisei static inline bool __pci__io_space_enabled(u16 command) 176*2f6384f9SAlexandru Elisei { 177*2f6384f9SAlexandru Elisei return command & PCI_COMMAND_IO; 178*2f6384f9SAlexandru Elisei } 179*2f6384f9SAlexandru Elisei 180*2f6384f9SAlexandru Elisei static inline bool pci__io_space_enabled(struct pci_device_header *pci_hdr) 181*2f6384f9SAlexandru Elisei { 182*2f6384f9SAlexandru Elisei return __pci__io_space_enabled(pci_hdr->command); 183*2f6384f9SAlexandru Elisei } 184*2f6384f9SAlexandru Elisei 185*2f6384f9SAlexandru Elisei static inline bool __pci__bar_is_io(u32 bar) 186*2f6384f9SAlexandru Elisei { 187*2f6384f9SAlexandru Elisei return bar & PCI_BASE_ADDRESS_SPACE_IO; 188*2f6384f9SAlexandru Elisei } 189*2f6384f9SAlexandru Elisei 190*2f6384f9SAlexandru Elisei static inline bool pci__bar_is_io(struct pci_device_header *pci_hdr, int bar_num) 191*2f6384f9SAlexandru Elisei { 192*2f6384f9SAlexandru Elisei return __pci__bar_is_io(pci_hdr->bar[bar_num]); 193*2f6384f9SAlexandru Elisei } 194*2f6384f9SAlexandru Elisei 195*2f6384f9SAlexandru Elisei static inline bool pci__bar_is_memory(struct pci_device_header *pci_hdr, int bar_num) 196*2f6384f9SAlexandru Elisei { 197*2f6384f9SAlexandru Elisei return !pci__bar_is_io(pci_hdr, bar_num); 198*2f6384f9SAlexandru Elisei } 199*2f6384f9SAlexandru Elisei 200*2f6384f9SAlexandru Elisei static inline u32 __pci__bar_address(u32 bar) 201*2f6384f9SAlexandru Elisei { 202*2f6384f9SAlexandru Elisei if (__pci__bar_is_io(bar)) 203*2f6384f9SAlexandru Elisei return bar & PCI_BASE_ADDRESS_IO_MASK; 204*2f6384f9SAlexandru Elisei return bar & PCI_BASE_ADDRESS_MEM_MASK; 205*2f6384f9SAlexandru Elisei } 206*2f6384f9SAlexandru Elisei 207*2f6384f9SAlexandru Elisei static inline u32 pci__bar_address(struct pci_device_header *pci_hdr, int bar_num) 208*2f6384f9SAlexandru Elisei { 209*2f6384f9SAlexandru Elisei return __pci__bar_address(pci_hdr->bar[bar_num]); 210*2f6384f9SAlexandru Elisei } 211*2f6384f9SAlexandru Elisei 212*2f6384f9SAlexandru Elisei static inline u32 pci__bar_size(struct pci_device_header *pci_hdr, int bar_num) 213*2f6384f9SAlexandru Elisei { 214*2f6384f9SAlexandru Elisei return pci_hdr->bar_size[bar_num]; 215*2f6384f9SAlexandru Elisei } 216*2f6384f9SAlexandru Elisei 21760742802SPekka Enberg #endif /* KVM__PCI_H */ 218