diff options
Diffstat (limited to 'arch/x86/platform')
| -rw-r--r-- | arch/x86/platform/efi/efi-bgrt.c | 13 | ||||
| -rw-r--r-- | arch/x86/platform/efi/efi.c | 198 | ||||
| -rw-r--r-- | arch/x86/platform/efi/efi_64.c | 23 | ||||
| -rw-r--r-- | arch/x86/platform/efi/quirks.c | 127 |
4 files changed, 208 insertions, 153 deletions
diff --git a/arch/x86/platform/efi/efi-bgrt.c b/arch/x86/platform/efi/efi-bgrt.c index 6a2f5691b1ab..6aad870e8962 100644 --- a/arch/x86/platform/efi/efi-bgrt.c +++ b/arch/x86/platform/efi/efi-bgrt.c | |||
| @@ -82,21 +82,12 @@ void __init efi_bgrt_init(void) | |||
| 82 | } | 82 | } |
| 83 | bgrt_image_size = bmp_header.size; | 83 | bgrt_image_size = bmp_header.size; |
| 84 | 84 | ||
| 85 | bgrt_image = kmalloc(bgrt_image_size, GFP_KERNEL | __GFP_NOWARN); | 85 | bgrt_image = memremap(bgrt_tab->image_address, bmp_header.size, MEMREMAP_WB); |
| 86 | if (!bgrt_image) { | 86 | if (!bgrt_image) { |
| 87 | pr_notice("Ignoring BGRT: failed to allocate memory for image (wanted %zu bytes)\n", | ||
| 88 | bgrt_image_size); | ||
| 89 | return; | ||
| 90 | } | ||
| 91 | |||
| 92 | image = memremap(bgrt_tab->image_address, bmp_header.size, MEMREMAP_WB); | ||
| 93 | if (!image) { | ||
| 94 | pr_notice("Ignoring BGRT: failed to map image memory\n"); | 87 | pr_notice("Ignoring BGRT: failed to map image memory\n"); |
| 95 | kfree(bgrt_image); | ||
| 96 | bgrt_image = NULL; | 88 | bgrt_image = NULL; |
| 97 | return; | 89 | return; |
| 98 | } | 90 | } |
| 99 | 91 | ||
| 100 | memcpy(bgrt_image, image, bgrt_image_size); | 92 | efi_mem_reserve(bgrt_tab->image_address, bgrt_image_size); |
| 101 | memunmap(image); | ||
| 102 | } | 93 | } |
diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c index 1fbb408e2e72..0955c70897ae 100644 --- a/arch/x86/platform/efi/efi.c +++ b/arch/x86/platform/efi/efi.c | |||
| @@ -172,7 +172,9 @@ static void __init do_add_efi_memmap(void) | |||
| 172 | int __init efi_memblock_x86_reserve_range(void) | 172 | int __init efi_memblock_x86_reserve_range(void) |
| 173 | { | 173 | { |
| 174 | struct efi_info *e = &boot_params.efi_info; | 174 | struct efi_info *e = &boot_params.efi_info; |
| 175 | struct efi_memory_map_data data; | ||
| 175 | phys_addr_t pmap; | 176 | phys_addr_t pmap; |
| 177 | int rv; | ||
| 176 | 178 | ||
| 177 | if (efi_enabled(EFI_PARAVIRT)) | 179 | if (efi_enabled(EFI_PARAVIRT)) |
| 178 | return 0; | 180 | return 0; |
| @@ -187,11 +189,17 @@ int __init efi_memblock_x86_reserve_range(void) | |||
| 187 | #else | 189 | #else |
| 188 | pmap = (e->efi_memmap | ((__u64)e->efi_memmap_hi << 32)); | 190 | pmap = (e->efi_memmap | ((__u64)e->efi_memmap_hi << 32)); |
| 189 | #endif | 191 | #endif |
| 190 | efi.memmap.phys_map = pmap; | 192 | data.phys_map = pmap; |
| 191 | efi.memmap.nr_map = e->efi_memmap_size / | 193 | data.size = e->efi_memmap_size; |
| 192 | e->efi_memdesc_size; | 194 | data.desc_size = e->efi_memdesc_size; |
| 193 | efi.memmap.desc_size = e->efi_memdesc_size; | 195 | data.desc_version = e->efi_memdesc_version; |
| 194 | efi.memmap.desc_version = e->efi_memdesc_version; | 196 | |
| 197 | rv = efi_memmap_init_early(&data); | ||
| 198 | if (rv) | ||
| 199 | return rv; | ||
| 200 | |||
| 201 | if (add_efi_memmap) | ||
| 202 | do_add_efi_memmap(); | ||
| 195 | 203 | ||
| 196 | WARN(efi.memmap.desc_version != 1, | 204 | WARN(efi.memmap.desc_version != 1, |
| 197 | "Unexpected EFI_MEMORY_DESCRIPTOR version %ld", | 205 | "Unexpected EFI_MEMORY_DESCRIPTOR version %ld", |
| @@ -218,19 +226,6 @@ void __init efi_print_memmap(void) | |||
| 218 | } | 226 | } |
| 219 | } | 227 | } |
| 220 | 228 | ||
| 221 | void __init efi_unmap_memmap(void) | ||
| 222 | { | ||
| 223 | unsigned long size; | ||
| 224 | |||
| 225 | clear_bit(EFI_MEMMAP, &efi.flags); | ||
| 226 | |||
| 227 | size = efi.memmap.nr_map * efi.memmap.desc_size; | ||
| 228 | if (efi.memmap.map) { | ||
| 229 | early_memunmap(efi.memmap.map, size); | ||
| 230 | efi.memmap.map = NULL; | ||
| 231 | } | ||
| 232 | } | ||
| 233 | |||
| 234 | static int __init efi_systab_init(void *phys) | 229 | static int __init efi_systab_init(void *phys) |
| 235 | { | 230 | { |
| 236 | if (efi_enabled(EFI_64BIT)) { | 231 | if (efi_enabled(EFI_64BIT)) { |
| @@ -414,33 +409,6 @@ static int __init efi_runtime_init(void) | |||
| 414 | return 0; | 409 | return 0; |
| 415 | } | 410 | } |
| 416 | 411 | ||
| 417 | static int __init efi_memmap_init(void) | ||
| 418 | { | ||
| 419 | unsigned long addr, size; | ||
| 420 | |||
| 421 | if (efi_enabled(EFI_PARAVIRT)) | ||
| 422 | return 0; | ||
| 423 | |||
| 424 | /* Map the EFI memory map */ | ||
| 425 | size = efi.memmap.nr_map * efi.memmap.desc_size; | ||
| 426 | addr = (unsigned long)efi.memmap.phys_map; | ||
| 427 | |||
| 428 | efi.memmap.map = early_memremap(addr, size); | ||
| 429 | if (efi.memmap.map == NULL) { | ||
| 430 | pr_err("Could not map the memory map!\n"); | ||
| 431 | return -ENOMEM; | ||
| 432 | } | ||
| 433 | |||
| 434 | efi.memmap.map_end = efi.memmap.map + size; | ||
| 435 | |||
| 436 | if (add_efi_memmap) | ||
| 437 | do_add_efi_memmap(); | ||
| 438 | |||
| 439 | set_bit(EFI_MEMMAP, &efi.flags); | ||
| 440 | |||
| 441 | return 0; | ||
| 442 | } | ||
| 443 | |||
| 444 | void __init efi_init(void) | 412 | void __init efi_init(void) |
| 445 | { | 413 | { |
| 446 | efi_char16_t *c16; | 414 | efi_char16_t *c16; |
| @@ -498,16 +466,14 @@ void __init efi_init(void) | |||
| 498 | if (!efi_runtime_supported()) | 466 | if (!efi_runtime_supported()) |
| 499 | pr_info("No EFI runtime due to 32/64-bit mismatch with kernel\n"); | 467 | pr_info("No EFI runtime due to 32/64-bit mismatch with kernel\n"); |
| 500 | else { | 468 | else { |
| 501 | if (efi_runtime_disabled() || efi_runtime_init()) | 469 | if (efi_runtime_disabled() || efi_runtime_init()) { |
| 470 | efi_memmap_unmap(); | ||
| 502 | return; | 471 | return; |
| 472 | } | ||
| 503 | } | 473 | } |
| 504 | if (efi_memmap_init()) | ||
| 505 | return; | ||
| 506 | 474 | ||
| 507 | if (efi_enabled(EFI_DBG)) | 475 | if (efi_enabled(EFI_DBG)) |
| 508 | efi_print_memmap(); | 476 | efi_print_memmap(); |
| 509 | |||
| 510 | efi_esrt_init(); | ||
| 511 | } | 477 | } |
| 512 | 478 | ||
| 513 | void __init efi_late_init(void) | 479 | void __init efi_late_init(void) |
| @@ -624,42 +590,6 @@ static void __init get_systab_virt_addr(efi_memory_desc_t *md) | |||
| 624 | } | 590 | } |
| 625 | } | 591 | } |
| 626 | 592 | ||
| 627 | static void __init save_runtime_map(void) | ||
| 628 | { | ||
| 629 | #ifdef CONFIG_KEXEC_CORE | ||
| 630 | unsigned long desc_size; | ||
| 631 | efi_memory_desc_t *md; | ||
| 632 | void *tmp, *q = NULL; | ||
| 633 | int count = 0; | ||
| 634 | |||
| 635 | if (efi_enabled(EFI_OLD_MEMMAP)) | ||
| 636 | return; | ||
| 637 | |||
| 638 | desc_size = efi.memmap.desc_size; | ||
| 639 | |||
| 640 | for_each_efi_memory_desc(md) { | ||
| 641 | if (!(md->attribute & EFI_MEMORY_RUNTIME) || | ||
| 642 | (md->type == EFI_BOOT_SERVICES_CODE) || | ||
| 643 | (md->type == EFI_BOOT_SERVICES_DATA)) | ||
| 644 | continue; | ||
| 645 | tmp = krealloc(q, (count + 1) * desc_size, GFP_KERNEL); | ||
| 646 | if (!tmp) | ||
| 647 | goto out; | ||
| 648 | q = tmp; | ||
| 649 | |||
| 650 | memcpy(q + count * desc_size, md, desc_size); | ||
| 651 | count++; | ||
| 652 | } | ||
| 653 | |||
| 654 | efi_runtime_map_setup(q, count, desc_size); | ||
| 655 | return; | ||
| 656 | |||
| 657 | out: | ||
| 658 | kfree(q); | ||
| 659 | pr_err("Error saving runtime map, efi runtime on kexec non-functional!!\n"); | ||
| 660 | #endif | ||
| 661 | } | ||
| 662 | |||
| 663 | static void *realloc_pages(void *old_memmap, int old_shift) | 593 | static void *realloc_pages(void *old_memmap, int old_shift) |
| 664 | { | 594 | { |
| 665 | void *ret; | 595 | void *ret; |
| @@ -745,6 +675,46 @@ static void *efi_map_next_entry(void *entry) | |||
| 745 | return entry; | 675 | return entry; |
| 746 | } | 676 | } |
| 747 | 677 | ||
| 678 | static bool should_map_region(efi_memory_desc_t *md) | ||
| 679 | { | ||
| 680 | /* | ||
| 681 | * Runtime regions always require runtime mappings (obviously). | ||
| 682 | */ | ||
| 683 | if (md->attribute & EFI_MEMORY_RUNTIME) | ||
| 684 | return true; | ||
| 685 | |||
| 686 | /* | ||
| 687 | * 32-bit EFI doesn't suffer from the bug that requires us to | ||
| 688 | * reserve boot services regions, and mixed mode support | ||
| 689 | * doesn't exist for 32-bit kernels. | ||
| 690 | */ | ||
| 691 | if (IS_ENABLED(CONFIG_X86_32)) | ||
| 692 | return false; | ||
| 693 | |||
| 694 | /* | ||
| 695 | * Map all of RAM so that we can access arguments in the 1:1 | ||
| 696 | * mapping when making EFI runtime calls. | ||
| 697 | */ | ||
| 698 | if (IS_ENABLED(CONFIG_EFI_MIXED) && !efi_is_native()) { | ||
| 699 | if (md->type == EFI_CONVENTIONAL_MEMORY || | ||
| 700 | md->type == EFI_LOADER_DATA || | ||
| 701 | md->type == EFI_LOADER_CODE) | ||
| 702 | return true; | ||
| 703 | } | ||
| 704 | |||
| 705 | /* | ||
| 706 | * Map boot services regions as a workaround for buggy | ||
| 707 | * firmware that accesses them even when they shouldn't. | ||
| 708 | * | ||
| 709 | * See efi_{reserve,free}_boot_services(). | ||
| 710 | */ | ||
| 711 | if (md->type == EFI_BOOT_SERVICES_CODE || | ||
| 712 | md->type == EFI_BOOT_SERVICES_DATA) | ||
| 713 | return true; | ||
| 714 | |||
| 715 | return false; | ||
| 716 | } | ||
| 717 | |||
| 748 | /* | 718 | /* |
| 749 | * Map the efi memory ranges of the runtime services and update new_mmap with | 719 | * Map the efi memory ranges of the runtime services and update new_mmap with |
| 750 | * virtual addresses. | 720 | * virtual addresses. |
| @@ -761,13 +731,9 @@ static void * __init efi_map_regions(int *count, int *pg_shift) | |||
| 761 | p = NULL; | 731 | p = NULL; |
| 762 | while ((p = efi_map_next_entry(p))) { | 732 | while ((p = efi_map_next_entry(p))) { |
| 763 | md = p; | 733 | md = p; |
| 764 | if (!(md->attribute & EFI_MEMORY_RUNTIME)) { | 734 | |
| 765 | #ifdef CONFIG_X86_64 | 735 | if (!should_map_region(md)) |
| 766 | if (md->type != EFI_BOOT_SERVICES_CODE && | 736 | continue; |
| 767 | md->type != EFI_BOOT_SERVICES_DATA) | ||
| 768 | #endif | ||
| 769 | continue; | ||
| 770 | } | ||
| 771 | 737 | ||
| 772 | efi_map_region(md); | 738 | efi_map_region(md); |
| 773 | get_systab_virt_addr(md); | 739 | get_systab_virt_addr(md); |
| @@ -803,7 +769,7 @@ static void __init kexec_enter_virtual_mode(void) | |||
| 803 | * non-native EFI | 769 | * non-native EFI |
| 804 | */ | 770 | */ |
| 805 | if (!efi_is_native()) { | 771 | if (!efi_is_native()) { |
| 806 | efi_unmap_memmap(); | 772 | efi_memmap_unmap(); |
| 807 | clear_bit(EFI_RUNTIME_SERVICES, &efi.flags); | 773 | clear_bit(EFI_RUNTIME_SERVICES, &efi.flags); |
| 808 | return; | 774 | return; |
| 809 | } | 775 | } |
| @@ -823,7 +789,18 @@ static void __init kexec_enter_virtual_mode(void) | |||
| 823 | get_systab_virt_addr(md); | 789 | get_systab_virt_addr(md); |
| 824 | } | 790 | } |
| 825 | 791 | ||
| 826 | save_runtime_map(); | 792 | /* |
| 793 | * Unregister the early EFI memmap from efi_init() and install | ||
| 794 | * the new EFI memory map. | ||
| 795 | */ | ||
| 796 | efi_memmap_unmap(); | ||
| 797 | |||
| 798 | if (efi_memmap_init_late(efi.memmap.phys_map, | ||
| 799 | efi.memmap.desc_size * efi.memmap.nr_map)) { | ||
| 800 | pr_err("Failed to remap late EFI memory map\n"); | ||
| 801 | clear_bit(EFI_RUNTIME_SERVICES, &efi.flags); | ||
| 802 | return; | ||
| 803 | } | ||
| 827 | 804 | ||
| 828 | BUG_ON(!efi.systab); | 805 | BUG_ON(!efi.systab); |
| 829 | 806 | ||
| @@ -884,6 +861,7 @@ static void __init __efi_enter_virtual_mode(void) | |||
| 884 | int count = 0, pg_shift = 0; | 861 | int count = 0, pg_shift = 0; |
| 885 | void *new_memmap = NULL; | 862 | void *new_memmap = NULL; |
| 886 | efi_status_t status; | 863 | efi_status_t status; |
| 864 | phys_addr_t pa; | ||
| 887 | 865 | ||
| 888 | efi.systab = NULL; | 866 | efi.systab = NULL; |
| 889 | 867 | ||
| @@ -901,11 +879,24 @@ static void __init __efi_enter_virtual_mode(void) | |||
| 901 | return; | 879 | return; |
| 902 | } | 880 | } |
| 903 | 881 | ||
| 904 | save_runtime_map(); | 882 | pa = __pa(new_memmap); |
| 883 | |||
| 884 | /* | ||
| 885 | * Unregister the early EFI memmap from efi_init() and install | ||
| 886 | * the new EFI memory map that we are about to pass to the | ||
| 887 | * firmware via SetVirtualAddressMap(). | ||
| 888 | */ | ||
| 889 | efi_memmap_unmap(); | ||
| 890 | |||
| 891 | if (efi_memmap_init_late(pa, efi.memmap.desc_size * count)) { | ||
| 892 | pr_err("Failed to remap late EFI memory map\n"); | ||
| 893 | clear_bit(EFI_RUNTIME_SERVICES, &efi.flags); | ||
| 894 | return; | ||
| 895 | } | ||
| 905 | 896 | ||
| 906 | BUG_ON(!efi.systab); | 897 | BUG_ON(!efi.systab); |
| 907 | 898 | ||
| 908 | if (efi_setup_page_tables(__pa(new_memmap), 1 << pg_shift)) { | 899 | if (efi_setup_page_tables(pa, 1 << pg_shift)) { |
| 909 | clear_bit(EFI_RUNTIME_SERVICES, &efi.flags); | 900 | clear_bit(EFI_RUNTIME_SERVICES, &efi.flags); |
| 910 | return; | 901 | return; |
| 911 | } | 902 | } |
| @@ -917,14 +908,14 @@ static void __init __efi_enter_virtual_mode(void) | |||
| 917 | efi.memmap.desc_size * count, | 908 | efi.memmap.desc_size * count, |
| 918 | efi.memmap.desc_size, | 909 | efi.memmap.desc_size, |
| 919 | efi.memmap.desc_version, | 910 | efi.memmap.desc_version, |
| 920 | (efi_memory_desc_t *)__pa(new_memmap)); | 911 | (efi_memory_desc_t *)pa); |
| 921 | } else { | 912 | } else { |
| 922 | status = efi_thunk_set_virtual_address_map( | 913 | status = efi_thunk_set_virtual_address_map( |
| 923 | efi_phys.set_virtual_address_map, | 914 | efi_phys.set_virtual_address_map, |
| 924 | efi.memmap.desc_size * count, | 915 | efi.memmap.desc_size * count, |
| 925 | efi.memmap.desc_size, | 916 | efi.memmap.desc_size, |
| 926 | efi.memmap.desc_version, | 917 | efi.memmap.desc_version, |
| 927 | (efi_memory_desc_t *)__pa(new_memmap)); | 918 | (efi_memory_desc_t *)pa); |
| 928 | } | 919 | } |
| 929 | 920 | ||
| 930 | if (status != EFI_SUCCESS) { | 921 | if (status != EFI_SUCCESS) { |
| @@ -956,15 +947,6 @@ static void __init __efi_enter_virtual_mode(void) | |||
| 956 | efi_runtime_update_mappings(); | 947 | efi_runtime_update_mappings(); |
| 957 | efi_dump_pagetable(); | 948 | efi_dump_pagetable(); |
| 958 | 949 | ||
| 959 | /* | ||
| 960 | * We mapped the descriptor array into the EFI pagetable above | ||
| 961 | * but we're not unmapping it here because if we're running in | ||
| 962 | * EFI mixed mode we need all of memory to be accessible when | ||
| 963 | * we pass parameters to the EFI runtime services in the | ||
| 964 | * thunking code. | ||
| 965 | */ | ||
| 966 | free_pages((unsigned long)new_memmap, pg_shift); | ||
| 967 | |||
| 968 | /* clean DUMMY object */ | 950 | /* clean DUMMY object */ |
| 969 | efi_delete_dummy_variable(); | 951 | efi_delete_dummy_variable(); |
| 970 | } | 952 | } |
diff --git a/arch/x86/platform/efi/efi_64.c b/arch/x86/platform/efi/efi_64.c index 8dd3784eb075..58b0f801f66f 100644 --- a/arch/x86/platform/efi/efi_64.c +++ b/arch/x86/platform/efi/efi_64.c | |||
| @@ -85,7 +85,7 @@ pgd_t * __init efi_call_phys_prolog(void) | |||
| 85 | early_code_mapping_set_exec(1); | 85 | early_code_mapping_set_exec(1); |
| 86 | 86 | ||
| 87 | n_pgds = DIV_ROUND_UP((max_pfn << PAGE_SHIFT), PGDIR_SIZE); | 87 | n_pgds = DIV_ROUND_UP((max_pfn << PAGE_SHIFT), PGDIR_SIZE); |
| 88 | save_pgd = kmalloc(n_pgds * sizeof(pgd_t), GFP_KERNEL); | 88 | save_pgd = kmalloc_array(n_pgds, sizeof(*save_pgd), GFP_KERNEL); |
| 89 | 89 | ||
| 90 | for (pgd = 0; pgd < n_pgds; pgd++) { | 90 | for (pgd = 0; pgd < n_pgds; pgd++) { |
| 91 | save_pgd[pgd] = *pgd_offset_k(pgd * PGDIR_SIZE); | 91 | save_pgd[pgd] = *pgd_offset_k(pgd * PGDIR_SIZE); |
| @@ -214,7 +214,6 @@ void efi_sync_low_kernel_mappings(void) | |||
| 214 | int __init efi_setup_page_tables(unsigned long pa_memmap, unsigned num_pages) | 214 | int __init efi_setup_page_tables(unsigned long pa_memmap, unsigned num_pages) |
| 215 | { | 215 | { |
| 216 | unsigned long pfn, text; | 216 | unsigned long pfn, text; |
| 217 | efi_memory_desc_t *md; | ||
| 218 | struct page *page; | 217 | struct page *page; |
| 219 | unsigned npages; | 218 | unsigned npages; |
| 220 | pgd_t *pgd; | 219 | pgd_t *pgd; |
| @@ -248,25 +247,6 @@ int __init efi_setup_page_tables(unsigned long pa_memmap, unsigned num_pages) | |||
| 248 | if (!IS_ENABLED(CONFIG_EFI_MIXED) || efi_is_native()) | 247 | if (!IS_ENABLED(CONFIG_EFI_MIXED) || efi_is_native()) |
| 249 | return 0; | 248 | return 0; |
| 250 | 249 | ||
| 251 | /* | ||
| 252 | * Map all of RAM so that we can access arguments in the 1:1 | ||
| 253 | * mapping when making EFI runtime calls. | ||
| 254 | */ | ||
| 255 | for_each_efi_memory_desc(md) { | ||
| 256 | if (md->type != EFI_CONVENTIONAL_MEMORY && | ||
| 257 | md->type != EFI_LOADER_DATA && | ||
| 258 | md->type != EFI_LOADER_CODE) | ||
| 259 | continue; | ||
| 260 | |||
| 261 | pfn = md->phys_addr >> PAGE_SHIFT; | ||
| 262 | npages = md->num_pages; | ||
| 263 | |||
| 264 | if (kernel_map_pages_in_pgd(pgd, pfn, md->phys_addr, npages, _PAGE_RW)) { | ||
| 265 | pr_err("Failed to map 1:1 memory\n"); | ||
| 266 | return 1; | ||
| 267 | } | ||
| 268 | } | ||
| 269 | |||
| 270 | page = alloc_page(GFP_KERNEL|__GFP_DMA32); | 250 | page = alloc_page(GFP_KERNEL|__GFP_DMA32); |
| 271 | if (!page) | 251 | if (!page) |
| 272 | panic("Unable to allocate EFI runtime stack < 4GB\n"); | 252 | panic("Unable to allocate EFI runtime stack < 4GB\n"); |
| @@ -359,6 +339,7 @@ void __init efi_map_region(efi_memory_desc_t *md) | |||
| 359 | */ | 339 | */ |
| 360 | void __init efi_map_region_fixed(efi_memory_desc_t *md) | 340 | void __init efi_map_region_fixed(efi_memory_desc_t *md) |
| 361 | { | 341 | { |
| 342 | __map_region(md, md->phys_addr); | ||
| 362 | __map_region(md, md->virt_addr); | 343 | __map_region(md, md->virt_addr); |
| 363 | } | 344 | } |
| 364 | 345 | ||
diff --git a/arch/x86/platform/efi/quirks.c b/arch/x86/platform/efi/quirks.c index 89d1146f5a6f..10aca63a50d7 100644 --- a/arch/x86/platform/efi/quirks.c +++ b/arch/x86/platform/efi/quirks.c | |||
| @@ -164,6 +164,75 @@ efi_status_t efi_query_variable_store(u32 attributes, unsigned long size, | |||
| 164 | EXPORT_SYMBOL_GPL(efi_query_variable_store); | 164 | EXPORT_SYMBOL_GPL(efi_query_variable_store); |
| 165 | 165 | ||
| 166 | /* | 166 | /* |
| 167 | * The UEFI specification makes it clear that the operating system is | ||
| 168 | * free to do whatever it wants with boot services code after | ||
| 169 | * ExitBootServices() has been called. Ignoring this recommendation a | ||
| 170 | * significant bunch of EFI implementations continue calling into boot | ||
| 171 | * services code (SetVirtualAddressMap). In order to work around such | ||
| 172 | * buggy implementations we reserve boot services region during EFI | ||
| 173 | * init and make sure it stays executable. Then, after | ||
| 174 | * SetVirtualAddressMap(), it is discarded. | ||
| 175 | * | ||
| 176 | * However, some boot services regions contain data that is required | ||
| 177 | * by drivers, so we need to track which memory ranges can never be | ||
| 178 | * freed. This is done by tagging those regions with the | ||
| 179 | * EFI_MEMORY_RUNTIME attribute. | ||
| 180 | * | ||
| 181 | * Any driver that wants to mark a region as reserved must use | ||
| 182 | * efi_mem_reserve() which will insert a new EFI memory descriptor | ||
| 183 | * into efi.memmap (splitting existing regions if necessary) and tag | ||
| 184 | * it with EFI_MEMORY_RUNTIME. | ||
| 185 | */ | ||
| 186 | void __init efi_arch_mem_reserve(phys_addr_t addr, u64 size) | ||
| 187 | { | ||
| 188 | phys_addr_t new_phys, new_size; | ||
| 189 | struct efi_mem_range mr; | ||
| 190 | efi_memory_desc_t md; | ||
| 191 | int num_entries; | ||
| 192 | void *new; | ||
| 193 | |||
| 194 | if (efi_mem_desc_lookup(addr, &md)) { | ||
| 195 | pr_err("Failed to lookup EFI memory descriptor for %pa\n", &addr); | ||
| 196 | return; | ||
| 197 | } | ||
| 198 | |||
| 199 | if (addr + size > md.phys_addr + (md.num_pages << EFI_PAGE_SHIFT)) { | ||
| 200 | pr_err("Region spans EFI memory descriptors, %pa\n", &addr); | ||
| 201 | return; | ||
| 202 | } | ||
| 203 | |||
| 204 | size += addr % EFI_PAGE_SIZE; | ||
| 205 | size = round_up(size, EFI_PAGE_SIZE); | ||
| 206 | addr = round_down(addr, EFI_PAGE_SIZE); | ||
| 207 | |||
| 208 | mr.range.start = addr; | ||
| 209 | mr.range.end = addr + size - 1; | ||
| 210 | mr.attribute = md.attribute | EFI_MEMORY_RUNTIME; | ||
| 211 | |||
| 212 | num_entries = efi_memmap_split_count(&md, &mr.range); | ||
| 213 | num_entries += efi.memmap.nr_map; | ||
| 214 | |||
| 215 | new_size = efi.memmap.desc_size * num_entries; | ||
| 216 | |||
| 217 | new_phys = memblock_alloc(new_size, 0); | ||
| 218 | if (!new_phys) { | ||
| 219 | pr_err("Could not allocate boot services memmap\n"); | ||
| 220 | return; | ||
| 221 | } | ||
| 222 | |||
| 223 | new = early_memremap(new_phys, new_size); | ||
| 224 | if (!new) { | ||
| 225 | pr_err("Failed to map new boot services memmap\n"); | ||
| 226 | return; | ||
| 227 | } | ||
| 228 | |||
| 229 | efi_memmap_insert(&efi.memmap, new, &mr); | ||
| 230 | early_memunmap(new, new_size); | ||
| 231 | |||
| 232 | efi_memmap_install(new_phys, num_entries); | ||
| 233 | } | ||
| 234 | |||
| 235 | /* | ||
| 167 | * Helper function for efi_reserve_boot_services() to figure out if we | 236 | * Helper function for efi_reserve_boot_services() to figure out if we |
| 168 | * can free regions in efi_free_boot_services(). | 237 | * can free regions in efi_free_boot_services(). |
| 169 | * | 238 | * |
| @@ -184,15 +253,6 @@ static bool can_free_region(u64 start, u64 size) | |||
| 184 | return true; | 253 | return true; |
| 185 | } | 254 | } |
| 186 | 255 | ||
| 187 | /* | ||
| 188 | * The UEFI specification makes it clear that the operating system is free to do | ||
| 189 | * whatever it wants with boot services code after ExitBootServices() has been | ||
| 190 | * called. Ignoring this recommendation a significant bunch of EFI implementations | ||
| 191 | * continue calling into boot services code (SetVirtualAddressMap). In order to | ||
| 192 | * work around such buggy implementations we reserve boot services region during | ||
| 193 | * EFI init and make sure it stays executable. Then, after SetVirtualAddressMap(), it | ||
| 194 | * is discarded. | ||
| 195 | */ | ||
| 196 | void __init efi_reserve_boot_services(void) | 256 | void __init efi_reserve_boot_services(void) |
| 197 | { | 257 | { |
| 198 | efi_memory_desc_t *md; | 258 | efi_memory_desc_t *md; |
| @@ -249,7 +309,10 @@ void __init efi_reserve_boot_services(void) | |||
| 249 | 309 | ||
| 250 | void __init efi_free_boot_services(void) | 310 | void __init efi_free_boot_services(void) |
| 251 | { | 311 | { |
| 312 | phys_addr_t new_phys, new_size; | ||
| 252 | efi_memory_desc_t *md; | 313 | efi_memory_desc_t *md; |
| 314 | int num_entries = 0; | ||
| 315 | void *new, *new_md; | ||
| 253 | 316 | ||
| 254 | for_each_efi_memory_desc(md) { | 317 | for_each_efi_memory_desc(md) { |
| 255 | unsigned long long start = md->phys_addr; | 318 | unsigned long long start = md->phys_addr; |
| @@ -257,12 +320,16 @@ void __init efi_free_boot_services(void) | |||
| 257 | size_t rm_size; | 320 | size_t rm_size; |
| 258 | 321 | ||
| 259 | if (md->type != EFI_BOOT_SERVICES_CODE && | 322 | if (md->type != EFI_BOOT_SERVICES_CODE && |
| 260 | md->type != EFI_BOOT_SERVICES_DATA) | 323 | md->type != EFI_BOOT_SERVICES_DATA) { |
| 324 | num_entries++; | ||
| 261 | continue; | 325 | continue; |
| 326 | } | ||
| 262 | 327 | ||
| 263 | /* Do not free, someone else owns it: */ | 328 | /* Do not free, someone else owns it: */ |
| 264 | if (md->attribute & EFI_MEMORY_RUNTIME) | 329 | if (md->attribute & EFI_MEMORY_RUNTIME) { |
| 330 | num_entries++; | ||
| 265 | continue; | 331 | continue; |
| 332 | } | ||
| 266 | 333 | ||
| 267 | /* | 334 | /* |
| 268 | * Nasty quirk: if all sub-1MB memory is used for boot | 335 | * Nasty quirk: if all sub-1MB memory is used for boot |
| @@ -287,7 +354,41 @@ void __init efi_free_boot_services(void) | |||
| 287 | free_bootmem_late(start, size); | 354 | free_bootmem_late(start, size); |
| 288 | } | 355 | } |
| 289 | 356 | ||
| 290 | efi_unmap_memmap(); | 357 | new_size = efi.memmap.desc_size * num_entries; |
| 358 | new_phys = memblock_alloc(new_size, 0); | ||
| 359 | if (!new_phys) { | ||
| 360 | pr_err("Failed to allocate new EFI memmap\n"); | ||
| 361 | return; | ||
| 362 | } | ||
| 363 | |||
| 364 | new = memremap(new_phys, new_size, MEMREMAP_WB); | ||
| 365 | if (!new) { | ||
| 366 | pr_err("Failed to map new EFI memmap\n"); | ||
| 367 | return; | ||
| 368 | } | ||
| 369 | |||
| 370 | /* | ||
| 371 | * Build a new EFI memmap that excludes any boot services | ||
| 372 | * regions that are not tagged EFI_MEMORY_RUNTIME, since those | ||
| 373 | * regions have now been freed. | ||
| 374 | */ | ||
| 375 | new_md = new; | ||
| 376 | for_each_efi_memory_desc(md) { | ||
| 377 | if (!(md->attribute & EFI_MEMORY_RUNTIME) && | ||
| 378 | (md->type == EFI_BOOT_SERVICES_CODE || | ||
| 379 | md->type == EFI_BOOT_SERVICES_DATA)) | ||
| 380 | continue; | ||
| 381 | |||
| 382 | memcpy(new_md, md, efi.memmap.desc_size); | ||
| 383 | new_md += efi.memmap.desc_size; | ||
| 384 | } | ||
| 385 | |||
| 386 | memunmap(new); | ||
| 387 | |||
| 388 | if (efi_memmap_install(new_phys, num_entries)) { | ||
| 389 | pr_err("Could not install new EFI memmap\n"); | ||
| 390 | return; | ||
| 391 | } | ||
| 291 | } | 392 | } |
| 292 | 393 | ||
| 293 | /* | 394 | /* |
| @@ -365,7 +466,7 @@ void __init efi_apply_memmap_quirks(void) | |||
| 365 | */ | 466 | */ |
| 366 | if (!efi_runtime_supported()) { | 467 | if (!efi_runtime_supported()) { |
| 367 | pr_info("Setup done, disabling due to 32/64-bit mismatch\n"); | 468 | pr_info("Setup done, disabling due to 32/64-bit mismatch\n"); |
| 368 | efi_unmap_memmap(); | 469 | efi_memmap_unmap(); |
| 369 | } | 470 | } |
| 370 | 471 | ||
| 371 | /* UV2+ BIOS has a fix for this issue. UV1 still needs the quirk. */ | 472 | /* UV2+ BIOS has a fix for this issue. UV1 still needs the quirk. */ |
