2016-02-24 18:59:31 -08:00
|
|
|
/*
|
|
|
|
|
* Copyright (c) 2009 Corey Tabaka
|
|
|
|
|
* Copyright (c) 2015 Intel Corporation
|
|
|
|
|
* Copyright (c) 2016 Travis Geiselbrecht
|
|
|
|
|
*
|
2019-07-05 17:22:23 -07:00
|
|
|
* Use of this source code is governed by a MIT-style
|
|
|
|
|
* license that can be found in the LICENSE file or at
|
|
|
|
|
* https://opensource.org/licenses/MIT
|
2016-02-24 18:59:31 -08:00
|
|
|
*/
|
2019-06-17 18:28:51 -07:00
|
|
|
#include <lk/asm.h>
|
2016-02-24 18:59:31 -08:00
|
|
|
#include <arch/x86/descriptor.h>
|
|
|
|
|
#include <arch/x86/mmu.h>
|
2022-08-07 23:04:23 -07:00
|
|
|
#include <hw/multiboot.h>
|
2016-02-24 18:59:31 -08:00
|
|
|
|
|
|
|
|
#define PHYS_LOAD_ADDRESS (MEMBASE + KERNEL_LOAD_OFFSET)
|
|
|
|
|
#define PHYS_ADDR_DELTA (KERNEL_BASE + KERNEL_LOAD_OFFSET - PHYS_LOAD_ADDRESS)
|
|
|
|
|
#define PHYS(x) ((x) - PHYS_ADDR_DELTA)
|
|
|
|
|
|
|
|
|
|
.section ".text.boot"
|
|
|
|
|
.global _start
|
|
|
|
|
_start:
|
|
|
|
|
jmp real_start
|
|
|
|
|
|
|
|
|
|
.align 4
|
|
|
|
|
|
2022-08-07 23:04:23 -07:00
|
|
|
/* flags for multiboot header */
|
|
|
|
|
#define MULTIBOOT_HEADER_FLAGS (MULTIBOOT_PAGE_ALIGN | MULTIBOOT_MEMORY_INFO | MULTIBOOT_AOUT_KLUDGE)
|
|
|
|
|
|
2016-02-24 18:59:31 -08:00
|
|
|
.type multiboot_header,STT_OBJECT
|
|
|
|
|
multiboot_header:
|
|
|
|
|
/* magic */
|
|
|
|
|
.int MULTIBOOT_HEADER_MAGIC
|
|
|
|
|
/* flags */
|
|
|
|
|
.int MULTIBOOT_HEADER_FLAGS
|
|
|
|
|
/* checksum */
|
|
|
|
|
.int -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS)
|
|
|
|
|
|
|
|
|
|
/* header_addr */
|
|
|
|
|
.int PHYS(multiboot_header)
|
|
|
|
|
/* load_addr */
|
|
|
|
|
.int PHYS(_start)
|
|
|
|
|
/* load_end_addr */
|
|
|
|
|
.int PHYS(__data_end)
|
|
|
|
|
/* bss_end_addr */
|
|
|
|
|
.int PHYS(__bss_end)
|
|
|
|
|
/* entry_addr */
|
|
|
|
|
.int PHYS(real_start)
|
|
|
|
|
|
|
|
|
|
real_start:
|
|
|
|
|
cmpl $MULTIBOOT_BOOTLOADER_MAGIC, %eax
|
|
|
|
|
jne 0f
|
|
|
|
|
movl %ebx, PHYS(_multiboot_info)
|
|
|
|
|
|
|
|
|
|
0:
|
|
|
|
|
/* load our new gdt by physical pointer */
|
|
|
|
|
lgdt PHYS(_gdtr_phys)
|
|
|
|
|
|
|
|
|
|
movw $DATA_SELECTOR, %ax
|
|
|
|
|
movw %ax, %ds
|
|
|
|
|
movw %ax, %es
|
|
|
|
|
movw %ax, %fs
|
|
|
|
|
movw %ax, %ss
|
|
|
|
|
movw %ax, %gs
|
|
|
|
|
movw %ax, %ss
|
|
|
|
|
|
2016-08-15 17:55:40 +02:00
|
|
|
/* load initial stack pointer */
|
2016-03-08 17:17:45 +08:00
|
|
|
movl $PHYS(_kstack + 4096), %esp
|
|
|
|
|
|
2016-02-24 18:59:31 -08:00
|
|
|
/*We jumped here in protected mode in a code segment that migh not longer
|
|
|
|
|
be valid , do a long jump to our code segment, we use retf instead of
|
|
|
|
|
ljmp to be able to use relative labels */
|
|
|
|
|
pushl $CODE_SELECTOR /*Pushing our code segment */
|
|
|
|
|
pushl $PHYS(.Lfarjump) /*and jump address */
|
|
|
|
|
retf /*This instruction will jump to codesel:farjump */
|
|
|
|
|
|
|
|
|
|
.Lfarjump:
|
|
|
|
|
|
|
|
|
|
/* zero the bss section */
|
|
|
|
|
bss_setup:
|
|
|
|
|
movl $PHYS(__bss_start), %edi /* starting address of the bss */
|
|
|
|
|
movl $PHYS(__bss_end), %ecx /* find the length of the bss in bytes */
|
|
|
|
|
subl %edi, %ecx
|
|
|
|
|
shrl $2, %ecx /* convert to 32 bit words, since the bss is aligned anyway */
|
|
|
|
|
2:
|
|
|
|
|
movl $0, (%edi)
|
|
|
|
|
addl $4, %edi
|
|
|
|
|
loop 2b
|
|
|
|
|
|
|
|
|
|
paging_setup:
|
2022-10-21 01:37:01 -07:00
|
|
|
#if X86_LEGACY
|
2018-12-30 21:03:27 -08:00
|
|
|
/* map the first 16MB 1:1 with 4KB pages and again at 0x8000.0000 */
|
|
|
|
|
|
|
|
|
|
/* set up 4 page tables worth of entries */
|
2020-07-25 16:46:34 -07:00
|
|
|
movl $PHYS(kernel_pt), %edi
|
2018-12-30 21:03:27 -08:00
|
|
|
movl $1024*4,%ecx
|
|
|
|
|
movl $X86_KERNEL_PT_FLAGS, %eax
|
|
|
|
|
|
|
|
|
|
.Lfill_pt:
|
|
|
|
|
movl %eax, (%edi)
|
|
|
|
|
addl $4, %edi
|
|
|
|
|
addl $4096, %eax
|
|
|
|
|
loop .Lfill_pt
|
|
|
|
|
|
|
|
|
|
/* set up the page dir with 4 entries at 0 and 0x8000.0000 pointing
|
|
|
|
|
* to 4 page tables that will map physical address 0 - 16MB
|
|
|
|
|
*/
|
2020-07-25 16:46:34 -07:00
|
|
|
movl $PHYS(kernel_pd), %esi
|
|
|
|
|
movl $PHYS(kernel_pd) + 512*4, %edi
|
|
|
|
|
movl $PHYS(kernel_pt) + X86_KERNEL_PT_FLAGS, %eax
|
2018-12-30 21:03:27 -08:00
|
|
|
movl %eax, (%esi)
|
|
|
|
|
movl %eax, (%edi)
|
|
|
|
|
addl $4096, %eax
|
|
|
|
|
movl %eax, 4(%esi)
|
|
|
|
|
movl %eax, 4(%edi)
|
|
|
|
|
addl $4096, %eax
|
|
|
|
|
movl %eax, 8(%esi)
|
|
|
|
|
movl %eax, 8(%edi)
|
|
|
|
|
addl $4096, %eax
|
|
|
|
|
movl %eax, 12(%esi)
|
|
|
|
|
movl %eax, 12(%edi)
|
2016-02-24 18:59:31 -08:00
|
|
|
#else
|
2018-12-30 21:03:27 -08:00
|
|
|
/* map the first 1GB 1:1 using 4MB pages */
|
2020-07-25 16:46:34 -07:00
|
|
|
movl $PHYS(kernel_pd), %esi
|
2016-02-24 18:59:31 -08:00
|
|
|
movl $0x100, %ecx
|
|
|
|
|
xor %eax, %eax
|
|
|
|
|
|
|
|
|
|
.Lfill_pd:
|
|
|
|
|
mov %eax, %edx
|
|
|
|
|
orl $X86_KERNEL_PD_LP_FLAGS, %edx
|
|
|
|
|
movl %edx, (%esi)
|
|
|
|
|
addl $4, %esi
|
|
|
|
|
addl $0x00400000, %eax
|
|
|
|
|
loop .Lfill_pd
|
|
|
|
|
|
|
|
|
|
/* map the first 1GB to KERNEL_ASPACE_BASE */
|
2020-07-25 16:46:34 -07:00
|
|
|
movl $(PHYS(kernel_pd) + 0x800), %esi
|
2016-02-24 18:59:31 -08:00
|
|
|
movl $0x100, %ecx
|
|
|
|
|
xor %eax, %eax
|
|
|
|
|
|
|
|
|
|
.Lfill_pd2:
|
|
|
|
|
mov %eax, %edx
|
|
|
|
|
orl $X86_KERNEL_PD_LP_FLAGS, %edx
|
|
|
|
|
movl %edx, (%esi)
|
|
|
|
|
addl $4, %esi
|
|
|
|
|
addl $0x00400000, %eax
|
|
|
|
|
loop .Lfill_pd2
|
|
|
|
|
|
2024-12-11 00:17:09 -08:00
|
|
|
/* enable PSE (4MB pages) */
|
|
|
|
|
mov %cr4, %eax
|
|
|
|
|
orl $(1<<4), %eax
|
|
|
|
|
mov %eax, %cr4
|
|
|
|
|
#endif
|
|
|
|
|
|
2016-02-24 18:59:31 -08:00
|
|
|
/* Set PD in CR3 */
|
2020-07-25 16:46:34 -07:00
|
|
|
movl $PHYS(kernel_pd), %eax
|
2016-02-24 18:59:31 -08:00
|
|
|
mov %eax, %cr3
|
|
|
|
|
|
2025-04-13 22:43:28 -07:00
|
|
|
/* save a copy of the address of the kernel page directory */
|
|
|
|
|
movl %eax, PHYS(kernel_pd_phys)
|
|
|
|
|
|
2016-02-24 18:59:31 -08:00
|
|
|
/* Enabling Paging and from this point we are in */
|
|
|
|
|
mov %cr0, %eax
|
|
|
|
|
btsl $(31), %eax
|
|
|
|
|
mov %eax, %cr0
|
|
|
|
|
|
|
|
|
|
/* load the high kernel stack */
|
|
|
|
|
movl $(_kstack + 4096), %esp
|
|
|
|
|
|
|
|
|
|
/* reload the high gdtr */
|
|
|
|
|
lgdt PHYS(_gdtr)
|
|
|
|
|
|
|
|
|
|
/* branch to the high address */
|
|
|
|
|
movl $main_lk, %eax
|
|
|
|
|
jmp *%eax
|
|
|
|
|
|
|
|
|
|
main_lk:
|
|
|
|
|
/* set up the idt */
|
|
|
|
|
call setup_idt
|
|
|
|
|
|
2024-12-06 22:10:49 -08:00
|
|
|
/* set up the percpu data structure pointer for the boot cpu */
|
2025-09-22 20:57:30 -07:00
|
|
|
/* NOTE: sets the first cpu as APIC id 0 for now, which may not be correct. Fixed later in boot. */
|
2024-12-06 22:10:49 -08:00
|
|
|
pushl $0
|
|
|
|
|
pushl $0
|
2024-12-13 00:07:46 -08:00
|
|
|
call x86_configure_percpu_early
|
2024-12-06 22:10:49 -08:00
|
|
|
|
2016-02-24 18:59:31 -08:00
|
|
|
/* call the main module */
|
|
|
|
|
call lk_main
|
|
|
|
|
0: /* just sit around waiting for interrupts */
|
|
|
|
|
hlt /* interrupts will unhalt the processor */
|
|
|
|
|
pause
|
|
|
|
|
jmp 0b /* so jump back to halt to conserve power */
|