Page 3 of 4
Re: IDT Help
Posted: Thu Mar 11, 2021 11:22 pm
by isaiah0311
SKC wrote:
Well yes, but actually no. The loop sets the entries to the same handler. If you use it for the entire IDT, every interrupt/exception/IRQ will call the same code. Since you're in a very early stage, you can set the exception entries (0-31) to the same handler. However, as I said before, you will need to give each interrupt its own handler at some point. But for now, setting all the exceptions (only exceptions, not IRQs) to a dummy handler that just hangs is fine.
Alright, I think I'm starting to understand it more. So basically in the IDT label I need to define 32 exceptions, 16 IRQs, and then the pointer? The loop has a counter of 48, so it sets all 32 exceptions and 16 IRQs to the same handler. But only the exceptions can have the same handler (for now, later that has to be changed)? So I should change the counter to 32, and then add code to set each of the 16 IRQs to a different handler? What should that handlers for the IRQs do? Also, should I call the loop after I load the IDT or before?
Re: IDT Help
Posted: Fri Mar 12, 2021 12:20 am
by SKC
isaiah0311 wrote:Alright, I think I'm starting to understand it more. So basically in the IDT label I need to define 32 exceptions, 16 IRQs, and then the pointer? The loop has a counter of 48, so it sets all 32 exceptions and 16 IRQs to the same handler. But only the exceptions can have the same handler (for now, later that has to be changed)? So I should change the counter to 32, and then add code to set each of the 16 IRQs to a different handler?
Exactly.
isaiah0311 wrote:What should that handlers for the IRQs do?
The only thing that is common among IRQ handlers is that they send EOI (End Of Interrupt, you can read more about it
here). Besides that, each IRQ handler is built to communicate with different hardware. Since you started this topic saying that you want to get keyboard input, I'll use it as an example. The keyboard uses IRQ1 (interrupt 33), and the handler would probably read from the keyboard and save the input somewhere. You can set the IRQs you don't use/support to a dummy handler that sends EOI and returns.
isaiah0311 wrote:Also, should I call the loop after I load the IDT or before?
Before. Loading an empty/corrupt IDT is like not having an IDT.
Re: IDT Help
Posted: Fri Mar 12, 2021 10:36 am
by isaiah0311
So here is the current main64.asm file. I'm still getting issues when I enable interrupts. If I don't enable interrupts it freezes before loading the kernel which is a new issue.
Code: Select all
global long_mode_start
extern gdt.data
extern kernel_main
section .text
bits 64
long_mode_start:
mov ax, gdt.data
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ss, ax
call map_entries
lidt [idt.pointer]
sti
call kernel_main
mov rax, 60
mov rdi, 2
syscall
map_entries:
mov rbx, idt
.map_exceptions:
mov rdx, 0
mov rax, exception_handler
mov rcx, 32
jmp .loop
.map_irqs_pic1:
mov rdx, 1
mov rax, isr_handler.pic1
mov rcx, 8
jmp .loop
.map_irqs_pic2:
mov rdx, 2
mov rax, isr_handler.pic2
mov rcx, 8
.loop:
mov word [rbx], ax
shr rax, 16
mov word [rbx + 6], ax
shr rax, 16
mov dword [rbx + 8], eax
add rbx, 16
dec rcx
jne .loop
test rdx, 0
je .map_irqs_pic1
test rdx, 1
je .map_irqs_pic2
ret
idt:
.exception_0:
dw 0
dw 0x8
db 0
db 10001110b
dw 0
dd 0
dd 0
; --------------------------------
; exception_1 - 30
; --------------------------------
.exception_31:
dw 0
dw 0x8
db 0
db 10001110b
dw 0
dd 0
dd 0
.irq_0:
dw 0
dw 0x8
db 0
db 10001110b
dw 0
dd 0
dd 0
; --------------------------------
; irq_1 - 14
; --------------------------------
.irq_15:
dw 0
dw 0x8
db 0
db 10001110b
dw 0
dd 0
dd 0
.pointer:
dw $ - idt - 1
dq idt
exception_handler:
jmp $
isr_handler:
.pic1:
mov ax, 0x20
out 0x20, ax
iretq
.pic2:
mov ax, 0x20
out 0xa0, ax
iretq
Re: IDT Help
Posted: Fri Mar 12, 2021 10:50 am
by SKC
What is gdt.data? Is it a selector, or is it the data descriptor in your GDT?
Re: IDT Help
Posted: Fri Mar 12, 2021 11:01 am
by isaiah0311
SKC wrote:What is gdt.data? Is it a selector, or is it the data descriptor in your GDT?
It's the data descriptor. I used the example in the wiki.
Code: Select all
section .rodata
gdt:
.null: equ $ - gdt
dw 0xffff
dw 0
db 0
db 0
db 1
db 0
.code: equ $ - gdt
dw 0
dw 0
db 0
db 10011010b
db 10101111b
db 0
.data: equ $ - gdt
dw 0
dw 0
db 0
db 10010010b
db 00000000b
db 0
.pointer:
dw $ - gdt - 1
dq gdt
Re: IDT Help
Posted: Fri Mar 12, 2021 11:24 am
by SKC
You need to set the data segment registers to the data selector, not descriptor.
Also, I don't think that your code descriptor is valid. I set the 7th byte (10101111b in your code) to 00100000b.
Re: IDT Help
Posted: Fri Mar 12, 2021 11:47 am
by isaiah0311
SKC wrote:You need to set the data segment registers to the data selector, not descriptor.
Also, I don't think that your code descriptor is valid. I set the 7th byte (10101111b in your code) to 00100000b.
I changed the byte to 00100000b and the data segment registers to 0x10 again. The OS still didn't boot.
I checked the wiki. The comment next to 10101111b is: granularity, 64 bits flag, limit19:16.
It also labels the .data as the descriptor and then loads gdt.data into the segment registers.
Is it valid both ways, or is the wiki wrong?
Here is the
link.
Re: IDT Help
Posted: Fri Mar 12, 2021 11:59 am
by SKC
isaiah0311 wrote:The comment next to 10101111b is: granularity, 64 bits flag, limit19:16.
AMD's manual says that granularity and limit are ignored, so I guess it's fine. Also, I didn't notice that, but I think 'equ $ - gdt' sets the labels to the selectors (so you can do 'mov ax,gdt.data'). Anyway, I think it's clearer to use the selector itself.
isaiah0311 wrote:The OS still didn't boot.
What happens? Exception? Triple fault? It just hangs?
Re: IDT Help
Posted: Fri Mar 12, 2021 12:11 pm
by isaiah0311
SKC wrote: What happens? Exception? Triple fault? It just hangs?
It just hangs.
Re: IDT Help
Posted: Fri Mar 12, 2021 1:08 pm
by isaiah0311
Update: It works... sort of?
The issue was in the loop where I map the IDT entries to the handler functions.
The new loop is this:
Code: Select all
map_entries:
mov rbx, idt
.map_exceptions:
mov rdx, 0
mov rax, exception_handler
mov rcx, 32
jmp .loop
.map_irqs_pic1:
mov rdx, 1
mov rax, isr_handler.pic1
mov rcx, 8
jmp .loop
.map_irqs_pic2:
mov rdx, 2
mov rax, isr_handler.pic2
mov rcx, 8
.loop:
mov word [rbx], ax
shr rax, 16
mov word [rbx + 6], ax
shr rax, 16
mov dword [rbx + 8], eax
add rbx, 16
dec rcx
jne .loop
test rdx, rdx
je .map_irqs_pic1
dec rdx
test rdx, rdx
je .map_irqs_pic2
ret
It now boots into the OS even with interrupts enabled. The issue I have now is when I press a key, it reboots.
Here is how the IRQs are handled:
Code: Select all
isr_handler:
.pic1
mov ax, 0x20
out 0x20, ax
iretq
.pic2
mov ax, 0x20
out 0xa0, ax
iretq
I know this won't read the keyboard input, but I didn't except it to cause a reboot. I figured it would just do nothing.
Re: IDT Help
Posted: Fri Mar 12, 2021 9:12 pm
by SKC
Wow. You know what I've just noticed? rax is not being set up properly after each loop iteration! I just shoved the code into a loop, and I overlooked that… To fix it, you need to use another register, and set rax to that register at the start of the loop. I'm thinking about something like:
Code: Select all
.loop:
mov rax, r8 ; r8 is the additional register
mov word [rbx], ax
shr rax, 16
mov word [rbx + 6], ax
shr rax, 16
mov dword [rbx + 8], eax
add rbx, 16
dec rcx
jne .loop
And then in the rest of your map_entries function, just change rax to r8.
Re: IDT Help
Posted: Fri Mar 12, 2021 9:23 pm
by isaiah0311
SKC wrote:Wow. You know what I've just noticed? rax is not being set up properly after each loop iteration! I just shoved the code into a loop, and I overlooked that… To fix it, you need to use another register, and set rax to that register at the start of the loop. I'm thinking about something like:
Code: Select all
.loop:
mov rax, r8 ; r8 is the additional register
mov word [rbx], ax
shr rax, 16
mov word [rbx + 6], ax
shr rax, 16
mov dword [rbx + 8], eax
add rbx, 16
dec rcx
jne .loop
And then in the rest of your map_entries function, just change rax to r8.
It works! Interrupts are enabled and it doesn't crash, even when I press a key.
So now the next step would be to assign the keyboard IRQ a handler of its own?
Re: IDT Help
Posted: Fri Mar 12, 2021 9:26 pm
by SKC
I'm glad it works! And yes, now you need to give the keyboard its own handler.
Re: IDT Help
Posted: Fri Mar 12, 2021 9:44 pm
by isaiah0311
SKC wrote:And yes, now you need to give the keyboard its own handler.
So how do I go about accessing the data for which key is pressed? After that can I just store it in RAX and then call a C function?
Re: IDT Help
Posted: Fri Mar 12, 2021 10:00 pm
by SKC
isaiah0311 wrote:So how do I go about accessing the data for which key is pressed?
Read
this.
isaiah0311 wrote:After that can I just store it in RAX and then call a C function?
And
this.