lcd-tests.c 11.2 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
/**
 * Regression tests for lcd code.
 *
 * Included in lcd-domains.c and
 * ran last in lcd_init.
 */

static int test01(void)
{
	struct lcd *lcd;
	int ret;

	ret = lcd_create(&lcd);
	if (ret) {
		printk(KERN_ERR "lcd test: test01 failed to create lcd\n");
16
		goto fail;
17 18
	}

19
	lcd_destroy(lcd);
20 21

	return 0;
22 23 24

fail:
	return ret;
25 26
}

Charlie Jacobsen's avatar
Charlie Jacobsen committed
27 28 29 30 31 32 33 34
static int test02(void)
{
	struct lcd *lcd;
	int ret;

	ret = lcd_create(&lcd);
	if (ret) {
		printk(KERN_ERR "lcd test: test02 failed to create lcd\n");
35
		goto fail1;
Charlie Jacobsen's avatar
Charlie Jacobsen committed
36 37
	}
	
Charles Jacobsen's avatar
Charles Jacobsen committed
38 39
	ret = lcd_mm_gva_init(lcd, LCD_ARCH_FREE,
			gpa_add(LCD_ARCH_FREE, 4 * (1 << 20)));
Charlie Jacobsen's avatar
Charlie Jacobsen committed
40 41
	if (ret) {
		printk(KERN_ERR "lcd test: test02 failed to init gva\n");
42
		goto fail2;
Charlie Jacobsen's avatar
Charlie Jacobsen committed
43 44 45 46 47
	}

	lcd_destroy(lcd);

	return 0;
48 49 50 51 52

fail2:
	lcd_destroy(lcd);
fail1:
	return ret;
Charlie Jacobsen's avatar
Charlie Jacobsen committed
53 54
}

Charlie Jacobsen's avatar
Charlie Jacobsen committed
55 56 57 58
static int test03(void)
{
	struct lcd *lcd;
	int ret;
59 60
	gpa_t gpa;
	hpa_t hpa;
Charlie Jacobsen's avatar
Charlie Jacobsen committed
61 62 63 64 65 66 67

	ret = lcd_create(&lcd);
	if (ret) {
		printk(KERN_ERR "lcd test: test03 failed to create lcd\n");
		goto fail1;
	}
	
Charles Jacobsen's avatar
Charles Jacobsen committed
68 69
	ret = lcd_mm_gva_init(lcd, LCD_ARCH_FREE,
			gpa_add(LCD_ARCH_FREE, 4 * (1 << 20)));
Charlie Jacobsen's avatar
Charlie Jacobsen committed
70 71 72 73 74 75 76 77 78 79
	if (ret) {
		printk(KERN_ERR "lcd test: test03 failed to init gva\n");
		goto fail2;
	}

	ret = lcd_mm_gva_alloc(lcd, &gpa, &hpa);
	if (ret) {
		printk(KERN_ERR "lcd test: test03 failed to alloc pg mem\n");
		goto fail3;
	}
80
	
81 82
	ret = 0;
	goto done;
Charlie Jacobsen's avatar
Charlie Jacobsen committed
83

84 85
done:
	free_page(hva_val(hpa2hva(hpa)));
86
	lcd_arch_ept_unmap_range(lcd->lcd_arch, gpa, 1);
Charlie Jacobsen's avatar
Charlie Jacobsen committed
87 88 89 90 91 92 93
fail3:
fail2:
	lcd_destroy(lcd);
fail1:
	return ret;
}

