You are browsing as a guest. Sign up (or log in) to start making projects!

5h 54m 45s logged

Hi guys, here we go again with another devlog.
Lately I worked a lot, so this devlog will be pretty long.
Let’s start with the first piece, the IDT. I made three files: idt.h with the structs and the prototypes, idt.c with the actual table, and idt_flush.s to load it. The table has 256 entries, one for each interrupt vector.

Then I worked on the exceptions raised by the CPU. I created 32 stubs in isr_stubs.s, one for each exception.

I also had to work on the hardware interrupts. I worked in the file io.h, with I/O ports. I used outb and inb, which are inline assembly, for managing ports in C, since C doesn’t have a way for managing them.

Another big part is the PIC 8259 with the remap. When booted, there’s IRQ 0-7 on vectors 8-15. In protected mode there’s already double fault and page fault, so those vectors are already taken. But without remap, when you type a key the kernel sees it as “coprocessor segment overrun”. A problem is that the chip is really old, so it’s older than the numbering it collides with.
There’s one more thing about the PIC, and it’s the end of interrupt. After it sends you an interrupt, it doesn’t send the next ones until you tell it you’re done, by writing 0x20 to its command port. So I have to do that at the end of every IRQ handler. If you forget it you get exactly one interrupt and then nothing, forever, and the annoying part is that nothing looks broken: no error, no crash, the first interrupt works perfectly.

The last piece is how the handler goes back, and it’s probably the most interesting one.
I would have used ret, like in a normal function, but it doesn’t work here. That’s because ret only restores eip, while an interrupt also pushed cs and eflags. Eflags is where the IF flag lives (the one that says if interrupts are enabled or not) and the CPU turns it off by itself when it gives you the interrupt, so that your handler doesn’t get interrupted in the middle.. So with ret interrupts stay off forever and you never get another one.

The solution is iret. And right before it I have to do add esp, 8, because the vector number and the error code were pushed by me, not by the CPU, and iret knows nothing about them.

To test all of this I unmasked IRQ 0, the timer, and I didn’t have to configure the timer at all: the BIOS had already programmed the PIT, so it was ticking the whole time and the interrupts started coming as soon as I enabled them. The screen fills up with IRQ raised: 00. That screenshot proves three things at the same time: the remap worked, because the interrupt arrives on vector 32 and not on 8; the EOI is getting through, otherwise there would be one single line; and iret puts the stack back exactly as it found it, a few hundred times in a row without missing once.

I’m so happy for this work. Look forward for the next steps

0
7

Comments 0

No comments yet. Be the first!