^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * linux/arch/i386/kernel/head32.c -- prepare to run common code
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 2000 Andrea Arcangeli <andrea@suse.de> SuSE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Copyright (C) 2007 Eric Biederman <ebiederm@xmission.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/start_kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/mm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/memblock.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <asm/desc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <asm/setup.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <asm/sections.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <asm/e820/api.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <asm/page.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <asm/apic.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <asm/io_apic.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <asm/bios_ebda.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <asm/tlbflush.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <asm/bootparam_utils.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) static void __init i386_default_early_setup(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) /* Initialize 32bit specific setup functions */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) x86_init.resources.reserve_resources = i386_reserve_resources;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) x86_init.mpparse.setup_ioapic_ids = setup_ioapic_ids_from_mpc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) asmlinkage __visible void __init i386_start_kernel(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) /* Make sure IDT is set up before any exception happens */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) idt_setup_early_handler();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) cr4_init_shadow();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) sanitize_boot_params(&boot_params);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) x86_early_init_platform_quirks();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) /* Call the subarch specific early setup function */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) switch (boot_params.hdr.hardware_subarch) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) case X86_SUBARCH_INTEL_MID:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) x86_intel_mid_early_setup();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) case X86_SUBARCH_CE4100:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) x86_ce4100_early_setup();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) i386_default_early_setup();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) start_kernel();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) * Initialize page tables. This creates a PDE and a set of page
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) * tables, which are located immediately beyond __brk_base. The variable
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) * _brk_end is set up to point to the first "safe" location.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) * Mappings are created both at virtual address 0 (identity mapping)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) * and PAGE_OFFSET for up to _end.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) * In PAE mode initial_page_table is statically defined to contain
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) * enough entries to cover the VMSPLIT option (that is the top 1, 2 or 3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) * entries). The identity mapping is handled by pointing two PGD entries
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) * to the first kernel PMD. Note the upper half of each PMD or PTE are
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) * always zero at this stage.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) void __init mk_early_pgtbl_32(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) #ifdef __pa
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) #undef __pa
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) #define __pa(x) ((unsigned long)(x) - PAGE_OFFSET)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) pte_t pte, *ptep;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) unsigned long *ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) /* Enough space to fit pagetables for the low memory linear map */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) const unsigned long limit = __pa(_end) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) (PAGE_TABLE_SIZE(LOWMEM_PAGES) << PAGE_SHIFT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) #ifdef CONFIG_X86_PAE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) pmd_t pl2, *pl2p = (pmd_t *)__pa(initial_pg_pmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) #define SET_PL2(pl2, val) { (pl2).pmd = (val); }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) pgd_t pl2, *pl2p = (pgd_t *)__pa(initial_page_table);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) #define SET_PL2(pl2, val) { (pl2).pgd = (val); }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) ptep = (pte_t *)__pa(__brk_base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) pte.pte = PTE_IDENT_ATTR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) while ((pte.pte & PTE_PFN_MASK) < limit) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) SET_PL2(pl2, (unsigned long)ptep | PDE_IDENT_ATTR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) *pl2p = pl2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) #ifndef CONFIG_X86_PAE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) /* Kernel PDE entry */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) *(pl2p + ((PAGE_OFFSET >> PGDIR_SHIFT))) = pl2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) for (i = 0; i < PTRS_PER_PTE; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) *ptep = pte;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) pte.pte += PAGE_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) ptep++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) pl2p++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) ptr = (unsigned long *)__pa(&max_pfn_mapped);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) /* Can't use pte_pfn() since it's a call with CONFIG_PARAVIRT */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) *ptr = (pte.pte & PTE_PFN_MASK) >> PAGE_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) ptr = (unsigned long *)__pa(&_brk_end);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) *ptr = (unsigned long)ptep + PAGE_OFFSET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119)