aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/x86/mm/ioremap.c77
-rw-r--r--include/asm-x86/fixmap_32.h4
-rw-r--r--include/asm-x86/fixmap_64.h4
3 files changed, 61 insertions, 24 deletions
diff --git a/arch/x86/mm/ioremap.c b/arch/x86/mm/ioremap.c
index 8876220d906b..e4c43ec71b29 100644
--- a/arch/x86/mm/ioremap.c
+++ b/arch/x86/mm/ioremap.c
@@ -616,16 +616,22 @@ static inline void __init early_clear_fixmap(enum fixed_addresses idx)
616 __early_set_fixmap(idx, 0, __pgprot(0)); 616 __early_set_fixmap(idx, 0, __pgprot(0));
617} 617}
618 618
619 619static void *prev_map[FIX_BTMAPS_SLOTS] __initdata;
620static int __initdata early_ioremap_nested; 620static unsigned long prev_size[FIX_BTMAPS_SLOTS] __initdata;
621
622static int __init check_early_ioremap_leak(void) 621static int __init check_early_ioremap_leak(void)
623{ 622{
624 if (!early_ioremap_nested) 623 int count = 0;
624 int i;
625
626 for (i = 0; i < FIX_BTMAPS_SLOTS; i++)
627 if (prev_map[i])
628 count++;
629
630 if (!count)
625 return 0; 631 return 0;
626 WARN(1, KERN_WARNING 632 WARN(1, KERN_WARNING
627 "Debug warning: early ioremap leak of %d areas detected.\n", 633 "Debug warning: early ioremap leak of %d areas detected.\n",
628 early_ioremap_nested); 634 count);
629 printk(KERN_WARNING 635 printk(KERN_WARNING
630 "please boot with early_ioremap_debug and report the dmesg.\n"); 636 "please boot with early_ioremap_debug and report the dmesg.\n");
631 637
@@ -636,15 +642,30 @@ late_initcall(check_early_ioremap_leak);
636static void __init *__early_ioremap(unsigned long phys_addr, unsigned long size, pgprot_t prot) 642static void __init *__early_ioremap(unsigned long phys_addr, unsigned long size, pgprot_t prot)
637{ 643{
638 unsigned long offset, last_addr; 644 unsigned long offset, last_addr;
639 unsigned int nrpages, nesting; 645 unsigned int nrpages;
640 enum fixed_addresses idx0, idx; 646 enum fixed_addresses idx0, idx;
647 int i, slot;
641 648
642 WARN_ON(system_state != SYSTEM_BOOTING); 649 WARN_ON(system_state != SYSTEM_BOOTING);
643 650
644 nesting = early_ioremap_nested; 651 slot = -1;
652 for (i = 0; i < FIX_BTMAPS_SLOTS; i++) {
653 if (!prev_map[i]) {
654 slot = i;
655 break;
656 }
657 }
658
659 if (slot < 0) {
660 printk(KERN_INFO "early_iomap(%08lx, %08lx) not found slot\n",
661 phys_addr, size);
662 WARN_ON(1);
663 return NULL;
664 }
665
645 if (early_ioremap_debug) { 666 if (early_ioremap_debug) {
646 printk(KERN_INFO "early_ioremap(%08lx, %08lx) [%d] => ", 667 printk(KERN_INFO "early_ioremap(%08lx, %08lx) [%d] => ",
647 phys_addr, size, nesting); 668 phys_addr, size, slot);
648 dump_stack(); 669 dump_stack();
649 } 670 }
650 671
@@ -655,11 +676,7 @@ static void __init *__early_ioremap(unsigned long phys_addr, unsigned long size,
655 return NULL; 676 return NULL;
656 } 677 }
657 678
658 if (nesting >= FIX_BTMAPS_NESTING) { 679 prev_size[slot] = size;
659 WARN_ON(1);
660 return NULL;
661 }
662 early_ioremap_nested++;
663 /* 680 /*
664 * Mappings have to be page-aligned 681 * Mappings have to be page-aligned
665 */ 682 */
@@ -679,7 +696,7 @@ static void __init *__early_ioremap(unsigned long phys_addr, unsigned long size,
679 /* 696 /*
680 * Ok, go for it.. 697 * Ok, go for it..
681 */ 698 */
682 idx0 = FIX_BTMAP_BEGIN - NR_FIX_BTMAPS*nesting; 699 idx0 = FIX_BTMAP_BEGIN - NR_FIX_BTMAPS*slot;
683 idx = idx0; 700 idx = idx0;
684 while (nrpages > 0) { 701 while (nrpages > 0) {
685 early_set_fixmap(idx, phys_addr, prot); 702 early_set_fixmap(idx, phys_addr, prot);
@@ -690,7 +707,8 @@ static void __init *__early_ioremap(unsigned long phys_addr, unsigned long size,
690 if (early_ioremap_debug) 707 if (early_ioremap_debug)
691 printk(KERN_CONT "%08lx + %08lx\n", offset, fix_to_virt(idx0)); 708 printk(KERN_CONT "%08lx + %08lx\n", offset, fix_to_virt(idx0));
692 709
693 return (void *) (offset + fix_to_virt(idx0)); 710 prev_map[slot] = (void *) (offset + fix_to_virt(idx0));
711 return prev_map[slot];
694} 712}
695 713
696/* Remap an IO device */ 714/* Remap an IO device */
@@ -711,15 +729,33 @@ void __init early_iounmap(void *addr, unsigned long size)
711 unsigned long offset; 729 unsigned long offset;
712 unsigned int nrpages; 730 unsigned int nrpages;
713 enum fixed_addresses idx; 731 enum fixed_addresses idx;
714 int nesting; 732 int i, slot;
733
734 slot = -1;
735 for (i = 0; i < FIX_BTMAPS_SLOTS; i++) {
736 if (prev_map[i] == addr) {
737 slot = i;
738 break;
739 }
740 }
715 741
716 nesting = --early_ioremap_nested; 742 if (slot < 0) {
717 if (WARN_ON(nesting < 0)) 743 printk(KERN_INFO "early_iounmap(%p, %08lx) not found slot\n",
744 addr, size);
745 WARN_ON(1);
746 return;
747 }
748
749 if (prev_size[slot] != size) {
750 printk(KERN_INFO "early_iounmap(%p, %08lx) [%d] size not consistent %08lx\n",
751 addr, size, slot, prev_size[slot]);
752 WARN_ON(1);
718 return; 753 return;
754 }
719 755
720 if (early_ioremap_debug) { 756 if (early_ioremap_debug) {
721 printk(KERN_INFO "early_iounmap(%p, %08lx) [%d]\n", addr, 757 printk(KERN_INFO "early_iounmap(%p, %08lx) [%d]\n", addr,
722 size, nesting); 758 size, slot);
723 dump_stack(); 759 dump_stack();
724 } 760 }
725 761
@@ -731,12 +767,13 @@ void __init early_iounmap(void *addr, unsigned long size)
731 offset = virt_addr & ~PAGE_MASK; 767 offset = virt_addr & ~PAGE_MASK;
732 nrpages = PAGE_ALIGN(offset + size - 1) >> PAGE_SHIFT; 768 nrpages = PAGE_ALIGN(offset + size - 1) >> PAGE_SHIFT;
733 769
734 idx = FIX_BTMAP_BEGIN - NR_FIX_BTMAPS*nesting; 770 idx = FIX_BTMAP_BEGIN - NR_FIX_BTMAPS*slot;
735 while (nrpages > 0) { 771 while (nrpages > 0) {
736 early_clear_fixmap(idx); 772 early_clear_fixmap(idx);
737 --idx; 773 --idx;
738 --nrpages; 774 --nrpages;
739 } 775 }
776 prev_map[slot] = 0;
740} 777}
741 778
742void __this_fixmap_does_not_exist(void) 779void __this_fixmap_does_not_exist(void)
diff --git a/include/asm-x86/fixmap_32.h b/include/asm-x86/fixmap_32.h
index 784e3e759866..8844002da0e0 100644
--- a/include/asm-x86/fixmap_32.h
+++ b/include/asm-x86/fixmap_32.h
@@ -94,10 +94,10 @@ enum fixed_addresses {
94 * can have a single pgd entry and a single pte table: 94 * can have a single pgd entry and a single pte table:
95 */ 95 */
96#define NR_FIX_BTMAPS 64 96#define NR_FIX_BTMAPS 64
97#define FIX_BTMAPS_NESTING 4 97#define FIX_BTMAPS_SLOTS 4
98 FIX_BTMAP_END = __end_of_permanent_fixed_addresses + 256 - 98 FIX_BTMAP_END = __end_of_permanent_fixed_addresses + 256 -
99 (__end_of_permanent_fixed_addresses & 255), 99 (__end_of_permanent_fixed_addresses & 255),
100 FIX_BTMAP_BEGIN = FIX_BTMAP_END + NR_FIX_BTMAPS*FIX_BTMAPS_NESTING - 1, 100 FIX_BTMAP_BEGIN = FIX_BTMAP_END + NR_FIX_BTMAPS*FIX_BTMAPS_SLOTS - 1,
101 FIX_WP_TEST, 101 FIX_WP_TEST,
102#ifdef CONFIG_ACPI 102#ifdef CONFIG_ACPI
103 FIX_ACPI_BEGIN, 103 FIX_ACPI_BEGIN,
diff --git a/include/asm-x86/fixmap_64.h b/include/asm-x86/fixmap_64.h
index 33df64fd0e18..dab4751d1307 100644
--- a/include/asm-x86/fixmap_64.h
+++ b/include/asm-x86/fixmap_64.h
@@ -65,10 +65,10 @@ enum fixed_addresses {
65 * can have a single pgd entry and a single pte table: 65 * can have a single pgd entry and a single pte table:
66 */ 66 */
67#define NR_FIX_BTMAPS 64 67#define NR_FIX_BTMAPS 64
68#define FIX_BTMAPS_NESTING 4 68#define FIX_BTMAPS_SLOTS 4
69 FIX_BTMAP_END = __end_of_permanent_fixed_addresses + 256 - 69 FIX_BTMAP_END = __end_of_permanent_fixed_addresses + 256 -
70 (__end_of_permanent_fixed_addresses & 255), 70 (__end_of_permanent_fixed_addresses & 255),
71 FIX_BTMAP_BEGIN = FIX_BTMAP_END + NR_FIX_BTMAPS*FIX_BTMAPS_NESTING - 1, 71 FIX_BTMAP_BEGIN = FIX_BTMAP_END + NR_FIX_BTMAPS*FIX_BTMAPS_SLOTS - 1,
72 __end_of_fixed_addresses 72 __end_of_fixed_addresses
73}; 73};
74 74