aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86')
-rw-r--r--arch/x86/include/asm/xen/page.h3
-rw-r--r--arch/x86/xen/mmu.c14
-rw-r--r--arch/x86/xen/p2m.c78
3 files changed, 95 insertions, 0 deletions
diff --git a/arch/x86/include/asm/xen/page.h b/arch/x86/include/asm/xen/page.h
index 65fa4f26aa34..78ebbeb88d9c 100644
--- a/arch/x86/include/asm/xen/page.h
+++ b/arch/x86/include/asm/xen/page.h
@@ -52,6 +52,9 @@ extern int m2p_remove_override(struct page *page);
52extern struct page *m2p_find_override(unsigned long mfn); 52extern struct page *m2p_find_override(unsigned long mfn);
53extern unsigned long m2p_find_override_pfn(unsigned long mfn, unsigned long pfn); 53extern unsigned long m2p_find_override_pfn(unsigned long mfn, unsigned long pfn);
54 54
55#ifdef CONFIG_XEN_DEBUG_FS
56extern int p2m_dump_show(struct seq_file *m, void *v);
57#endif
55static inline unsigned long pfn_to_mfn(unsigned long pfn) 58static inline unsigned long pfn_to_mfn(unsigned long pfn)
56{ 59{
57 unsigned long mfn; 60 unsigned long mfn;
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
2371static int p2m_dump_open(struct inode *inode, struct file *filp)
2372{
2373 return single_open(filp, p2m_dump_show, NULL);
2374}
2375
2376static 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
2370static struct dentry *d_mmu_debug; 2383static struct dentry *d_mmu_debug;
2371 2384
2372static int __init xen_mmu_debugfs(void) 2385static 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}
2427fs_initcall(xen_mmu_debugfs); 2441fs_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}
760EXPORT_SYMBOL_GPL(m2p_find_override_pfn); 761EXPORT_SYMBOL_GPL(m2p_find_override_pfn);
762
763#ifdef CONFIG_XEN_DEBUG_FS
764
765int 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