diff options
-rw-r--r-- | arch/x86/xen/setup.c | 52 |
1 files changed, 52 insertions, 0 deletions
diff --git a/arch/x86/xen/setup.c b/arch/x86/xen/setup.c index 7201800e55a4..54d93791ddb9 100644 --- a/arch/x86/xen/setup.c +++ b/arch/x86/xen/setup.c | |||
@@ -143,12 +143,55 @@ static unsigned long __init xen_return_unused_memory(unsigned long max_pfn, | |||
143 | return released; | 143 | return released; |
144 | } | 144 | } |
145 | 145 | ||
146 | static unsigned long __init xen_set_identity(const struct e820entry *list, | ||
147 | ssize_t map_size) | ||
148 | { | ||
149 | phys_addr_t last = xen_initial_domain() ? 0 : ISA_END_ADDRESS; | ||
150 | phys_addr_t start_pci = last; | ||
151 | const struct e820entry *entry; | ||
152 | unsigned long identity = 0; | ||
153 | int i; | ||
154 | |||
155 | for (i = 0, entry = list; i < map_size; i++, entry++) { | ||
156 | phys_addr_t start = entry->addr; | ||
157 | phys_addr_t end = start + entry->size; | ||
158 | |||
159 | if (start < last) | ||
160 | start = last; | ||
161 | |||
162 | if (end <= start) | ||
163 | continue; | ||
164 | |||
165 | /* Skip over the 1MB region. */ | ||
166 | if (last > end) | ||
167 | continue; | ||
168 | |||
169 | if (entry->type == E820_RAM) { | ||
170 | if (start > start_pci) | ||
171 | identity += set_phys_range_identity( | ||
172 | PFN_UP(start_pci), PFN_DOWN(start)); | ||
173 | |||
174 | /* Without saving 'last' we would gooble RAM too | ||
175 | * at the end of the loop. */ | ||
176 | last = end; | ||
177 | start_pci = end; | ||
178 | continue; | ||
179 | } | ||
180 | start_pci = min(start, start_pci); | ||
181 | last = end; | ||
182 | } | ||
183 | if (last > start_pci) | ||
184 | identity += set_phys_range_identity( | ||
185 | PFN_UP(start_pci), PFN_DOWN(last)); | ||
186 | return identity; | ||
187 | } | ||
146 | /** | 188 | /** |
147 | * machine_specific_memory_setup - Hook for machine specific memory setup. | 189 | * machine_specific_memory_setup - Hook for machine specific memory setup. |
148 | **/ | 190 | **/ |
149 | char * __init xen_memory_setup(void) | 191 | char * __init xen_memory_setup(void) |
150 | { | 192 | { |
151 | static struct e820entry map[E820MAX] __initdata; | 193 | static struct e820entry map[E820MAX] __initdata; |
194 | static struct e820entry map_raw[E820MAX] __initdata; | ||
152 | 195 | ||
153 | unsigned long max_pfn = xen_start_info->nr_pages; | 196 | unsigned long max_pfn = xen_start_info->nr_pages; |
154 | unsigned long long mem_end; | 197 | unsigned long long mem_end; |
@@ -156,6 +199,7 @@ char * __init xen_memory_setup(void) | |||
156 | struct xen_memory_map memmap; | 199 | struct xen_memory_map memmap; |
157 | unsigned long extra_pages = 0; | 200 | unsigned long extra_pages = 0; |
158 | unsigned long extra_limit; | 201 | unsigned long extra_limit; |
202 | unsigned long identity_pages = 0; | ||
159 | int i; | 203 | int i; |
160 | int op; | 204 | int op; |
161 | 205 | ||
@@ -181,6 +225,7 @@ char * __init xen_memory_setup(void) | |||
181 | } | 225 | } |
182 | BUG_ON(rc); | 226 | BUG_ON(rc); |
183 | 227 | ||
228 | memcpy(map_raw, map, sizeof(map)); | ||
184 | e820.nr_map = 0; | 229 | e820.nr_map = 0; |
185 | xen_extra_mem_start = mem_end; | 230 | xen_extra_mem_start = mem_end; |
186 | for (i = 0; i < memmap.nr_entries; i++) { | 231 | for (i = 0; i < memmap.nr_entries; i++) { |
@@ -251,6 +296,13 @@ char * __init xen_memory_setup(void) | |||
251 | 296 | ||
252 | xen_add_extra_mem(extra_pages); | 297 | xen_add_extra_mem(extra_pages); |
253 | 298 | ||
299 | /* | ||
300 | * Set P2M for all non-RAM pages and E820 gaps to be identity | ||
301 | * type PFNs. We supply it with the non-sanitized version | ||
302 | * of the E820. | ||
303 | */ | ||
304 | identity_pages = xen_set_identity(map_raw, memmap.nr_entries); | ||
305 | printk(KERN_INFO "Set %ld page(s) to 1-1 mapping.\n", identity_pages); | ||
254 | return "Xen"; | 306 | return "Xen"; |
255 | } | 307 | } |
256 | 308 | ||