xref: /kvmtool/pci.c (revision bca12bf63703c74f96942b12736e4337ef2c7d4d)
1 #include "kvm/pci.h"
2 #include "kvm/ioport.h"
3 #include "kvm/util.h"
4 #include "kvm/kvm.h"
5 
6 #include <linux/err.h>
7 #include <assert.h>
8 
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 union pci_config_address		pci_config_address;
14 
15 /* This is within our PCI gap - in an unused area.
16  * Note this is a PCI *bus address*, is used to assign BARs etc.!
17  * (That's why it can still 32bit even with 64bit guests-- 64bit
18  * PCI isn't currently supported.)
19  */
20 static u32 io_space_blocks		= KVM_PCI_MMIO_AREA;
21 
22 u32 pci_get_io_space_block(u32 size)
23 {
24 	u32 block = io_space_blocks;
25 	io_space_blocks += size;
26 
27 	return block;
28 }
29 
30 static void *pci_config_address_ptr(u16 port)
31 {
32 	unsigned long offset;
33 	void *base;
34 
35 	offset	= port - PCI_CONFIG_ADDRESS;
36 	base	= &pci_config_address;
37 
38 	return base + offset;
39 }
40 
41 static bool pci_config_address_out(struct ioport *ioport, struct kvm *kvm, u16 port, void *data, int size)
42 {
43 	void *p = pci_config_address_ptr(port);
44 
45 	memcpy(p, data, size);
46 
47 	return true;
48 }
49 
50 static bool pci_config_address_in(struct ioport *ioport, struct kvm *kvm, u16 port, void *data, int size)
51 {
52 	void *p = pci_config_address_ptr(port);
53 
54 	memcpy(data, p, size);
55 
56 	return true;
57 }
58 
59 static struct ioport_operations pci_config_address_ops = {
60 	.io_in	= pci_config_address_in,
61 	.io_out	= pci_config_address_out,
62 };
63 
64 static bool pci_device_exists(u8 bus_number, u8 device_number, u8 function_number)
65 {
66 	struct pci_device_header *dev;
67 
68 	if (pci_config_address.bus_number != bus_number)
69 		return false;
70 
71 	if (pci_config_address.function_number != function_number)
72 		return false;
73 
74 	if (device_number >= PCI_MAX_DEVICES)
75 		return false;
76 
77 	dev = pci_devices[device_number];
78 
79 	return dev != NULL;
80 }
81 
82 static bool pci_config_data_out(struct ioport *ioport, struct kvm *kvm, u16 port, void *data, int size)
83 {
84 	/*
85 	 * If someone accesses PCI configuration space offsets that are not
86 	 * aligned to 4 bytes, it uses ioports to signify that.
87 	 */
88 	pci_config_address.reg_offset = port - PCI_CONFIG_DATA;
89 
90 	pci__config_wr(kvm, pci_config_address, data, size);
91 
92 	return true;
93 }
94 
95 static bool pci_config_data_in(struct ioport *ioport, struct kvm *kvm, u16 port, void *data, int size)
96 {
97 	/*
98 	 * If someone accesses PCI configuration space offsets that are not
99 	 * aligned to 4 bytes, it uses ioports to signify that.
100 	 */
101 	pci_config_address.reg_offset = port - PCI_CONFIG_DATA;
102 
103 	pci__config_rd(kvm, pci_config_address, data, size);
104 
105 	return true;
106 }
107 
108 static struct ioport_operations pci_config_data_ops = {
109 	.io_in	= pci_config_data_in,
110 	.io_out	= pci_config_data_out,
111 };
112 
113 void pci__config_wr(struct kvm *kvm, union pci_config_address addr, void *data, int size)
114 {
115 	u8 dev_num;
116 
117 	dev_num	= addr.device_number;
118 
119 	if (pci_device_exists(0, dev_num, 0)) {
120 		unsigned long offset;
121 
122 		offset = addr.w & 0xff;
123 		if (offset < sizeof(struct pci_device_header)) {
124 			void *p = pci_devices[dev_num];
125 			u8 bar = (offset - PCI_BAR_OFFSET(0)) / (sizeof(u32));
126 			u32 sz = PCI_IO_SIZE;
127 
128 			if (bar < 6 && pci_devices[dev_num]->bar_size[bar])
129 				sz = pci_devices[dev_num]->bar_size[bar];
130 
131 			/*
132 			 * If the kernel masks the BAR it would expect to find the
133 			 * size of the BAR there next time it reads from it.
134 			 * When the kernel got the size it would write the address
135 			 * back.
136 			 */
137 			if (*(u32 *)(p + offset)) {
138 				/* See if kernel tries to mask one of the BARs */
139 				if ((offset >= PCI_BAR_OFFSET(0)) &&
140 				    (offset <= PCI_BAR_OFFSET(6)) &&
141 				    (ioport__read32(data)  == 0xFFFFFFFF))
142 					memcpy(p + offset, &sz, sizeof(sz));
143 				    else
144 					memcpy(p + offset, data, size);
145 			}
146 		}
147 	}
148 }
149 
150 void pci__config_rd(struct kvm *kvm, union pci_config_address addr, void *data, int size)
151 {
152 	u8 dev_num;
153 
154 	dev_num	= addr.device_number;
155 
156 	if (pci_device_exists(0, dev_num, 0)) {
157 		unsigned long offset;
158 
159 		offset = addr.w & 0xff;
160 		if (offset < sizeof(struct pci_device_header)) {
161 			void *p = pci_devices[dev_num];
162 
163 			memcpy(data, p + offset, size);
164 		} else {
165 			memset(data, 0x00, size);
166 		}
167 	} else {
168 		memset(data, 0xff, size);
169 	}
170 }
171 
172 int pci__register(struct pci_device_header *dev, u8 dev_num)
173 {
174 	if (dev_num >= PCI_MAX_DEVICES)
175 		return -ENOSPC;
176 
177 	pci_devices[dev_num] = dev;
178 
179 	return 0;
180 }
181 
182 struct pci_device_header *pci__find_dev(u8 dev_num)
183 {
184 	if (dev_num >= PCI_MAX_DEVICES)
185 		return ERR_PTR(-EOVERFLOW);
186 
187 	return pci_devices[dev_num];
188 }
189 
190 int pci__init(struct kvm *kvm)
191 {
192 	int r;
193 
194 	r = ioport__register(kvm, PCI_CONFIG_DATA + 0, &pci_config_data_ops, 4, NULL);
195 	if (r < 0)
196 		return r;
197 
198 	r = ioport__register(kvm, PCI_CONFIG_ADDRESS + 0, &pci_config_address_ops, 4, NULL);
199 	if (r < 0) {
200 		ioport__unregister(kvm, PCI_CONFIG_DATA);
201 		return r;
202 	}
203 
204 	return 0;
205 }
206 dev_base_init(pci__init);
207 
208 int pci__exit(struct kvm *kvm)
209 {
210 	ioport__unregister(kvm, PCI_CONFIG_DATA);
211 	ioport__unregister(kvm, PCI_CONFIG_ADDRESS);
212 
213 	return 0;
214 }
215 dev_base_exit(pci__exit);
216