94 95 96 97
static int test04(void)
{
	struct lcd *lcd;
	int ret;
98 99
	gpa_t gpa;
	hpa_t hpa;
100 101
	pmd_t *pmd_entry;
	pte_t *pt;
102
	pte_t *pte_entry;
103 104 105 106 107 108 109

	ret = lcd_create(&lcd);
	if (ret) {
		printk(KERN_ERR "lcd test: test04 failed to create lcd\n");
		goto fail1;
	}
	
Charles Jacobsen's avatar
Charles Jacobsen committed
110 111
	ret = lcd_mm_gva_init(lcd, LCD_ARCH_FREE,
			gpa_add(LCD_ARCH_FREE, 4 * (1 << 20)));
112 113 114 115 116 117 118 119 120 121 122 123
	if (ret) {
		printk(KERN_ERR "lcd test: test04 failed to init gva\n");
		goto fail2;
	}

	ret = lcd_mm_gva_alloc(lcd, &gpa, &hpa);
	if (ret) {
		printk(KERN_ERR "lcd test: test04 failed to alloc pg mem\n");
		goto fail3;
	}

	/*
Charles Jacobsen's avatar
Charles Jacobsen committed
124
	 * Map gva = 0x4000 (start of 5th page frame) to gpa = 0x1234000UL
125
	 */
126 127
	pt = (pte_t *)hpa2va(hpa);
	set_pte_gpa(pt + 4, __gpa(0x1234000UL));
128 129 130 131

	/*
	 * Set up pmd entry for look up, and find pte
	 */
132 133 134 135 136
	pmd_entry = (pmd_t *)kmalloc(sizeof(*pmd_entry), GFP_KERNEL);
	if (!pmd_entry) {
		goto fail4;
	}

137 138 139
	set_pmd(pmd_entry, __pmd(gpa_val(gpa) | _KERNPG_TABLE));
	ret = lcd_mm_gva_lookup_pte(lcd, __gva(0x4000UL), 
				pmd_entry, &pte_entry);
140 141
	if (ret) {
		printk(KERN_ERR "lcd test: test04 failed to lookup pte\n");
142
		goto fail5;
143 144 145 146 147
	}

	/*
	 * Check
	 */
148
	if (gpa_val(pte_gpa(pte_entry)) != 0x1234000UL) {
149
		printk(KERN_ERR "lcd test: test04 pte gpa is %lx\n",
150
			gpa_val(pte_gpa(pte_entry)));
151
		ret = -1;
152
		goto fail6;
153 154
	}

155 156
	ret = 0;
	goto done;
157

158
done:
159
fail6:
160
fail5:
161
	kfree(pmd_entry);
162
fail4:
163
	free_page(hva_val(hpa2hva(hpa)));
164
	lcd_arch_ept_unmap_range(lcd->lcd_arch, gpa, 1);
165 166 167 168 169 170 171
fail3:
fail2:
	lcd_destroy(lcd);
fail1:
	return ret;
}

