diff options
author | Ingo Molnar <mingo@elte.hu> | 2011-03-18 05:38:53 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2011-03-18 05:39:00 -0400 |
commit | 8dd8997d2c56c9f248294805e129e1fc69444380 (patch) | |
tree | 3b030a04295fc031db98746c4074c2df1ed6a19f /arch/x86/xen/mmu.c | |
parent | 1eda75c131ea42ec173323b6c34aeed78ae637c1 (diff) | |
parent | 016aa2ed1cc9cf704cf76d8df07751b6daa9750f (diff) |
Merge branch 'linus' into x86/urgent
Merge reason: Merge upstream commits to avoid conflicts in upcoming patches.
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'arch/x86/xen/mmu.c')
-rw-r--r-- | arch/x86/xen/mmu.c | 74 |
1 files changed, 70 insertions, 4 deletions
diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c index f6089421147a..3f6f3347aa17 100644 --- a/arch/x86/xen/mmu.c +++ b/arch/x86/xen/mmu.c | |||
@@ -46,6 +46,7 @@ | |||
46 | #include <linux/module.h> | 46 | #include <linux/module.h> |
47 | #include <linux/gfp.h> | 47 | #include <linux/gfp.h> |
48 | #include <linux/memblock.h> | 48 | #include <linux/memblock.h> |
49 | #include <linux/seq_file.h> | ||
49 | 50 | ||
50 | #include <asm/pgtable.h> | 51 | #include <asm/pgtable.h> |
51 | #include <asm/tlbflush.h> | 52 | #include <asm/tlbflush.h> |
@@ -416,8 +417,12 @@ static pteval_t pte_pfn_to_mfn(pteval_t val) | |||
416 | if (val & _PAGE_PRESENT) { | 417 | if (val & _PAGE_PRESENT) { |
417 | unsigned long pfn = (val & PTE_PFN_MASK) >> PAGE_SHIFT; | 418 | unsigned long pfn = (val & PTE_PFN_MASK) >> PAGE_SHIFT; |
418 | pteval_t flags = val & PTE_FLAGS_MASK; | 419 | pteval_t flags = val & PTE_FLAGS_MASK; |
419 | unsigned long mfn = pfn_to_mfn(pfn); | 420 | unsigned long mfn; |
420 | 421 | ||
422 | if (!xen_feature(XENFEAT_auto_translated_physmap)) | ||
423 | mfn = get_phys_to_machine(pfn); | ||
424 | else | ||
425 | mfn = pfn; | ||
421 | /* | 426 | /* |
422 | * If there's no mfn for the pfn, then just create an | 427 | * If there's no mfn for the pfn, then just create an |
423 | * empty non-present pte. Unfortunately this loses | 428 | * empty non-present pte. Unfortunately this loses |
@@ -427,8 +432,18 @@ static pteval_t pte_pfn_to_mfn(pteval_t val) | |||
427 | if (unlikely(mfn == INVALID_P2M_ENTRY)) { | 432 | if (unlikely(mfn == INVALID_P2M_ENTRY)) { |
428 | mfn = 0; | 433 | mfn = 0; |
429 | flags = 0; | 434 | flags = 0; |
435 | } else { | ||
436 | /* | ||
437 | * Paramount to do this test _after_ the | ||
438 | * INVALID_P2M_ENTRY as INVALID_P2M_ENTRY & | ||
439 | * IDENTITY_FRAME_BIT resolves to true. | ||
440 | */ | ||
441 | mfn &= ~FOREIGN_FRAME_BIT; | ||
442 | if (mfn & IDENTITY_FRAME_BIT) { | ||
443 | mfn &= ~IDENTITY_FRAME_BIT; | ||
444 | flags |= _PAGE_IOMAP; | ||
445 | } | ||
430 | } | 446 | } |
431 | |||
432 | val = ((pteval_t)mfn << PAGE_SHIFT) | flags; | 447 | val = ((pteval_t)mfn << PAGE_SHIFT) | flags; |
433 | } | 448 | } |
434 | 449 | ||
@@ -532,6 +547,41 @@ pte_t xen_make_pte(pteval_t pte) | |||
532 | } | 547 | } |
533 | PV_CALLEE_SAVE_REGS_THUNK(xen_make_pte); | 548 | PV_CALLEE_SAVE_REGS_THUNK(xen_make_pte); |
534 | 549 | ||
550 | #ifdef CONFIG_XEN_DEBUG | ||
551 | pte_t xen_make_pte_debug(pteval_t pte) | ||
552 | { | ||
553 | phys_addr_t addr = (pte & PTE_PFN_MASK); | ||
554 | phys_addr_t other_addr; | ||
555 | bool io_page = false; | ||
556 | pte_t _pte; | ||
557 | |||
558 | if (pte & _PAGE_IOMAP) | ||
559 | io_page = true; | ||
560 | |||
561 | _pte = xen_make_pte(pte); | ||
562 | |||
563 | if (!addr) | ||
564 | return _pte; | ||
565 | |||
566 | if (io_page && | ||
567 | (xen_initial_domain() || addr >= ISA_END_ADDRESS)) { | ||
568 | other_addr = pfn_to_mfn(addr >> PAGE_SHIFT) << PAGE_SHIFT; | ||
569 | WARN(addr != other_addr, | ||
570 | "0x%lx is using VM_IO, but it is 0x%lx!\n", | ||
571 | (unsigned long)addr, (unsigned long)other_addr); | ||
572 | } else { | ||
573 | pteval_t iomap_set = (_pte.pte & PTE_FLAGS_MASK) & _PAGE_IOMAP; | ||
574 | other_addr = (_pte.pte & PTE_PFN_MASK); | ||
575 | WARN((addr == other_addr) && (!io_page) && (!iomap_set), | ||
576 | "0x%lx is missing VM_IO (and wasn't fixed)!\n", | ||
577 | (unsigned long)addr); | ||
578 | } | ||
579 | |||
580 | return _pte; | ||
581 | } | ||
582 | PV_CALLEE_SAVE_REGS_THUNK(xen_make_pte_debug); | ||
583 | #endif | ||
584 | |||
535 | pgd_t xen_make_pgd(pgdval_t pgd) | 585 | pgd_t xen_make_pgd(pgdval_t pgd) |
536 | { | 586 | { |
537 | pgd = pte_pfn_to_mfn(pgd); | 587 | pgd = pte_pfn_to_mfn(pgd); |
@@ -1441,7 +1491,7 @@ static __init pte_t mask_rw_pte(pte_t *ptep, pte_t pte) | |||
1441 | * early_ioremap fixmap slot, make sure it is RO. | 1491 | * early_ioremap fixmap slot, make sure it is RO. |
1442 | */ | 1492 | */ |
1443 | if (!is_early_ioremap_ptep(ptep) && | 1493 | if (!is_early_ioremap_ptep(ptep) && |
1444 | pfn >= e820_table_start && pfn < e820_table_end) | 1494 | pfn >= pgt_buf_start && pfn < pgt_buf_end) |
1445 | pte = pte_wrprotect(pte); | 1495 | pte = pte_wrprotect(pte); |
1446 | 1496 | ||
1447 | return pte; | 1497 | return pte; |
@@ -1940,6 +1990,9 @@ __init void xen_ident_map_ISA(void) | |||
1940 | 1990 | ||
1941 | static __init void xen_post_allocator_init(void) | 1991 | static __init void xen_post_allocator_init(void) |
1942 | { | 1992 | { |
1993 | #ifdef CONFIG_XEN_DEBUG | ||
1994 | pv_mmu_ops.make_pte = PV_CALLEE_SAVE(xen_make_pte_debug); | ||
1995 | #endif | ||
1943 | pv_mmu_ops.set_pte = xen_set_pte; | 1996 | pv_mmu_ops.set_pte = xen_set_pte; |
1944 | pv_mmu_ops.set_pmd = xen_set_pmd; | 1997 | pv_mmu_ops.set_pmd = xen_set_pmd; |
1945 | pv_mmu_ops.set_pud = xen_set_pud; | 1998 | pv_mmu_ops.set_pud = xen_set_pud; |
@@ -2072,7 +2125,7 @@ static void xen_zap_pfn_range(unsigned long vaddr, unsigned int order, | |||
2072 | in_frames[i] = virt_to_mfn(vaddr); | 2125 | in_frames[i] = virt_to_mfn(vaddr); |
2073 | 2126 | ||
2074 | MULTI_update_va_mapping(mcs.mc, vaddr, VOID_PTE, 0); | 2127 | MULTI_update_va_mapping(mcs.mc, vaddr, VOID_PTE, 0); |
2075 | set_phys_to_machine(virt_to_pfn(vaddr), INVALID_P2M_ENTRY); | 2128 | __set_phys_to_machine(virt_to_pfn(vaddr), INVALID_P2M_ENTRY); |
2076 | 2129 | ||
2077 | if (out_frames) | 2130 | if (out_frames) |
2078 | out_frames[i] = virt_to_pfn(vaddr); | 2131 | out_frames[i] = virt_to_pfn(vaddr); |
@@ -2351,6 +2404,18 @@ EXPORT_SYMBOL_GPL(xen_remap_domain_mfn_range); | |||
2351 | 2404 | ||
2352 | #ifdef CONFIG_XEN_DEBUG_FS | 2405 | #ifdef CONFIG_XEN_DEBUG_FS |
2353 | 2406 | ||
2407 | static int p2m_dump_open(struct inode *inode, struct file *filp) | ||
2408 | { | ||
2409 | return single_open(filp, p2m_dump_show, NULL); | ||
2410 | } | ||
2411 | |||
2412 | static const struct file_operations p2m_dump_fops = { | ||
2413 | .open = p2m_dump_open, | ||
2414 | .read = seq_read, | ||
2415 | .llseek = seq_lseek, | ||
2416 | .release = single_release, | ||
2417 | }; | ||
2418 | |||
2354 | static struct dentry *d_mmu_debug; | 2419 | static struct dentry *d_mmu_debug; |
2355 | 2420 | ||
2356 | static int __init xen_mmu_debugfs(void) | 2421 | static int __init xen_mmu_debugfs(void) |
@@ -2406,6 +2471,7 @@ static int __init xen_mmu_debugfs(void) | |||
2406 | debugfs_create_u32("prot_commit_batched", 0444, d_mmu_debug, | 2471 | debugfs_create_u32("prot_commit_batched", 0444, d_mmu_debug, |
2407 | &mmu_stats.prot_commit_batched); | 2472 | &mmu_stats.prot_commit_batched); |
2408 | 2473 | ||
2474 | debugfs_create_file("p2m", 0600, d_mmu_debug, NULL, &p2m_dump_fops); | ||
2409 | return 0; | 2475 | return 0; |
2410 | } | 2476 | } |
2411 | fs_initcall(xen_mmu_debugfs); | 2477 | fs_initcall(xen_mmu_debugfs); |