diff options
| -rw-r--r-- | arch/x86/xen/mmu.c | 30 |
1 files changed, 25 insertions, 5 deletions
diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c index 3a73785631ce..3f1783a79a3c 100644 --- a/arch/x86/xen/mmu.c +++ b/arch/x86/xen/mmu.c | |||
| @@ -308,8 +308,20 @@ static bool xen_batched_set_pte(pte_t *ptep, pte_t pteval) | |||
| 308 | 308 | ||
| 309 | static inline void __xen_set_pte(pte_t *ptep, pte_t pteval) | 309 | static inline void __xen_set_pte(pte_t *ptep, pte_t pteval) |
| 310 | { | 310 | { |
| 311 | if (!xen_batched_set_pte(ptep, pteval)) | 311 | if (!xen_batched_set_pte(ptep, pteval)) { |
| 312 | native_set_pte(ptep, pteval); | 312 | /* |
| 313 | * Could call native_set_pte() here and trap and | ||
| 314 | * emulate the PTE write but with 32-bit guests this | ||
| 315 | * needs two traps (one for each of the two 32-bit | ||
| 316 | * words in the PTE) so do one hypercall directly | ||
| 317 | * instead. | ||
| 318 | */ | ||
| 319 | struct mmu_update u; | ||
| 320 | |||
| 321 | u.ptr = virt_to_machine(ptep).maddr | MMU_NORMAL_PT_UPDATE; | ||
| 322 | u.val = pte_val_ma(pteval); | ||
| 323 | HYPERVISOR_mmu_update(&u, 1, NULL, DOMID_SELF); | ||
| 324 | } | ||
| 313 | } | 325 | } |
| 314 | 326 | ||
| 315 | static void xen_set_pte(pte_t *ptep, pte_t pteval) | 327 | static void xen_set_pte(pte_t *ptep, pte_t pteval) |
| @@ -1416,13 +1428,21 @@ static pte_t __init mask_rw_pte(pte_t *ptep, pte_t pte) | |||
| 1416 | } | 1428 | } |
| 1417 | #endif /* CONFIG_X86_64 */ | 1429 | #endif /* CONFIG_X86_64 */ |
| 1418 | 1430 | ||
| 1419 | /* Init-time set_pte while constructing initial pagetables, which | 1431 | /* |
| 1420 | doesn't allow RO pagetable pages to be remapped RW */ | 1432 | * Init-time set_pte while constructing initial pagetables, which |
| 1433 | * doesn't allow RO page table pages to be remapped RW. | ||
| 1434 | * | ||
| 1435 | * Many of these PTE updates are done on unpinned and writable pages | ||
| 1436 | * and doing a hypercall for these is unnecessary and expensive. At | ||
| 1437 | * this point it is not possible to tell if a page is pinned or not, | ||
| 1438 | * so always write the PTE directly and rely on Xen trapping and | ||
| 1439 | * emulating any updates as necessary. | ||
| 1440 | */ | ||
| 1421 | static void __init xen_set_pte_init(pte_t *ptep, pte_t pte) | 1441 | static void __init xen_set_pte_init(pte_t *ptep, pte_t pte) |
| 1422 | { | 1442 | { |
| 1423 | pte = mask_rw_pte(ptep, pte); | 1443 | pte = mask_rw_pte(ptep, pte); |
| 1424 | 1444 | ||
| 1425 | xen_set_pte(ptep, pte); | 1445 | native_set_pte(ptep, pte); |
| 1426 | } | 1446 | } |
| 1427 | 1447 | ||
| 1428 | static void pin_pagetable_pfn(unsigned cmd, unsigned long pfn) | 1448 | static void pin_pagetable_pfn(unsigned cmd, unsigned long pfn) |
