1 /*
2 * Unit tests for the generic vPCI handler code.
3 *
4 * Copyright (C) 2017 Citrix Systems R&D
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms and conditions of the GNU General Public
8 * License, version 2, as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public
16 * License along with this program; If not, see <http://www.gnu.org/licenses/>.
17 */
18
19 #include "emul.h"
20
21 /* Single vcpu (current), and single domain with a single PCI device. */
22 static struct vpci vpci;
23
24 static struct domain d;
25
26 const struct pci_dev test_pdev = {
27 .vpci = &vpci,
28 };
29
30 const static struct vcpu v = {
31 .domain = &d
32 };
33
34 const struct vcpu *current = &v;
35
36 /* Dummy hooks, write stores data, read fetches it. */
vpci_read8(const struct pci_dev * pdev,unsigned int reg,void * data)37 static uint32_t vpci_read8(const struct pci_dev *pdev, unsigned int reg,
38 void *data)
39 {
40 return *(uint8_t *)data;
41 }
42
vpci_write8(const struct pci_dev * pdev,unsigned int reg,uint32_t val,void * data)43 static void vpci_write8(const struct pci_dev *pdev, unsigned int reg,
44 uint32_t val, void *data)
45 {
46 *(uint8_t *)data = val;
47 }
48
vpci_read16(const struct pci_dev * pdev,unsigned int reg,void * data)49 static uint32_t vpci_read16(const struct pci_dev *pdev, unsigned int reg,
50 void *data)
51 {
52 return *(uint16_t *)data;
53 }
54
vpci_write16(const struct pci_dev * pdev,unsigned int reg,uint32_t val,void * data)55 static void vpci_write16(const struct pci_dev *pdev, unsigned int reg,
56 uint32_t val, void *data)
57 {
58 *(uint16_t *)data = val;
59 }
60
vpci_read32(const struct pci_dev * pdev,unsigned int reg,void * data)61 static uint32_t vpci_read32(const struct pci_dev *pdev, unsigned int reg,
62 void *data)
63 {
64 return *(uint32_t *)data;
65 }
66
vpci_write32(const struct pci_dev * pdev,unsigned int reg,uint32_t val,void * data)67 static void vpci_write32(const struct pci_dev *pdev, unsigned int reg,
68 uint32_t val, void *data)
69 {
70 *(uint32_t *)data = val;
71 }
72
73 struct mask_data {
74 uint32_t val;
75 uint32_t rw1c_mask;
76 };
77
vpci_read32_mask(const struct pci_dev * pdev,unsigned int reg,void * data)78 static uint32_t vpci_read32_mask(const struct pci_dev *pdev, unsigned int reg,
79 void *data)
80 {
81 const struct mask_data *md = data;
82
83 return md->val;
84 }
85
vpci_write32_mask(const struct pci_dev * pdev,unsigned int reg,uint32_t val,void * data)86 static void vpci_write32_mask(const struct pci_dev *pdev, unsigned int reg,
87 uint32_t val, void *data)
88 {
89 struct mask_data *md = data;
90
91 md->val = val | (md->val & md->rw1c_mask);
92 md->val &= ~(val & md->rw1c_mask);
93 }
94
95 #define VPCI_READ(reg, size, data) ({ \
96 data = vpci_read((pci_sbdf_t){ .sbdf = 0 }, reg, size); \
97 })
98
99 #define VPCI_READ_CHECK(reg, size, expected) ({ \
100 uint32_t rd; \
101 \
102 VPCI_READ(reg, size, rd); \
103 assert(rd == (expected)); \
104 })
105
106 #define VPCI_WRITE(reg, size, data) ({ \
107 vpci_write((pci_sbdf_t){ .sbdf = 0 }, reg, size, data); \
108 })
109
110 #define VPCI_WRITE_CHECK(reg, size, data) ({ \
111 VPCI_WRITE(reg, size, data); \
112 VPCI_READ_CHECK(reg, size, data); \
113 })
114
115 #define VPCI_ADD_REG(fread, fwrite, off, size, store) \
116 assert(!vpci_add_register(test_pdev.vpci, fread, fwrite, off, size, \
117 &store))
118
119 #define VPCI_ADD_REG_MASK(fread, fwrite, off, size, store, \
120 ro_mask, rw1c_mask, rsvdp_mask, rsvdz_mask) \
121 assert(!vpci_add_register_mask(test_pdev.vpci, fread, fwrite, off, size, \
122 &store, \
123 ro_mask, rw1c_mask, rsvdp_mask, rsvdz_mask))
124
125 #define VPCI_ADD_INVALID_REG(fread, fwrite, off, size) \
126 assert(vpci_add_register(test_pdev.vpci, fread, fwrite, off, size, NULL))
127
128 #define VPCI_ADD_INVALID_REG_MASK(fread, fwrite, off, size, \
129 ro_mask, rw1c_mask, rsvdp_mask, rsvdz_mask) \
130 assert(vpci_add_register_mask(test_pdev.vpci, fread, fwrite, off, size, \
131 NULL, ro_mask, rw1c_mask, rsvdp_mask, \
132 rsvdz_mask))
133
134 #define VPCI_REMOVE_REG(off, size) \
135 assert(!vpci_remove_register(test_pdev.vpci, off, size))
136
137 #define VPCI_REMOVE_INVALID_REG(off, size) \
138 assert(vpci_remove_register(test_pdev.vpci, off, size))
139
140 /* Read a 32b register using all possible sizes. */
multiread4_check(unsigned int reg,uint32_t val)141 void multiread4_check(unsigned int reg, uint32_t val)
142 {
143 unsigned int i;
144
145 /* Read using bytes. */
146 for ( i = 0; i < 4; i++ )
147 VPCI_READ_CHECK(reg + i, 1, (val >> (i * 8)) & UINT8_MAX);
148
149 /* Read using 2bytes. */
150 for ( i = 0; i < 2; i++ )
151 VPCI_READ_CHECK(reg + i * 2, 2, (val >> (i * 2 * 8)) & UINT16_MAX);
152
153 VPCI_READ_CHECK(reg, 4, val);
154 }
155
multiwrite4_check(unsigned int reg)156 void multiwrite4_check(unsigned int reg)
157 {
158 unsigned int i;
159 uint32_t val = 0xa2f51732;
160
161 /* Write using bytes. */
162 for ( i = 0; i < 4; i++ )
163 VPCI_WRITE_CHECK(reg + i, 1, (val >> (i * 8)) & UINT8_MAX);
164 multiread4_check(reg, val);
165
166 /* Change the value each time to be sure writes work fine. */
167 val = 0x2b836fda;
168 /* Write using 2bytes. */
169 for ( i = 0; i < 2; i++ )
170 VPCI_WRITE_CHECK(reg + i * 2, 2, (val >> (i * 2 * 8)) & UINT16_MAX);
171 multiread4_check(reg, val);
172
173 val = 0xc4693beb;
174 VPCI_WRITE_CHECK(reg, 4, val);
175 multiread4_check(reg, val);
176 }
177
178 int
main(int argc,char ** argv)179 main(int argc, char **argv)
180 {
181 /* Index storage by offset. */
182 uint32_t r0 = 0xdeadbeef;
183 uint8_t r5 = 0xef;
184 uint8_t r6 = 0xbe;
185 uint8_t r7 = 0xef;
186 uint16_t r12 = 0x8696;
187 uint8_t r16[4] = { };
188 uint16_t r20[2] = { };
189 uint32_t r24 = 0;
190 uint8_t r28, r30;
191 struct mask_data r32;
192 unsigned int i;
193 int rc;
194
195 INIT_LIST_HEAD(&vpci.handlers);
196 spin_lock_init(&vpci.lock);
197
198 VPCI_ADD_REG(vpci_read32, vpci_write32, 0, 4, r0);
199 VPCI_READ_CHECK(0, 4, r0);
200 VPCI_WRITE_CHECK(0, 4, 0xbcbcbcbc);
201
202 VPCI_ADD_REG(vpci_read8, vpci_write8, 5, 1, r5);
203 VPCI_READ_CHECK(5, 1, r5);
204 VPCI_WRITE_CHECK(5, 1, 0xba);
205
206 VPCI_ADD_REG(vpci_read8, vpci_write8, 6, 1, r6);
207 VPCI_READ_CHECK(6, 1, r6);
208 VPCI_WRITE_CHECK(6, 1, 0xba);
209
210 VPCI_ADD_REG(vpci_read8, vpci_write8, 7, 1, r7);
211 VPCI_READ_CHECK(7, 1, r7);
212 VPCI_WRITE_CHECK(7, 1, 0xbd);
213
214 VPCI_ADD_REG(vpci_read16, vpci_write16, 12, 2, r12);
215 VPCI_READ_CHECK(12, 2, r12);
216 VPCI_READ_CHECK(12, 4, 0xffff8696);
217
218 /*
219 * At this point we have the following layout:
220 *
221 * Note that this refers to the position of the variables,
222 * but the value has already changed from the one given at
223 * initialization time because write tests have been performed.
224 *
225 * 32 24 16 8 0
226 * +-----+-----+-----+-----+
227 * | r0 | 0
228 * +-----+-----+-----+-----+
229 * | r7 | r6 | r5 |/////| 32
230 * +-----+-----+-----+-----|
231 * |///////////////////////| 64
232 * +-----------+-----------+
233 * |///////////| r12 | 96
234 * +-----------+-----------+
235 * ...
236 * / = unhandled.
237 */
238
239 /* Try to add an overlapping register handler. */
240 VPCI_ADD_INVALID_REG(vpci_read32, vpci_write32, 4, 4);
241
242 /* Try to add a non-aligned register. */
243 VPCI_ADD_INVALID_REG(vpci_read16, vpci_write16, 15, 2);
244
245 /* Try to add a register with wrong size. */
246 VPCI_ADD_INVALID_REG(vpci_read16, vpci_write16, 8, 3);
247
248 /* Try to add a register with missing handlers. */
249 VPCI_ADD_INVALID_REG(NULL, NULL, 8, 2);
250
251 /* Try to add registers with the same bits set in multiple masks. */
252 VPCI_ADD_INVALID_REG_MASK(vpci_read32, vpci_write32, 8, 4, 1, 1, 0, 0);
253 VPCI_ADD_INVALID_REG_MASK(vpci_read32, vpci_write32, 8, 4, 1, 0, 1, 0);
254 VPCI_ADD_INVALID_REG_MASK(vpci_read32, vpci_write32, 8, 4, 1, 0, 0, 1);
255 VPCI_ADD_INVALID_REG_MASK(vpci_read32, vpci_write32, 8, 4, 0, 1, 1, 0);
256 VPCI_ADD_INVALID_REG_MASK(vpci_read32, vpci_write32, 8, 4, 0, 1, 0, 1);
257 VPCI_ADD_INVALID_REG_MASK(vpci_read32, vpci_write32, 8, 4, 0, 0, 1, 1);
258
259 /* Try to add registers with mask bits set beyond the register size */
260 VPCI_ADD_INVALID_REG_MASK(vpci_read8, vpci_write8, 8, 1, 0x100U, 0, 0, 0);
261 VPCI_ADD_INVALID_REG_MASK(vpci_read8, vpci_write8, 8, 1, 0, 0x100U, 0, 0);
262 VPCI_ADD_INVALID_REG_MASK(vpci_read8, vpci_write8, 8, 1, 0, 0, 0x100U, 0);
263 VPCI_ADD_INVALID_REG_MASK(vpci_read8, vpci_write8, 8, 1, 0, 0, 0, 0x100U);
264 VPCI_ADD_INVALID_REG_MASK(vpci_read16, vpci_write16, 8, 2, 0x10000U,0,0,0);
265 VPCI_ADD_INVALID_REG_MASK(vpci_read16, vpci_write16, 8, 2, 0,0x10000U,0,0);
266 VPCI_ADD_INVALID_REG_MASK(vpci_read16, vpci_write16, 8, 2, 0,0,0x10000U,0);
267 VPCI_ADD_INVALID_REG_MASK(vpci_read16, vpci_write16, 8, 2, 0,0,0,0x10000U);
268
269 /* Read/write of unset register. */
270 VPCI_READ_CHECK(8, 4, 0xffffffff);
271 VPCI_READ_CHECK(8, 2, 0xffff);
272 VPCI_READ_CHECK(8, 1, 0xff);
273 VPCI_WRITE(10, 2, 0xbeef);
274 VPCI_READ_CHECK(10, 2, 0xffff);
275
276 /* Read of multiple registers */
277 VPCI_WRITE_CHECK(7, 1, 0xbd);
278 VPCI_READ_CHECK(4, 4, 0xbdbabaff);
279
280 /* Partial read of a register. */
281 VPCI_WRITE_CHECK(0, 4, 0x1a1b1c1d);
282 VPCI_READ_CHECK(2, 1, 0x1b);
283 VPCI_READ_CHECK(6, 2, 0xbdba);
284
285 /* Write of multiple registers. */
286 VPCI_WRITE_CHECK(4, 4, 0xaabbccff);
287
288 /* Partial write of a register. */
289 VPCI_WRITE_CHECK(2, 1, 0xfe);
290 VPCI_WRITE_CHECK(6, 2, 0xfebc);
291
292 /*
293 * Test all possible read/write size combinations.
294 *
295 * Place 4 1B registers at 128bits (16B), 2 2B registers at 160bits
296 * (20B) and finally 1 4B register at 192bits (24B).
297 *
298 * Then perform all possible write and read sizes on each of them.
299 *
300 * ...
301 * 32 24 16 8 0
302 * +------+------+------+------+
303 * |r16[3]|r16[2]|r16[1]|r16[0]| 16
304 * +------+------+------+------+
305 * | r20[1] | r20[0] | 20
306 * +-------------+-------------|
307 * | r24 | 24
308 * +-------------+-------------+
309 *
310 */
311 VPCI_ADD_REG(vpci_read8, vpci_write8, 16, 1, r16[0]);
312 VPCI_ADD_REG(vpci_read8, vpci_write8, 17, 1, r16[1]);
313 VPCI_ADD_REG(vpci_read8, vpci_write8, 18, 1, r16[2]);
314 VPCI_ADD_REG(vpci_read8, vpci_write8, 19, 1, r16[3]);
315
316 VPCI_ADD_REG(vpci_read16, vpci_write16, 20, 2, r20[0]);
317 VPCI_ADD_REG(vpci_read16, vpci_write16, 22, 2, r20[1]);
318
319 VPCI_ADD_REG(vpci_read32, vpci_write32, 24, 4, r24);
320
321 /* Check the initial value is 0. */
322 multiread4_check(16, 0);
323 multiread4_check(20, 0);
324 multiread4_check(24, 0);
325
326 multiwrite4_check(16);
327 multiwrite4_check(20);
328 multiwrite4_check(24);
329
330 /*
331 * Check multiple non-consecutive gaps on the same read/write:
332 *
333 * 32 24 16 8 0
334 * +------+------+------+------+
335 * |//////| r30 |//////| r28 | 28
336 * +------+------+------+------+
337 *
338 */
339 VPCI_ADD_REG(vpci_read8, vpci_write8, 28, 1, r28);
340 VPCI_ADD_REG(vpci_read8, vpci_write8, 30, 1, r30);
341 VPCI_WRITE_CHECK(28, 4, 0xffacffdc);
342
343 /*
344 * Test ro/rw1c/rsvdp/rsvdz masks.
345 *
346 * 32 24 16 8 0
347 * +------+------+------+------+
348 * |rsvdz |rsvdp | rw1c | ro | 32
349 * +------+------+------+------+
350 *
351 */
352 r32.rw1c_mask = 0x0000ff00U;
353 VPCI_ADD_REG_MASK(vpci_read32_mask, vpci_write32_mask, 32, 4, r32,
354 0x000000ffU /* RO */,
355 r32.rw1c_mask /* RW1C */,
356 0x00ff0000U /* RsvdP */,
357 0xff000000U /* RsvdZ */);
358
359 /* ro */
360 r32.val = 0x0f0f0f0fU;
361 VPCI_READ_CHECK(32, 1, 0x0f);
362 VPCI_WRITE(32, 1, 0x5a);
363 VPCI_READ_CHECK(32, 1, 0x0f);
364 assert(r32.val == 0x000f0f0fU);
365
366 /* rw1c */
367 r32.val = 0x0f0f0f0fU;
368 VPCI_READ_CHECK(33, 1, 0x0f);
369 VPCI_WRITE(33, 1, 0x5a);
370 VPCI_READ_CHECK(33, 1, 0x05);
371 assert(r32.val == 0x000f050fU);
372
373 /* rsvdp */
374 r32.val = 0x0f0f0f0fU;
375 VPCI_READ_CHECK(34, 1, 0);
376 VPCI_WRITE(34, 1, 0x5a);
377 VPCI_READ_CHECK(34, 1, 0);
378 assert(r32.val == 0x000f0f0fU);
379
380 /* rsvdz */
381 r32.val = 0x0f0f0f0fU;
382 VPCI_READ_CHECK(35, 1, 0);
383 VPCI_WRITE(35, 1, 0x5a);
384 VPCI_READ_CHECK(35, 1, 0);
385 assert(r32.val == 0x000f0f0fU);
386
387 /* write all 0's */
388 r32.val = 0x0f0f0f0fU;
389 VPCI_READ_CHECK(32, 4, 0x00000f0fU);
390 VPCI_WRITE(32, 4, 0);
391 VPCI_READ_CHECK(32, 4, 0x00000f0fU);
392 assert(r32.val == 0x000f0f0fU);
393
394 /* write all 1's */
395 r32.val = 0x0f0f0f0fU;
396 VPCI_READ_CHECK(32, 4, 0x00000f0fU);
397 VPCI_WRITE(32, 4, 0xffffffffU);
398 VPCI_READ_CHECK(32, 4, 0x0000000fU);
399 assert(r32.val == 0x000f000fU);
400
401 /* Finally try to remove a couple of registers. */
402 VPCI_REMOVE_REG(28, 1);
403 VPCI_REMOVE_REG(24, 4);
404 VPCI_REMOVE_REG(12, 2);
405
406 VPCI_REMOVE_INVALID_REG(20, 1);
407 VPCI_REMOVE_INVALID_REG(16, 2);
408 VPCI_REMOVE_INVALID_REG(30, 2);
409
410 return 0;
411 }
412
413 /*
414 * Local variables:
415 * mode: C
416 * c-file-style: "BSD"
417 * c-basic-offset: 4
418 * indent-tabs-mode: nil
419 * End:
420 */
421