a working x86-64 loader

This commit is contained in:
Yanyan Jiang 2020-01-22 14:49:24 +00:00
parent 644beac40a
commit 7ae828957c
5 changed files with 97 additions and 46 deletions

View File

@ -14,7 +14,7 @@ image:
run:
@( echo -n $(mainargs); ) | dd if=/dev/stdin of=$(BINARY) bs=512 count=1 seek=1 conv=notrunc status=none
@qemu-system-x86_64 -serial none -machine accel=kvm:tcg -smp "$(smp)" -drive format=raw,file=$(BINARY) -nographic
@qemu-system-x86_64 -serial stdio -machine accel=kvm:tcg -smp "$(smp)" -drive format=raw,file=$(BINARY)
debug:
@( echo -n $(mainargs); ) | dd if=/dev/stdin of=$(BINARY) bs=512 count=1 seek=1 conv=notrunc status=none

View File

@ -266,7 +266,7 @@ static inline void set_cr0(uint32_t cr0) {
}
/*
#ifndef __x86_64__
static inline void set_idt(GateDesc *idt, int size) {
volatile static uint16_t data[3];
data[0] = size - 1;
@ -286,7 +286,7 @@ static inline void set_gdt(SegDesc *gdt, int size) {
static inline void set_tr(int selector) {
asm volatile ("ltr %0" : : "r"((uint16_t)selector));
}
*/
#endif
static inline uint32_t get_cr2() {
volatile uint32_t val;

View File

@ -1,51 +1,63 @@
#include <x86.h>
#define KERNEL_BASE 0x00100000
.code32
.globl _start
#define PML4_ADDR_TO_ENTRY_INDEX(addr) (((addr) >> 39) & 0x1FF)
#define PDPT_ADDR_TO_ENTRY_INDEX(addr) (((addr) >> 30) & 0x1FF)
#define TWO_MEGABYTES_SHIFT 21
#define TWO_MEGABYTES (1 << TWO_MEGABYTES_SHIFT)
#define KERNEL_BASE 0x00100000
.section .bss
// bootstrap page table
.comm pml4, 0x1000, 0x1000
.comm low_pdpt, 0x1000, 0x1000
.comm high_pdpt, 0x1000, 0x1000
.comm low_page_directory_table, 0x1000, 0x1000
.comm high_page_directory_table, 0x1000, 0x1000
.section .text
.global _start
.type _start, @function
_start:
movl $0x1000, %edi
movl %edi, %cr3
movl $low_pdpt + 3, %eax
movl %eax, pml4 + (PML4_ADDR_TO_ENTRY_INDEX(KERNEL_BASE) * 8)
movl $high_pdpt + 3, %eax
movl %eax, pml4 + (PML4_ADDR_TO_ENTRY_INDEX(KERNEL_BASE) * 8)
movl $low_page_directory_table + 3, %eax
movl %eax, low_pdpt + (PDPT_ADDR_TO_ENTRY_INDEX(KERNEL_BASE) * 8)
movl $high_page_directory_table + 3, %eax
movl %eax, high_pdpt + (PDPT_ADDR_TO_ENTRY_INDEX(KERNEL_BASE) * 8)
mov $0, %ecx
movl $_end, %esi
shrl $21, %esi
addl $1, %esi
page_directory_table_loop:
movl $200000, %eax
mul %ecx
or $0x83, %eax
movl %eax, low_page_directory_table(, %ecx, 8)
movl %eax, high_page_directory_table(, %ecx, 8)
movl $0x2003, (%edi)
addl $0x1000, %edi
movl $0x3003, (%edi)
addl $0x1000, %edi
movl $0x4003, (%edi)
addl $0x1000, %edi
inc %ecx
cmp %esi, %ecx
jne page_directory_table_loop // if not equal redo loop
movl $0x3, %ebx
movl $512, %ecx
.fill_pt:
movl %ebx, (%edi)
addl $4096, %ebx
addl $8, %edi
loop .fill_pt
.align 128
movl %cr0, %eax
orl $(CR0_PE | CR0_PG), %eax
movl %eax, %cr4 // enable CR4 PE and PG
movl $pml4, %eax
movl %eax, %cr3 // %cr3 = PML4 base
movl $0x20, %eax
movl %eax, %cr4 // %cr4.PAE = 1
movl $0xc0000080, %ecx
rdmsr
orl $256, %eax
wrmsr // enable long mode
or $0x100, %eax
wrmsr // %msr.LME = 1.
movl $0x80000011, %eax
movl %eax, %cr0 // %cr0.PG = 1; %cr0.PE = 1;
lgdt gdt_ptr + KERNEL_BASE // set a gdt
ljmp $8, $_start64 + KERNEL_BASE
cli
hlt
movl %cr0, %eax
orl $(CR0_PE | CR0_PG), %eax
movl %eax, %cr0 // eanble CR0 PE and PG
lgdt gdtr64
ljmp $8, $entry64
.align 128
entry64:
jmp .
gdtr64:
gdt_ptr:
.word gdt64_end - gdt64_begin - 1;
.quad gdt64_begin + KERNEL_BASE
@ -57,3 +69,22 @@ gdt64_begin:
.long 0x00000000 # 2: Data, R/W, Expand Down
.long 0x00009000
gdt64_end:
.code64
.global _start64
.type _start64, @function
_start64:
movw $0, %ax
movw %ax, %ds
movw %ax, %es
movw %ax, %fs
movw %ax, %gs
movw %ax, %ss
movq $0x4000, %rsp
movq $0x7e00, %rdi
call _start_c
cli
hlt

View File

@ -5,12 +5,15 @@ _Area _heap = {}; // the heap memory defined in AM spec
int main(const char *args);
void _start64(char *args) {
void _start_c(char *args) {
// TODO: build full page table
int ret = main(args);
_halt(ret);
}
void _putc(char ch) {
#define COM1 0x3f8
outb(COM1, ch);
}
void _halt(int code) {
@ -19,4 +22,4 @@ void _halt(int code) {
void some_code() {
}
}

View File

@ -1,3 +1,20 @@
int main() {
while (1);
#include <am.h>
#include <klib.h>
void putd(int n) {
_putc("0123456789"[n]);
}
int main(const char *args) {
printf("args = \"");
while (*args) {
_putc(*args++);
}
printf("\"\n");
printf("sizeof(long) = ");
putd(sizeof(long));
printf("\n");
while (1);
return 0;
}