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