121ff329dSWill Deacon #include "kvm/devices.h" 260742802SPekka Enberg #include "kvm/pci.h" 360742802SPekka Enberg #include "kvm/ioport.h" 4b5981636SWill Deacon #include "kvm/irq.h" 576f9c841SCyrill Gorcunov #include "kvm/util.h" 69575e724SSasha Levin #include "kvm/kvm.h" 760742802SPekka Enberg 86d987703SSasha Levin #include <linux/err.h> 96d987703SSasha Levin #include <assert.h> 106d987703SSasha Levin 11a0a7d66fSDavid Daney static u32 pci_config_address_bits; 1260742802SPekka Enberg 1340f2fd06SMatt Evans /* This is within our PCI gap - in an unused area. 1440f2fd06SMatt Evans * Note this is a PCI *bus address*, is used to assign BARs etc.! 1540f2fd06SMatt Evans * (That's why it can still 32bit even with 64bit guests-- 64bit 1640f2fd06SMatt Evans * PCI isn't currently supported.) 1740f2fd06SMatt Evans */ 1840f2fd06SMatt Evans static u32 io_space_blocks = KVM_PCI_MMIO_AREA; 199575e724SSasha Levin 20c7575d17SWill Deacon /* 21c7575d17SWill Deacon * BARs must be naturally aligned, so enforce this in the allocator. 22c7575d17SWill Deacon */ 2395d13a52SSasha Levin u32 pci_get_io_space_block(u32 size) 249575e724SSasha Levin { 25c7575d17SWill Deacon u32 block = ALIGN(io_space_blocks, size); 26c7575d17SWill Deacon io_space_blocks = block + size; 279575e724SSasha Levin return block; 289575e724SSasha Levin } 299575e724SSasha Levin 301a51c93dSJean-Philippe Brucker void *pci_find_cap(struct pci_device_header *hdr, u8 cap_type) 311a51c93dSJean-Philippe Brucker { 321a51c93dSJean-Philippe Brucker u8 pos; 331a51c93dSJean-Philippe Brucker struct pci_cap_hdr *cap; 341a51c93dSJean-Philippe Brucker 351a51c93dSJean-Philippe Brucker pci_for_each_cap(pos, cap, hdr) { 361a51c93dSJean-Philippe Brucker if (cap->type == cap_type) 371a51c93dSJean-Philippe Brucker return cap; 381a51c93dSJean-Philippe Brucker } 391a51c93dSJean-Philippe Brucker 401a51c93dSJean-Philippe Brucker return NULL; 411a51c93dSJean-Philippe Brucker } 421a51c93dSJean-Philippe Brucker 43b5981636SWill Deacon void pci__assign_irq(struct device_header *dev_hdr) 44b5981636SWill Deacon { 45b5981636SWill Deacon struct pci_device_header *pci_hdr = dev_hdr->data; 46b5981636SWill Deacon 47b5981636SWill Deacon /* 48b5981636SWill Deacon * PCI supports only INTA#,B#,C#,D# per device. 49b5981636SWill Deacon * 50b5981636SWill Deacon * A#,B#,C#,D# are allowed for multifunctional devices so stick 51b5981636SWill Deacon * with A# for our single function devices. 52b5981636SWill Deacon */ 53b5981636SWill Deacon pci_hdr->irq_pin = 1; 54b5981636SWill Deacon pci_hdr->irq_line = irq__alloc_line(); 55ff01b5dbSJean-Philippe Brucker 56ff01b5dbSJean-Philippe Brucker if (!pci_hdr->irq_type) 57ff01b5dbSJean-Philippe Brucker pci_hdr->irq_type = IRQ_TYPE_EDGE_RISING; 58b5981636SWill Deacon } 59b5981636SWill Deacon 603fdf659dSSasha Levin static void *pci_config_address_ptr(u16 port) 61ba824677SPekka Enberg { 62ba824677SPekka Enberg unsigned long offset; 63ba824677SPekka Enberg void *base; 64ba824677SPekka Enberg 65ba824677SPekka Enberg offset = port - PCI_CONFIG_ADDRESS; 66a0a7d66fSDavid Daney base = &pci_config_address_bits; 67ba824677SPekka Enberg 68ba824677SPekka Enberg return base + offset; 69ba824677SPekka Enberg } 70ba824677SPekka Enberg 714123ca55SMarc Zyngier static bool pci_config_address_out(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *data, int size) 7260742802SPekka Enberg { 73ba824677SPekka Enberg void *p = pci_config_address_ptr(port); 7460742802SPekka Enberg 75ba824677SPekka Enberg memcpy(p, data, size); 7660742802SPekka Enberg 7760742802SPekka Enberg return true; 7860742802SPekka Enberg } 7960742802SPekka Enberg 804123ca55SMarc Zyngier static bool pci_config_address_in(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *data, int size) 8160742802SPekka Enberg { 82ba824677SPekka Enberg void *p = pci_config_address_ptr(port); 8360742802SPekka Enberg 84ba824677SPekka Enberg memcpy(data, p, size); 8560742802SPekka Enberg 8660742802SPekka Enberg return true; 8760742802SPekka Enberg } 8860742802SPekka Enberg 89305b72ceSCyrill Gorcunov static struct ioport_operations pci_config_address_ops = { 90305b72ceSCyrill Gorcunov .io_in = pci_config_address_in, 91305b72ceSCyrill Gorcunov .io_out = pci_config_address_out, 9260742802SPekka Enberg }; 9360742802SPekka Enberg 943fdf659dSSasha Levin static bool pci_device_exists(u8 bus_number, u8 device_number, u8 function_number) 9576f9c841SCyrill Gorcunov { 96a0a7d66fSDavid Daney union pci_config_address pci_config_address; 97a0a7d66fSDavid Daney 98a0a7d66fSDavid Daney pci_config_address.w = ioport__read32(&pci_config_address_bits); 99a0a7d66fSDavid Daney 10076f9c841SCyrill Gorcunov if (pci_config_address.bus_number != bus_number) 10176f9c841SCyrill Gorcunov return false; 10276f9c841SCyrill Gorcunov 103b30d05adSPekka Enberg if (pci_config_address.function_number != function_number) 10476f9c841SCyrill Gorcunov return false; 10576f9c841SCyrill Gorcunov 10621ff329dSWill Deacon return !IS_ERR_OR_NULL(device__find_dev(DEVICE_BUS_PCI, device_number)); 10776f9c841SCyrill Gorcunov } 10876f9c841SCyrill Gorcunov 1094123ca55SMarc Zyngier static bool pci_config_data_out(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *data, int size) 1109575e724SSasha Levin { 111a0a7d66fSDavid Daney union pci_config_address pci_config_address; 112a0a7d66fSDavid Daney 113a0a7d66fSDavid Daney pci_config_address.w = ioport__read32(&pci_config_address_bits); 1149575e724SSasha Levin /* 1159575e724SSasha Levin * If someone accesses PCI configuration space offsets that are not 1169575e724SSasha Levin * aligned to 4 bytes, it uses ioports to signify that. 1179575e724SSasha Levin */ 118d0297a59SMatt Evans pci_config_address.reg_offset = port - PCI_CONFIG_DATA; 1199575e724SSasha Levin 1204123ca55SMarc Zyngier pci__config_wr(vcpu->kvm, pci_config_address, data, size); 121d0297a59SMatt Evans 122d0297a59SMatt Evans return true; 123d0297a59SMatt Evans } 124d0297a59SMatt Evans 1254123ca55SMarc Zyngier static bool pci_config_data_in(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *data, int size) 126d0297a59SMatt Evans { 127a0a7d66fSDavid Daney union pci_config_address pci_config_address; 128a0a7d66fSDavid Daney 129a0a7d66fSDavid Daney pci_config_address.w = ioport__read32(&pci_config_address_bits); 130d0297a59SMatt Evans /* 131d0297a59SMatt Evans * If someone accesses PCI configuration space offsets that are not 132d0297a59SMatt Evans * aligned to 4 bytes, it uses ioports to signify that. 133d0297a59SMatt Evans */ 134d0297a59SMatt Evans pci_config_address.reg_offset = port - PCI_CONFIG_DATA; 135d0297a59SMatt Evans 1364123ca55SMarc Zyngier pci__config_rd(vcpu->kvm, pci_config_address, data, size); 137d0297a59SMatt Evans 138d0297a59SMatt Evans return true; 139d0297a59SMatt Evans } 140d0297a59SMatt Evans 141d0297a59SMatt Evans static struct ioport_operations pci_config_data_ops = { 142d0297a59SMatt Evans .io_in = pci_config_data_in, 143d0297a59SMatt Evans .io_out = pci_config_data_out, 144d0297a59SMatt Evans }; 145d0297a59SMatt Evans 146d0297a59SMatt Evans void pci__config_wr(struct kvm *kvm, union pci_config_address addr, void *data, int size) 147d0297a59SMatt Evans { 148023fdaaeSJean-Philippe Brucker void *base; 149023fdaaeSJean-Philippe Brucker u8 bar, offset; 150023fdaaeSJean-Philippe Brucker struct pci_device_header *pci_hdr; 151023fdaaeSJean-Philippe Brucker u8 dev_num = addr.device_number; 152*bb0d509bSSami Mujawar u32 value = 0; 153*bb0d509bSSami Mujawar u32 mask; 154d0297a59SMatt Evans 155023fdaaeSJean-Philippe Brucker if (!pci_device_exists(addr.bus_number, dev_num, 0)) 156023fdaaeSJean-Philippe Brucker return; 1579575e724SSasha Levin 158023fdaaeSJean-Philippe Brucker offset = addr.w & PCI_DEV_CFG_MASK; 159023fdaaeSJean-Philippe Brucker base = pci_hdr = device__find_dev(DEVICE_BUS_PCI, dev_num)->data; 1609575e724SSasha Levin 161023fdaaeSJean-Philippe Brucker if (pci_hdr->cfg_ops.write) 162023fdaaeSJean-Philippe Brucker pci_hdr->cfg_ops.write(kvm, pci_hdr, offset, data, size); 163c64f7ff0SSasha Levin 1649575e724SSasha Levin /* 165023fdaaeSJean-Philippe Brucker * legacy hack: ignore writes to uninitialized regions (e.g. ROM BAR). 166023fdaaeSJean-Philippe Brucker * Not very nice but has been working so far. 1679575e724SSasha Levin */ 168023fdaaeSJean-Philippe Brucker if (*(u32 *)(base + offset) == 0) 169023fdaaeSJean-Philippe Brucker return; 170023fdaaeSJean-Philippe Brucker 171023fdaaeSJean-Philippe Brucker bar = (offset - PCI_BAR_OFFSET(0)) / sizeof(u32); 172023fdaaeSJean-Philippe Brucker 173023fdaaeSJean-Philippe Brucker /* 174*bb0d509bSSami Mujawar * If the kernel masks the BAR, it will expect to find the size of the 175*bb0d509bSSami Mujawar * BAR there next time it reads from it. After the kernel reads the 176*bb0d509bSSami Mujawar * size, it will write the address back. 177023fdaaeSJean-Philippe Brucker */ 178*bb0d509bSSami Mujawar if (bar < 6) { 179*bb0d509bSSami Mujawar if (pci_hdr->bar[bar] & PCI_BASE_ADDRESS_SPACE_IO) 180*bb0d509bSSami Mujawar mask = (u32)PCI_BASE_ADDRESS_IO_MASK; 181*bb0d509bSSami Mujawar else 182*bb0d509bSSami Mujawar mask = (u32)PCI_BASE_ADDRESS_MEM_MASK; 183*bb0d509bSSami Mujawar /* 184*bb0d509bSSami Mujawar * According to the PCI local bus specification REV 3.0: 185*bb0d509bSSami Mujawar * The number of upper bits that a device actually implements 186*bb0d509bSSami Mujawar * depends on how much of the address space the device will 187*bb0d509bSSami Mujawar * respond to. A device that wants a 1 MB memory address space 188*bb0d509bSSami Mujawar * (using a 32-bit base address register) would build the top 189*bb0d509bSSami Mujawar * 12 bits of the address register, hardwiring the other bits 190*bb0d509bSSami Mujawar * to 0. 191*bb0d509bSSami Mujawar * 192*bb0d509bSSami Mujawar * Furthermore, software can determine how much address space 193*bb0d509bSSami Mujawar * the device requires by writing a value of all 1's to the 194*bb0d509bSSami Mujawar * register and then reading the value back. The device will 195*bb0d509bSSami Mujawar * return 0's in all don't-care address bits, effectively 196*bb0d509bSSami Mujawar * specifying the address space required. 197*bb0d509bSSami Mujawar * 198*bb0d509bSSami Mujawar * Software computes the size of the address space with the 199*bb0d509bSSami Mujawar * formula S = ~B + 1, where S is the memory size and B is the 200*bb0d509bSSami Mujawar * value read from the BAR. This means that the BAR value that 201*bb0d509bSSami Mujawar * kvmtool should return is B = ~(S - 1). 202*bb0d509bSSami Mujawar */ 203*bb0d509bSSami Mujawar memcpy(&value, data, size); 204*bb0d509bSSami Mujawar if (value == 0xffffffff) 205*bb0d509bSSami Mujawar value = ~(pci_hdr->bar_size[bar] - 1); 206*bb0d509bSSami Mujawar /* Preserve the special bits. */ 207*bb0d509bSSami Mujawar value = (value & mask) | (pci_hdr->bar[bar] & ~mask); 208*bb0d509bSSami Mujawar memcpy(base + offset, &value, size); 209023fdaaeSJean-Philippe Brucker } else { 210023fdaaeSJean-Philippe Brucker memcpy(base + offset, data, size); 2119575e724SSasha Levin } 2129575e724SSasha Levin } 2139575e724SSasha Levin 214d0297a59SMatt Evans void pci__config_rd(struct kvm *kvm, union pci_config_address addr, void *data, int size) 21560742802SPekka Enberg { 216023fdaaeSJean-Philippe Brucker u8 offset; 217023fdaaeSJean-Philippe Brucker struct pci_device_header *pci_hdr; 218023fdaaeSJean-Philippe Brucker u8 dev_num = addr.device_number; 219e4d2cea2SPekka Enberg 220023fdaaeSJean-Philippe Brucker if (pci_device_exists(addr.bus_number, dev_num, 0)) { 221023fdaaeSJean-Philippe Brucker pci_hdr = device__find_dev(DEVICE_BUS_PCI, dev_num)->data; 222023fdaaeSJean-Philippe Brucker offset = addr.w & PCI_DEV_CFG_MASK; 223b30d05adSPekka Enberg 224023fdaaeSJean-Philippe Brucker if (pci_hdr->cfg_ops.read) 225023fdaaeSJean-Philippe Brucker pci_hdr->cfg_ops.read(kvm, pci_hdr, offset, data, size); 226598419d5SPekka Enberg 227023fdaaeSJean-Philippe Brucker memcpy(data, (void *)pci_hdr + offset, size); 2283a60be06SSasha Levin } else { 229e498ea08SPekka Enberg memset(data, 0xff, size); 23060742802SPekka Enberg } 2313a60be06SSasha Levin } 23260742802SPekka Enberg 2339b735910SMarc Zyngier static void pci_config_mmio_access(struct kvm_cpu *vcpu, u64 addr, u8 *data, 2349b735910SMarc Zyngier u32 len, u8 is_write, void *kvm) 235b403f2f7SWill Deacon { 236b403f2f7SWill Deacon union pci_config_address cfg_addr; 237b403f2f7SWill Deacon 238b403f2f7SWill Deacon addr -= KVM_PCI_CFG_AREA; 239b403f2f7SWill Deacon cfg_addr.w = (u32)addr; 240b403f2f7SWill Deacon cfg_addr.enable_bit = 1; 241b403f2f7SWill Deacon 242b403f2f7SWill Deacon if (is_write) 243b403f2f7SWill Deacon pci__config_wr(kvm, cfg_addr, data, len); 244b403f2f7SWill Deacon else 245b403f2f7SWill Deacon pci__config_rd(kvm, cfg_addr, data, len); 246b403f2f7SWill Deacon } 247b403f2f7SWill Deacon 248d0297a59SMatt Evans struct pci_device_header *pci__find_dev(u8 dev_num) 249d0297a59SMatt Evans { 25021ff329dSWill Deacon struct device_header *hdr = device__find_dev(DEVICE_BUS_PCI, dev_num); 2516d987703SSasha Levin 25221ff329dSWill Deacon if (IS_ERR_OR_NULL(hdr)) 25321ff329dSWill Deacon return NULL; 25421ff329dSWill Deacon 25521ff329dSWill Deacon return hdr->data; 256d0297a59SMatt Evans } 257d0297a59SMatt Evans 2586d987703SSasha Levin int pci__init(struct kvm *kvm) 25960742802SPekka Enberg { 2606d987703SSasha Levin int r; 2616d987703SSasha Levin 2624346fd8fSSasha Levin r = ioport__register(kvm, PCI_CONFIG_DATA + 0, &pci_config_data_ops, 4, NULL); 2636d987703SSasha Levin if (r < 0) 2646d987703SSasha Levin return r; 2656d987703SSasha Levin 2664346fd8fSSasha Levin r = ioport__register(kvm, PCI_CONFIG_ADDRESS + 0, &pci_config_address_ops, 4, NULL); 267b403f2f7SWill Deacon if (r < 0) 268b403f2f7SWill Deacon goto err_unregister_data; 269b403f2f7SWill Deacon 270b403f2f7SWill Deacon r = kvm__register_mmio(kvm, KVM_PCI_CFG_AREA, PCI_CFG_SIZE, false, 271b403f2f7SWill Deacon pci_config_mmio_access, kvm); 272b403f2f7SWill Deacon if (r < 0) 273b403f2f7SWill Deacon goto err_unregister_addr; 2746d987703SSasha Levin 2756d987703SSasha Levin return 0; 276b403f2f7SWill Deacon 277b403f2f7SWill Deacon err_unregister_addr: 278b403f2f7SWill Deacon ioport__unregister(kvm, PCI_CONFIG_ADDRESS); 279b403f2f7SWill Deacon err_unregister_data: 280b403f2f7SWill Deacon ioport__unregister(kvm, PCI_CONFIG_DATA); 281b403f2f7SWill Deacon return r; 2826d987703SSasha Levin } 283bca12bf6SSasha Levin dev_base_init(pci__init); 2846d987703SSasha Levin 2856d987703SSasha Levin int pci__exit(struct kvm *kvm) 2866d987703SSasha Levin { 2874346fd8fSSasha Levin ioport__unregister(kvm, PCI_CONFIG_DATA); 2884346fd8fSSasha Levin ioport__unregister(kvm, PCI_CONFIG_ADDRESS); 2896d987703SSasha Levin 2906d987703SSasha Levin return 0; 29160742802SPekka Enberg } 292bca12bf6SSasha Levin dev_base_exit(pci__exit); 293