History

Revert "x86-64/efi: Use EFI to deal with platform wall clock (again)"

This reverts commit bd52276fa1d4 ("x86-64/efi: Use EFI to deal with platform wall clock (again)"), and the two supporting commits: da5a108d05b4: "x86/kernel: remove tboot 1:1 page table creation code" 185034e72d59: "x86, efi: 1:1 pagetable mapping for virtual EFI calls") as they all depend semantically on commit 53b87cf088e2 ("x86, mm: Include the entire kernel memory map in trampoline_pgd") that got reverted earlier due to the problems it caused. This was pointed out by Yinghai Lu, and verified by me on my Macbook Air that uses EFI.

Linus Torvalds committed 13 years ago

Commit 11520e51 parent 5bd665f7 files · +116 −55Browse files

Unified · Split

7 files
  1. arch/x86/include/asm/efi.h +7 −21
  2. arch/x86/kernel/tboot.c +73 −5
  3. arch/x86/mm/pageattr.c +4 −6
  4. arch/x86/platform/efi/efi.c +26 −4
  5. arch/x86/platform/efi/efi_64.c +0 −15
  6. include/linux/efi.h +2 −0
  7. init/main.c +4 −4
arch/x86/include/asm/efi.h+7−21
@@ -69,37 +69,23 @@ extern u64 efi_call6(void *fp, u64 arg1, u64 arg2, u64 arg3, · 68 unmodified lines
69 efi_call6((void *)(f), (u64)(a1), (u64)(a2), (u64)(a3), \69 efi_call6((void *)(f), (u64)(a1), (u64)(a2), (u64)(a3), \
70 (u64)(a4), (u64)(a5), (u64)(a6))70 (u64)(a4), (u64)(a5), (u64)(a6))
71 71
72extern unsigned long efi_call_virt_prelog(void);
73extern void efi_call_virt_epilog(unsigned long);
74
75#define efi_callx(x, func, ...) \
76 ({ \
77 efi_status_t __status; \
78 unsigned long __pgd; \
79 \
80 __pgd = efi_call_virt_prelog(); \
81 __status = efi_call##x(func, __VA_ARGS__); \
82 efi_call_virt_epilog(__pgd); \
83 __status; \
84 })
85
86#define efi_call_virt0(f) \72#define efi_call_virt0(f) \
87 efi_callx(0, (void *)(efi.systab->runtime->f))73 efi_call0((void *)(efi.systab->runtime->f))
88#define efi_call_virt1(f, a1) \74#define efi_call_virt1(f, a1) \
89 efi_callx(1, (void *)(efi.systab->runtime->f), (u64)(a1))75 efi_call1((void *)(efi.systab->runtime->f), (u64)(a1))
90#define efi_call_virt2(f, a1, a2) \76#define efi_call_virt2(f, a1, a2) \
91 efi_callx(2, (void *)(efi.systab->runtime->f), (u64)(a1), (u64)(a2))77 efi_call2((void *)(efi.systab->runtime->f), (u64)(a1), (u64)(a2))
92#define efi_call_virt3(f, a1, a2, a3) \78#define efi_call_virt3(f, a1, a2, a3) \
93 efi_callx(3, (void *)(efi.systab->runtime->f), (u64)(a1), (u64)(a2), \79 efi_call3((void *)(efi.systab->runtime->f), (u64)(a1), (u64)(a2), \
94 (u64)(a3))80 (u64)(a3))
95#define efi_call_virt4(f, a1, a2, a3, a4) \81#define efi_call_virt4(f, a1, a2, a3, a4) \
96 efi_callx(4, (void *)(efi.systab->runtime->f), (u64)(a1), (u64)(a2), \82 efi_call4((void *)(efi.systab->runtime->f), (u64)(a1), (u64)(a2), \
97 (u64)(a3), (u64)(a4))83 (u64)(a3), (u64)(a4))
98#define efi_call_virt5(f, a1, a2, a3, a4, a5) \84#define efi_call_virt5(f, a1, a2, a3, a4, a5) \
99 efi_callx(5, (void *)(efi.systab->runtime->f), (u64)(a1), (u64)(a2), \85 efi_call5((void *)(efi.systab->runtime->f), (u64)(a1), (u64)(a2), \
100 (u64)(a3), (u64)(a4), (u64)(a5))86 (u64)(a3), (u64)(a4), (u64)(a5))
101#define efi_call_virt6(f, a1, a2, a3, a4, a5, a6) \87#define efi_call_virt6(f, a1, a2, a3, a4, a5, a6) \
102 efi_callx(6, (void *)(efi.systab->runtime->f), (u64)(a1), (u64)(a2), \88 efi_call6((void *)(efi.systab->runtime->f), (u64)(a1), (u64)(a2), \
103 (u64)(a3), (u64)(a4), (u64)(a5), (u64)(a6))89 (u64)(a3), (u64)(a4), (u64)(a5), (u64)(a6))
104 90
105extern void __iomem *efi_ioremap(unsigned long addr, unsigned long size,91extern void __iomem *efi_ioremap(unsigned long addr, unsigned long size,
arch/x86/kernel/tboot.c+73−5
@@ -103,13 +103,71 @@ void __init tboot_probe(void) · 102 unmodified lines
103 pr_debug("tboot_size: 0x%x\n", tboot->tboot_size);103 pr_debug("tboot_size: 0x%x\n", tboot->tboot_size);
104}104}
105 105
106static pgd_t *tboot_pg_dir;
107static struct mm_struct tboot_mm = {
108 .mm_rb = RB_ROOT,
109 .pgd = swapper_pg_dir,
110 .mm_users = ATOMIC_INIT(2),
111 .mm_count = ATOMIC_INIT(1),
112 .mmap_sem = __RWSEM_INITIALIZER(init_mm.mmap_sem),
113 .page_table_lock = __SPIN_LOCK_UNLOCKED(init_mm.page_table_lock),
114 .mmlist = LIST_HEAD_INIT(init_mm.mmlist),
115};
116
106static inline void switch_to_tboot_pt(void)117static inline void switch_to_tboot_pt(void)
107{118{
108#ifdef CONFIG_X86_32119 write_cr3(virt_to_phys(tboot_pg_dir));
109 load_cr3(initial_page_table);120}
110#else121
111 write_cr3(real_mode_header->trampoline_pgd);122static int map_tboot_page(unsigned long vaddr, unsigned long pfn,
112#endif123 pgprot_t prot)
124{
125 pgd_t *pgd;
126 pud_t *pud;
127 pmd_t *pmd;
128 pte_t *pte;
129
130 pgd = pgd_offset(&tboot_mm, vaddr);
131 pud = pud_alloc(&tboot_mm, pgd, vaddr);
132 if (!pud)
133 return -1;
134 pmd = pmd_alloc(&tboot_mm, pud, vaddr);
135 if (!pmd)
136 return -1;
137 pte = pte_alloc_map(&tboot_mm, NULL, pmd, vaddr);
138 if (!pte)
139 return -1;
140 set_pte_at(&tboot_mm, vaddr, pte, pfn_pte(pfn, prot));
141 pte_unmap(pte);
142 return 0;
143}
144
145static int map_tboot_pages(unsigned long vaddr, unsigned long start_pfn,
146 unsigned long nr)
147{
148 /* Reuse the original kernel mapping */
149 tboot_pg_dir = pgd_alloc(&tboot_mm);
150 if (!tboot_pg_dir)
151 return -1;
152
153 for (; nr > 0; nr--, vaddr += PAGE_SIZE, start_pfn++) {
154 if (map_tboot_page(vaddr, start_pfn, PAGE_KERNEL_EXEC))
155 return -1;
156 }
157
158 return 0;
159}
160
161static void tboot_create_trampoline(void)
162{
163 u32 map_base, map_size;
164
165 /* Create identity map for tboot shutdown code. */
166 map_base = PFN_DOWN(tboot->tboot_base);
167 map_size = PFN_UP(tboot->tboot_size);
168 if (map_tboot_pages(map_base << PAGE_SHIFT, map_base, map_size))
169 panic("tboot: Error mapping tboot pages (mfns) @ 0x%x, 0x%x\n",
170 map_base, map_size);
113}171}
114 172
115#ifdef CONFIG_ACPI_SLEEP173#ifdef CONFIG_ACPI_SLEEP
@@ -167,6 +225,14 @@ void tboot_shutdown(u32 shutdown_type) · 51 unmodified lines
167 if (!tboot_enabled())225 if (!tboot_enabled())
168 return;226 return;
169 227
228 /*
229 * if we're being called before the 1:1 mapping is set up then just
230 * return and let the normal shutdown happen; this should only be
231 * due to very early panic()
232 */
233 if (!tboot_pg_dir)
234 return;
235
170 /* if this is S3 then set regions to MAC */236 /* if this is S3 then set regions to MAC */
171 if (shutdown_type == TB_SHUTDOWN_S3)237 if (shutdown_type == TB_SHUTDOWN_S3)
172 if (tboot_setup_sleep())238 if (tboot_setup_sleep())
@@ -277,6 +343,8 @@ static __init int tboot_late_init(void) · 104 unmodified lines
277 if (!tboot_enabled())343 if (!tboot_enabled())
278 return 0;344 return 0;
279 345
346 tboot_create_trampoline();
347
280 atomic_set(&ap_wfs_count, 0);348 atomic_set(&ap_wfs_count, 0);
281 register_hotcpu_notifier(&tboot_cpu_notifier);349 register_hotcpu_notifier(&tboot_cpu_notifier);
282 350
arch/x86/mm/pageattr.c+4−6
@@ -919,13 +919,11 @@ static int change_page_attr_set_clr(unsigned long *addr, int numpages, · 918 unmodified lines
919 919
920 /*920 /*
921 * On success we use clflush, when the CPU supports it to921 * On success we use clflush, when the CPU supports it to
922 * avoid the wbindv. If the CPU does not support it, in the922 * avoid the wbindv. If the CPU does not support it and in the
923 * error case, and during early boot (for EFI) we fall back923 * error case we fall back to cpa_flush_all (which uses
924 * to cpa_flush_all (which uses wbinvd):924 * wbindv):
925 */925 */
926 if (early_boot_irqs_disabled)926 if (!ret && cpu_has_clflush) {
927 __cpa_flush_all((void *)(long)cache);
928 else if (!ret && cpu_has_clflush) {
929 if (cpa.flags & (CPA_PAGES_ARRAY | CPA_ARRAY)) {927 if (cpa.flags & (CPA_PAGES_ARRAY | CPA_ARRAY)) {
930 cpa_flush_array(addr, numpages, cache,928 cpa_flush_array(addr, numpages, cache,
931 cpa.flags, pages);929 cpa.flags, pages);
arch/x86/platform/efi/efi.c+26−4
@@ -239,7 +239,22 @@ static efi_status_t __init phys_efi_set_virtual_address_map( · 238 unmodified lines
239 return status;239 return status;
240}240}
241 241
242static int efi_set_rtc_mmss(unsigned long nowtime)242static efi_status_t __init phys_efi_get_time(efi_time_t *tm,
243 efi_time_cap_t *tc)
244{
245 unsigned long flags;
246 efi_status_t status;
247
248 spin_lock_irqsave(&rtc_lock, flags);
249 efi_call_phys_prelog();
250 status = efi_call_phys2(efi_phys.get_time, virt_to_phys(tm),
251 virt_to_phys(tc));
252 efi_call_phys_epilog();
253 spin_unlock_irqrestore(&rtc_lock, flags);
254 return status;
255}
256
257int efi_set_rtc_mmss(unsigned long nowtime)
243{258{
244 int real_seconds, real_minutes;259 int real_seconds, real_minutes;
245 efi_status_t status;260 efi_status_t status;
@@ -268,7 +283,7 @@ static int efi_set_rtc_mmss(unsigned long nowtime) · 22 unmodified lines
268 return 0;283 return 0;
269}284}
270 285
271static unsigned long efi_get_time(void)286unsigned long efi_get_time(void)
272{287{
273 efi_status_t status;288 efi_status_t status;
274 efi_time_t eft;289 efi_time_t eft;
@@ -624,13 +639,18 @@ static int __init efi_runtime_init(void) · 349 unmodified lines
624 }639 }
625 /*640 /*
626 * We will only need *early* access to the following641 * We will only need *early* access to the following
627 * EFI runtime service before set_virtual_address_map642 * two EFI runtime services before set_virtual_address_map
628 * is invoked.643 * is invoked.
629 */644 */
645 efi_phys.get_time = (efi_get_time_t *)runtime->get_time;
630 efi_phys.set_virtual_address_map =646 efi_phys.set_virtual_address_map =
631 (efi_set_virtual_address_map_t *)647 (efi_set_virtual_address_map_t *)
632 runtime->set_virtual_address_map;648 runtime->set_virtual_address_map;
633 649 /*
650 * Make efi_get_time can be called before entering
651 * virtual mode.
652 */
653 efi.get_time = phys_efi_get_time;
634 early_iounmap(runtime, sizeof(efi_runtime_services_t));654 early_iounmap(runtime, sizeof(efi_runtime_services_t));
635 655
636 return 0;656 return 0;
@@ -716,10 +736,12 @@ void __init efi_init(void) · 79 unmodified lines
716 efi_enabled = 0;736 efi_enabled = 0;
717 return;737 return;
718 }738 }
739#ifdef CONFIG_X86_32
719 if (efi_is_native()) {740 if (efi_is_native()) {
720 x86_platform.get_wallclock = efi_get_time;741 x86_platform.get_wallclock = efi_get_time;
721 x86_platform.set_wallclock = efi_set_rtc_mmss;742 x86_platform.set_wallclock = efi_set_rtc_mmss;
722 }743 }
744#endif
723 745
724#if EFI_DEBUG746#if EFI_DEBUG
725 print_efi_memmap();747 print_efi_memmap();
arch/x86/platform/efi/efi_64.c+0−15
@@ -58,21 +58,6 @@ static void __init early_code_mapping_set_exec(int executable) · 57 unmodified lines
58 }58 }
59}59}
60 60
61unsigned long efi_call_virt_prelog(void)
62{
63 unsigned long saved;
64
65 saved = read_cr3();
66 write_cr3(real_mode_header->trampoline_pgd);
67
68 return saved;
69}
70
71void efi_call_virt_epilog(unsigned long saved)
72{
73 write_cr3(saved);
74}
75
76void __init efi_call_phys_prelog(void)61void __init efi_call_phys_prelog(void)
77{62{
78 unsigned long vaddress;63 unsigned long vaddress;
include/linux/efi.h+2−0
@@ -587,6 +587,8 @@ extern u64 efi_mem_attribute (unsigned long phys_addr, unsigned long size); · 586 unmodified lines
587extern int __init efi_uart_console_only (void);587extern int __init efi_uart_console_only (void);
588extern void efi_initialize_iomem_resources(struct resource *code_resource,588extern void efi_initialize_iomem_resources(struct resource *code_resource,
589 struct resource *data_resource, struct resource *bss_resource);589 struct resource *data_resource, struct resource *bss_resource);
590extern unsigned long efi_get_time(void);
591extern int efi_set_rtc_mmss(unsigned long nowtime);
590extern void efi_reserve_boot_services(void);592extern void efi_reserve_boot_services(void);
591extern struct efi_memory_map memmap;593extern struct efi_memory_map memmap;
592 594
init/main.c+4−4
@@ -463,10 +463,6 @@ static void __init mm_init(void) · 462 unmodified lines
463 percpu_init_late();463 percpu_init_late();
464 pgtable_cache_init();464 pgtable_cache_init();
465 vmalloc_init();465 vmalloc_init();
466#ifdef CONFIG_X86
467 if (efi_enabled)
468 efi_enter_virtual_mode();
469#endif
470}466}
471 467
472asmlinkage void __init start_kernel(void)468asmlinkage void __init start_kernel(void)
@@ -607,6 +603,10 @@ asmlinkage void __init start_kernel(void) · 134 unmodified lines
607 calibrate_delay();603 calibrate_delay();
608 pidmap_init();604 pidmap_init();
609 anon_vma_init();605 anon_vma_init();
606#ifdef CONFIG_X86
607 if (efi_enabled)
608 efi_enter_virtual_mode();
609#endif
610 thread_info_cache_init();610 thread_info_cache_init();
611 cred_init();611 cred_init();
612 fork_init(totalram_pages);612 fork_init(totalram_pages);