1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* |
3 | * Extensible Firmware Interface |
4 | * |
5 | * Based on Extensible Firmware Interface Specification version 1.0 |
6 | * |
7 | * Copyright (C) 1999 VA Linux Systems |
8 | * Copyright (C) 1999 Walt Drummond <drummond@valinux.com> |
9 | * Copyright (C) 1999-2002 Hewlett-Packard Co. |
10 | * David Mosberger-Tang <davidm@hpl.hp.com> |
11 | * Stephane Eranian <eranian@hpl.hp.com> |
12 | * |
13 | * All EFI Runtime Services are not implemented yet as EFI only |
14 | * supports physical mode addressing on SoftSDV. This is to be fixed |
15 | * in a future version. --drummond 1999-07-20 |
16 | * |
17 | * Implemented EFI runtime services and virtual mode calls. --davidm |
18 | * |
19 | * Goutham Rao: <goutham.rao@intel.com> |
20 | * Skip non-WB memory and ignore empty memory ranges. |
21 | */ |
22 | |
23 | #include <linux/kernel.h> |
24 | #include <linux/types.h> |
25 | #include <linux/ioport.h> |
26 | #include <linux/efi.h> |
27 | #include <linux/pgtable.h> |
28 | |
29 | #include <asm/io.h> |
30 | #include <asm/desc.h> |
31 | #include <asm/page.h> |
32 | #include <asm/set_memory.h> |
33 | #include <asm/tlbflush.h> |
34 | #include <asm/efi.h> |
35 | |
36 | void __init efi_map_region(efi_memory_desc_t *md) |
37 | { |
38 | u64 start_pfn, end_pfn, end; |
39 | unsigned long size; |
40 | void *va; |
41 | |
42 | start_pfn = PFN_DOWN(md->phys_addr); |
43 | size = md->num_pages << PAGE_SHIFT; |
44 | end = md->phys_addr + size; |
45 | end_pfn = PFN_UP(end); |
46 | |
47 | if (pfn_range_is_mapped(start_pfn, end_pfn)) { |
48 | va = __va(md->phys_addr); |
49 | |
50 | if (!(md->attribute & EFI_MEMORY_WB)) |
51 | set_memory_uc(addr: (unsigned long)va, numpages: md->num_pages); |
52 | } else { |
53 | va = ioremap_cache(offset: md->phys_addr, size); |
54 | } |
55 | |
56 | md->virt_addr = (unsigned long)va; |
57 | if (!va) |
58 | pr_err("ioremap of 0x%llX failed!\n" , md->phys_addr); |
59 | } |
60 | |
61 | /* |
62 | * To make EFI call EFI runtime service in physical addressing mode we need |
63 | * prolog/epilog before/after the invocation to claim the EFI runtime service |
64 | * handler exclusively and to duplicate a memory mapping in low memory space, |
65 | * say 0 - 3G. |
66 | */ |
67 | |
68 | int __init efi_alloc_page_tables(void) |
69 | { |
70 | return 0; |
71 | } |
72 | |
73 | void efi_sync_low_kernel_mappings(void) {} |
74 | |
75 | void __init efi_dump_pagetable(void) |
76 | { |
77 | #ifdef CONFIG_EFI_PGT_DUMP |
78 | ptdump_walk_pgd_level(NULL, mm: &init_mm); |
79 | #endif |
80 | } |
81 | |
82 | int __init efi_setup_page_tables(unsigned long pa_memmap, unsigned num_pages) |
83 | { |
84 | return 0; |
85 | } |
86 | |
87 | void __init efi_map_region_fixed(efi_memory_desc_t *md) {} |
88 | void __init parse_efi_setup(u64 phys_addr, u32 data_len) {} |
89 | |
90 | efi_status_t efi_call_svam(efi_runtime_services_t * const *, |
91 | u32, u32, u32, void *, u32); |
92 | |
93 | efi_status_t __init efi_set_virtual_address_map(unsigned long memory_map_size, |
94 | unsigned long descriptor_size, |
95 | u32 descriptor_version, |
96 | efi_memory_desc_t *virtual_map, |
97 | unsigned long systab_phys) |
98 | { |
99 | const efi_system_table_t *systab = (efi_system_table_t *)systab_phys; |
100 | struct desc_ptr gdt_descr; |
101 | efi_status_t status; |
102 | unsigned long flags; |
103 | pgd_t *save_pgd; |
104 | |
105 | /* Current pgd is swapper_pg_dir, we'll restore it later: */ |
106 | save_pgd = swapper_pg_dir; |
107 | load_cr3(pgdir: initial_page_table); |
108 | __flush_tlb_all(); |
109 | |
110 | gdt_descr.address = get_cpu_gdt_paddr(cpu: 0); |
111 | gdt_descr.size = GDT_SIZE - 1; |
112 | load_gdt(dtr: &gdt_descr); |
113 | |
114 | /* Disable interrupts around EFI calls: */ |
115 | local_irq_save(flags); |
116 | status = efi_call_svam(&systab->runtime, |
117 | memory_map_size, descriptor_size, |
118 | descriptor_version, virtual_map, |
119 | __pa(&efi.runtime)); |
120 | local_irq_restore(flags); |
121 | |
122 | load_fixmap_gdt(0); |
123 | load_cr3(pgdir: save_pgd); |
124 | __flush_tlb_all(); |
125 | |
126 | return status; |
127 | } |
128 | |
129 | void __init efi_runtime_update_mappings(void) |
130 | { |
131 | if (__supported_pte_mask & _PAGE_NX) { |
132 | efi_memory_desc_t *md; |
133 | |
134 | /* Make EFI runtime service code area executable */ |
135 | for_each_efi_memory_desc(md) { |
136 | if (md->type != EFI_RUNTIME_SERVICES_CODE) |
137 | continue; |
138 | |
139 | set_memory_x(addr: md->virt_addr, numpages: md->num_pages); |
140 | } |
141 | } |
142 | } |
143 | |
144 | void arch_efi_call_virt_setup(void) |
145 | { |
146 | efi_fpu_begin(); |
147 | firmware_restrict_branch_speculation_start(); |
148 | } |
149 | |
150 | void arch_efi_call_virt_teardown(void) |
151 | { |
152 | firmware_restrict_branch_speculation_end(); |
153 | efi_fpu_end(); |
154 | } |
155 | |