aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel/e820.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86/kernel/e820.c')
-rw-r--r--arch/x86/kernel/e820.c109
1 files changed, 109 insertions, 0 deletions
diff --git a/arch/x86/kernel/e820.c b/arch/x86/kernel/e820.c
index cd2b99e27d4..c140f731743 100644
--- a/arch/x86/kernel/e820.c
+++ b/arch/x86/kernel/e820.c
@@ -764,3 +764,112 @@ u64 __init early_reserve_e820(u64 startt, u64 sizet, u64 align)
764 return addr; 764 return addr;
765} 765}
766 766
767#ifdef CONFIG_X86_32
768# ifdef CONFIG_X86_PAE
769# define MAX_ARCH_PFN (1ULL<<(36-PAGE_SHIFT))
770# else
771# define MAX_ARCH_PFN (1ULL<<(32-PAGE_SHIFT))
772# endif
773#else /* CONFIG_X86_32 */
774# define MAX_ARCH_PFN MAXMEM<<PAGE_SHIFT
775#endif
776
777/*
778 * Last pfn which the user wants to use.
779 */
780unsigned long __initdata end_user_pfn = MAX_ARCH_PFN;
781
782/*
783 * Find the highest page frame number we have available
784 */
785unsigned long __init e820_end_of_ram(void)
786{
787 unsigned long last_pfn;
788 unsigned long max_arch_pfn = MAX_ARCH_PFN;
789
790 last_pfn = find_max_pfn_with_active_regions();
791
792 if (last_pfn > max_arch_pfn)
793 last_pfn = max_arch_pfn;
794 if (last_pfn > end_user_pfn)
795 last_pfn = end_user_pfn;
796
797 printk(KERN_INFO "last_pfn = %lu max_arch_pfn = %lu\n",
798 last_pfn, max_arch_pfn);
799 return last_pfn;
800}
801
802/*
803 * Finds an active region in the address range from start_pfn to last_pfn and
804 * returns its range in ei_startpfn and ei_endpfn for the e820 entry.
805 */
806int __init e820_find_active_region(const struct e820entry *ei,
807 unsigned long start_pfn,
808 unsigned long last_pfn,
809 unsigned long *ei_startpfn,
810 unsigned long *ei_endpfn)
811{
812 u64 align = PAGE_SIZE;
813
814 *ei_startpfn = round_up(ei->addr, align) >> PAGE_SHIFT;
815 *ei_endpfn = round_down(ei->addr + ei->size, align) >> PAGE_SHIFT;
816
817 /* Skip map entries smaller than a page */
818 if (*ei_startpfn >= *ei_endpfn)
819 return 0;
820
821 /* Skip if map is outside the node */
822 if (ei->type != E820_RAM || *ei_endpfn <= start_pfn ||
823 *ei_startpfn >= last_pfn)
824 return 0;
825
826 /* Check for overlaps */
827 if (*ei_startpfn < start_pfn)
828 *ei_startpfn = start_pfn;
829 if (*ei_endpfn > last_pfn)
830 *ei_endpfn = last_pfn;
831
832 /* Obey end_user_pfn to save on memmap */
833 if (*ei_startpfn >= end_user_pfn)
834 return 0;
835 if (*ei_endpfn > end_user_pfn)
836 *ei_endpfn = end_user_pfn;
837
838 return 1;
839}
840
841/* Walk the e820 map and register active regions within a node */
842void __init e820_register_active_regions(int nid, unsigned long start_pfn,
843 unsigned long last_pfn)
844{
845 unsigned long ei_startpfn;
846 unsigned long ei_endpfn;
847 int i;
848
849 for (i = 0; i < e820.nr_map; i++)
850 if (e820_find_active_region(&e820.map[i],
851 start_pfn, last_pfn,
852 &ei_startpfn, &ei_endpfn))
853 add_active_range(nid, ei_startpfn, ei_endpfn);
854}
855
856/*
857 * Find the hole size (in bytes) in the memory range.
858 * @start: starting address of the memory range to scan
859 * @end: ending address of the memory range to scan
860 */
861u64 __init e820_hole_size(u64 start, u64 end)
862{
863 unsigned long start_pfn = start >> PAGE_SHIFT;
864 unsigned long last_pfn = end >> PAGE_SHIFT;
865 unsigned long ei_startpfn, ei_endpfn, ram = 0;
866 int i;
867
868 for (i = 0; i < e820.nr_map; i++) {
869 if (e820_find_active_region(&e820.map[i],
870 start_pfn, last_pfn,
871 &ei_startpfn, &ei_endpfn))
872 ram += ei_endpfn - ei_startpfn;
873 }
874 return end - start - ((u64)ram << PAGE_SHIFT);
875}