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" 13e69b7663SAlexandru Elisei #include "kvm/kvm-arch.h" 14d0297a59SMatt Evans 15465edc9dSAlexandru Elisei #define pci_dev_err(pci_hdr, fmt, ...) \ 16465edc9dSAlexandru Elisei pr_err("[%04x:%04x] " fmt, pci_hdr->vendor_id, pci_hdr->device_id, ##__VA_ARGS__) 17465edc9dSAlexandru Elisei #define pci_dev_warn(pci_hdr, fmt, ...) \ 18465edc9dSAlexandru Elisei pr_warning("[%04x:%04x] " fmt, pci_hdr->vendor_id, pci_hdr->device_id, ##__VA_ARGS__) 19465edc9dSAlexandru Elisei #define pci_dev_info(pci_hdr, fmt, ...) \ 20465edc9dSAlexandru Elisei pr_info("[%04x:%04x] " fmt, pci_hdr->vendor_id, pci_hdr->device_id, ##__VA_ARGS__) 21465edc9dSAlexandru Elisei #define pci_dev_dbg(pci_hdr, fmt, ...) \ 22465edc9dSAlexandru Elisei pr_debug("[%04x:%04x] " fmt, pci_hdr->vendor_id, pci_hdr->device_id, ##__VA_ARGS__) 23465edc9dSAlexandru Elisei #define pci_dev_die(pci_hdr, fmt, ...) \ 24465edc9dSAlexandru Elisei die("[%04x:%04x] " fmt, pci_hdr->vendor_id, pci_hdr->device_id, ##__VA_ARGS__) 25465edc9dSAlexandru Elisei 264402a581SPekka Enberg /* 274402a581SPekka Enberg * PCI Configuration Mechanism #1 I/O ports. See Section 3.7.4.1. 284402a581SPekka Enberg * ("Configuration Mechanism #1") of the PCI Local Bus Specification 2.1 for 294402a581SPekka Enberg * details. 304402a581SPekka Enberg */ 31305b72ceSCyrill Gorcunov #define PCI_CONFIG_ADDRESS 0xcf8 32305b72ceSCyrill Gorcunov #define PCI_CONFIG_DATA 0xcfc 332b9e4709SCyrill Gorcunov #define PCI_CONFIG_BUS_FORWARD 0xcfa 3495d13a52SSasha Levin #define PCI_IO_SIZE 0x100 35854aa2efSJulien Thierry #define PCI_IOPORT_START 0x6200 36305b72ceSCyrill Gorcunov 376078a454SJean-Philippe Brucker struct kvm; 386078a454SJean-Philippe Brucker 39e69b7663SAlexandru Elisei /* 40e69b7663SAlexandru Elisei * On some distributions, pci_regs.h doesn't define PCI_CFG_SPACE_SIZE and 41e69b7663SAlexandru Elisei * PCI_CFG_SPACE_EXP_SIZE, so we define our own. 42e69b7663SAlexandru Elisei */ 43e69b7663SAlexandru Elisei #define PCI_CFG_SIZE_LEGACY (1ULL << 24) 44e69b7663SAlexandru Elisei #define PCI_DEV_CFG_SIZE_LEGACY 256 45e69b7663SAlexandru Elisei #define PCI_CFG_SIZE_EXTENDED (1ULL << 28) 46e69b7663SAlexandru Elisei #define PCI_DEV_CFG_SIZE_EXTENDED 4096 47e69b7663SAlexandru Elisei 48e69b7663SAlexandru Elisei #ifdef ARCH_HAS_PCI_EXP 49*25c1dc6cSAlexandru Elisei #define arch_has_pci_exp() (true) 50*25c1dc6cSAlexandru Elisei 51e69b7663SAlexandru Elisei #define PCI_CFG_SIZE PCI_CFG_SIZE_EXTENDED 52e69b7663SAlexandru Elisei #define PCI_DEV_CFG_SIZE PCI_DEV_CFG_SIZE_EXTENDED 53e69b7663SAlexandru Elisei 54e69b7663SAlexandru Elisei union pci_config_address { 55e69b7663SAlexandru Elisei struct { 56e69b7663SAlexandru Elisei #if __BYTE_ORDER == __LITTLE_ENDIAN 57e69b7663SAlexandru Elisei unsigned reg_offset : 2; /* 1 .. 0 */ 58e69b7663SAlexandru Elisei unsigned register_number : 10; /* 11 .. 2 */ 59e69b7663SAlexandru Elisei unsigned function_number : 3; /* 14 .. 12 */ 60e69b7663SAlexandru Elisei unsigned device_number : 5; /* 19 .. 15 */ 61e69b7663SAlexandru Elisei unsigned bus_number : 8; /* 27 .. 20 */ 62e69b7663SAlexandru Elisei unsigned reserved : 3; /* 30 .. 28 */ 63e69b7663SAlexandru Elisei unsigned enable_bit : 1; /* 31 */ 64e69b7663SAlexandru Elisei #else 65e69b7663SAlexandru Elisei unsigned enable_bit : 1; /* 31 */ 66e69b7663SAlexandru Elisei unsigned reserved : 3; /* 30 .. 28 */ 67e69b7663SAlexandru Elisei unsigned bus_number : 8; /* 27 .. 20 */ 68e69b7663SAlexandru Elisei unsigned device_number : 5; /* 19 .. 15 */ 69e69b7663SAlexandru Elisei unsigned function_number : 3; /* 14 .. 12 */ 70e69b7663SAlexandru Elisei unsigned register_number : 10; /* 11 .. 2 */ 71e69b7663SAlexandru Elisei unsigned reg_offset : 2; /* 1 .. 0 */ 72e69b7663SAlexandru Elisei #endif 73e69b7663SAlexandru Elisei }; 74e69b7663SAlexandru Elisei u32 w; 75e69b7663SAlexandru Elisei }; 76e69b7663SAlexandru Elisei 77e69b7663SAlexandru Elisei #else 78*25c1dc6cSAlexandru Elisei #define arch_has_pci_exp() (false) 79*25c1dc6cSAlexandru Elisei 80e69b7663SAlexandru Elisei #define PCI_CFG_SIZE PCI_CFG_SIZE_LEGACY 81e69b7663SAlexandru Elisei #define PCI_DEV_CFG_SIZE PCI_DEV_CFG_SIZE_LEGACY 82e69b7663SAlexandru Elisei 83aa73be70SMatt Evans union pci_config_address { 84aa73be70SMatt Evans struct { 85aa73be70SMatt Evans #if __BYTE_ORDER == __LITTLE_ENDIAN 86d0297a59SMatt Evans unsigned reg_offset : 2; /* 1 .. 0 */ 874402a581SPekka Enberg unsigned register_number : 6; /* 7 .. 2 */ 884402a581SPekka Enberg unsigned function_number : 3; /* 10 .. 8 */ 894402a581SPekka Enberg unsigned device_number : 5; /* 15 .. 11 */ 904402a581SPekka Enberg unsigned bus_number : 8; /* 23 .. 16 */ 914402a581SPekka Enberg unsigned reserved : 7; /* 30 .. 24 */ 924402a581SPekka Enberg unsigned enable_bit : 1; /* 31 */ 93aa73be70SMatt Evans #else 94aa73be70SMatt Evans unsigned enable_bit : 1; /* 31 */ 95aa73be70SMatt Evans unsigned reserved : 7; /* 30 .. 24 */ 96aa73be70SMatt Evans unsigned bus_number : 8; /* 23 .. 16 */ 97aa73be70SMatt Evans unsigned device_number : 5; /* 15 .. 11 */ 98aa73be70SMatt Evans unsigned function_number : 3; /* 10 .. 8 */ 99aa73be70SMatt Evans unsigned register_number : 6; /* 7 .. 2 */ 100d0297a59SMatt Evans unsigned reg_offset : 2; /* 1 .. 0 */ 101aa73be70SMatt Evans #endif 102aa73be70SMatt Evans }; 103aa73be70SMatt Evans u32 w; 1044402a581SPekka Enberg }; 105e69b7663SAlexandru Elisei #endif /* ARCH_HAS_PCI_EXP */ 106e69b7663SAlexandru Elisei 107e69b7663SAlexandru Elisei #define PCI_DEV_CFG_MASK (PCI_DEV_CFG_SIZE - 1) 1084402a581SPekka Enberg 109bc485053SSasha Levin struct msix_table { 1101de74957SSasha Levin struct msi_msg msg; 111bc485053SSasha Levin u32 ctrl; 112bc485053SSasha Levin }; 113bc485053SSasha Levin 114bc485053SSasha Levin struct msix_cap { 115bc485053SSasha Levin u8 cap; 116bc485053SSasha Levin u8 next; 11706f48103SSasha Levin u16 ctrl; 118bc485053SSasha Levin u32 table_offset; 11906f48103SSasha Levin u32 pba_offset; 120bc485053SSasha Levin }; 121bc485053SSasha Levin 1228dd28afeSJean-Philippe Brucker struct msi_cap_64 { 1238dd28afeSJean-Philippe Brucker u8 cap; 1248dd28afeSJean-Philippe Brucker u8 next; 1258dd28afeSJean-Philippe Brucker u16 ctrl; 1268dd28afeSJean-Philippe Brucker u32 address_lo; 1278dd28afeSJean-Philippe Brucker u32 address_hi; 1288dd28afeSJean-Philippe Brucker u16 data; 1298dd28afeSJean-Philippe Brucker u16 _align; 1308dd28afeSJean-Philippe Brucker u32 mask_bits; 1318dd28afeSJean-Philippe Brucker u32 pend_bits; 1328dd28afeSJean-Philippe Brucker }; 1338dd28afeSJean-Philippe Brucker 1348dd28afeSJean-Philippe Brucker struct msi_cap_32 { 1358dd28afeSJean-Philippe Brucker u8 cap; 1368dd28afeSJean-Philippe Brucker u8 next; 1378dd28afeSJean-Philippe Brucker u16 ctrl; 1388dd28afeSJean-Philippe Brucker u32 address_lo; 1398dd28afeSJean-Philippe Brucker u16 data; 1408dd28afeSJean-Philippe Brucker u16 _align; 1418dd28afeSJean-Philippe Brucker u32 mask_bits; 1428dd28afeSJean-Philippe Brucker u32 pend_bits; 1438dd28afeSJean-Philippe Brucker }; 1448dd28afeSJean-Philippe Brucker 1451a51c93dSJean-Philippe Brucker struct pci_cap_hdr { 1461a51c93dSJean-Philippe Brucker u8 type; 1471a51c93dSJean-Philippe Brucker u8 next; 1481a51c93dSJean-Philippe Brucker }; 1491a51c93dSJean-Philippe Brucker 150*25c1dc6cSAlexandru Elisei struct pci_exp_cap { 151*25c1dc6cSAlexandru Elisei u8 cap; 152*25c1dc6cSAlexandru Elisei u8 next; 153*25c1dc6cSAlexandru Elisei u16 cap_reg; 154*25c1dc6cSAlexandru Elisei u32 dev_cap; 155*25c1dc6cSAlexandru Elisei u16 dev_ctrl; 156*25c1dc6cSAlexandru Elisei u16 dev_status; 157*25c1dc6cSAlexandru Elisei u32 link_cap; 158*25c1dc6cSAlexandru Elisei u16 link_ctrl; 159*25c1dc6cSAlexandru Elisei u16 link_status; 160*25c1dc6cSAlexandru Elisei u32 slot_cap; 161*25c1dc6cSAlexandru Elisei u16 slot_ctrl; 162*25c1dc6cSAlexandru Elisei u16 slot_status; 163*25c1dc6cSAlexandru Elisei u16 root_ctrl; 164*25c1dc6cSAlexandru Elisei u16 root_cap; 165*25c1dc6cSAlexandru Elisei u32 root_status; 166*25c1dc6cSAlexandru Elisei }; 167*25c1dc6cSAlexandru Elisei 1685a8e4f25SAlexandru Elisei struct pci_device_header; 1695a8e4f25SAlexandru Elisei 1705a8e4f25SAlexandru Elisei typedef int (*bar_activate_fn_t)(struct kvm *kvm, 1715a8e4f25SAlexandru Elisei struct pci_device_header *pci_hdr, 1725a8e4f25SAlexandru Elisei int bar_num, void *data); 1735a8e4f25SAlexandru Elisei typedef int (*bar_deactivate_fn_t)(struct kvm *kvm, 1745a8e4f25SAlexandru Elisei struct pci_device_header *pci_hdr, 1755a8e4f25SAlexandru Elisei int bar_num, void *data); 1765a8e4f25SAlexandru Elisei 177023fdaaeSJean-Philippe Brucker #define PCI_BAR_OFFSET(b) (offsetof(struct pci_device_header, bar[b])) 178023fdaaeSJean-Philippe Brucker 179023fdaaeSJean-Philippe Brucker struct pci_config_operations { 180023fdaaeSJean-Philippe Brucker void (*write)(struct kvm *kvm, struct pci_device_header *pci_hdr, 181e69b7663SAlexandru Elisei u16 offset, void *data, int sz); 182023fdaaeSJean-Philippe Brucker void (*read)(struct kvm *kvm, struct pci_device_header *pci_hdr, 183e69b7663SAlexandru Elisei u16 offset, void *data, int sz); 184023fdaaeSJean-Philippe Brucker }; 185023fdaaeSJean-Philippe Brucker 18676f9c841SCyrill Gorcunov struct pci_device_header { 187023fdaaeSJean-Philippe Brucker /* Configuration space, as seen by the guest */ 188023fdaaeSJean-Philippe Brucker union { 189023fdaaeSJean-Philippe Brucker struct { 1903fdf659dSSasha Levin u16 vendor_id; 1913fdf659dSSasha Levin u16 device_id; 1923fdf659dSSasha Levin u16 command; 1933fdf659dSSasha Levin u16 status; 194aa73be70SMatt Evans u8 revision_id; 195aa73be70SMatt Evans u8 class[3]; 1963fdf659dSSasha Levin u8 cacheline_size; 1973fdf659dSSasha Levin u8 latency_timer; 1983fdf659dSSasha Levin u8 header_type; 1993fdf659dSSasha Levin u8 bist; 2003fdf659dSSasha Levin u32 bar[6]; 2013fdf659dSSasha Levin u32 card_bus; 2023fdf659dSSasha Levin u16 subsys_vendor_id; 2033fdf659dSSasha Levin u16 subsys_id; 2043fdf659dSSasha Levin u32 exp_rom_bar; 205aa73be70SMatt Evans u8 capabilities; 206aa73be70SMatt Evans u8 reserved1[3]; 2073fdf659dSSasha Levin u32 reserved2; 2083fdf659dSSasha Levin u8 irq_line; 2093fdf659dSSasha Levin u8 irq_pin; 2103fdf659dSSasha Levin u8 min_gnt; 2113fdf659dSSasha Levin u8 max_lat; 212bc485053SSasha Levin struct msix_cap msix; 213*25c1dc6cSAlexandru Elisei /* Used only by architectures which support PCIE */ 214*25c1dc6cSAlexandru Elisei struct pci_exp_cap pci_exp; 215aa73be70SMatt Evans } __attribute__((packed)); 216023fdaaeSJean-Philippe Brucker /* Pad to PCI config space size */ 217023fdaaeSJean-Philippe Brucker u8 __pad[PCI_DEV_CFG_SIZE]; 218023fdaaeSJean-Philippe Brucker }; 219023fdaaeSJean-Philippe Brucker 220023fdaaeSJean-Philippe Brucker /* Private to lkvm */ 221023fdaaeSJean-Philippe Brucker u32 bar_size[6]; 222465edc9dSAlexandru Elisei bool bar_active[6]; 2235a8e4f25SAlexandru Elisei bar_activate_fn_t bar_activate_fn; 2245a8e4f25SAlexandru Elisei bar_deactivate_fn_t bar_deactivate_fn; 2255a8e4f25SAlexandru Elisei void *data; 226023fdaaeSJean-Philippe Brucker struct pci_config_operations cfg_ops; 227ff01b5dbSJean-Philippe Brucker /* 228ff01b5dbSJean-Philippe Brucker * PCI INTx# are level-triggered, but virtual device often feature 229ff01b5dbSJean-Philippe Brucker * edge-triggered INTx# for convenience. 230ff01b5dbSJean-Philippe Brucker */ 231ff01b5dbSJean-Philippe Brucker enum irq_type irq_type; 232023fdaaeSJean-Philippe Brucker }; 23376f9c841SCyrill Gorcunov 2341a51c93dSJean-Philippe Brucker #define PCI_CAP(pci_hdr, pos) ((void *)(pci_hdr) + (pos)) 2351a51c93dSJean-Philippe Brucker 2361a51c93dSJean-Philippe Brucker #define pci_for_each_cap(pos, cap, hdr) \ 2371a51c93dSJean-Philippe Brucker for ((pos) = (hdr)->capabilities & ~3; \ 2381a51c93dSJean-Philippe Brucker (cap) = PCI_CAP(hdr, pos), (pos) != 0; \ 2391a51c93dSJean-Philippe Brucker (pos) = ((struct pci_cap_hdr *)(cap))->next & ~3) 2401a51c93dSJean-Philippe Brucker 2416d987703SSasha Levin int pci__init(struct kvm *kvm); 2426d987703SSasha Levin int pci__exit(struct kvm *kvm); 243d0297a59SMatt Evans struct pci_device_header *pci__find_dev(u8 dev_num); 244854aa2efSJulien Thierry u32 pci_get_mmio_block(u32 size); 245854aa2efSJulien Thierry u16 pci_get_io_port_block(u32 size); 246c0c45eedSAndre Przywara int pci__assign_irq(struct pci_device_header *pci_hdr); 247d0297a59SMatt Evans void pci__config_wr(struct kvm *kvm, union pci_config_address addr, void *data, int size); 248d0297a59SMatt Evans void pci__config_rd(struct kvm *kvm, union pci_config_address addr, void *data, int size); 24960742802SPekka Enberg 2501a51c93dSJean-Philippe Brucker void *pci_find_cap(struct pci_device_header *hdr, u8 cap_type); 2511a51c93dSJean-Philippe Brucker 2525a8e4f25SAlexandru Elisei int pci__register_bar_regions(struct kvm *kvm, struct pci_device_header *pci_hdr, 2535a8e4f25SAlexandru Elisei bar_activate_fn_t bar_activate_fn, 2545a8e4f25SAlexandru Elisei bar_deactivate_fn_t bar_deactivate_fn, void *data); 2555a8e4f25SAlexandru Elisei 2562f6384f9SAlexandru Elisei static inline bool __pci__memory_space_enabled(u16 command) 2572f6384f9SAlexandru Elisei { 2582f6384f9SAlexandru Elisei return command & PCI_COMMAND_MEMORY; 2592f6384f9SAlexandru Elisei } 2602f6384f9SAlexandru Elisei 2612f6384f9SAlexandru Elisei static inline bool pci__memory_space_enabled(struct pci_device_header *pci_hdr) 2622f6384f9SAlexandru Elisei { 2632f6384f9SAlexandru Elisei return __pci__memory_space_enabled(pci_hdr->command); 2642f6384f9SAlexandru Elisei } 2652f6384f9SAlexandru Elisei 2662f6384f9SAlexandru Elisei static inline bool __pci__io_space_enabled(u16 command) 2672f6384f9SAlexandru Elisei { 2682f6384f9SAlexandru Elisei return command & PCI_COMMAND_IO; 2692f6384f9SAlexandru Elisei } 2702f6384f9SAlexandru Elisei 2712f6384f9SAlexandru Elisei static inline bool pci__io_space_enabled(struct pci_device_header *pci_hdr) 2722f6384f9SAlexandru Elisei { 2732f6384f9SAlexandru Elisei return __pci__io_space_enabled(pci_hdr->command); 2742f6384f9SAlexandru Elisei } 2752f6384f9SAlexandru Elisei 2762f6384f9SAlexandru Elisei static inline bool __pci__bar_is_io(u32 bar) 2772f6384f9SAlexandru Elisei { 2782f6384f9SAlexandru Elisei return bar & PCI_BASE_ADDRESS_SPACE_IO; 2792f6384f9SAlexandru Elisei } 2802f6384f9SAlexandru Elisei 2812f6384f9SAlexandru Elisei static inline bool pci__bar_is_io(struct pci_device_header *pci_hdr, int bar_num) 2822f6384f9SAlexandru Elisei { 2832f6384f9SAlexandru Elisei return __pci__bar_is_io(pci_hdr->bar[bar_num]); 2842f6384f9SAlexandru Elisei } 2852f6384f9SAlexandru Elisei 2862f6384f9SAlexandru Elisei static inline bool pci__bar_is_memory(struct pci_device_header *pci_hdr, int bar_num) 2872f6384f9SAlexandru Elisei { 2882f6384f9SAlexandru Elisei return !pci__bar_is_io(pci_hdr, bar_num); 2892f6384f9SAlexandru Elisei } 2902f6384f9SAlexandru Elisei 2912f6384f9SAlexandru Elisei static inline u32 __pci__bar_address(u32 bar) 2922f6384f9SAlexandru Elisei { 2932f6384f9SAlexandru Elisei if (__pci__bar_is_io(bar)) 2942f6384f9SAlexandru Elisei return bar & PCI_BASE_ADDRESS_IO_MASK; 2952f6384f9SAlexandru Elisei return bar & PCI_BASE_ADDRESS_MEM_MASK; 2962f6384f9SAlexandru Elisei } 2972f6384f9SAlexandru Elisei 2982f6384f9SAlexandru Elisei static inline u32 pci__bar_address(struct pci_device_header *pci_hdr, int bar_num) 2992f6384f9SAlexandru Elisei { 3002f6384f9SAlexandru Elisei return __pci__bar_address(pci_hdr->bar[bar_num]); 3012f6384f9SAlexandru Elisei } 3022f6384f9SAlexandru Elisei 3032f6384f9SAlexandru Elisei static inline u32 pci__bar_size(struct pci_device_header *pci_hdr, int bar_num) 3042f6384f9SAlexandru Elisei { 3052f6384f9SAlexandru Elisei return pci_hdr->bar_size[bar_num]; 3062f6384f9SAlexandru Elisei } 3072f6384f9SAlexandru Elisei 30860742802SPekka Enberg #endif /* KVM__PCI_H */ 309