diff options
Diffstat (limited to 'arch/x86')
-rw-r--r-- | arch/x86/mm/pat.c | 88 |
1 files changed, 88 insertions, 0 deletions
diff --git a/arch/x86/mm/pat.c b/arch/x86/mm/pat.c index d4585077977a..0917a540a55e 100644 --- a/arch/x86/mm/pat.c +++ b/arch/x86/mm/pat.c | |||
@@ -12,6 +12,8 @@ | |||
12 | #include <linux/gfp.h> | 12 | #include <linux/gfp.h> |
13 | #include <linux/fs.h> | 13 | #include <linux/fs.h> |
14 | #include <linux/bootmem.h> | 14 | #include <linux/bootmem.h> |
15 | #include <linux/debugfs.h> | ||
16 | #include <linux/seq_file.h> | ||
15 | 17 | ||
16 | #include <asm/msr.h> | 18 | #include <asm/msr.h> |
17 | #include <asm/tlbflush.h> | 19 | #include <asm/tlbflush.h> |
@@ -489,3 +491,89 @@ void unmap_devmem(unsigned long pfn, unsigned long size, pgprot_t vma_prot) | |||
489 | 491 | ||
490 | free_memtype(addr, addr + size); | 492 | free_memtype(addr, addr + size); |
491 | } | 493 | } |
494 | |||
495 | #if defined(CONFIG_DEBUG_FS) | ||
496 | |||
497 | /* get Nth element of the linked list */ | ||
498 | static struct memtype *memtype_get_idx(loff_t pos) | ||
499 | { | ||
500 | struct memtype *list_node, *print_entry; | ||
501 | int i = 1; | ||
502 | |||
503 | print_entry = kmalloc(sizeof(struct memtype), GFP_KERNEL); | ||
504 | if (!print_entry) | ||
505 | return NULL; | ||
506 | |||
507 | spin_lock(&memtype_lock); | ||
508 | list_for_each_entry(list_node, &memtype_list, nd) { | ||
509 | if (pos == i) { | ||
510 | *print_entry = *list_node; | ||
511 | spin_unlock(&memtype_lock); | ||
512 | return print_entry; | ||
513 | } | ||
514 | ++i; | ||
515 | } | ||
516 | spin_unlock(&memtype_lock); | ||
517 | kfree(print_entry); | ||
518 | return NULL; | ||
519 | } | ||
520 | |||
521 | static void *memtype_seq_start(struct seq_file *seq, loff_t *pos) | ||
522 | { | ||
523 | if (*pos == 0) { | ||
524 | ++*pos; | ||
525 | seq_printf(seq, "PAT memtype list:\n"); | ||
526 | } | ||
527 | |||
528 | return memtype_get_idx(*pos); | ||
529 | } | ||
530 | |||
531 | static void *memtype_seq_next(struct seq_file *seq, void *v, loff_t *pos) | ||
532 | { | ||
533 | ++*pos; | ||
534 | return memtype_get_idx(*pos); | ||
535 | } | ||
536 | |||
537 | static void memtype_seq_stop(struct seq_file *seq, void *v) | ||
538 | { | ||
539 | } | ||
540 | |||
541 | static int memtype_seq_show(struct seq_file *seq, void *v) | ||
542 | { | ||
543 | struct memtype *print_entry = (struct memtype *)v; | ||
544 | |||
545 | seq_printf(seq, "%s @ 0x%Lx-0x%Lx\n", cattr_name(print_entry->type), | ||
546 | print_entry->start, print_entry->end); | ||
547 | kfree(print_entry); | ||
548 | return 0; | ||
549 | } | ||
550 | |||
551 | static struct seq_operations memtype_seq_ops = { | ||
552 | .start = memtype_seq_start, | ||
553 | .next = memtype_seq_next, | ||
554 | .stop = memtype_seq_stop, | ||
555 | .show = memtype_seq_show, | ||
556 | }; | ||
557 | |||
558 | static int memtype_seq_open(struct inode *inode, struct file *file) | ||
559 | { | ||
560 | return seq_open(file, &memtype_seq_ops); | ||
561 | } | ||
562 | |||
563 | static const struct file_operations memtype_fops = { | ||
564 | .open = memtype_seq_open, | ||
565 | .read = seq_read, | ||
566 | .llseek = seq_lseek, | ||
567 | .release = seq_release, | ||
568 | }; | ||
569 | |||
570 | static int __init pat_memtype_list_init(void) | ||
571 | { | ||
572 | debugfs_create_file("pat_memtype_list", S_IRUSR, arch_debugfs_dir, | ||
573 | NULL, &memtype_fops); | ||
574 | return 0; | ||
575 | } | ||
576 | |||
577 | late_initcall(pat_memtype_list_init); | ||
578 | |||
579 | #endif /* CONFIG_DEBUG_FS */ | ||