diff options
Diffstat (limited to 'drivers/lguest/page_tables.c')
-rw-r--r-- | drivers/lguest/page_tables.c | 42 |
1 files changed, 29 insertions, 13 deletions
diff --git a/drivers/lguest/page_tables.c b/drivers/lguest/page_tables.c index e8b55c3a6170..69c35caa955a 100644 --- a/drivers/lguest/page_tables.c +++ b/drivers/lguest/page_tables.c | |||
@@ -647,7 +647,7 @@ void guest_pagetable_flush_user(struct lg_cpu *cpu) | |||
647 | /*:*/ | 647 | /*:*/ |
648 | 648 | ||
649 | /* We walk down the guest page tables to get a guest-physical address */ | 649 | /* We walk down the guest page tables to get a guest-physical address */ |
650 | unsigned long guest_pa(struct lg_cpu *cpu, unsigned long vaddr) | 650 | bool __guest_pa(struct lg_cpu *cpu, unsigned long vaddr, unsigned long *paddr) |
651 | { | 651 | { |
652 | pgd_t gpgd; | 652 | pgd_t gpgd; |
653 | pte_t gpte; | 653 | pte_t gpte; |
@@ -656,31 +656,47 @@ unsigned long guest_pa(struct lg_cpu *cpu, unsigned long vaddr) | |||
656 | #endif | 656 | #endif |
657 | 657 | ||
658 | /* Still not set up? Just map 1:1. */ | 658 | /* Still not set up? Just map 1:1. */ |
659 | if (unlikely(cpu->linear_pages)) | 659 | if (unlikely(cpu->linear_pages)) { |
660 | return vaddr; | 660 | *paddr = vaddr; |
661 | return true; | ||
662 | } | ||
661 | 663 | ||
662 | /* First step: get the top-level Guest page table entry. */ | 664 | /* First step: get the top-level Guest page table entry. */ |
663 | gpgd = lgread(cpu, gpgd_addr(cpu, vaddr), pgd_t); | 665 | gpgd = lgread(cpu, gpgd_addr(cpu, vaddr), pgd_t); |
664 | /* Toplevel not present? We can't map it in. */ | 666 | /* Toplevel not present? We can't map it in. */ |
665 | if (!(pgd_flags(gpgd) & _PAGE_PRESENT)) { | 667 | if (!(pgd_flags(gpgd) & _PAGE_PRESENT)) |
666 | kill_guest(cpu, "Bad address %#lx", vaddr); | 668 | goto fail; |
667 | return -1UL; | ||
668 | } | ||
669 | 669 | ||
670 | #ifdef CONFIG_X86_PAE | 670 | #ifdef CONFIG_X86_PAE |
671 | gpmd = lgread(cpu, gpmd_addr(gpgd, vaddr), pmd_t); | 671 | gpmd = lgread(cpu, gpmd_addr(gpgd, vaddr), pmd_t); |
672 | if (!(pmd_flags(gpmd) & _PAGE_PRESENT)) { | 672 | if (!(pmd_flags(gpmd) & _PAGE_PRESENT)) |
673 | kill_guest(cpu, "Bad address %#lx", vaddr); | 673 | goto fail; |
674 | return -1UL; | ||
675 | } | ||
676 | gpte = lgread(cpu, gpte_addr(cpu, gpmd, vaddr), pte_t); | 674 | gpte = lgread(cpu, gpte_addr(cpu, gpmd, vaddr), pte_t); |
677 | #else | 675 | #else |
678 | gpte = lgread(cpu, gpte_addr(cpu, gpgd, vaddr), pte_t); | 676 | gpte = lgread(cpu, gpte_addr(cpu, gpgd, vaddr), pte_t); |
679 | #endif | 677 | #endif |
680 | if (!(pte_flags(gpte) & _PAGE_PRESENT)) | 678 | if (!(pte_flags(gpte) & _PAGE_PRESENT)) |
681 | kill_guest(cpu, "Bad address %#lx", vaddr); | 679 | goto fail; |
680 | |||
681 | *paddr = pte_pfn(gpte) * PAGE_SIZE | (vaddr & ~PAGE_MASK); | ||
682 | return true; | ||
683 | |||
684 | fail: | ||
685 | *paddr = -1UL; | ||
686 | return false; | ||
687 | } | ||
682 | 688 | ||
683 | return pte_pfn(gpte) * PAGE_SIZE | (vaddr & ~PAGE_MASK); | 689 | /* |
690 | * This is the version we normally use: kills the Guest if it uses a | ||
691 | * bad address | ||
692 | */ | ||
693 | unsigned long guest_pa(struct lg_cpu *cpu, unsigned long vaddr) | ||
694 | { | ||
695 | unsigned long paddr; | ||
696 | |||
697 | if (!__guest_pa(cpu, vaddr, &paddr)) | ||
698 | kill_guest(cpu, "Bad address %#lx", vaddr); | ||
699 | return paddr; | ||
684 | } | 700 | } |
685 | 701 | ||
686 | /* | 702 | /* |