diff options
Diffstat (limited to 'arch/x86/xen')
-rw-r--r-- | arch/x86/xen/mmu.c | 14 | ||||
-rw-r--r-- | arch/x86/xen/p2m.c | 78 |
2 files changed, 92 insertions, 0 deletions
diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c index 9c9e07615139..b13b6ca9052a 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> |
@@ -2367,6 +2368,18 @@ EXPORT_SYMBOL_GPL(xen_remap_domain_mfn_range); | |||
2367 | 2368 | ||
2368 | #ifdef CONFIG_XEN_DEBUG_FS | 2369 | #ifdef CONFIG_XEN_DEBUG_FS |
2369 | 2370 | ||
2371 | static int p2m_dump_open(struct inode *inode, struct file *filp) | ||
2372 | { | ||
2373 | return single_open(filp, p2m_dump_show, NULL); | ||
2374 | } | ||
2375 | |||
2376 | static const struct file_operations p2m_dump_fops = { | ||
2377 | .open = p2m_dump_open, | ||
2378 | .read = seq_read, | ||
2379 | .llseek = seq_lseek, | ||
2380 | .release = single_release, | ||
2381 | }; | ||
2382 | |||
2370 | static struct dentry *d_mmu_debug; | 2383 | static struct dentry *d_mmu_debug; |
2371 | 2384 | ||
2372 | static int __init xen_mmu_debugfs(void) | 2385 | static int __init xen_mmu_debugfs(void) |
@@ -2422,6 +2435,7 @@ static int __init xen_mmu_debugfs(void) | |||
2422 | debugfs_create_u32("prot_commit_batched", 0444, d_mmu_debug, | 2435 | debugfs_create_u32("prot_commit_batched", 0444, d_mmu_debug, |
2423 | &mmu_stats.prot_commit_batched); | 2436 | &mmu_stats.prot_commit_batched); |
2424 | 2437 | ||
2438 | debugfs_create_file("p2m", 0600, d_mmu_debug, NULL, &p2m_dump_fops); | ||
2425 | return 0; | 2439 | return 0; |
2426 | } | 2440 | } |
2427 | fs_initcall(xen_mmu_debugfs); | 2441 | fs_initcall(xen_mmu_debugfs); |
diff --git a/arch/x86/xen/p2m.c b/arch/x86/xen/p2m.c index 4631cf99e714..65f21f4b3962 100644 --- a/arch/x86/xen/p2m.c +++ b/arch/x86/xen/p2m.c | |||
@@ -153,6 +153,7 @@ | |||
153 | #include <linux/list.h> | 153 | #include <linux/list.h> |
154 | #include <linux/hash.h> | 154 | #include <linux/hash.h> |
155 | #include <linux/sched.h> | 155 | #include <linux/sched.h> |
156 | #include <linux/seq_file.h> | ||
156 | 157 | ||
157 | #include <asm/cache.h> | 158 | #include <asm/cache.h> |
158 | #include <asm/setup.h> | 159 | #include <asm/setup.h> |
@@ -758,3 +759,80 @@ unsigned long m2p_find_override_pfn(unsigned long mfn, unsigned long pfn) | |||
758 | return ret; | 759 | return ret; |
759 | } | 760 | } |
760 | EXPORT_SYMBOL_GPL(m2p_find_override_pfn); | 761 | EXPORT_SYMBOL_GPL(m2p_find_override_pfn); |
762 | |||
763 | #ifdef CONFIG_XEN_DEBUG_FS | ||
764 | |||
765 | int p2m_dump_show(struct seq_file *m, void *v) | ||
766 | { | ||
767 | static const char * const level_name[] = { "top", "middle", | ||
768 | "entry", "abnormal" }; | ||
769 | static const char * const type_name[] = { "identity", "missing", | ||
770 | "pfn", "abnormal"}; | ||
771 | #define TYPE_IDENTITY 0 | ||
772 | #define TYPE_MISSING 1 | ||
773 | #define TYPE_PFN 2 | ||
774 | #define TYPE_UNKNOWN 3 | ||
775 | unsigned long pfn, prev_pfn_type = 0, prev_pfn_level = 0; | ||
776 | unsigned int uninitialized_var(prev_level); | ||
777 | unsigned int uninitialized_var(prev_type); | ||
778 | |||
779 | if (!p2m_top) | ||
780 | return 0; | ||
781 | |||
782 | for (pfn = 0; pfn < MAX_DOMAIN_PAGES; pfn++) { | ||
783 | unsigned topidx = p2m_top_index(pfn); | ||
784 | unsigned mididx = p2m_mid_index(pfn); | ||
785 | unsigned idx = p2m_index(pfn); | ||
786 | unsigned lvl, type; | ||
787 | |||
788 | lvl = 4; | ||
789 | type = TYPE_UNKNOWN; | ||
790 | if (p2m_top[topidx] == p2m_mid_missing) { | ||
791 | lvl = 0; type = TYPE_MISSING; | ||
792 | } else if (p2m_top[topidx] == NULL) { | ||
793 | lvl = 0; type = TYPE_UNKNOWN; | ||
794 | } else if (p2m_top[topidx][mididx] == NULL) { | ||
795 | lvl = 1; type = TYPE_UNKNOWN; | ||
796 | } else if (p2m_top[topidx][mididx] == p2m_identity) { | ||
797 | lvl = 1; type = TYPE_IDENTITY; | ||
798 | } else if (p2m_top[topidx][mididx] == p2m_missing) { | ||
799 | lvl = 1; type = TYPE_MISSING; | ||
800 | } else if (p2m_top[topidx][mididx][idx] == 0) { | ||
801 | lvl = 2; type = TYPE_UNKNOWN; | ||
802 | } else if (p2m_top[topidx][mididx][idx] == IDENTITY_FRAME(pfn)) { | ||
803 | lvl = 2; type = TYPE_IDENTITY; | ||
804 | } else if (p2m_top[topidx][mididx][idx] == INVALID_P2M_ENTRY) { | ||
805 | lvl = 2; type = TYPE_MISSING; | ||
806 | } else if (p2m_top[topidx][mididx][idx] == pfn) { | ||
807 | lvl = 2; type = TYPE_PFN; | ||
808 | } else if (p2m_top[topidx][mididx][idx] != pfn) { | ||
809 | lvl = 2; type = TYPE_PFN; | ||
810 | } | ||
811 | if (pfn == 0) { | ||
812 | prev_level = lvl; | ||
813 | prev_type = type; | ||
814 | } | ||
815 | if (pfn == MAX_DOMAIN_PAGES-1) { | ||
816 | lvl = 3; | ||
817 | type = TYPE_UNKNOWN; | ||
818 | } | ||
819 | if (prev_type != type) { | ||
820 | seq_printf(m, " [0x%lx->0x%lx] %s\n", | ||
821 | prev_pfn_type, pfn, type_name[prev_type]); | ||
822 | prev_pfn_type = pfn; | ||
823 | prev_type = type; | ||
824 | } | ||
825 | if (prev_level != lvl) { | ||
826 | seq_printf(m, " [0x%lx->0x%lx] level %s\n", | ||
827 | prev_pfn_level, pfn, level_name[prev_level]); | ||
828 | prev_pfn_level = pfn; | ||
829 | prev_level = lvl; | ||
830 | } | ||
831 | } | ||
832 | return 0; | ||
833 | #undef TYPE_IDENTITY | ||
834 | #undef TYPE_MISSING | ||
835 | #undef TYPE_PFN | ||
836 | #undef TYPE_UNKNOWN | ||
837 | } | ||
838 | #endif | ||