Charlie Jacobsen's avatar
Charlie Jacobsen committed
172 173 174 175
static int test05(void)
{
	struct lcd *lcd;
	int ret;
176 177
	gpa_t gpa;
	hpa_t hpa;
Charlie Jacobsen's avatar
Charlie Jacobsen committed
178 179 180 181 182 183 184 185 186 187
	pud_t *pud_entry;
	pmd_t *pmd;
	pmd_t *pmd_entry;

	ret = lcd_create(&lcd);
	if (ret) {
		printk(KERN_ERR "lcd test: test05 failed to create lcd\n");
		goto fail1;
	}
	
Charles Jacobsen's avatar
Charles Jacobsen committed
188 189
	ret = lcd_mm_gva_init(lcd, LCD_ARCH_FREE,
			gpa_add(LCD_ARCH_FREE, 4 * (1 << 20)));
Charlie Jacobsen's avatar
Charlie Jacobsen committed
190 191 192 193 194 195 196 197 198 199 200 201 202 203 204
	if (ret) {
		printk(KERN_ERR "lcd test: test05 failed to init gva\n");
		goto fail2;
	}

	ret = lcd_mm_gva_alloc(lcd, &gpa, &hpa);
	if (ret) {
		printk(KERN_ERR "lcd test: test05 failed to alloc pg mem\n");
		goto fail3;
	}

	/*
	 * Populate 5th entry in pmd to point to a (bogus) page table at
	 * gpa 0x1234000UL.
	 */
205 206
	pmd = (pmd_t *)hpa2va(hpa);
	set_pmd_gpa(pmd + 4, __gpa(0x1234000UL));
Charlie Jacobsen's avatar
Charlie Jacobsen committed
207 208 209 210 211 212 213 214 215

	/*
	 * Set up pud entry for look up, and find pmd
	 */
	pud_entry = (pud_t *)kmalloc(sizeof(*pud_entry), GFP_KERNEL);
	if (!pud_entry) {
		goto fail4;
	}

216 217
	set_pud_gpa(pud_entry, gpa);
	ret = lcd_mm_gva_lookup_pmd(lcd, __gva(0x4UL << PMD_SHIFT), 
Charlie Jacobsen's avatar
Charlie Jacobsen committed
218 219 220 221 222 223 224 225 226
				pud_entry, &pmd_entry);
	if (ret) {
		printk(KERN_ERR "lcd test: test05 failed to lookup pmd\n");
		goto fail5;
	}

	/*
	 * Check
	 */
227
	if (gpa_val(pmd_gpa(pmd_entry)) != 0x1234000UL) {
Charlie Jacobsen's avatar
Charlie Jacobsen committed
228
		printk(KERN_ERR "lcd test: test05 pte gpa is %lx\n",
229
			gpa_val(pmd_gpa(pmd_entry)));
230
		ret = -1;
Charlie Jacobsen's avatar
Charlie Jacobsen committed
231 232 233
		goto fail6;
	}

234 235
	ret = 0;
	goto done;
Charlie Jacobsen's avatar
Charlie Jacobsen committed
236

237
done:
Charlie Jacobsen's avatar
Charlie Jacobsen committed
238 239 240 241
fail6:
fail5:
	kfree(pud_entry);
fail4:
242
	free_page(hva_val(hpa2hva(hpa)));
243
	lcd_arch_ept_unmap_range(lcd->lcd_arch, gpa, 1);
Charlie Jacobsen's avatar
Charlie Jacobsen committed
244 245 246 247 248 249 250
fail3:
fail2:
	lcd_destroy(lcd);
fail1:
	return ret;
}

251 252 253 254
static int test06(void)
{
	struct lcd *lcd;
	int ret;
255 256
	gpa_t gpa;
	hpa_t hpa;
257 258 259 260 261 262 263 264 265 266
	pgd_t *pgd_entry;
	pud_t *pud;
	pud_t *pud_entry;

	ret = lcd_create(&lcd);
	if (ret) {
		printk(KERN_ERR "lcd test: test06 failed to create lcd\n");
		goto fail1;
	}
	
Charles Jacobsen's avatar
Charles Jacobsen committed
267 268
	ret = lcd_mm_gva_init(lcd, LCD_ARCH_FREE,
			gpa_add(LCD_ARCH_FREE, 4 * (1 << 20)));
269 270 271 272 273 274 275 276 277 278 279 280 281 282 283
	if (ret) {
		printk(KERN_ERR "lcd test: test06 failed to init gva\n");
		goto fail2;
	}

	ret = lcd_mm_gva_alloc(lcd, &gpa, &hpa);
	if (ret) {
		printk(KERN_ERR "lcd test: test06 failed to alloc pg mem\n");
		goto fail3;
	}

	/*
	 * Populate 5th entry in pud to point to a (bogus) pmd at
	 * gpa 0x1234000UL.
	 */
284 285
	pud = (pud_t *)hpa2va(hpa);
	set_pud_gpa(pud + 4, __gpa(0x1234000UL));
286 287 288 289 290 291 292 293 294

	/*
	 * Set up pgd entry for look up, and find pud
	 */
	pgd_entry = kmalloc(sizeof(*pgd_entry), GFP_KERNEL);
	if (!pgd_entry) {
		goto fail4;
	}

295 296
	set_pgd_gpa(pgd_entry, gpa);
	ret = lcd_mm_gva_lookup_pud(lcd, __gva(0x4UL << PUD_SHIFT), 
297 298 299 300 301 302 303 304 305
				pgd_entry, &pud_entry);
	if (ret) {
		printk(KERN_ERR "lcd test: test06 failed to lookup pud\n");
		goto fail5;
	}

	/*
	 * Check
	 */
306
	if (gpa_val(pud_gpa(pud_entry)) != 0x1234000UL) {
307
		printk(KERN_ERR "lcd test: test06 pmd gpa is %lx\n",
308
			gpa_val(pud_gpa(pud_entry)));
309
		ret = -1;
310 311 312
		goto fail6;
	}

313 314
	ret = 0;
	goto done;
315

Charles Jacobsen's avatar
Charles Jacobsen committed
316
done:
317 318 319 320
fail6:
fail5:
	kfree(pgd_entry);
fail4:
321
	free_page(hva_val(hpa2hva(hpa)));
322
	lcd_arch_ept_unmap_range(lcd->lcd_arch, gpa, 1);
323 324 325 326 327 328 329 330 331 332 333
fail3:
fail2:
	lcd_destroy(lcd);
fail1:
	return ret;
}

