diff --git a/Makefile b/Makefile index 5854adb..0977128 100644 --- a/Makefile +++ b/Makefile @@ -28,32 +28,30 @@ INC_COMMON := inc MK := mk OUT := out -C_IGNORED_WARNINGS = -Wno-cast-align \ - -Wno-padded +C_FLAGS_ARCH_X86_64 := -mcmodel=kernel \ + -target x86_64-pc-none-elf \ + -mno-red-zone \ + -mno-mmx \ + -mno-sse \ + -mno-sse2 \ + -mno-sse3 \ + -mno-3dnow # generic freestanding cflags used for target # each submodule can append to this flag -C_FLAGS = -xc\ - -g \ +C_FLAGS = -x c \ + -g \ -c \ -O2 \ - -std=c11 \ - -Weverything \ + -std=c17 \ + -Wall \ + -Wextra \ + -Wpedantic \ -Werror \ - $(C_IGNORED_WARNINGS) \ -ffreestanding \ - -fno-builtin \ - -nostdlib \ -fno-pic \ - -mcmodel=kernel \ -fno-stack-protector \ - -mno-red-zone \ - -mno-mmx \ - -mno-sse \ - -mno-sse2 \ - -mno-sse3 \ - -mno-3dnow \ - -target x86_64-pc-none-elf \ + $(C_FLAGS_ARCH_X86_64) \ -I$(INC_COMMON) \ $(C_FLAGS_$(MOD)) diff --git a/Rules.top b/Rules.top index 97b8d54..7258941 100644 --- a/Rules.top +++ b/Rules.top @@ -25,7 +25,8 @@ DUMP_FLAGS = -x86-asm-syntax=intel \ -disassemble \ -r \ -t \ - -triple=x86_64-pc-none-elf + -triple=x86_64-pc-none-elf \ + -print-imm-hex LD_FLAGS = -fuse-ld=$(LD) \ -nostdlib \ @@ -52,12 +53,9 @@ clean: rm -rf $(OUT) .PHONY: compile -compile: $(TGT) - -.PHONY: dump -dump: $(DMP) +compile: $(TGT) $(DMP) .PHONY: all -all: compile dump iso +all: compile iso include $(MK)/epilogue.mk diff --git a/dbgq b/dbgq index 0385adf..9be1584 100644 --- a/dbgq +++ b/dbgq @@ -1,3 +1,4 @@ +file out/secxkrnl.elf +set arch i386:x86-64:intel target remote localhost:1234 -symbol-file out/secxkrnl.elf -break *0x1001000 +break sys_entry_64.high diff --git a/hal/boot.asm.in b/hal/boot.asm.in index 4368a54..5336eb5 100644 --- a/hal/boot.asm.in +++ b/hal/boot.asm.in @@ -2,10 +2,12 @@ #include "mlayout.h" #include "multiboot2.h" -%define GET_PADDR(x) ((x) - KERNEL_IMAGE_VADDR + KERNEL_IMAGE_PADDR) -%define BOCHS_BREAK xchg bx,bx +%define GET_PADDR(x) ((x) - KERNEL_IMAGE_VADDR) +%define GET_PML4(vaddr) (((vaddr) >> 39 ) & 0x1FF) +%define GET_PDPT(vaddr) (((vaddr) >> 30 ) & 0x1FF) global sys_entry +global sys_entry_64 extern hmain section .text @@ -13,48 +15,46 @@ bits 32 sys_entry: cli cld - cmp eax,MULTIBOOT2_BOOTLOADER_MAGIC - je .loaded_by_grub - hlt + cmp eax, MULTIBOOT2_BOOTLOADER_MAGIC + jne .end -.loaded_by_grub: - ; save multiboot_info* - mov esi,ebx - call halp_check_long_mode - cmp eax,1 - je .init_long_mode - hlt + ; save multiboot info + mov dword [GET_PADDR(multiboot_info_ptr)], ebx + + ; setup stack + call check_long_mode ; check support for long mode + cmp eax, 1 + jne .end -.init_long_mode: ; disable paging first mov eax, cr0 ; Set the A-register to control register 0. - and eax, 0x7FFFFFFF ; Clear the PG-bit, which is bit 31. + and eax, ~(1 << 31) & 0xFFFFFFFF ; Clear the PG-bit, which is bit 31, and hack to get rid of warning mov cr0, eax ; Set control register 0 to the A-register. + ; point the first PML4 entry to the identity pdpt + mov eax, GET_PADDR(init_pml4) + mov dword [eax], GET_PADDR(init_pdpt_iden) + 11b ; write the lower bits, higher = 0 + ; point the nth PML4 entry to the kernel pdpt + add eax, GET_PML4(KERNEL_IMAGE_VADDR) * 8 + mov dword [eax], GET_PADDR(init_pdpt_kern) + 11b + + ; identity map the first 4GB - ; ATTRIBUTE = READ/WRITE + SU - mov eax, GET_PADDR(_pml4) - mov dword [eax], GET_PADDR(_pdpt) + 11b + mov eax, GET_PADDR(init_pdpt_iden) + mov ebx, 10000011b ; R/W + SU + 1G page + mov ecx, 4 ; loop 4 times +.l0: + mov dword [eax], ebx + add ebx, 1*1024*1024*1024 ; 1G + add eax, 8 + loop .l0 - ; write values for pdpt - mov ecx, 10000011b - - mov eax, GET_PADDR(_pdpt) - mov dword [eax], ecx - - add eax,8 - add ecx,0x40000000 ;1G - mov dword [eax], ecx - - add eax,8 - add ecx,0x40000000 ;1G - mov dword [eax], ecx - - add eax,8 - add ecx,0x40000000 ;1G - mov dword [eax], ecx - - BOCHS_BREAK + ; map the first 1 GB, which contains the kernel, to KERNEL_BASE_VADDR + mov eax, GET_PADDR(init_pdpt_kern) + ; extract the PML4 entry + add eax, GET_PDPT(KERNEL_IMAGE_VADDR) * 8 + mov ebx, 10000011b ; R/W + SU + 1G page + mov dword [eax], ebx ; enable PAE mov eax, cr4 ; Set the A-register to control register 4. @@ -68,7 +68,7 @@ sys_entry: wrmsr ; Write to the model-specific register. ; let cr3 point at page table - mov eax, GET_PADDR(_pml4) + mov eax, GET_PADDR(init_pml4) mov cr3, eax ; enable paging, enter compatibility mode @@ -76,12 +76,18 @@ sys_entry: or eax, 1 << 31 ; Set the PG-bit, which is bit 31. mov cr0, eax ; Set control register 0 to the A-register. - ; enter long mode - lgdt [GET_PADDR(_gdt.ptr)] - jmp _gdt.code:GET_PADDR(hmain_stub) + ; now we are in compat mode + + ; load the long mode GDT + lgdt [GET_PADDR(init_gdt.ptr)] + + ; switch to long mode + jmp init_gdt.code:GET_PADDR(sys_entry_64) +.end: hlt -halp_check_long_mode: + +check_long_mode: push ebp mov ebp,esp pushfd @@ -113,51 +119,70 @@ halp_check_long_mode: pop ebp ret +section .data +bits 32 +multiboot_info_ptr: + dd 0 + section .text bits 64 -hmain_stub: - ; note that we are still at the identity mapping - mov ax,_gdt.data +sys_entry_64: + ; note that we are in long mode but rip is still lower + ; switch to high address + mov rax, .high + jmp rax +.high: + ; set proper segment registers + mov ax,init_gdt.data mov ds,ax mov es,ax mov fs,ax mov gs,ax mov ss,ax - mov rsp, GET_PADDR(_stack) - mov rdi, rsi ; multiboot_info* + mov rsp, init_stack + xor edi, edi + mov edi, dword [multiboot_info_ptr] + mov rdi, rsi call hmain .end: hlt + section .data bits 64 align KERNEL_PAGE_SIZE times KERNEL_PAGE_SIZE db 0 -_stack: +init_stack: -_pml4: +init_pml4: align KERNEL_PAGE_SIZE times KERNEL_PAGE_SIZE db 0 -_pdpt: + +init_pdpt_iden: align KERNEL_PAGE_SIZE times KERNEL_PAGE_SIZE db 0 -_gdt: ; Global Descriptor Table (long mode). -.null: equ $ - _gdt ; The null descriptor. + +init_pdpt_kern: +align KERNEL_PAGE_SIZE + times KERNEL_PAGE_SIZE db 0 + +init_gdt: ; Global Descriptor Table (long mode). +.null: equ $ - init_gdt ; The null descriptor. dw 0 ; Limit (low). dw 0 ; Base (low). db 0 ; Base (middle) db 0 ; Access. db 0 ; Granularity. db 0 ; Base (high). -.code: equ $ - _gdt ; The code descriptor. +.code: equ $ - init_gdt ; The code descriptor. dw 0 ; Limit (low). dw 0 ; Base (low). db 0 ; Base (middle) db 10011010b ; Access (exec/read). db 00100000b ; Granularity. db 0 ; Base (high). -.data: equ $ - _gdt ; The data descriptor. +.data: equ $ - init_gdt ; The data descriptor. dw 0 ; Limit (low). dw 0 ; Base (low). db 0 ; Base (middle) @@ -166,5 +191,5 @@ _gdt: ; Global Descriptor Table (long mode). db 0 ; Base (high). .ptr: ; GDT PTR - dw $ - _gdt - 1 ; Limit. - dq GET_PADDR(_gdt) ; Base. + dw $ - init_gdt - 1 ; Limit. + dq GET_PADDR(init_gdt) ; Base. diff --git a/hal/boot.c b/hal/boot.c index 855263d..4e61021 100644 --- a/hal/boot.c +++ b/hal/boot.c @@ -20,9 +20,6 @@ // hal_info->cpu_vd_str[12] = 0; //} -void HABI -hmain(void *m_info); - void HABI hmain(void *m_info) { diff --git a/hal/inc/cpu.h b/hal/inc/cpu.h index 07330b9..ade7a1d 100644 --- a/hal/inc/cpu.h +++ b/hal/inc/cpu.h @@ -4,13 +4,13 @@ #define HAL_CORE_COUNT 1 -struct STRUCT_PACKED hal_gdt_ptr +struct PRAGMA_PACKED hal_gdt_ptr { uint16 limit; uint64 base; }; -struct STRUCT_PACKED hal_idt_ptr +struct PRAGMA_PACKED hal_idt_ptr { uint16 limit; uint64 base; diff --git a/hal/intr.c b/hal/intr.c index aa45f13..77f2f1b 100644 --- a/hal/intr.c +++ b/hal/intr.c @@ -110,7 +110,7 @@ hal_exception_dispatcher(uint64 exc_vec, struct interrupt_context *context, uint } static void -halp_populate_idt(void) +populate_idt(void) { hal_set_interrupt_handler(0, hal_interrupt_handler_0); hal_set_interrupt_handler(1, hal_interrupt_handler_1); @@ -380,16 +380,23 @@ impl_hal_get_core_id(void) int32 hal_interrupt_init(void) { - uint32 coreid = hal_get_core_id(); - uint32 eax = 0, ebx = 0, ecx = 0, edx = 0; + uint32 coreid; + uint32 eax; + uint32 ebx; + uint32 ecx; + uint32 edx; + + // detect APIC first eax = 1; hal_cpuid(&eax, &ebx, &ecx, &edx); - if (!(edx & bit_mask(9))) + if (!(edx & (1 << 9))) { - hal_printf("ERROR: APIC not supported by CPU.\n"); + hal_printf("ERROR: APIC is not present.\n"); return 1; } + coreid = hal_get_core_id(); + // get idt ptr ready cpu_idt_ptrs[coreid].base = (uint64) &cpu_idts[coreid]; cpu_idt_ptrs[coreid].limit = IDT_ENTRY_NUM * IDT_ENTRY_SIZE - 1; @@ -399,7 +406,7 @@ hal_interrupt_init(void) k_intr_disps[coreid] = NULL; // hook asm interrupt handlers - halp_populate_idt(); + populate_idt(); hal_flush_idt(&cpu_idt_ptrs[coreid]); diff --git a/hal/mb_hdr.asm.in b/hal/mb_hdr.asm.in index 587572c..f4df5cc 100644 --- a/hal/mb_hdr.asm.in +++ b/hal/mb_hdr.asm.in @@ -5,43 +5,44 @@ extern hmain global hal_main_32 +ASM_MULTIBOOT_CHECK_SUM equ (0xFFFFFFFF - (MULTIBOOT2_HEADER_MAGIC + ASM_MULTIBOOT_HEADER_SIZE + MULTIBOOT_ARCHITECTURE_I386) + 1) + section .multiboot_header bits 32 align KERNEL_PAGE_SIZE -MULTIBOOT_ARCH equ 0 -MULTIBOOT_CHECK_SUM equ (0xFFFFFFFF - (MULTIBOOT2_HEADER_MAGIC + MULTIBOOT_HEADER_SIZE + MULTIBOOT_ARCH) + 1) -MULTIBOOT_REQ_LOADERNAME equ 2 -MULTIBOOT_REQ_MMAP equ 6 -MULTIBOOT_REQ_ACPI_RSDP equ 15 ;==================== -;header tag align MULTIBOOT_HEADER_ALIGN -multiboot_header_tag: +start_hdr: dd MULTIBOOT2_HEADER_MAGIC - dd MULTIBOOT_ARCH - dd MULTIBOOT_HEADER_SIZE - dd MULTIBOOT_CHECK_SUM -;==================== -;INFO_REQUEST_TAG -align MULTIBOOT_INFO_ALIGN -multiboot_info_tag: - dw 0x1 ; type=1 - dw 0x0 ; flag=0 - dd MULTIBOOT_INFO_TAG_SIZE - dd MULTIBOOT_REQ_LOADERNAME - dd MULTIBOOT_REQ_MMAP -MULTIBOOT_INFO_TAG_SIZE equ ($ - multiboot_info_tag) -;==================== -;MODULE ALIGNMENT TAG -align MULTIBOOT_INFO_ALIGN - dw 0x6; type=6 - dw 0x0; flag=0 - dd 0x8 + dd MULTIBOOT_ARCHITECTURE_I386 + dd ASM_MULTIBOOT_HEADER_SIZE + dd ASM_MULTIBOOT_CHECK_SUM ;==================== align MULTIBOOT_INFO_ALIGN - ;End_tag - dw 0x0 - dw 0x0 - dd 0x8 + dw MULTIBOOT_HEADER_TAG_INFORMATION_REQUEST + dw 0 ; flag + dd (8+4*4) ; size + dd MULTIBOOT_TAG_TYPE_BOOT_LOADER_NAME + dd MULTIBOOT_TAG_TYPE_MMAP + dd MULTIBOOT_TAG_TYPE_ACPI_NEW + dd MULTIBOOT_TAG_TYPE_BOOTDEV ;==================== -MULTIBOOT_HEADER_SIZE equ ($ - multiboot_header_tag) \ No newline at end of file +align MULTIBOOT_INFO_ALIGN + dw MULTIBOOT_HEADER_TAG_FRAMEBUFFER; type=5 + dw 0 ; flag + dw 20 ; size + dd 0 ; width + dd 0 ; depth + dd 0 ; height +;==================== +align MULTIBOOT_INFO_ALIGN + dw MULTIBOOT_HEADER_TAG_MODULE_ALIGN; type=6 + dw 0 ; flag + dd 8 ; size +;==================== +align MULTIBOOT_INFO_ALIGN + dw MULTIBOOT_HEADER_TAG_END + dw 0 ; flag + dd 8 ; size +;==================== +ASM_MULTIBOOT_HEADER_SIZE equ ($ - start_hdr) diff --git a/hal/print.c b/hal/print.c index 03a9eec..5c43c4e 100644 --- a/hal/print.c +++ b/hal/print.c @@ -144,13 +144,13 @@ hal_clear_screen(void) static void halp_vprintf(char const *format, va_list args) { - char buf[2] = {0, 0}; - int64 - d; - uint64 - u; + char buf[2]; + int64 d; + uint64 u; char *s; char c; + + buf[1] = '\0'; for (; *format != '\0'; format++) { if (*format != '%') @@ -210,8 +210,7 @@ hal_printf(char const *format, ...) } void -hal_assert(uint32 expression, char *message -) +hal_assert(uint32 expression, char *message) { if (!expression) { diff --git a/inc/cdef.h b/inc/cdef.h index 20ddc41..1a415d7 100644 --- a/inc/cdef.h +++ b/inc/cdef.h @@ -18,7 +18,11 @@ typedef _Bool bool; #define TRUE (1) #define FALSE (0) -#define STRUCT_PACKED __attribute__((packed)) +#define PRAGMA_PACKED __attribute__((packed)) + +#define PRAGMA_SECTION(x) __attribute__ ((section (x))) + +#define PRAGMA_ALIGN(x) __attribute__ ((aligned(x))) #define UNREFERENCED(x) {(x) = (x);} diff --git a/inc/mlayout.h b/inc/mlayout.h index 280d59d..1560af3 100644 --- a/inc/mlayout.h +++ b/inc/mlayout.h @@ -17,15 +17,22 @@ * ----------------------- 0xFFFF,FFFF,FFFF,FFFF **/ +/** + * kernel loaded at physical address 16MB + * 0x1000000 = 16777216 = 16 * 1024 * 1024 + */ #define KERNEL_IMAGE_PADDR (0x1000000) #define KERNEL_PAGE_SIZE (0x1000) + #define KERNEL_SPACE_VADDR (0xFFFF800000000000) #define KERNEL_RESERVED_VADDR KERNEL_SPACE_VADDR -#define KERNEL_RESERVED_SIZE (0x00007F0000000000) #define KERNEL_PAGE_TABLE_VADDR (0xFFFFFF0000000000) -#define KERNEL_PAGE_TABLE_SIZE (0x0000008000000000) #define KERNEL_DYNAMIC_VADDR (0xFFFFFF8000000000) -#define KERNEL_DYNAMIC_SIZE (0x0000007F80000000) + +/** + * Minus 2GB + */ #define KERNEL_IMAGE_VADDR (0xFFFFFFFF80000000) -#define KERNEL_IMAGE_SIZE (0x0000000080000000) +#define KERNEL_IMAGE_OFFSET (KERNEL_IMAGE_PADDR) + diff --git a/mk/linker.ld.in b/mk/linker.ld.in index 0e5646c..dc2a92a 100644 --- a/mk/linker.ld.in +++ b/mk/linker.ld.in @@ -5,25 +5,25 @@ ENTRY(sys_entry) SECTIONS { - . = KERNEL_IMAGE_VADDR; + . = KERNEL_IMAGE_VADDR + KERNEL_IMAGE_OFFSET; - .multiboot_header ALIGN(KERNEL_PAGE_SIZE) : AT(ADDR(.multiboot_header) + KERNEL_IMAGE_PADDR - KERNEL_IMAGE_VADDR) + .multiboot_header ALIGN(KERNEL_PAGE_SIZE) : AT(ADDR(.multiboot_header) - KERNEL_IMAGE_VADDR) { *(.multiboot_header) } - .text ALIGN(KERNEL_PAGE_SIZE) : AT(ADDR(.text) + KERNEL_IMAGE_PADDR - KERNEL_IMAGE_VADDR) + .text ALIGN(KERNEL_PAGE_SIZE) : AT(ADDR(.text) - KERNEL_IMAGE_VADDR) { *(.text) } - .data ALIGN(KERNEL_PAGE_SIZE) : AT(ADDR(.data) + KERNEL_IMAGE_PADDR - KERNEL_IMAGE_VADDR) + .data ALIGN(KERNEL_PAGE_SIZE) : AT(ADDR(.data) - KERNEL_IMAGE_VADDR) { *(.data) *(.rodata*) } - .bss ALIGN(KERNEL_PAGE_SIZE) : AT(ADDR(.bss) + KERNEL_IMAGE_PADDR - KERNEL_IMAGE_VADDR) + .bss ALIGN(KERNEL_PAGE_SIZE) : AT(ADDR(.bss) - KERNEL_IMAGE_VADDR) { *(.bss) *(COMMON) diff --git a/runq.sh b/runq.sh index 18abac9..9391862 100644 --- a/runq.sh +++ b/runq.sh @@ -1,4 +1,4 @@ #!/bin/bash -qemu-system-x86_64 -bios qemu_bios.bin -vnc :10 -monitor stdio -cdrom out/secxkrnl.iso -s -S +qemu-system-x86_64 -bios qemu_bios.bin -vnc :10 -monitor stdio -cdrom out/secxkrnl.iso -s -S -no_reboot