xref: /linux/arch/x86/realmode/init.c (revision 805185b7c7a1069e407b6f7b3bc98e44d415f484)
1 // SPDX-License-Identifier: GPL-2.0
2 #include <linux/io.h>
3 #include <linux/slab.h>
4 #include <linux/memblock.h>
5 #include <linux/cc_platform.h>
6 #include <linux/pgtable.h>
7 
8 #include <asm/set_memory.h>
9 #include <asm/realmode.h>
10 #include <asm/tlbflush.h>
11 #include <asm/crash.h>
12 #include <asm/msr.h>
13 #include <asm/sev.h>
14 
15 struct real_mode_header *real_mode_header;
16 u32 *trampoline_cr4_features;
17 
18 /* Hold the pgd entry used on booting additional CPUs */
19 pgd_t trampoline_pgd_entry;
20 
21 void load_trampoline_pgtable(void)
22 {
23 #ifdef CONFIG_X86_32
24 	load_cr3(initial_page_table);
25 #else
26 	/*
27 	 * This function is called before exiting to real-mode and that will
28 	 * fail with CR4.PCIDE still set.
29 	 */
30 	if (boot_cpu_has(X86_FEATURE_PCID))
31 		cr4_clear_bits(X86_CR4_PCIDE);
32 
33 	write_cr3(real_mode_header->trampoline_pgd);
34 #endif
35 
36 	/*
37 	 * The CR3 write above will not flush global TLB entries.
38 	 * Stale, global entries from previous page tables may still be
39 	 * present.  Flush those stale entries.
40 	 *
41 	 * This ensures that memory accessed while running with
42 	 * trampoline_pgd is *actually* mapped into trampoline_pgd.
43 	 */
44 	__flush_tlb_all();
45 }
46 
47 void __init reserve_real_mode(void)
48 {
49 	phys_addr_t mem, limit = x86_init.resources.realmode_limit;
50 	size_t size = real_mode_size_needed();
51 
52 	if (!size)
53 		return;
54 
55 	WARN_ON(slab_is_available());
56 
57 	mem = memblock_phys_alloc_range(size, PAGE_SIZE, 0, limit);
58 	if (!mem)
59 		pr_info("No memory below %pa for the real-mode trampoline\n", &limit);
60 	else
61 		set_real_mode_mem(mem);
62 
63 	/*
64 	 * Unconditionally reserve the entire first 1M, see comment in
65 	 * setup_arch().
66 	 */
67 	memblock_reserve(0, SZ_1M);
68 
69 	memblock_clear_kho_scratch(0, SZ_1M);
70 }
71 
72 static void __init sme_sev_setup_real_mode(struct trampoline_header *th)
73 {
74 #ifdef CONFIG_AMD_MEM_ENCRYPT
75 	if (cc_platform_has(CC_ATTR_HOST_MEM_ENCRYPT))
76 		th->flags |= TH_FLAGS_SME_ACTIVE;
77 
78 	if (cc_platform_has(CC_ATTR_GUEST_STATE_ENCRYPT)) {
79 		/*
80 		 * Skip the call to verify_cpu() in secondary_startup_64 as it
81 		 * will cause #VC exceptions when the AP can't handle them yet.
82 		 */
83 		th->start = (u64) secondary_startup_64_no_verify;
84 
85 		if (sev_es_setup_ap_jump_table(real_mode_header))
86 			panic("Failed to get/update SEV-ES AP Jump Table");
87 	}
88 #endif
89 }
90 
91 static void __init setup_real_mode(void)
92 {
93 	u16 real_mode_seg;
94 	const u32 *rel;
95 	u32 count;
96 	unsigned char *base;
97 	unsigned long phys_base;
98 	struct trampoline_header *trampoline_header;
99 	size_t size = PAGE_ALIGN(real_mode_blob_end - real_mode_blob);
100 #ifdef CONFIG_X86_64
101 	u64 *trampoline_pgd;
102 	u64 efer;
103 	int i;
104 #endif
105 
106 	base = (unsigned char *)real_mode_header;
107 
108 	/*
109 	 * If SME is active, the trampoline area will need to be in
110 	 * decrypted memory in order to bring up other processors
111 	 * successfully. This is not needed for SEV.
112 	 */
113 	if (cc_platform_has(CC_ATTR_HOST_MEM_ENCRYPT))
114 		set_memory_decrypted((unsigned long)base, size >> PAGE_SHIFT);
115 
116 	memcpy(base, real_mode_blob, size);
117 
118 	phys_base = __pa(base);
119 	real_mode_seg = phys_base >> 4;
120 
121 	rel = (u32 *) real_mode_relocs;
122 
123 	/* 16-bit segment relocations. */
124 	count = *rel++;
125 	while (count--) {
126 		u16 *seg = (u16 *) (base + *rel++);
127 		*seg = real_mode_seg;
128 	}
129 
130 	/* 32-bit linear relocations. */
131 	count = *rel++;
132 	while (count--) {
133 		u32 *ptr = (u32 *) (base + *rel++);
134 		*ptr += phys_base;
135 	}
136 
137 	/* Must be performed *after* relocation. */
138 	trampoline_header = (struct trampoline_header *)
139 		__va(real_mode_header->trampoline_header);
140 
141 #ifdef CONFIG_X86_32
142 	trampoline_header->start = __pa_symbol(startup_32_smp);
143 	trampoline_header->gdt_limit = __BOOT_DS + 7;
144 	trampoline_header->gdt_base = __pa_symbol(boot_gdt);
145 #else
146 	/*
147 	 * Some AMD processors will #GP(0) if EFER.LMA is set in WRMSR
148 	 * so we need to mask it out.
149 	 */
150 	rdmsrq(MSR_EFER, efer);
151 	trampoline_header->efer = efer & ~EFER_LMA;
152 
153 	trampoline_header->start = (u64) secondary_startup_64;
154 	trampoline_cr4_features = &trampoline_header->cr4;
155 	*trampoline_cr4_features = mmu_cr4_features;
156 
157 	trampoline_header->flags = 0;
158 
159 	trampoline_lock = &trampoline_header->lock;
160 	*trampoline_lock = 0;
161 
162 	trampoline_pgd = (u64 *) __va(real_mode_header->trampoline_pgd);
163 
164 	/* Map the real mode stub as virtual == physical */
165 	trampoline_pgd[0] = trampoline_pgd_entry.pgd;
166 
167 	/*
168 	 * Include the entirety of the kernel mapping into the trampoline
169 	 * PGD.  This way, all mappings present in the normal kernel page
170 	 * tables are usable while running on trampoline_pgd.
171 	 */
172 	for (i = pgd_index(__PAGE_OFFSET); i < PTRS_PER_PGD; i++)
173 		trampoline_pgd[i] = init_top_pgt[i].pgd;
174 #endif
175 
176 	sme_sev_setup_real_mode(trampoline_header);
177 }
178 
179 /*
180  * reserve_real_mode() gets called very early, to guarantee the
181  * availability of low memory. This is before the proper kernel page
182  * tables are set up, so we cannot set page permissions in that
183  * function. Also trampoline code will be executed by APs so we
184  * need to mark it executable at do_pre_smp_initcalls() at least,
185  * thus run it as a early_initcall().
186  */
187 static void __init set_real_mode_permissions(void)
188 {
189 	unsigned char *base = (unsigned char *) real_mode_header;
190 	size_t size = PAGE_ALIGN(real_mode_blob_end - real_mode_blob);
191 
192 	size_t ro_size =
193 		PAGE_ALIGN(real_mode_header->ro_end) -
194 		__pa(base);
195 
196 	size_t text_size =
197 		PAGE_ALIGN(real_mode_header->ro_end) -
198 		real_mode_header->text_start;
199 
200 	unsigned long text_start =
201 		(unsigned long) __va(real_mode_header->text_start);
202 
203 	set_memory_nx((unsigned long) base, size >> PAGE_SHIFT);
204 	set_memory_ro((unsigned long) base, ro_size >> PAGE_SHIFT);
205 	set_memory_x((unsigned long) text_start, text_size >> PAGE_SHIFT);
206 }
207 
208 void __init init_real_mode(void)
209 {
210 	if (!real_mode_header)
211 		panic("Real mode trampoline was not allocated");
212 
213 	setup_real_mode();
214 	set_real_mode_permissions();
215 }
216 
217 static int __init do_init_real_mode(void)
218 {
219 	x86_platform.realmode_init();
220 	return 0;
221 }
222 early_initcall(do_init_real_mode);
223