aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRusty Russell <rusty@rustcorp.com.au>2013-04-22 00:40:39 -0400
committerRusty Russell <rusty@rustcorp.com.au>2013-04-22 02:14:47 -0400
commit17427e08faae3e63271a9c2d0edb6a22e5fbb54b (patch)
treef2a7b84741ce7c21b818a2da9873d7eef0b92307
parente1d12606f756bdb8328a66a2873dca6c46bcb4e5 (diff)
lguest: extract shadow PTE walking / allocating.
We want a separate find_pte() function so we can call it for populating the switcher PTE entries. We can also use it in page_writable(). Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
-rw-r--r--drivers/lguest/page_tables.c170
1 files changed, 101 insertions, 69 deletions
diff --git a/drivers/lguest/page_tables.c b/drivers/lguest/page_tables.c
index f074f34acb86..009c717fda99 100644
--- a/drivers/lguest/page_tables.c
+++ b/drivers/lguest/page_tables.c
@@ -291,6 +291,88 @@ static bool check_gpmd(struct lg_cpu *cpu, pmd_t gpmd)
291} 291}
292#endif 292#endif
293 293
294/*H:331
295 * This is the core routine to walk the shadow page tables and find the page
296 * table entry for a specific address.
297 *
298 * If allocate is set, then we allocate any missing levels, setting the flags
299 * on the new page directory and mid-level directories using the arguments
300 * (which are copied from the Guest's page table entries).
301 */
302static pte_t *find_spte(struct lg_cpu *cpu, unsigned long vaddr, bool allocate,
303 int pgd_flags, int pmd_flags)
304{
305 pgd_t *spgd;
306 /* Mid level for PAE. */
307#ifdef CONFIG_X86_PAE
308 pmd_t *spmd;
309#endif
310
311 /* Get top level entry. */
312 spgd = spgd_addr(cpu, cpu->cpu_pgd, vaddr);
313 if (!(pgd_flags(*spgd) & _PAGE_PRESENT)) {
314 /* No shadow entry: allocate a new shadow PTE page. */
315 unsigned long ptepage;
316
317 /* If they didn't want us to allocate anything, stop. */
318 if (!allocate)
319 return NULL;
320
321 ptepage = get_zeroed_page(GFP_KERNEL);
322 /*
323 * This is not really the Guest's fault, but killing it is
324 * simple for this corner case.
325 */
326 if (!ptepage) {
327 kill_guest(cpu, "out of memory allocating pte page");
328 return NULL;
329 }
330 /*
331 * And we copy the flags to the shadow PGD entry. The page
332 * number in the shadow PGD is the page we just allocated.
333 */
334 set_pgd(spgd, __pgd(__pa(ptepage) | pgd_flags));
335 }
336
337 /*
338 * Intel's Physical Address Extension actually uses three levels of
339 * page tables, so we need to look in the mid-level.
340 */
341#ifdef CONFIG_X86_PAE
342 /* Now look at the mid-level shadow entry. */
343 spmd = spmd_addr(cpu, *spgd, vaddr);
344
345 if (!(pmd_flags(*spmd) & _PAGE_PRESENT)) {
346 /* No shadow entry: allocate a new shadow PTE page. */
347 unsigned long ptepage;
348
349 /* If they didn't want us to allocate anything, stop. */
350 if (!allocate)
351 return NULL;
352
353 ptepage = get_zeroed_page(GFP_KERNEL);
354
355 /*
356 * This is not really the Guest's fault, but killing it is
357 * simple for this corner case.
358 */
359 if (!ptepage) {
360 kill_guest(cpu, "out of memory allocating pmd page");
361 return NULL;
362 }
363
364 /*
365 * And we copy the flags to the shadow PMD entry. The page
366 * number in the shadow PMD is the page we just allocated.
367 */
368 set_pmd(spmd, __pmd(__pa(ptepage) | pmd_flags));
369 }
370#endif
371
372 /* Get the pointer to the shadow PTE entry we're going to set. */
373 return spte_addr(cpu, *spgd, vaddr);
374}
375
294/*H:330 376/*H:330
295 * (i) Looking up a page table entry when the Guest faults. 377 * (i) Looking up a page table entry when the Guest faults.
296 * 378 *
@@ -304,17 +386,11 @@ static bool check_gpmd(struct lg_cpu *cpu, pmd_t gpmd)
304 */ 386 */
305bool demand_page(struct lg_cpu *cpu, unsigned long vaddr, int errcode) 387bool demand_page(struct lg_cpu *cpu, unsigned long vaddr, int errcode)
306{ 388{
307 pgd_t gpgd;
308 pgd_t *spgd;
309 unsigned long gpte_ptr; 389 unsigned long gpte_ptr;
310 pte_t gpte; 390 pte_t gpte;
311 pte_t *spte; 391 pte_t *spte;
312
313 /* Mid level for PAE. */
314#ifdef CONFIG_X86_PAE
315 pmd_t *spmd;
316 pmd_t gpmd; 392 pmd_t gpmd;
317#endif 393 pgd_t gpgd;
318 394
319 /* We never demand page the Switcher, so trying is a mistake. */ 395 /* We never demand page the Switcher, so trying is a mistake. */
320 if (vaddr >= switcher_addr) 396 if (vaddr >= switcher_addr)
@@ -329,67 +405,31 @@ bool demand_page(struct lg_cpu *cpu, unsigned long vaddr, int errcode)
329 /* Toplevel not present? We can't map it in. */ 405 /* Toplevel not present? We can't map it in. */
330 if (!(pgd_flags(gpgd) & _PAGE_PRESENT)) 406 if (!(pgd_flags(gpgd) & _PAGE_PRESENT))
331 return false; 407 return false;
332 }
333 408
334 /* Now look at the matching shadow entry. */ 409 /*
335 spgd = spgd_addr(cpu, cpu->cpu_pgd, vaddr); 410 * This kills the Guest if it has weird flags or tries to
336 if (!(pgd_flags(*spgd) & _PAGE_PRESENT)) { 411 * refer to a "physical" address outside the bounds.
337 /* No shadow entry: allocate a new shadow PTE page. */
338 unsigned long ptepage = get_zeroed_page(GFP_KERNEL);
339 /*
340 * This is not really the Guest's fault, but killing it is
341 * simple for this corner case.
342 */ 412 */
343 if (!ptepage) {
344 kill_guest(cpu, "out of memory allocating pte page");
345 return false;
346 }
347 /* We check that the Guest pgd is OK. */
348 if (!check_gpgd(cpu, gpgd)) 413 if (!check_gpgd(cpu, gpgd))
349 return false; 414 return false;
350 /*
351 * And we copy the flags to the shadow PGD entry. The page
352 * number in the shadow PGD is the page we just allocated.
353 */
354 set_pgd(spgd, __pgd(__pa(ptepage) | pgd_flags(gpgd)));
355 } 415 }
356 416
417 /* This "mid-level" entry is only used for non-linear, PAE mode. */
418 gpmd = __pmd(_PAGE_TABLE);
419
357#ifdef CONFIG_X86_PAE 420#ifdef CONFIG_X86_PAE
358 if (unlikely(cpu->linear_pages)) { 421 if (likely(!cpu->linear_pages)) {
359 /* Faking up a linear mapping. */
360 gpmd = __pmd(_PAGE_TABLE);
361 } else {
362 gpmd = lgread(cpu, gpmd_addr(gpgd, vaddr), pmd_t); 422 gpmd = lgread(cpu, gpmd_addr(gpgd, vaddr), pmd_t);
363 /* Middle level not present? We can't map it in. */ 423 /* Middle level not present? We can't map it in. */
364 if (!(pmd_flags(gpmd) & _PAGE_PRESENT)) 424 if (!(pmd_flags(gpmd) & _PAGE_PRESENT))
365 return false; 425 return false;
366 }
367
368 /* Now look at the matching shadow entry. */
369 spmd = spmd_addr(cpu, *spgd, vaddr);
370
371 if (!(pmd_flags(*spmd) & _PAGE_PRESENT)) {
372 /* No shadow entry: allocate a new shadow PTE page. */
373 unsigned long ptepage = get_zeroed_page(GFP_KERNEL);
374 426
375 /* 427 /*
376 * This is not really the Guest's fault, but killing it is 428 * This kills the Guest if it has weird flags or tries to
377 * simple for this corner case. 429 * refer to a "physical" address outside the bounds.
378 */ 430 */
379 if (!ptepage) {
380 kill_guest(cpu, "out of memory allocating pte page");
381 return false;
382 }
383
384 /* We check that the Guest pmd is OK. */
385 if (!check_gpmd(cpu, gpmd)) 431 if (!check_gpmd(cpu, gpmd))
386 return false; 432 return false;
387
388 /*
389 * And we copy the flags to the shadow PMD entry. The page
390 * number in the shadow PMD is the page we just allocated.
391 */
392 set_pmd(spmd, __pmd(__pa(ptepage) | pmd_flags(gpmd)));
393 } 433 }
394 434
395 /* 435 /*
@@ -441,7 +481,9 @@ bool demand_page(struct lg_cpu *cpu, unsigned long vaddr, int errcode)
441 gpte = pte_mkdirty(gpte); 481 gpte = pte_mkdirty(gpte);
442 482
443 /* Get the pointer to the shadow PTE entry we're going to set. */ 483 /* Get the pointer to the shadow PTE entry we're going to set. */
444 spte = spte_addr(cpu, *spgd, vaddr); 484 spte = find_spte(cpu, vaddr, true, pgd_flags(gpgd), pmd_flags(gpmd));
485 if (!spte)
486 return false;
445 487
446 /* 488 /*
447 * If there was a valid shadow PTE entry here before, we release it. 489 * If there was a valid shadow PTE entry here before, we release it.
@@ -493,33 +535,23 @@ bool demand_page(struct lg_cpu *cpu, unsigned long vaddr, int errcode)
493 */ 535 */
494static bool page_writable(struct lg_cpu *cpu, unsigned long vaddr) 536static bool page_writable(struct lg_cpu *cpu, unsigned long vaddr)
495{ 537{
496 pgd_t *spgd; 538 pte_t *spte;
497 unsigned long flags; 539 unsigned long flags;
498#ifdef CONFIG_X86_PAE
499 pmd_t *spmd;
500#endif
501 540
502 /* You can't put your stack in the Switcher! */ 541 /* You can't put your stack in the Switcher! */
503 if (vaddr >= switcher_addr) 542 if (vaddr >= switcher_addr)
504 return false; 543 return false;
505 544
506 /* Look at the current top level entry: is it present? */ 545 /* If there's no shadow PTE, it's not writable. */
507 spgd = spgd_addr(cpu, cpu->cpu_pgd, vaddr); 546 spte = find_spte(cpu, vaddr, false, 0, 0);
508 if (!(pgd_flags(*spgd) & _PAGE_PRESENT)) 547 if (!spte)
509 return false; 548 return false;
510 549
511#ifdef CONFIG_X86_PAE
512 spmd = spmd_addr(cpu, *spgd, vaddr);
513 if (!(pmd_flags(*spmd) & _PAGE_PRESENT))
514 return false;
515#endif
516
517 /* 550 /*
518 * Check the flags on the pte entry itself: it must be present and 551 * Check the flags on the pte entry itself: it must be present and
519 * writable. 552 * writable.
520 */ 553 */
521 flags = pte_flags(*(spte_addr(cpu, *spgd, vaddr))); 554 flags = pte_flags(*spte);
522
523 return (flags & (_PAGE_PRESENT|_PAGE_RW)) == (_PAGE_PRESENT|_PAGE_RW); 555 return (flags & (_PAGE_PRESENT|_PAGE_RW)) == (_PAGE_PRESENT|_PAGE_RW);
524} 556}
525 557