static int test07(void)
{
	struct lcd *lcd;
	int ret;
334
	gpa_t gpa;
335 336 337 338 339 340 341

	ret = lcd_create(&lcd);
	if (ret) {
		printk(KERN_ERR "lcd test: test07 failed to create lcd\n");
		goto fail1;
	}
	
Charles Jacobsen's avatar
Charles Jacobsen committed
342 343
	ret = lcd_mm_gva_init(lcd, LCD_ARCH_FREE,
			gpa_add(LCD_ARCH_FREE, 4 * (1 << 20)));
344 345 346 347 348 349 350 351
	if (ret) {
		printk(KERN_ERR "lcd test: test07 failed to init gva\n");
		goto fail2;
	}

	/*
	 * Map gva 0x1234000UL to gpa 0x5678000UL
	 */
352
	ret = lcd_mm_gva_map(lcd, __gva(0x1234000UL), __gpa(0x5678000UL));
353 354
	if (ret) {
		printk(KERN_ERR "lcd test: test07 failed to map\n");
355
		goto fail3;
356 357 358 359 360
	}

	/*
	 * Check
	 */
361
	ret = lcd_mm_gva_to_gpa(lcd, __gva(0x1234000UL), &gpa);
362 363
	if (ret) {
		printk(KERN_ERR "lcd test: test07 failed to lookup\n");
364
		goto fail4;
365 366
	}

367
	if (gpa_val(gpa) != 0x5678000UL) {
368
		printk(KERN_ERR "lcd test: test07 got phys addr %lx\n",
369
			gpa_val(gpa));
370
		goto fail5;
371 372
	}

373 374 375 376 377 378
	ret = lcd_mm_gva_unmap(lcd, __gva(0x1234000UL));
	if (ret) {
		printk(KERN_ERR "lcd test: test07 failed to unmap\n");
		goto fail6;
	}

379 380
	ret = 0;
	goto done;
381

Charles Jacobsen's avatar
Charles Jacobsen committed
382
done:
383
fail6:
384 385 386 387 388 389 390 391 392
fail5:
fail4:
fail3:
fail2:
	lcd_destroy(lcd);
fail1:
	return ret;
}

