123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322 |
- .section .stage1
- #include <kernel/mem/paging_asm.h>
- .code16
- .align 4
- .Lbios_idt_desc:
- .word 0x03ff # size
- .long 0x00000000 # base
- .align 4
- .Lnull_idt_desc:
- .word 0 # size
- .long 0 # base
- .Lhalt16:
- hlt
- jmp .Lhalt16
- # scratch %eax
- # return address should be of 2 bytes, and will be zero extended to 4 bytes
- go_32bit:
- cli
- lidt .Lnull_idt_desc
- # set PE bit
- mov %cr0, %eax
- or $1, %eax
- mov %eax, %cr0
- ljmp $0x08, $.Lgo_32bit0
- .Lgo_16bit0:
- mov $0x20, %ax
- mov %ax, %ds
- mov %ax, %ss
- lidt .Lbios_idt_desc
- mov %cr0, %eax
- and $0xfffffffe, %eax
- mov %eax, %cr0
- ljmp $0x00, $.Lgo_16bit1
- .Lgo_16bit1:
- xor %ax, %ax
- mov %ax, %ds
- mov %ax, %ss
- mov %ax, %es
- sti
- pop %eax
- push %ax
- ret
- .code32
- # scratch %eax
- # return address should be of 4 bytes, and extra 2 bytes will be popped from the stack
- go_16bit:
- cli
- ljmp $0x18, $.Lgo_16bit0
- .Lgo_32bit0:
- mov $0x10, %ax
- mov %ax, %ds
- mov %ax, %es
- mov %ax, %ss
- pop %ax
- movzw %ax, %eax
- push %eax
- ret
- # build read disk packet on the stack and perform read operation
- #
- # read 32k to 0x2000 and then copy to destination
- #
- # %edi: lba start
- # %esi: destination
- .code32
- read_disk:
- push %ebp
- mov %esp, %ebp
- lea -24(%esp), %esp
- mov $0x00400010, %eax # packet size 0, sector count 64
- mov %eax, (%esp)
- mov $0x02000000, %eax # destination address 0x0200:0x0000
- mov %eax, 4(%esp)
- mov %edi, 8(%esp) # lba low 4bytes
- xor %eax, %eax
- mov %eax, 12(%esp) # lba high 2bytes
- mov %esi, %edi
- mov %esp, %esi # packet address
- call go_16bit
- .code16
- mov $0x42, %ah
- mov $0x80, %dl
- int $0x13
- jc .Lhalt16
- call go_32bit
- .code32
- # move data to destination
- mov $0x2000, %esi
- mov $8192, %ecx
- rep movsl
- mov %ebp, %esp
- pop %ebp
- ret
- .globl start_32bit
- start_32bit:
- mov $0x10, %ax
- mov %ax, %ds
- mov %ax, %es
- mov %ax, %ss
- # read kimage into memory
- lea -16(%esp), %esp
- mov $KIMAGE_32K_COUNT, %ecx
- movl $KERNEL_IMAGE_PADDR, 4(%esp) # destination address
- movl $9, (%esp) # LBA
- .Lread_kimage:
- mov (%esp), %edi
- mov 4(%esp), %esi
- mov %ecx, %ebx
- call read_disk
- mov %ebx, %ecx
- addl $0x8000, 4(%esp)
- addl $64, (%esp)
- loop .Lread_kimage
- lea 16(%esp), %esp
- cld
- xor %eax, %eax
- # clear paging structures
- mov $0x2000, %edi
- mov $0x6000, %ecx
- shr $2, %ecx # %ecx /= 4
- rep stosl
- # set P, RW, G
- mov $(PA_P | PA_RW | PA_G), %ebx
- xor %edx, %edx
- mov $KERNEL_PDPT_PHYS_MAPPING, %esi
- # PML4E 0x000
- # we need the first 1GB identically mapped
- # so that we won't trigger a triple fault after
- # enabling paging
- mov $KERNEL_PML4, %edi
- call fill_pxe
- # PML4E 0xff0
- mov $(PA_NXE >> 32), %edx
- lea 0xff0(%edi), %edi
- call fill_pxe
- xor %edx, %edx
- # setup PDPT for physical memory mapping
- mov $KERNEL_PDPT_PHYS_MAPPING, %edi
- # set PS
- or $PA_PS, %ebx
- mov $256, %ecx
- xor %esi, %esi
- .Lfill1:
- call fill_pxe
- lea 8(%edi), %edi
- add $0x40000000, %esi # 1GB
- adc $0, %edx
- loop .Lfill1
- mov $(PA_NXE >> 32), %edx
- # set PCD, PWT
- or $(PA_PCD | PA_PWT), %ebx
- mov $256, %ecx
- xor %esi, %esi
- .Lfill2:
- call fill_pxe
- lea 8(%edi), %edi
- add $0x40000000, %esi # 1GB
- adc $0, %edx
- loop .Lfill2
- xor %edx, %edx
- # PML4E 0xff8
- mov $KERNEL_PDPT_KERNEL_SPACE, %esi
- mov $KERNEL_PML4, %edi
- lea 0xff8(%edi), %edi
- # clear PCD, PWT, PS
- and $(~(PA_PCD | PA_PWT | PA_PS)), %ebx
- call fill_pxe
- # PDPTE 0xff8
- mov $KERNEL_PDPT_KERNEL_SPACE, %edi
- lea 0xff8(%edi), %edi
- mov $KERNEL_PD_KIMAGE, %esi
- call fill_pxe
- # PDE 0xff0
- mov $KERNEL_PD_KIMAGE, %edi
- lea 0xff0(%edi), %edi
- mov $KERNEL_PT_KIMAGE, %esi # 0x104000
- call fill_pxe
- # fill PT (kernel image)
- mov $KERNEL_PT_KIMAGE, %edi
- mov $KERNEL_IMAGE_PADDR, %esi
- mov $KIMAGE_PAGES, %ecx
- .Lfill3:
- call fill_pxe
- lea 8(%edi), %edi
- lea 0x1000(%esi), %esi
- loop .Lfill3
- # set msr
- mov $0xc0000080, %ecx
- rdmsr
- or $0x901, %eax # set LME, NXE, SCE
- wrmsr
- # set cr4
- mov %cr4, %eax
- or $0xa0, %eax # set PAE, PGE
- mov %eax, %cr4
- # load new page table
- mov $KERNEL_PML4, %eax
- mov %eax, %cr3
- mov %cr0, %eax
- // SET PE, WP, PG
- or $0x80010001, %eax
- mov %eax, %cr0
- # create gdt
- xor %eax, %eax # at 0x0000
- mov %eax, 0x00(%eax)
- mov %eax, 0x04(%eax) # null descriptor
- mov %eax, 0x08(%eax) # code segment lower
- mov %eax, 0x10(%eax) # data segment lower
- mov $0x00209a00, %ecx
- mov %ecx, 0x0c(%eax) # code segment higher
- mov $0x00009200, %ecx
- mov %ecx, 0x14(%eax) # data segment higher
- # gdt descriptor
- push %eax
- push %eax
- # pad with a word
- mov $0x00170000, %eax
- push %eax
- lgdt 2(%esp)
- add $12, %esp
- ljmp $0x08, $.L64bit_entry
- # %ebx: attribute low
- # %edx: attribute high
- # %esi: page physical address
- # %edi: page x entry address
- fill_pxe:
- lea (%ebx, %esi, 1), %eax
- mov %eax, (%edi)
- mov %edx, 4(%edi)
- ret
- .code64
- .L64bit_entry:
- jmp start_64bit
- .section .text.kinit
- start_64bit:
- # set stack pointer and clear stack bottom
- mov %rsp, %rdi
- xor %rsp, %rsp
- inc %rsp
- neg %rsp
- shr $40, %rsp
- shl $40, %rsp
- add %rdi, %rsp
- mov %rsp, %rdi
- # make stack frame
- lea -16(%rsp), %rsp
- mov %rsp, %rbp
- xor %rax, %rax
- mov %rax, (%rsp)
- mov %rax, 8(%rsp)
- call kernel_init
- .L64bit_hlt:
- cli
- hlt
- jmp .L64bit_hlt
|