1 #include "kvm/pci.h" 2 #include "kvm/ioport.h" 3 #include "kvm/util.h" 4 5 #include <assert.h> 6 #include <stdint.h> 7 8 #define PCI_MAX_DEVICES 256 9 10 static struct pci_device_header *pci_devices[PCI_MAX_DEVICES]; 11 12 static struct pci_config_address pci_config_address; 13 14 static void *pci_config_address_ptr(uint16_t port) 15 { 16 unsigned long offset; 17 void *base; 18 19 offset = port - PCI_CONFIG_ADDRESS; 20 base = &pci_config_address; 21 22 return base + offset; 23 } 24 25 static bool pci_config_address_out(struct kvm *self, uint16_t port, void *data, int size, uint32_t count) 26 { 27 void *p = pci_config_address_ptr(port); 28 29 memcpy(p, data, size); 30 31 return true; 32 } 33 34 static bool pci_config_address_in(struct kvm *self, uint16_t port, void *data, int size, uint32_t count) 35 { 36 void *p = pci_config_address_ptr(port); 37 38 memcpy(data, p, size); 39 40 return true; 41 } 42 43 static struct ioport_operations pci_config_address_ops = { 44 .io_in = pci_config_address_in, 45 .io_out = pci_config_address_out, 46 }; 47 48 static bool pci_config_data_out(struct kvm *self, uint16_t port, void *data, int size, uint32_t count) 49 { 50 return true; 51 } 52 53 static bool pci_device_exists(uint8_t bus_number, uint8_t device_number, uint8_t function_number) 54 { 55 struct pci_device_header *dev; 56 57 if (pci_config_address.bus_number != bus_number) 58 return false; 59 60 if (pci_config_address.function_number != function_number) 61 return false; 62 63 if (device_number >= PCI_MAX_DEVICES) 64 return false; 65 66 dev = pci_devices[device_number]; 67 68 return dev != NULL; 69 } 70 71 static bool pci_config_data_in(struct kvm *self, uint16_t port, void *data, int size, uint32_t count) 72 { 73 unsigned long start; 74 uint8_t dev_num; 75 76 /* 77 * If someone accesses PCI configuration space offsets that are not 78 * aligned to 4 bytes, it uses ioports to signify that. 79 */ 80 start = port - PCI_CONFIG_DATA; 81 82 dev_num = pci_config_address.device_number; 83 84 if (pci_device_exists(0, dev_num, 0)) { 85 unsigned long offset; 86 87 offset = start + (pci_config_address.register_number << 2); 88 if (offset < sizeof(struct pci_device_header)) { 89 void *p = pci_devices[dev_num]; 90 91 memcpy(data, p + offset, size); 92 } else 93 memset(data, 0x00, size); 94 } else 95 memset(data, 0xff, size); 96 97 return true; 98 } 99 100 static struct ioport_operations pci_config_data_ops = { 101 .io_in = pci_config_data_in, 102 .io_out = pci_config_data_out, 103 }; 104 105 void pci__register(struct pci_device_header *dev, uint8_t dev_num) 106 { 107 assert(dev_num < PCI_MAX_DEVICES); 108 109 pci_devices[dev_num] = dev; 110 } 111 112 void pci__init(void) 113 { 114 ioport__register(PCI_CONFIG_DATA + 0, &pci_config_data_ops); 115 ioport__register(PCI_CONFIG_DATA + 1, &pci_config_data_ops); 116 ioport__register(PCI_CONFIG_DATA + 2, &pci_config_data_ops); 117 ioport__register(PCI_CONFIG_DATA + 3, &pci_config_data_ops); 118 119 ioport__register(PCI_CONFIG_ADDRESS + 0, &pci_config_address_ops); 120 ioport__register(PCI_CONFIG_ADDRESS + 1, &pci_config_address_ops); 121 ioport__register(PCI_CONFIG_ADDRESS + 2, &pci_config_address_ops); 122 ioport__register(PCI_CONFIG_ADDRESS + 3, &pci_config_address_ops); 123 } 124