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?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.
IDT Help
-
- Member
- Posts: 25
- Joined: Tue Mar 09, 2021 9:31 pm
- Libera.chat IRC: isaiah0311
Re: IDT Help
Re: IDT Help
Exactly.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?
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:What should that handlers for the IRQs do?
Before. Loading an empty/corrupt IDT is like not having an IDT.isaiah0311 wrote:Also, should I call the loop after I load the IDT or before?
-
- Member
- Posts: 25
- Joined: Tue Mar 09, 2021 9:31 pm
- Libera.chat IRC: isaiah0311
Re: IDT Help
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
What is gdt.data? Is it a selector, or is it the data descriptor in your GDT?
-
- Member
- Posts: 25
- Joined: Tue Mar 09, 2021 9:31 pm
- Libera.chat IRC: isaiah0311
Re: IDT Help
It's the data descriptor. I used the example in the wiki.SKC wrote:What is gdt.data? Is it a selector, or is it the data descriptor in your GDT?
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
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.
Also, I don't think that your code descriptor is valid. I set the 7th byte (10101111b in your code) to 00100000b.
-
- Member
- Posts: 25
- Joined: Tue Mar 09, 2021 9:31 pm
- Libera.chat IRC: isaiah0311
Re: IDT Help
I changed the byte to 00100000b and the data segment registers to 0x10 again. The OS still didn't boot.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 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
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 comment next to 10101111b is: granularity, 64 bits flag, limit19:16.
What happens? Exception? Triple fault? It just hangs?isaiah0311 wrote:The OS still didn't boot.
-
- Member
- Posts: 25
- Joined: Tue Mar 09, 2021 9:31 pm
- Libera.chat IRC: isaiah0311
Re: IDT Help
It just hangs.SKC wrote: What happens? Exception? Triple fault? It just hangs?
-
- Member
- Posts: 25
- Joined: Tue Mar 09, 2021 9:31 pm
- Libera.chat IRC: isaiah0311
Re: IDT Help
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:
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:
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.
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
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
Re: IDT Help
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:
And then in the rest of your map_entries function, just change rax to r8.
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
-
- Member
- Posts: 25
- Joined: Tue Mar 09, 2021 9:31 pm
- Libera.chat IRC: isaiah0311
Re: IDT Help
It works! Interrupts are enabled and it doesn't crash, even when I press a key.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:And then in the rest of your map_entries function, just change rax to r8.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
So now the next step would be to assign the keyboard IRQ a handler of its own?
Re: IDT Help
I'm glad it works! And yes, now you need to give the keyboard its own handler.
-
- Member
- Posts: 25
- Joined: Tue Mar 09, 2021 9:31 pm
- Libera.chat IRC: isaiah0311
Re: IDT Help
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?SKC wrote:And yes, now you need to give the keyboard its own handler.