1b2441318SGreg Kroah-Hartman/* SPDX-License-Identifier: GPL-2.0 */ 21da177e4SLinus Torvalds/* 31da177e4SLinus Torvalds * 41da177e4SLinus Torvalds * Copyright (C) 1991, 1992 Linus Torvalds 51da177e4SLinus Torvalds * 61da177e4SLinus Torvalds * Enhanced CPU detection and feature setting code by Mike Jagdis 71da177e4SLinus Torvalds * and Martin Mares, November 1997. 81da177e4SLinus Torvalds */ 91da177e4SLinus Torvalds 101da177e4SLinus Torvalds.text 1194ea9c05SMasahiro Yamada#include <linux/export.h> 121da177e4SLinus Torvalds#include <linux/threads.h> 138b2f7fffSSam Ravnborg#include <linux/init.h> 141da177e4SLinus Torvalds#include <linux/linkage.h> 151da177e4SLinus Torvalds#include <asm/segment.h> 160341c14dSJeremy Fitzhardinge#include <asm/page_types.h> 170341c14dSJeremy Fitzhardinge#include <asm/pgtable_types.h> 181da177e4SLinus Torvalds#include <asm/cache.h> 191da177e4SLinus Torvalds#include <asm/thread_info.h> 2086feeaa8SSam Ravnborg#include <asm/asm-offsets.h> 211da177e4SLinus Torvalds#include <asm/setup.h> 22551889a6SIan Campbell#include <asm/processor-flags.h> 238a50e513SH. Peter Anvin#include <asm/msr-index.h> 24cd4d09ecSBorislav Petkov#include <asm/cpufeatures.h> 2560a5317fSTejun Heo#include <asm/percpu.h> 264c5023a3SH. Peter Anvin#include <asm/nops.h> 273131ef39SJiri Slaby#include <asm/nospec-branch.h> 28fb148d83SAlexander Kuleshov#include <asm/bootparam.h> 291e620f9bSBoris Ostrovsky#include <asm/pgtable_32.h> 30551889a6SIan Campbell 31551889a6SIan Campbell/* Physical address */ 32551889a6SIan Campbell#define pa(X) ((X) - __PAGE_OFFSET) 331da177e4SLinus Torvalds 341da177e4SLinus Torvalds/* 351da177e4SLinus Torvalds * References to members of the new_cpu_data structure. 361da177e4SLinus Torvalds */ 371da177e4SLinus Torvalds 381da177e4SLinus Torvalds#define X86 new_cpu_data+CPUINFO_x86 391da177e4SLinus Torvalds#define X86_VENDOR new_cpu_data+CPUINFO_x86_vendor 401da177e4SLinus Torvalds#define X86_MODEL new_cpu_data+CPUINFO_x86_model 41b399151cSJia Zhang#define X86_STEPPING new_cpu_data+CPUINFO_x86_stepping 421da177e4SLinus Torvalds#define X86_HARD_MATH new_cpu_data+CPUINFO_hard_math 431da177e4SLinus Torvalds#define X86_CPUID new_cpu_data+CPUINFO_cpuid_level 441da177e4SLinus Torvalds#define X86_CAPABILITY new_cpu_data+CPUINFO_x86_capability 451da177e4SLinus Torvalds#define X86_VENDOR_ID new_cpu_data+CPUINFO_x86_vendor_id 461da177e4SLinus Torvalds 479ce8c2edSJeremy Fitzhardinge/* 4822dc3918SJosh Poimboeuf * Worst-case size of the kernel mapping we need to make: 4922dc3918SJosh Poimboeuf * a relocatable kernel can live anywhere in lowmem, so we need to be able 5004c17341SBorislav Petkov * to map all of lowmem. 51c090f532SJeremy Fitzhardinge */ 52147dd561SH. Peter AnvinKERNEL_PAGES = LOWMEM_PAGES 53147dd561SH. Peter Anvin 54c090f532SJeremy FitzhardingeINIT_MAP_SIZE = PAGE_TABLE_SIZE(KERNEL_PAGES) * PAGE_SIZE 55147dd561SH. Peter AnvinRESERVE_BRK(pagetables, INIT_MAP_SIZE) 56c090f532SJeremy Fitzhardinge 577bf04be8SStratos Psomadakis/* 582bd2753fSYinghai Lu * 32-bit kernel entrypoint; only used by the boot CPU. On entry, 59796216a5SJeremy Fitzhardinge * %esi points to the real-mode code as a 32-bit pointer. 601da177e4SLinus Torvalds * CS and DS must be 4 GB flat segments, but we don't depend on 611da177e4SLinus Torvalds * any particular GDT layout, because we load our own as soon as we 621da177e4SLinus Torvalds * can. 631da177e4SLinus Torvalds */ 641da177e4SLinus Torvalds __INIT 651da177e4SLinus TorvaldsSYM_CODE_START(startup_32) 661da177e4SLinus Torvalds movl pa(initial_stack),%ecx 674ae59b91STim Abbott 6878762b0eSJiri Slaby/* 69b32f96c7SJosh Poimboeuf * Set segments to known values. 7011d4c3f9SH. Peter Anvin */ 711da177e4SLinus Torvalds lgdt pa(boot_gdt_descr) 721da177e4SLinus Torvalds movl $(__BOOT_DS),%eax 731da177e4SLinus Torvalds movl %eax,%ds 74551889a6SIan Campbell movl %eax,%es 751da177e4SLinus Torvalds movl %eax,%fs 761da177e4SLinus Torvalds movl %eax,%gs 771da177e4SLinus Torvalds movl %eax,%ss 781da177e4SLinus Torvalds leal -__PAGE_OFFSET(%ecx),%esp 791da177e4SLinus Torvalds 8011d4c3f9SH. Peter Anvin/* 8111d4c3f9SH. Peter Anvin * Clear BSS first so that there are no surprises... 821da177e4SLinus Torvalds */ 831da177e4SLinus Torvalds cld 841da177e4SLinus Torvalds xorl %eax,%eax 851da177e4SLinus Torvalds movl $pa(__bss_start),%edi 86a24e7851SRusty Russell movl $pa(__bss_stop),%ecx 871da177e4SLinus Torvalds subl %edi,%ecx 88551889a6SIan Campbell shrl $2,%ecx 89551889a6SIan Campbell rep stosl 901da177e4SLinus Torvalds/* 911da177e4SLinus Torvalds * Copy bootup parameters out of the way. 921da177e4SLinus Torvalds * Note: %esi still has the pointer to the real-mode data. 93484b90c4SVivek Goyal * With the kexec as boot loader, parameter segment might be loaded beyond 94484b90c4SVivek Goyal * kernel image and might not even be addressable by early boot page tables. 95484b90c4SVivek Goyal * (kexec on panic case). Hence copy out the parameters before initializing 96484b90c4SVivek Goyal * page tables. 97484b90c4SVivek Goyal */ 98484b90c4SVivek Goyal movl $pa(boot_params),%edi 99484b90c4SVivek Goyal movl $(PARAM_SIZE/4),%ecx 100484b90c4SVivek Goyal cld 101551889a6SIan Campbell rep movsl 102484b90c4SVivek Goyal movl pa(boot_params) + NEW_CL_POINTER,%esi 103484b90c4SVivek Goyal andl %esi,%esi 104484b90c4SVivek Goyal jz 1f # No command line 105484b90c4SVivek Goyal movl $pa(boot_command_line),%edi 106551889a6SIan Campbell movl $(COMMAND_LINE_SIZE/4),%ecx 107484b90c4SVivek Goyal rep movsl 108b595076aSUwe Kleine-König1: 109551889a6SIan Campbell 110484b90c4SVivek Goyal#ifdef CONFIG_OLPC 111484b90c4SVivek Goyal /* save OFW's pgdir table for later use when calling into OFW */ 112484b90c4SVivek Goyal movl %cr3, %eax 113484b90c4SVivek Goyal movl %eax, pa(olpc_ofw_pgd) 1141da177e4SLinus Torvalds#endif 115dc3119e7SThomas Gleixner 116fd699c76SAndres Salomon /* Create early pagetables. */ 117fd699c76SAndres Salomon call mk_early_pgtbl_32 118fd699c76SAndres Salomon 119fd699c76SAndres Salomon /* Do early initialization of the fixmap area */ 120fd699c76SAndres Salomon movl $pa(initial_pg_fixmap)+PDE_IDENT_ATTR,%eax 1211e620f9bSBoris Ostrovsky#ifdef CONFIG_X86_PAE 1221e620f9bSBoris Ostrovsky#define KPMDS (((-__PAGE_OFFSET) >> 30) & 3) /* Number of kernel PMDs */ 1231e620f9bSBoris Ostrovsky movl %eax,pa(initial_pg_pmd+0x1000*KPMDS-8) 1241e620f9bSBoris Ostrovsky#else 1251e620f9bSBoris Ostrovsky movl %eax,pa(initial_page_table+0xffc) 126551889a6SIan Campbell#endif 12786b2b70eSJoe Korty 128b40827faSBorislav Petkov jmp .Ldefault_entry 1291e620f9bSBoris OstrovskySYM_CODE_END(startup_32) 130b40827faSBorislav Petkov 131551889a6SIan Campbell/* 132d50d8fe1SRusty Russell * Non-boot CPU entry point; entered from trampoline.S 1331b00255fSJosh Poimboeuf * We can't lgdt here, because lgdt itself uses a data segment, but 13478762b0eSJiri Slaby * we know the trampoline has already loaded the boot_gdt for us. 135d50d8fe1SRusty Russell * 1361da177e4SLinus Torvalds * If cpu hotplug is not supported then this code can go in init section 1371da177e4SLinus Torvalds * which will be freed later 1381da177e4SLinus Torvalds */ 13952de74ddSSebastien Dugue#ifdef CONFIG_HOTPLUG_CPU 140f8657e1bSVivek Goyal .text 141f8657e1bSVivek Goyal#endif 142f8657e1bSVivek GoyalSYM_FUNC_START(startup_32_smp) 1431da177e4SLinus Torvalds cld 1446d685e53SJiri Slaby movl $(__BOOT_DS),%eax 1451da177e4SLinus Torvalds movl %eax,%ds 1461da177e4SLinus Torvalds movl %eax,%es 1471da177e4SLinus Torvalds movl %eax,%fs 1481da177e4SLinus Torvalds movl %eax,%gs 1491da177e4SLinus Torvalds movl pa(initial_stack),%ecx 1501da177e4SLinus Torvalds movl %eax,%ss 151b32f96c7SJosh Poimboeuf leal -__PAGE_OFFSET(%ecx),%esp 15211d4c3f9SH. Peter Anvin 15311d4c3f9SH. Peter Anvin.Ldefault_entry: 15448927bbbSJarkko Sakkinen movl $(CR0_STATE & ~X86_CR0_PG),%eax 1551b00255fSJosh Poimboeuf movl %eax,%cr0 156021ef050SH. Peter Anvin 157021ef050SH. Peter Anvin/* 158021ef050SH. Peter Anvin * We want to start out with EFLAGS unambiguously cleared. Some BIOSes leave 1591da177e4SLinus Torvalds * bits like NT set. This would confuse the debugger if this code is traced. So 1609efb58deSBorislav Petkov * initialize them properly now before switching to protected mode. That means 1619efb58deSBorislav Petkov * DF in particular (even though we have cleared it earlier after copying the 1629efb58deSBorislav Petkov * command line) because GCC expects it. 1639efb58deSBorislav Petkov */ 1649efb58deSBorislav Petkov pushl $0 1651da177e4SLinus Torvalds popfl 1665a5a51dbSH. Peter Anvin 1675a5a51dbSH. Peter Anvin/* 1689efb58deSBorislav Petkov * New page tables may be in 4Mbyte page mode and may be using the global pages. 1699efb58deSBorislav Petkov * 1709efb58deSBorislav Petkov * NOTE! If we are on a 486 we may have no cr4 at all! Specifically, cr4 exists 1719efb58deSBorislav Petkov * if and only if CPUID exists and has flags other than the FPU flag set. 1729efb58deSBorislav Petkov */ 1739efb58deSBorislav Petkov movl $-1,pa(X86_CPUID) # preset CPUID level 1749efb58deSBorislav Petkov movl $X86_EFLAGS_ID,%ecx 1759efb58deSBorislav Petkov pushl %ecx 1769efb58deSBorislav Petkov popfl # set EFLAGS=ID 1779efb58deSBorislav Petkov pushfl 1789efb58deSBorislav Petkov popl %eax # get EFLAGS 1795a5a51dbSH. Peter Anvin testl $X86_EFLAGS_ID,%eax # did EFLAGS.ID remained set? 1809efb58deSBorislav Petkov jz .Lenable_paging # hw disallowed setting of ID bit 1819efb58deSBorislav Petkov # which means no CPUID and no CR4 1821b00255fSJosh Poimboeuf 1839efb58deSBorislav Petkov xorl %eax,%eax 1849efb58deSBorislav Petkov cpuid 1859efb58deSBorislav Petkov movl %eax,pa(X86_CPUID) # save largest std CPUID function 1869efb58deSBorislav Petkov 1879efb58deSBorislav Petkov movl $1,%eax 1885a5a51dbSH. Peter Anvin cpuid 1896662c34fSH. Peter Anvin andl $~1,%edx # Ignore CPUID.FPU 1906662c34fSH. Peter Anvin jz .Lenable_paging # No flags or only CPUID.FPU = no CR4 1916662c34fSH. Peter Anvin 1921b00255fSJosh Poimboeuf movl pa(mmu_cr4_features),%eax 1936662c34fSH. Peter Anvin movl %eax,%cr4 1945a5a51dbSH. Peter Anvin 1951da177e4SLinus Torvalds testb $X86_CR4_PAE, %al # check if PAE is enabled 1961da177e4SLinus Torvalds jz .Lenable_paging 1978a50e513SH. Peter Anvin 1981b00255fSJosh Poimboeuf /* Check if extended functions are implemented */ 1991da177e4SLinus Torvalds movl $0x80000000, %eax 2001da177e4SLinus Torvalds cpuid 2011da177e4SLinus Torvalds /* Value must be in the range 0x80000001 to 0x8000ffff */ 2021da177e4SLinus Torvalds subl $0x80000001, %eax 2038a50e513SH. Peter Anvin cmpl $(0x8000ffff-0x80000001), %eax 2048a50e513SH. Peter Anvin ja .Lenable_paging 2058a50e513SH. Peter Anvin 2061b00255fSJosh Poimboeuf /* Clear bogus XD_DISABLE bits */ 207ebba638aSKees Cook call verify_cpu 208ebba638aSKees Cook 209ebba638aSKees Cook mov $0x80000001, %eax 210ebba638aSKees Cook cpuid 2111da177e4SLinus Torvalds /* Execute Disable bit supported? */ 2121da177e4SLinus Torvalds btl $(X86_FEATURE_NX & 31), %edx 2131da177e4SLinus Torvalds jnc .Lenable_paging 2148a50e513SH. Peter Anvin 2151b00255fSJosh Poimboeuf /* Setup EFER (Extended Feature Enable Register) */ 2161da177e4SLinus Torvalds movl $MSR_EFER, %ecx 2171da177e4SLinus Torvalds rdmsr 2188a50e513SH. Peter Anvin 2191da177e4SLinus Torvalds btsl $_EFER_NX, %eax 2201da177e4SLinus Torvalds /* Make changes effective */ 2218a50e513SH. Peter Anvin wrmsr 2221da177e4SLinus Torvalds 2231da177e4SLinus Torvalds.Lenable_paging: 2241da177e4SLinus Torvalds 2251b00255fSJosh Poimboeuf/* 2261da177e4SLinus Torvalds * Enable paging 2271da177e4SLinus Torvalds */ 2281da177e4SLinus Torvalds movl $pa(initial_page_table), %eax 2291da177e4SLinus Torvalds movl %eax,%cr3 /* set the page table pointer.. */ 230b40827faSBorislav Petkov movl $CR0_STATE,%eax 2311da177e4SLinus Torvalds movl %eax,%cr0 /* ..and set paging (PG) bit */ 232021ef050SH. Peter Anvin ljmp $__BOOT_CS,$1f /* Clear prefetch and normalize %eip */ 2331da177e4SLinus Torvalds1: 2341da177e4SLinus Torvalds /* Shift the stack pointer to a virtual address */ 2351da177e4SLinus Torvalds addl $__PAGE_OFFSET, %esp 23611d4c3f9SH. Peter Anvin 23711d4c3f9SH. Peter Anvin/* 2381da177e4SLinus Torvalds * Check if it is 486 2391da177e4SLinus Torvalds */ 240166df91dSBorislav Petkov movb $4,X86 # at least 486 2411da177e4SLinus Torvalds cmpl $-1,X86_CPUID 242237d1548SWang YanQing je .Lis486 243c3a22a26SBorislav Petkov 2441b00255fSJosh Poimboeuf /* get vendor info */ 2451da177e4SLinus Torvalds xorl %eax,%eax # call CPUID with 0 -> return vendor ID 2461da177e4SLinus Torvalds cpuid 2471da177e4SLinus Torvalds movl %eax,X86_CPUID # save CPUID level 2481da177e4SLinus Torvalds movl %ebx,X86_VENDOR_ID # lo 4 chars 2491da177e4SLinus Torvalds movl %edx,X86_VENDOR_ID+4 # next 4 chars 2501da177e4SLinus Torvalds movl %ecx,X86_VENDOR_ID+8 # last 4 chars 2511da177e4SLinus Torvalds 2521da177e4SLinus Torvalds orl %eax,%eax # do we have processor info as well? 2531da177e4SLinus Torvalds je .Lis486 2541da177e4SLinus Torvalds 2551b00255fSJosh Poimboeuf movl $1,%eax # Use the CPUID instruction to get CPU type 2561da177e4SLinus Torvalds cpuid 2571da177e4SLinus Torvalds movb %al,%cl # save reg for future use 2581da177e4SLinus Torvalds andb $0x0f,%ah # mask processor family 2591da177e4SLinus Torvalds movb %ah,X86 2601da177e4SLinus Torvalds andb $0xf0,%al # mask model 2611da177e4SLinus Torvalds shrb $4,%al 2621da177e4SLinus Torvalds movb %al,X86_MODEL 2631da177e4SLinus Torvalds andb $0x0f,%cl # mask mask revision 2641da177e4SLinus Torvalds movb %cl,X86_STEPPING 2651da177e4SLinus Torvalds movl %edx,X86_CAPABILITY 266b399151cSJia Zhang 2671da177e4SLinus Torvalds.Lis486: 2681da177e4SLinus Torvalds movl $0x50022,%ecx # set AM, WP, NE and MP 2691b00255fSJosh Poimboeuf movl %cr0,%eax 270c3a22a26SBorislav Petkov andl $0x80000011,%eax # Save PG,PE,ET 271166df91dSBorislav Petkov orl %ecx,%eax 2721da177e4SLinus Torvalds movl %eax,%cr0 2731da177e4SLinus Torvalds 2741da177e4SLinus Torvalds lgdt early_gdt_descr 2751da177e4SLinus Torvalds ljmp $(__KERNEL_CS),$1f 2762a57ff1aSRusty Russell1: movl $(__KERNEL_DS),%eax # reload all the segment registers 2771da177e4SLinus Torvalds movl %eax,%ss # after changing gdt. 2781da177e4SLinus Torvalds 2791da177e4SLinus Torvalds movl $(__USER_DS),%eax # DS/ES contains default USER segment 2801da177e4SLinus Torvalds movl %eax,%ds 2811da177e4SLinus Torvalds movl %eax,%es 2821da177e4SLinus Torvalds 2831da177e4SLinus Torvalds movl $(__KERNEL_PERCPU), %eax 2841da177e4SLinus Torvalds movl %eax,%fs # set this cpu's percpu 2850dd76d73SBrian Gerst 2860dd76d73SBrian Gerst xorl %eax,%eax 2870dd76d73SBrian Gerst movl %eax,%gs # clear possible garbage in %gs 2883fb0fdb3SAndy Lutomirski 2893fb0fdb3SAndy Lutomirski xorl %eax,%eax # Clear LDT 29060a5317fSTejun Heo lldt %ax 29160a5317fSTejun Heo 2921da177e4SLinus Torvalds call *(initial_code) 293f95d47caSJeremy Fitzhardinge1: jmp 1b 2946616a147SJosh PoimboeufSYM_FUNC_END(startup_32_smp) 2956616a147SJosh Poimboeuf 2966d685e53SJiri Slaby#include "verify_cpu.S" 2971da177e4SLinus Torvalds 2984c5023a3SH. Peter Anvin__INIT 2994c5023a3SH. Peter AnvinSYM_FUNC_START(early_idt_handler_array) 3004c5023a3SH. Peter Anvin # 36(%esp) %eflags 3016d685e53SJiri Slaby # 32(%esp) %cs 3024c5023a3SH. Peter Anvin # 28(%esp) %eip 3034c5023a3SH. Peter Anvin # 24(%rsp) error code 3044c5023a3SH. Peter Anvin i = 0 3054c5023a3SH. Peter Anvin .rept NUM_EXCEPTION_VECTORS 3064c5023a3SH. Peter Anvin .if ((EXCEPTION_ERRCODE_MASK >> i) & 1) == 0 3074c5023a3SH. Peter Anvin pushl $0 # Dummy error code, to make stack frame uniform 30882c62fa0SJosh Poimboeuf .endif 3094c5023a3SH. Peter Anvin pushl $i # 20(%esp) Vector number 3104c5023a3SH. Peter Anvin jmp early_idt_handler_common 3114c5023a3SH. Peter Anvin i = i + 1 312425be567SAndy Lutomirski .fill early_idt_handler_array + i*EARLY_IDT_HANDLER_SIZE - ., 1, 0xcc 3134c5023a3SH. Peter Anvin .endr 314425be567SAndy LutomirskiSYM_FUNC_END(early_idt_handler_array) 3154c5023a3SH. Peter Anvin 3166d685e53SJiri SlabySYM_CODE_START_LOCAL(early_idt_handler_common) 317ec5c0926SChuck Ebbert /* 318ef77e688SJiri Slaby * The stack is the hardware frame, an error code or zero, and the 319425be567SAndy Lutomirski * vector number. 320425be567SAndy Lutomirski */ 321425be567SAndy Lutomirski cld 322425be567SAndy Lutomirski 323ec5c0926SChuck Ebbert incl %ss:early_recursion_flag 3245fa10196SH. Peter Anvin 3254c5023a3SH. Peter Anvin /* The vector number is in pt_regs->gs */ 3264c5023a3SH. Peter Anvin 3277bbcdb1cSAndy Lutomirski cld 3284c5023a3SH. Peter Anvin pushl %fs /* pt_regs->fs (__fsh varies by model) */ 3297bbcdb1cSAndy Lutomirski pushl %es /* pt_regs->es (__esh varies by model) */ 330630c1863SAndy Lutomirski pushl %ds /* pt_regs->ds (__dsh varies by model) */ 331630c1863SAndy Lutomirski pushl %eax /* pt_regs->ax */ 332630c1863SAndy Lutomirski pushl %ebp /* pt_regs->bp */ 3337bbcdb1cSAndy Lutomirski pushl %edi /* pt_regs->di */ 3347bbcdb1cSAndy Lutomirski pushl %esi /* pt_regs->si */ 3357bbcdb1cSAndy Lutomirski pushl %edx /* pt_regs->dx */ 3367bbcdb1cSAndy Lutomirski pushl %ecx /* pt_regs->cx */ 3377bbcdb1cSAndy Lutomirski pushl %ebx /* pt_regs->bx */ 3387bbcdb1cSAndy Lutomirski 3397bbcdb1cSAndy Lutomirski /* Fix up DS and ES */ 3407bbcdb1cSAndy Lutomirski movl $(__KERNEL_DS), %ecx 3417bbcdb1cSAndy Lutomirski movl %ecx, %ds 3427bbcdb1cSAndy Lutomirski movl %ecx, %es 3437bbcdb1cSAndy Lutomirski 3447bbcdb1cSAndy Lutomirski /* Load the vector number into EDX */ 3457bbcdb1cSAndy Lutomirski movl PT_GS(%esp), %edx 3467bbcdb1cSAndy Lutomirski 3477bbcdb1cSAndy Lutomirski /* Load GS into pt_regs->gs (and maybe clobber __gsh) */ 3487bbcdb1cSAndy Lutomirski movw %gs, PT_GS(%esp) 349630c1863SAndy Lutomirski 3507bbcdb1cSAndy Lutomirski movl %esp, %eax /* args are pt_regs (EAX), trapnr (EDX) */ 3517bbcdb1cSAndy Lutomirski call early_fixup_exception 3527bbcdb1cSAndy Lutomirski 3534c5023a3SH. Peter Anvin popl %ebx /* pt_regs->bx */ 3547bbcdb1cSAndy Lutomirski popl %ecx /* pt_regs->cx */ 3557bbcdb1cSAndy Lutomirski popl %edx /* pt_regs->dx */ 3567bbcdb1cSAndy Lutomirski popl %esi /* pt_regs->si */ 3577bbcdb1cSAndy Lutomirski popl %edi /* pt_regs->di */ 3587bbcdb1cSAndy Lutomirski popl %ebp /* pt_regs->bp */ 3597bbcdb1cSAndy Lutomirski popl %eax /* pt_regs->ax */ 3607bbcdb1cSAndy Lutomirski popl %ds /* pt_regs->ds (always ignores __dsh) */ 3617bbcdb1cSAndy Lutomirski popl %es /* pt_regs->es (always ignores __esh) */ 362630c1863SAndy Lutomirski popl %fs /* pt_regs->fs (always ignores __fsh) */ 363630c1863SAndy Lutomirski popl %gs /* pt_regs->gs (always ignores __gsh) */ 364630c1863SAndy Lutomirski decl %ss:early_recursion_flag 365630c1863SAndy Lutomirski addl $4, %esp /* pop pt_regs->orig_ax */ 3667bbcdb1cSAndy Lutomirski iret 3677bbcdb1cSAndy LutomirskiSYM_CODE_END(early_idt_handler_common) 3687bbcdb1cSAndy Lutomirski 369ef77e688SJiri Slaby/* This is the default interrupt "handler" :-) */ 3704c5023a3SH. Peter AnvinSYM_FUNC_START(early_ignore_irq) 3711da177e4SLinus Torvalds cld 3726d685e53SJiri Slaby#ifdef CONFIG_PRINTK 3731da177e4SLinus Torvalds pushl %eax 374d59745ceSMatt Mackall pushl %ecx 3751da177e4SLinus Torvalds pushl %edx 3761da177e4SLinus Torvalds pushl %es 3771da177e4SLinus Torvalds pushl %ds 3781da177e4SLinus Torvalds movl $(__KERNEL_DS),%eax 3791da177e4SLinus Torvalds movl %eax,%ds 3801da177e4SLinus Torvalds movl %eax,%es 3811da177e4SLinus Torvalds cmpl $2,early_recursion_flag 3821da177e4SLinus Torvalds je hlt_loop 383ec5c0926SChuck Ebbert incl early_recursion_flag 384ec5c0926SChuck Ebbert pushl 16(%esp) 385ec5c0926SChuck Ebbert pushl 24(%esp) 3861da177e4SLinus Torvalds pushl 32(%esp) 3871da177e4SLinus Torvalds pushl 40(%esp) 3881da177e4SLinus Torvalds pushl $int_msg 3891da177e4SLinus Torvalds call _printk 3901da177e4SLinus Torvalds 39133701557SChris Down call dump_stack 392d5e397cbSIngo Molnar 393d5e397cbSIngo Molnar addl $(5*4),%esp 394d5e397cbSIngo Molnar popl %ds 3951da177e4SLinus Torvalds popl %es 3961da177e4SLinus Torvalds popl %edx 3971da177e4SLinus Torvalds popl %ecx 3981da177e4SLinus Torvalds popl %eax 3991da177e4SLinus Torvalds#endif 4001da177e4SLinus Torvalds iret 401d59745ceSMatt Mackall 4021da177e4SLinus Torvaldshlt_loop: 4030e861fbbSAndy Lutomirski hlt 4040e861fbbSAndy Lutomirski jmp hlt_loop 4050e861fbbSAndy LutomirskiSYM_FUNC_END(early_ignore_irq) 4060e861fbbSAndy Lutomirski 4076d685e53SJiri Slaby__INITDATA 40804b5de3aSJiri Slaby .align 4 4094c5023a3SH. Peter AnvinSYM_DATA(early_recursion_flag, .long 0) 4104c5023a3SH. Peter Anvin 411b1bd27b9SJiri Slaby__REFDATA 412ebba638aSKees Cook .align 4 4130e83815bSRobert RichterSYM_DATA(initial_code, .long i386_start_kernel) 414583323b9SThomas Gleixner 415b1bd27b9SJiri Slaby#ifdef CONFIG_MITIGATION_PAGE_TABLE_ISOLATION 416583323b9SThomas Gleixner#define PGD_ALIGN (2 * PAGE_SIZE) 417*ea4654e0SBreno Leitao#define PTI_USER_PGD_FILL 1024 418e3238fafSJoerg Roedel#else 419e3238fafSJoerg Roedel#define PGD_ALIGN (PAGE_SIZE) 420e3238fafSJoerg Roedel#define PTI_USER_PGD_FILL 0 421e3238fafSJoerg Roedel#endif 422e3238fafSJoerg Roedel/* 423e3238fafSJoerg Roedel * BSS section 4241da177e4SLinus Torvalds */ 4251da177e4SLinus Torvalds__PAGE_ALIGNED_BSS 4261da177e4SLinus Torvalds .align PGD_ALIGN 42702b7da37STim Abbott#ifdef CONFIG_X86_PAE 428e3238fafSJoerg Roedel.globl initial_pg_pmd 429551889a6SIan Campbellinitial_pg_pmd: 4301e620f9bSBoris Ostrovsky .fill 1024*KPMDS,4,0 431d50d8fe1SRusty Russell#else 432551889a6SIan Campbell.globl initial_page_table 433551889a6SIan Campbellinitial_page_table: 434553bbc11SArnd Bergmann .fill 1024,4,0 435553bbc11SArnd Bergmann#endif 4361da177e4SLinus Torvalds .align PGD_ALIGN 437551889a6SIan Campbellinitial_pg_fixmap: 438e3238fafSJoerg Roedel .fill 1024,4,0 439d50d8fe1SRusty Russell.globl swapper_pg_dir 440b1c931e3SEric W. Biderman .align PGD_ALIGN 441e3238fafSJoerg Roedelswapper_pg_dir: 442e3238fafSJoerg Roedel .fill 1024,4,0 443e3238fafSJoerg Roedel .fill PTI_USER_PGD_FILL,4,0 444e3238fafSJoerg Roedel.globl empty_zero_page 445e3238fafSJoerg Roedelempty_zero_page: 446553bbc11SArnd Bergmann .fill 4096,1,0 447553bbc11SArnd BergmannEXPORT_SYMBOL(empty_zero_page) 4481da177e4SLinus Torvalds 449784d5699SAl Viro/* 4502bd2753fSYinghai Lu * This starts the data section. 4511da177e4SLinus Torvalds */ 4521da177e4SLinus Torvalds#ifdef CONFIG_X86_PAE 4531da177e4SLinus Torvalds__PAGE_ALIGNED_DATA 454551889a6SIan Campbell /* Page-aligned for the benefit of paravirt? */ 455abe1ee3aSTim Abbott .align PGD_ALIGN 456551889a6SIan CampbellSYM_DATA_START(initial_page_table) 457e3238fafSJoerg Roedel .long pa(initial_pg_pmd+PGD_IDENT_ATTR),0 /* low identity map */ 458b1bd27b9SJiri Slaby# if KPMDS == 3 459b40827faSBorislav Petkov .long pa(initial_pg_pmd+PGD_IDENT_ATTR),0 460551889a6SIan Campbell .long pa(initial_pg_pmd+PGD_IDENT_ATTR+0x1000),0 461b40827faSBorislav Petkov .long pa(initial_pg_pmd+PGD_IDENT_ATTR+0x2000),0 462b40827faSBorislav Petkov# elif KPMDS == 2 463b40827faSBorislav Petkov .long 0,0 464551889a6SIan Campbell .long pa(initial_pg_pmd+PGD_IDENT_ATTR),0 465551889a6SIan Campbell .long pa(initial_pg_pmd+PGD_IDENT_ATTR+0x1000),0 466b40827faSBorislav Petkov# elif KPMDS == 1 467b40827faSBorislav Petkov .long 0,0 468551889a6SIan Campbell .long 0,0 469551889a6SIan Campbell .long pa(initial_pg_pmd+PGD_IDENT_ATTR),0 470551889a6SIan Campbell# else 471b40827faSBorislav Petkov# error "Kernel PMDs should be 1, 2 or 3" 472551889a6SIan Campbell# endif 473551889a6SIan Campbell .align PAGE_SIZE /* needs to be page-sized too */ 474551889a6SIan Campbell 4757bf04be8SStratos Psomadakis#ifdef CONFIG_MITIGATION_PAGE_TABLE_ISOLATION 476f490e07cSThomas Gleixner /* 477*ea4654e0SBreno Leitao * PTI needs another page so sync_initial_pagetable() works correctly 478f490e07cSThomas Gleixner * and does not scribble over the data which is placed behind the 479f490e07cSThomas Gleixner * actual initial_page_table. See clone_pgd_range(). 480f490e07cSThomas Gleixner */ 481f490e07cSThomas Gleixner .fill 1024, 4, 0 482f490e07cSThomas Gleixner#endif 483f490e07cSThomas Gleixner 484f490e07cSThomas GleixnerSYM_DATA_END(initial_page_table) 485f490e07cSThomas Gleixner#endif 486b1bd27b9SJiri Slaby 487551889a6SIan Campbell.data 488551889a6SIan Campbell.balign 4 4891da177e4SLinus TorvaldsSYM_DATA(initial_stack, .long __top_init_kernel_stack) 49011d4c3f9SH. Peter Anvin 49122dc3918SJosh Poimboeuf__INITRODATA 492b1bd27b9SJiri Slabyint_msg: 493b1bd27b9SJiri Slaby .asciz "Unknown interrupt or fault at: %p %p %p\n" 49422dc3918SJosh Poimboeuf 495b1bd27b9SJiri Slaby#include "../xen/xen-head.S" 496b1bd27b9SJiri Slaby 497b1bd27b9SJiri Slaby/* 4981da177e4SLinus Torvalds * The IDT and GDT 'descriptors' are a strange 48-bit object 4994c5023a3SH. Peter Anvin * only used by the lidt and lgdt instructions. They are not 5001da177e4SLinus Torvalds * like usual segment descriptors - they consist of a 16-bit 501d5e397cbSIngo Molnar * segment size, and 32-bit linear address value: 5021da177e4SLinus Torvalds */ 5039702785aSThomas Gleixner 5045ead97c8SJeremy Fitzhardinge .data 5051da177e4SLinus Torvalds ALIGN 5061da177e4SLinus Torvalds# early boot GDT descriptor (must use 1:1 address mapping) 5071da177e4SLinus Torvalds .word 0 # 32 bit align gdt_desc.address 5081da177e4SLinus TorvaldsSYM_DATA_START_LOCAL(boot_gdt_descr) 5091da177e4SLinus Torvalds .word __BOOT_DS+7 5101da177e4SLinus Torvalds .long boot_gdt - __PAGE_OFFSET 5111da177e4SLinus TorvaldsSYM_DATA_END(boot_gdt_descr) 5124c5023a3SH. Peter Anvin 5131da177e4SLinus Torvalds# boot GDT descriptor (later on used by CPU#0): 5141da177e4SLinus Torvalds .word 0 # 32 bit align gdt_desc.address 5151da177e4SLinus TorvaldsSYM_DATA_START(early_gdt_descr) 516b1bd27b9SJiri Slaby .word GDT_ENTRIES*8-1 5171da177e4SLinus Torvalds .long gdt_page /* Overwritten for secondary CPUs */ 51852de74ddSSebastien DugueSYM_DATA_END(early_gdt_descr) 519b1bd27b9SJiri Slaby 5201da177e4SLinus Torvalds/* 5211da177e4SLinus Torvalds * The boot_gdt must mirror the equivalent in setup.S and is 5221da177e4SLinus Torvalds * used only for booting. 523b1bd27b9SJiri Slaby */ 5241da177e4SLinus Torvalds .align L1_CACHE_BYTES 525dd17c8f7SRusty RussellSYM_DATA_START(boot_gdt) 526b1bd27b9SJiri Slaby .fill GDT_ENTRY_BOOT_CS,8,0 5271da177e4SLinus Torvalds .quad 0x00cf9a000000ffff /* kernel 4GB code at 0x00000000 */ 5281da177e4SLinus Torvalds .quad 0x00cf92000000ffff /* kernel 4GB data at 0x00000000 */ 52952de74ddSSebastien DugueSYM_DATA_END(boot_gdt) 5301da177e4SLinus Torvalds