Merge pull request #65 from phil-opp/move-setup-SSE

Move `setup_SSE` to boot.asm
This commit is contained in:
Philipp Oppermann
2015-12-12 15:03:13 +01:00
3 changed files with 31 additions and 57 deletions

View File

@@ -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. 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 ### 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 We add it to the `boot.asm` file:
; 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:
```nasm ```nasm
; Check for SSE and enable it. If it's not supported throw error "a". ; Check for SSE and enable it. If it's not supported throw error "a".
setup_SSE: setup_SSE:
; check for SSE ; check for SSE
mov rax, 0x1 mov eax, 0x1
cpuid cpuid
test edx, 1<<25 test edx, 1<<25
jz .no_SSE jz .no_SSE
; enable SSE ; enable SSE
mov rax, cr0 mov eax, cr0
and ax, 0xFFFB ; clear coprocessor emulation CR0.EM and ax, 0xFFFB ; clear coprocessor emulation CR0.EM
or ax, 0x2 ; set coprocessor monitoring CR0.MP or ax, 0x2 ; set coprocessor monitoring CR0.MP
mov cr0, rax mov cr0, eax
mov rax, cr4 mov eax, cr4
or ax, 3 << 9 ; set CR4.OSFXSR and CR4.OSXMMEXCPT at the same time or ax, 3 << 9 ; set CR4.OSFXSR and CR4.OSXMMEXCPT at the same time
mov cr4, rax mov cr4, eax
ret ret
.no_SSE: .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. 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 [32-bit error function]: {{ page.previous.url }}#some-tests
[osdev sse]: http://wiki.osdev.org/SSE#Checking_for_SSE [osdev sse]: http://wiki.osdev.org/SSE#Checking_for_SSE

View File

@@ -29,6 +29,7 @@ start:
call setup_page_tables call setup_page_tables
call enable_paging call enable_paging
call setup_SSE
; load the 64-bit GDT ; load the 64-bit GDT
lgdt [gdt64.pointer] lgdt [gdt64.pointer]
@@ -147,6 +148,28 @@ test_long_mode:
mov al, "2" mov al, "2"
jmp error 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 section .bss
align 4096 align 4096
p4_table: p4_table:

View File

@@ -18,8 +18,6 @@ extern rust_main
section .text section .text
bits 64 bits 64
long_mode_start: long_mode_start:
call setup_SSE
; call rust main (with multiboot pointer in rdi) ; call rust main (with multiboot pointer in rdi)
call rust_main call rust_main
.os_returned: .os_returned:
@@ -31,36 +29,3 @@ long_mode_start:
mov rax, 0x4f214f644f654f6e mov rax, 0x4f214f644f654f6e
mov [0xb8010], rax mov [0xb8010], rax
hlt 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