aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/platform
diff options
context:
space:
mode:
authorMatt Fleming <matt.fleming@intel.com>2014-03-05 13:15:37 -0500
committerMatt Fleming <matt.fleming@intel.com>2014-03-05 13:15:37 -0500
commit994448f1afa6689bafbebaf7412b23b541b41ef5 (patch)
treeb7460c6a9bdadc6554ad7f0da52b5c60403164c1 /arch/x86/platform
parent4fd69331ad227a4d8de26592d017b73e00caca9f (diff)
parent18c46461d9e42d398536055f31f58cdcd2c6347e (diff)
Merge remote-tracking branch 'tip/x86/efi-mixed' into efi-for-mingo
Conflicts: arch/x86/kernel/setup.c arch/x86/platform/efi/efi.c arch/x86/platform/efi/efi_64.c
Diffstat (limited to 'arch/x86/platform')
-rw-r--r--arch/x86/platform/efi/Makefile1
-rw-r--r--arch/x86/platform/efi/efi.c158
-rw-r--r--arch/x86/platform/efi/efi_64.c327
-rw-r--r--arch/x86/platform/efi/efi_stub_64.S157
-rw-r--r--arch/x86/platform/efi/efi_thunk_64.S65
5 files changed, 651 insertions, 57 deletions
diff --git a/arch/x86/platform/efi/Makefile b/arch/x86/platform/efi/Makefile
index b7b0b35c1981..d51045afcaaf 100644
--- a/arch/x86/platform/efi/Makefile
+++ b/arch/x86/platform/efi/Makefile
@@ -1,3 +1,4 @@
1obj-$(CONFIG_EFI) += efi.o efi_$(BITS).o efi_stub_$(BITS).o 1obj-$(CONFIG_EFI) += efi.o efi_$(BITS).o efi_stub_$(BITS).o
2obj-$(CONFIG_ACPI_BGRT) += efi-bgrt.o 2obj-$(CONFIG_ACPI_BGRT) += efi-bgrt.o
3obj-$(CONFIG_EARLY_PRINTK_EFI) += early_printk.o 3obj-$(CONFIG_EARLY_PRINTK_EFI) += early_printk.o
4obj-$(CONFIG_EFI_MIXED) += efi_thunk_$(BITS).o
diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c
index 45d4f7674678..43e7cf6c6111 100644
--- a/arch/x86/platform/efi/efi.c
+++ b/arch/x86/platform/efi/efi.c
@@ -453,9 +453,6 @@ void __init efi_free_boot_services(void)
453{ 453{
454 void *p; 454 void *p;
455 455
456 if (!efi_is_native())
457 return;
458
459 for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) { 456 for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) {
460 efi_memory_desc_t *md = p; 457 efi_memory_desc_t *md = p;
461 unsigned long long start = md->phys_addr; 458 unsigned long long start = md->phys_addr;
@@ -579,37 +576,85 @@ static int __init efi_systab_init(void *phys)
579 return 0; 576 return 0;
580} 577}
581 578
582static int __init efi_runtime_init(void) 579static int __init efi_runtime_init32(void)
583{ 580{
584 efi_runtime_services_t *runtime; 581 efi_runtime_services_32_t *runtime;
582
583 runtime = early_ioremap((unsigned long)efi.systab->runtime,
584 sizeof(efi_runtime_services_32_t));
585 if (!runtime) {
586 pr_err("Could not map the runtime service table!\n");
587 return -ENOMEM;
588 }
585 589
586 /* 590 /*
587 * Check out the runtime services table. We need to map 591 * We will only need *early* access to the following two
588 * the runtime services table so that we can grab the physical 592 * EFI runtime services before set_virtual_address_map
589 * address of several of the EFI runtime functions, needed to 593 * is invoked.
590 * set the firmware into virtual mode. 594 */
595 efi_phys.get_time = (efi_get_time_t *)
596 (unsigned long)runtime->get_time;
597 efi_phys.set_virtual_address_map =
598 (efi_set_virtual_address_map_t *)
599 (unsigned long)runtime->set_virtual_address_map;
600 /*
601 * Make efi_get_time can be called before entering
602 * virtual mode.
591 */ 603 */
604 efi.get_time = phys_efi_get_time;
605 early_iounmap(runtime, sizeof(efi_runtime_services_32_t));
606
607 return 0;
608}
609
610static int __init efi_runtime_init64(void)
611{
612 efi_runtime_services_64_t *runtime;
613
592 runtime = early_ioremap((unsigned long)efi.systab->runtime, 614 runtime = early_ioremap((unsigned long)efi.systab->runtime,
593 sizeof(efi_runtime_services_t)); 615 sizeof(efi_runtime_services_64_t));
594 if (!runtime) { 616 if (!runtime) {
595 pr_err("Could not map the runtime service table!\n"); 617 pr_err("Could not map the runtime service table!\n");
596 return -ENOMEM; 618 return -ENOMEM;
597 } 619 }
620
598 /* 621 /*
599 * We will only need *early* access to the following 622 * We will only need *early* access to the following two
600 * two EFI runtime services before set_virtual_address_map 623 * EFI runtime services before set_virtual_address_map
601 * is invoked. 624 * is invoked.
602 */ 625 */
603 efi_phys.get_time = (efi_get_time_t *)runtime->get_time; 626 efi_phys.get_time = (efi_get_time_t *)
627 (unsigned long)runtime->get_time;
604 efi_phys.set_virtual_address_map = 628 efi_phys.set_virtual_address_map =
605 (efi_set_virtual_address_map_t *) 629 (efi_set_virtual_address_map_t *)
606 runtime->set_virtual_address_map; 630 (unsigned long)runtime->set_virtual_address_map;
607 /* 631 /*
608 * Make efi_get_time can be called before entering 632 * Make efi_get_time can be called before entering
609 * virtual mode. 633 * virtual mode.
610 */ 634 */
611 efi.get_time = phys_efi_get_time; 635 efi.get_time = phys_efi_get_time;
612 early_iounmap(runtime, sizeof(efi_runtime_services_t)); 636 early_iounmap(runtime, sizeof(efi_runtime_services_64_t));
637
638 return 0;
639}
640
641static int __init efi_runtime_init(void)
642{
643 int rv;
644
645 /*
646 * Check out the runtime services table. We need to map
647 * the runtime services table so that we can grab the physical
648 * address of several of the EFI runtime functions, needed to
649 * set the firmware into virtual mode.
650 */
651 if (efi_enabled(EFI_64BIT))
652 rv = efi_runtime_init64();
653 else
654 rv = efi_runtime_init32();
655
656 if (rv)
657 return rv;
613 658
614 set_bit(EFI_RUNTIME_SERVICES, &efi.flags); 659 set_bit(EFI_RUNTIME_SERVICES, &efi.flags);
615 660
@@ -747,7 +792,7 @@ void __init efi_init(void)
747 * that doesn't match the kernel 32/64-bit mode. 792 * that doesn't match the kernel 32/64-bit mode.
748 */ 793 */
749 794
750 if (!efi_is_native()) 795 if (!efi_runtime_supported())
751 pr_info("No EFI runtime due to 32/64-bit mismatch with kernel\n"); 796 pr_info("No EFI runtime due to 32/64-bit mismatch with kernel\n");
752 else { 797 else {
753 if (disable_runtime || efi_runtime_init()) 798 if (disable_runtime || efi_runtime_init())
@@ -833,6 +878,22 @@ void __init old_map_region(efi_memory_desc_t *md)
833 (unsigned long long)md->phys_addr); 878 (unsigned long long)md->phys_addr);
834} 879}
835 880
881static void native_runtime_setup(void)
882{
883 efi.get_time = virt_efi_get_time;
884 efi.set_time = virt_efi_set_time;
885 efi.get_wakeup_time = virt_efi_get_wakeup_time;
886 efi.set_wakeup_time = virt_efi_set_wakeup_time;
887 efi.get_variable = virt_efi_get_variable;
888 efi.get_next_variable = virt_efi_get_next_variable;
889 efi.set_variable = virt_efi_set_variable;
890 efi.get_next_high_mono_count = virt_efi_get_next_high_mono_count;
891 efi.reset_system = virt_efi_reset_system;
892 efi.query_variable_info = virt_efi_query_variable_info;
893 efi.update_capsule = virt_efi_update_capsule;
894 efi.query_capsule_caps = virt_efi_query_capsule_caps;
895}
896
836/* Merge contiguous regions of the same type and attribute */ 897/* Merge contiguous regions of the same type and attribute */
837static void __init efi_merge_regions(void) 898static void __init efi_merge_regions(void)
838{ 899{
@@ -1015,19 +1076,10 @@ static void __init kexec_enter_virtual_mode(void)
1015 * Call EFI services through wrapper functions. 1076 * Call EFI services through wrapper functions.
1016 */ 1077 */
1017 efi.runtime_version = efi_systab.hdr.revision; 1078 efi.runtime_version = efi_systab.hdr.revision;
1018 efi.get_time = virt_efi_get_time; 1079
1019 efi.set_time = virt_efi_set_time; 1080 native_runtime_setup();
1020 efi.get_wakeup_time = virt_efi_get_wakeup_time; 1081
1021 efi.set_wakeup_time = virt_efi_set_wakeup_time;
1022 efi.get_variable = virt_efi_get_variable;
1023 efi.get_next_variable = virt_efi_get_next_variable;
1024 efi.set_variable = virt_efi_set_variable;
1025 efi.get_next_high_mono_count = virt_efi_get_next_high_mono_count;
1026 efi.reset_system = virt_efi_reset_system;
1027 efi.set_virtual_address_map = NULL; 1082 efi.set_virtual_address_map = NULL;
1028 efi.query_variable_info = virt_efi_query_variable_info;
1029 efi.update_capsule = virt_efi_update_capsule;
1030 efi.query_capsule_caps = virt_efi_query_capsule_caps;
1031 1083
1032 if (efi_enabled(EFI_OLD_MEMMAP) && (__supported_pte_mask & _PAGE_NX)) 1084 if (efi_enabled(EFI_OLD_MEMMAP) && (__supported_pte_mask & _PAGE_NX))
1033 runtime_code_page_mkexec(); 1085 runtime_code_page_mkexec();
@@ -1071,15 +1123,6 @@ static void __init __efi_enter_virtual_mode(void)
1071 1123
1072 efi.systab = NULL; 1124 efi.systab = NULL;
1073 1125
1074 /*
1075 * We don't do virtual mode, since we don't do runtime services, on
1076 * non-native EFI
1077 */
1078 if (!efi_is_native()) {
1079 efi_unmap_memmap();
1080 return;
1081 }
1082
1083 efi_merge_regions(); 1126 efi_merge_regions();
1084 new_memmap = efi_map_regions(&count, &pg_shift); 1127 new_memmap = efi_map_regions(&count, &pg_shift);
1085 if (!new_memmap) { 1128 if (!new_memmap) {
@@ -1097,11 +1140,20 @@ static void __init __efi_enter_virtual_mode(void)
1097 efi_sync_low_kernel_mappings(); 1140 efi_sync_low_kernel_mappings();
1098 efi_dump_pagetable(); 1141 efi_dump_pagetable();
1099 1142
1100 status = phys_efi_set_virtual_address_map( 1143 if (efi_is_native()) {
1101 memmap.desc_size * count, 1144 status = phys_efi_set_virtual_address_map(
1102 memmap.desc_size, 1145 memmap.desc_size * count,
1103 memmap.desc_version, 1146 memmap.desc_size,
1104 (efi_memory_desc_t *)__pa(new_memmap)); 1147 memmap.desc_version,
1148 (efi_memory_desc_t *)__pa(new_memmap));
1149 } else {
1150 status = efi_thunk_set_virtual_address_map(
1151 efi_phys.set_virtual_address_map,
1152 memmap.desc_size * count,
1153 memmap.desc_size,
1154 memmap.desc_version,
1155 (efi_memory_desc_t *)__pa(new_memmap));
1156 }
1105 1157
1106 if (status != EFI_SUCCESS) { 1158 if (status != EFI_SUCCESS) {
1107 pr_alert("Unable to switch EFI into virtual mode (status=%lx)!\n", 1159 pr_alert("Unable to switch EFI into virtual mode (status=%lx)!\n",
@@ -1116,19 +1168,13 @@ static void __init __efi_enter_virtual_mode(void)
1116 * Call EFI services through wrapper functions. 1168 * Call EFI services through wrapper functions.
1117 */ 1169 */
1118 efi.runtime_version = efi_systab.hdr.revision; 1170 efi.runtime_version = efi_systab.hdr.revision;
1119 efi.get_time = virt_efi_get_time; 1171
1120 efi.set_time = virt_efi_set_time; 1172 if (efi_is_native())
1121 efi.get_wakeup_time = virt_efi_get_wakeup_time; 1173 native_runtime_setup();
1122 efi.set_wakeup_time = virt_efi_set_wakeup_time; 1174 else
1123 efi.get_variable = virt_efi_get_variable; 1175 efi_thunk_runtime_setup();
1124 efi.get_next_variable = virt_efi_get_next_variable; 1176
1125 efi.set_variable = virt_efi_set_variable;
1126 efi.get_next_high_mono_count = virt_efi_get_next_high_mono_count;
1127 efi.reset_system = virt_efi_reset_system;
1128 efi.set_virtual_address_map = NULL; 1177 efi.set_virtual_address_map = NULL;
1129 efi.query_variable_info = virt_efi_query_variable_info;
1130 efi.update_capsule = virt_efi_update_capsule;
1131 efi.query_capsule_caps = virt_efi_query_capsule_caps;
1132 1178
1133 efi_runtime_mkexec(); 1179 efi_runtime_mkexec();
1134 1180
@@ -1311,7 +1357,7 @@ void __init efi_apply_memmap_quirks(void)
1311 * firmware/kernel architectures since there is no support for runtime 1357 * firmware/kernel architectures since there is no support for runtime
1312 * services. 1358 * services.
1313 */ 1359 */
1314 if (!efi_is_native()) { 1360 if (!efi_runtime_supported()) {
1315 pr_info("efi: Setup done, disabling due to 32/64-bit mismatch\n"); 1361 pr_info("efi: Setup done, disabling due to 32/64-bit mismatch\n");
1316 efi_unmap_memmap(); 1362 efi_unmap_memmap();
1317 } 1363 }
diff --git a/arch/x86/platform/efi/efi_64.c b/arch/x86/platform/efi/efi_64.c
index 19280900ec25..7e7f195aa5cf 100644
--- a/arch/x86/platform/efi/efi_64.c
+++ b/arch/x86/platform/efi/efi_64.c
@@ -39,6 +39,7 @@
39#include <asm/cacheflush.h> 39#include <asm/cacheflush.h>
40#include <asm/fixmap.h> 40#include <asm/fixmap.h>
41#include <asm/realmode.h> 41#include <asm/realmode.h>
42#include <asm/time.h>
42 43
43static pgd_t *save_pgd __initdata; 44static pgd_t *save_pgd __initdata;
44static unsigned long efi_flags __initdata; 45static unsigned long efi_flags __initdata;
@@ -58,7 +59,8 @@ struct efi_scratch {
58 u64 prev_cr3; 59 u64 prev_cr3;
59 pgd_t *efi_pgt; 60 pgd_t *efi_pgt;
60 bool use_pgd; 61 bool use_pgd;
61}; 62 u64 phys_stack;
63} __packed;
62 64
63static void __init early_code_mapping_set_exec(int executable) 65static void __init early_code_mapping_set_exec(int executable)
64{ 66{
@@ -139,6 +141,9 @@ void efi_sync_low_kernel_mappings(void)
139 141
140int efi_setup_page_tables(unsigned long pa_memmap, unsigned num_pages) 142int efi_setup_page_tables(unsigned long pa_memmap, unsigned num_pages)
141{ 143{
144 unsigned long text;
145 struct page *page;
146 unsigned npages;
142 pgd_t *pgd; 147 pgd_t *pgd;
143 148
144 if (efi_enabled(EFI_OLD_MEMMAP)) 149 if (efi_enabled(EFI_OLD_MEMMAP))
@@ -160,6 +165,29 @@ int efi_setup_page_tables(unsigned long pa_memmap, unsigned num_pages)
160 165
161 efi_scratch.use_pgd = true; 166 efi_scratch.use_pgd = true;
162 167
168 /*
169 * When making calls to the firmware everything needs to be 1:1
170 * mapped and addressable with 32-bit pointers. Map the kernel
171 * text and allocate a new stack because we can't rely on the
172 * stack pointer being < 4GB.
173 */
174 if (!IS_ENABLED(CONFIG_EFI_MIXED))
175 return 0;
176
177 page = alloc_page(GFP_KERNEL|__GFP_DMA32);
178 if (!page)
179 panic("Unable to allocate EFI runtime stack < 4GB\n");
180
181 efi_scratch.phys_stack = virt_to_phys(page_address(page));
182 efi_scratch.phys_stack += PAGE_SIZE; /* stack grows down */
183
184 npages = (_end - _text) >> PAGE_SHIFT;
185 text = __pa(_text);
186
187 if (kernel_map_pages_in_pgd(pgd, text >> PAGE_SHIFT, text, npages, 0)) {
188 pr_err("Failed to map kernel text 1:1\n");
189 return 1;
190 }
163 191
164 return 0; 192 return 0;
165} 193}
@@ -199,6 +227,16 @@ void __init efi_map_region(efi_memory_desc_t *md)
199 */ 227 */
200 __map_region(md, md->phys_addr); 228 __map_region(md, md->phys_addr);
201 229
230 /*
231 * Enforce the 1:1 mapping as the default virtual address when
232 * booting in EFI mixed mode, because even though we may be
233 * running a 64-bit kernel, the firmware may only be 32-bit.
234 */
235 if (!efi_is_native () && IS_ENABLED(CONFIG_EFI_MIXED)) {
236 md->virt_addr = md->phys_addr;
237 return;
238 }
239
202 efi_va -= size; 240 efi_va -= size;
203 241
204 /* Is PA 2M-aligned? */ 242 /* Is PA 2M-aligned? */
@@ -277,3 +315,290 @@ void __init efi_dump_pagetable(void)
277 ptdump_walk_pgd_level(NULL, pgd); 315 ptdump_walk_pgd_level(NULL, pgd);
278#endif 316#endif
279} 317}
318
319#ifdef CONFIG_EFI_MIXED
320extern efi_status_t efi64_thunk(u32, ...);
321
322#define runtime_service32(func) \
323({ \
324 u32 table = (u32)(unsigned long)efi.systab; \
325 u32 *rt, *___f; \
326 \
327 rt = (u32 *)(table + offsetof(efi_system_table_32_t, runtime)); \
328 ___f = (u32 *)(*rt + offsetof(efi_runtime_services_32_t, func)); \
329 *___f; \
330})
331
332/*
333 * Switch to the EFI page tables early so that we can access the 1:1
334 * runtime services mappings which are not mapped in any other page
335 * tables. This function must be called before runtime_service32().
336 *
337 * Also, disable interrupts because the IDT points to 64-bit handlers,
338 * which aren't going to function correctly when we switch to 32-bit.
339 */
340#define efi_thunk(f, ...) \
341({ \
342 efi_status_t __s; \
343 unsigned long flags; \
344 u32 func; \
345 \
346 efi_sync_low_kernel_mappings(); \
347 local_irq_save(flags); \
348 \
349 efi_scratch.prev_cr3 = read_cr3(); \
350 write_cr3((unsigned long)efi_scratch.efi_pgt); \
351 __flush_tlb_all(); \
352 \
353 func = runtime_service32(f); \
354 __s = efi64_thunk(func, __VA_ARGS__); \
355 \
356 write_cr3(efi_scratch.prev_cr3); \
357 __flush_tlb_all(); \
358 local_irq_restore(flags); \
359 \
360 __s; \
361})
362
363efi_status_t efi_thunk_set_virtual_address_map(
364 void *phys_set_virtual_address_map,
365 unsigned long memory_map_size,
366 unsigned long descriptor_size,
367 u32 descriptor_version,
368 efi_memory_desc_t *virtual_map)
369{
370 efi_status_t status;
371 unsigned long flags;
372 u32 func;
373
374 efi_sync_low_kernel_mappings();
375 local_irq_save(flags);
376
377 efi_scratch.prev_cr3 = read_cr3();
378 write_cr3((unsigned long)efi_scratch.efi_pgt);
379 __flush_tlb_all();
380
381 func = (u32)(unsigned long)phys_set_virtual_address_map;
382 status = efi64_thunk(func, memory_map_size, descriptor_size,
383 descriptor_version, virtual_map);
384
385 write_cr3(efi_scratch.prev_cr3);
386 __flush_tlb_all();
387 local_irq_restore(flags);
388
389 return status;
390}
391
392static efi_status_t efi_thunk_get_time(efi_time_t *tm, efi_time_cap_t *tc)
393{
394 efi_status_t status;
395 u32 phys_tm, phys_tc;
396
397 spin_lock(&rtc_lock);
398
399 phys_tm = virt_to_phys(tm);
400 phys_tc = virt_to_phys(tc);
401
402 status = efi_thunk(get_time, phys_tm, phys_tc);
403
404 spin_unlock(&rtc_lock);
405
406 return status;
407}
408
409static efi_status_t efi_thunk_set_time(efi_time_t *tm)
410{
411 efi_status_t status;
412 u32 phys_tm;
413
414 spin_lock(&rtc_lock);
415
416 phys_tm = virt_to_phys(tm);
417
418 status = efi_thunk(set_time, phys_tm);
419
420 spin_unlock(&rtc_lock);
421
422 return status;
423}
424
425static efi_status_t
426efi_thunk_get_wakeup_time(efi_bool_t *enabled, efi_bool_t *pending,
427 efi_time_t *tm)
428{
429 efi_status_t status;
430 u32 phys_enabled, phys_pending, phys_tm;
431
432 spin_lock(&rtc_lock);
433
434 phys_enabled = virt_to_phys(enabled);
435 phys_pending = virt_to_phys(pending);
436 phys_tm = virt_to_phys(tm);
437
438 status = efi_thunk(get_wakeup_time, phys_enabled,
439 phys_pending, phys_tm);
440
441 spin_unlock(&rtc_lock);
442
443 return status;
444}
445
446static efi_status_t
447efi_thunk_set_wakeup_time(efi_bool_t enabled, efi_time_t *tm)
448{
449 efi_status_t status;
450 u32 phys_tm;
451
452 spin_lock(&rtc_lock);
453
454 phys_tm = virt_to_phys(tm);
455
456 status = efi_thunk(set_wakeup_time, enabled, phys_tm);
457
458 spin_unlock(&rtc_lock);
459
460 return status;
461}
462
463
464static efi_status_t
465efi_thunk_get_variable(efi_char16_t *name, efi_guid_t *vendor,
466 u32 *attr, unsigned long *data_size, void *data)
467{
468 efi_status_t status;
469 u32 phys_name, phys_vendor, phys_attr;
470 u32 phys_data_size, phys_data;
471
472 phys_data_size = virt_to_phys(data_size);
473 phys_vendor = virt_to_phys(vendor);
474 phys_name = virt_to_phys(name);
475 phys_attr = virt_to_phys(attr);
476 phys_data = virt_to_phys(data);
477
478 status = efi_thunk(get_variable, phys_name, phys_vendor,
479 phys_attr, phys_data_size, phys_data);
480
481 return status;
482}
483
484static efi_status_t
485efi_thunk_set_variable(efi_char16_t *name, efi_guid_t *vendor,
486 u32 attr, unsigned long data_size, void *data)
487{
488 u32 phys_name, phys_vendor, phys_data;
489 efi_status_t status;
490
491 phys_name = virt_to_phys(name);
492 phys_vendor = virt_to_phys(vendor);
493 phys_data = virt_to_phys(data);
494
495 /* If data_size is > sizeof(u32) we've got problems */
496 status = efi_thunk(set_variable, phys_name, phys_vendor,
497 attr, data_size, phys_data);
498
499 return status;
500}
501
502static efi_status_t
503efi_thunk_get_next_variable(unsigned long *name_size,
504 efi_char16_t *name,
505 efi_guid_t *vendor)
506{
507 efi_status_t status;
508 u32 phys_name_size, phys_name, phys_vendor;
509
510 phys_name_size = virt_to_phys(name_size);
511 phys_vendor = virt_to_phys(vendor);
512 phys_name = virt_to_phys(name);
513
514 status = efi_thunk(get_next_variable, phys_name_size,
515 phys_name, phys_vendor);
516
517 return status;
518}
519
520static efi_status_t
521efi_thunk_get_next_high_mono_count(u32 *count)
522{
523 efi_status_t status;
524 u32 phys_count;
525
526 phys_count = virt_to_phys(count);
527 status = efi_thunk(get_next_high_mono_count, phys_count);
528
529 return status;
530}
531
532static void
533efi_thunk_reset_system(int reset_type, efi_status_t status,
534 unsigned long data_size, efi_char16_t *data)
535{
536 u32 phys_data;
537
538 phys_data = virt_to_phys(data);
539
540 efi_thunk(reset_system, reset_type, status, data_size, phys_data);
541}
542
543static efi_status_t
544efi_thunk_update_capsule(efi_capsule_header_t **capsules,
545 unsigned long count, unsigned long sg_list)
546{
547 /*
548 * To properly support this function we would need to repackage
549 * 'capsules' because the firmware doesn't understand 64-bit
550 * pointers.
551 */
552 return EFI_UNSUPPORTED;
553}
554
555static efi_status_t
556efi_thunk_query_variable_info(u32 attr, u64 *storage_space,
557 u64 *remaining_space,
558 u64 *max_variable_size)
559{
560 efi_status_t status;
561 u32 phys_storage, phys_remaining, phys_max;
562
563 if (efi.runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION)
564 return EFI_UNSUPPORTED;
565
566 phys_storage = virt_to_phys(storage_space);
567 phys_remaining = virt_to_phys(remaining_space);
568 phys_max = virt_to_phys(max_variable_size);
569
570 status = efi_thunk(query_variable_info, phys_storage,
571 phys_remaining, phys_max);
572
573 return status;
574}
575
576static efi_status_t
577efi_thunk_query_capsule_caps(efi_capsule_header_t **capsules,
578 unsigned long count, u64 *max_size,
579 int *reset_type)
580{
581 /*
582 * To properly support this function we would need to repackage
583 * 'capsules' because the firmware doesn't understand 64-bit
584 * pointers.
585 */
586 return EFI_UNSUPPORTED;
587}
588
589void efi_thunk_runtime_setup(void)
590{
591 efi.get_time = efi_thunk_get_time;
592 efi.set_time = efi_thunk_set_time;
593 efi.get_wakeup_time = efi_thunk_get_wakeup_time;
594 efi.set_wakeup_time = efi_thunk_set_wakeup_time;
595 efi.get_variable = efi_thunk_get_variable;
596 efi.get_next_variable = efi_thunk_get_next_variable;
597 efi.set_variable = efi_thunk_set_variable;
598 efi.get_next_high_mono_count = efi_thunk_get_next_high_mono_count;
599 efi.reset_system = efi_thunk_reset_system;
600 efi.query_variable_info = efi_thunk_query_variable_info;
601 efi.update_capsule = efi_thunk_update_capsule;
602 efi.query_capsule_caps = efi_thunk_query_capsule_caps;
603}
604#endif /* CONFIG_EFI_MIXED */
diff --git a/arch/x86/platform/efi/efi_stub_64.S b/arch/x86/platform/efi/efi_stub_64.S
index 88073b140298..65b787a9fc4e 100644
--- a/arch/x86/platform/efi/efi_stub_64.S
+++ b/arch/x86/platform/efi/efi_stub_64.S
@@ -7,6 +7,10 @@
7 */ 7 */
8 8
9#include <linux/linkage.h> 9#include <linux/linkage.h>
10#include <asm/segment.h>
11#include <asm/msr.h>
12#include <asm/processor-flags.h>
13#include <asm/page_types.h>
10 14
11#define SAVE_XMM \ 15#define SAVE_XMM \
12 mov %rsp, %rax; \ 16 mov %rsp, %rax; \
@@ -164,7 +168,160 @@ ENTRY(efi_call6)
164 ret 168 ret
165ENDPROC(efi_call6) 169ENDPROC(efi_call6)
166 170
171#ifdef CONFIG_EFI_MIXED
172
173/*
174 * We run this function from the 1:1 mapping.
175 *
176 * This function must be invoked with a 1:1 mapped stack.
177 */
178ENTRY(__efi64_thunk)
179 subq $32, %rsp
180 movl %esi, 0x0(%rsp)
181 movl %edx, 0x4(%rsp)
182 movl %ecx, 0x8(%rsp)
183 movq %r8, %rsi
184 movl %esi, 0xc(%rsp)
185 movq %r9, %rsi
186 movl %esi, 0x10(%rsp)
187
188 sgdt save_gdt(%rip)
189
190 leaq 1f(%rip), %rbx
191 movq %rbx, func_rt_ptr(%rip)
192
193 /* Switch to gdt with 32-bit segments */
194 movl 40(%rsp), %eax
195 lgdt (%rax)
196
197 leaq efi_enter32(%rip), %rax
198 pushq $__KERNEL_CS
199 pushq %rax
200 lretq
201
2021: addq $32, %rsp
203
204 lgdt save_gdt(%rip)
205
206 /*
207 * Convert 32-bit status code into 64-bit.
208 */
209 test %rax, %rax
210 jz 1f
211 movl %eax, %ecx
212 andl $0x0fffffff, %ecx
213 andl $0xf0000000, %eax
214 shl $32, %rax
215 or %rcx, %rax
2161:
217 ret
218ENDPROC(__efi64_thunk)
219
220ENTRY(efi_exit32)
221 xorq %rax, %rax
222 movl %eax, %ds
223 movl %eax, %es
224 movl %eax, %ss
225
226 movq func_rt_ptr(%rip), %rax
227 push %rax
228 mov %rdi, %rax
229 ret
230ENDPROC(efi_exit32)
231
232 .code32
233/*
234 * EFI service pointer must be in %edi.
235 *
236 * The stack should represent the 32-bit calling convention.
237 */
238ENTRY(efi_enter32)
239 movl $__KERNEL_DS, %eax
240 movl %eax, %ds
241 movl %eax, %es
242 movl %eax, %ss
243
244 /* Reload pgtables */
245 movl %cr3, %eax
246 movl %eax, %cr3
247
248 /* Disable paging */
249 movl %cr0, %eax
250 btrl $X86_CR0_PG_BIT, %eax
251 movl %eax, %cr0
252
253 /* Disable long mode via EFER */
254 movl $MSR_EFER, %ecx
255 rdmsr
256 btrl $_EFER_LME, %eax
257 wrmsr
258
259 call *%edi
260
261 /* We must preserve return value */
262 movl %eax, %edi
263
264 /*
265 * Some firmware will return with interrupts enabled. Be sure to
266 * disable them before we switch GDTs.
267 */
268 cli
269
270 movl 44(%esp), %eax
271 movl %eax, 2(%eax)
272 lgdtl (%eax)
273
274 movl %cr4, %eax
275 btsl $(X86_CR4_PAE_BIT), %eax
276 movl %eax, %cr4
277
278 movl %cr3, %eax
279 movl %eax, %cr3
280
281 movl $MSR_EFER, %ecx
282 rdmsr
283 btsl $_EFER_LME, %eax
284 wrmsr
285
286 xorl %eax, %eax
287 lldt %ax
288
289 movl 48(%esp), %eax
290 pushl $__KERNEL_CS
291 pushl %eax
292
293 /* Enable paging */
294 movl %cr0, %eax
295 btsl $X86_CR0_PG_BIT, %eax
296 movl %eax, %cr0
297 lret
298ENDPROC(efi_enter32)
299
300 .data
301 .balign 8
302 .global efi32_boot_gdt
303efi32_boot_gdt: .word 0
304 .quad 0
305
306save_gdt: .word 0
307 .quad 0
308func_rt_ptr: .quad 0
309
310 .global efi_gdt64
311efi_gdt64:
312 .word efi_gdt64_end - efi_gdt64
313 .long 0 /* Filled out by user */
314 .word 0
315 .quad 0x0000000000000000 /* NULL descriptor */
316 .quad 0x00af9a000000ffff /* __KERNEL_CS */
317 .quad 0x00cf92000000ffff /* __KERNEL_DS */
318 .quad 0x0080890000000000 /* TS descriptor */
319 .quad 0x0000000000000000 /* TS continued */
320efi_gdt64_end:
321#endif /* CONFIG_EFI_MIXED */
322
167 .data 323 .data
168ENTRY(efi_scratch) 324ENTRY(efi_scratch)
169 .fill 3,8,0 325 .fill 3,8,0
170 .byte 0 326 .byte 0
327 .quad 0
diff --git a/arch/x86/platform/efi/efi_thunk_64.S b/arch/x86/platform/efi/efi_thunk_64.S
new file mode 100644
index 000000000000..8806fa73e6e6
--- /dev/null
+++ b/arch/x86/platform/efi/efi_thunk_64.S
@@ -0,0 +1,65 @@
1/*
2 * Copyright (C) 2014 Intel Corporation; author Matt Fleming
3 */
4
5#include <linux/linkage.h>
6#include <asm/page_types.h>
7
8 .text
9 .code64
10ENTRY(efi64_thunk)
11 push %rbp
12 push %rbx
13
14 /*
15 * Switch to 1:1 mapped 32-bit stack pointer.
16 */
17 movq %rsp, efi_saved_sp(%rip)
18 movq efi_scratch+25(%rip), %rsp
19
20 /*
21 * Calculate the physical address of the kernel text.
22 */
23 movq $__START_KERNEL_map, %rax
24 subq phys_base(%rip), %rax
25
26 /*
27 * Push some physical addresses onto the stack. This is easier
28 * to do now in a code64 section while the assembler can address
29 * 64-bit values. Note that all the addresses on the stack are
30 * 32-bit.
31 */
32 subq $16, %rsp
33 leaq efi_exit32(%rip), %rbx
34 subq %rax, %rbx
35 movl %ebx, 8(%rsp)
36 leaq efi_gdt64(%rip), %rbx
37 subq %rax, %rbx
38 movl %ebx, 2(%ebx)
39 movl %ebx, 4(%rsp)
40 leaq efi_gdt32(%rip), %rbx
41 subq %rax, %rbx
42 movl %ebx, 2(%ebx)
43 movl %ebx, (%rsp)
44
45 leaq __efi64_thunk(%rip), %rbx
46 subq %rax, %rbx
47 call *%rbx
48
49 movq efi_saved_sp(%rip), %rsp
50 pop %rbx
51 pop %rbp
52 retq
53ENDPROC(efi64_thunk)
54
55 .data
56efi_gdt32:
57 .word efi_gdt32_end - efi_gdt32
58 .long 0 /* Filled out above */
59 .word 0
60 .quad 0x0000000000000000 /* NULL descriptor */
61 .quad 0x00cf9a000000ffff /* __KERNEL_CS */
62 .quad 0x00cf93000000ffff /* __KERNEL_DS */
63efi_gdt32_end:
64
65efi_saved_sp: .quad 0