1 #include "kvm/pci.h" 2 #include "kvm/ioport.h" 3 #include "kvm/util.h" 4 #include "kvm/kvm.h" 5 6 #include <assert.h> 7 8 #define PCI_BAR_OFFSET(b) (offsetof(struct pci_device_header, bar[b])) 9 10 static struct pci_device_header *pci_devices[PCI_MAX_DEVICES]; 11 12 static union pci_config_address pci_config_address; 13 14 /* This is within our PCI gap - in an unused area */ 15 static u32 io_space_blocks = KVM_32BIT_GAP_START + 0x1000000; 16 17 u32 pci_get_io_space_block(u32 size) 18 { 19 u32 block = io_space_blocks; 20 io_space_blocks += size; 21 22 return block; 23 } 24 25 static void *pci_config_address_ptr(u16 port) 26 { 27 unsigned long offset; 28 void *base; 29 30 offset = port - PCI_CONFIG_ADDRESS; 31 base = &pci_config_address; 32 33 return base + offset; 34 } 35 36 static bool pci_config_address_out(struct ioport *ioport, struct kvm *kvm, u16 port, void *data, int size) 37 { 38 void *p = pci_config_address_ptr(port); 39 40 memcpy(p, data, size); 41 42 return true; 43 } 44 45 static bool pci_config_address_in(struct ioport *ioport, struct kvm *kvm, u16 port, void *data, int size) 46 { 47 void *p = pci_config_address_ptr(port); 48 49 memcpy(data, p, size); 50 51 return true; 52 } 53 54 static struct ioport_operations pci_config_address_ops = { 55 .io_in = pci_config_address_in, 56 .io_out = pci_config_address_out, 57 }; 58 59 static bool pci_device_exists(u8 bus_number, u8 device_number, u8 function_number) 60 { 61 struct pci_device_header *dev; 62 63 if (pci_config_address.bus_number != bus_number) 64 return false; 65 66 if (pci_config_address.function_number != function_number) 67 return false; 68 69 if (device_number >= PCI_MAX_DEVICES) 70 return false; 71 72 dev = pci_devices[device_number]; 73 74 return dev != NULL; 75 } 76 77 static bool pci_config_data_out(struct ioport *ioport, struct kvm *kvm, u16 port, void *data, int size) 78 { 79 /* 80 * If someone accesses PCI configuration space offsets that are not 81 * aligned to 4 bytes, it uses ioports to signify that. 82 */ 83 pci_config_address.reg_offset = port - PCI_CONFIG_DATA; 84 85 pci__config_wr(kvm, pci_config_address, data, size); 86 87 return true; 88 } 89 90 static bool pci_config_data_in(struct ioport *ioport, struct kvm *kvm, u16 port, void *data, int size) 91 { 92 /* 93 * If someone accesses PCI configuration space offsets that are not 94 * aligned to 4 bytes, it uses ioports to signify that. 95 */ 96 pci_config_address.reg_offset = port - PCI_CONFIG_DATA; 97 98 pci__config_rd(kvm, pci_config_address, data, size); 99 100 return true; 101 } 102 103 static struct ioport_operations pci_config_data_ops = { 104 .io_in = pci_config_data_in, 105 .io_out = pci_config_data_out, 106 }; 107 108 void pci__config_wr(struct kvm *kvm, union pci_config_address addr, void *data, int size) 109 { 110 u8 dev_num; 111 112 dev_num = addr.device_number; 113 114 if (pci_device_exists(0, dev_num, 0)) { 115 unsigned long offset; 116 117 offset = addr.w & 0xff; 118 if (offset < sizeof(struct pci_device_header)) { 119 void *p = pci_devices[dev_num]; 120 u8 bar = (offset - PCI_BAR_OFFSET(0)) / (sizeof(u32)); 121 u32 sz = PCI_IO_SIZE; 122 123 if (bar < 6 && pci_devices[dev_num]->bar_size[bar]) 124 sz = pci_devices[dev_num]->bar_size[bar]; 125 126 /* 127 * If the kernel masks the BAR it would expect to find the 128 * size of the BAR there next time it reads from it. 129 * When the kernel got the size it would write the address 130 * back. 131 */ 132 if (*(u32 *)(p + offset)) { 133 /* See if kernel tries to mask one of the BARs */ 134 if ((offset >= PCI_BAR_OFFSET(0)) && 135 (offset <= PCI_BAR_OFFSET(6)) && 136 (ioport__read32(data) == 0xFFFFFFFF)) 137 memcpy(p + offset, &sz, sizeof(sz)); 138 else 139 memcpy(p + offset, data, size); 140 } 141 } 142 } 143 } 144 145 void pci__config_rd(struct kvm *kvm, union pci_config_address addr, void *data, int size) 146 { 147 u8 dev_num; 148 149 dev_num = addr.device_number; 150 151 if (pci_device_exists(0, dev_num, 0)) { 152 unsigned long offset; 153 154 offset = addr.w & 0xff; 155 if (offset < sizeof(struct pci_device_header)) { 156 void *p = pci_devices[dev_num]; 157 158 memcpy(data, p + offset, size); 159 } else 160 memset(data, 0x00, size); 161 } else 162 memset(data, 0xff, size); 163 } 164 165 void pci__register(struct pci_device_header *dev, u8 dev_num) 166 { 167 assert(dev_num < PCI_MAX_DEVICES); 168 pci_devices[dev_num] = dev; 169 } 170 171 struct pci_device_header *pci__find_dev(u8 dev_num) 172 { 173 assert(dev_num < PCI_MAX_DEVICES); 174 return pci_devices[dev_num]; 175 } 176 177 void pci__init(void) 178 { 179 ioport__register(PCI_CONFIG_DATA + 0, &pci_config_data_ops, 4, NULL); 180 ioport__register(PCI_CONFIG_ADDRESS + 0, &pci_config_address_ops, 4, NULL); 181 } 182