393 394 395 396 397 398
static int test08(void)
{
	struct lcd *lcd;
	int ret;
	pgd_t *pgd_entry1;
	pgd_t *pgd_entry2;
399 400
	gpa_t gpa1;
	gpa_t gpa2;
401 402 403 404 405 406 407

	ret = lcd_create(&lcd);
	if (ret) {
		printk(KERN_ERR "lcd test: test08 failed to create lcd\n");
		goto fail1;
	}
	
Charles Jacobsen's avatar
Charles Jacobsen committed
408 409
	ret = lcd_mm_gva_init(lcd, LCD_ARCH_FREE, 
			gpa_add(LCD_ARCH_FREE, 2 * PAGE_SIZE));
410 411 412 413 414
	if (ret) {
		printk(KERN_ERR "lcd test: test08 failed to init gva\n");
		goto fail2;
	}

415
	ret = lcd_mm_gva_walk_pgd(lcd, __gva(0x1234000UL), &pgd_entry1);
416 417 418 419 420
	if (ret) {
		printk(KERN_ERR "lcd test: test08 failed to walk pgd\n");
		goto fail3;
	}

421
	ret = lcd_mm_gva_walk_pgd(lcd, __gva(0x1234000UL), &pgd_entry2);
422 423 424 425 426 427 428 429 430 431 432
	if (ret) {
		printk(KERN_ERR "lcd test: test08 failed to walk pgd2\n");
		goto fail4;
	}

	if (pgd_entry1 != pgd_entry2) {
		printk(KERN_ERR "lcd test: test08 entries differ\n");
		ret = -1;
		goto fail5;
	}

Charles Jacobsen's avatar
Charles Jacobsen committed
433 434 435 436 437 438
	if (!pgd_present(*pgd_entry1) || !pgd_present(*pgd_entry2)) {
		printk(KERN_ERR "lcd test: test08 entries not present\n");
		ret = -1;
		goto fail5;
	}

439 440
	gpa1 = pgd_gpa(pgd_entry1);
	gpa2 = pgd_gpa(pgd_entry2);
Charles Jacobsen's avatar
Charles Jacobsen committed
441 442
	if (gpa_val(gpa1) < gpa_val(LCD_ARCH_FREE) || 
		gpa_val(gpa1) > gpa_val(gpa_add(LCD_ARCH_FREE,2 * PAGE_SIZE))){
443
		printk(KERN_ERR "lcd test: test08 bad gpa %lx\n",
444
			gpa_val(gpa1));
445 446 447 448
		ret = -1;
		goto fail5;
	}
	
449
	if (gpa_val(gpa1) != gpa_val(gpa2)) {
450
		printk(KERN_ERR "lcd test: test08 two diff gpa's: first = %lx, second %lx\n",
451
			gpa_val(gpa1), gpa_val(gpa2));
452 453 454 455
		ret = -1;
		goto fail5;
	}

456 457
	ret = 0;
	goto done;
458

Charles Jacobsen's avatar
Charles Jacobsen committed
459
done:
460 461 462 463 464 465 466 467 468
fail5:
fail4:
fail3:
fail2:
	lcd_destroy(lcd);
fail1:
	return ret;
}

469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486
static int test09_help(struct lcd *lcd, unsigned long base)
{
	unsigned long off;
	gpa_t actual;

	for (off = 0; off < (1 << 22); off += PAGE_SIZE) {
		if (lcd_mm_gva_to_gpa(lcd, __gva(base + off), &actual)) {
			printk(KERN_ERR "lcd test: test09 failed lookup at %lx\n",
				base + off);
			return -1;
		}
		if (gpa_val(actual) != base + off) {
			printk(KERN_ERR "lcd test: test09 expected gpa %lx got %lx\n",
				base + off,
				gpa_val(actual));
			return -1;
		}
	}
Charles Jacobsen's avatar
Charles Jacobsen committed
487
	return 0;
488 489
}

