0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 .text
0011 #include <linux/threads.h>
0012 #include <linux/init.h>
0013 #include <linux/linkage.h>
0014 #include <asm/segment.h>
0015 #include <asm/page_types.h>
0016 #include <asm/pgtable_types.h>
0017 #include <asm/cache.h>
0018 #include <asm/thread_info.h>
0019 #include <asm/asm-offsets.h>
0020 #include <asm/setup.h>
0021 #include <asm/processor-flags.h>
0022 #include <asm/msr-index.h>
0023 #include <asm/cpufeatures.h>
0024 #include <asm/percpu.h>
0025 #include <asm/nops.h>
0026 #include <asm/nospec-branch.h>
0027 #include <asm/bootparam.h>
0028 #include <asm/export.h>
0029 #include <asm/pgtable_32.h>
0030
0031
0032 #define pa(X) ((X) - __PAGE_OFFSET)
0033
0034
0035
0036
0037
0038 #define X86 new_cpu_data+CPUINFO_x86
0039 #define X86_VENDOR new_cpu_data+CPUINFO_x86_vendor
0040 #define X86_MODEL new_cpu_data+CPUINFO_x86_model
0041 #define X86_STEPPING new_cpu_data+CPUINFO_x86_stepping
0042 #define X86_HARD_MATH new_cpu_data+CPUINFO_hard_math
0043 #define X86_CPUID new_cpu_data+CPUINFO_cpuid_level
0044 #define X86_CAPABILITY new_cpu_data+CPUINFO_x86_capability
0045 #define X86_VENDOR_ID new_cpu_data+CPUINFO_x86_vendor_id
0046
0047
0048 #define SIZEOF_PTREGS 17*4
0049
0050
0051
0052
0053
0054
0055 KERNEL_PAGES = LOWMEM_PAGES
0056
0057 INIT_MAP_SIZE = PAGE_TABLE_SIZE(KERNEL_PAGES) * PAGE_SIZE
0058 RESERVE_BRK(pagetables, INIT_MAP_SIZE)
0059
0060
0061
0062
0063
0064
0065
0066
0067 __HEAD
0068 SYM_CODE_START(startup_32)
0069 movl pa(initial_stack),%ecx
0070
0071
0072
0073
0074 lgdt pa(boot_gdt_descr)
0075 movl $(__BOOT_DS),%eax
0076 movl %eax,%ds
0077 movl %eax,%es
0078 movl %eax,%fs
0079 movl %eax,%gs
0080 movl %eax,%ss
0081 leal -__PAGE_OFFSET(%ecx),%esp
0082
0083
0084
0085
0086 cld
0087 xorl %eax,%eax
0088 movl $pa(__bss_start),%edi
0089 movl $pa(__bss_stop),%ecx
0090 subl %edi,%ecx
0091 shrl $2,%ecx
0092 rep ; stosl
0093
0094
0095
0096
0097
0098
0099
0100
0101 movl $pa(boot_params),%edi
0102 movl $(PARAM_SIZE/4),%ecx
0103 cld
0104 rep
0105 movsl
0106 movl pa(boot_params) + NEW_CL_POINTER,%esi
0107 andl %esi,%esi
0108 jz 1f # No command line
0109 movl $pa(boot_command_line),%edi
0110 movl $(COMMAND_LINE_SIZE/4),%ecx
0111 rep
0112 movsl
0113 1:
0114
0115 #ifdef CONFIG_OLPC
0116
0117 movl %cr3, %eax
0118 movl %eax, pa(olpc_ofw_pgd)
0119 #endif
0120
0121 #ifdef CONFIG_MICROCODE
0122
0123 call load_ucode_bsp
0124 #endif
0125
0126
0127 call mk_early_pgtbl_32
0128
0129
0130 movl $pa(initial_pg_fixmap)+PDE_IDENT_ATTR,%eax
0131 #ifdef CONFIG_X86_PAE
0132 #define KPMDS (((-__PAGE_OFFSET) >> 30) & 3)
0133 movl %eax,pa(initial_pg_pmd+0x1000*KPMDS-8)
0134 #else
0135 movl %eax,pa(initial_page_table+0xffc)
0136 #endif
0137
0138 jmp .Ldefault_entry
0139 SYM_CODE_END(startup_32)
0140
0141 #ifdef CONFIG_HOTPLUG_CPU
0142
0143
0144
0145
0146
0147 SYM_FUNC_START(start_cpu0)
0148 movl initial_stack, %ecx
0149 movl %ecx, %esp
0150 call *(initial_code)
0151 1: jmp 1b
0152 SYM_FUNC_END(start_cpu0)
0153 #endif
0154
0155
0156
0157
0158
0159
0160
0161
0162
0163 SYM_FUNC_START(startup_32_smp)
0164 cld
0165 movl $(__BOOT_DS),%eax
0166 movl %eax,%ds
0167 movl %eax,%es
0168 movl %eax,%fs
0169 movl %eax,%gs
0170 movl pa(initial_stack),%ecx
0171 movl %eax,%ss
0172 leal -__PAGE_OFFSET(%ecx),%esp
0173
0174 #ifdef CONFIG_MICROCODE
0175
0176 call load_ucode_ap
0177 #endif
0178
0179 .Ldefault_entry:
0180 movl $(CR0_STATE & ~X86_CR0_PG),%eax
0181 movl %eax,%cr0
0182
0183
0184
0185
0186
0187
0188
0189
0190 pushl $0
0191 popfl
0192
0193
0194
0195
0196
0197
0198
0199 movl $-1,pa(X86_CPUID) # preset CPUID level
0200 movl $X86_EFLAGS_ID,%ecx
0201 pushl %ecx
0202 popfl # set EFLAGS=ID
0203 pushfl
0204 popl %eax # get EFLAGS
0205 testl $X86_EFLAGS_ID,%eax # did EFLAGS.ID remained set?
0206 jz .Lenable_paging # hw disallowed setting of ID bit
0207 # which means no CPUID and no CR4
0208
0209 xorl %eax,%eax
0210 cpuid
0211 movl %eax,pa(X86_CPUID) # save largest std CPUID function
0212
0213 movl $1,%eax
0214 cpuid
0215 andl $~1,%edx # Ignore CPUID.FPU
0216 jz .Lenable_paging # No flags or only CPUID.FPU = no CR4
0217
0218 movl pa(mmu_cr4_features),%eax
0219 movl %eax,%cr4
0220
0221 testb $X86_CR4_PAE, %al # check if PAE is enabled
0222 jz .Lenable_paging
0223
0224
0225 movl $0x80000000, %eax
0226 cpuid
0227
0228 subl $0x80000001, %eax
0229 cmpl $(0x8000ffff-0x80000001), %eax
0230 ja .Lenable_paging
0231
0232
0233 call verify_cpu
0234
0235 mov $0x80000001, %eax
0236 cpuid
0237
0238 btl $(X86_FEATURE_NX & 31), %edx
0239 jnc .Lenable_paging
0240
0241
0242 movl $MSR_EFER, %ecx
0243 rdmsr
0244
0245 btsl $_EFER_NX, %eax
0246
0247 wrmsr
0248
0249 .Lenable_paging:
0250
0251
0252
0253
0254 movl $pa(initial_page_table), %eax
0255 movl %eax,%cr3
0256 movl $CR0_STATE,%eax
0257 movl %eax,%cr0
0258 ljmp $__BOOT_CS,$1f
0259 1:
0260
0261 addl $__PAGE_OFFSET, %esp
0262
0263
0264
0265
0266
0267 movl setup_once_ref,%eax
0268 andl %eax,%eax
0269 jz 1f # Did we do this already?
0270 call *%eax
0271 1:
0272
0273
0274
0275
0276 movb $4,X86 # at least 486
0277 cmpl $-1,X86_CPUID
0278 je .Lis486
0279
0280
0281 xorl %eax,%eax # call CPUID with 0 -> return vendor ID
0282 cpuid
0283 movl %eax,X86_CPUID # save CPUID level
0284 movl %ebx,X86_VENDOR_ID # lo 4 chars
0285 movl %edx,X86_VENDOR_ID+4 # next 4 chars
0286 movl %ecx,X86_VENDOR_ID+8 # last 4 chars
0287
0288 orl %eax,%eax # do we have processor info as well?
0289 je .Lis486
0290
0291 movl $1,%eax # Use the CPUID instruction to get CPU type
0292 cpuid
0293 movb %al,%cl # save reg for future use
0294 andb $0x0f,%ah # mask processor family
0295 movb %ah,X86
0296 andb $0xf0,%al # mask model
0297 shrb $4,%al
0298 movb %al,X86_MODEL
0299 andb $0x0f,%cl # mask mask revision
0300 movb %cl,X86_STEPPING
0301 movl %edx,X86_CAPABILITY
0302
0303 .Lis486:
0304 movl $0x50022,%ecx # set AM, WP, NE and MP
0305 movl %cr0,%eax
0306 andl $0x80000011,%eax # Save PG,PE,ET
0307 orl %ecx,%eax
0308 movl %eax,%cr0
0309
0310 lgdt early_gdt_descr
0311 ljmp $(__KERNEL_CS),$1f
0312 1: movl $(__KERNEL_DS),%eax # reload all the segment registers
0313 movl %eax,%ss # after changing gdt.
0314
0315 movl $(__USER_DS),%eax # DS/ES contains default USER segment
0316 movl %eax,%ds
0317 movl %eax,%es
0318
0319 movl $(__KERNEL_PERCPU), %eax
0320 movl %eax,%fs # set this cpu's percpu
0321
0322 xorl %eax,%eax
0323 movl %eax,%gs # clear possible garbage in %gs
0324
0325 xorl %eax,%eax # Clear LDT
0326 lldt %ax
0327
0328 call *(initial_code)
0329 1: jmp 1b
0330 SYM_FUNC_END(startup_32_smp)
0331
0332 #include "verify_cpu.S"
0333
0334
0335
0336
0337
0338
0339
0340
0341 __INIT
0342 setup_once:
0343 andl $0,setup_once_ref
0344 RET
0345
0346 SYM_FUNC_START(early_idt_handler_array)
0347 # 36(%esp) %eflags
0348 # 32(%esp) %cs
0349 # 28(%esp) %eip
0350 # 24(%rsp) error code
0351 i = 0
0352 .rept NUM_EXCEPTION_VECTORS
0353 .if ((EXCEPTION_ERRCODE_MASK >> i) & 1) == 0
0354 pushl $0 # Dummy error code, to make stack frame uniform
0355 .endif
0356 pushl $i # 20(%esp) Vector number
0357 jmp early_idt_handler_common
0358 i = i + 1
0359 .fill early_idt_handler_array + i*EARLY_IDT_HANDLER_SIZE - ., 1, 0xcc
0360 .endr
0361 SYM_FUNC_END(early_idt_handler_array)
0362
0363 SYM_CODE_START_LOCAL(early_idt_handler_common)
0364
0365
0366
0367
0368 cld
0369
0370 incl %ss:early_recursion_flag
0371
0372
0373
0374 cld
0375 pushl %fs
0376 pushl %es
0377 pushl %ds
0378 pushl %eax
0379 pushl %ebp
0380 pushl %edi
0381 pushl %esi
0382 pushl %edx
0383 pushl %ecx
0384 pushl %ebx
0385
0386
0387 movl $(__KERNEL_DS), %ecx
0388 movl %ecx, %ds
0389 movl %ecx, %es
0390
0391
0392 movl PT_GS(%esp), %edx
0393
0394
0395 movw %gs, PT_GS(%esp)
0396
0397 movl %esp, %eax
0398 call early_fixup_exception
0399
0400 popl %ebx
0401 popl %ecx
0402 popl %edx
0403 popl %esi
0404 popl %edi
0405 popl %ebp
0406 popl %eax
0407 popl %ds
0408 popl %es
0409 popl %fs
0410 popl %gs
0411 decl %ss:early_recursion_flag
0412 addl $4, %esp
0413 iret
0414 SYM_CODE_END(early_idt_handler_common)
0415
0416
0417 SYM_FUNC_START(early_ignore_irq)
0418 cld
0419 #ifdef CONFIG_PRINTK
0420 pushl %eax
0421 pushl %ecx
0422 pushl %edx
0423 pushl %es
0424 pushl %ds
0425 movl $(__KERNEL_DS),%eax
0426 movl %eax,%ds
0427 movl %eax,%es
0428 cmpl $2,early_recursion_flag
0429 je hlt_loop
0430 incl early_recursion_flag
0431 pushl 16(%esp)
0432 pushl 24(%esp)
0433 pushl 32(%esp)
0434 pushl 40(%esp)
0435 pushl $int_msg
0436 call _printk
0437
0438 call dump_stack
0439
0440 addl $(5*4),%esp
0441 popl %ds
0442 popl %es
0443 popl %edx
0444 popl %ecx
0445 popl %eax
0446 #endif
0447 iret
0448
0449 hlt_loop:
0450 hlt
0451 jmp hlt_loop
0452 SYM_FUNC_END(early_ignore_irq)
0453
0454 __INITDATA
0455 .align 4
0456 SYM_DATA(early_recursion_flag, .long 0)
0457
0458 __REFDATA
0459 .align 4
0460 SYM_DATA(initial_code, .long i386_start_kernel)
0461 SYM_DATA(setup_once_ref, .long setup_once)
0462
0463 #ifdef CONFIG_PAGE_TABLE_ISOLATION
0464 #define PGD_ALIGN (2 * PAGE_SIZE)
0465 #define PTI_USER_PGD_FILL 1024
0466 #else
0467 #define PGD_ALIGN (PAGE_SIZE)
0468 #define PTI_USER_PGD_FILL 0
0469 #endif
0470
0471
0472
0473 __PAGE_ALIGNED_BSS
0474 .align PGD_ALIGN
0475 #ifdef CONFIG_X86_PAE
0476 .globl initial_pg_pmd
0477 initial_pg_pmd:
0478 .fill 1024*KPMDS,4,0
0479 #else
0480 .globl initial_page_table
0481 initial_page_table:
0482 .fill 1024,4,0
0483 #endif
0484 .align PGD_ALIGN
0485 initial_pg_fixmap:
0486 .fill 1024,4,0
0487 .globl swapper_pg_dir
0488 .align PGD_ALIGN
0489 swapper_pg_dir:
0490 .fill 1024,4,0
0491 .fill PTI_USER_PGD_FILL,4,0
0492 .globl empty_zero_page
0493 empty_zero_page:
0494 .fill 4096,1,0
0495 EXPORT_SYMBOL(empty_zero_page)
0496
0497
0498
0499
0500 #ifdef CONFIG_X86_PAE
0501 __PAGE_ALIGNED_DATA
0502
0503 .align PGD_ALIGN
0504 SYM_DATA_START(initial_page_table)
0505 .long pa(initial_pg_pmd+PGD_IDENT_ATTR),0
0506 # if KPMDS == 3
0507 .long pa(initial_pg_pmd+PGD_IDENT_ATTR),0
0508 .long pa(initial_pg_pmd+PGD_IDENT_ATTR+0x1000),0
0509 .long pa(initial_pg_pmd+PGD_IDENT_ATTR+0x2000),0
0510 # elif KPMDS == 2
0511 .long 0,0
0512 .long pa(initial_pg_pmd+PGD_IDENT_ATTR),0
0513 .long pa(initial_pg_pmd+PGD_IDENT_ATTR+0x1000),0
0514 # elif KPMDS == 1
0515 .long 0,0
0516 .long 0,0
0517 .long pa(initial_pg_pmd+PGD_IDENT_ATTR),0
0518 # else
0519 # error "Kernel PMDs should be 1, 2 or 3"
0520 # endif
0521 .align PAGE_SIZE
0522
0523 #ifdef CONFIG_PAGE_TABLE_ISOLATION
0524
0525
0526
0527
0528
0529 .fill 1024, 4, 0
0530 #endif
0531
0532 SYM_DATA_END(initial_page_table)
0533 #endif
0534
0535 .data
0536 .balign 4
0537
0538
0539
0540
0541 SYM_DATA(initial_stack,
0542 .long init_thread_union + THREAD_SIZE -
0543 SIZEOF_PTREGS - TOP_OF_KERNEL_STACK_PADDING)
0544
0545 __INITRODATA
0546 int_msg:
0547 .asciz "Unknown interrupt or fault at: %p %p %p\n"
0548
0549 #include "../../x86/xen/xen-head.S"
0550
0551
0552
0553
0554
0555
0556
0557
0558 .data
0559 ALIGN
0560 # early boot GDT descriptor (must use 1:1 address mapping)
0561 .word 0 # 32 bit align gdt_desc.address
0562 SYM_DATA_START_LOCAL(boot_gdt_descr)
0563 .word __BOOT_DS+7
0564 .long boot_gdt - __PAGE_OFFSET
0565 SYM_DATA_END(boot_gdt_descr)
0566
0567 # boot GDT descriptor (later on used by CPU#0):
0568 .word 0 # 32 bit align gdt_desc.address
0569 SYM_DATA_START(early_gdt_descr)
0570 .word GDT_ENTRIES*8-1
0571 .long gdt_page
0572 SYM_DATA_END(early_gdt_descr)
0573
0574
0575
0576
0577
0578 .align L1_CACHE_BYTES
0579 SYM_DATA_START(boot_gdt)
0580 .fill GDT_ENTRY_BOOT_CS,8,0
0581 .quad 0x00cf9a000000ffff
0582 .quad 0x00cf92000000ffff
0583 SYM_DATA_END(boot_gdt)