OS triple faults in protected mode
Posted: Sun Nov 06, 2022 8:33 am
Hello,
I'm working on my own OS. I'm keeping what I can in the boot sector right now because I want to use that space. My OS seems to switch into protected mode and print strings just fine, but it triple faults after a few seconds. I looked in Bochs's output and see this directly after the booting message:
The gate descriptor is from the IDT, which I have (purposefully) not set up yet. I only have the GDT set up, so I'm confused as to why this error is being caused. I can tell the first exception is a general protection fault, and I can't find anywhere in my code that may be causing it.
Here is my code (ignore the unused disk read function, I'm using that later):
I'm working on my own OS. I'm keeping what I can in the boot sector right now because I want to use that space. My OS seems to switch into protected mode and print strings just fine, but it triple faults after a few seconds. I looked in Bochs's output and see this directly after the booting message:
Code: Select all
00015041311e[CPU0 ] interrupt(): gate.type(9) != {5,6,7,14,15}
00015041311e[CPU0 ] interrupt(): gate descriptor is not valid sys seg (vector=0x0d)
00015041311e[CPU0 ] interrupt(): gate descriptor is not valid sys seg (vector=0x08)
...
00015041311i[CPU0 ] 0x000000000000ffb1>> (invalid) : F0CE
00015041311e[CPU0 ] exception(): 3rd (13) exception with no resolution, shutdown status is 00h, resetting
Here is my code (ignore the unused disk read function, I'm using that later):
Code: Select all
[org 0x7c00]
[bits 16]
%define ENDL 0x0D, 0x0A
start:
jmp main
;
; Prints a string to the screen
; Params:
; - ds:si points to string
;
main:
; setup data segments
xor ax, ax
mov es, ax
mov ds, ax
mov bp, 0x9000
mov ss, ax
mov sp, bp
; print hello world message
mov si, string16
call puts16
mov ah, 0x0e
mov al, 'J'
int 0x10
EnterProtectedMode:
call EnableA20
cli
lgdt [gdt_descriptor]
mov eax, cr0
or eax, 1
mov cr0, eax
jmp codeseg:StartProtectedMode
EnableA20:
in al, 0x92
or al, 2
out 0x92, al
ret
[bits 32]
StartProtectedMode:
mov ax, dataseg
mov ds, ax
mov ss, ax
mov es, ax
mov fs, ax
mov gs, ax
mov edx, 0xb8000 ; init edx w/ proper start location
mov si, string32a
call puts32
mov si, string32b
call puts32
jmp $
[bits 16]
puts16:
; save registers we will modify
pusha
.puts16_loop:
lodsb ; loads next character in al
or al, al ; verify if next character is null?
jz .puts16_done
mov ah, 0x0E ; call bios interrupt
mov bh, 0 ; set page number to 0
int 0x10
jmp .puts16_loop
.puts16_done:
popa
ret
[bits 32]
puts32:
pusha
loop_puts32:
lodsb
cmp al, 0
je done_puts32
cmp al, 0dh
je cr_puts32
cmp al, 0ah
je lf_puts32
mov [edx], al
add edx, 2
jmp loop_puts32
cr_puts32:
and edx, 0xfff00
jmp loop_puts32
lf_puts32:
add edx, 0xa0
jmp loop_puts32
done_puts32:
pusha
ret
[bits 16]
read_disk:
xor ax, ax ; make sure ds is set to 0
mov ds, ax
cld
; start putting in values:
mov ah, 2h ; int13h function 2
mov al, 1 ; we want to read 1 sector
mov ch, 0 ; from cylinder number 0
mov cl, 2 ; the sector number 2 - second sector (starts from 1, not 0)
mov dh, 0 ; head number 0
xor bx, bx
mov es, bx ; es should be 0
mov bx, 7e00h ; 512bytes from origin address 7c00h
int 13h
jc disk_read_failed
ret
disk_read_failed:
mov si, DiskReadErrorString
call puts16
hlt
gdt_nulldesc:
dd 0
dd 0
gdt_codedesc:
dw 0xFFFF ; Limit
dw 0x0000 ; Base (low)
db 0x00 ; Base (medium)
db 10011010b ; Flags
db 11001111b ; Flags + Upper Limit
db 0x00 ; Base (high)
gdt_datadesc:
dw 0xFFFF
dw 0x0000
db 0x00
db 10010010b
db 11001111b
db 0x00
gdt_end:
gdt_descriptor:
gdt_size:
dw gdt_end - gdt_nulldesc - 1
dq gdt_nulldesc
codeseg equ gdt_codedesc - gdt_nulldesc
dataseg equ gdt_datadesc - gdt_nulldesc
string16: db 'Hello, 16-bit world!', ENDL, 0
string32a: db 'Hello, 32-bit world!', ENDL, 0
string32b: db 'Goodbye, cruel world!', 0
DiskReadErrorString: db 'Disk Read Failed',0
times 510-($-$$) db 0
dw 0AA55h