diff options
-rw-r--r-- | arch/x86/kernel/e820.c | 109 | ||||
-rw-r--r-- | arch/x86/kernel/e820_64.c | 97 | ||||
-rw-r--r-- | include/asm-x86/e820.h | 11 | ||||
-rw-r--r-- | include/asm-x86/e820_64.h | 5 |
4 files changed, 120 insertions, 102 deletions
diff --git a/arch/x86/kernel/e820.c b/arch/x86/kernel/e820.c index cd2b99e27d43..c140f731743b 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 | */ | ||
780 | unsigned long __initdata end_user_pfn = MAX_ARCH_PFN; | ||
781 | |||
782 | /* | ||
783 | * Find the highest page frame number we have available | ||
784 | */ | ||
785 | unsigned 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 | */ | ||
806 | int __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 */ | ||
842 | void __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 | */ | ||
861 | u64 __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 | } | ||
diff --git a/arch/x86/kernel/e820_64.c b/arch/x86/kernel/e820_64.c index a11bec20f65d..0afee2ca0bf8 100644 --- a/arch/x86/kernel/e820_64.c +++ b/arch/x86/kernel/e820_64.c | |||
@@ -42,29 +42,6 @@ unsigned long end_pfn; | |||
42 | unsigned long max_pfn_mapped; | 42 | unsigned long max_pfn_mapped; |
43 | 43 | ||
44 | /* | 44 | /* |
45 | * Last pfn which the user wants to use. | ||
46 | */ | ||
47 | static unsigned long __initdata end_user_pfn = MAXMEM>>PAGE_SHIFT; | ||
48 | |||
49 | /* | ||
50 | * Find the highest page frame number we have available | ||
51 | */ | ||
52 | unsigned long __init e820_end_of_ram(void) | ||
53 | { | ||
54 | unsigned long last_pfn; | ||
55 | |||
56 | last_pfn = find_max_pfn_with_active_regions(); | ||
57 | |||
58 | if (last_pfn > MAXMEM>>PAGE_SHIFT) | ||
59 | last_pfn = MAXMEM>>PAGE_SHIFT; | ||
60 | if (last_pfn > end_user_pfn) | ||
61 | last_pfn = end_user_pfn; | ||
62 | |||
63 | printk(KERN_INFO "last_pfn = %lu\n", last_pfn); | ||
64 | return last_pfn; | ||
65 | } | ||
66 | |||
67 | /* | ||
68 | * Mark e820 reserved areas as busy for the resource manager. | 45 | * Mark e820 reserved areas as busy for the resource manager. |
69 | */ | 46 | */ |
70 | void __init e820_reserve_resources(void) | 47 | void __init e820_reserve_resources(void) |
@@ -88,80 +65,6 @@ void __init e820_reserve_resources(void) | |||
88 | } | 65 | } |
89 | } | 66 | } |
90 | 67 | ||
91 | /* | ||
92 | * Finds an active region in the address range from start_pfn to last_pfn and | ||
93 | * returns its range in ei_startpfn and ei_endpfn for the e820 entry. | ||
94 | */ | ||
95 | static int __init e820_find_active_region(const struct e820entry *ei, | ||
96 | unsigned long start_pfn, | ||
97 | unsigned long last_pfn, | ||
98 | unsigned long *ei_startpfn, | ||
99 | unsigned long *ei_endpfn) | ||
100 | { | ||
101 | *ei_startpfn = round_up(ei->addr, PAGE_SIZE) >> PAGE_SHIFT; | ||
102 | *ei_endpfn = round_down(ei->addr + ei->size, PAGE_SIZE) >> PAGE_SHIFT; | ||
103 | |||
104 | /* Skip map entries smaller than a page */ | ||
105 | if (*ei_startpfn >= *ei_endpfn) | ||
106 | return 0; | ||
107 | |||
108 | /* Skip if map is outside the node */ | ||
109 | if (ei->type != E820_RAM || *ei_endpfn <= start_pfn || | ||
110 | *ei_startpfn >= last_pfn) | ||
111 | return 0; | ||
112 | |||
113 | /* Check for overlaps */ | ||
114 | if (*ei_startpfn < start_pfn) | ||
115 | *ei_startpfn = start_pfn; | ||
116 | if (*ei_endpfn > last_pfn) | ||
117 | *ei_endpfn = last_pfn; | ||
118 | |||
119 | /* Obey end_user_pfn to save on memmap */ | ||
120 | if (*ei_startpfn >= end_user_pfn) | ||
121 | return 0; | ||
122 | if (*ei_endpfn > end_user_pfn) | ||
123 | *ei_endpfn = end_user_pfn; | ||
124 | |||
125 | return 1; | ||
126 | } | ||
127 | |||
128 | /* Walk the e820 map and register active regions within a node */ | ||
129 | void __init | ||
130 | e820_register_active_regions(int nid, unsigned long start_pfn, | ||
131 | unsigned long last_pfn) | ||
132 | { | ||
133 | unsigned long ei_startpfn; | ||
134 | unsigned long ei_endpfn; | ||
135 | int i; | ||
136 | |||
137 | for (i = 0; i < e820.nr_map; i++) | ||
138 | if (e820_find_active_region(&e820.map[i], | ||
139 | start_pfn, last_pfn, | ||
140 | &ei_startpfn, &ei_endpfn)) | ||
141 | add_active_range(nid, ei_startpfn, ei_endpfn); | ||
142 | } | ||
143 | |||
144 | /* | ||
145 | * Find the hole size (in bytes) in the memory range. | ||
146 | * @start: starting address of the memory range to scan | ||
147 | * @end: ending address of the memory range to scan | ||
148 | */ | ||
149 | unsigned long __init e820_hole_size(unsigned long start, unsigned long end) | ||
150 | { | ||
151 | unsigned long start_pfn = start >> PAGE_SHIFT; | ||
152 | unsigned long last_pfn = end >> PAGE_SHIFT; | ||
153 | unsigned long ei_startpfn, ei_endpfn, ram = 0; | ||
154 | int i; | ||
155 | |||
156 | for (i = 0; i < e820.nr_map; i++) { | ||
157 | if (e820_find_active_region(&e820.map[i], | ||
158 | start_pfn, last_pfn, | ||
159 | &ei_startpfn, &ei_endpfn)) | ||
160 | ram += ei_endpfn - ei_startpfn; | ||
161 | } | ||
162 | return end - start - (ram << PAGE_SHIFT); | ||
163 | } | ||
164 | |||
165 | static void early_panic(char *msg) | 68 | static void early_panic(char *msg) |
166 | { | 69 | { |
167 | early_printk(msg); | 70 | early_printk(msg); |
diff --git a/include/asm-x86/e820.h b/include/asm-x86/e820.h index ee8fe4c5da41..44ed9c0a4dfd 100644 --- a/include/asm-x86/e820.h +++ b/include/asm-x86/e820.h | |||
@@ -79,6 +79,8 @@ static inline void e820_mark_nosave_regions(unsigned long limit_pfn) | |||
79 | } | 79 | } |
80 | #endif | 80 | #endif |
81 | 81 | ||
82 | extern unsigned long end_user_pfn; | ||
83 | |||
82 | extern u64 find_e820_area(u64 start, u64 end, u64 size, u64 align); | 84 | extern u64 find_e820_area(u64 start, u64 end, u64 size, u64 align); |
83 | extern u64 find_e820_area_size(u64 start, u64 *sizep, u64 align); | 85 | extern u64 find_e820_area_size(u64 start, u64 *sizep, u64 align); |
84 | extern void reserve_early(u64 start, u64 end, char *name); | 86 | extern void reserve_early(u64 start, u64 end, char *name); |
@@ -86,6 +88,15 @@ extern void free_early(u64 start, u64 end); | |||
86 | extern void early_res_to_bootmem(u64 start, u64 end); | 88 | extern void early_res_to_bootmem(u64 start, u64 end); |
87 | extern u64 early_reserve_e820(u64 startt, u64 sizet, u64 align); | 89 | extern u64 early_reserve_e820(u64 startt, u64 sizet, u64 align); |
88 | 90 | ||
91 | extern unsigned long e820_end_of_ram(void); | ||
92 | extern int e820_find_active_region(const struct e820entry *ei, | ||
93 | unsigned long start_pfn, | ||
94 | unsigned long last_pfn, | ||
95 | unsigned long *ei_startpfn, | ||
96 | unsigned long *ei_endpfn); | ||
97 | extern void e820_register_active_regions(int nid, unsigned long start_pfn, | ||
98 | unsigned long end_pfn); | ||
99 | extern u64 e820_hole_size(u64 start, u64 end); | ||
89 | #endif /* __ASSEMBLY__ */ | 100 | #endif /* __ASSEMBLY__ */ |
90 | 101 | ||
91 | #define ISA_START_ADDRESS 0xa0000 | 102 | #define ISA_START_ADDRESS 0xa0000 |
diff --git a/include/asm-x86/e820_64.h b/include/asm-x86/e820_64.h index 917963ccab69..368585daaa42 100644 --- a/include/asm-x86/e820_64.h +++ b/include/asm-x86/e820_64.h | |||
@@ -16,16 +16,11 @@ | |||
16 | #ifndef __ASSEMBLY__ | 16 | #ifndef __ASSEMBLY__ |
17 | extern void setup_memory_region(void); | 17 | extern void setup_memory_region(void); |
18 | extern void contig_e820_setup(void); | 18 | extern void contig_e820_setup(void); |
19 | extern unsigned long e820_end_of_ram(void); | ||
20 | extern void e820_reserve_resources(void); | 19 | extern void e820_reserve_resources(void); |
21 | extern int e820_any_non_reserved(unsigned long start, unsigned long end); | 20 | extern int e820_any_non_reserved(unsigned long start, unsigned long end); |
22 | extern int is_memory_any_valid(unsigned long start, unsigned long end); | 21 | extern int is_memory_any_valid(unsigned long start, unsigned long end); |
23 | extern int e820_all_non_reserved(unsigned long start, unsigned long end); | 22 | extern int e820_all_non_reserved(unsigned long start, unsigned long end); |
24 | extern int is_memory_all_valid(unsigned long start, unsigned long end); | 23 | extern int is_memory_all_valid(unsigned long start, unsigned long end); |
25 | extern unsigned long e820_hole_size(unsigned long start, unsigned long end); | ||
26 | |||
27 | extern void e820_register_active_regions(int nid, unsigned long start_pfn, | ||
28 | unsigned long end_pfn); | ||
29 | 24 | ||
30 | extern void finish_e820_parsing(void); | 25 | extern void finish_e820_parsing(void); |
31 | 26 | ||