Charles Jacobsen's avatar
Charles Jacobsen committed
490
static int test09(void)
491 492 493
{
	struct lcd *lcd;
	int ret;
494
	unsigned long base;
495 496 497

	ret = lcd_create(&lcd);
	if (ret) {
Charles Jacobsen's avatar
Charles Jacobsen committed
498
		printk(KERN_ERR "lcd test: test09 failed to create lcd\n");
499 500 501
		goto fail1;
	}
	
Charles Jacobsen's avatar
Charles Jacobsen committed
502 503
	ret = lcd_mm_gva_init(lcd, LCD_ARCH_FREE,
			gpa_add(LCD_ARCH_FREE, 4 * (1 << 20)));
504
	if (ret) {
Charles Jacobsen's avatar
Charles Jacobsen committed
505
		printk(KERN_ERR "lcd test: test09 failed to init gva\n");
506 507 508 509
		goto fail2;
	}

	/*
510
	 * Map 0x0 - 0x400000 (first 4 MBs, takes two page tables)
511
	 */
512
	ret = lcd_mm_gva_map_range(lcd, __gva(0), __gpa(0), 1024);
513
	if (ret) {
Charles Jacobsen's avatar
Charles Jacobsen committed
514
		printk(KERN_ERR "lcd test: test09 failed to map first 4 MBs\n");
515 516 517 518
		goto fail3;
	}

	/*
519
	 * Map 0x40000000 - 0x40400000 (1GB -- 1GB + 4MBs)
520
	 */
521
	ret = lcd_mm_gva_map_range(lcd, __gva(1 << 30), __gpa(1 << 30), 1024);
522
	if (ret) {
Charles Jacobsen's avatar
Charles Jacobsen committed
523
		printk(KERN_ERR "lcd test: test09 failed to map 2nd 4 MBs\n");
524
		goto fail4;
525 526 527
	}

	/*
528
	 * Map 0x8000000000 - 0x8000400000 (512GB -- 512GB + 4MBs)
529
	 */
Charles Jacobsen's avatar
Charles Jacobsen committed
530 531
	ret = lcd_mm_gva_map_range(lcd, __gva(1UL << 39), 
				__gpa(1UL << 39), 1024);
532
	if (ret) {
Charles Jacobsen's avatar
Charles Jacobsen committed
533
		printk(KERN_ERR "lcd test: test09 failed to map 3rd 4 MBs\n");
534
		goto fail5;
535 536 537 538 539 540 541
	}

	/*
	 * CHECK
	 */

	base = 0;
542 543 544 545 546
	if (test09_help(lcd, base))
		goto fail6;
	base = 1 << 30;
	if (test09_help(lcd, base))
		goto fail6;
Charles Jacobsen's avatar
Charles Jacobsen committed
547
	base = 1UL << 39;
548 549
	if (test09_help(lcd, base))
		goto fail6;
550

551 552
	ret = 0;
	goto done;
553

554 555
done:
fail6:
Charles Jacobsen's avatar
Charles Jacobsen committed
556
	lcd_mm_gva_unmap_range(lcd, __gva(1UL << 39), 1024);
557 558 559 560
fail5:
	lcd_mm_gva_unmap_range(lcd, __gva(1 << 30), 1024);
fail4:
	lcd_mm_gva_unmap_range(lcd, __gva(0), 1024);
561 562 563 564 565 566
fail3:
fail2:
	lcd_destroy(lcd);
fail1:
	return ret;
}
567

568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606
static int test10(void)
{
	struct task_struct *t;
	int r;

	/*
	 * lcd-module-load-test.c is in virt/lcd-domains/
	 */

	/*
	 * Create it
	 */
	t = lcd_create_as_module("lcd_module_load_test");
	if (!t) {
		LCD_ERR("create");
		goto fail1;
	}
	
	/*
	 * Run it (once)
	 */
	r = lcd_run_as_module(t);
	if (r) {
		LCD_ERR("run");
		goto fail2;
	}

	/*
	 * Tear it down
	 */
	lcd_destroy_as_module(t, "lcd_module_load_test");
	return 0;

fail2:
	lcd_destroy_as_module(t, "lcd_module_load_test");
fail1:
	return -1;
}

607 608 609 610
static void lcd_tests(void)
{
	if (test01())
		return;
Charlie Jacobsen's avatar
Charlie Jacobsen committed
611 612
	if (test02())
		return;
613 614
	if (test03())
		return;
615 616
	if (test04())
		return;
Charlie Jacobsen's avatar
Charlie Jacobsen committed
617 618
	if (test05())
		return;
619 620 621 622
	if (test06())
		return;
	if (test07())
		return;
Charles Jacobsen's avatar
Charles Jacobsen committed
623 624
	if (test08())
		return;
625 626
	if (test09())
		return;
627 628
	if (test10())
		return;
629
	printk(KERN_ERR "lcd-domains: all tests passed!\n");
630 631
	return;
}