aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/lguest/page_tables.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/lguest/page_tables.c')
-rw-r--r--drivers/lguest/page_tables.c42
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 */
650unsigned long guest_pa(struct lg_cpu *cpu, unsigned long vaddr) 650bool __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
684fail:
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 */
693unsigned 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/*