diff --git a/posts/2015-09-02-setup-rust.md b/posts/2015-09-02-setup-rust.md index 0221944a..24cf25c4 100644 --- a/posts/2015-09-02-setup-rust.md +++ b/posts/2015-09-02-setup-rust.md @@ -273,41 +273,27 @@ Through `objdump -D` we disassemble our whole kernel and `grep` picks the releva The rough translation of this cryptic definition is: _If SSE isn't enabled_. So apparently Rust uses SSE instructions by default and we didn't enable SSE before. So the fix for this bug is enabling SSE. ### Enabling SSE -To enable SSE, assembly code is needed again. We want to add a function that tests if SSE is available and enables it then. Else we want to print an error message. But we can't use our existing `error` procedure because it uses (now invalid) 32-bit instructions. So we need a new one (in `long_mode_init.asm`): +To enable SSE, assembly code is needed again. We want to add a function that tests if SSE is available and enables it then. Else we want to print an error message. -```nasm -; Prints `ERROR: ` and the given error code to screen and hangs. -; parameter: error code (in ascii) in al -error: - mov rbx, 0x4f4f4f524f524f45 - mov [0xb8000], rbx - mov rbx, 0x4f204f204f3a4f52 - mov [0xb8008], rbx - mov byte [0xb800e], al - hlt - jmp error -``` -It's the nearly the same as the 32-bit procedure in the [previous post][32-bit error function] (instead of `ERR:` we print `ERROR:` here). - -Now we can add a function that checks for SSE and enables it: +We add it to the `boot.asm` file: ```nasm ; Check for SSE and enable it. If it's not supported throw error "a". setup_SSE: ; check for SSE - mov rax, 0x1 + mov eax, 0x1 cpuid test edx, 1<<25 jz .no_SSE ; enable SSE - mov rax, cr0 + mov eax, cr0 and ax, 0xFFFB ; clear coprocessor emulation CR0.EM or ax, 0x2 ; set coprocessor monitoring CR0.MP - mov cr0, rax - mov rax, cr4 + mov cr0, eax + mov eax, cr4 or ax, 3 << 9 ; set CR4.OSFXSR and CR4.OSXMMEXCPT at the same time - mov cr4, rax + mov cr4, eax ret .no_SSE: @@ -316,7 +302,7 @@ setup_SSE: ``` The code is from the great [OSDev Wiki][osdev sse] again. Notice that it sets/unsets exactly the bits that can cause the `Invalid Opcode` exception. -When we insert a `call setup_SSE` right before calling `rust_main`, our Rust code will finally work. +When we insert a `call setup_SSE` somewhere in the `start` function (for example after `call enable_paging`), our Rust code will finally work. [32-bit error function]: {{ page.previous.url }}#some-tests [osdev sse]: http://wiki.osdev.org/SSE#Checking_for_SSE diff --git a/src/arch/x86_64/boot.asm b/src/arch/x86_64/boot.asm index 7035fc17..ade4dc4a 100644 --- a/src/arch/x86_64/boot.asm +++ b/src/arch/x86_64/boot.asm @@ -29,6 +29,7 @@ start: call setup_page_tables call enable_paging + call setup_SSE ; load the 64-bit GDT lgdt [gdt64.pointer] @@ -147,6 +148,28 @@ test_long_mode: mov al, "2" jmp error +; Check for SSE and enable it. If it's not supported throw error "a". +setup_SSE: + ; check for SSE + mov eax, 0x1 + cpuid + test edx, 1<<25 + jz .no_SSE + + ; enable SSE + mov eax, cr0 + and ax, 0xFFFB ; clear coprocessor emulation CR0.EM + or ax, 0x2 ; set coprocessor monitoring CR0.MP + mov cr0, eax + mov eax, cr4 + or ax, 3 << 9 ; set CR4.OSFXSR and CR4.OSXMMEXCPT at the same time + mov cr4, eax + + ret +.no_SSE: + mov al, "a" + jmp error + section .bss align 4096 p4_table: diff --git a/src/arch/x86_64/long_mode_init.asm b/src/arch/x86_64/long_mode_init.asm index 47927d58..bcf588a8 100644 --- a/src/arch/x86_64/long_mode_init.asm +++ b/src/arch/x86_64/long_mode_init.asm @@ -18,8 +18,6 @@ extern rust_main section .text bits 64 long_mode_start: - call setup_SSE - ; call rust main (with multiboot pointer in rdi) call rust_main .os_returned: @@ -31,36 +29,3 @@ long_mode_start: mov rax, 0x4f214f644f654f6e mov [0xb8010], rax hlt - -; Check for SSE and enable it. If it's not supported throw error "a". -setup_SSE: - ; check for SSE - mov rax, 0x1 - cpuid - test edx, 1<<25 - jz .no_SSE - - ; enable SSE - mov rax, cr0 - and ax, 0xFFFB ; clear coprocessor emulation CR0.EM - or ax, 0x2 ; set coprocessor monitoring CR0.MP - mov cr0, rax - mov rax, cr4 - or ax, 3 << 9 ; set CR4.OSFXSR and CR4.OSXMMEXCPT at the same time - mov cr4, rax - - ret -.no_SSE: - mov al, "a" - jmp error - -; Prints `ERROR: ` and the given error code to screen and hangs. -; parameter: error code (in ascii) in al -error: - mov rbx, 0x4f4f4f524f524f45 - mov [0xb8000], rbx - mov rbx, 0x4f204f204f3a4f52 - mov [0xb8008], rbx - mov byte [0xb800e], al - hlt - jmp error