Commit 92b4d8df8436cdd74d22a2a5b6b23b9abc737a3e
1 parent
acdd0b6292
Exists in
master
and in
20 other branches
lguest: PAE fixes
1) j wasn't initialized in setup_pagetables, so they weren't set up for me causing immediate guest crashes. 2) gpte_addr should not re-read the pmd from the Guest. Especially not BUG_ON() based on the value. If we ever supported SMP guests, they could trigger that. And the Launcher could also trigger it (tho currently root-only). Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Showing 1 changed file with 21 additions and 17 deletions Side-by-side Diff
drivers/lguest/page_tables.c
| ... | ... | @@ -154,26 +154,25 @@ |
| 154 | 154 | BUG_ON(!(pgd_flags(gpgd) & _PAGE_PRESENT)); |
| 155 | 155 | return gpage + pmd_index(vaddr) * sizeof(pmd_t); |
| 156 | 156 | } |
| 157 | -#endif | |
| 158 | 157 | |
| 159 | 158 | static unsigned long gpte_addr(struct lg_cpu *cpu, |
| 160 | - pgd_t gpgd, unsigned long vaddr) | |
| 159 | + pmd_t gpmd, unsigned long vaddr) | |
| 161 | 160 | { |
| 162 | -#ifdef CONFIG_X86_PAE | |
| 163 | - pmd_t gpmd; | |
| 164 | -#endif | |
| 165 | - unsigned long gpage; | |
| 161 | + unsigned long gpage = pmd_pfn(gpmd) << PAGE_SHIFT; | |
| 166 | 162 | |
| 167 | - BUG_ON(!(pgd_flags(gpgd) & _PAGE_PRESENT)); | |
| 168 | -#ifdef CONFIG_X86_PAE | |
| 169 | - gpmd = lgread(cpu, gpmd_addr(gpgd, vaddr), pmd_t); | |
| 170 | - gpage = pmd_pfn(gpmd) << PAGE_SHIFT; | |
| 171 | 163 | BUG_ON(!(pmd_flags(gpmd) & _PAGE_PRESENT)); |
| 164 | + return gpage + pte_index(vaddr) * sizeof(pte_t); | |
| 165 | +} | |
| 172 | 166 | #else |
| 173 | - gpage = pgd_pfn(gpgd) << PAGE_SHIFT; | |
| 174 | -#endif | |
| 167 | +static unsigned long gpte_addr(struct lg_cpu *cpu, | |
| 168 | + pgd_t gpgd, unsigned long vaddr) | |
| 169 | +{ | |
| 170 | + unsigned long gpage = pgd_pfn(gpgd) << PAGE_SHIFT; | |
| 171 | + | |
| 172 | + BUG_ON(!(pgd_flags(gpgd) & _PAGE_PRESENT)); | |
| 175 | 173 | return gpage + pte_index(vaddr) * sizeof(pte_t); |
| 176 | 174 | } |
| 175 | +#endif | |
| 177 | 176 | /*:*/ |
| 178 | 177 | |
| 179 | 178 | /*M:014 get_pfn is slow: we could probably try to grab batches of pages here as |
| 180 | 179 | |
| 181 | 180 | |
| ... | ... | @@ -339,10 +338,15 @@ |
| 339 | 338 | * number in the shadow PMD is the page we just allocated. */ |
| 340 | 339 | native_set_pmd(spmd, __pmd(__pa(ptepage) | pmd_flags(gpmd))); |
| 341 | 340 | } |
| 342 | -#endif | |
| 341 | + | |
| 343 | 342 | /* OK, now we look at the lower level in the Guest page table: keep its |
| 344 | 343 | * address, because we might update it later. */ |
| 344 | + gpte_ptr = gpte_addr(cpu, gpmd, vaddr); | |
| 345 | +#else | |
| 346 | + /* OK, now we look at the lower level in the Guest page table: keep its | |
| 347 | + * address, because we might update it later. */ | |
| 345 | 348 | gpte_ptr = gpte_addr(cpu, gpgd, vaddr); |
| 349 | +#endif | |
| 346 | 350 | gpte = lgread(cpu, gpte_ptr, pte_t); |
| 347 | 351 | |
| 348 | 352 | /* If this page isn't in the Guest page tables, we can't page it in. */ |
| ... | ... | @@ -522,7 +526,6 @@ |
| 522 | 526 | { |
| 523 | 527 | pgd_t gpgd; |
| 524 | 528 | pte_t gpte; |
| 525 | - | |
| 526 | 529 | #ifdef CONFIG_X86_PAE |
| 527 | 530 | pmd_t gpmd; |
| 528 | 531 | #endif |
| 529 | 532 | |
| 530 | 533 | |
| ... | ... | @@ -534,13 +537,14 @@ |
| 534 | 537 | return -1UL; |
| 535 | 538 | } |
| 536 | 539 | |
| 537 | - gpte = lgread(cpu, gpte_addr(cpu, gpgd, vaddr), pte_t); | |
| 538 | 540 | #ifdef CONFIG_X86_PAE |
| 539 | 541 | gpmd = lgread(cpu, gpmd_addr(gpgd, vaddr), pmd_t); |
| 540 | 542 | if (!(pmd_flags(gpmd) & _PAGE_PRESENT)) |
| 541 | 543 | kill_guest(cpu, "Bad address %#lx", vaddr); |
| 542 | -#endif | |
| 544 | + gpte = lgread(cpu, gpte_addr(cpu, gpmd, vaddr), pte_t); | |
| 545 | +#else | |
| 543 | 546 | gpte = lgread(cpu, gpte_addr(cpu, gpgd, vaddr), pte_t); |
| 547 | +#endif | |
| 544 | 548 | if (!(pte_flags(gpte) & _PAGE_PRESENT)) |
| 545 | 549 | kill_guest(cpu, "Bad address %#lx", vaddr); |
| 546 | 550 | |
| ... | ... | @@ -847,7 +851,7 @@ |
| 847 | 851 | /* The top level points to the linear page table pages above. |
| 848 | 852 | * We setup the identity and linear mappings here. */ |
| 849 | 853 | #ifdef CONFIG_X86_PAE |
| 850 | - for (i = 0, j; i < mapped_pages && j < PTRS_PER_PMD; | |
| 854 | + for (i = j = 0; i < mapped_pages && j < PTRS_PER_PMD; | |
| 851 | 855 | i += PTRS_PER_PTE, j++) { |
| 852 | 856 | native_set_pmd(&pmd, __pmd(((unsigned long)(linear + i) |
| 853 | 857 | - mem_base) | _PAGE_PRESENT | _PAGE_RW | _PAGE_USER)); |