Skip to content

Commit 81a1da8

Browse files
KAGA-KOKOopsiff
authored andcommitted
x86/boot/32: Temporarily map initrd for microcode loading
stable inclusion from stable-v6.6.82 category: bugfix bugzilla: deepin-community#665 commit 4c585af upstream Early microcode loading on 32-bit runs in physical address mode because the initrd is not covered by the initial page tables. That results in a horrible mess all over the microcode loader code. Provide a temporary mapping for the initrd in the initial page tables by appending it to the actual initial mapping starting with a new PGD or PMD depending on the configured page table levels ([non-]PAE). The page table entries are located after _brk_end so they are not permanently using memory space. The mapping is invalidated right away in i386_start_kernel() after the early microcode loader has run. This prepares for removing the physical address mode oddities from all over the microcode loader code, which in turn allows further cleanups. Provide the map and unmap code and document the place where the microcode loader needs to be invoked with a comment. Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de> Link: https://lore.kernel.org/r/20231017211722.292291436@linutronix.de Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> (cherry picked from commit c92bd95)
1 parent 2af5caa commit 81a1da8

2 files changed

Lines changed: 52 additions & 2 deletions

File tree

arch/x86/include/asm/microcode.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ static inline void load_ucode_ap(void) { }
2323
static inline void microcode_bsp_resume(void) { }
2424
#endif
2525

26+
extern unsigned long initrd_start_early;
27+
2628
#ifdef CONFIG_CPU_SUP_INTEL
2729
/* Intel specific microcode defines. Public for IFS */
2830
struct microcode_header_intel {

arch/x86/kernel/head32.c

Lines changed: 50 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,32 @@ static void __init i386_default_early_setup(void)
3030
x86_init.mpparse.setup_ioapic_ids = setup_ioapic_ids_from_mpc;
3131
}
3232

33+
#ifdef CONFIG_MICROCODE_INITRD32
34+
unsigned long __initdata initrd_start_early;
35+
static pte_t __initdata *initrd_pl2p_start, *initrd_pl2p_end;
36+
37+
static void zap_early_initrd_mapping(void)
38+
{
39+
pte_t *pl2p = initrd_pl2p_start;
40+
41+
for (; pl2p < initrd_pl2p_end; pl2p++) {
42+
*pl2p = (pte_t){ .pte = 0 };
43+
44+
if (!IS_ENABLED(CONFIG_X86_PAE))
45+
*(pl2p + ((PAGE_OFFSET >> PGDIR_SHIFT))) = (pte_t) {.pte = 0};
46+
}
47+
}
48+
#else
49+
static inline void zap_early_initrd_mapping(void) { }
50+
#endif
51+
3352
asmlinkage __visible void __init __noreturn i386_start_kernel(void)
3453
{
3554
/* Make sure IDT is set up before any exception happens */
3655
idt_setup_early_handler();
3756

3857
load_ucode_bsp();
58+
zap_early_initrd_mapping();
3959

4060
cr4_init_shadow();
4161

@@ -108,9 +128,9 @@ static __init __no_stack_protector pte_t init_map(pte_t pte, pte_t **ptep, pl2_t
108128
void __init __no_stack_protector mk_early_pgtbl_32(void)
109129
{
110130
/* Enough space to fit pagetables for the low memory linear map */
111-
const unsigned long limit = __pa_nodebug(_end) +
112-
(PAGE_TABLE_SIZE(LOWMEM_PAGES) << PAGE_SHIFT);
131+
unsigned long limit = __pa_nodebug(_end) + (PAGE_TABLE_SIZE(LOWMEM_PAGES) << PAGE_SHIFT);
113132
pte_t pte, *ptep = (pte_t *)__pa_nodebug(__brk_base);
133+
struct boot_params __maybe_unused *params;
114134
pl2_t *pl2p = (pl2_t *)__pa_nodebug(pl2_base);
115135
unsigned long *ptr;
116136

@@ -123,4 +143,32 @@ void __init __no_stack_protector mk_early_pgtbl_32(void)
123143

124144
ptr = (unsigned long *)__pa_nodebug(&_brk_end);
125145
*ptr = (unsigned long)ptep + PAGE_OFFSET;
146+
147+
#ifdef CONFIG_MICROCODE_INITRD32
148+
/* Running on a hypervisor? */
149+
if (native_cpuid_ecx(1) & BIT(31))
150+
return;
151+
152+
params = (struct boot_params *)__pa_nodebug(&boot_params);
153+
if (!params->hdr.ramdisk_size || !params->hdr.ramdisk_image)
154+
return;
155+
156+
/* Save the virtual start address */
157+
ptr = (unsigned long *)__pa_nodebug(&initrd_start_early);
158+
*ptr = (pte.pte & PTE_PFN_MASK) + PAGE_OFFSET;
159+
*ptr += ((unsigned long)params->hdr.ramdisk_image) & ~PAGE_MASK;
160+
161+
/* Save PLP2 for cleanup */
162+
ptr = (unsigned long *)__pa_nodebug(&initrd_pl2p_start);
163+
*ptr = (unsigned long)pl2p + PAGE_OFFSET;
164+
165+
limit = (unsigned long)params->hdr.ramdisk_image;
166+
pte.pte = PTE_IDENT_ATTR | PFN_ALIGN(limit);
167+
limit = (unsigned long)params->hdr.ramdisk_image + params->hdr.ramdisk_size;
168+
169+
init_map(pte, &ptep, &pl2p, limit);
170+
171+
ptr = (unsigned long *)__pa_nodebug(&initrd_pl2p_end);
172+
*ptr = (unsigned long)pl2p + PAGE_OFFSET;
173+
#endif
126174
}

0 commit comments

Comments
 (0)