From f72b2b11b8603f8afdd0a2d0d16d51c64747c4ea Mon Sep 17 00:00:00 2001 From: Tianhao Wang Date: Tue, 16 Apr 2024 18:23:45 +0200 Subject: re-organize code --- Makefile | 9 +- boot/startup-x86_64.s | 445 +++++++++++++++++++++++++++++++++++++++++++ compiler/x86_64-linker.ld | 76 ++++++++ compiler/x86_64-rustubs.json | 13 ++ src/arch/x86_64/linker.ld | 76 -------- startup.s | 445 ------------------------------------------- x86_64-rustubs.json | 13 -- 7 files changed, 539 insertions(+), 538 deletions(-) create mode 100644 boot/startup-x86_64.s create mode 100644 compiler/x86_64-linker.ld create mode 100644 compiler/x86_64-rustubs.json delete mode 100644 src/arch/x86_64/linker.ld delete mode 100644 startup.s delete mode 100644 x86_64-rustubs.json diff --git a/Makefile b/Makefile index a7cade0..0e3f565 100644 --- a/Makefile +++ b/Makefile @@ -18,7 +18,8 @@ BUILD = build ARCH = x86_64 ASM = nasm ASMOBJFORMAT = elf64 -LINKER_SCRIPT = ./src/arch/$(ARCH)/linker.ld +LINKER_SCRIPT = ./compiler/$(ARCH)-linker.ld +CARGO_XBUILD_TARGET = ./compiler/$(ARCH)-rustubs.json CARGO_XBUILD_FLAGS = # ---------- No need to edit below this line -------------- # ---------- If you have to, something is wrong ----------- @@ -61,13 +62,13 @@ $(BUILD)/_%.o : %.s | $(BUILD) # Compile the rust part: note that the the cargo crate is of type [staticlib], if you don't # define this, the linker will have troubles, especially when we use a "no_std" build rust_kernel: - cargo xbuild --target $(ARCH)-rustubs.json $(CARGO_XBUILD_FLAG) + cargo xbuild --target $(CARGO_XBUILD_TARGET) $(CARGO_XBUILD_FLAG) # need nasm # TODO make this arch dependent -startup.o: startup.s | $(BUILD) +startup.o: boot/startup-$(ARCH).s | $(BUILD) @if test \( ! \( -d $(@D) \) \) ;then mkdir -p $(@D);fi - nasm -f elf64 -o $(BUILD)/startup.o startup.s + nasm -f elf64 -o $(BUILD)/startup.o boot/startup-$(ARCH).s .PHONY: $(BUILD) $(BUILD): diff --git a/boot/startup-x86_64.s b/boot/startup-x86_64.s new file mode 100644 index 0000000..dfc6262 --- /dev/null +++ b/boot/startup-x86_64.s @@ -0,0 +1,445 @@ +; THis code is copied from the OSC lab project OOStuBS @ TU Dresden + +;****************************************************************************** +;* Operating-System Construction * +;*----------------------------------------------------------------------------* +;* * +;* S T A R T U P . A S M * +;* * +;*----------------------------------------------------------------------------* +;* The 'startup' function is the entry point for the whole system. Switching * +;* to 32-bit Protected Mode has already been done (by a boot loader that runs * +;* before). Here we prepare everything to be able to start running C++ code * +;* in 64-bit Long Mode as quickly as possible. * +;****************************************************************************** + +; +; Constants +; + +; stack for the main function (renamed to _entry()) +STACKSIZE: equ 65536 + +; video memory base address +CGA: equ 0xB8000 + +; 512 GB maximum RAM size for page table +; DON'T MODIFY THIS UNLESS YOU UPDATE THE setup_paging accordingly +MAX_MEM: equ 512 + +; Multiboot constants +MULTIBOOT_PAGE_ALIGN equ 1<<0 +MULTIBOOT_MEMORY_INFO equ 1<<1 + +; magic number for Multiboot +MULTIBOOT_HEADER_MAGIC equ 0x1badb002 + +; Multiboot flags (ELF specific!) +MULTIBOOT_HEADER_FLAGS equ MULTIBOOT_PAGE_ALIGN | MULTIBOOT_MEMORY_INFO +MULTIBOOT_HEADER_CHKSUM equ -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS) +MULTIBOOT_EAX_MAGIC equ 0x2badb002 + + +; +; System +; + +; exported symbols +[GLOBAL startup] +[GLOBAL idt] +[GLOBAL pml4] +[GLOBAL pdp] + +; functions from the C parts of the system +[EXTERN _entry] +[EXTERN guardian] + +; addresses provided by the compiler +[EXTERN ___BSS_START__] +[EXTERN ___BSS_END__] + +[SECTION .text] + +; +; system start, part 1 (in 32-bit Protected Mode) +; +; GDT and page-table initialization, and switch to 64-bit Long Mode +; + +[BITS 32] + + jmp startup ; jump over Multiboot header + align 4 ; 32-bit alignment for GRUB + +; +; Multiboot header for starting with GRUB or QEMU (w/o BIOS) +; + + dd MULTIBOOT_HEADER_MAGIC + dd MULTIBOOT_HEADER_FLAGS + dd MULTIBOOT_HEADER_CHKSUM + dd 0 ; header_addr (gets ignored) + dd 0 ; load_addr (gets ignored) + dd 0 ; load_end_addr (gets ignored) + dd 0 ; bss_end_addr (gets ignored) + dd 0 ; entry_addr (gets ignored) + dd 0 ; mode_type (gets ignored) + dd 0 ; width (gets ignored) + dd 0 ; height (gets ignored) + dd 0 ; depth (gets ignored) + +; +; GRUB entry point +; + +startup: + cld ; GCC-compiled code expects the direction flag to be 0 + cli ; disable interrupts + lgdt [gdt_80] ; set new segment descriptors + + ; global data segment + mov eax, 3 * 0x8 + ; 0x8 is the length of each entry + ; these registers point to 4th entry the GDT (see also the code there) + ; in x86 long mode these are dummy pointers + ; which are not actually used in addressing. (don't use segmentation at all) + ; all the addresses are physical addresses from 0. + mov ds, ax + mov es, ax + mov fs, ax + mov gs, ax + + ; define stack + mov ss, ax + mov esp, init_stack+STACKSIZE + +; +; Switch to 64-bit Long Mode +; + +init_longmode: + ; activate address extension (PAE) + mov eax, cr4 + or eax, 1 << 5 + mov cr4, eax + + ; create page table (mandatory) + call setup_paging + + ; activate Long Mode (for now in compatibility mode) + mov ecx, 0x0C0000080 ; select EFER (Extended Feature Enable Register) + rdmsr + or eax, 1 << 8 ; LME (Long Mode Enable) + wrmsr + + ; activate paging + mov eax, cr0 + or eax, 1 << 31 + mov cr0, eax + + ; jump to 64-bit code segment -> full activation of Long Mode + jmp 2 * 0x8 : longmode_start + +; +; Provisional identical page mapping, using 1G huge page (therefore only 2 table +; levels needed) +; + +setup_paging: + ; PML4 (Page Map Level 4 / 1st level) + mov eax, pdp + or eax, 0xf + mov dword [pml4+0], eax + mov dword [pml4+4], 0 + ; PDPE flags + mov eax, 0x0 | 0x87 ; start-address bytes bit [30:31] + flags + mov ebx, 0 ; start-address bytes bit [32:38] + mov ecx, 0 +fill_tables2: + ; fill one single PDP table, with 1G pages, 512 PDPE maps to 512 GB + cmp ecx, MAX_MEM + je fill_tables2_done + mov dword [pdp + 8*ecx + 0], eax ; low bytes + mov dword [pdp + 8*ecx + 4], ebx ; high bytes + add eax, 0x40000000 ; 1G per page + adc ebx, 0 ; overflow? -> increment higher-order half of the address + inc ecx + ja fill_tables2 +fill_tables2_done: + ; set base pointer to PML4 + mov eax, pml4 + mov cr3, eax + ret + +; +; system start, part 2 (in 64-bit Long Mode) +; +; This code clears the BSS segment and initializes IDT and PICs. Then the +; constructors of global C++ objects are called, and finally _entry() is run. +; + +longmode_start: +[BITS 64] + ; clear BSS + mov rdi, ___BSS_START__ +clear_bss: + mov byte [rdi], 0 + inc rdi + cmp rdi, ___BSS_END__ + jne clear_bss + + ; initialize IDT and PICs + call setup_idt + call reprogram_pics + call setup_cursor + + fninit ; activate FPU + + ; init SSE + ; NOTE: must NOT use sse target features for rust compiler, if sse not enabled here. + ;mov rax, cr0 + ;and rax, ~(1 << 2) ;clear coprocessor emulation CR0.EM + ;or rax, 1 << 1 ;set coprocessor monitoring CR0.MP + ;mov cr0, rax + ;mov rax, cr4 + ;or rax, 3 << 9 ;set CR4.OSFXSR and CR4.OSXMMEXCPT at the same time + ;mov cr4, rax + + call _entry ; call the OS kernel's C / C++ part + cli ; Usually we should not get here. + hlt + +; +; Interrupt handling +; + +; template for header for each interrupt-handling routine +; TODO: vectors should have their dedicated place +%macro wrapper 1 +wrapper_%1: + push rbp + mov rbp, rsp + push rax + mov al, %1 + jmp wrapper_body +%endmacro + +; automatic generation of 256 interrupt-handling routines, based on above macro +%assign i 0 +%rep 256 +wrapper i +%assign i i+1 +%endrep + +; common handler body +wrapper_body: + ; GCC expects the direction flag to be 0 + cld + ; save volatile registers + push rcx + push rdx + push rdi + push rsi + push r8 + push r9 + push r10 + push r11 + + ; the generated wrapper only gives us 8 bits, mask the rest + and rax, 0xff + + ; pass interrupt number as the first parameter + mov rdi, rax + ; call the interrupt handler wrapper here. + ; TODO implement it in rust then uncomment the line + call guardian + + ; restore volatile registers + pop r11 + pop r10 + pop r9 + pop r8 + pop rsi + pop rdi + pop rdx + pop rcx + + ; ... also those from the wrapper + pop rax + pop rbp + + ; done + iretq + +; +; Relocating of IDT entries and setting IDTR +; + +setup_idt: + mov rax, wrapper_0 + + ; bits 0..15 -> ax, 16..31 -> bx, 32..64 -> edx + mov rbx, rax + mov rdx, rax + shr rdx, 32 + shr rbx, 16 + + mov r10, idt ; pointer to the actual interrupt gate + mov rcx, 255 ; counter +.loop: + add [r10+0], ax + adc [r10+6], bx + adc [r10+8], edx + add r10, 16 + dec rcx + jge .loop + + lidt [idt_descr] + ret + +; +; make cursor blink (GRUB disables this) +; + +setup_cursor: + mov al, 0x0a + mov dx, 0x3d4 + out dx, al + call delay + mov dx, 0x3d5 + in al, dx + call delay + and al, 0xc0 + or al, 14 + out dx, al + call delay + mov al, 0x0b + mov dx, 0x3d4 + out dx, al + call delay + mov dx, 0x3d5 + in al, dx + call delay + and al, 0xe0 + or al, 15 + out dx, al + ret + +; +; Reprogram the PICs (programmable interrupt controllers) to have all 15 +; hardware interrupts in sequence in the IDT. +; + +reprogram_pics: + mov al, 0x11 ; ICW1: 8086 mode with ICW4 + out 0x20, al + call delay + out 0xa0, al + call delay + mov al, 0x20 ; ICW2 master: IRQ # offset (32) + out 0x21, al + call delay + mov al, 0x28 ; ICW2 slave: IRQ # offset (40) + out 0xa1, al + call delay + mov al, 0x04 ; ICW3 master: slaves with IRQs + out 0x21, al + call delay + mov al, 0x02 ; ICW3 slave: connected to master's IRQ2 + out 0xa1, al + call delay + mov al, 0x03 ; ICW4: 8086 mode and automatic EOI + out 0x21, al + call delay + out 0xa1, al + call delay + + mov al, 0xff ; Mask/disable hardware interrupts + out 0xa1, al ; in the PICs. Only interrupt #2, which + call delay ; serves for cascading both PICs, is + mov al, 0xfb ; allowed. + out 0x21, al + + ret + +; +; Short delay for in/out instructions +; + +delay: + jmp .L2 +.L2: + ret + +[SECTION .data] + +; +; Segment descriptors +; + +gdt: + dw 0,0,0,0 ; NULL descriptor + + ; 32-bit code segment descriptor + dw 0xFFFF ; 4Gb - (0x100000*0x1000 = 4Gb) + dw 0x0000 ; base address=0 + dw 0x9A00 ; code read/exec + dw 0x00CF ; granularity=4096, 386 (+5th nibble of limit) + + ; 64-bit code segment descriptor + dw 0xFFFF ; 4Gb - (0x100000*0x1000 = 4Gb) + dw 0x0000 ; base address=0 + dw 0x9A00 ; code read/exec + dw 0x00AF ; granularity=4096, 386 (+5th nibble of limit), Long-Mode + + ; data segment descriptor + dw 0xFFFF ; 4Gb - (0x100000*0x1000 = 4Gb) + dw 0x0000 ; base address=0 + dw 0x9200 ; data read/write + dw 0x00CF ; granularity=4096, 386 (+5th nibble of limit) + +gdt_80: + dw 4*8 - 1 ; GDT limit=24, 4 GDT entries - 1 + dq gdt ; GDT address + +; +; Interrupt descriptor table with 256 entries +; + +idt: +%macro idt_entry 1 + dw (wrapper_%1 - wrapper_0) & 0xffff ; offset 0 .. 15 + dw 0x0000 | 0x8 * 2 ; selector points to 64-bit code segment selector (GDT) + dw 0x8e00 ; 8 -> interrupt is present, e -> 80386 32-bit interrupt gate + dw ((wrapper_%1 - wrapper_0) & 0xffff0000) >> 16 ; offset 16 .. 31 + dd ((wrapper_%1 - wrapper_0) & 0xffffffff00000000) >> 32 ; offset 32..63 + dd 0x00000000 ; reserved +%endmacro + +%assign i 0 +%rep 256 +idt_entry i +%assign i i+1 +%endrep + +idt_descr: + dw 256*8 - 1 ; 256 entries + dq idt + +[SECTION .bss] + +global init_stack:data (init_stack.end - init_stack) +init_stack: + resb STACKSIZE +.end: + +[SECTION .global_pagetable] + + +pml4: + resb 4096 + alignb 4096 + +pdp: + resb 4096 + alignb 4096 diff --git a/compiler/x86_64-linker.ld b/compiler/x86_64-linker.ld new file mode 100644 index 0000000..b484366 --- /dev/null +++ b/compiler/x86_64-linker.ld @@ -0,0 +1,76 @@ +SECTIONS +{ + . = 0x100000; /* system's start address */ + + .text : + { + *(".text") + *(".text.*") + *(".text$") + *(".init") + *(".fini") + *(".gnu.linkonce.*") + } + + .init_array : + { + PROVIDE_HIDDEN (__init_array_start = .); + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array)) + KEEP (*(".ctors")) + KEEP (*(".ctor")) + PROVIDE_HIDDEN (__init_array_end = .); + } + + .fini_array : + { + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP (*(SORT(.fini_array.*))) + KEEP (*(.fini_array)) + KEEP (*(".dtors")) + KEEP (*(".dtor")) + PROVIDE_HIDDEN (__fini_array_end = .); + } + + .data : + { + *(".data") + *(".data$") + *(".rodata") + *(".rodata.*") + *(".got") + *(".got.plt") + *(".eh_frame") + *(".eh_fram") + *(".jcr") + *(".note.*") + } + + .bss : + { + ___BSS_START__ = .; + *(".bss") + *(".bss.*") + ___BSS_END__ = .; + } + + /* global page table for 64-bit long mode */ + .global_pagetable ALIGN(4096) (NOLOAD) : + { + *(".global_pagetable") + } + +/* + /DISCARD/ : + { + *(".note") + *(".comment") + *(".debug_line") + *(".debug_info") + *(".debug_abbrev") + *(".debug_aranges") + } +*/ + . = ALIGN(4096); + PROVIDE (___KERNEL_END__ = .); +} diff --git a/compiler/x86_64-rustubs.json b/compiler/x86_64-rustubs.json new file mode 100644 index 0000000..93512ed --- /dev/null +++ b/compiler/x86_64-rustubs.json @@ -0,0 +1,13 @@ +{ + "llvm-target": "x86_64-unknown-none", + "data-layout": "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128", + "linker-flavor": "gcc", + "target-endian": "little", + "target-pointer-width": "64", + "target-c-int-width": "32", + "arch": "x86_64", + "os": "none", + "disable-redzone": true, + "features": "-mmx,-sse,-avx,+soft-float", + "frame-pointer": "always" +} diff --git a/src/arch/x86_64/linker.ld b/src/arch/x86_64/linker.ld deleted file mode 100644 index b484366..0000000 --- a/src/arch/x86_64/linker.ld +++ /dev/null @@ -1,76 +0,0 @@ -SECTIONS -{ - . = 0x100000; /* system's start address */ - - .text : - { - *(".text") - *(".text.*") - *(".text$") - *(".init") - *(".fini") - *(".gnu.linkonce.*") - } - - .init_array : - { - PROVIDE_HIDDEN (__init_array_start = .); - KEEP (*(SORT(.init_array.*))) - KEEP (*(.init_array)) - KEEP (*(".ctors")) - KEEP (*(".ctor")) - PROVIDE_HIDDEN (__init_array_end = .); - } - - .fini_array : - { - PROVIDE_HIDDEN (__fini_array_start = .); - KEEP (*(SORT(.fini_array.*))) - KEEP (*(.fini_array)) - KEEP (*(".dtors")) - KEEP (*(".dtor")) - PROVIDE_HIDDEN (__fini_array_end = .); - } - - .data : - { - *(".data") - *(".data$") - *(".rodata") - *(".rodata.*") - *(".got") - *(".got.plt") - *(".eh_frame") - *(".eh_fram") - *(".jcr") - *(".note.*") - } - - .bss : - { - ___BSS_START__ = .; - *(".bss") - *(".bss.*") - ___BSS_END__ = .; - } - - /* global page table for 64-bit long mode */ - .global_pagetable ALIGN(4096) (NOLOAD) : - { - *(".global_pagetable") - } - -/* - /DISCARD/ : - { - *(".note") - *(".comment") - *(".debug_line") - *(".debug_info") - *(".debug_abbrev") - *(".debug_aranges") - } -*/ - . = ALIGN(4096); - PROVIDE (___KERNEL_END__ = .); -} diff --git a/startup.s b/startup.s deleted file mode 100644 index dfc6262..0000000 --- a/startup.s +++ /dev/null @@ -1,445 +0,0 @@ -; THis code is copied from the OSC lab project OOStuBS @ TU Dresden - -;****************************************************************************** -;* Operating-System Construction * -;*----------------------------------------------------------------------------* -;* * -;* S T A R T U P . A S M * -;* * -;*----------------------------------------------------------------------------* -;* The 'startup' function is the entry point for the whole system. Switching * -;* to 32-bit Protected Mode has already been done (by a boot loader that runs * -;* before). Here we prepare everything to be able to start running C++ code * -;* in 64-bit Long Mode as quickly as possible. * -;****************************************************************************** - -; -; Constants -; - -; stack for the main function (renamed to _entry()) -STACKSIZE: equ 65536 - -; video memory base address -CGA: equ 0xB8000 - -; 512 GB maximum RAM size for page table -; DON'T MODIFY THIS UNLESS YOU UPDATE THE setup_paging accordingly -MAX_MEM: equ 512 - -; Multiboot constants -MULTIBOOT_PAGE_ALIGN equ 1<<0 -MULTIBOOT_MEMORY_INFO equ 1<<1 - -; magic number for Multiboot -MULTIBOOT_HEADER_MAGIC equ 0x1badb002 - -; Multiboot flags (ELF specific!) -MULTIBOOT_HEADER_FLAGS equ MULTIBOOT_PAGE_ALIGN | MULTIBOOT_MEMORY_INFO -MULTIBOOT_HEADER_CHKSUM equ -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS) -MULTIBOOT_EAX_MAGIC equ 0x2badb002 - - -; -; System -; - -; exported symbols -[GLOBAL startup] -[GLOBAL idt] -[GLOBAL pml4] -[GLOBAL pdp] - -; functions from the C parts of the system -[EXTERN _entry] -[EXTERN guardian] - -; addresses provided by the compiler -[EXTERN ___BSS_START__] -[EXTERN ___BSS_END__] - -[SECTION .text] - -; -; system start, part 1 (in 32-bit Protected Mode) -; -; GDT and page-table initialization, and switch to 64-bit Long Mode -; - -[BITS 32] - - jmp startup ; jump over Multiboot header - align 4 ; 32-bit alignment for GRUB - -; -; Multiboot header for starting with GRUB or QEMU (w/o BIOS) -; - - dd MULTIBOOT_HEADER_MAGIC - dd MULTIBOOT_HEADER_FLAGS - dd MULTIBOOT_HEADER_CHKSUM - dd 0 ; header_addr (gets ignored) - dd 0 ; load_addr (gets ignored) - dd 0 ; load_end_addr (gets ignored) - dd 0 ; bss_end_addr (gets ignored) - dd 0 ; entry_addr (gets ignored) - dd 0 ; mode_type (gets ignored) - dd 0 ; width (gets ignored) - dd 0 ; height (gets ignored) - dd 0 ; depth (gets ignored) - -; -; GRUB entry point -; - -startup: - cld ; GCC-compiled code expects the direction flag to be 0 - cli ; disable interrupts - lgdt [gdt_80] ; set new segment descriptors - - ; global data segment - mov eax, 3 * 0x8 - ; 0x8 is the length of each entry - ; these registers point to 4th entry the GDT (see also the code there) - ; in x86 long mode these are dummy pointers - ; which are not actually used in addressing. (don't use segmentation at all) - ; all the addresses are physical addresses from 0. - mov ds, ax - mov es, ax - mov fs, ax - mov gs, ax - - ; define stack - mov ss, ax - mov esp, init_stack+STACKSIZE - -; -; Switch to 64-bit Long Mode -; - -init_longmode: - ; activate address extension (PAE) - mov eax, cr4 - or eax, 1 << 5 - mov cr4, eax - - ; create page table (mandatory) - call setup_paging - - ; activate Long Mode (for now in compatibility mode) - mov ecx, 0x0C0000080 ; select EFER (Extended Feature Enable Register) - rdmsr - or eax, 1 << 8 ; LME (Long Mode Enable) - wrmsr - - ; activate paging - mov eax, cr0 - or eax, 1 << 31 - mov cr0, eax - - ; jump to 64-bit code segment -> full activation of Long Mode - jmp 2 * 0x8 : longmode_start - -; -; Provisional identical page mapping, using 1G huge page (therefore only 2 table -; levels needed) -; - -setup_paging: - ; PML4 (Page Map Level 4 / 1st level) - mov eax, pdp - or eax, 0xf - mov dword [pml4+0], eax - mov dword [pml4+4], 0 - ; PDPE flags - mov eax, 0x0 | 0x87 ; start-address bytes bit [30:31] + flags - mov ebx, 0 ; start-address bytes bit [32:38] - mov ecx, 0 -fill_tables2: - ; fill one single PDP table, with 1G pages, 512 PDPE maps to 512 GB - cmp ecx, MAX_MEM - je fill_tables2_done - mov dword [pdp + 8*ecx + 0], eax ; low bytes - mov dword [pdp + 8*ecx + 4], ebx ; high bytes - add eax, 0x40000000 ; 1G per page - adc ebx, 0 ; overflow? -> increment higher-order half of the address - inc ecx - ja fill_tables2 -fill_tables2_done: - ; set base pointer to PML4 - mov eax, pml4 - mov cr3, eax - ret - -; -; system start, part 2 (in 64-bit Long Mode) -; -; This code clears the BSS segment and initializes IDT and PICs. Then the -; constructors of global C++ objects are called, and finally _entry() is run. -; - -longmode_start: -[BITS 64] - ; clear BSS - mov rdi, ___BSS_START__ -clear_bss: - mov byte [rdi], 0 - inc rdi - cmp rdi, ___BSS_END__ - jne clear_bss - - ; initialize IDT and PICs - call setup_idt - call reprogram_pics - call setup_cursor - - fninit ; activate FPU - - ; init SSE - ; NOTE: must NOT use sse target features for rust compiler, if sse not enabled here. - ;mov rax, cr0 - ;and rax, ~(1 << 2) ;clear coprocessor emulation CR0.EM - ;or rax, 1 << 1 ;set coprocessor monitoring CR0.MP - ;mov cr0, rax - ;mov rax, cr4 - ;or rax, 3 << 9 ;set CR4.OSFXSR and CR4.OSXMMEXCPT at the same time - ;mov cr4, rax - - call _entry ; call the OS kernel's C / C++ part - cli ; Usually we should not get here. - hlt - -; -; Interrupt handling -; - -; template for header for each interrupt-handling routine -; TODO: vectors should have their dedicated place -%macro wrapper 1 -wrapper_%1: - push rbp - mov rbp, rsp - push rax - mov al, %1 - jmp wrapper_body -%endmacro - -; automatic generation of 256 interrupt-handling routines, based on above macro -%assign i 0 -%rep 256 -wrapper i -%assign i i+1 -%endrep - -; common handler body -wrapper_body: - ; GCC expects the direction flag to be 0 - cld - ; save volatile registers - push rcx - push rdx - push rdi - push rsi - push r8 - push r9 - push r10 - push r11 - - ; the generated wrapper only gives us 8 bits, mask the rest - and rax, 0xff - - ; pass interrupt number as the first parameter - mov rdi, rax - ; call the interrupt handler wrapper here. - ; TODO implement it in rust then uncomment the line - call guardian - - ; restore volatile registers - pop r11 - pop r10 - pop r9 - pop r8 - pop rsi - pop rdi - pop rdx - pop rcx - - ; ... also those from the wrapper - pop rax - pop rbp - - ; done - iretq - -; -; Relocating of IDT entries and setting IDTR -; - -setup_idt: - mov rax, wrapper_0 - - ; bits 0..15 -> ax, 16..31 -> bx, 32..64 -> edx - mov rbx, rax - mov rdx, rax - shr rdx, 32 - shr rbx, 16 - - mov r10, idt ; pointer to the actual interrupt gate - mov rcx, 255 ; counter -.loop: - add [r10+0], ax - adc [r10+6], bx - adc [r10+8], edx - add r10, 16 - dec rcx - jge .loop - - lidt [idt_descr] - ret - -; -; make cursor blink (GRUB disables this) -; - -setup_cursor: - mov al, 0x0a - mov dx, 0x3d4 - out dx, al - call delay - mov dx, 0x3d5 - in al, dx - call delay - and al, 0xc0 - or al, 14 - out dx, al - call delay - mov al, 0x0b - mov dx, 0x3d4 - out dx, al - call delay - mov dx, 0x3d5 - in al, dx - call delay - and al, 0xe0 - or al, 15 - out dx, al - ret - -; -; Reprogram the PICs (programmable interrupt controllers) to have all 15 -; hardware interrupts in sequence in the IDT. -; - -reprogram_pics: - mov al, 0x11 ; ICW1: 8086 mode with ICW4 - out 0x20, al - call delay - out 0xa0, al - call delay - mov al, 0x20 ; ICW2 master: IRQ # offset (32) - out 0x21, al - call delay - mov al, 0x28 ; ICW2 slave: IRQ # offset (40) - out 0xa1, al - call delay - mov al, 0x04 ; ICW3 master: slaves with IRQs - out 0x21, al - call delay - mov al, 0x02 ; ICW3 slave: connected to master's IRQ2 - out 0xa1, al - call delay - mov al, 0x03 ; ICW4: 8086 mode and automatic EOI - out 0x21, al - call delay - out 0xa1, al - call delay - - mov al, 0xff ; Mask/disable hardware interrupts - out 0xa1, al ; in the PICs. Only interrupt #2, which - call delay ; serves for cascading both PICs, is - mov al, 0xfb ; allowed. - out 0x21, al - - ret - -; -; Short delay for in/out instructions -; - -delay: - jmp .L2 -.L2: - ret - -[SECTION .data] - -; -; Segment descriptors -; - -gdt: - dw 0,0,0,0 ; NULL descriptor - - ; 32-bit code segment descriptor - dw 0xFFFF ; 4Gb - (0x100000*0x1000 = 4Gb) - dw 0x0000 ; base address=0 - dw 0x9A00 ; code read/exec - dw 0x00CF ; granularity=4096, 386 (+5th nibble of limit) - - ; 64-bit code segment descriptor - dw 0xFFFF ; 4Gb - (0x100000*0x1000 = 4Gb) - dw 0x0000 ; base address=0 - dw 0x9A00 ; code read/exec - dw 0x00AF ; granularity=4096, 386 (+5th nibble of limit), Long-Mode - - ; data segment descriptor - dw 0xFFFF ; 4Gb - (0x100000*0x1000 = 4Gb) - dw 0x0000 ; base address=0 - dw 0x9200 ; data read/write - dw 0x00CF ; granularity=4096, 386 (+5th nibble of limit) - -gdt_80: - dw 4*8 - 1 ; GDT limit=24, 4 GDT entries - 1 - dq gdt ; GDT address - -; -; Interrupt descriptor table with 256 entries -; - -idt: -%macro idt_entry 1 - dw (wrapper_%1 - wrapper_0) & 0xffff ; offset 0 .. 15 - dw 0x0000 | 0x8 * 2 ; selector points to 64-bit code segment selector (GDT) - dw 0x8e00 ; 8 -> interrupt is present, e -> 80386 32-bit interrupt gate - dw ((wrapper_%1 - wrapper_0) & 0xffff0000) >> 16 ; offset 16 .. 31 - dd ((wrapper_%1 - wrapper_0) & 0xffffffff00000000) >> 32 ; offset 32..63 - dd 0x00000000 ; reserved -%endmacro - -%assign i 0 -%rep 256 -idt_entry i -%assign i i+1 -%endrep - -idt_descr: - dw 256*8 - 1 ; 256 entries - dq idt - -[SECTION .bss] - -global init_stack:data (init_stack.end - init_stack) -init_stack: - resb STACKSIZE -.end: - -[SECTION .global_pagetable] - - -pml4: - resb 4096 - alignb 4096 - -pdp: - resb 4096 - alignb 4096 diff --git a/x86_64-rustubs.json b/x86_64-rustubs.json deleted file mode 100644 index 93512ed..0000000 --- a/x86_64-rustubs.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "llvm-target": "x86_64-unknown-none", - "data-layout": "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128", - "linker-flavor": "gcc", - "target-endian": "little", - "target-pointer-width": "64", - "target-c-int-width": "32", - "arch": "x86_64", - "os": "none", - "disable-redzone": true, - "features": "-mmx,-sse,-avx,+soft-float", - "frame-pointer": "always" -} -- cgit v1.2.3-70-g09d2