diff options
Diffstat (limited to 'arch/x86/platform')
-rw-r--r-- | arch/x86/platform/efi/efi.c | 59 | ||||
-rw-r--r-- | arch/x86/platform/efi/efi_64.c | 22 | ||||
-rw-r--r-- | arch/x86/platform/uv/tlb_uv.c | 10 |
3 files changed, 59 insertions, 32 deletions
diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c index ad4439145f85..77cf0090c0a3 100644 --- a/arch/x86/platform/efi/efi.c +++ b/arch/x86/platform/efi/efi.c | |||
@@ -51,9 +51,6 @@ | |||
51 | 51 | ||
52 | #define EFI_DEBUG 1 | 52 | #define EFI_DEBUG 1 |
53 | 53 | ||
54 | int efi_enabled; | ||
55 | EXPORT_SYMBOL(efi_enabled); | ||
56 | |||
57 | struct efi __read_mostly efi = { | 54 | struct efi __read_mostly efi = { |
58 | .mps = EFI_INVALID_TABLE_ADDR, | 55 | .mps = EFI_INVALID_TABLE_ADDR, |
59 | .acpi = EFI_INVALID_TABLE_ADDR, | 56 | .acpi = EFI_INVALID_TABLE_ADDR, |
@@ -69,19 +66,28 @@ EXPORT_SYMBOL(efi); | |||
69 | 66 | ||
70 | struct efi_memory_map memmap; | 67 | struct efi_memory_map memmap; |
71 | 68 | ||
72 | bool efi_64bit; | ||
73 | |||
74 | static struct efi efi_phys __initdata; | 69 | static struct efi efi_phys __initdata; |
75 | static efi_system_table_t efi_systab __initdata; | 70 | static efi_system_table_t efi_systab __initdata; |
76 | 71 | ||
77 | static inline bool efi_is_native(void) | 72 | static inline bool efi_is_native(void) |
78 | { | 73 | { |
79 | return IS_ENABLED(CONFIG_X86_64) == efi_64bit; | 74 | return IS_ENABLED(CONFIG_X86_64) == efi_enabled(EFI_64BIT); |
75 | } | ||
76 | |||
77 | unsigned long x86_efi_facility; | ||
78 | |||
79 | /* | ||
80 | * Returns 1 if 'facility' is enabled, 0 otherwise. | ||
81 | */ | ||
82 | int efi_enabled(int facility) | ||
83 | { | ||
84 | return test_bit(facility, &x86_efi_facility) != 0; | ||
80 | } | 85 | } |
86 | EXPORT_SYMBOL(efi_enabled); | ||
81 | 87 | ||
82 | static int __init setup_noefi(char *arg) | 88 | static int __init setup_noefi(char *arg) |
83 | { | 89 | { |
84 | efi_enabled = 0; | 90 | clear_bit(EFI_BOOT, &x86_efi_facility); |
85 | return 0; | 91 | return 0; |
86 | } | 92 | } |
87 | early_param("noefi", setup_noefi); | 93 | early_param("noefi", setup_noefi); |
@@ -426,6 +432,7 @@ void __init efi_reserve_boot_services(void) | |||
426 | 432 | ||
427 | void __init efi_unmap_memmap(void) | 433 | void __init efi_unmap_memmap(void) |
428 | { | 434 | { |
435 | clear_bit(EFI_MEMMAP, &x86_efi_facility); | ||
429 | if (memmap.map) { | 436 | if (memmap.map) { |
430 | early_iounmap(memmap.map, memmap.nr_map * memmap.desc_size); | 437 | early_iounmap(memmap.map, memmap.nr_map * memmap.desc_size); |
431 | memmap.map = NULL; | 438 | memmap.map = NULL; |
@@ -460,7 +467,7 @@ void __init efi_free_boot_services(void) | |||
460 | 467 | ||
461 | static int __init efi_systab_init(void *phys) | 468 | static int __init efi_systab_init(void *phys) |
462 | { | 469 | { |
463 | if (efi_64bit) { | 470 | if (efi_enabled(EFI_64BIT)) { |
464 | efi_system_table_64_t *systab64; | 471 | efi_system_table_64_t *systab64; |
465 | u64 tmp = 0; | 472 | u64 tmp = 0; |
466 | 473 | ||
@@ -552,7 +559,7 @@ static int __init efi_config_init(u64 tables, int nr_tables) | |||
552 | void *config_tables, *tablep; | 559 | void *config_tables, *tablep; |
553 | int i, sz; | 560 | int i, sz; |
554 | 561 | ||
555 | if (efi_64bit) | 562 | if (efi_enabled(EFI_64BIT)) |
556 | sz = sizeof(efi_config_table_64_t); | 563 | sz = sizeof(efi_config_table_64_t); |
557 | else | 564 | else |
558 | sz = sizeof(efi_config_table_32_t); | 565 | sz = sizeof(efi_config_table_32_t); |
@@ -572,7 +579,7 @@ static int __init efi_config_init(u64 tables, int nr_tables) | |||
572 | efi_guid_t guid; | 579 | efi_guid_t guid; |
573 | unsigned long table; | 580 | unsigned long table; |
574 | 581 | ||
575 | if (efi_64bit) { | 582 | if (efi_enabled(EFI_64BIT)) { |
576 | u64 table64; | 583 | u64 table64; |
577 | guid = ((efi_config_table_64_t *)tablep)->guid; | 584 | guid = ((efi_config_table_64_t *)tablep)->guid; |
578 | table64 = ((efi_config_table_64_t *)tablep)->table; | 585 | table64 = ((efi_config_table_64_t *)tablep)->table; |
@@ -684,7 +691,6 @@ void __init efi_init(void) | |||
684 | if (boot_params.efi_info.efi_systab_hi || | 691 | if (boot_params.efi_info.efi_systab_hi || |
685 | boot_params.efi_info.efi_memmap_hi) { | 692 | boot_params.efi_info.efi_memmap_hi) { |
686 | pr_info("Table located above 4GB, disabling EFI.\n"); | 693 | pr_info("Table located above 4GB, disabling EFI.\n"); |
687 | efi_enabled = 0; | ||
688 | return; | 694 | return; |
689 | } | 695 | } |
690 | efi_phys.systab = (efi_system_table_t *)boot_params.efi_info.efi_systab; | 696 | efi_phys.systab = (efi_system_table_t *)boot_params.efi_info.efi_systab; |
@@ -694,10 +700,10 @@ void __init efi_init(void) | |||
694 | ((__u64)boot_params.efi_info.efi_systab_hi<<32)); | 700 | ((__u64)boot_params.efi_info.efi_systab_hi<<32)); |
695 | #endif | 701 | #endif |
696 | 702 | ||
697 | if (efi_systab_init(efi_phys.systab)) { | 703 | if (efi_systab_init(efi_phys.systab)) |
698 | efi_enabled = 0; | ||
699 | return; | 704 | return; |
700 | } | 705 | |
706 | set_bit(EFI_SYSTEM_TABLES, &x86_efi_facility); | ||
701 | 707 | ||
702 | /* | 708 | /* |
703 | * Show what we know for posterity | 709 | * Show what we know for posterity |
@@ -715,10 +721,10 @@ void __init efi_init(void) | |||
715 | efi.systab->hdr.revision >> 16, | 721 | efi.systab->hdr.revision >> 16, |
716 | efi.systab->hdr.revision & 0xffff, vendor); | 722 | efi.systab->hdr.revision & 0xffff, vendor); |
717 | 723 | ||
718 | if (efi_config_init(efi.systab->tables, efi.systab->nr_tables)) { | 724 | if (efi_config_init(efi.systab->tables, efi.systab->nr_tables)) |
719 | efi_enabled = 0; | ||
720 | return; | 725 | return; |
721 | } | 726 | |
727 | set_bit(EFI_CONFIG_TABLES, &x86_efi_facility); | ||
722 | 728 | ||
723 | /* | 729 | /* |
724 | * Note: We currently don't support runtime services on an EFI | 730 | * Note: We currently don't support runtime services on an EFI |
@@ -727,15 +733,17 @@ void __init efi_init(void) | |||
727 | 733 | ||
728 | if (!efi_is_native()) | 734 | if (!efi_is_native()) |
729 | pr_info("No EFI runtime due to 32/64-bit mismatch with kernel\n"); | 735 | pr_info("No EFI runtime due to 32/64-bit mismatch with kernel\n"); |
730 | else if (efi_runtime_init()) { | 736 | else { |
731 | efi_enabled = 0; | 737 | if (efi_runtime_init()) |
732 | return; | 738 | return; |
739 | set_bit(EFI_RUNTIME_SERVICES, &x86_efi_facility); | ||
733 | } | 740 | } |
734 | 741 | ||
735 | if (efi_memmap_init()) { | 742 | if (efi_memmap_init()) |
736 | efi_enabled = 0; | ||
737 | return; | 743 | return; |
738 | } | 744 | |
745 | set_bit(EFI_MEMMAP, &x86_efi_facility); | ||
746 | |||
739 | #ifdef CONFIG_X86_32 | 747 | #ifdef CONFIG_X86_32 |
740 | if (efi_is_native()) { | 748 | if (efi_is_native()) { |
741 | x86_platform.get_wallclock = efi_get_time; | 749 | x86_platform.get_wallclock = efi_get_time; |
@@ -941,7 +949,7 @@ void __init efi_enter_virtual_mode(void) | |||
941 | * | 949 | * |
942 | * Call EFI services through wrapper functions. | 950 | * Call EFI services through wrapper functions. |
943 | */ | 951 | */ |
944 | efi.runtime_version = efi_systab.fw_revision; | 952 | efi.runtime_version = efi_systab.hdr.revision; |
945 | efi.get_time = virt_efi_get_time; | 953 | efi.get_time = virt_efi_get_time; |
946 | efi.set_time = virt_efi_set_time; | 954 | efi.set_time = virt_efi_set_time; |
947 | efi.get_wakeup_time = virt_efi_get_wakeup_time; | 955 | efi.get_wakeup_time = virt_efi_get_wakeup_time; |
@@ -969,6 +977,9 @@ u32 efi_mem_type(unsigned long phys_addr) | |||
969 | efi_memory_desc_t *md; | 977 | efi_memory_desc_t *md; |
970 | void *p; | 978 | void *p; |
971 | 979 | ||
980 | if (!efi_enabled(EFI_MEMMAP)) | ||
981 | return 0; | ||
982 | |||
972 | for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) { | 983 | for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) { |
973 | md = p; | 984 | md = p; |
974 | if ((md->phys_addr <= phys_addr) && | 985 | if ((md->phys_addr <= phys_addr) && |
diff --git a/arch/x86/platform/efi/efi_64.c b/arch/x86/platform/efi/efi_64.c index 95fd505dfeb6..2b2003860615 100644 --- a/arch/x86/platform/efi/efi_64.c +++ b/arch/x86/platform/efi/efi_64.c | |||
@@ -38,7 +38,7 @@ | |||
38 | #include <asm/cacheflush.h> | 38 | #include <asm/cacheflush.h> |
39 | #include <asm/fixmap.h> | 39 | #include <asm/fixmap.h> |
40 | 40 | ||
41 | static pgd_t save_pgd __initdata; | 41 | static pgd_t *save_pgd __initdata; |
42 | static unsigned long efi_flags __initdata; | 42 | static unsigned long efi_flags __initdata; |
43 | 43 | ||
44 | static void __init early_code_mapping_set_exec(int executable) | 44 | static void __init early_code_mapping_set_exec(int executable) |
@@ -61,12 +61,20 @@ static void __init early_code_mapping_set_exec(int executable) | |||
61 | void __init efi_call_phys_prelog(void) | 61 | void __init efi_call_phys_prelog(void) |
62 | { | 62 | { |
63 | unsigned long vaddress; | 63 | unsigned long vaddress; |
64 | int pgd; | ||
65 | int n_pgds; | ||
64 | 66 | ||
65 | early_code_mapping_set_exec(1); | 67 | early_code_mapping_set_exec(1); |
66 | local_irq_save(efi_flags); | 68 | local_irq_save(efi_flags); |
67 | vaddress = (unsigned long)__va(0x0UL); | 69 | |
68 | save_pgd = *pgd_offset_k(0x0UL); | 70 | n_pgds = DIV_ROUND_UP((max_pfn << PAGE_SHIFT), PGDIR_SIZE); |
69 | set_pgd(pgd_offset_k(0x0UL), *pgd_offset_k(vaddress)); | 71 | save_pgd = kmalloc(n_pgds * sizeof(pgd_t), GFP_KERNEL); |
72 | |||
73 | for (pgd = 0; pgd < n_pgds; pgd++) { | ||
74 | save_pgd[pgd] = *pgd_offset_k(pgd * PGDIR_SIZE); | ||
75 | vaddress = (unsigned long)__va(pgd * PGDIR_SIZE); | ||
76 | set_pgd(pgd_offset_k(pgd * PGDIR_SIZE), *pgd_offset_k(vaddress)); | ||
77 | } | ||
70 | __flush_tlb_all(); | 78 | __flush_tlb_all(); |
71 | } | 79 | } |
72 | 80 | ||
@@ -75,7 +83,11 @@ void __init efi_call_phys_epilog(void) | |||
75 | /* | 83 | /* |
76 | * After the lock is released, the original page table is restored. | 84 | * After the lock is released, the original page table is restored. |
77 | */ | 85 | */ |
78 | set_pgd(pgd_offset_k(0x0UL), save_pgd); | 86 | int pgd; |
87 | int n_pgds = DIV_ROUND_UP((max_pfn << PAGE_SHIFT) , PGDIR_SIZE); | ||
88 | for (pgd = 0; pgd < n_pgds; pgd++) | ||
89 | set_pgd(pgd_offset_k(pgd * PGDIR_SIZE), save_pgd[pgd]); | ||
90 | kfree(save_pgd); | ||
79 | __flush_tlb_all(); | 91 | __flush_tlb_all(); |
80 | local_irq_restore(efi_flags); | 92 | local_irq_restore(efi_flags); |
81 | early_code_mapping_set_exec(0); | 93 | early_code_mapping_set_exec(0); |
diff --git a/arch/x86/platform/uv/tlb_uv.c b/arch/x86/platform/uv/tlb_uv.c index b8b3a37c80cd..dbbdca5f508c 100644 --- a/arch/x86/platform/uv/tlb_uv.c +++ b/arch/x86/platform/uv/tlb_uv.c | |||
@@ -1034,7 +1034,8 @@ static int set_distrib_bits(struct cpumask *flush_mask, struct bau_control *bcp, | |||
1034 | * globally purge translation cache of a virtual address or all TLB's | 1034 | * globally purge translation cache of a virtual address or all TLB's |
1035 | * @cpumask: mask of all cpu's in which the address is to be removed | 1035 | * @cpumask: mask of all cpu's in which the address is to be removed |
1036 | * @mm: mm_struct containing virtual address range | 1036 | * @mm: mm_struct containing virtual address range |
1037 | * @va: virtual address to be removed (or TLB_FLUSH_ALL for all TLB's on cpu) | 1037 | * @start: start virtual address to be removed from TLB |
1038 | * @end: end virtual address to be remove from TLB | ||
1038 | * @cpu: the current cpu | 1039 | * @cpu: the current cpu |
1039 | * | 1040 | * |
1040 | * This is the entry point for initiating any UV global TLB shootdown. | 1041 | * This is the entry point for initiating any UV global TLB shootdown. |
@@ -1056,7 +1057,7 @@ static int set_distrib_bits(struct cpumask *flush_mask, struct bau_control *bcp, | |||
1056 | */ | 1057 | */ |
1057 | const struct cpumask *uv_flush_tlb_others(const struct cpumask *cpumask, | 1058 | const struct cpumask *uv_flush_tlb_others(const struct cpumask *cpumask, |
1058 | struct mm_struct *mm, unsigned long start, | 1059 | struct mm_struct *mm, unsigned long start, |
1059 | unsigned end, unsigned int cpu) | 1060 | unsigned long end, unsigned int cpu) |
1060 | { | 1061 | { |
1061 | int locals = 0; | 1062 | int locals = 0; |
1062 | int remotes = 0; | 1063 | int remotes = 0; |
@@ -1113,7 +1114,10 @@ const struct cpumask *uv_flush_tlb_others(const struct cpumask *cpumask, | |||
1113 | 1114 | ||
1114 | record_send_statistics(stat, locals, hubs, remotes, bau_desc); | 1115 | record_send_statistics(stat, locals, hubs, remotes, bau_desc); |
1115 | 1116 | ||
1116 | bau_desc->payload.address = start; | 1117 | if (!end || (end - start) <= PAGE_SIZE) |
1118 | bau_desc->payload.address = start; | ||
1119 | else | ||
1120 | bau_desc->payload.address = TLB_FLUSH_ALL; | ||
1117 | bau_desc->payload.sending_cpu = cpu; | 1121 | bau_desc->payload.sending_cpu = cpu; |
1118 | /* | 1122 | /* |
1119 | * uv_flush_send_and_wait returns 0 if all cpu's were messaged, | 1123 | * uv_flush_send_and_wait returns 0 if all cpu's were messaged, |