19a163ed8SThomas Gleixner/* 29a163ed8SThomas Gleixner * 39a163ed8SThomas Gleixner * Copyright (C) 1991, 1992 Linus Torvalds 49a163ed8SThomas Gleixner * 59a163ed8SThomas Gleixner * Enhanced CPU detection and feature setting code by Mike Jagdis 69a163ed8SThomas Gleixner * and Martin Mares, November 1997. 79a163ed8SThomas Gleixner */ 89a163ed8SThomas Gleixner 99a163ed8SThomas Gleixner.text 109a163ed8SThomas Gleixner#include <linux/threads.h> 118b2f7fffSSam Ravnborg#include <linux/init.h> 129a163ed8SThomas Gleixner#include <linux/linkage.h> 139a163ed8SThomas Gleixner#include <asm/segment.h> 140341c14dSJeremy Fitzhardinge#include <asm/page_types.h> 150341c14dSJeremy Fitzhardinge#include <asm/pgtable_types.h> 169a163ed8SThomas Gleixner#include <asm/cache.h> 179a163ed8SThomas Gleixner#include <asm/thread_info.h> 189a163ed8SThomas Gleixner#include <asm/asm-offsets.h> 199a163ed8SThomas Gleixner#include <asm/setup.h> 20551889a6SIan Campbell#include <asm/processor-flags.h> 218a50e513SH. Peter Anvin#include <asm/msr-index.h> 228a50e513SH. Peter Anvin#include <asm/cpufeature.h> 2360a5317fSTejun Heo#include <asm/percpu.h> 244c5023a3SH. Peter Anvin#include <asm/nops.h> 25551889a6SIan Campbell 26551889a6SIan Campbell/* Physical address */ 27551889a6SIan Campbell#define pa(X) ((X) - __PAGE_OFFSET) 289a163ed8SThomas Gleixner 299a163ed8SThomas Gleixner/* 309a163ed8SThomas Gleixner * References to members of the new_cpu_data structure. 319a163ed8SThomas Gleixner */ 329a163ed8SThomas Gleixner 339a163ed8SThomas Gleixner#define X86 new_cpu_data+CPUINFO_x86 349a163ed8SThomas Gleixner#define X86_VENDOR new_cpu_data+CPUINFO_x86_vendor 359a163ed8SThomas Gleixner#define X86_MODEL new_cpu_data+CPUINFO_x86_model 369a163ed8SThomas Gleixner#define X86_MASK new_cpu_data+CPUINFO_x86_mask 379a163ed8SThomas Gleixner#define X86_HARD_MATH new_cpu_data+CPUINFO_hard_math 389a163ed8SThomas Gleixner#define X86_CPUID new_cpu_data+CPUINFO_cpuid_level 399a163ed8SThomas Gleixner#define X86_CAPABILITY new_cpu_data+CPUINFO_x86_capability 409a163ed8SThomas Gleixner#define X86_VENDOR_ID new_cpu_data+CPUINFO_x86_vendor_id 419a163ed8SThomas Gleixner 429a163ed8SThomas Gleixner/* 43c090f532SJeremy Fitzhardinge * This is how much memory in addition to the memory covered up to 44c090f532SJeremy Fitzhardinge * and including _end we need mapped initially. 459a163ed8SThomas Gleixner * We need: 462bd2753fSYinghai Lu * (KERNEL_IMAGE_SIZE/4096) / 1024 pages (worst case, non PAE) 472bd2753fSYinghai Lu * (KERNEL_IMAGE_SIZE/4096) / 512 + 4 pages (worst case for PAE) 489a163ed8SThomas Gleixner * 499a163ed8SThomas Gleixner * Modulo rounding, each megabyte assigned here requires a kilobyte of 509a163ed8SThomas Gleixner * memory, which is currently unreclaimed. 519a163ed8SThomas Gleixner * 529a163ed8SThomas Gleixner * This should be a multiple of a page. 532bd2753fSYinghai Lu * 542bd2753fSYinghai Lu * KERNEL_IMAGE_SIZE should be greater than pa(_end) 552bd2753fSYinghai Lu * and small than max_low_pfn, otherwise will waste some page table entries 569a163ed8SThomas Gleixner */ 579a163ed8SThomas Gleixner 589a163ed8SThomas Gleixner#if PTRS_PER_PMD > 1 59c090f532SJeremy Fitzhardinge#define PAGE_TABLE_SIZE(pages) (((pages) / PTRS_PER_PMD) + PTRS_PER_PGD) 609a163ed8SThomas Gleixner#else 61c090f532SJeremy Fitzhardinge#define PAGE_TABLE_SIZE(pages) ((pages) / PTRS_PER_PGD) 629a163ed8SThomas Gleixner#endif 639a163ed8SThomas Gleixner 64147dd561SH. Peter Anvin/* Number of possible pages in the lowmem region */ 65147dd561SH. Peter AnvinLOWMEM_PAGES = (((1<<32) - __PAGE_OFFSET) >> PAGE_SHIFT) 66147dd561SH. Peter Anvin 67c090f532SJeremy Fitzhardinge/* Enough space to fit pagetables for the low memory linear map */ 68147dd561SH. Peter AnvinMAPPING_BEYOND_END = PAGE_TABLE_SIZE(LOWMEM_PAGES) << PAGE_SHIFT 69c090f532SJeremy Fitzhardinge 70c090f532SJeremy Fitzhardinge/* 71c090f532SJeremy Fitzhardinge * Worst-case size of the kernel mapping we need to make: 72147dd561SH. Peter Anvin * a relocatable kernel can live anywhere in lowmem, so we need to be able 73147dd561SH. Peter Anvin * to map all of lowmem. 74c090f532SJeremy Fitzhardinge */ 75147dd561SH. Peter AnvinKERNEL_PAGES = LOWMEM_PAGES 76c090f532SJeremy Fitzhardinge 777bf04be8SStratos PsomadakisINIT_MAP_SIZE = PAGE_TABLE_SIZE(KERNEL_PAGES) * PAGE_SIZE 782bd2753fSYinghai LuRESERVE_BRK(pagetables, INIT_MAP_SIZE) 79796216a5SJeremy Fitzhardinge 809a163ed8SThomas Gleixner/* 819a163ed8SThomas Gleixner * 32-bit kernel entrypoint; only used by the boot CPU. On entry, 829a163ed8SThomas Gleixner * %esi points to the real-mode code as a 32-bit pointer. 839a163ed8SThomas Gleixner * CS and DS must be 4 GB flat segments, but we don't depend on 849a163ed8SThomas Gleixner * any particular GDT layout, because we load our own as soon as we 859a163ed8SThomas Gleixner * can. 869a163ed8SThomas Gleixner */ 874ae59b91STim Abbott__HEAD 889a163ed8SThomas GleixnerENTRY(startup_32) 8911d4c3f9SH. Peter Anvin movl pa(stack_start),%ecx 9011d4c3f9SH. Peter Anvin 91a24e7851SRusty Russell /* test KEEP_SEGMENTS flag to see if the bootloader is asking 92a24e7851SRusty Russell us to not reload segments */ 93a24e7851SRusty Russell testb $(1<<6), BP_loadflags(%esi) 94a24e7851SRusty Russell jnz 2f 959a163ed8SThomas Gleixner 969a163ed8SThomas Gleixner/* 979a163ed8SThomas Gleixner * Set segments to known values. 989a163ed8SThomas Gleixner */ 99551889a6SIan Campbell lgdt pa(boot_gdt_descr) 1009a163ed8SThomas Gleixner movl $(__BOOT_DS),%eax 1019a163ed8SThomas Gleixner movl %eax,%ds 1029a163ed8SThomas Gleixner movl %eax,%es 1039a163ed8SThomas Gleixner movl %eax,%fs 1049a163ed8SThomas Gleixner movl %eax,%gs 10511d4c3f9SH. Peter Anvin movl %eax,%ss 106a24e7851SRusty Russell2: 10711d4c3f9SH. Peter Anvin leal -__PAGE_OFFSET(%ecx),%esp 1089a163ed8SThomas Gleixner 1099a163ed8SThomas Gleixner/* 1109a163ed8SThomas Gleixner * Clear BSS first so that there are no surprises... 1119a163ed8SThomas Gleixner */ 112a24e7851SRusty Russell cld 1139a163ed8SThomas Gleixner xorl %eax,%eax 114551889a6SIan Campbell movl $pa(__bss_start),%edi 115551889a6SIan Campbell movl $pa(__bss_stop),%ecx 1169a163ed8SThomas Gleixner subl %edi,%ecx 1179a163ed8SThomas Gleixner shrl $2,%ecx 1189a163ed8SThomas Gleixner rep ; stosl 1199a163ed8SThomas Gleixner/* 1209a163ed8SThomas Gleixner * Copy bootup parameters out of the way. 1219a163ed8SThomas Gleixner * Note: %esi still has the pointer to the real-mode data. 1229a163ed8SThomas Gleixner * With the kexec as boot loader, parameter segment might be loaded beyond 1239a163ed8SThomas Gleixner * kernel image and might not even be addressable by early boot page tables. 1249a163ed8SThomas Gleixner * (kexec on panic case). Hence copy out the parameters before initializing 1259a163ed8SThomas Gleixner * page tables. 1269a163ed8SThomas Gleixner */ 127551889a6SIan Campbell movl $pa(boot_params),%edi 1289a163ed8SThomas Gleixner movl $(PARAM_SIZE/4),%ecx 1299a163ed8SThomas Gleixner cld 1309a163ed8SThomas Gleixner rep 1319a163ed8SThomas Gleixner movsl 132551889a6SIan Campbell movl pa(boot_params) + NEW_CL_POINTER,%esi 1339a163ed8SThomas Gleixner andl %esi,%esi 134b595076aSUwe Kleine-König jz 1f # No command line 135551889a6SIan Campbell movl $pa(boot_command_line),%edi 1369a163ed8SThomas Gleixner movl $(COMMAND_LINE_SIZE/4),%ecx 1379a163ed8SThomas Gleixner rep 1389a163ed8SThomas Gleixner movsl 1399a163ed8SThomas Gleixner1: 1409a163ed8SThomas Gleixner 141dc3119e7SThomas Gleixner#ifdef CONFIG_OLPC 142fd699c76SAndres Salomon /* save OFW's pgdir table for later use when calling into OFW */ 143fd699c76SAndres Salomon movl %cr3, %eax 144fd699c76SAndres Salomon movl %eax, pa(olpc_ofw_pgd) 145fd699c76SAndres Salomon#endif 146fd699c76SAndres Salomon 1479a163ed8SThomas Gleixner/* 1489a163ed8SThomas Gleixner * Initialize page tables. This creates a PDE and a set of page 1492bd2753fSYinghai Lu * tables, which are located immediately beyond __brk_base. The variable 150ccf3fe02SJeremy Fitzhardinge * _brk_end is set up to point to the first "safe" location. 1519a163ed8SThomas Gleixner * Mappings are created both at virtual address 0 (identity mapping) 1522bd2753fSYinghai Lu * and PAGE_OFFSET for up to _end. 1539a163ed8SThomas Gleixner */ 154551889a6SIan Campbell#ifdef CONFIG_X86_PAE 155551889a6SIan Campbell 156551889a6SIan Campbell /* 157b40827faSBorislav Petkov * In PAE mode initial_page_table is statically defined to contain 158b40827faSBorislav Petkov * enough entries to cover the VMSPLIT option (that is the top 1, 2 or 3 159b40827faSBorislav Petkov * entries). The identity mapping is handled by pointing two PGD entries 160b40827faSBorislav Petkov * to the first kernel PMD. 161551889a6SIan Campbell * 162b40827faSBorislav Petkov * Note the upper half of each PMD or PTE are always zero at this stage. 163551889a6SIan Campbell */ 164551889a6SIan Campbell 16586b2b70eSJoe Korty#define KPMDS (((-__PAGE_OFFSET) >> 30) & 3) /* Number of kernel PMDs */ 166551889a6SIan Campbell 167551889a6SIan Campbell xorl %ebx,%ebx /* %ebx is kept at zero */ 168551889a6SIan Campbell 169ccf3fe02SJeremy Fitzhardinge movl $pa(__brk_base), %edi 170b40827faSBorislav Petkov movl $pa(initial_pg_pmd), %edx 171b2bc2731SSuresh Siddha movl $PTE_IDENT_ATTR, %eax 1729a163ed8SThomas Gleixner10: 173b2bc2731SSuresh Siddha leal PDE_IDENT_ATTR(%edi),%ecx /* Create PMD entry */ 174551889a6SIan Campbell movl %ecx,(%edx) /* Store PMD entry */ 175551889a6SIan Campbell /* Upper half already zero */ 176551889a6SIan Campbell addl $8,%edx 177551889a6SIan Campbell movl $512,%ecx 178551889a6SIan Campbell11: 179551889a6SIan Campbell stosl 180551889a6SIan Campbell xchgl %eax,%ebx 181551889a6SIan Campbell stosl 182551889a6SIan Campbell xchgl %eax,%ebx 183551889a6SIan Campbell addl $0x1000,%eax 184551889a6SIan Campbell loop 11b 185551889a6SIan Campbell 186551889a6SIan Campbell /* 187c090f532SJeremy Fitzhardinge * End condition: we must map up to the end + MAPPING_BEYOND_END. 188551889a6SIan Campbell */ 189c090f532SJeremy Fitzhardinge movl $pa(_end) + MAPPING_BEYOND_END + PTE_IDENT_ATTR, %ebp 190551889a6SIan Campbell cmpl %ebp,%eax 191551889a6SIan Campbell jb 10b 192551889a6SIan Campbell1: 193ccf3fe02SJeremy Fitzhardinge addl $__PAGE_OFFSET, %edi 194ccf3fe02SJeremy Fitzhardinge movl %edi, pa(_brk_end) 1956af61a76SYinghai Lu shrl $12, %eax 1966af61a76SYinghai Lu movl %eax, pa(max_pfn_mapped) 197551889a6SIan Campbell 198551889a6SIan Campbell /* Do early initialization of the fixmap area */ 199b40827faSBorislav Petkov movl $pa(initial_pg_fixmap)+PDE_IDENT_ATTR,%eax 200b40827faSBorislav Petkov movl %eax,pa(initial_pg_pmd+0x1000*KPMDS-8) 201551889a6SIan Campbell#else /* Not PAE */ 202551889a6SIan Campbell 203551889a6SIan Campbellpage_pde_offset = (__PAGE_OFFSET >> 20); 204551889a6SIan Campbell 205ccf3fe02SJeremy Fitzhardinge movl $pa(__brk_base), %edi 206b40827faSBorislav Petkov movl $pa(initial_page_table), %edx 207b2bc2731SSuresh Siddha movl $PTE_IDENT_ATTR, %eax 208551889a6SIan Campbell10: 209b2bc2731SSuresh Siddha leal PDE_IDENT_ATTR(%edi),%ecx /* Create PDE entry */ 2109a163ed8SThomas Gleixner movl %ecx,(%edx) /* Store identity PDE entry */ 2119a163ed8SThomas Gleixner movl %ecx,page_pde_offset(%edx) /* Store kernel PDE entry */ 2129a163ed8SThomas Gleixner addl $4,%edx 2139a163ed8SThomas Gleixner movl $1024, %ecx 2149a163ed8SThomas Gleixner11: 2159a163ed8SThomas Gleixner stosl 2169a163ed8SThomas Gleixner addl $0x1000,%eax 2179a163ed8SThomas Gleixner loop 11b 218551889a6SIan Campbell /* 219c090f532SJeremy Fitzhardinge * End condition: we must map up to the end + MAPPING_BEYOND_END. 220551889a6SIan Campbell */ 221c090f532SJeremy Fitzhardinge movl $pa(_end) + MAPPING_BEYOND_END + PTE_IDENT_ATTR, %ebp 2229a163ed8SThomas Gleixner cmpl %ebp,%eax 2239a163ed8SThomas Gleixner jb 10b 224ccf3fe02SJeremy Fitzhardinge addl $__PAGE_OFFSET, %edi 225ccf3fe02SJeremy Fitzhardinge movl %edi, pa(_brk_end) 2266af61a76SYinghai Lu shrl $12, %eax 2276af61a76SYinghai Lu movl %eax, pa(max_pfn_mapped) 2289a163ed8SThomas Gleixner 229551889a6SIan Campbell /* Do early initialization of the fixmap area */ 230b40827faSBorislav Petkov movl $pa(initial_pg_fixmap)+PDE_IDENT_ATTR,%eax 231b40827faSBorislav Petkov movl %eax,pa(initial_page_table+0xffc) 232551889a6SIan Campbell#endif 233d50d8fe1SRusty Russell 234d50d8fe1SRusty Russell#ifdef CONFIG_PARAVIRT 235d50d8fe1SRusty Russell /* This is can only trip for a broken bootloader... */ 236d50d8fe1SRusty Russell cmpw $0x207, pa(boot_params + BP_version) 237d50d8fe1SRusty Russell jb default_entry 238d50d8fe1SRusty Russell 239d50d8fe1SRusty Russell /* Paravirt-compatible boot parameters. Look to see what architecture 240d50d8fe1SRusty Russell we're booting under. */ 241d50d8fe1SRusty Russell movl pa(boot_params + BP_hardware_subarch), %eax 242d50d8fe1SRusty Russell cmpl $num_subarch_entries, %eax 243d50d8fe1SRusty Russell jae bad_subarch 244d50d8fe1SRusty Russell 245d50d8fe1SRusty Russell movl pa(subarch_entries)(,%eax,4), %eax 246d50d8fe1SRusty Russell subl $__PAGE_OFFSET, %eax 247d50d8fe1SRusty Russell jmp *%eax 248d50d8fe1SRusty Russell 249d50d8fe1SRusty Russellbad_subarch: 250d50d8fe1SRusty RussellWEAK(lguest_entry) 251d50d8fe1SRusty RussellWEAK(xen_entry) 252d50d8fe1SRusty Russell /* Unknown implementation; there's really 253d50d8fe1SRusty Russell nothing we can do at this point. */ 254d50d8fe1SRusty Russell ud2a 255d50d8fe1SRusty Russell 256d50d8fe1SRusty Russell __INITDATA 257d50d8fe1SRusty Russell 258d50d8fe1SRusty Russellsubarch_entries: 259d50d8fe1SRusty Russell .long default_entry /* normal x86/PC */ 260d50d8fe1SRusty Russell .long lguest_entry /* lguest hypervisor */ 261d50d8fe1SRusty Russell .long xen_entry /* Xen hypervisor */ 262d50d8fe1SRusty Russell .long default_entry /* Moorestown MID */ 263d50d8fe1SRusty Russellnum_subarch_entries = (. - subarch_entries) / 4 264d50d8fe1SRusty Russell.previous 265d50d8fe1SRusty Russell#else 266d50d8fe1SRusty Russell jmp default_entry 267d50d8fe1SRusty Russell#endif /* CONFIG_PARAVIRT */ 268d50d8fe1SRusty Russell 2693e2a0cc3SFenghua Yu#ifdef CONFIG_HOTPLUG_CPU 2703e2a0cc3SFenghua Yu/* 2713e2a0cc3SFenghua Yu * Boot CPU0 entry point. It's called from play_dead(). Everything has been set 2723e2a0cc3SFenghua Yu * up already except stack. We just set up stack here. Then call 2733e2a0cc3SFenghua Yu * start_secondary(). 2743e2a0cc3SFenghua Yu */ 2753e2a0cc3SFenghua YuENTRY(start_cpu0) 2763e2a0cc3SFenghua Yu movl stack_start, %ecx 2773e2a0cc3SFenghua Yu movl %ecx, %esp 2783e2a0cc3SFenghua Yu jmp *(initial_code) 2793e2a0cc3SFenghua YuENDPROC(start_cpu0) 2803e2a0cc3SFenghua Yu#endif 2813e2a0cc3SFenghua Yu 2829a163ed8SThomas Gleixner/* 2839a163ed8SThomas Gleixner * Non-boot CPU entry point; entered from trampoline.S 2849a163ed8SThomas Gleixner * We can't lgdt here, because lgdt itself uses a data segment, but 2859a163ed8SThomas Gleixner * we know the trampoline has already loaded the boot_gdt for us. 2869a163ed8SThomas Gleixner * 2879a163ed8SThomas Gleixner * If cpu hotplug is not supported then this code can go in init section 2889a163ed8SThomas Gleixner * which will be freed later 2899a163ed8SThomas Gleixner */ 29078b89ecdSJan Beulich__CPUINIT 2919a163ed8SThomas GleixnerENTRY(startup_32_smp) 2929a163ed8SThomas Gleixner cld 2939a163ed8SThomas Gleixner movl $(__BOOT_DS),%eax 2949a163ed8SThomas Gleixner movl %eax,%ds 2959a163ed8SThomas Gleixner movl %eax,%es 2969a163ed8SThomas Gleixner movl %eax,%fs 2979a163ed8SThomas Gleixner movl %eax,%gs 29811d4c3f9SH. Peter Anvin movl pa(stack_start),%ecx 29911d4c3f9SH. Peter Anvin movl %eax,%ss 30011d4c3f9SH. Peter Anvin leal -__PAGE_OFFSET(%ecx),%esp 30148927bbbSJarkko Sakkinen 302d50d8fe1SRusty Russelldefault_entry: 3039a163ed8SThomas Gleixner/* 3049a163ed8SThomas Gleixner * New page tables may be in 4Mbyte page mode and may 3059a163ed8SThomas Gleixner * be using the global pages. 3069a163ed8SThomas Gleixner * 3079a163ed8SThomas Gleixner * NOTE! If we are on a 486 we may have no cr4 at all! 3085a5a51dbSH. Peter Anvin * Specifically, cr4 exists if and only if CPUID exists, 3095a5a51dbSH. Peter Anvin * which in turn exists if and only if EFLAGS.ID exists. 3109a163ed8SThomas Gleixner */ 3115a5a51dbSH. Peter Anvin movl $X86_EFLAGS_ID,%ecx 3125a5a51dbSH. Peter Anvin pushl %ecx 3135a5a51dbSH. Peter Anvin popfl 3145a5a51dbSH. Peter Anvin pushfl 3155a5a51dbSH. Peter Anvin popl %eax 3165a5a51dbSH. Peter Anvin pushl $0 3175a5a51dbSH. Peter Anvin popfl 3185a5a51dbSH. Peter Anvin pushfl 3195a5a51dbSH. Peter Anvin popl %edx 3205a5a51dbSH. Peter Anvin xorl %edx,%eax 3215a5a51dbSH. Peter Anvin testl %ecx,%eax 3225a5a51dbSH. Peter Anvin jz 6f # No ID flag = no CPUID = no CR4 3235a5a51dbSH. Peter Anvin 3245a5a51dbSH. Peter Anvin movl pa(mmu_cr4_features),%eax 3259a163ed8SThomas Gleixner movl %eax,%cr4 3269a163ed8SThomas Gleixner 3278a50e513SH. Peter Anvin testb $X86_CR4_PAE, %al # check if PAE is enabled 3288a50e513SH. Peter Anvin jz 6f 3299a163ed8SThomas Gleixner 3309a163ed8SThomas Gleixner /* Check if extended functions are implemented */ 3319a163ed8SThomas Gleixner movl $0x80000000, %eax 3329a163ed8SThomas Gleixner cpuid 3338a50e513SH. Peter Anvin /* Value must be in the range 0x80000001 to 0x8000ffff */ 3348a50e513SH. Peter Anvin subl $0x80000001, %eax 3358a50e513SH. Peter Anvin cmpl $(0x8000ffff-0x80000001), %eax 3368a50e513SH. Peter Anvin ja 6f 337ebba638aSKees Cook 338ebba638aSKees Cook /* Clear bogus XD_DISABLE bits */ 339ebba638aSKees Cook call verify_cpu 340ebba638aSKees Cook 3419a163ed8SThomas Gleixner mov $0x80000001, %eax 3429a163ed8SThomas Gleixner cpuid 3439a163ed8SThomas Gleixner /* Execute Disable bit supported? */ 3448a50e513SH. Peter Anvin btl $(X86_FEATURE_NX & 31), %edx 3459a163ed8SThomas Gleixner jnc 6f 3469a163ed8SThomas Gleixner 3479a163ed8SThomas Gleixner /* Setup EFER (Extended Feature Enable Register) */ 3488a50e513SH. Peter Anvin movl $MSR_EFER, %ecx 3499a163ed8SThomas Gleixner rdmsr 3509a163ed8SThomas Gleixner 3518a50e513SH. Peter Anvin btsl $_EFER_NX, %eax 3529a163ed8SThomas Gleixner /* Make changes effective */ 3539a163ed8SThomas Gleixner wrmsr 3549a163ed8SThomas Gleixner 3559a163ed8SThomas Gleixner6: 3569a163ed8SThomas Gleixner 3579a163ed8SThomas Gleixner/* 3589a163ed8SThomas Gleixner * Enable paging 3599a163ed8SThomas Gleixner */ 360b40827faSBorislav Petkov movl $pa(initial_page_table), %eax 3619a163ed8SThomas Gleixner movl %eax,%cr3 /* set the page table pointer.. */ 3629a163ed8SThomas Gleixner movl %cr0,%eax 363551889a6SIan Campbell orl $X86_CR0_PG,%eax 3649a163ed8SThomas Gleixner movl %eax,%cr0 /* ..and set paging (PG) bit */ 3659a163ed8SThomas Gleixner ljmp $__BOOT_CS,$1f /* Clear prefetch and normalize %eip */ 3669a163ed8SThomas Gleixner1: 36711d4c3f9SH. Peter Anvin /* Shift the stack pointer to a virtual address */ 36811d4c3f9SH. Peter Anvin addl $__PAGE_OFFSET, %esp 3699a163ed8SThomas Gleixner 3709a163ed8SThomas Gleixner/* 3719a163ed8SThomas Gleixner * Initialize eflags. Some BIOS's leave bits like NT set. This would 3729a163ed8SThomas Gleixner * confuse the debugger if this code is traced. 3739a163ed8SThomas Gleixner * XXX - best to initialize before switching to protected mode. 3749a163ed8SThomas Gleixner */ 3759a163ed8SThomas Gleixner pushl $0 3769a163ed8SThomas Gleixner popfl 3779a163ed8SThomas Gleixner 3789a163ed8SThomas Gleixner/* 3799a163ed8SThomas Gleixner * start system 32-bit setup. We need to re-do some of the things done 3809a163ed8SThomas Gleixner * in 16-bit mode for the "real" operations. 3819a163ed8SThomas Gleixner */ 3824c5023a3SH. Peter Anvin movl setup_once_ref,%eax 3834c5023a3SH. Peter Anvin andl %eax,%eax 3844c5023a3SH. Peter Anvin jz 1f # Did we do this already? 3854c5023a3SH. Peter Anvin call *%eax 3864c5023a3SH. Peter Anvin1: 3879a163ed8SThomas Gleixner 3889a163ed8SThomas Gleixner/* check if it is 486 or 386. */ 3899a163ed8SThomas Gleixner/* 3909a163ed8SThomas Gleixner * XXX - this does a lot of unnecessary setup. Alignment checks don't 3919a163ed8SThomas Gleixner * apply at our cpl of 0 and the stack ought to be aligned already, and 3929a163ed8SThomas Gleixner * we don't need to preserve eflags. 3939a163ed8SThomas Gleixner */ 3944c5023a3SH. Peter Anvin movl $-1,X86_CPUID # -1 for no CPUID initially 3959a163ed8SThomas Gleixner movb $3,X86 # at least 386 3969a163ed8SThomas Gleixner pushfl # push EFLAGS 3979a163ed8SThomas Gleixner popl %eax # get EFLAGS 3989a163ed8SThomas Gleixner movl %eax,%ecx # save original EFLAGS 3999a163ed8SThomas Gleixner xorl $0x240000,%eax # flip AC and ID bits in EFLAGS 4009a163ed8SThomas Gleixner pushl %eax # copy to EFLAGS 4019a163ed8SThomas Gleixner popfl # set EFLAGS 4029a163ed8SThomas Gleixner pushfl # get new EFLAGS 4039a163ed8SThomas Gleixner popl %eax # put it in eax 4049a163ed8SThomas Gleixner xorl %ecx,%eax # change in flags 4059a163ed8SThomas Gleixner pushl %ecx # restore original EFLAGS 4069a163ed8SThomas Gleixner popfl 4079a163ed8SThomas Gleixner testl $0x40000,%eax # check if AC bit changed 4089a163ed8SThomas Gleixner je is386 4099a163ed8SThomas Gleixner 4109a163ed8SThomas Gleixner movb $4,X86 # at least 486 4119a163ed8SThomas Gleixner testl $0x200000,%eax # check if ID bit changed 4129a163ed8SThomas Gleixner je is486 4139a163ed8SThomas Gleixner 4149a163ed8SThomas Gleixner /* get vendor info */ 4159a163ed8SThomas Gleixner xorl %eax,%eax # call CPUID with 0 -> return vendor ID 4169a163ed8SThomas Gleixner cpuid 4179a163ed8SThomas Gleixner movl %eax,X86_CPUID # save CPUID level 4189a163ed8SThomas Gleixner movl %ebx,X86_VENDOR_ID # lo 4 chars 4199a163ed8SThomas Gleixner movl %edx,X86_VENDOR_ID+4 # next 4 chars 4209a163ed8SThomas Gleixner movl %ecx,X86_VENDOR_ID+8 # last 4 chars 4219a163ed8SThomas Gleixner 4229a163ed8SThomas Gleixner orl %eax,%eax # do we have processor info as well? 4239a163ed8SThomas Gleixner je is486 4249a163ed8SThomas Gleixner 4259a163ed8SThomas Gleixner movl $1,%eax # Use the CPUID instruction to get CPU type 4269a163ed8SThomas Gleixner cpuid 4279a163ed8SThomas Gleixner movb %al,%cl # save reg for future use 4289a163ed8SThomas Gleixner andb $0x0f,%ah # mask processor family 4299a163ed8SThomas Gleixner movb %ah,X86 4309a163ed8SThomas Gleixner andb $0xf0,%al # mask model 4319a163ed8SThomas Gleixner shrb $4,%al 4329a163ed8SThomas Gleixner movb %al,X86_MODEL 4339a163ed8SThomas Gleixner andb $0x0f,%cl # mask mask revision 4349a163ed8SThomas Gleixner movb %cl,X86_MASK 4359a163ed8SThomas Gleixner movl %edx,X86_CAPABILITY 4369a163ed8SThomas Gleixner 4379a163ed8SThomas Gleixneris486: movl $0x50022,%ecx # set AM, WP, NE and MP 4389a163ed8SThomas Gleixner jmp 2f 4399a163ed8SThomas Gleixner 4409a163ed8SThomas Gleixneris386: movl $2,%ecx # set MP 4419a163ed8SThomas Gleixner2: movl %cr0,%eax 4429a163ed8SThomas Gleixner andl $0x80000011,%eax # Save PG,PE,ET 4439a163ed8SThomas Gleixner orl %ecx,%eax 4449a163ed8SThomas Gleixner movl %eax,%cr0 4459a163ed8SThomas Gleixner 4469a163ed8SThomas Gleixner call check_x87 4479a163ed8SThomas Gleixner lgdt early_gdt_descr 4489a163ed8SThomas Gleixner lidt idt_descr 4499a163ed8SThomas Gleixner ljmp $(__KERNEL_CS),$1f 4509a163ed8SThomas Gleixner1: movl $(__KERNEL_DS),%eax # reload all the segment registers 4519a163ed8SThomas Gleixner movl %eax,%ss # after changing gdt. 4529a163ed8SThomas Gleixner 4539a163ed8SThomas Gleixner movl $(__USER_DS),%eax # DS/ES contains default USER segment 4549a163ed8SThomas Gleixner movl %eax,%ds 4559a163ed8SThomas Gleixner movl %eax,%es 4569a163ed8SThomas Gleixner 4570dd76d73SBrian Gerst movl $(__KERNEL_PERCPU), %eax 4580dd76d73SBrian Gerst movl %eax,%fs # set this cpu's percpu 4590dd76d73SBrian Gerst 46060a5317fSTejun Heo movl $(__KERNEL_STACK_CANARY),%eax 4619a163ed8SThomas Gleixner movl %eax,%gs 46260a5317fSTejun Heo 46360a5317fSTejun Heo xorl %eax,%eax # Clear LDT 4649a163ed8SThomas Gleixner lldt %ax 4659a163ed8SThomas Gleixner 4669a163ed8SThomas Gleixner cld # gcc2 wants the direction flag cleared at all times 4679a163ed8SThomas Gleixner pushl $0 # fake return address for unwinder 468e3f77edfSGlauber Costa jmp *(initial_code) 4699a163ed8SThomas Gleixner 4709a163ed8SThomas Gleixner/* 4719a163ed8SThomas Gleixner * We depend on ET to be correct. This checks for 287/387. 4729a163ed8SThomas Gleixner */ 4739a163ed8SThomas Gleixnercheck_x87: 4749a163ed8SThomas Gleixner movb $0,X86_HARD_MATH 4759a163ed8SThomas Gleixner clts 4769a163ed8SThomas Gleixner fninit 4779a163ed8SThomas Gleixner fstsw %ax 4789a163ed8SThomas Gleixner cmpb $0,%al 4799a163ed8SThomas Gleixner je 1f 4809a163ed8SThomas Gleixner movl %cr0,%eax /* no coprocessor: have to set bits */ 4819a163ed8SThomas Gleixner xorl $4,%eax /* set EM */ 4829a163ed8SThomas Gleixner movl %eax,%cr0 4839a163ed8SThomas Gleixner ret 4849a163ed8SThomas Gleixner ALIGN 4859a163ed8SThomas Gleixner1: movb $1,X86_HARD_MATH 4869a163ed8SThomas Gleixner .byte 0xDB,0xE4 /* fsetpm for 287, ignored by 387 */ 4879a163ed8SThomas Gleixner ret 4889a163ed8SThomas Gleixner 4894c5023a3SH. Peter Anvin 4904c5023a3SH. Peter Anvin#include "verify_cpu.S" 4914c5023a3SH. Peter Anvin 4929a163ed8SThomas Gleixner/* 4934c5023a3SH. Peter Anvin * setup_once 4949a163ed8SThomas Gleixner * 4954c5023a3SH. Peter Anvin * The setup work we only want to run on the BSP. 4969a163ed8SThomas Gleixner * 4979a163ed8SThomas Gleixner * Warning: %esi is live across this function. 4989a163ed8SThomas Gleixner */ 4994c5023a3SH. Peter Anvin__INIT 5004c5023a3SH. Peter Anvinsetup_once: 5014c5023a3SH. Peter Anvin /* 5024c5023a3SH. Peter Anvin * Set up a idt with 256 entries pointing to ignore_int, 5034c5023a3SH. Peter Anvin * interrupt gates. It doesn't actually load idt - that needs 5044c5023a3SH. Peter Anvin * to be done on each CPU. Interrupts are enabled elsewhere, 5054c5023a3SH. Peter Anvin * when we can be relatively sure everything is ok. 5064c5023a3SH. Peter Anvin */ 5074c5023a3SH. Peter Anvin 5084c5023a3SH. Peter Anvin movl $idt_table,%edi 5094c5023a3SH. Peter Anvin movl $early_idt_handlers,%eax 5104c5023a3SH. Peter Anvin movl $NUM_EXCEPTION_VECTORS,%ecx 5114c5023a3SH. Peter Anvin1: 5124c5023a3SH. Peter Anvin movl %eax,(%edi) 5134c5023a3SH. Peter Anvin movl %eax,4(%edi) 5144c5023a3SH. Peter Anvin /* interrupt gate, dpl=0, present */ 5154c5023a3SH. Peter Anvin movl $(0x8E000000 + __KERNEL_CS),2(%edi) 5164c5023a3SH. Peter Anvin addl $9,%eax 5174c5023a3SH. Peter Anvin addl $8,%edi 5184c5023a3SH. Peter Anvin loop 1b 5194c5023a3SH. Peter Anvin 5204c5023a3SH. Peter Anvin movl $256 - NUM_EXCEPTION_VECTORS,%ecx 5214c5023a3SH. Peter Anvin movl $ignore_int,%edx 5229a163ed8SThomas Gleixner movl $(__KERNEL_CS << 16),%eax 5239a163ed8SThomas Gleixner movw %dx,%ax /* selector = 0x0010 = cs */ 5249a163ed8SThomas Gleixner movw $0x8E00,%dx /* interrupt gate - dpl=0, present */ 5254c5023a3SH. Peter Anvin2: 5269a163ed8SThomas Gleixner movl %eax,(%edi) 5279a163ed8SThomas Gleixner movl %edx,4(%edi) 5289a163ed8SThomas Gleixner addl $8,%edi 5294c5023a3SH. Peter Anvin loop 2b 5309a163ed8SThomas Gleixner 5314c5023a3SH. Peter Anvin#ifdef CONFIG_CC_STACKPROTECTOR 5324c5023a3SH. Peter Anvin /* 5334c5023a3SH. Peter Anvin * Configure the stack canary. The linker can't handle this by 5344c5023a3SH. Peter Anvin * relocation. Manually set base address in stack canary 5354c5023a3SH. Peter Anvin * segment descriptor. 5364c5023a3SH. Peter Anvin */ 5374c5023a3SH. Peter Anvin movl $gdt_page,%eax 5384c5023a3SH. Peter Anvin movl $stack_canary,%ecx 5394c5023a3SH. Peter Anvin movw %cx, 8 * GDT_ENTRY_STACK_CANARY + 2(%eax) 5404c5023a3SH. Peter Anvin shrl $16, %ecx 5414c5023a3SH. Peter Anvin movb %cl, 8 * GDT_ENTRY_STACK_CANARY + 4(%eax) 5424c5023a3SH. Peter Anvin movb %ch, 8 * GDT_ENTRY_STACK_CANARY + 7(%eax) 5434c5023a3SH. Peter Anvin#endif 5449a163ed8SThomas Gleixner 5454c5023a3SH. Peter Anvin andl $0,setup_once_ref /* Once is enough, thanks */ 5469a163ed8SThomas Gleixner ret 5479a163ed8SThomas Gleixner 5484c5023a3SH. Peter AnvinENTRY(early_idt_handlers) 5494c5023a3SH. Peter Anvin # 36(%esp) %eflags 5504c5023a3SH. Peter Anvin # 32(%esp) %cs 5514c5023a3SH. Peter Anvin # 28(%esp) %eip 5524c5023a3SH. Peter Anvin # 24(%rsp) error code 5534c5023a3SH. Peter Anvin i = 0 5544c5023a3SH. Peter Anvin .rept NUM_EXCEPTION_VECTORS 5554c5023a3SH. Peter Anvin .if (EXCEPTION_ERRCODE_MASK >> i) & 1 5564c5023a3SH. Peter Anvin ASM_NOP2 5574c5023a3SH. Peter Anvin .else 5584c5023a3SH. Peter Anvin pushl $0 # Dummy error code, to make stack frame uniform 5594c5023a3SH. Peter Anvin .endif 5604c5023a3SH. Peter Anvin pushl $i # 20(%esp) Vector number 5614c5023a3SH. Peter Anvin jmp early_idt_handler 5624c5023a3SH. Peter Anvin i = i + 1 5634c5023a3SH. Peter Anvin .endr 5644c5023a3SH. Peter AnvinENDPROC(early_idt_handlers) 5659a163ed8SThomas Gleixner 5664c5023a3SH. Peter Anvin /* This is global to keep gas from relaxing the jumps */ 5674c5023a3SH. Peter AnvinENTRY(early_idt_handler) 5689a163ed8SThomas Gleixner cld 5694c5023a3SH. Peter Anvin cmpl $2,%ss:early_recursion_flag 5704c5023a3SH. Peter Anvin je hlt_loop 5714c5023a3SH. Peter Anvin incl %ss:early_recursion_flag 5724c5023a3SH. Peter Anvin 5734c5023a3SH. Peter Anvin push %eax # 16(%esp) 5744c5023a3SH. Peter Anvin push %ecx # 12(%esp) 5754c5023a3SH. Peter Anvin push %edx # 8(%esp) 5764c5023a3SH. Peter Anvin push %ds # 4(%esp) 5774c5023a3SH. Peter Anvin push %es # 0(%esp) 5789a163ed8SThomas Gleixner movl $(__KERNEL_DS),%eax 5799a163ed8SThomas Gleixner movl %eax,%ds 5809a163ed8SThomas Gleixner movl %eax,%es 5814c5023a3SH. Peter Anvin 5824c5023a3SH. Peter Anvin cmpl $(__KERNEL_CS),32(%esp) 5834c5023a3SH. Peter Anvin jne 10f 5844c5023a3SH. Peter Anvin 5854c5023a3SH. Peter Anvin leal 28(%esp),%eax # Pointer to %eip 5864c5023a3SH. Peter Anvin call early_fixup_exception 5874c5023a3SH. Peter Anvin andl %eax,%eax 5884c5023a3SH. Peter Anvin jnz ex_entry /* found an exception entry */ 5894c5023a3SH. Peter Anvin 5904c5023a3SH. Peter Anvin10: 5914c5023a3SH. Peter Anvin#ifdef CONFIG_PRINTK 5924c5023a3SH. Peter Anvin xorl %eax,%eax 5934c5023a3SH. Peter Anvin movw %ax,2(%esp) /* clean up the segment values on some cpus */ 5944c5023a3SH. Peter Anvin movw %ax,6(%esp) 5954c5023a3SH. Peter Anvin movw %ax,34(%esp) 5964c5023a3SH. Peter Anvin leal 40(%esp),%eax 5974c5023a3SH. Peter Anvin pushl %eax /* %esp before the exception */ 5984c5023a3SH. Peter Anvin pushl %ebx 5994c5023a3SH. Peter Anvin pushl %ebp 6004c5023a3SH. Peter Anvin pushl %esi 6014c5023a3SH. Peter Anvin pushl %edi 6029a163ed8SThomas Gleixner movl %cr2,%eax 6039a163ed8SThomas Gleixner pushl %eax 6044c5023a3SH. Peter Anvin pushl (20+6*4)(%esp) /* trapno */ 6059a163ed8SThomas Gleixner pushl $fault_msg 6069a163ed8SThomas Gleixner call printk 6079a163ed8SThomas Gleixner#endif 60894878efdSIngo Molnar call dump_stack 6099a163ed8SThomas Gleixnerhlt_loop: 6109a163ed8SThomas Gleixner hlt 6119a163ed8SThomas Gleixner jmp hlt_loop 6129a163ed8SThomas Gleixner 6134c5023a3SH. Peter Anvinex_entry: 6144c5023a3SH. Peter Anvin pop %es 6154c5023a3SH. Peter Anvin pop %ds 6164c5023a3SH. Peter Anvin pop %edx 6174c5023a3SH. Peter Anvin pop %ecx 6184c5023a3SH. Peter Anvin pop %eax 6194c5023a3SH. Peter Anvin addl $8,%esp /* drop vector number and error code */ 6204c5023a3SH. Peter Anvin decl %ss:early_recursion_flag 6214c5023a3SH. Peter Anvin iret 6224c5023a3SH. Peter AnvinENDPROC(early_idt_handler) 6234c5023a3SH. Peter Anvin 6249a163ed8SThomas Gleixner/* This is the default interrupt "handler" :-) */ 6259a163ed8SThomas Gleixner ALIGN 6269a163ed8SThomas Gleixnerignore_int: 6279a163ed8SThomas Gleixner cld 6289a163ed8SThomas Gleixner#ifdef CONFIG_PRINTK 6299a163ed8SThomas Gleixner pushl %eax 6309a163ed8SThomas Gleixner pushl %ecx 6319a163ed8SThomas Gleixner pushl %edx 6329a163ed8SThomas Gleixner pushl %es 6339a163ed8SThomas Gleixner pushl %ds 6349a163ed8SThomas Gleixner movl $(__KERNEL_DS),%eax 6359a163ed8SThomas Gleixner movl %eax,%ds 6369a163ed8SThomas Gleixner movl %eax,%es 6379a163ed8SThomas Gleixner cmpl $2,early_recursion_flag 6389a163ed8SThomas Gleixner je hlt_loop 6399a163ed8SThomas Gleixner incl early_recursion_flag 6409a163ed8SThomas Gleixner pushl 16(%esp) 6419a163ed8SThomas Gleixner pushl 24(%esp) 6429a163ed8SThomas Gleixner pushl 32(%esp) 6439a163ed8SThomas Gleixner pushl 40(%esp) 6449a163ed8SThomas Gleixner pushl $int_msg 6459a163ed8SThomas Gleixner call printk 646d5e397cbSIngo Molnar 647d5e397cbSIngo Molnar call dump_stack 648d5e397cbSIngo Molnar 6499a163ed8SThomas Gleixner addl $(5*4),%esp 6509a163ed8SThomas Gleixner popl %ds 6519a163ed8SThomas Gleixner popl %es 6529a163ed8SThomas Gleixner popl %edx 6539a163ed8SThomas Gleixner popl %ecx 6549a163ed8SThomas Gleixner popl %eax 6559a163ed8SThomas Gleixner#endif 6569a163ed8SThomas Gleixner iret 6574c5023a3SH. Peter AnvinENDPROC(ignore_int) 6584c5023a3SH. Peter Anvin__INITDATA 6594c5023a3SH. Peter Anvin .align 4 6604c5023a3SH. Peter Anvinearly_recursion_flag: 6614c5023a3SH. Peter Anvin .long 0 662ebba638aSKees Cook 6630e83815bSRobert Richter__REFDATA 664583323b9SThomas Gleixner .align 4 665583323b9SThomas GleixnerENTRY(initial_code) 666583323b9SThomas Gleixner .long i386_start_kernel 6674c5023a3SH. Peter AnvinENTRY(setup_once_ref) 6684c5023a3SH. Peter Anvin .long setup_once 669583323b9SThomas Gleixner 6709a163ed8SThomas Gleixner/* 6719a163ed8SThomas Gleixner * BSS section 6729a163ed8SThomas Gleixner */ 67302b7da37STim Abbott__PAGE_ALIGNED_BSS 6747bf04be8SStratos Psomadakis .align PAGE_SIZE 675551889a6SIan Campbell#ifdef CONFIG_X86_PAE 676d50d8fe1SRusty Russellinitial_pg_pmd: 677551889a6SIan Campbell .fill 1024*KPMDS,4,0 678551889a6SIan Campbell#else 679b40827faSBorislav PetkovENTRY(initial_page_table) 6809a163ed8SThomas Gleixner .fill 1024,4,0 681551889a6SIan Campbell#endif 682d50d8fe1SRusty Russellinitial_pg_fixmap: 6839a163ed8SThomas Gleixner .fill 1024,4,0 6849a163ed8SThomas GleixnerENTRY(empty_zero_page) 6859a163ed8SThomas Gleixner .fill 4096,1,0 686b40827faSBorislav PetkovENTRY(swapper_pg_dir) 687b40827faSBorislav Petkov .fill 1024,4,0 6882bd2753fSYinghai Lu 6899a163ed8SThomas Gleixner/* 6909a163ed8SThomas Gleixner * This starts the data section. 6919a163ed8SThomas Gleixner */ 692551889a6SIan Campbell#ifdef CONFIG_X86_PAE 693abe1ee3aSTim Abbott__PAGE_ALIGNED_DATA 694551889a6SIan Campbell /* Page-aligned for the benefit of paravirt? */ 6957bf04be8SStratos Psomadakis .align PAGE_SIZE 696b40827faSBorislav PetkovENTRY(initial_page_table) 697b40827faSBorislav Petkov .long pa(initial_pg_pmd+PGD_IDENT_ATTR),0 /* low identity map */ 698551889a6SIan Campbell# if KPMDS == 3 699b40827faSBorislav Petkov .long pa(initial_pg_pmd+PGD_IDENT_ATTR),0 700b40827faSBorislav Petkov .long pa(initial_pg_pmd+PGD_IDENT_ATTR+0x1000),0 701b40827faSBorislav Petkov .long pa(initial_pg_pmd+PGD_IDENT_ATTR+0x2000),0 702551889a6SIan Campbell# elif KPMDS == 2 703551889a6SIan Campbell .long 0,0 704b40827faSBorislav Petkov .long pa(initial_pg_pmd+PGD_IDENT_ATTR),0 705b40827faSBorislav Petkov .long pa(initial_pg_pmd+PGD_IDENT_ATTR+0x1000),0 706551889a6SIan Campbell# elif KPMDS == 1 707551889a6SIan Campbell .long 0,0 708551889a6SIan Campbell .long 0,0 709b40827faSBorislav Petkov .long pa(initial_pg_pmd+PGD_IDENT_ATTR),0 710551889a6SIan Campbell# else 711551889a6SIan Campbell# error "Kernel PMDs should be 1, 2 or 3" 712551889a6SIan Campbell# endif 7137bf04be8SStratos Psomadakis .align PAGE_SIZE /* needs to be page-sized too */ 714551889a6SIan Campbell#endif 715551889a6SIan Campbell 7169a163ed8SThomas Gleixner.data 71711d4c3f9SH. Peter Anvin.balign 4 7189a163ed8SThomas GleixnerENTRY(stack_start) 7199a163ed8SThomas Gleixner .long init_thread_union+THREAD_SIZE 7209a163ed8SThomas Gleixner 7214c5023a3SH. Peter Anvin__INITRODATA 7229a163ed8SThomas Gleixnerint_msg: 723d5e397cbSIngo Molnar .asciz "Unknown interrupt or fault at: %p %p %p\n" 7249a163ed8SThomas Gleixner 7259a163ed8SThomas Gleixnerfault_msg: 726575ca735SVegard Nossum/* fault info: */ 727575ca735SVegard Nossum .ascii "BUG: Int %d: CR2 %p\n" 7284c5023a3SH. Peter Anvin/* regs pushed in early_idt_handler: */ 7294c5023a3SH. Peter Anvin .ascii " EDI %p ESI %p EBP %p EBX %p\n" 7304c5023a3SH. Peter Anvin .ascii " ESP %p ES %p DS %p\n" 7314c5023a3SH. Peter Anvin .ascii " EDX %p ECX %p EAX %p\n" 732575ca735SVegard Nossum/* fault frame: */ 7334c5023a3SH. Peter Anvin .ascii " vec %p err %p EIP %p CS %p flg %p\n" 734575ca735SVegard Nossum .ascii "Stack: %p %p %p %p %p %p %p %p\n" 735575ca735SVegard Nossum .ascii " %p %p %p %p %p %p %p %p\n" 736575ca735SVegard Nossum .asciz " %p %p %p %p %p %p %p %p\n" 7379a163ed8SThomas Gleixner 7389a163ed8SThomas Gleixner#include "../../x86/xen/xen-head.S" 7399a163ed8SThomas Gleixner 7409a163ed8SThomas Gleixner/* 7419a163ed8SThomas Gleixner * The IDT and GDT 'descriptors' are a strange 48-bit object 7429a163ed8SThomas Gleixner * only used by the lidt and lgdt instructions. They are not 7439a163ed8SThomas Gleixner * like usual segment descriptors - they consist of a 16-bit 7449a163ed8SThomas Gleixner * segment size, and 32-bit linear address value: 7459a163ed8SThomas Gleixner */ 7469a163ed8SThomas Gleixner 7474c5023a3SH. Peter Anvin .data 7489a163ed8SThomas Gleixner.globl boot_gdt_descr 7499a163ed8SThomas Gleixner.globl idt_descr 7509a163ed8SThomas Gleixner 7519a163ed8SThomas Gleixner ALIGN 7529a163ed8SThomas Gleixner# early boot GDT descriptor (must use 1:1 address mapping) 7539a163ed8SThomas Gleixner .word 0 # 32 bit align gdt_desc.address 7549a163ed8SThomas Gleixnerboot_gdt_descr: 7559a163ed8SThomas Gleixner .word __BOOT_DS+7 7569a163ed8SThomas Gleixner .long boot_gdt - __PAGE_OFFSET 7579a163ed8SThomas Gleixner 7589a163ed8SThomas Gleixner .word 0 # 32-bit align idt_desc.address 7599a163ed8SThomas Gleixneridt_descr: 7609a163ed8SThomas Gleixner .word IDT_ENTRIES*8-1 # idt contains 256 entries 7619a163ed8SThomas Gleixner .long idt_table 7629a163ed8SThomas Gleixner 7639a163ed8SThomas Gleixner# boot GDT descriptor (later on used by CPU#0): 7649a163ed8SThomas Gleixner .word 0 # 32 bit align gdt_desc.address 7659a163ed8SThomas GleixnerENTRY(early_gdt_descr) 7669a163ed8SThomas Gleixner .word GDT_ENTRIES*8-1 767dd17c8f7SRusty Russell .long gdt_page /* Overwritten for secondary CPUs */ 7689a163ed8SThomas Gleixner 7699a163ed8SThomas Gleixner/* 7709a163ed8SThomas Gleixner * The boot_gdt must mirror the equivalent in setup.S and is 7719a163ed8SThomas Gleixner * used only for booting. 7729a163ed8SThomas Gleixner */ 7739a163ed8SThomas Gleixner .align L1_CACHE_BYTES 7749a163ed8SThomas GleixnerENTRY(boot_gdt) 7759a163ed8SThomas Gleixner .fill GDT_ENTRY_BOOT_CS,8,0 7769a163ed8SThomas Gleixner .quad 0x00cf9a000000ffff /* kernel 4GB code at 0x00000000 */ 7779a163ed8SThomas Gleixner .quad 0x00cf92000000ffff /* kernel 4GB data at 0x00000000 */ 778