a working x86-64 loader
This commit is contained in:
parent
644beac40a
commit
7ae828957c
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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() {
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue