aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/lguest
diff options
context:
space:
mode:
authorRusty Russell <rusty@rustcorp.com.au>2015-02-10 23:45:09 -0500
committerRusty Russell <rusty@rustcorp.com.au>2015-02-11 01:17:31 -0500
commitc9e433e4b852b70ea267388cf9b5d8096b04c44c (patch)
treee456fdc2a7b08ded02723f9235e6d6afd7991642 /drivers/lguest
parent8ed313001a892f240269dea05d4b925cbd150492 (diff)
lguest: add infrastructure to check mappings.
We normally abort the guest unconditionally when it gives us a bad address, but in the next patch we want to copy some bytes which may not be mapped. Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Diffstat (limited to 'drivers/lguest')
-rw-r--r--drivers/lguest/lg.h1
-rw-r--r--drivers/lguest/page_tables.c42
2 files changed, 30 insertions, 13 deletions
diff --git a/drivers/lguest/lg.h b/drivers/lguest/lg.h
index 020fec5bb072..9da4f351e077 100644
--- a/drivers/lguest/lg.h
+++ b/drivers/lguest/lg.h
@@ -202,6 +202,7 @@ void guest_set_pte(struct lg_cpu *cpu, unsigned long gpgdir,
202void map_switcher_in_guest(struct lg_cpu *cpu, struct lguest_pages *pages); 202void map_switcher_in_guest(struct lg_cpu *cpu, struct lguest_pages *pages);
203bool demand_page(struct lg_cpu *cpu, unsigned long cr2, int errcode); 203bool demand_page(struct lg_cpu *cpu, unsigned long cr2, int errcode);
204void pin_page(struct lg_cpu *cpu, unsigned long vaddr); 204void pin_page(struct lg_cpu *cpu, unsigned long vaddr);
205bool __guest_pa(struct lg_cpu *cpu, unsigned long vaddr, unsigned long *paddr);
205unsigned long guest_pa(struct lg_cpu *cpu, unsigned long vaddr); 206unsigned long guest_pa(struct lg_cpu *cpu, unsigned long vaddr);
206void page_table_guest_data_init(struct lg_cpu *cpu); 207void page_table_guest_data_init(struct lg_cpu *cpu);
207 208
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/*