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