Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge branch 'efi-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull EFI fixes from Ingo Molnar:
"A number of regression fixes:

- Fix a boot hang on machines that have somewhat unusual memory map
entries of phys_addr=0x0 num_pages=0, which broke due to a recent
commit. This commit got cherry-picked from the v4.11 queue because
the bug is affecting real machines.

- Fix a boot hang also reported by KASAN, caused by incorrect init
ordering introduced by a recent optimization.

- Fix a recent robustification fix to allocate_new_fdt_and_exit_boot()
that introduced an invalid assumption. Neither bugs were seen in
the wild AFAIK"

* 'efi-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
efi/x86: Prune invalid memory map entries and fix boot regression
x86/efi: Don't allocate memmap through memblock after mm_init()
efi/libstub/arm*: Pass latest memory map to the kernel

+165 -43
+66
arch/x86/platform/efi/efi.c
··· 210 210 return 0; 211 211 } 212 212 213 + #define OVERFLOW_ADDR_SHIFT (64 - EFI_PAGE_SHIFT) 214 + #define OVERFLOW_ADDR_MASK (U64_MAX << OVERFLOW_ADDR_SHIFT) 215 + #define U64_HIGH_BIT (~(U64_MAX >> 1)) 216 + 217 + static bool __init efi_memmap_entry_valid(const efi_memory_desc_t *md, int i) 218 + { 219 + u64 end = (md->num_pages << EFI_PAGE_SHIFT) + md->phys_addr - 1; 220 + u64 end_hi = 0; 221 + char buf[64]; 222 + 223 + if (md->num_pages == 0) { 224 + end = 0; 225 + } else if (md->num_pages > EFI_PAGES_MAX || 226 + EFI_PAGES_MAX - md->num_pages < 227 + (md->phys_addr >> EFI_PAGE_SHIFT)) { 228 + end_hi = (md->num_pages & OVERFLOW_ADDR_MASK) 229 + >> OVERFLOW_ADDR_SHIFT; 230 + 231 + if ((md->phys_addr & U64_HIGH_BIT) && !(end & U64_HIGH_BIT)) 232 + end_hi += 1; 233 + } else { 234 + return true; 235 + } 236 + 237 + pr_warn_once(FW_BUG "Invalid EFI memory map entries:\n"); 238 + 239 + if (end_hi) { 240 + pr_warn("mem%02u: %s range=[0x%016llx-0x%llx%016llx] (invalid)\n", 241 + i, efi_md_typeattr_format(buf, sizeof(buf), md), 242 + md->phys_addr, end_hi, end); 243 + } else { 244 + pr_warn("mem%02u: %s range=[0x%016llx-0x%016llx] (invalid)\n", 245 + i, efi_md_typeattr_format(buf, sizeof(buf), md), 246 + md->phys_addr, end); 247 + } 248 + return false; 249 + } 250 + 251 + static void __init efi_clean_memmap(void) 252 + { 253 + efi_memory_desc_t *out = efi.memmap.map; 254 + const efi_memory_desc_t *in = out; 255 + const efi_memory_desc_t *end = efi.memmap.map_end; 256 + int i, n_removal; 257 + 258 + for (i = n_removal = 0; in < end; i++) { 259 + if (efi_memmap_entry_valid(in, i)) { 260 + if (out != in) 261 + memcpy(out, in, efi.memmap.desc_size); 262 + out = (void *)out + efi.memmap.desc_size; 263 + } else { 264 + n_removal++; 265 + } 266 + in = (void *)in + efi.memmap.desc_size; 267 + } 268 + 269 + if (n_removal > 0) { 270 + u64 size = efi.memmap.nr_map - n_removal; 271 + 272 + pr_warn("Removing %d invalid memory map entries.\n", n_removal); 273 + efi_memmap_install(efi.memmap.phys_map, size); 274 + } 275 + } 276 + 213 277 void __init efi_print_memmap(void) 214 278 { 215 279 efi_memory_desc_t *md; ··· 535 471 return; 536 472 } 537 473 } 474 + 475 + efi_clean_memmap(); 538 476 539 477 if (efi_enabled(EFI_DBG)) 540 478 efi_print_memmap();
+2 -2
arch/x86/platform/efi/quirks.c
··· 214 214 215 215 new_size = efi.memmap.desc_size * num_entries; 216 216 217 - new_phys = memblock_alloc(new_size, 0); 217 + new_phys = efi_memmap_alloc(num_entries); 218 218 if (!new_phys) { 219 219 pr_err("Could not allocate boot services memmap\n"); 220 220 return; ··· 355 355 } 356 356 357 357 new_size = efi.memmap.desc_size * num_entries; 358 - new_phys = memblock_alloc(new_size, 0); 358 + new_phys = efi_memmap_alloc(num_entries); 359 359 if (!new_phys) { 360 360 pr_err("Failed to allocate new EFI memmap\n"); 361 361 return;
+1 -2
drivers/firmware/efi/fake_mem.c
··· 71 71 } 72 72 73 73 /* allocate memory for new EFI memmap */ 74 - new_memmap_phy = memblock_alloc(efi.memmap.desc_size * new_nr_map, 75 - PAGE_SIZE); 74 + new_memmap_phy = efi_memmap_alloc(new_nr_map); 76 75 if (!new_memmap_phy) 77 76 return; 78 77
-8
drivers/firmware/efi/libstub/efistub.h
··· 39 39 40 40 unsigned long get_dram_base(efi_system_table_t *sys_table_arg); 41 41 42 - efi_status_t update_fdt(efi_system_table_t *sys_table, void *orig_fdt, 43 - unsigned long orig_fdt_size, 44 - void *fdt, int new_fdt_size, char *cmdline_ptr, 45 - u64 initrd_addr, u64 initrd_size, 46 - efi_memory_desc_t *memory_map, 47 - unsigned long map_size, unsigned long desc_size, 48 - u32 desc_ver); 49 - 50 42 efi_status_t allocate_new_fdt_and_exit_boot(efi_system_table_t *sys_table, 51 43 void *handle, 52 44 unsigned long *new_fdt_addr,
+56 -31
drivers/firmware/efi/libstub/fdt.c
··· 16 16 17 17 #include "efistub.h" 18 18 19 - efi_status_t update_fdt(efi_system_table_t *sys_table, void *orig_fdt, 20 - unsigned long orig_fdt_size, 21 - void *fdt, int new_fdt_size, char *cmdline_ptr, 22 - u64 initrd_addr, u64 initrd_size, 23 - efi_memory_desc_t *memory_map, 24 - unsigned long map_size, unsigned long desc_size, 25 - u32 desc_ver) 19 + static efi_status_t update_fdt(efi_system_table_t *sys_table, void *orig_fdt, 20 + unsigned long orig_fdt_size, 21 + void *fdt, int new_fdt_size, char *cmdline_ptr, 22 + u64 initrd_addr, u64 initrd_size) 26 23 { 27 24 int node, num_rsv; 28 25 int status; ··· 98 101 if (status) 99 102 goto fdt_set_fail; 100 103 101 - fdt_val64 = cpu_to_fdt64((u64)(unsigned long)memory_map); 104 + fdt_val64 = U64_MAX; /* placeholder */ 102 105 status = fdt_setprop(fdt, node, "linux,uefi-mmap-start", 103 106 &fdt_val64, sizeof(fdt_val64)); 104 107 if (status) 105 108 goto fdt_set_fail; 106 109 107 - fdt_val32 = cpu_to_fdt32(map_size); 110 + fdt_val32 = U32_MAX; /* placeholder */ 108 111 status = fdt_setprop(fdt, node, "linux,uefi-mmap-size", 109 112 &fdt_val32, sizeof(fdt_val32)); 110 113 if (status) 111 114 goto fdt_set_fail; 112 115 113 - fdt_val32 = cpu_to_fdt32(desc_size); 114 116 status = fdt_setprop(fdt, node, "linux,uefi-mmap-desc-size", 115 117 &fdt_val32, sizeof(fdt_val32)); 116 118 if (status) 117 119 goto fdt_set_fail; 118 120 119 - fdt_val32 = cpu_to_fdt32(desc_ver); 120 121 status = fdt_setprop(fdt, node, "linux,uefi-mmap-desc-ver", 121 122 &fdt_val32, sizeof(fdt_val32)); 122 123 if (status) ··· 141 146 return EFI_BUFFER_TOO_SMALL; 142 147 143 148 return EFI_LOAD_ERROR; 149 + } 150 + 151 + static efi_status_t update_fdt_memmap(void *fdt, struct efi_boot_memmap *map) 152 + { 153 + int node = fdt_path_offset(fdt, "/chosen"); 154 + u64 fdt_val64; 155 + u32 fdt_val32; 156 + int err; 157 + 158 + if (node < 0) 159 + return EFI_LOAD_ERROR; 160 + 161 + fdt_val64 = cpu_to_fdt64((unsigned long)*map->map); 162 + err = fdt_setprop_inplace(fdt, node, "linux,uefi-mmap-start", 163 + &fdt_val64, sizeof(fdt_val64)); 164 + if (err) 165 + return EFI_LOAD_ERROR; 166 + 167 + fdt_val32 = cpu_to_fdt32(*map->map_size); 168 + err = fdt_setprop_inplace(fdt, node, "linux,uefi-mmap-size", 169 + &fdt_val32, sizeof(fdt_val32)); 170 + if (err) 171 + return EFI_LOAD_ERROR; 172 + 173 + fdt_val32 = cpu_to_fdt32(*map->desc_size); 174 + err = fdt_setprop_inplace(fdt, node, "linux,uefi-mmap-desc-size", 175 + &fdt_val32, sizeof(fdt_val32)); 176 + if (err) 177 + return EFI_LOAD_ERROR; 178 + 179 + fdt_val32 = cpu_to_fdt32(*map->desc_ver); 180 + err = fdt_setprop_inplace(fdt, node, "linux,uefi-mmap-desc-ver", 181 + &fdt_val32, sizeof(fdt_val32)); 182 + if (err) 183 + return EFI_LOAD_ERROR; 184 + 185 + return EFI_SUCCESS; 144 186 } 145 187 146 188 #ifndef EFI_FDT_ALIGN ··· 275 243 goto fail; 276 244 } 277 245 278 - /* 279 - * Now that we have done our final memory allocation (and free) 280 - * we can get the memory map key needed for 281 - * exit_boot_services(). 282 - */ 283 - status = efi_get_memory_map(sys_table, &map); 284 - if (status != EFI_SUCCESS) 285 - goto fail_free_new_fdt; 286 - 287 246 status = update_fdt(sys_table, 288 247 (void *)fdt_addr, fdt_size, 289 248 (void *)*new_fdt_addr, new_fdt_size, 290 - cmdline_ptr, initrd_addr, initrd_size, 291 - memory_map, map_size, desc_size, desc_ver); 249 + cmdline_ptr, initrd_addr, initrd_size); 292 250 293 251 /* Succeeding the first time is the expected case. */ 294 252 if (status == EFI_SUCCESS) ··· 288 266 /* 289 267 * We need to allocate more space for the new 290 268 * device tree, so free existing buffer that is 291 - * too small. Also free memory map, as we will need 292 - * to get new one that reflects the free/alloc we do 293 - * on the device tree buffer. 269 + * too small. 294 270 */ 295 271 efi_free(sys_table, new_fdt_size, *new_fdt_addr); 296 - sys_table->boottime->free_pool(memory_map); 297 272 new_fdt_size += EFI_PAGE_SIZE; 298 273 } else { 299 274 pr_efi_err(sys_table, "Unable to construct new device tree.\n"); 300 - goto fail_free_mmap; 275 + goto fail_free_new_fdt; 301 276 } 302 277 } 303 278 304 - sys_table->boottime->free_pool(memory_map); 305 279 priv.runtime_map = runtime_map; 306 280 priv.runtime_entry_count = &runtime_entry_count; 307 281 status = efi_exit_boot_services(sys_table, handle, &map, &priv, ··· 305 287 306 288 if (status == EFI_SUCCESS) { 307 289 efi_set_virtual_address_map_t *svam; 290 + 291 + status = update_fdt_memmap((void *)*new_fdt_addr, &map); 292 + if (status != EFI_SUCCESS) { 293 + /* 294 + * The kernel won't get far without the memory map, but 295 + * may still be able to print something meaningful so 296 + * return success here. 297 + */ 298 + return EFI_SUCCESS; 299 + } 308 300 309 301 /* Install the new virtual address map */ 310 302 svam = sys_table->runtime->set_virtual_address_map; ··· 346 318 } 347 319 348 320 pr_efi_err(sys_table, "Exit boot services failed.\n"); 349 - 350 - fail_free_mmap: 351 - sys_table->boottime->free_pool(memory_map); 352 321 353 322 fail_free_new_fdt: 354 323 efi_free(sys_table, new_fdt_size, *new_fdt_addr);
+38
drivers/firmware/efi/memmap.c
··· 9 9 #include <linux/efi.h> 10 10 #include <linux/io.h> 11 11 #include <asm/early_ioremap.h> 12 + #include <linux/memblock.h> 13 + #include <linux/slab.h> 14 + 15 + static phys_addr_t __init __efi_memmap_alloc_early(unsigned long size) 16 + { 17 + return memblock_alloc(size, 0); 18 + } 19 + 20 + static phys_addr_t __init __efi_memmap_alloc_late(unsigned long size) 21 + { 22 + unsigned int order = get_order(size); 23 + struct page *p = alloc_pages(GFP_KERNEL, order); 24 + 25 + if (!p) 26 + return 0; 27 + 28 + return PFN_PHYS(page_to_pfn(p)); 29 + } 30 + 31 + /** 32 + * efi_memmap_alloc - Allocate memory for the EFI memory map 33 + * @num_entries: Number of entries in the allocated map. 34 + * 35 + * Depending on whether mm_init() has already been invoked or not, 36 + * either memblock or "normal" page allocation is used. 37 + * 38 + * Returns the physical address of the allocated memory map on 39 + * success, zero on failure. 40 + */ 41 + phys_addr_t __init efi_memmap_alloc(unsigned int num_entries) 42 + { 43 + unsigned long size = num_entries * efi.memmap.desc_size; 44 + 45 + if (slab_is_available()) 46 + return __efi_memmap_alloc_late(size); 47 + 48 + return __efi_memmap_alloc_early(size); 49 + } 12 50 13 51 /** 14 52 * __efi_memmap_init - Common code for mapping the EFI memory map
+2
include/linux/efi.h
··· 103 103 104 104 #define EFI_PAGE_SHIFT 12 105 105 #define EFI_PAGE_SIZE (1UL << EFI_PAGE_SHIFT) 106 + #define EFI_PAGES_MAX (U64_MAX >> EFI_PAGE_SHIFT) 106 107 107 108 typedef struct { 108 109 u32 type; ··· 951 950 #endif 952 951 extern void __iomem *efi_lookup_mapped_addr(u64 phys_addr); 953 952 953 + extern phys_addr_t __init efi_memmap_alloc(unsigned int num_entries); 954 954 extern int __init efi_memmap_init_early(struct efi_memory_map_data *data); 955 955 extern int __init efi_memmap_init_late(phys_addr_t addr, unsigned long size); 956 956 extern void __init efi_memmap_unmap(void);