diff options
Diffstat (limited to 'arch/x86/xen/setup.c')
| -rw-r--r-- | arch/x86/xen/setup.c | 68 |
1 files changed, 67 insertions, 1 deletions
diff --git a/arch/x86/xen/setup.c b/arch/x86/xen/setup.c index a8a66a50d44..fa0269a9937 100644 --- a/arch/x86/xen/setup.c +++ b/arch/x86/xen/setup.c | |||
| @@ -52,6 +52,8 @@ phys_addr_t xen_extra_mem_start, xen_extra_mem_size; | |||
| 52 | 52 | ||
| 53 | static __init void xen_add_extra_mem(unsigned long pages) | 53 | static __init void xen_add_extra_mem(unsigned long pages) |
| 54 | { | 54 | { |
| 55 | unsigned long pfn; | ||
| 56 | |||
| 55 | u64 size = (u64)pages * PAGE_SIZE; | 57 | u64 size = (u64)pages * PAGE_SIZE; |
| 56 | u64 extra_start = xen_extra_mem_start + xen_extra_mem_size; | 58 | u64 extra_start = xen_extra_mem_start + xen_extra_mem_size; |
| 57 | 59 | ||
| @@ -66,6 +68,9 @@ static __init void xen_add_extra_mem(unsigned long pages) | |||
| 66 | xen_extra_mem_size += size; | 68 | xen_extra_mem_size += size; |
| 67 | 69 | ||
| 68 | xen_max_p2m_pfn = PFN_DOWN(extra_start + size); | 70 | xen_max_p2m_pfn = PFN_DOWN(extra_start + size); |
| 71 | |||
| 72 | for (pfn = PFN_DOWN(extra_start); pfn <= xen_max_p2m_pfn; pfn++) | ||
| 73 | __set_phys_to_machine(pfn, INVALID_P2M_ENTRY); | ||
| 69 | } | 74 | } |
| 70 | 75 | ||
| 71 | static unsigned long __init xen_release_chunk(phys_addr_t start_addr, | 76 | static unsigned long __init xen_release_chunk(phys_addr_t start_addr, |
| @@ -104,7 +109,7 @@ static unsigned long __init xen_release_chunk(phys_addr_t start_addr, | |||
| 104 | WARN(ret != 1, "Failed to release memory %lx-%lx err=%d\n", | 109 | WARN(ret != 1, "Failed to release memory %lx-%lx err=%d\n", |
| 105 | start, end, ret); | 110 | start, end, ret); |
| 106 | if (ret == 1) { | 111 | if (ret == 1) { |
| 107 | set_phys_to_machine(pfn, INVALID_P2M_ENTRY); | 112 | __set_phys_to_machine(pfn, INVALID_P2M_ENTRY); |
| 108 | len++; | 113 | len++; |
| 109 | } | 114 | } |
| 110 | } | 115 | } |
| @@ -138,12 +143,55 @@ static unsigned long __init xen_return_unused_memory(unsigned long max_pfn, | |||
| 138 | return released; | 143 | return released; |
| 139 | } | 144 | } |
| 140 | 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 | } | ||
| 141 | /** | 188 | /** |
| 142 | * machine_specific_memory_setup - Hook for machine specific memory setup. | 189 | * machine_specific_memory_setup - Hook for machine specific memory setup. |
| 143 | **/ | 190 | **/ |
| 144 | char * __init xen_memory_setup(void) | 191 | char * __init xen_memory_setup(void) |
| 145 | { | 192 | { |
| 146 | static struct e820entry map[E820MAX] __initdata; | 193 | static struct e820entry map[E820MAX] __initdata; |
| 194 | static struct e820entry map_raw[E820MAX] __initdata; | ||
| 147 | 195 | ||
| 148 | unsigned long max_pfn = xen_start_info->nr_pages; | 196 | unsigned long max_pfn = xen_start_info->nr_pages; |
| 149 | unsigned long long mem_end; | 197 | unsigned long long mem_end; |
| @@ -151,6 +199,7 @@ char * __init xen_memory_setup(void) | |||
| 151 | struct xen_memory_map memmap; | 199 | struct xen_memory_map memmap; |
| 152 | unsigned long extra_pages = 0; | 200 | unsigned long extra_pages = 0; |
| 153 | unsigned long extra_limit; | 201 | unsigned long extra_limit; |
| 202 | unsigned long identity_pages = 0; | ||
| 154 | int i; | 203 | int i; |
| 155 | int op; | 204 | int op; |
| 156 | 205 | ||
| @@ -176,6 +225,7 @@ char * __init xen_memory_setup(void) | |||
| 176 | } | 225 | } |
| 177 | BUG_ON(rc); | 226 | BUG_ON(rc); |
| 178 | 227 | ||
| 228 | memcpy(map_raw, map, sizeof(map)); | ||
| 179 | e820.nr_map = 0; | 229 | e820.nr_map = 0; |
| 180 | xen_extra_mem_start = mem_end; | 230 | xen_extra_mem_start = mem_end; |
| 181 | for (i = 0; i < memmap.nr_entries; i++) { | 231 | for (i = 0; i < memmap.nr_entries; i++) { |
| @@ -194,6 +244,15 @@ char * __init xen_memory_setup(void) | |||
| 194 | end -= delta; | 244 | end -= delta; |
| 195 | 245 | ||
| 196 | extra_pages += PFN_DOWN(delta); | 246 | extra_pages += PFN_DOWN(delta); |
| 247 | /* | ||
| 248 | * Set RAM below 4GB that is not for us to be unusable. | ||
| 249 | * This prevents "System RAM" address space from being | ||
| 250 | * used as potential resource for I/O address (happens | ||
| 251 | * when 'allocate_resource' is called). | ||
| 252 | */ | ||
| 253 | if (delta && | ||
| 254 | (xen_initial_domain() && end < 0x100000000ULL)) | ||
| 255 | e820_add_region(end, delta, E820_UNUSABLE); | ||
| 197 | } | 256 | } |
| 198 | 257 | ||
| 199 | if (map[i].size > 0 && end > xen_extra_mem_start) | 258 | if (map[i].size > 0 && end > xen_extra_mem_start) |
| @@ -251,6 +310,13 @@ char * __init xen_memory_setup(void) | |||
| 251 | 310 | ||
| 252 | xen_add_extra_mem(extra_pages); | 311 | xen_add_extra_mem(extra_pages); |
| 253 | 312 | ||
| 313 | /* | ||
| 314 | * Set P2M for all non-RAM pages and E820 gaps to be identity | ||
| 315 | * type PFNs. We supply it with the non-sanitized version | ||
| 316 | * of the E820. | ||
| 317 | */ | ||
| 318 | identity_pages = xen_set_identity(map_raw, memmap.nr_entries); | ||
| 319 | printk(KERN_INFO "Set %ld page(s) to 1-1 mapping.\n", identity_pages); | ||
| 254 | return "Xen"; | 320 | return "Xen"; |
| 255 | } | 321 | } |
| 256 | 322 | ||
