/* Copyright (c) 2009-13 The Regents of the University of California * Barret Rhoden * See LICENSE for details. */ #include #include #include .set CODE_SEL,0x8 # index of code seg within mygdt .set DATA_SEL,0x10 # index of data seg within mygdt #define MULTIBOOT_PAGE_ALIGN (1<<0) #define MULTIBOOT_MEMORY_INFO (1<<1) #define MULTIBOOT_HEADER_MAGIC (0x1BADB002) #define MULTIBOOT_HEADER_FLAGS (MULTIBOOT_MEMORY_INFO | MULTIBOOT_PAGE_ALIGN) #define CHECKSUM (-(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS)) # The kernel bootstrap (this code) is linked and loaded at physical address # 0x00100000 (1MB), which is the start of extended memory. (See kernel.ld) # Flagging boottext to be text. Check out: # http://sourceware.org/binutils/docs/as/Section.html .section .boottext, "awx" .code32 .align 4 multiboot_header: .long MULTIBOOT_HEADER_MAGIC .long MULTIBOOT_HEADER_FLAGS .long CHECKSUM .globl _start _start: movw $0x1234,0x472 # warm boot # Reload all segment registers (including CS!) with flag segment selectors # from our boot GDT. lgdt mygdtdesc movl $DATA_SEL, %eax movw %ax,%ds movw %ax,%es movw %ax,%ss ljmp $CODE_SEL,$newcs # reload CS by jumping newcs: # build page table. need a mapping for current code at 0x00100000 and a # basic kernbase mapping. we're using the 32 bit second PT (aka, pg_dir), # which covers 4MB per entry movl $boot_pdt, %edx # identity map the first jumbo PTE from 0x0 -> 0x0 movl $(PTE_P | PTE_W | PTE_PS), (%edx) # map KERNBASE -> 0 for 1GB (1/4 of the 1024 entries) movl $256, %ecx # init loop, eax at paddr 0, and edx is advanced by KERNBASE mapping slots # (with 4 bytes per PTE). addl $((KERNBASE >> PTSHIFT) << 2), %edx movl $(PTE_P | PTE_W | PTE_PS), %eax loop: movl %eax, (%edx) addl $PTSIZE, %eax addl $4, %edx decl %ecx jnz loop # load cr3 and turn on paging. note we assume PSE support. if we didn't # have it, then our jumbo page mappings are going to fail. movl $boot_pdt, %eax movl %eax, %cr3 movl %cr4, %eax orl $(CR4_PSE | CR4_PGE), %eax movl %eax, %cr4 movl %cr0, %eax orl $(CR0_PE | CR0_PG | CR0_AM | CR0_WP | CR0_NE | CR0_MP), %eax andl $(~(CR0_TS | CR0_EM | CR0_CD | CR0_NW)), %eax movl %eax, %cr0 # paging is on, and our code is still running at 0x00100000 do some # miscellaneous OS setup. the coreid stuff is so we can call core_id() # before smp_boot. this is the only arch-dependent code called before then. movl $0x0, os_coreid_lookup movl $0x0, hw_coreid_lookup # Clear the frame pointer register (EBP) # so that once we get into debugging C code, # stack backtraces will be terminated properly. movl $0x0,%ebp movl $(bootstacktop),%esp # Save multiboot info push %ebx movl $0x1,num_cpus # init global var, for now call kernel_init # Should never get here, but in case we do, just spin. spin: jmp spin .section .bootdata, "aw" .p2align 2 # force 4 byte alignment mygdt: SEG_NULL # null seg SEG(STA_X|STA_R, 0, 0xffffffff) # code seg SEG(STA_W, 0, 0xffffffff) # data seg mygdtdesc: .word 0x17 # sizeof(mygdt) - 1 .long mygdt # address mygdt # boot page directory. going to use jumbo page entries .align PGSIZE boot_pdt: .space PGSIZE # From here down is linked for KERNBASE .data .p2align PGSHIFT # force page alignment .globl bootstack bootstack: .space KSTKSIZE .globl bootstacktop bootstacktop: